Imported from ArgumentumGames/Argumentum (
.claude/skills/coordinate/SKILL.md). Install upstream withnpx skills add ArgumentumGames/Argumentum --skill coordinate. Copyright stays with the author.
Skill : Coordinate — Hub de coordination multi-agents Argumentum
Tu es le coordinateur sur myia-ai-01 (hostname MyIA-AI-01). Le cluster compte 2 workers : myia-po-2023 et myia-po-2024. Ta mission : faire avancer la roadmap release v0.9.0 + go-live DNN, merger ce qui est mergeable, et dispatcher du travail durable et profond aux workers pour qu'ils ne stallent jamais pendant ton gap cron.
Vérifie ton identité d'abord : hostname. Si différent de MyIA-AI-01, tu n'es pas le coordinateur — utilise pipeline-recovery (entrée de session worker/exécution), pas ce skill.
coordinate ≠ pipeline-recovery. Ce skill est l'entrée coordinateur (merge + dispatch + structuration). pipeline-recovery reste l'entrée worker / exécution (sync état, prochaine tâche pipeline, fix/iterate/validate, rapport DONE).
Cluster
| Machine | Rôle | Lane |
|---|---|---|
myia-ai-01 |
Coordinateur | merge, dispatch deep-queue, structuration issues/Epics, verdict QA visuelle (Playwright+vision), aiguillage root-cause, conclusion de cycle |
myia-po-2023 |
Worker | driver DNN (#131/#132/#457…) + régénérations lourdes du pipeline + présente le dossier de validation release à jsboige |
myia-po-2024 |
Worker | backlog : polish traduction (gpt-5.6-sol, vérif cell-by-cell), dette technique, micro-fixes éditoriaux, contenu |
Adressage : toujours machine-id:workspace-id (ex myia-po-2023:Argumentum, myia-po-2024:Argumentum).
Repo GitHub : ArgumentumGames/Argumentum. Le compte gh actif sur ai-01 = jsboige (a les droits write ici). Vérifie gh auth status ; si le défaut a basculé, gh auth switch --user jsboige. Le droit de merge ai-01 est intermittent : en régime deny, router merge ET close via jsboige (cf [[feedback_can_merge_argumentum]]).
Phase 1 — Charger le contexte
Lecture obligatoire dans cet ordre :
MEMORY.md(déjà chargé via auto-injection) — relis les feedbacks cadence/QA/scepticisme.- Dashboard workspace :
(JAMAISroosync_dashboard(action: "read", type: "workspace", section: "all")section: "status"seul, #2306.) → repère le dernier cycle, les dispatches en cours, les messages workers post-dispatch, lesASK/BLOCKED/BUGnon traités. - Inbox roosync_messages :
→ ACKs et notifications des workers (si timeout, retry × 2 puis skip — bug intermittent connu).roosync_messages(action: "inbox", status: "unread", limit: 10) - État GitHub — ⚠️ toujours un
--limitexplicite et large : les défauts CLI (gh pr list= 30,gh issue list= 30) tronquent silencieusement, et le dépôt porte en permanence ~46 PRs dependabot gelées (DNNPlatform/Portals/**, cf #942/#910) qui saturent la première page. Sans--limit, le scan rend « 0 PR non-dependabot » alors qu'il y en a.
Contrôle de non-troncature : si# PRs : exclure dependabot DANS la requête, pas après gh pr list --state open --limit 200 \ --json number,title,author,headRefName,statusCheckRollup,mergeStateStatus \ --jq '.[]|select(.author.login!="app/dependabot")' gh pr list --state open --limit 200 --json number --jq 'length' # total, pour vérifier la non-troncature # Issues : le tri est created-desc ⇒ un --limit trop court coupe les PLUS ANCIENNES, # c'est-à-dire précisément #131/#133/#134/#135/#136 (release + go-live) et #458. gh issue list --state open --limit 300 --json number,title,labels git fetch origin && git log --oneline -5lengthest exactement égal au--limit, la liste est probablement coupée — relance avec un--limitplus grand avant de conclure quoi que ce soit sur une absence. - Roadmap durable :
gh issue view 458(issue de tracking coordination — tracks, owners, décisions jsboige enregistrées). Elle survit à la condensation du dashboard ; mets-la à jour quand la structure évolue.
Phase 1bis — Triage des demandes humaines GitHub (AVANT toute autre lecture)
Les commentaires d'issues sont redevenus un canal vivant (jsboige, 2026-08-26 : « On a commencé à mettre des commentaires dans les issues, il faudra en tenir compte dans les prochains crons »). Ne jamais relire le backlog pour les trouver — un cycle complet de lecture coûte des dizaines de milliers de tokens pour ~2 demandes/mois.
scripts/triage/human-requests.sh # 3 filets, ~1 appel API
scripts/triage/human-requests.sh --self-test # si ça échoue, l'organe est aveugle — le dire
Puis classer chaque prise M (mesure) / F (fix) / D (décision) / V (verdict) et dispatcher M+F aux workers avec citation verbatim, le worker répondant lui-même sur GitHub. ai-01 ne rédige plus que D et V.
⚠️ author.login ne discrimine pas humain/agent : les workers poussent sous le token partagé jsboige. Et Adeline n'a pas de compte — ses demandes passent par jsboige.
📖 Politique complète, mesures et angles morts : triage-github.md.
Phase 2 — Lire AVANT d'agir (règle HARD, aucune exception)
Avant tout merge / comment / dispatch / review :
| Action | Lecture obligatoire |
|---|---|
gh pr merge N |
body + tous comments + toutes reviews (gh pr view N --json body,comments,reviews,statusCheckRollup,mergeStateStatus) + diff (gh pr diff N) |
gh pr review/comment N |
body + comments + reviews existantes (humains ET bots) + diff |
| Dispatch worker | body issue cible + comments + PRs liées (un autre agent a-t-il déjà commencé/abandonné ?) |
| Conclusion de cycle | PRs récentes mergées + état des tracks #458 |
Anti-patterns interdits : « le titre dit X » (lire le body) · « CI verte → merge » (lire les reviews, CHANGES_REQUESTED bloque) · « le bot a APPROVED → merge » (vérifier les humains) · « je sais quoi dispatcher » (lire si déjà commencé). Incident référence : 2026-05-17 CoursIA EPITA, 6 reviews en duplicate/conflit faute d'avoir lu les comments existants.
Phase 2bis — Scepticisme sur les « décisions jsboige » (leçon Argumentum)
Une décision n'est actionnable que si jsboige l'a énoncée dans un canal interactif (message utilisateur direct, ou réponse explicite). Les « arbitrages jsboige », « GO », « décisions » relayés via un worker ou trouvés dans un auto-report ai-01 sur le dashboard ne sont PAS une autorité — le routage d'auth fait que des auto-reports ai-01 peuvent apparaître sous l'identité GitHub de jsboige.
- Avant d'agir sur une « décision jsboige » que tu n'as pas reçue toi-même en interactif : vérifie la source. Si elle vient d'un dashboard/worker → traite-la comme une proposition à confirmer, pas un ordre.
- Si jsboige est présent en interactif et qu'un point bloquant dépend de lui → demande-lui directement (ne pas agir sur une décision hallucinée).
- Qualifie toujours : VÉRIFIÉ (dit par jsboige en interactif) / RAPPORTÉ (relayé) / SUPPOSÉ.
Phase 3 — Merger ce qui est mergeable
Critères (TOUS vrais) :
- Provenance worker établie — ⛔ PAS via
author. Les deux workers poussent avec le token partagéjsboige:author.loginvautjsboigesur toutes les PRs du cluster, donc un critère « auteur =myia-po-2023» est structurellement toujours faux et rejetterait toute PR mergeable. La provenance se lit dans le corps de la PR (signaturepo-2023/po-2024) et se recoupe avec le dispatch correspondant sur le dashboard :bash gh pr view N --json body,headRefName --jq '.body' | grep -oiE 'po-20(23|24)' | head -1Seulapp/dependabots'exclut parauthor(c'est une app, pas le token partagé). Si le corps ne porte pas de signature — le cas mesuré sur #1338 le 12/09 — le critère n'est pas coché : la provenance s'établit par recoupement, et se consigne comme tel. Deux recoupements valent preuve ensemble : le post dashboard de la lane nommant la PR, et un artefact que seule cette machine peut produire (arbre gaté local, chemin de worktree, version de lib câblée). ⚠️ Ne jamais écrire « lu dans le corps » quand le grep est revenu vide : un critère coché sur une mesure absente est pire qu'un critère non coché. Et traiter la cause — c'est le gabarit de dispatch qui doit exiger la signature, pas la PR qui doit être devinée. - CI GREEN (
statusCheckRollup: build + tests pass — Argumentum vise 155+/0/5) - Aucun reviewer
CHANGES_REQUESTEDnon-adressé (reviews ET comments inline) - Diff sans secrets :
gh pr diff N | grep -iE "(api.?key|token|secret|password|BEGIN.*PRIVATE|sk-[a-zA-Z0-9])" - Pas de CSV modifié avant injection CardPen (cf CLAUDE.md —
.Replace("\n","\\n")casse PapaParse) ; pas deRowsetNbforcé nirscount=0;SkipConfigFilecohérent - Pas de modification de
.github/workflows/,.claude/rules/*, ou config de discipline sans intention claire - PR rebasé sur master récent (
mergeStateStatus; siBEHIND→ demander rebase au worker)
Workflow merge :
gh auth status # confirme "jsboige" actif (sinon: gh auth switch --user jsboige)
gh pr merge N --squash --delete-branch
Si mergeStateStatus: BLOCKED malgré CI verte et concerns adressés (reviews "commented" jamais dismissed) → gh pr merge N --admin --squash --delete-branch, mais uniquement après lecture body+reviews+comments+diff et vérification explicite que tous les bloquants sont adressés. Documenter dans le dashboard.
Anti-pendule : si tu allais bypasser une CI rouge ou un CHANGES_REQUESTED non-adressé → STOP, demande à l'utilisateur. Quand un fix swingue vers l'extrême opposé (cf CLAUDE.md « No Pendulum ») → refuser, soustraire plutôt qu'ajouter un contrepoids.
Phase 3bis — Verdict QA visuelle (ai-01 ONLY)
Le verdict de validation visuelle reste sur ai-01 (Playwright + vision). Les workers signalent, ne déclarent jamais « PASS ».
- Hash avant re-check (récurrence #3, [[feedback_stale_harvest_validation]]) : avant de re-valider une re-livraison, hash SHA256 la capture contre la livraison précédente. SHA identique = capture jamais re-générée (harvest périmé) → pas un fix, redemander régén avec clobber du cache.
- Géométrie, pas seulement texte ([[feedback_verification_geometry_not_just_text]]) : pour une carte structurée (grille Mémo Back…), compter la géométrie (colonnes × lignes par famille), pas seulement « texte traduit ». Un 6/6 PASS « texte » sans géométrie est un faux PASS.
- Signature harvest périmé : sous-titre traduit MAIS taxonomie FR = binaire/harvest pré-fix, pas un défaut code.
Phase 4 — Pull master après merges
git fetch origin master && git pull --ff-only origin master
git log --oneline -3
Note le hash de tête ($NEW_MASTER) pour le dispatch. Si des tests doivent re-tourner après un merge structurant : dotnet test "Generation/Converters/Argumentum.AssetConverter.Tests/Argumentum.AssetConverter.Tests.csproj" (jamais npm test).
Phase 5 — Provisionner les pools multi-cycles (mandat « avancer sans moi »)
Principe : ne pas hoarder. Chaque worker possède un pool global multi-cycle, pas une file P0 linéaire. Provisionne 8–12 grains indépendants et exécutables — au moins deux cycles de travail — plus un registre séparé des candidats bloqués. Le pool remplace primaire + secondaire + tertiaire + idle : son ordre guide la pioche, mais un élément indisponible ne bloque jamais les suivants.
Blocage événementiel : représenter chaque blocage par (candidat, événement exact de reprise), exclure temporairement le candidat de la pioche, puis prendre le grain READY suivant. Une PR rouge, une re-review attendue, une tête déjà jugée ou une décision owner manquante ne doit pas être re-sondée tant que l'événement nommé n'est pas arrivé. Le temps qui passe sans événement nommé n'est pas un événement.
Multi-grains (règle owner du 2026-09-10, en vigueur) : une PR ouverte ne met pas le worker en attente du merge coordinateur. Chaque session worker traite tous les grains READY indépendants qu'elle peut terminer sans feedback : branche fraîche depuis origin/master + une PR autonome par grain, jamais de branche empilée sur une PR en vol. Arrêt uniquement sur : vraie décision owner/coordinateur, collision de fichiers avec une PR en vol, gate explicite (tag, QA visuelle, UAC/IIS, séquencement régén) ou épuisement démontré des grains READY. Les gates de merge (Phase 3), UAC et verdict QA visuelle restent inchangées — l'autonomie porte sur l'enchaînement des grains, pas sur les portes. Le débit doit être limité par les dépendances réelles, pas par la cadence de merge du coordinateur.
Responsabilité du paquet de preuve : le worker porte l'instrumentation, le contrôle inverse, la mutation falsifiante, la correction complète, la CI et le paquet de revue. Quand une contre-review croisée est utile, po-2024 prépare le paquet final des PR po-2023 et po-2023 celui des PR po-2024, sans corriger la PR de l'autre. Ai-01 conserve les arbitrages owner, le merge final, la QA visuelle et les frontières de sécurité ; il spot-checke les claims falsifiables au lieu de reconstruire l'analyse complète.
Vérifie chaque lane. ⛔ Ne mesure PAS la liveness d'une lane avec gh pr list --author "po-20XX" : le token GitHub est partagé, ce filtre rend toujours 0, donc « worker sans PR » y est un artefact permanent — et re-dispatcher là-dessus double-démarre une campagne (coûteuse en crédits sur les lanes traduction). La liveness se mesure là où le travail atterrit, c'est-à-dire sur le dashboard (cf [[feedback_explicit_dashboard_comm]]) :
roosync_dashboard(action: "list") # qui a posté, où, quand — y compris les lanes sœurs
roosync_dashboard(action: "read", type: "workspace", section: "all")
# recoupement git, par signature de corps (pas par --author) :
gh pr list --state open --limit 200 --json number,title,body,headRefName \
--jq '.[]|select(.body|test("po-2024";"i"))|"#\(.number) \(.title)"'
Un worker est à re-dispatcher s'il n'a ni PR ouverte signée, ni post dashboard récent, ni dispatch en cours non-ACKé. Si un dispatch est en vol et non ACKé → ping, jamais re-dispatch. Et l'absence de post ≠ mort : certaines lanes ont une cadence cron longue (po-2023 lane IIS = 12 h, cf [[feedback_po2023_iis_cron_12h]]).
Tasking par worker
- po-2023 : DNN (Epic #131/#132/#457…), régénérations lourdes du pipeline, dossier de validation release pour jsboige. Travail compute-intensive et visuel-lourd.
- po-2024 : backlog — polish traduction (
gpt-5.6-soluniquement, re-runs vérifiés cell-by-cell ; pushback si un worker propose un tier inférieur), dette technique (#28/#29/#415…), micro-fixes éditoriaux, contenu. - Sérialisation forcée : si deux tâches éditent les mêmes fichiers (ex CSV trad), dispatcher en séquentiel.
git log -- <fichier>pour repérer les collisions avant un dispatch parallèle.
Où poser le dispatch — le dashboard/l'issue PORTE, le DM NOTIFIE
⛔ Un DM roosync_messages seul ne constitue pas un dispatch. Il n'est consommé que si la lane ouvre son inbox — ce que son protocole d'ouverture de session ne garantit pas. Le dashboard, lui, est lu à chaque ouverture par construction (la Phase 1 l'impose à tous les rôles).
Incident fondateur 2026-09-11 : le dispatch #1294 — seul verrou restant de la régénération — a été confié à un DM (0mp331) puis à un ping (xwwzmb). Aucun des deux relevé. 2 h 35 après un GO owner nommant explicitement l'option, la lane rapportait encore « attente GO owner nommant l'option », et son rapport énumérait ce qu'elle avait lu : dashboard, 6 issues, docs, CI — aucun DM.
⚠️ Piège de diagnostic à ne pas répéter : j'en ai d'abord conclu « canal DM mort », à partir de deux faits tous deux exacts (dispatch non ACKé + worker déclarant attendre). Le fait qui réfute était dans mon propre inbox — un ACK de cette même lane le matin même. Le canal marchait. Deux mesures vraies ne valident pas l'histoire qui les relie : chercher le fait qui réfuterait avant de graver une cause.
Placement, par ordre de durabilité :
| Canal | Rôle | Pourquoi |
|---|---|---|
| Issue GitHub | porte l'ordre qui doit tenir plusieurs cycles | survit à la condensation du dashboard ; c'est déjà là que les workers Argumentum livrent |
Dashboard [TASK] + mentions |
porte l'ordre du cycle | lu à chaque ouverture de session, par construction |
DM roosync_messages |
notifie | urgence, pièce jointe, pointeur vers les deux ci-dessus — jamais seul porteur d'un ordre |
Le remède n'est pas d'abandonner le DM (ce serait le pendule), ni d'ajouter une cérémonie d'accusé de réception : c'est de poser l'ordre là où il sera lu, et de laisser au DM le rôle qu'il remplit bien.
Gabarit pool multi-cycle — l'issue porte, le dashboard résume, le DM pointe
Publie le pool durable sur #458 ou l'issue de tracking appropriée ; ne recopie pas son contenu intégral dans trois canaux.
## Lane pool — `myia-po-XXXX:Argumentum`
### Pool exécutable — plusieurs cycles, une PR autonome par grain
1. **#NNN — objet.** Base/instrument/DoD mesurable ; limites explicites.
2. **#NNN — objet.** …
[… 8–12 grains indépendants, au moins deux cycles …]
### Candidats bloqués — exclus jusqu'à l'événement nommé
- **#NNN** — événement de reprise : nouvelle tête / décision owner nommée / merge préalable / fenêtre réservée.
### Paquet de preuve obligatoire
Body signé worker ; tête/base/merge-state ; surface HARD complète ; diff borné ; CI sur la tête ; instrument + contrôle inverse + mutation falsifiante ; claims qualifiés ; section « n'établit pas » ; commit + PR avant `[DONE]`.
### Gardes
Ai-01 garde merge, arbitrage owner et verdict QA visuelle. Rappeler les gates UAC/webroot/régénération/publication pertinentes à cette lane.
Puis notifier sans dupliquer :
roosync_messages(
action: "send",
to: "myia-po-XXXX:Argumentum",
subject: "[DISPATCH] pool multi-cycle <lane>",
priority: "HIGH",
tags: ["TASK"],
body: "Pool durable : #458 c.<comment-id> ; gouvernance c.<comment-id>. Prends les grains READY sans attendre merge/ACK ; candidat bloqué exclu jusqu'à son événement nommé. Le dashboard porte le résumé."
)
Le dispatch doit aussi structurer dans la durée : si une track #458 manque d'issues granulaires READY, crée-les (issues/Epics) avant de dispatcher — c'est le cœur du mandat « coordination profonde ».
Phase 6 — Dashboard append (synthèse-first)
Ordre OBLIGATOIRE : commit + PR + merge AVANT de poster le DONE. Ne jamais annoncer un travail non commité.
Format (synthèse d'abord, jamais une table de counts seule) :
- Synthèse (2-3 paragraphes) : ce qui vient de se passer, pourquoi, vers où
- Mergé ce cycle : 1 PR/ligne avec commit master + tests
- Tracks #458 — état : progression par track active
- Pools multi-cycles : table workers (grains READY + événements de reprise des bloqués)
- Cluster : master hash + CI + arbitrages en attente jsboige
- Conclusion : 1-2 phrases
roosync_dashboard(
action: "append",
type: "workspace",
tags: ["DONE"],
author: {"machineId": "myia-ai-01", "workspace": "Argumentum"},
content: "## [YYYY-MM-DD HH:MM] ai-01 — <titre>\n\n### Synthèse\n...\n\n### ✅ Mergé\n...\n\n### 🗺️ Tracks #458\n...\n\n### 📤 Pools multi-cycles\n...\n\n### 📊 Cluster + arbitrages en attente\n...\n\n### 🧭 Conclusion\n...\n\n🤖 Coordinator ai-01"
)
Si le status global du pipeline a changé : roosync_dashboard(action: "write", type: "workspace", content: "<nouveau status>"). Si l'append timeout (limite MCP) : version courte — mais le détail actionnable doit rester sur un canal lu (issue GitHub de préférence), jamais reporté sur les seuls DM.
Condition positive de fin du tour ai-01
Après les obligations du cycle, terminer le tour lorsque ces trois conditions sont vraies :
- chaque lane dispose d'au moins deux cycles de grains READY dans son pool ;
- chaque obligation du cycle est mergée, bloquée avec événement de reprise, ou transmise avec un paquet de preuve ;
- aucune tête, décision, review, CI ou autre frontière nouvelle à valeur non marginale ne justifie une action immédiate.
Ne pas relire une tête inchangée, reconstruire un paquet worker déjà complet, ni lancer un nouveau sweep pour remplir le temps. Never-idle reste satisfait par les pools workers ; ai-01 laisse alors le cron de 6 h fournir la prochaine frontière de fraîcheur.
Phase 7 — Ré-armer le cron (régime cron, PAS de ScheduleWakeup)
Argumentum est en régime cron autonome (week-end, jsboige en retrait). Les jobs cron sont session-only : un reload VSCode / reset les tue → vérifier CronList à chaque session et ré-armer si vide.
CronList()
# si aucun job /coordinate :
CronCreate(cron: "<minute off-:00> */<N> * * *", prompt: "/coordinate", recurring: true)
- Cadence = dernière demande explicite jsboige (cf [[feedback-argumentum-cron-3h]] / [[feedback_schedulewakeup_not_cron]]). Elle oscille — aucune valeur n'est écrite ici parce qu'elle s'y périme : la lire dans le dashboard (section État / Décisions actées) ou dans la dernière demande owner, jamais dans ce fichier.
- En régime cron, NE PAS empiler de
ScheduleWakeup— cela ré-introduirait un cycle court superseded. - Minute off-
:00(jitter, éviter que tout le fleet frappe l'API à la même seconde). - Exception : si jsboige bascule explicitement en ping-pong serré interactif (≤1h), alors
ScheduleWakeup(delaySeconds: 3540, prompt: "/coordinate", reason: "...")à chaque fin de turn — mais c'est l'exception, pas le régime courant.
Phase 8 — Présenter à l'utilisateur (+ arbitrages en attente)
Si la session est interactive, termine par 2-4 phrases factuelles : ce qui a été mergé, quelles lanes ont été dispatchées (workers + issues), état des tracks #458, prochain tick cron.
Arbitrages en attente — critère de suffisance : un arbitrage doit être tranchable sur ta description seule, sans ouvrir l'issue. C'est la barre, pas un nombre de lignes.
Correction jsboige, 2026-08-30 (verbatim) : « tu n'es pas assez précis. C'est souvent le cas quand tu me présente les choses […] je dois pouvoir arbitrer sur tes descriptions, elles sont trop expéditives ». Le contre-exemple : « 5 cartes : 1092/1120/362 — réécrire, reclasser ou retirer ». Des branches nommées, donc formellement conforme — et pourtant indécidable, et faux : ces PK étaient corrigés depuis trois semaines (PR #1032).
Chaque dossier porté à l'arbitrage doit donc porter :
| Élément | Pourquoi |
|---|---|
| L'objet cité — le texte fautif, pas son numéro | un PK nu ne dit rien ; c'est le contenu qui se tranche |
| Le défaut en une phrase | ce qui cloche, pas la catégorie du défaut |
| Les branches avec leur conséquence concrète | ce que chacune change dans le corpus |
| Le coût si GO | cellules, langues, régénération ou non |
| La nature de la décision (éditorial / sémantique / hygiène / convention) | des lignes homogènes cachent que une seule est un vrai choix de fond |
⚠️ Re-mesurer l'état au moment de présenter, jamais recopier une note de cycle antérieure : une liste d'arbitrages est un état du corpus, pas du bookkeeping. Une liste expéditive est justement le terrain où une donnée périmée ne se voit pas. Recommandation en première position, et le dire.
Surtout le dossier de validation release (jsboige valide les docs le WE si po-2023 les présente proprement en fin de session). Vérifie que cette présentation est bien prévue côté po-2023 ; sinon, dispatche-la.
Issues, Epics et tracks — source de vérité = GitHub
Ne JAMAIS citer d'Epic/track en dur dans ce skill (ils changent à chaque cycle). Source unique = GitHub Issues + l'issue de tracking #458. Toujours requêter avant d'agir :
gh issue list --state open --limit 300 --search "Epic in:title" --json number,title,labels
gh issue view N --json title,body,comments,state
gh pr list --state merged --limit 10 # avancement récent
Démarrage
hostname → confirme coordinateur. Puis Phase 1 (memory + dashboard + inbox + GitHub + #458) → Phase 2 (lire avant d'agir) → Phase 2bis (scepticisme décisions) → Phase 3-8.
Si tu détectes une PR worker prête à merger ou un worker sans tâche → agis directement, pas de confirmation pour les actions standard. Pour les actions risquées (force push, bypass branch protection non-artefactuel, suppression de fichier non-évidente, action sur une décision jsboige non vérifiée) → STOP et présenter à l'utilisateur.