Skip to content

fix(coordination,#19869): --emit pre-renseigne supersedes/supersedes-why quand BLOCKED anterieur a meme tete - #19892

Merged
myia-ai-01 merged 2 commits into
mainfrom
fix/19869-emit-supersedes
Oct 8, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
fix/19869-emit-supersedes

Conversation

@jsboige

@jsboige jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner

Grain: MED/coordination -- lane myia-ai-01:CoursIA-2 -- prev: MED/coordination #19833 c.261

Fix #19869 : --emit ne produisait aucune occurrence de supersedes / supersedes-why -- un READY sur un BLOCKED anterieur a la meme tete etait poste puis refuse en NO-DOSSIER (cas fondateur #19773). Le gate (mute_contradictions l.1307) etait le seul organe qui mordait, et il mordait apres publication.

Diagnostic (verbatim du ticket #19869)

--emit rend TOUJOURS un dossier sans supersedes (et sans supersedes-why). Le template (render_template) ne les declare pas dans ses fields. Le gate les exige quand un dossier anterieur de la meme tete est verdict: BLOCKED et que le nouveau est READY. Resultat : existing_lane != args.lane exempte la meme lane de son garde anti-double-stamp dans post_dossier.py, le dossier part, et c'est le gate qui dit NO-DOSSIER ensuite. Deux organes distincts, et le seul qui mord est interroge en second.

Correctif

  1. find_previous_blocked_same_head(snapshot, current_head) : miroir de la recherche que mute_contradictions fait au moment du gate. Itere les commentaires en sens inverse, parse chaque comme un Dossier, renvoie le plus recent (position_1_based, Dossier) avec verdict: BLOCKED et head == current_head. Renvoie None si rien ne correspond (tete changee = peremption exact-head).

  2. render_emitted_dossier integre la detection : si le verdict derive est READY et qu'un BLOCKED anterieur existe a la meme tete, deux lignes supersedes: <N> et supersedes-why: auto -- ... sont inserees dans le bloc, avant END. L'auto-texte invite la lane emettrice a remplacer la ligne par la preuve qui a change (le gate n'en exige pas plus).

  3. Le geste est nul quand :

    • le verdict derive est BLOCKED (la direction conservatrice serre, elle ne debloque pas) ;
    • le dossier BLOCKED anterieur est sur une tete differente (perime par exact-head, rien a refuter) ;
    • aucun dossier anterieur n'est un dossier (snapshot vide).

Mesure

  • 8 nouveaux tests pour find_previous_blocked_same_head (4 cas nominaux + 4 cas vides) ;
  • 7 nouveaux tests pour render_emitted_dossier (autofill READY, omission sans BLOCKED, omission verdict BLOCKED, omission tete differente, omission BLOCKED+READY) ;
  • 158/158 tests OK (15 nouveaux + 143 anciens intacts).
  • Round-trip end-to-end : un dossier emis avec --emit sur un snapshot a 2 dossiers (BLOCKED + READY) sort avec supersedes: 2 + supersedes-why: auto -- covers BLOCKED ... et passe mute_contradictions (le gate accepte).

Pourquoi pas de changement de post_dossier.py

Le bug du ticket est dans --emit (sortie), pas dans post_dossier.py (transport). Elargir l'exemption existing_lane != args.lane aurait masque le defaut ; le rendre visible par l'emetteur est le bon endroit : l'organe produit ce que le gate exige, et la lane peut editer l'auto-texte en prose si elle dispose d'un argument plus precis.

Verification (G.1)

Fichiers touches (2, +201/-0) :

  • scripts/check_adjoint_prevalidation.py

  • scripts/tests/test_check_adjoint_prevalidation.py

  • 0 chemin tiers modifie hors perimetre de l'issue

  • Pre-commit hooks (gitleaks, subprocess encoding, etc.) : tous PASS

  • Tests pytest : 158/158 OK (15 nouveaux + 143 anciens)

  • Round-trip : render_emitted_dossier produit le bloc complet + supersedes quand applicable, evaluate accepte le dossier rendu (pas de NO-DOSSIER)

🤖 Generated with Claude Code

@github-actions github-actions Bot added the variation-tag-genre-offlist GENRE hors de l'enumeration variation-protocol §1 label Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-ai-01:CoursIA-2` voit ces signaux actifs sur les mergees du jour (UTC 2026-10-08) :

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 variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 19892
head: 4a4abce
complete: true
body: read
comments-reviewed: 2
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: ce4ffddc54f4743889efbb3155c4fd587b87d5ecf5766bd58dd8c71a66b5ef0f
diff-files: 2
diff-additions: 201
diff-deletions: 0
checks: BLOCKED
b0: clear
scope: pass
domain: pass
verdict: BLOCKED
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19892
organ-rc: 3
[/ADJOINT PREFLIGHT]

…r_emitted_dossier

Les 5 tests c.282 (test_render_emitted_dossier_*) appellent render_emitted_dossier
qui derive_verdict -> probe_b0(snapshot["number"]) -> check_unaddressed_nits.analyse_pr
qui depend d'un `gh` authentifie. En CI Linux, gh n'est pas auth, la commande
echoue avec exit 4, et `B.0 organ could not measure PR #123` remonte comme
RuntimeError -> 5 fail dans Scripts Tests (CPU).

Fix : ajouter `monkeypatch` en parametre et `monkeypatch.setattr(mod, "probe_b0",
lambda pr: {"blocked": False, "blocking": []})` au debut de chaque test, comme
les tests existants test_main_exits_*_when_organ_* le font deja (l.1889, l.1900,
l.1913).

Verification :
- Local : 158/158 tests OK (5 fixes + 153 anciens intacts)
- Le test couvre la MACHINE A ETAT (le rendu du bloc supersedes) -- l'etat derive
  reste explicite, on court-circuite juste la mesure de b0.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2026:CoursIA-3
pr: 19892
head: 4649e7f
complete: true
body: read
comments-reviewed: 3
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 526b0051fd49c84c2319d2b764f5b7e18e12cec2c84ad36b1e078100b5c0251f
diff-files: 2
diff-additions: 216
diff-deletions: 0
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19892
organ-rc: 0
[/ADJOINT PREFLIGHT]

@myia-ai-01
myia-ai-01 merged commit 3da0412 into main Oct 8, 2026
19 of 20 checks passed
jsboige added a commit that referenced this pull request Oct 8, 2026
… unique

Le pre-remplissage de `supersedes`/`supersedes-why` par `--emit` (#19869,
livre par #19892) reposait sur `find_previous_blocked_same_head`, presente
comme le « miroir » de la recherche que `mute_contradictions` effectue au
moment du gate -- deux implementations independantes de la meme regle.

C'est la cause racine decrite par l'issue : « deux organes distincts, et le
seul qui mord est celui qu'on interroge en second ». Une divergence entre
les deux fait que l'emetteur pre-remplit un `supersedes` que le gate refuse,
ce qui reproduit exactement l'aller-retour que le fix devait supprimer.

Extraction d'un coeur unique `covered_blocked_dossier(previous, head)`, que
les deux chemins appellent : le gate passe ses candidats, l'emetteur passe
les dossiers lus dans le fil. Le comportement est inchange (la recherche
reste tete-a-tete, le plus recent BLOCKED gagne).

Controles :
- `test_emitter_and_gate_name_the_same_covered_dossier` : sur une pile a
  deux BLOCKED a la meme tete suivie d'un READY muet, la position rendue par
  l'emetteur et celle que le gate cite dans son refus doivent coincider.
- `test_covered_blocked_dossier_is_the_shared_core` : les deux chemins
  designent le meme Dossier.
- Controle negatif joue : une recherche divergente reintroduite dans le seul
  emetteur fait rougir les deux tests (emetteur 2 vs gate 3), puis restaure.

191 passed (189 avant, 2 ajoutes).

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
myia-ai-01 pushed a commit that referenced this pull request Oct 9, 2026
… unique (#19926)

Le pre-remplissage de `supersedes`/`supersedes-why` par `--emit` (#19869,
livre par #19892) reposait sur `find_previous_blocked_same_head`, presente
comme le « miroir » de la recherche que `mute_contradictions` effectue au
moment du gate -- deux implementations independantes de la meme regle.

C'est la cause racine decrite par l'issue : « deux organes distincts, et le
seul qui mord est celui qu'on interroge en second ». Une divergence entre
les deux fait que l'emetteur pre-remplit un `supersedes` que le gate refuse,
ce qui reproduit exactement l'aller-retour que le fix devait supprimer.

Extraction d'un coeur unique `covered_blocked_dossier(previous, head)`, que
les deux chemins appellent : le gate passe ses candidats, l'emetteur passe
les dossiers lus dans le fil. Le comportement est inchange (la recherche
reste tete-a-tete, le plus recent BLOCKED gagne).

Controles :
- `test_emitter_and_gate_name_the_same_covered_dossier` : sur une pile a
  deux BLOCKED a la meme tete suivie d'un READY muet, la position rendue par
  l'emetteur et celle que le gate cite dans son refus doivent coincider.
- `test_covered_blocked_dossier_is_the_shared_core` : les deux chemins
  designent le meme Dossier.
- Controle negatif joue : une recherche divergente reintroduite dans le seul
  emetteur fait rougir les deux tests (emetteur 2 vs gate 3), puis restaure.

191 passed (189 avant, 2 ajoutes).

Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

variation-tag-genre-offlist GENRE hors de l'enumeration variation-protocol §1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(coordination): --emit ne produit pas supersedes/supersedes-why -- un READY sur un BLOCKED de la meme lane part puis est refuse

2 participants