ADRADR-0001 · Le verrou d'un item de travail est une branche git, pas une checklist partagee

ADR-0001 — Le verrou d'un item de travail est une branche git, pas une checklist partagee

La codebase passe d'un seul developpeur a une flotte d'agents Claude Code travaillant en parallele. Ces agents ont trois proprietes qui cassent les methodes de coordination habituelles : Ils ne se voient pas. Chaque…

Statut

Accepté · 2026-08-12

Piliers : data-platform, security-identity, billing, ai-platform, integrations, commerce-systems, intelligence, marketplace, design-system, growth-web, platform-ops, app-shell

Contexte

La codebase passe d'un seul developpeur a une flotte d'agents Claude Code travaillant en parallele. Ces agents ont trois proprietes qui cassent les methodes de coordination habituelles :

  1. Ils ne se voient pas. Chaque session est isolee. Un agent ne saura jamais qu'un autre edite le meme fichier a la meme seconde.
  2. Ils demarrent amnesiques. Aucune memoire d'une session a l'autre. Tout ce qui n'est pas ecrit dans le repo n'existe pas.
  3. Ils sont rapides et simultanes. Le nombre d'ecritures concurrentes est plus proche d'une equipe de dix que d'un solo.

L'etat de depart etait tasks/todo.md : 356 lignes, 13 workstreams, des cases a cocher. Format parfait pour une personne seule. Avec trois agents, chaque progression est une ecriture dans le meme fichier, donc un conflit git.

Le probleme n'est pas "comment les faire communiquer". C'est "comment rendre la collision impossible sans communication".

Décision

L'unite de travail est un fichier isole dans backlog/, et le verrou qui dit "cet item est pris" est l'existence de la branche fleet/<pillar>/<id>-<slug> sur origin.

En complement, la frontiere d'ecriture de chaque agent est une liste de chemins dans .claude/fleet/ownership.json, verifiee mecaniquement par pnpm fleet:scope en CI.

Alternatives écartées

OptionPourquoi non
Checklist partagee (todo.md avec des cases)Chaque claim est une ecriture dans un fichier commun. C'est le mode de panne qu'on veut supprimer, pas le formaliser.
Champ status: claimed dans le fichier de l'item, sans brancheDeux agents peuvent lire ready puis ecrire claimed en meme temps. Le fichier est le verrou et le verrou est racy : rien n'est gagne.
Issues GitHub avec assignationFonctionne, mais deplace la source de verite hors du repo. Un agent qui clone n'a plus le contexte, et la boucle depend d'un appel reseau. Le repo doit se suffire.
Un service de lock externe (Redis, table Lock)Correct techniquement, mais ajoute une dependance runtime a un probleme de coordination de developpement. Et un lock qui survit au crash de l'agent doit etre expire par un autre systeme.
Confiance dans les consignes ("reste dans ton domaine")Un agent respecte une consigne de bonne foi et la viole quand meme, parce que le fix "d'a cote" est evident. Une regle non verifiee n'est pas une regle.

Conséquences

Ce que ca donne. Le claim est atomique (une ref git existe ou n'existe pas), visible par tout le monde en une commande (git ls-remote), et ne demande d'editer aucun fichier partage. Zero conflit possible sur le claim lui-meme.

Ce que ca coute.

  • Une branche abandonnee bloque un item indefiniment. Mitige par la regle des 72h : @conductor supprime la branche et repasse l'item en ready. pnpm fleet:status remonte le signal dead-lock, mais la liberation reste manuelle.
  • Le champ status dans le fichier de l'item peut diverger de la realite des branches. La branche fait foi ; le champ est une commodite de lecture.
  • Une collision d'id (deux agents prennent le meme numero au meme moment) est possible. Elle est benigne : deux fichiers differents, aucun conflit git, et le triage renumerote.
  • La granularite est celle de la PR. Deux agents ne peuvent pas travailler sur deux zones du meme pilier en meme temps sans se coordonner. C'est assume : un pilier trop large est un signal qu'il faut le decouper, pas relacher le verrou.

Ce qui indiquerait qu'il faut revisiter. Si fleet:status montre regulierement des locks morts, ou si les agents attendent souvent qu'un pilier se libere, la granularite des piliers est mauvaise. Le fix est de decouper la carte d'ownership, pas d'abandonner le verrou.

Comment c'est appliqué

  • scripts/fleet-scope-check.mjs + .github/workflows/fleet-guard.yml : une PR qui traverse plusieurs piliers sans trailer Cross-pillar:, touche un hot file sans trailer Hot-file:, ou laisse un role en ecriture restreinte modifier du code de production, echoue en CI.
  • scripts/fleet-status.mjs : remonte les locks inactifs, les items P0/P1 bloques, les piliers non audites.
  • docs/team/protocol.md section 1 : la procedure de claim.
  • AGENTS.md section "Git workflow" : la convention de branche.

Le verrou lui-meme n'est pas verifie par une machine : rien n'empeche un agent de travailler sans creer la branche. C'est la partie tenue par la convention, et donc la partie qui cassera en premier si le protocole n'est pas lu.