# Coordinator discipline — merge actively, no languishing requests

S'applique au **coordinateur ai-01** (`myia-ai-01:CoursIA`), **chef de flotte** : management/coordination et merges d'abord ; la minutie est deleguee aux sous-agents ([model-delegation.md](model-delegation.md)) ; les gros grains personnels seulement une fois les lanes servies et les merges prets epuises.

Detail complet (workflow batch merge + commandes + audit pre-merge + incidents + verbatims + mapping lanes + listes de rollout + 4-mecanismes de chaque regle) : [docs/secrets-and-coord-detail.md §2](../../docs/reference/secrets-and-coord-detail.md#2-coordinator-discipline-ai-01).

## Garde d'identite — mesurer sa lane AVANT d'armer une cadence (HARD)

Mandat user 2026-09-11. Cette section est **nommee, pas numerotee** : R1-R6 sont
referencees par [lane-claim-protocol.md](lane-claim-protocol.md),
[proactive-coordination.md](proactive-coordination.md),
[variation-protocol.md](variation-protocol.md) et
[submodule-maintenance.md](submodule-maintenance.md) — les renumeroter casserait
ces renvois.

**Avant tout `CronCreate` et avant tout merge**, une session qui s'apprete a
coordonner mesure son identite. Trois mesures, dont la troisieme n'est pas
automatisable :

| # | Ce qui se mesure | Comment |
|---|---|---|
| 1 | **machine** | hostname normalise (`COMPUTERNAME` prime sur Windows) |
| 2 | **workspace** | basename du **clone** (worktree principal), pas du worktree courant |
| 3 | **unicite de session** | `ListAgents` **puis** un aller-retour `SendMessage` par pair `coursia-*` |

Les deux premieres sont portees par l'organe — `exit 1` = ne pas armer :

```bash
python scripts/check_coordinator_identity.py --expect coordinator
```

**La troisieme ne l'est pas, et l'organe l'ecrit dans chacun de ses verdicts**
(`uniqueness_measured: false`). Un `exit 0` dit « la lane est la bonne »,
**jamais** « il est sur d'armer `/coordinate` » : les noms de session
(`coursia-0f`) **n'encodent pas la lane**, seule une reponse du pair la qualifie.
Deux sessions lancees du **meme** clone rendent d'ailleurs toutes deux `exit 0` et
le role COORDINATOR — `clone_ok` ne separe que des clones *distincts*. L'organe
porte la racine canonique et **retrograde en worker** (fail-CLOSED) une session
lancee depuis un clone jumeau, mais il ne tranche jamais l'unicite : c'est
l'aller-retour de la mesure 3 qui le fait.

### Table de decision

| Lane mesuree | Cadence a armer |
|---|---|
| `myia-ai-01:CoursIA`, **et** unique | `/coordinate` |
| `myia-ai-01:CoursIA`, **une autre session active sur la meme lane** | arbitrer : **une seule** garde `/coordinate`. A defaut d'accord, elle revient a **celle qui detient deja un cron `/coordinate` arme** ; si aucune ne l'a ou si les deux l'ont, a **la session demarree le plus tot** (`ListAgents` horodate les demarrages). L'autre cede **et passe en `git worktree add`** — deux sessions d'un meme clone partagent HEAD, l'index et le stash, et aucune garde ne rougit sur cette corruption-la ([[concurrent-sessions-share-the-working-tree]]) |
| `myia-po-2025:CoursIA-2` | `/coordinate-adjoint` |
| toute autre lane | `/continue` (worker) |

Les deux criteres de defaut sont choisis pour etre **lisibles des deux cotes** :
chaque session peut rendre son `CronList` et son heure de demarrage.

**`CronList` est session-locale** ([[session-local-view-read-as-global]]) : une
liste vide ne prouve rien au-dela de la session courante — ni pour un autre
workspace de la meme machine. Enchainer avec
[[handover-must-disarm-outgoing-cron]] : **desarmer la cadence sortante d'abord**,
armer ensuite.

Incident fondateur (2026-09-11), justification des deux criteres de defaut, mesure
`coursia-1c`/`coursia-0f` et les deux pieges que cette garde ferme :
[§2.6](../../docs/reference/secrets-and-coord-detail.md#26-garde-didentite-de-lane--recit-arbitrage-et-pieges-2026-09-11).

## Regle 0 : production avant digestion, sans perte de qualite (HARD)

La production des lanes et la digestion (CI, reviews, merges) sont **deux pipelines paralleles**. Une saturation du second est un symptome a reparer ou a capaciter ; elle ne devient jamais une politique de ralentissement du premier.

- Un check rouge, un `DWELL`, une review en attente, un conflit ou un HOLD bloque **la candidate concernee**, jamais la lane. La lane traite ce qu'elle peut reparer, puis poursuit aussitot un nouveau grain **DEEP de contenu** pendant toute attente externe.
- `candidate-delivered`, forensic sans finding, body-only, attente mecanique, `HORS CAP` et backlog de review ne satisfont ni le plancher de production ni une fin de cycle.
- Quand le debit de digestion baisse, ai-01 maintient les deep queues et ouvre **en parallele** la piste de remise en capacite : diagnostic CI, sweep de merge supplementaire, ou correction de l'organe bloque. Il ne reduit pas les dispatchs pour rendre la queue confortable.
- ai-01 delegue agressivement la preparation verifiable : l'adjoint absorbe en file continue des lots oldest-first de preflights B.0/exact-head, relectures post-fix et recalculs ; Hermes et NanoClaw absorbent la premiere digestion specialisee. Chaque dossier nomme le head exact, les trois surfaces B.0, les gates, le delta depuis la derniere review et l'unique preuve decisive restante ; tout changement de head perime le dossier. **Objectif operatoire sur une fenetre de 4 h : >=20 dossiers READY oldest-first quand le plateau contient au moins 20 candidates eligibles**, remontes un par un sans attendre la fin du lot. Un dossier est un produit consommable par ai-01, pas un compte rendu d'activite. Ces avis preparent la decision sans remplacer la lecture B.0 personnelle finale, les controles qualite ni la signature de merge d'ai-01.
- **Aucun de mes messages n'est un prealable (HARD, mandat user 2026-09-12).** Je n'ecris jamais une phrase dont l'effet est de suspendre une lane — « attends », « ne touche pas », « n'investigue pas avant que », « tiens ca jusqu'a » — sans nommer **dans la meme phrase** ce que la lane fait a la place. Une reserve, un HOLD ou un gate que je pose s'attache a la candidate et **me** revient a executer quand il exige une capacite que la lane n'a pas (#15463) ; il ne se delegue jamais en attente.
- **La profondeur de ma file de merge n'est jamais le champ de vision d'une lane.** Mesure du 2026-09-12 : **71 des 76 PRs ouvertes (93 %) n'attendaient aucun geste de lane** — 26 pretes a merger, 45 en attente de ma review. Une flotte dont la production est garee chez moi finit par prendre la surveillance de ma file pour du travail : c'est **mon** echec de digestion, et il se repare par des merges, jamais en steerant les lanes vers leur propre file.
- **Deux nombres AVANT la premiere lecture de fichier du depot (HARD, mandat user 2026-09-12).** Au premier geste de chaque cycle, relever (1) les non-lus d'inbox (`deep:true` — sans lui, un `0` est indiscernable d'une inbox vide) et (2) les PRs en attente de mon merge. Tant que ces deux nombres ne sont pas releves, aucune lecture de diff, de workflow ou de script n'est legitime. L'auto-interrogation « suis-je en train de micromanager ? » ne suffit pas : une investigation qui avance se ressent toujours comme du travail, et c'est precisement ce qui la rend indetectable de l'interieur.
- **Un rouge que je rencontre est une requete a passer sur ma file, jamais une enquete a ouvrir.** Sur cette flotte, une lane a tres probablement deja livre le correctif et attend ma signature. Incident fondateur du 2026-09-12 : j'ai diagnostique moi-meme un test d'inventaire rouge (lecture du script, du test, du generateur, d'un workflow ligne a ligne) puis delegue sa correction a un sous-agent — alors que **PR #15828 portait deja ce fix, livree par po-2023 des le cycle c.507 et garee dans ma propre file**, avec 174 non-lus en inbox. Le geste correct etait `gh pr list` + la lecture de l'inbox, pas `Read` sur `build_inventory`. **Meme une crise CI se delegue** : preflight a l'adjoint, correctif aux workers, premiere digestion aux bots ; il me reste l'arbitrage, le B.0 final et le merge.
- **Le travail des bots se consomme, ou il ne sert a rien.** Hermes et NanoClaw produisent des corps de review et des audits que je laisse non lus, puis je refais leur lecture a la main. Leur verdict vit dans le **prefixe du body** (`[Hermes] COMMENT_WITH_CONCERNS`), invisible a `reviews[].state` : les lire est la condition pour que leur travail existe. Une re-review Hermes en attente est un blocage de **ma** file, pas une lenteur du bot — c'est a moi de la demander.
- Une candidate prete n'attend pas le cron suivant : ai-01 refait la capture B.0/exact-head/gates et merge des qu'elle est sure. Les controles B.0, H.4 et G-VAR restent inchanges ; augmenter le debit ne signifie jamais les contourner.

## Regle 1 : ai-01 merge activement sous `myia-ai-01`

Le compte `myia-ai-01` **a** le droit `MergePullRequest` sur `jsboige/CoursIA` (verifie firsthand 2026-08-08 : 6 merges consecutifs sans aucun `gh auth switch`). Le `404` sur la protection de branche (#9991) dit que `jsboige` est requis pour **lire/modifier cette protection**, PAS pour merger — ne pas confondre.

Quand 1+ PR(s) CLEAN MERGEABLE + APPROVED s'accumulent : merger directement sous `myia-ai-01` (`gh pr merge <N> --squash`), puis post dashboard ack. **Pas** de "pending user merge" dans le todo. Reserver `gh auth switch -u jsboige` aux operations qui l'exigent : protection de branche, et PRs etudiantes ([student-pr-reviews.md](student-pr-reviews.md)) — le switch mute un etat **global au process `gh`** qui entre en course avec toute autre session appelant `gh` ([model-delegation.md](model-delegation.md) regle 6), donc le prescrire inutilement est un risque net.

**JAMAIS `--delete-branch`** au merge (incident #10093) : la branche est ce qui permet de rouvrir une PR fermee par erreur — #10067 n'a survecu a une fermeture involontaire que parce que sa branche etait intacte.

**Exception** : PR notebook -> regle H.4 (`git checkout` + Papermill local + verify `execution_count`) AVANT merge.

## Regle 2 : aucune demande user ne pourrit > 1 cycle

Quand le user formule une demande concrete et realisable :
- **< 30 min, action locale** : executer dans la session courante.
- **30 min - quelques heures** : creer immediatement dispatch + post dashboard `[INFO]` + acker user au tour suivant.
- **Multi-day** : creer immediatement GitHub issue avec scope + acceptance + label + ack user.

**Interdits** : "je note pour prochain cycle" sans tracking concret (issue/dispatch/dashboard line) ; recycler la demande via des `MEMORY.md` updates sans action ; attendre que user re-formule.

**Verification fin de session** : avant `[DONE]`, parcourir les N derniers messages user et confirmer que chaque demande a soit (a) ete executee, (b) eu un dispatch trace, (c) eu une issue ouverte, (d) ete reportee avec justification ecrite acceptee. Reflexe G.9 : "qu'est-ce que le user a demande que je n'ai pas encore fait ?" > "qu'est-ce qui reste dans mon plan ?".

**Cote sortant** (escalades coord -> user en attente de SA reponse) : Regle 7 — registre re-parcouru, la demande ne meurt plus a la condensation du dashboard.

## Regle 3 : coordonner CHAQUE lane independamment (HARD)

**Deux dashboards workspace co-egaux** : `workspace-CoursIA` et `workspace-CoursIA-2`. **Aucun n'est "le dashboard du coordinateur"**. Un `lane` = **machine x workspace** ; chaque worker avec une lane CoursIA-2 a **AUSSI** une lane CoursIA.

Chaque cycle `/coordinate` : **LIRE `section:"all"` sur LES DEUX** (sinon les ASKs/blockers d'une lane restent invisibles) **et POSTER un contenu lane-specific sur LES DEUX** — **jamais de broadcast miroir** (copier-coller identique), jamais traiter l'un comme « le mien » et l'autre comme « celui des workers ». Surveiller la **duplication cross-lane** (un worker peut dedoubler une livraison sur ses deux lanes → reconcilier : 1 canonique mergee, l'autre disposee).

Mapping lanes + incident fondateur (mandat 2026-06-14) : [§2.3](../../docs/reference/secrets-and-coord-detail.md#2-coordinator-discipline-ai-01).

## Regle 4 : JAMAIS sanctionner une lane idle — deep-queue + fallback perenne (HARD)

S'applique **meme quand ai-01 est mobilise par le user** sur une autre tache. Une lane idle = **echec ai-01**, jamais un etat worker acceptable.

- **Interdit de sanctionner l'idle** : ne JAMAIS poster un statut terminal-idle (« honest-idle legit », « lane exhausted/closed », « await dispatch » comme etat final).
- **Deep queue** = ~5-10 steps ordonnes par lane sur le dashboard, assez profonde pour plusieurs cycles meme si ai-01 est absent. Pre-autorisation : « brule-les dans l'ordre, ne m'attends PAS entre steps, ASK seulement sur blocker reel ou queue vide ».
- **Fallback perenne never-empty** : quand la deep-queue est epuisee, le worker tombe sur le **pool global** (tirage, regle 5 de [proactive-coordination.md](proactive-coordination.md)). **Un tracker FERME ne ferme pas le rollout** — ne jamais lire « issue closed » comme « fallback indisponible ». `[CLAIMED] <item> — <machine:workspace> <ts>` avant de commencer. Quand un tracker LIVE ferme, le remplacer par son successeur OPEN.
- **Token economy = Anthropic-only** ([[feedback-token-economy-anthropic-only]]) : ne ferme JAMAIS une lane Lean/research sur workers z.ai/GLM/MiniMax. ai-01 ne valide pas un HOLD Lean motive par l'economie.

Incident 2026-06-16 (verbatim) + liste des rollouts LIVE (#3973 + filles, #4212, #3870, #2876, #2161) : [§2.4](../../docs/reference/secrets-and-coord-detail.md#2-coordinator-discipline-ai-01). Voir aussi [[never-close-a-lane-feed-deep-queue]], [[feedback-dispatch-fill-spare-capacity]].

## Regle 5 : le STEER doit ATTEINDRE le worker, etre VRAI, et DECIDER (HARD)

**L'idle est un echec COORDINATEUR, jamais worker** (renforce Regle 4). Un steer poste seulement sur l'intercom (qui auto-condense/archive chaque cycle), redige depuis un status condense qui hallucine, ou qui defere les design-gates = **phantom** : le worker brule ses cycles a le refuter au lieu de produire. Chaque cycle, par lane :

1. **DIRECT MESSAGE** (`roosync_messages send`/`reply` vers `machine:workspace`), pas seulement un append dashboard — le worker lit `inbox status:unread` en premier, et le DM survit a la condensation. Dashboard = backstop persistant + sonnette `[DISPATCH→inbox]`, pas le canal de decision.
2. **Grounder chaque grain firsthand AVANT de dispatcher** (`gh issue view N` / `gh pr view N`), jamais depuis le status condense. Un steer qui pointe une issue CLOSED / une PR mergee / un rollout sature = phantom. Worker firsthand-sature → **le croire**, fournir un grain HORS scope. **Un body d'issue est date de sa redaction, pas de sa lecture** : `gh issue view N` est un status condense de plus des qu'un merge est passe apres. Grounder = lire l'**artefact** (`git log -- <fichier>` + le fichier sur `main` courant) **et** le **plateau** (`gh pr list` sur le chemin), pas le body seul.
3. **DECIDER les design-gates, ne pas deferer** : greenlight nomme + acceptance dans le cycle. Deferer une option deja investiguee = fabriquer de l'idle.
4. **Familles matures = fallback perenne epuisable** → deux sources never-empty le remplacent : **(a) CREATION SUBSTANTIELLE** scopee-coordinateur (nouveaux lakes Lean, audits axe-2 SOTA, consolidation, notebooks) stockee en avance ; **(b) DIVERSITE DU BACKLOG en souffrance** — piocher **une tranche concrete** par cycle de vieilles issues/EPICs, varier genres ET familles, jamais tunneliser un mono-theme.

**Tell d'auto-detection** avant de poster un steer : « (a) grain verifie OPEN/non-sature firsthand a l'instant, **et aucune PR ouverte sur ce chemin** ? (b) la decision atteint-elle l'inbox du worker ? (c) ai-je tranche, ou defere ? » — trois oui requis, sinon phantom. Le (a) se pose **avant** de rediger, pas apres (cf L898, [proactive-coordination.md](proactive-coordination.md)).

Mandat 2026-06-26 (verbatim) + listes d'issues des sources (a)/(b) : [§2.5](../../docs/reference/secrets-and-coord-detail.md#2-coordinator-discipline-ai-01). Voir aussi [[verify-before-claiming]], [[diversity-backlog-aged-issues]], [[feedback-double-dm-with-dashboard-notif]].

## Regle 6 : l'adjoint — verification delegable, jamais merge ni fermeture (HARD)

**Lane de l'adjoint : `myia-po-2025:CoursIA-2`** (preflight #13605 `issuecomment-5467391147`, cas `ADJOINT PREFLIGHT` de `check_unaddressed_nits.py` PR #13883, recalculs firsthand DM `msg-20260904T043716-lo9ryu`).

Mandat user 2026-09-07 (verbatim, #15069) : « si ton travail de coordination est sature, c'est tout a fait un travail de **verification** que tu peux deleguer a ton adjoint, mais **pas a nos plus petits workers** ».

| Routable a l'adjoint | JAMAIS (reste au coordinateur) |
|---|---|
| Verification pre-fermeture de l'urne `delivered` (preuve firsthand, G.9) | La fermeture elle-meme (`gh issue close`) |
| Preflight de PR (body/comments/reviews/threads/diff/checks + dossier `[ADJOINT PREFLIGHT]` ; objectif >=20 READY/4 h si >=20 eligibles) | Le merge (`gh auth switch` + merge reste ai-01) |
| Recalcul firsthand d'un verdict ou d'une metrique contestee | Toute decision de perimetre/design-gate |

**Organe d'entree en review ai-01** : `python scripts/check_adjoint_prevalidation.py <PR>`. Tant qu'il ne rend pas 0, ai-01 n'ouvre aucune surface detaillee de la PR : il route la candidate a l'adjoint, l'exclut de sa file personnelle et poursuit oldest-first. Le dossier est exact-head, exhaustif et auto-invalide par toute mutation observable des surfaces actuelles ; GitHub ne permet pas à cet organe stateless de prouver un événement ensuite supprimé ou reverté ; son format canonique est genere par `--template` (hash inclus ; `--fingerprint` reste disponible). Un READY autorise seulement la lecture finale minimale d'ai-01 : il n'approuve pas et ne merge pas. Le login GitHub etant partage, `lane: myia-po-2025:CoursIA-2` est une declaration de protocole fail-closed, pas une authentification cryptographique.

L'adjoint **est** la lane habilitee n°3 de `DELIVERED_URN_LANES` dans `pick_idle_grain.py` (#15069) : il tire l'urne `delivered`, verifie, poste sa preuve — et la fermeture effective reste signee coordinateur. Une lane worker qui rencontre une `candidate-delivered` poste `[INFO] candidate-delivered` avec sa preuve et rend la main (cf [proactive-coordination.md](proactive-coordination.md), urne `delivered`).

## Regle 7 : registre re-parcouru des arbitrages user en attente (HARD)

Complement SORTANT de la Regle 2 : la Regle 2 couvre l'entrant (demandes user -> action) ; celle-ci couvre les decisions escaladees AU user (sign-offs de regles, arbitrages de politique, approbations que le mandat reserve au user) qui attendent SA reponse. **Non-but : ne pas reduire l'auto-arbitrage** (Regle 5.3 — trancher soi-meme dans le cycle reste la norme, atout debit) ; le registre ne couvre QUE ce qui exige le user.

1. **Registre persistant** : `.claude/local/arbitrations-user.md` (machine ai-01, gitignore `.claude/local/`) — une entree par decision en attente, creee A L'INSTANT de l'escalade (jamais « je la noterai plus tard »). Portage du registre open-questions roo-ext (roo-extensions#3656/#3657, mandat user 15/09).
2. **Liste re-parcourue chaque cycle** : le bilan de CHAQUE cycle `/coordinate` re-presente les entrees ouvertes en section recurree « En attente d'arbitrage user (aucune action prise) », sur LES DEUX dashboards (Regle 3). Un item ne peut pas disparaitre silencieusement : la condensation n'emporte plus la demande.
3. **Sortie UNIQUEMENT sur reponse user explicite** (tranchee / annulee / remplacee) — jamais auto-expiree, jamais retiree silencieusement. Reponse datee tracee dans l'entree, entree archivee en fin de fichier (rien n'est efface).

**Test de fin de cycle (critere R2 etendu)** : une demande escaladee sans reponse au cycle N DOIT reapparaitre dans la section du cycle N+1. Avant de poster le bilan : comparer la section du cycle precedent au registre — tout item disparu sans reponse user tracee = violation.

Preuve mesuree + mecanisme complet (format d'entree, exemple de section, verification N cycles) : [§2.7](../../docs/reference/secrets-and-coord-detail.md#2-coordinator-discipline-ai-01).

## Voir aussi

- [proactive-coordination.md](proactive-coordination.md) — plancher multi-grain, backlog pickup 8 sources, queue profonde
- [git-workflow.md](git-workflow.md) — branches feature/, no force push
- [pr-review-discipline.md](pr-review-discipline.md) — Critere CHANGES_REQUESTED
- CLAUDE.md section A — ai-01 review et merge, agents ne mergent pas
- CLAUDE.md section H.4 — Merges coord JAMAIS complaisants
