doc: improve contributor guidance

Co-authored-by: OpenAI/GPT-5.6-Terra <vibecoder@antoineve.me>
Co-authored-by: Google/Gemini-3.5-Flash <vibecoder@antoineve.me>
Co-authored-by: DeepSeek/DeepSeek-v4-Flash <vibecoder@antoineve.me>
This commit is contained in:
2026-08-13 12:21:00 +02:00
parent e9977f5a1b
commit b6fa09a709
3 changed files with 25 additions and 9 deletions

View File

@@ -1,6 +1,8 @@
# CLAUDE.md
# AGENTS.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Ce fichier fournit des directives et des consignes pour les agents d'intelligence artificielle et assistants de développement (multi-modèles et multi-fournisseurs) travaillant sur ce dépôt.
Pour une présentation complète de l'architecture, de la configuration et du guide de démarrage, se référer à [docs/onboarding.md](docs/onboarding.md).
## Commands
@@ -25,14 +27,28 @@ python -m venv .venv
sudo systemctl edit --full tableau-de-bord-pro # configurer SECRET_KEY
sudo systemctl restart tableau-de-bord-pro
# Git commit (GPG signing désactivé — pinentry inaccessible dans cet env)
git -c commit.gpgsign=false commit -m "..."
# Qualité du code (Ruff)
.venv/bin/ruff check .
.venv/bin/ruff format --check .
.venv/bin/ruff format .
# Découverte des modèles OpenCode (configuration environnementale hors dépôt)
grep -A 1 -B 1 subagent /home/antoine/.config/opencode/opencode.json
```
## Variables d'environnement
- `SECRET_KEY` : requis en production (défaut `dev-secret-change-in-prod` en dev)
## Git & Conventions de Commit
- **Politique Git** : Les commits intermédiaires générés par les agents d'IA doivent être non signés en utilisant l'option `git -c commit.gpgsign=false commit -m "..."` (car pinentry est inaccessible dans cet environnement). L'utilisateur effectuera un amend signé (`git commit --amend -S`) du commit final lorsqu'il sera disponible.
- **Convention de trailers** : Chaque commit réalisé par un agent d'IA doit inclure le trailer suivant à la fin du message de commit pour identifier le modèle utilisé :
```text
Co-authored-by: Fournisseur/Modèle <vibecoder@antoineve.me>
```
*Exemple :* `Co-authored-by: Anthropic/Claude-3.5-Sonnet <vibecoder@antoineve.me>` ou `Co-authored-by: Google/Gemini-3.5-Flash <vibecoder@antoineve.me>`.
## Architecture
Flask app using the factory pattern (`create_app()` in `app/__init__.py`). The DB is SQLite via SQLAlchemy, stored in `instance/worklog.db`. All vehicle/journey/tax configuration lives in `config.toml` (loaded at startup into `app.config["TOML"]`), not in the database.
@@ -62,7 +78,7 @@ Flask app using the factory pattern (`create_app()` in `app/__init__.py`). The D
- **Pas de migration de schéma** : l'app utilise `db.create_all()` uniquement (pas d'Alembic). Tout changement de modèle nécessite de supprimer `instance/worklog.db` en dev, ou une migration manuelle en prod.
- **Barème kilométrique** : les tranches dans `config.toml` sont à mettre à jour manuellement chaque année (section `[bareme_kilometrique.YYYY]`).
- **`datetime.utcnow()` deprecated** : les modèles utilisent `datetime.utcnow` (warning sur Python 3.14+). À remplacer par `datetime.now(UTC)` lors d'une prochaine évolution des modèles.
- **`datetime.utcnow()` déprécié** : Les modèles utilisent actuellement `datetime.utcnow` (générant un avertissement sur Python 3.12+ et obsolète sur Python 3.14+). Il est formellement recommandé d'utiliser `datetime.now(UTC)` (avec `from datetime import UTC`) à la place pour toute nouvelle manipulation de date/heure ou lors de la prochaine évolution des modèles.
- **Filtres Jinja2** (définis dans `app/__init__.py`) : `{{ date | date_fr }}` pour les dates en français ; `{{ day_type | day_type_fr }}` pour les libellés de types de jours (WORK→Travail, TT→Télétravail, etc.).
- **`db.get_engine()` deprecated** en Flask-SQLAlchemy 3.x → utiliser `db.engine`.
- **Migration `_migrate_db`** : vérifier l'existence de la table avant `ALTER TABLE` — SQLite peut avoir un fichier DB sans tables (ex: premier démarrage avec `instance/worklog.db` vide).

View File

@@ -263,7 +263,7 @@ sudo systemctl restart tableau-de-bord-pro
- En **production** : Tu dois écrire une migration manuelle dans la fonction `_migrate_db` située dans `app/__init__.py`. Cette fonction s'exécute au démarrage de l'application, vérifie l'existence des colonnes via SQLite, et applique les instructions `ALTER TABLE` nécessaires de manière sécurisée.
### Dépréciations à surveiller
- **`datetime.utcnow()`** : Utilisé dans les modèles de données. Cette méthode est dépréciée depuis Python 3.12. Lors d'une prochaine évolution majeure des modèles, il faudra la remplacer par `datetime.now(UTC)`.
- **`datetime.utcnow()`** : Cette méthode est dépréciée depuis Python 3.12. Il est formellement recommandé d'utiliser `datetime.now(UTC)` (avec `from datetime import UTC`) à la place. Lors d'une prochaine évolution majeure des modèles, il faudra remplacer les occurrences existantes.
- **`db.get_engine()`** : Déprécié dans Flask-SQLAlchemy 3.x. Utilise toujours `db.engine` à la place.
---

View File

@@ -384,7 +384,7 @@ git commit -m "feat: TOML config loader for vehicles, journeys, and tax scales"
```python
from app import db
from datetime import date, time, datetime
from datetime import date, time, datetime, UTC
from enum import Enum as PyEnum
import sqlalchemy as sa
import sqlalchemy.orm as so
@@ -410,9 +410,9 @@ class WorkEntry(db.Model):
journey_profile_id: so.Mapped[str | None] = so.mapped_column(sa.String(64), nullable=True)
day_type: so.Mapped[str] = so.mapped_column(sa.String(16), nullable=False, default="WORK")
comment: so.Mapped[str | None] = so.mapped_column(sa.Text, nullable=True)
created_at: so.Mapped[datetime] = so.mapped_column(sa.DateTime, default=datetime.utcnow)
created_at: so.Mapped[datetime] = so.mapped_column(sa.DateTime, default=lambda: datetime.now(UTC))
updated_at: so.Mapped[datetime] = so.mapped_column(
sa.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow
sa.DateTime, default=lambda: datetime.now(UTC), onupdate=lambda: datetime.now(UTC)
)
time_slots: so.Mapped[list["TimeSlot"]] = so.relationship(