Chapitres
Sur cette page
DOC-05 / Référence technique · Chapitre 04
Chantiers, travaux & tâches — modèle de données et API
Décrit la hiérarchie chantier/travail/tâche de Synedre OS, le modèle de données DB, les statuts/scopes canoniques et l'API Python associée.
Chantiers, travaux & tâches
À quoi ça sert
Le harness Synedre OS organise tout travail de développement en une hiérarchie persistée en base — 1 chantier = N travaux = N tâches — afin que l'orchestrateur (Atlas) et les agents puissent créer, suivre, paralléliser et clôturer du travail sans état hors-base. Cette page documente le modèle de données, l'interface Python qui le manipule, la procédure de création en sept étapes, le mécanisme de verrou multi-session, et les cascades de statut (dont la résolution dite « travail-bis » d'un travail en pause).
1. Modèle de données
1.1 Hiérarchie
Trois niveaux imbriqués structurent tout travail :
- Chantier — unité de pilotage de haut niveau
- Travail — sous-ensemble d'un chantier, assignable à un agent
- Tâche — action atomique au sein d'un travail
Trois entités Python principales encapsulent ces niveaux. Chacune étend une classe de base commune et expose des méthodes de validation, de création et de mise à jour. Deux entités secondaires gèrent respectivement les verrous multi-session et les dépendances entre tâches.
| Entité | Rôle | Clé primaire |
|---|---|---|
| Chantier | Unité de pilotage | identifiant chantier |
| Travail | Sous-ensemble d'un chantier | identifiant travail |
| Tâche | Action atomique | identifiant tâche |
| Journal d'auto-décomposition | Audit des runs de décomposition automatique | identifiant run |
| Verrou | Mutex par chantier et par type de propriétaire | (identifiant chantier, type propriétaire) |
| Dépendance tâche | Arc du DAG intra-travail | identifiant dépendance |
Note de migration — La nomenclature des tables est hétérogène pour des raisons historiques. Ne pas renommer sans chantier dédié.
1.2 Statuts
Les statuts canoniques sont scindés par niveau pour prévenir les validations croisées.
Statuts chantier : planning, dev, test, paused, done, cancelled.
Statuts travail : discovery, planning, dev, paused, review, done, cancelled.
Un alias regroupant l'union des deux ensembles est conservé pour compatibilité ascendante avec certains modules internes. Tout nouveau code doit utiliser l'ensemble propre au niveau concerné.
La validation commune accepte un paramètre status_set : l'entité Chantier lui passe les statuts chantier, l'entité Travail les statuts travail. Un INSERT SQL avec un statut hors-enum est rejeté directement par la base de données grâce à des contraintes CHECK posées sur les deux tables concernées.
Statuts tâche : todo, doing, done, paused, cancelled — vocable distinct, sans contrainte CHECK en base à ce jour.
Les priorités canoniques sont : P0, P1, P2, P3.
1.3 Scopes
Le champ scope discrimine le périmètre de synchronisation (monolithe ou OSS) et conditionne certaines validations.
Scope chantier (colonne scope, nullable) — valeurs autorisées par contrainte en base :
synedre | codemyshop-oss | codemyshop-enterprise | tenant | business | juridique | negociation | conseil
Attention — La documentation interne de la méthode de création ne liste que les cinq premiers scopes. La base en autorise trois de plus (
juridique,negociation,conseil), ajoutés pour les intents Atlas. La base fait foi.
Scope tâche — validé à la fois en code et par contrainte en base :
synedre-internal | codemyshop-oss | codemyshop-enterprise | tenant-single | tenant-multi | infra | doctrine
Un scope tâche invalide lève une ValueError dès la création de la tâche.
1.4 Champs notables
Au niveau chantier :
| Champ | Rôle |
|---|---|
mission_letter (texte libre) |
Lettre de mission structurée (étape 2 de la doctrine) |
preprod_test_plan (texte libre) |
Plan de test preprod — Markdown ou YAML v2 (présence de version: déclenche la QA automatique) |
ship_command (chaîne courte) |
Commande exacte de clôture, ex. ./ship synedre-os |
auto_explode (booléen, défaut true) |
Kill-switch par chantier de la décomposition automatique discovery→implémentation |
mode_auto (booléen) |
Autonomie chantier V1 — l'agent exécute sans valider chaque action |
max_cost_eur (numérique) |
Plafond de coût IA par chantier (NULL = illimité) |
client_id |
Référence vers un client, ou NULL pour un chantier interne |
Au niveau travail : les champs notables incluent le codename et le prompt de l'agent assigné, le périmètre de zone, les critères de sortie, des blocs JSON structurés de contexte / décisions / découvertes, un identifiant de dépendance inter-travaux (avec détection de cycle), l'identifiant de résolution pour le pattern travail-bis (voir §6), ainsi que des métadonnées de conduite, de modèle contractuel, de mode auto, de chemins de dépôt et de backlogs associés.
Au niveau tâche : les champs notables incluent le codename de l'assigné, l'estimation en tokens, le modèle recommandé, la position d'affichage, le résultat du dernier test, les métriques réelles (tokens, coût), les horodatages de début et fin, ainsi que deux champs visuels (visual_intent et visual_url) utilisés par le pipeline de vérification visuelle post-déploiement — une valeur NULL indique une tâche non-visuelle.
1.5 Recrutement d'agents — persistance
Le recrutement d'agents sur un chantier (étape 3 de la doctrine) est persisté dans une table dédiée, distincte du champ d'assignation d'une tâche individuelle (qui ne porte que l'assignation d'une tâche isolée).
| Colonne | Rôle |
|---|---|
| Identifiant assignation (PK) | Clé primaire de l'assignation |
| Identifiant chantier | Lien vers le chantier |
| Codename agent | Agent recruté (ex. Mitnick, Turing, Brunel…) |
| Rôle | production / lead_production / validation / lead_validation |
| Position | Ordre d'affichage |
| Date assignation / désassignation | Cycle de vie de l'assignation |
| Notes | Justification du recrutement |
La logique de cascade tâche→travail interroge cette table pour détecter la présence d'une équipe QA : si un agent avec un rôle validation ou lead_validation est présent, la cascade bascule vers un run de QA plutôt qu'un simple changement de statut (voir §5).
1.6 Journal de décomposition automatique
Une entité dédiée persiste un enregistrement d'audit par invocation du module qui transforme les décisions d'un travail de type discovery en travaux d'implémentation (phases A/B/C). Un enregistrement équivaut à une invocation. Il est créé avec le statut pending en début de pipeline, puis mis à jour en fin.
| Statut | Sens |
|---|---|
pending |
Run en cours |
success |
Travaux d'implémentation créés |
validation_failed |
Plan LLM rejeté par la validation |
llm_failed |
Erreur d'API LLM |
killswitched |
L'un des trois kill-switches a interrompu l'exécution |
Les champs clés comprennent le plan JSON produit, le nombre de travaux créés, les métriques de tokens et de coût, ainsi que des drapeaux dry_run et force. La rétention des enregistrements est configurable (défaut : 90 jours). Un quota journalier global est également configurable : si le nombre de runs des dernières 24 heures le dépasse, la décomposition est marquée killswitched sans erreur. L'historique des runs est consultable depuis le dashboard via la commande /chantier explode list.
1.7 Dépendances tâche→tâche — DAG intra-travail
Le moteur de dépendances entre tâches gère un graphe orienté acyclique (DAG) N:M. À ne pas confondre avec les dépendances inter-travaux (colonne de l'entité Travail) : ces deux mécanismes opèrent sur des niveaux distincts.
Sémantique : une tâche bloquée ne peut démarrer avant que la tâche bloquante ne soit au statut done. Contrainte métier forte : les deux tâches doivent appartenir au même travail — une dépendance inter-travaux lève une erreur applicative dédiée (refus en code, pas de trigger SQL).
| Opération | Méthode conceptuelle |
|---|---|
| Ajouter une dépendance | add_dep(bloquée, bloquante) |
| Lister les dépendances d'un travail | JOIN blocker/blocked avec titres des tâches |
| Lister les bloqueurs d'une tâche | Bloqueurs directs d'une tâche donnée |
| Vérifier si une tâche est débloquée | is_tache_unblocked(id) |
| Supprimer une dépendance | Idempotent — sans effet si inexistante |
Anti-cycle : avant tout ajout, un parcours en profondeur (DFS) est effectué depuis la tâche bloquante dans le graphe existant. Si le parcours atteint la tâche bloquée, une erreur de cycle est levée avant l'insertion. Une garde à profondeur maximale (100 niveaux) protège contre les DAG corrompus.
Un bloqueur au statut
cancelledest considéré comme résolu dans la vérification de déblocage, afin d'éviter les deadlocks. Ce comportement s'applique également au mode auto sélectif, qui ne lance une tâche que si tous ses bloqueurs sont résolus.
Création atomique d'un chantier
La méthode de création de chantier exposée par le moteur de gestion de projets constitue l'unique voie canonique pour instancier un chantier : elle insère atomiquement le chantier, son premier travail et au moins une tâche, empêchant ainsi l'apparition de chantiers orphelins.
Signature
La méthode accepte les paramètres suivants :
- codename : identifiant kebab-case du chantier.
- title : libellé humain du chantier.
- first_travail (obligatoire) : dictionnaire décrivant le premier travail — codename, titre, et champs optionnels tels que priorité, phase courante, tâche courante, prochaine action, blocages.
- first_taches (préféré, doctrine v3) : liste de dictionnaires décrivant les tâches initiales. Chaque tâche porte au minimum un titre et le codename de l'agent assigné ; des champs optionnels enrichissent la description (priorité, estimation de tokens, durée estimée, description, position, modèle recommandé, portée, intention visuelle, URL visuelle).
- first_tache : forme singulière conservée pour compatibilité ascendante — à ne pas combiner avec
first_taches. - client_id : référence optionnelle au tenant concerné.
- priority : niveau de priorité parmi
P0,P1,P2(défaut),P3. - scope, current_focus, notes : champs contextuels optionnels.
La méthode retourne un dictionnaire de confirmation (voir § Retour ci-dessous).
Validations bloquantes
Toutes les validations sont accumulées avant le premier INSERT ; une seule violation lève une ValidationError et annule l'ensemble :
- Format kebab-case du codename — expression régulière
^[a-z0-9][a-z0-9\-]{2,62}[a-z0-9]$: minuscules, chiffres et tirets, 4 à 64 caractères. - Unicité du codename — une vérification d'existence est effectuée ; si le codename est déjà utilisé, la création est refusée.
- Priorité valide — doit appartenir à
{P0, P1, P2, P3}. - Travail initial valide — codename et titre doivent être renseignés et non vides.
- Au moins une tâche —
first_tacheoufirst_tachesest obligatoire ; fournir les deux simultanément est une erreur. - Agent connu — chaque codename d'agent assigné est vérifié dans le registre des agents actifs.
- Au moins deux agents distincts si la portée est de type tenant (doctrine v3) — si le champ
scopecommence partenant, le set des assignees doit contenir au moins deux codenames distincts.
Avertissement non-bloquant : l'absence d'estimation de tokens sur une tâche génère un warning mais n'empêche pas la création — un estimateur automatique complète la valeur manquante (voir § Estimation ci-dessous).
Atomicité et rollback
L'insertion s'effectue dans une transaction unique (BEGIN … COMMIT) avec l'option d'arrêt immédiat sur erreur. Si un seul INSERT échoue, toute la transaction est annulée : il ne peut exister ni chantier sans travail, ni travail sans tâche. Les travaux et tâches référencent leur parent via une sous-sélection sur le codename du chantier, garantissant la résolution des clés étrangères dans l'ordre d'insertion.
Estimation de tokens et modèle recommandé
Si le modèle recommandé n'est pas fourni explicitement pour une tâche, il est calculé automatiquement selon la règle suivante :
| Condition | Modèle sélectionné |
|---|---|
Priorité P0 ou tâche en échec récurrent (≥ 2 itérations en état fail) |
Modèle haute capacité (ex. : opus) |
| Estimation ≥ 8 000 tokens ou estimation absente | Modèle haute capacité (ex. : opus) |
| Estimation ≥ 1 500 tokens | Modèle intermédiaire (ex. : sonnet) |
| Sinon | Modèle léger (ex. : haiku) |
Lors de la création d'une tâche hors skeleton, si l'estimation de tokens est absente, le moteur la calcule via un estimateur dédié, puis recalcule le modèle recommandé sur la ligne persistée.
Compétences et outils attachés
Après l'insertion, le skeleton attache les compétences (skills) et outils (tools) optionnels déclarés par tâche. Un skill ou outil inconnu du registre ne provoque pas d'erreur : un warning est émis et une proposition est mise en attente de validation.
Retour
La méthode retourne un dictionnaire contenant :
- Les identifiants internes du chantier, du travail et des tâches créés.
- Un champ
id_tache(compatibilité ascendante, égal au premier de la liste) etid_taches(liste complète, doctrine v3). - Un objet
codenamesregroupant les codenames du chantier, du travail et des tâches. - Une liste
warningsdes avertissements non-bloquants émis pendant la création.
Interface en ligne de commande
Le moteur de gestion de projets expose une interface CLI permettant de déclencher la création atomique en passant le payload JSON en entrée standard ou via un fichier. L'option --dry-run affiche le payload construit sans effectuer d'insertion. D'autres verbes sont disponibles — liste, affichage, création de travail, mise à jour, clôture, résolution — consultables via l'option --help.
Un hook de garde détecte toute tentative d'insertion SQL directe sur les tables du moteur de projets effectuée en dehors de cette façade, et émet un avertissement.
Procédure de création en 7 étapes
Aucun chantier ne peut être créé sans parcourir ces étapes dans l'ordre. Pour les chantiers déclenchés par email, la façade dédiée exécute les étapes 0a à 4 sous contrainte (blocage si scan d'attachement non-clean ou moins de 2 agents). Elle s'arrête à la création atomique du skeleton (étape 4) et n'effectue ni l'étape 2 (rédaction de la lettre de mission : la façade génère uniquement des titres de tâches génériques du type @agent — analyse…) ni l'étape 5 (mise à jour post-skeleton des champs de mission, de portée, du plan de test et de la commande de livraison). Ces deux étapes restent à compléter manuellement après l'appel de la façade.
| Étape | Action | Mécanisme |
|---|---|---|
| 0a | Lire la demande email verbatim | Lecture via l'API interne de la boîte de réception |
| 0b | Extraire et scanner les pièces jointes avant toute lecture | Extraction des attachements, puis analyse antivirale/antimalware. Verdict non-clean → blocage immédiat |
| 1 | Audit des agents disponibles | Interrogation du registre des agents actifs (codename, surnom, rôle, groupe) |
| 2 | Rédiger la lettre de mission | Structure : OBJECTIF / CONTEXTE / PÉRIMÈTRE / LIVRABLES / CONTRAINTES / DOCTRINE, à partir du contenu lu aux étapes 0a/0b |
| 3 | Recrutement explicite | Au moins 2 agents distincts si la portée est de type tenant |
| 4 | Création atomique du skeleton | Voir § Création atomique |
| 5 | Mise à jour post-skeleton | Persistance de la lettre de mission, de la portée, du plan de test en préprod et de la commande de livraison via UPDATE nominatif sur le codename |
Façade de création depuis un email
La façade de création depuis un email suit le flux suivant :
- Récupération de l'email — appel à l'API interne de la boîte de réception (jamais de SQL direct).
- Extraction et scan des pièces jointes — si un attachement n'est pas
clean, la façade affiche un message de blocage et s'arrête avec le code de sortie2. - Résumé de la demande — extraction du titre, du client, de la priorité et de la portée.
- Liste des agents et recrutement — si moins de 2 agents distincts sont sélectionnés, blocage avec le code de sortie
3. - Construction et insertion du skeleton — une tâche par agent avec des titres génériques, travail initial en phase
discovery. Correspond à l'étape doctrinale 4. Aucune mise à jour de lettre de mission ni d'étape doctrinale 5 n'est effectuée.
Codes de sortie : 2 = attachement non-clean, 3 = moins de 2 agents, 4 = erreur de validation.
Deux niveaux de contrôle distincts sur le nombre d'agents : la façade exige toujours au moins 2 agents distincts, indépendamment de la portée déclarée. Le moteur de création atomique, lui, n'applique cette contrainte que lorsque le champ
scopecommence partenant. Le scope par défauttenantaligne le message de blocage de la façade, mais ne conditionne pas son propre contrôle.
La façade crée un unique travail initial en phase
discovery. La transition vers les travaux d'implémentation reste manuelle ou passe par le mécanisme d'explosion automatique de travaux (voir § Auto-explode).
Champs plan de test et commande de livraison (étape 5)
Ces deux champs sont obligatoires pour tout chantier non-trivial. En leur absence, la cascade de mise à jour du chantier enregistre un avertissement non-bloquant, mais le bandeau « PRÊT À SHIP » ne peut pas être validé. Si le plan de test est rédigé au format YAML v2 (en-tête version:), la cascade déclenche automatiquement en arrière-plan une session de tests Playwright. Un interrupteur d'environnement permet de désactiver ce déclenchement automatique.
Verrouillage multi-session
Le mécanisme de verrouillage permet d'ouvrir N chantiers différents en parallèle (N terminaux ou workers) tout en refusant deux sessions concurrentes sur le même chantier. Ce n'est pas un bloqueur ergonomique, mais un filet anti-collision.
Modèle de données
Le verrou repose sur une table dédiée avec une clé primaire composite (identifiant du chantier, nature du propriétaire). La nature du propriétaire est contrainte à deux valeurs :
- user : session interactive (par exemple, une session SSH d'un opérateur humain).
- worker : sous-processus agent spawné par le moteur de tâches automatisées.
Les deux natures peuvent coexister sur le même chantier ; chaque nature ne conteste que son propre slot. La nature est détectée via une variable d'environnement, avec repli sur l'inspection de l'arbre de processus parents. L'identifiant de session est résolu dans l'ordre : variable d'environnement de session Claude > empreinte du chemin de transcription > combinaison PID/utilisateur/hôte.
TTL et acquisition
La durée de vie d'un verrou inactif est de 30 minutes. L'acquisition tente un INSERT … ON CONFLICT … DO UPDATE qui ne réussit que si l'identifiant de session correspond à l'acquéreur actuel ou si le verrou a expiré (dernière activité il y a plus de 30 minutes). Dans le cas contraire, la méthode retourne {acquired: False, owner: {…}}.
Le verrou est acquis automatiquement lors de la récupération du contexte d'un chantier. En cas de refus, une exception ChantierLockedError est levée, interceptée par la compétence de gestion de chantiers. Un interrupteur d'environnement permet de désactiver entièrement le mécanisme de verrouillage.
Opérations disponibles
| Opération | Description | Option CLI |
|---|---|---|
| Inventaire des verrous actifs | Liste les verrous vivants avec leur propriétaire et date d'activité | --locks |
| Libérer son verrou | Suppression idempotente du verrou correspondant à la session courante | --release <codename> |
| Reprendre le verrou (kick) | Force la reprise du slot de même nature, évinçant le propriétaire précédent | --force-claim <codename> |
| Maintenir le verrou vivant | Met à jour l'horodatage d'activité pour repousser l'expiration TTL | — |
Trois filets de libération
- Hook de fin de session — déclaré dans la configuration des hooks Claude, libère le verrou rapidement en fin de session interactive.
- Tâche cron TTL — s'exécute toutes les 5 minutes, supprime les verrous dont la dernière activité dépasse 30 minutes. Idempotente, toujours en exit 0, silencieuse si la base de données est indisponible ou si la table est absente. C'est le vrai garde-fou contre les crashes, coupures réseau ou terminaisons brutales de processus.
- Force-claim manuel — utilisé en dernier recours pour reprendre un verrou orphelin.
Cascades de statut
Les méthodes de mise à jour des entités sont surchargées pour propager les statuts terminaux d'un niveau au suivant. La cascade est limitée à un cran par niveau — chaque cran redéclenche sa propre cascade de manière autonome.
Logique de propagation tâche → travail
Lorsque toutes les tâches d'un travail atteignent un statut terminal (terminé ou annulé) et qu'au moins une tâche est terminée, le système évalue si une équipe de validation est présente sur le chantier :
- Avec équipe de validation — le moteur de réflexes délègue à un sous-processus de contrôle qualité. Si le verdict global est positif, le travail passe à l'état terminé. Dans le cas contraire, des tâches correctives sont créées et le travail reste actif dans sa phase de développement.
- Sans équipe de validation — le passage à terminé est effectué directement.
Toute exception levée par le sous-processus de contrôle qualité est fail-safe : elle est journalisée sans bloquer ni modifier l'état du travail.
Logique de propagation travail → chantier
Lorsque tous les travaux d'un chantier atteignent un statut terminal et qu'au moins un est terminé, le chantier est promu à l'état test (préprod, en attente de revue). Ce passage déclenche également, de manière non bloquante, le détecteur d'entropie décrit à la section suivante.
⚠️ Le passage tâche → travail n'est pas systématiquement direct. Dès qu'un chantier comporte au moins un agent affecté à un rôle de validation, la cascade délègue au sous-processus de contrôle qualité plutôt que d'effectuer le bump immédiatement. Le travail ne passe à l'état terminé que si le verdict global est positif ; sinon, des tâches correctives sont générées et le travail reste actif. Le bump direct n'a lieu que lorsqu'aucune équipe de validation n'est configurée.
Le passage final test → terminé reste manuel — c'est un acte de validation humaine effectué après la commande de livraison ./ship, jamais déclenché automatiquement par une cascade.
Cascade déclenchée nativement par la base de données (messagerie entrante)
Indépendamment des cascades applicatives décrites ci-dessus, un déclencheur natif de base de données propage automatiquement l'état terminé côté données, de façon transparente pour la couche applicative :
- Ce déclencheur s'active après toute mise à jour du statut d'un chantier.
- Lorsque le chantier passe à terminé pour la première fois, il marque automatiquement comme résolu tous les emails entrants rattachés à ce chantier qui ne sont pas déjà résolus ou classés comme spam. La date de traitement est enregistrée au moment de la résolution.
- Conséquence pratique : un email entrant peut apparaître comme résolu sans qu'aucune action applicative explicite ne l'ait traité directement. Ce comportement est normal et intentionnel — il est à garder en mémoire lors du débogage d'un email passé à l'état résolu de manière apparemment autonome.
Garde-fou : chantiers en phase de découverte et auto-explosion
La cascade travail → chantier comporte un garde-fou spécifique : si tous les travaux terminés sont encore en phase de découverte, le chantier n'est pas promu à l'état test. Ce garde-fou évite qu'un chantier nouvellement créé — ne portant qu'un seul travail d'analyse initiale — ne soit promu en préprod dès la fin de l'analyse, avant que les travaux d'implémentation n'aient été définis.
Dans ce cas, un mécanisme d'auto-explosion peut se déclencher pour transformer le travail de découverte en travaux d'implémentation concrets. Ce mécanisme est protégé par trois coupe-circuits successifs, évalués dans l'ordre :
- Une variable d'environnement permettant de désactiver globalement l'auto-explosion.
- Un indicateur par chantier en base de données (
auto_explode = FALSE). - Un drapeau global activable via fichier de configuration YAML.
Si l'un de ces trois coupe-circuits est actif, le chantier reste en état planification pour revue manuelle. Chaque invocation du mécanisme d'auto-explosion est auditée dans un journal dédié, avec les statuts suivants :
- killswitched — au moins un coupe-circuit a bloqué l'opération ;
- success — les travaux d'implémentation ont été créés avec succès ;
- validation_failed — le plan proposé par le modèle de langage a été rejeté.
Resolve-paused — le pattern travail-bis
Lorsqu'un travail est mis en état bloqué (paused), un travail-bis est créé pour porter la résolution du blocage. Ce travail-bis référence le travail bloqué. Quand le bis passe à l'état terminé, le mécanisme de résolution nettoie automatiquement le travail parent bloqué, avant que la cascade travail → chantier ne soit réévaluée (car ce nettoyage modifie le décompte des travaux terminaux du chantier).
Effets produits lorsque le travail-bis passe à l'état terminé
- Le travail bloqué parent passe à l'état terminé via une mise à jour directe (contournant la récursion de cascade).
- Toutes les tâches encore en attente du travail bloqué parent sont annulées par mise à jour groupée.
- Le journal de décisions est mis à jour symétriquement sur le bis et sur le parent (traçabilité complète).
Garde-fous du mécanisme de résolution
| Condition | Comportement |
|---|---|
| Aucun travail parent référencé | Opération silencieuse sans effet (chemin hérité) |
| Travail parent et bis sur des chantiers différents | Erreur levée — résolution inter-chantier interdite |
| Travail parent déjà terminé | Opération idempotente sans effet |
| Cycle de référence mutuel (A → B et B → A) | Erreur levée — cycle interdit |
| Travail parent introuvable (référence orpheline) | Avertissement journalisé, opération ignorée |
| Statut du parent hors de {bloqué, dev, planification} | Avertissement journalisé, opération ignorée |
Des contraintes de base de données renforcent ce garde-fou : un index partiel sur la colonne de référence, une contrainte empêchant un travail de se référencer lui-même, et une clé étrangère configurée pour mettre la référence à NULL en cas de suppression du parent.
Pièges & invariants
- Colonnes multi-lignes et lecteurs SQL — certains champs textuels (lettre de mission, notes, plan de test, focus courant, prochaine action, tâche courante) contiennent des retours à la ligne. Les fonctions de lecture génériques basées sur un séparateur de colonnes échouent sur ces champs : utiliser systématiquement le lecteur CSV dédié pour toute nouvelle requête portant sur ces colonnes.
- Synchronisation schéma DB / déclaration d'entité — ajouter une colonne en base de données sans l'ajouter à la liste des champs de l'entité applicative correspondante rend les mises à jour silencieusement inopérantes sur cette colonne. Vérifier systématiquement la cohérence entre le schéma DB et la déclaration d'entité lors de toute migration.
- Statuts distincts par niveau (depuis le découpage en deux ensembles) — les statuts valides pour un travail ne sont pas les mêmes que ceux valides pour un chantier. Un statut review est admis pour un travail mais hors-énumération pour un chantier. Toujours passer le bon ensemble de statuts lors de la validation. Ne jamais réutiliser l'ensemble canonique générique pour un nouveau code niveau-spécifique.
-
Contraintes de statut en base de données — des contraintes
CHECKsont présentes en base pour les deux niveaux. Un insert brut avec un statut hors-énumération sera rejeté par la base, y compris dans les scripts de migration. - Périmètre du chantier : la base de données fait autorité — en cas de divergence entre la contrainte DB et la docstring applicative, toujours se référer à la contrainte DB.
-
Champs visuels sur les tâches — deux champs optionnels permettent d'associer une intention visuelle et une URL de référence à une tâche.
NULLsignifie que la tâche n'a pas de composante visuelle. Le pipeline de vérification visuelle post-déploiement contrôle que l'intention est bien rendue. Ne pas omettre ces champs de la déclaration d'entité sous peine d'une régression silencieuse de mise à jour (cf. le piège de synchronisation décrit ci-dessus). - Credentials de base de données — les identifiants d'accès à la base sont lus exclusivement depuis les variables d'environnement du fichier de configuration racine. Ils ne doivent jamais apparaître en clair dans le code source ni dans la base de données.
- Deux mécanismes de dépendances coexistent — les dépendances travail → travail sont gérées par une colonne de référence directe sur l'entité travail ; les dépendances tâche → tâche au sein d'un même travail sont gérées par un graphe orienté acyclique N:M via une entité de dépendance dédiée. Ces deux mécanismes ne sont pas interchangeables. La contrainte inter-travaux sur les dépendances de tâches est purement applicative : la corrompre directement en SQL ne sera pas rattrapée par un déclencheur.
- Le journal d'auto-explosion est un log passif, pas une file de traitement — les entrées de ce journal sont créées et mises à jour par le pipeline d'explosion lui-même. Rien ne les consomme. Ne pas les utiliser pour déclencher ou relancer une opération d'explosion.