From b6fa09a709e15ca4949d2393004545b7cccd9a8b Mon Sep 17 00:00:00 2001 From: Antoine Van Elstraete Date: Thu, 13 Aug 2026 12:21:00 +0200 Subject: [PATCH] doc: improve contributor guidance Co-authored-by: OpenAI/GPT-5.6-Terra Co-authored-by: Google/Gemini-3.5-Flash Co-authored-by: DeepSeek/DeepSeek-v4-Flash --- AGENTS.md | 26 +++++++++++++++---- docs/onboarding.md | 2 +- .../2026-03-11-tableau-de-bord-travail.md | 6 ++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index eafe029..ff909d4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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 + ``` + *Exemple :* `Co-authored-by: Anthropic/Claude-3.5-Sonnet ` ou `Co-authored-by: Google/Gemini-3.5-Flash `. + ## 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). diff --git a/docs/onboarding.md b/docs/onboarding.md index 7c79511..4fcda35 100644 --- a/docs/onboarding.md +++ b/docs/onboarding.md @@ -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. --- diff --git a/docs/plans/2026-03-11-tableau-de-bord-travail.md b/docs/plans/2026-03-11-tableau-de-bord-travail.md index 3c0ca8a..4d50b20 100644 --- a/docs/plans/2026-03-11-tableau-de-bord-travail.md +++ b/docs/plans/2026-03-11-tableau-de-bord-travail.md @@ -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(