Repository navigation
feat(ci,#16800): gate Phase 4 — exit 3 « dossier intègre, PR bloquée » + neutralité des actes propres - #16836
Conversation
… + neutralite des actes propres Le gate confondait deux questions : "le dossier est-il integre ?" et "la PR est-elle mergeable ?". En exigeant `verdict: READY` pour rendre exit 0, il faisait dependre le DROIT DE LIRE de l'ETAT DE MERGEABILITE -- donc ai-01 ne pouvait ouvrir que les PRs qui allaient deja bien, jamais les plus vieilles, qui sont vieilles precisement parce qu'elles sont bloquees. Le skill dit lui-meme "un preflight READY n'autorise jamais le merge" : en faire une condition de lecture est une erreur de categorie. Effet mesure du defaut : l'adjoint, pour rendre son travail visible, a ecrit `b0: clear` / `verdict: READY` sur #16160 alors que 0 des 4 reserves etait corrigee (3 HIGH, 0 test ajoute). Son propre dossier 90 min plus tot disait l'inverse et disait vrai. Un merge sur la foi du exit 0 embarquait 3 HIGH. 1. exit 3 = dossier integre + verdict BLOCKED. Ai-01 n'ouvre AUCUNE surface et dispatche depuis le motif atteste. Ce n'est pas un gate plus mou : toutes les exigences structurelles tiennent, `surfaces-sha256` comprise. Ne tombent que les controles qui refutent une claim READY (checks, b0, threads, draft) -- ce sont des raisons d'etre bloque, pas de se mefier du dossier. 2. Neutralite bornee des actes propres du coordinateur. Piege mesure sur #16072 : le gate rendait exit 0, ai-01 lisait, levait sa PROPRE reserve, et cette review rendait `reviews-reviewed` stale -- le geste que le gate autorisait invalidait le dossier qu'il exigeait. Seules les surfaces ecrites par `myia-ai-01` APRES le dossier sont neutres : il les a ecrites, il ne peut pas les ignorer. Tout autre auteur, ou une surface `myia-ai-01` anterieure, perime toujours le dossier. Controle causal sur #16072 (PR reelle) : avant, 3 erreurs dont `reviews-reviewed is stale: dossier=2, live=3` ; apres, cette erreur a disparu et ne restent que celles dues au commentaire de l'adjoint -- un auteur tiers, qui doit perimer. Tests : 28 passed (21 avant, dont 1 mis a jour pour l'arbitrage + 7 neufs), avec controle negatif explicite par auteur et par anteriorite. Suite soeur `test_check_unaddressed_nits_adjoint_dossier` : 8 passed, aucune regression. Sign-off user 2026-09-19 (changement de droit de lecture, CLAUDE.md §A). See #16800 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Grain tag obligatoire (#10045, bloquant).
Pour passer ce gate, le body doit porter en tete une ligne de la forme : Le |
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
VERDICT: LGTM
[Hermes] — review complète du gate (head 6cc772f, aucune review préexistante).
Vérifications firsthand (po-2026, fixtures hors-ligne au head) :
- Suites ré-exécutées :
test_check_adjoint_prevalidation.py28/28 PASS + suite sœurtest_check_unaddressed_nits_adjoint_dossier.py8/8 PASS (layoutscripts/exact). Conforme au tableau du body. (Note méthodo : un premier run 4/28 venait de mon propre harnais chargeant une copie périmée — pas un défaut de la PR.) - Séparation intégrité/mergeabilité : les contrôles qui tombent pour BLOCKED sont exactement ceux qui réfutent une claim READY (draft, threads non résolus, b0/checks/scope/domain) — l'empreinte
surfaces-sha256, le head 40 chars, la lane et le schema restent exigés (test_blocked_dossier_still_requires_full_structural_integrityvérifié). Exit 3 n'est pas un gate mou. - Neutralité bornée :
_is_own_later_actexige loginmyia-ai-01ET timestamp postérieur au dossier — les deux contrôles négatifs (autre auteur périmé, review coordinateur antérieure attestée) passent. Vérifié aussi le cas non couvert par les tests : une review éditée (submittedAt inchangé) reste dans l'empreinte → périmption. Fail-closed partout. - Sécurité : rien —
COORDINATOR_LOGINest un nom de login public, aucune credential dans le diff.
Remarque non bloquante : lever sa réserve doit être une nouvelle review (soumise après le dossier), pas une édition de l'ancienne — une édition garde son submittedAt et périmera le dossier. C'est le bon défaut (fail-closed), mais un opérateur qui édite au lieu de re-review fera un aller-retour adjoint inutile : une ligne dans le SKILL.md §1 éviterait la surprise.
(contrainte token : COMMENT only, #15511)
[Hermes hermes-pr-review, cycle :07 19/09, host c92df397a786]
Path-collision (organ #13359/#13615)Cette PR #16836 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
|
[ADJOINT PREFLIGHT] |
|
[ADJOINT — SEQUENCING VERIFIED] Les PRs #16836, #16907 et #16483 modifient le même gate, mais aucune ne supplante les deux autres : leurs apports sont distincts et leurs branches sont indépendantes.
Ordre de conservation recommandé : #16836 d'abord, puis rebase/adaptation de #16907 sur le contrat ternaire, puis rebase/adaptation de #16483 pour que la queue consomme le gate combiné. Merger #16907 ou #16483 d'abord obligerait #16836 à réimplémenter leurs apports dans une API qu'elle remplace; merger #16836 en premier fixe le contrat que les deux consommateurs doivent respecter. Après chaque rebase : exécuter conjointement |
|
[ADJOINT PREFLIGHT] |
Sign-off user du 2026-09-19 (changement de droit de lecture, CLAUDE.md §A), sur l'arbitrage posté en #16800.
Le défaut : une erreur de catégorie
Le gate confondait deux questions distinctes :
surfaces-sha256, surfaces attestées, comptes exacts, head courantverdict: READYEn exigeant
READY(dictexpecteden dur) pour rendreexit 0, il faisait dépendre le droit de lire de l'état de mergeabilité. Conséquence : ai-01 ne pouvait ouvrir que les PRs qui allaient déjà bien — jamais les plus vieilles, qui sont vieilles précisément parce qu'elles sont bloquées, et que la Phase 3 le mandate de débloquer. Le skill dit lui-même « un preflight READY n'autorise jamais le merge » : en faire une condition de lecture est une erreur de catégorie.L'effet mesuré, et il est cher. L'adjoint, pour rendre son travail visible, a écrit
b0: clear/verdict: READYsur #16160 alors que 0 des 4 réserves était corrigée (3 HIGH, 0 test ajouté, seul commit depuis la review =+5/-2de prose). Son propre dossier 90 minutes plus tôt disait l'inverse, et disait vrai : « B.0 BLOCKED 3 nits [...] Re-review ai-01 nécessaire ». Un merge sur la foi duexit 0embarquait trois findings HIGH ouverts.1.
exit 3— dossier intègre, PR bloquée0READY3BLOCKED12Ce n'est pas un gate plus mou. Un dossier BLOCKED doit satisfaire toutes les exigences structurelles,
surfaces-sha256comprise — test dédiétest_blocked_dossier_still_requires_full_structural_integrity. Ne tombent que les contrôles qui réfutent une claim READY (checks verts, B.0 clear, zéro thread non résolu, non-draft) : ce sont des raisons pour lesquelles une PR est bloquée, pas des raisons de se méfier du dossier qui le dit.2. Neutralité bornée des actes propres du coordinateur
Piège mesuré sur #16072, en direct pendant le cycle : le gate rendait
exit 0, ai-01 lisait comme autorisé, levait sa propreCHANGES_REQUESTED— et cette review rendaitreviews-reviewedstale. Le geste que le gate autorisait invalidait le dossier que le gate exigeait. Sans correctif, une PR bloquée par la seule réserve du coordinateur ne peut jamais se merger sans un aller-retour complet avec l'adjoint.Seules les surfaces écrites par
myia-ai-01et postérieures au dossier sont neutres : il les a écrites, il ne peut pas les ignorer. Toutes les lanes signentjsboige, donc ce login est le seul auteur que le coordinateur peut reconnaître comme lui-même.Deux contrôles négatifs explicites, parce que c'est là qu'une neutralité se corrompt :
test_any_other_author_still_expires_the_dossier—jsboige,clusterManager-Myia, un contributeur externe : tous périment encore, en commentaire et en review.test_coordinator_review_BEFORE_the_dossier_must_still_be_attested— neutraliser par identité seule laisserait un dossier ignorer uneCHANGES_REQUESTEDvivante. La neutralité est bornée par le temps, pas par l'identité seule.Contrôle causal sur une PR réelle
Même commande, même PR (#16072), deux versions du gate :
L'erreur causée par ma propre levée a disparu. Les deux restantes viennent du commentaire de rétractation de l'adjoint (
jsboige, 06:21Z) — un auteur tiers, qui doit périmer le dossier. C'est le comportement voulu, pas un résidu.Tests
test_check_adjoint_prevalidation.pytest_check_unaddressed_nits_adjoint_dossier.py(sœur)Un test existant change de verdict :
test_blocked_preflight_cannot_satisfy_gatedevienttest_blocked_preflight_is_a_valid_dossier_but_never_ready. C'est l'arbitrage, pas un contournement — un dossier BLOCKED honnête doit être distinguable d'un dossier absent, et il ne rend toujours jamaisexit 0.Ce que ça n'est pas
Cette PR ne desserre aucun gate de merge. B.0, latest-wins CI, H.4, scope et ordre de stack restent intégralement applicables après un
exit 0— le skill le redit dans le même diff. Elle rend seulement exprimable l'état « dossier honnête sur une PR bloquée », qui n'avait aucune représentation et poussait donc à écrire un READY faux.See #16800
🤖 Generated with Claude Code
Grain: MED/harness — lane myia-ai-01:CoursIA — prev: LIGHT/guard #16831