Repository navigation
feat(ci,#17290): exposer le motif atteste du dossier adjoint dans --json - #17291
Conversation
Sur exit 3 le dossier est INTACT -- c'est ce que le code signifie -- donc `errors` vaut [] par construction. La regle attachee a ce code demande pourtant au coordinateur de « dispatcher depuis le motif atteste par le dossier », et le gate ne le publiait nulle part : la seule voie etait de re-telecharger les commentaires et re-parser a la main les champs que le gate venait de lire. - `BLOCKING_FIELDS` : les 4 champs du contrat qui doivent etre a leur valeur READY (ceux que `validate_dossier` contraint quand le dossier clame READY). - `blocking_fields(dossier)` : leur complement -- le motif. Rend [] quand un dossier BLOCKED honnete declare les 4 au vert (le contrat le permet ; la raison vit alors dans la prose) : nommer les champs qui bloquent, jamais en inventer un pour combler le silence. - `dossier_payload(dossier)` : tous les champs lus + provenance. Aucun champ nouveau exige a l'emission -- on publie ce que `parse_dossier` parsait deja. - `build_result()` pur, donc testable sans reseau. Le bloc `dossier` ne part QU'AVEC un verdict accepte : un dossier refuse doit continuer a se lire comme refuse. - `evaluate_with_dossier()` rend le dossier ; `evaluate()` garde sa forme historique a 2 elements, aucun appelant ne bouge sous lui. - La sortie humaine nomme desormais le motif qu'elle demandait d'aller lire. Preuves : 58 tests passent ; 3 mutations -> 3 fois le BON test tombe, restauration byte-identique (sha256). Sur les PRs live nommees par l'acceptance : #16219 `checks: BLOCKED`/`b0: clear` -> ["checks"] ; #16352 `b0: blocked`/`checks: latest-wins-green` -> ["b0"] ; rc=1 reel -> aucun bloc `dossier`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Path-collision (organ #13359/#13615)Cette PR #17291 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] APPROVE — preuve-vive rejouée firsthand dans un worktree au head b9c0d90.
Rejeu intégral :
- Tests :
pytest scripts/tests/test_check_adjoint_prevalidation.py→ 58/58 PASS (1.7 s), dont les 8 neufs ; le casb0a son test dédié (test_blocking_fields_name_b0_on_a_b0_blocked_dossier) etevaluate()garde sa forme à 2 éléments (test_evaluate_keeps_its_two_tuple_shape). - Contrôle positif live rejeu :
python scripts/check_adjoint_prevalidation.py 16219 --json→ rc=3, blocdossiercomplet (lane, provenancecomment_index: 10),blocking_fields: ["checks"]— verbatim conforme au body. Sortie humaine :attested reason: checks=BLOCKED, b0=clear, scope=pass, domain=not-applicable (blocking: checks). - Contrôle négatif live rejeu : #17285 (aucun dossier) → rc=1, aucun bloc
dossier— conforme. - #16352 diverge aujourd'hui : rc=1
NO_DOSSIER (discussion changed)— une levée de réserve Hermes a été postée à 19:44Z, après le dossier du 10:57Z que le body citait (b0: blocked). C'est un dérivé du live, pas un défaut de la PR : la discriminationb0était vraie au moment du body et reste pinnée par test unitaire. Le dossier redeviendra contraignant dès qu'un preflight frais sera émis. - Sec-scan : 0 match sur les 2 fichiers.
build_result()pur = l'acceptance est vérifiable sans réseau ; aucun champ requis à l'émission (contrat inchangé).
L'honnêteté du tableau d'acceptance (2 lignes prouvées par test unitaire, non live, et dites comme telles) est appréciée.
|
Grain tag obligatoire (#10045, bloquant).
Pour passer ce gate, le body doit porter en tete une ligne de la forme : Le |
|
[ADJOINT PREFLIGHT] [Tell c.81 - BLOCKED-WITH-SUBSTANCE] Always-on guards failure + PR gate FAIL (rate-limit). Cycle 15 hub secretaire. |
# Conflicts: # scripts/tests/test_check_adjoint_prevalidation.py
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
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 |
|
[ADJOINT PREFLIGHT] |
|
[ADJOINT PREFLIGHT] Note : merge e100d40 résolu à la main sur scripts/tests/test_check_adjoint_prevalidation.py ; la résolution est l'union des deux blocs de tests (seuls les marqueurs retirés, diff auto-merge→tête = 1+/3−). Arbre fusionné avec origin/main : pytest 72 passed ; le gate fusionné, rejoué sur #17497, rend blocking_fields ['checks'] et errors []. La review Hermes 5271616602 date de deae559 : elle précède cette résolution. |
|
[ADJOINT PREFLIGHT] Note : merge e100d40 résolu à la main sur scripts/tests/test_check_adjoint_prevalidation.py ; la résolution est l'union des deux blocs de tests (seuls les marqueurs retirés, diff auto-merge→tête = 1+/3−). Arbre fusionné avec origin/main : pytest 72 passed ; le gate fusionné, rejoué sur #17497, rend blocking_fields ['checks'] et errors []. La review Hermes 5271616602 date de deae559 : elle précède cette résolution. Le dossier 5794400580 juste au-dessus porte une valeur b0 invalide (refusé par le gate) : celui-ci le remplace. |
Grain: MED/guard -- lane myia-po-2026:CoursIA -- prev: MED/docs #17289
Quoi: sur
exit 3, le dossier est intact — c'est ce que le code signifie — doncerrorsvaut[]par construction. La règle attachée à ce code demande pourtant de « dispatcher depuis le motif attesté par le dossier », et le gate ne le publiait nulle part : la seule voie était de re-télécharger les commentaires et de re-parser à la main les champs que le gate venait de lire.Preuve: 58 tests passent ; 3 mutations → 3 fois le BON test tombe, restauration byte-identique vérifiée par sha256 ; sur les PRs live nommées par l'acceptance,
blocking_fieldsdiscrimine les motifs (["checks"]vs["b0"]).Perimetre: 2 fichiers —
scripts/check_adjoint_prevalidation.py(+104/−17),scripts/tests/test_check_adjoint_prevalidation.py(+130). Aucun notebook, aucun workflow, aucun.github/. Le contrat de dossier est inchangé côté émission.Closes #17290Le défaut, tel qu'il se lit dans le code
verdict == BLOCKED⇒return dossier.fields.get("verdict", ""), []: la liste d'erreurs est vide parce que le dossier est intègre. Le seul champ qui aurait pu porter le motif était donc structurellement vide, et leresultémis ne portait quepr,head,ready,verdict,errors.L'organe se contredisait lui-même dans sa propre sortie :
La phrase désignait un motif que la commande ne rendait pas.
Ce que le gate publie maintenant
BLOCKING_FIELDSvalidate_dossiercontraint quand le dossier clame READYblocking_fields(dossier)dossier_payload(dossier)author,created_at,comment_index)build_result()evaluate_with_dossier()evaluate()garde sa forme à 2 éléments — aucun appelant ne bouge sous luiAucun champ nouveau n'est requis à l'émission : on publie ce que
parse_dossierparsait déjà. Le contrat de dossier est inchangé.Le cas que je refuse de maquiller
Un dossier
BLOCKEDpeut déclarer les 4 champs au vert :validate_dossierne les contraint que sousverdict: READY, donc un dossier bloqué honnête peut porter sa raison dans sa prose.blocking_fieldsrend alors[]— et c'est la vraie réponse. Inventer un champ pour combler le silence fabriquerait précisément le motif que cette issue existe pour publier. Le cas est pinné partest_a_blocked_dossier_can_name_no_blocking_field.Sur les PRs live (lecture seule, aucune surface ouverte)
Les deux premiers sont exactement les contrôles positifs nommés par l'acceptance, et ils discriminent : un
checksmort part à l'adjoint pour un--template, unb0réel part à la lane porteuse pour une phrase de levée. Sans motif exposé, ces deux dispatches étaient indiscernables.Sortie humaine sur le même rc=3 :
Falsification (une épingle qui passe toujours est un test vide)
Sauvegarde par
cpdans un arbre jetable — jamaisgit checkout --, qui restaure depuis l'INDEX.blocking_fieldsretiré du résultat émistest_blocked_result_publishes_the_dossier_and_its_blockerdossierpublié même sur dossier refusétest_a_refused_dossier_is_not_published_at_allblocking_fieldsnomme les 4 champs en permanencetest_blocking_fields_name_checks_on_a_checks_blocked_dossiersha256de la source identique avant/après les 3 mutations.Acceptance
--jsonsur rc=3 exposedossier+blocking_fieldsnon videtest_blocked_result_publishes_the_dossier_and_its_blocker--jsonsur rc=0 expose le même bloc,blocking_fields: []test_ready_result_publishes_the_dossier_with_no_blocker(unitaire : aucune PR live à dossier READY trouvée au moment du commit)["checks"], #16352 →["b0"]dossiertest_a_refused_dossier_is_not_published_at_all(mutation B) ; variante « dossier absent » vérifiée live sur #17285dossier_payload=dict(dossier.fields)+ provenance ; contrat inchangéscripts/tests/test_check_adjoint_prevalidation.pyDeux lignes de ce tableau sont prouvées par test unitaire et non par une PR live (rc=0 : aucune PR à dossier READY disponible à l'instant du commit). Je le dis plutôt que de laisser croire à six preuves live.
Hors scope, respecté
Le contenu du contrat de dossier (aucun champ ajouté côté émission) ;
check_unaddressed_nits.py; la péremption deb0(#17271).🤖 Generated with Claude Code