Skip to content

fix(gate,#17791): exempt hors-flotte PRs from the carrying-lane refusal (claude/* + Hors flotte) - #17798

Merged
myia-ai-01 merged 3 commits into
mainfrom
fix/17791-gate-hors-flotte
Sep 26, 2026
Merged

myia-ai-01 merged 3 commits into
mainfrom
fix/17791-gate-hors-flotte

Conversation

@jsboige

@jsboige jsboige commented Sep 25, 2026

Copy link
Copy Markdown
Owner

Grain: MED/guard — lane myia-po-2024:CoursIA — prev: LIGHT/docs #17795

Suit le spec de l'issue point par point. C'est la suite directe de #17713/#17726 : l'exemption hors flotte existait côté CI (tag_required), pas côté gate de merge.

Le défaut

carrying_lane() rend None sans tag Grain: ; validate_dossier transforme ce None en refus. Juste pour une PR de flotte non taguée (sinon une lane prévaliderait sa propre PR). Pour une PR hors flotte (#17691 : branche claude/affectionate-mccarthy-6dvuea, marqueur « Hors flotte »), c'est une impasse structurelle : CLAUDE.md (« À qui ce fichier s'adresse ») dispense ces PRs du tag, aucune lane de la flotte ne les porte, donc toute lane qualifiante est tierce — mais le gate ne pouvait pas le voir.

Le fix (scripts/check_adjoint_prevalidation.py, +84 lignes avec tests)

  1. is_out_of_fleet(snapshot) — les DEUX conditions, miroir de variation_tag_required.py (fix(ci): le garde Grain-tag bloque les PRs hors flotte (sessions cloud du mainteneur) que CLAUDE.md exempte #17713/fix(ci,#17713): exempter les PRs claude/* + Hors flotte du garde Grain-tag #17715) : headRefName commence par claude/ et le body porte « Hors flotte ». L'une sans l'autre n'exempte rien.
  2. validate_dossier : une PR hors flotte n'a aucune lane porteuse — le bloc carrier (refus « carrying lane cannot be established » et refus d'auto-attestation) est sauté. Le snapshot capture déjà headRefName (l.1119).
  3. Message du gate : la sortie texte nomme l'exemption (« hors-flotte PR: no fleet lane carries it, any qualifying lane is third-party ») et le --json porte out_of_fleet: bool.

Tests (4 nouveaux, miroir de l'acceptance 3)

Cas Attendu Mesuré
claude/* + marqueur + dossier lane qualifiante accepté ✅ READY
claude/* sans marqueur refus inchangé ✅ carrying lane cannot be established
branche de flotte + marqueur (recopié) refus inchangé ✅ carrying lane cannot be established
PR de flotte taguée, dossier de la lane porteuse self-attestation refusée intacte ✅

Suite complète : 95 passed (test_check_adjoint_prevalidation.py).

Contrôle positif réel (acceptance 4)

$ python scripts/check_adjoint_prevalidation.py 17691
READY -- PR #17691 prevalidated by adjoint at 050b65003169c88b73e35560643ffa850a1b5719
  note: hors-flotte PR (claude/* + 'Hors flotte'): no fleet lane carries it, any qualifying lane is third-party (#17791)
RC=0

--json : ready: true, out_of_fleet: true, dossier myia-po-2023:CoursIA (existant, non re-tamponné) accepté à la tête 050b650031.

merge_ready.py — vérifié, aucun changement

Il invoque le gate en CLI (l.435 : check_adjoint_prevalidation.py <PR> --json) et lit rc == 0 + ready: true — le contrat d'interface ne bouge pas (rc 0-3 inchangés, clé out_of_fleet additive). Ses 41 tests passent sur la branche.

Closes #17791

🤖 Generated with Claude Code

A maintainer cloud session (claude/* branch + « Hors flotte » body
marker) carries no fleet lane, so validate_dossier's third-party check
had no carrier to compare against and refused every dossier by
construction -- the impasse measured on #17691. Both conditions mirror
the tag_required exemption (#17713/#17715, variation_tag_required.py);
either alone changes nothing. The gate names the exemption in its
output and json (out_of_fleet), merge_ready consumes rc+ready and needs
no change (verified: 41 tests pass).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) label Sep 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2024:CoursIA a deja consomme son budget LIGHT du jour (axe genre G-VAR-2/3 (light-genre, quel que soit le tier declare) : #17726 (MED/guard, merge a 2026-09-25T09:17:35Z)).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour,
toutes categories LIGHT confondues
(guard, doc, refs, ... partagent un seul budget) :
c'est un RATIO, pas un plafond plat. La decision de merge reste au coordinateur.

@github-actions github-actions Bot added the trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740) label Sep 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Trivial-diff advisory (#15740, non bloquant).
genre guard dans la famille META (docs/guard/ledger/readme/test) + diff de 84 lignes changees (<= 100) + aucune exception ecrite dans le body : le litmus de la trivialite (une douzaine d'instances scannees a la suite) est credible. Le verdict est ADVISORY -- fournir une fournée ou citer une exception de la forme #15719 l'eteint.
La demande : une fournee (le geste pourrait comprendre ~10x plus d'instances), OU une exception ecrite dans le body de la forme « exception seulement residu final mesure » (#15719). Editer le body re-deroule cet organe et retire le label.

@github-actions

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).

@github-actions

github-actions Bot commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #17798 (fix(gate,#17791): exempt hors-flotte PRs from the carrying-lane refusal (claude/* + Hors flotte)) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@github-actions github-actions Bot added variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory) variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) labels Sep 25, 2026
@github-actions

Copy link
Copy Markdown
Contributor

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

  • TIER-INFLATION : declared LIGHT << effective LIGHT-genre (tally : declared=0 genre=4 cap=3)
  • GENRE-RUN : run consecutif d'un genre LIGHT (voir signals.runs dans le log du job)
  • CAP-EXCEEDED-BY-GENRE : light_genre > cap partage G-VAR-2 (tally : declared=0 genre=4 cap=3)

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.

@jsboige

jsboige commented Sep 25, 2026

Copy link
Copy Markdown
Owner Author

Rouge Scripts Tests (CPU) — hérité de main, reproduit firsthand, fix déjà en vol.

Le seul échec réel est scripts/tests/test_check_arxiv_attributions.py::test_real_registry_lives_against_main_repo (la jambe PR gate n'est qu'un agrégateur : son log nomme exactement ce test). La PR ne touche que scripts/check_adjoint_prevalidation.py et son test — aucun des artefacts en cause.

Preuve qu'il est hérité de la base, et non introduit ici :

Mesure Commande Résultat
Au head de la PR (a280b5fa386, worktree CoursIA-17791) pytest scripts/tests/test_check_arxiv_attributions.py::test_real_registry_lives_against_main_repo 1 failed — PASS: 12, FAIL: 1
Sur origin/main seul, arbre propre (1740a4099d3, worktree détaché jetable) idem 1 failed — PASS: 12, FAIL: 1, message identique

L'entrée fautive est {'arxiv_id': '1706.00883', 'notebook': 'MyIA.AI.Notebooks/IIT/ICT-Series/ICT-37-FLens-BeliefState.ipynb', 'cell_index': 17}, et la cause est nommée par le fix en vol : #17835 (fix(arxiv,#17622): registre — cell_index 17 -> 18 du renvoi References, décalage causé par #17807) — hors du périmètre de cette PR et hors de cette lane.

Conduite : je ne touche pas au registre d'autrui. Dès que #17835 est mergée, je fusionne origin/main dans cette branche pour faire disparaître le rouge à la nouvelle tête, puis je redemande la review. Rien d'autre n'est en attente de mon côté : aucune réserve, aucun nit, aucun thread inline sur cette PR.

@jsboige

jsboige commented Sep 25, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 17798
head: 2fd85d0
complete: true
body: read
comments-reviewed: 6
reviews-reviewed: 0
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 97d7c6942090cbbaa831691d68e4a3792370f36c661201060cf1744a7391575d
diff-files: 2
diff-additions: 84
diff-deletions: 0
checks: latest-wins-green
b0: clear
scope: pass
domain: not-applicable
verdict: READY
[/ADJOINT PREFLIGHT]

NARRATIF — mesures de l'attestation (tete 2fd85d02eae6)

Porteur : myia-po-2024:CoursIA (tag Grain: MED/guard) — lane tierce, attestation valide.

1. checks = latest-wins-green : check_run_state.py --pr 17798 plie 19 jambes / 19 noms, latest_reds [], residual_reds [], aucune jambe a plusieurs tentatives (legs_per_name vide — pas de rouge supersede possible ici). Controle explicite de la suite nommee dans le bloc « A RELIRE » : Scripts Tests (CPU) est PRESENTE et VERTE a cette tete (success), et PR gate est verte. Le rouge heredite de main decrit par le commentaire du 17:46:53Z (test_check_arxiv_attributions.py::test_real_registry_lives_against_main_repo) n'existe donc plus a cette tete : la jambe re-evalue le merge ref (base + tete), et le correctif de base a atterri depuis — le rouge s'est eteint sans aucun geste de la lane. C'est la lecture la plus utile pour ai-01 : rien a reparer ici.

2. b0 = clear : check_unaddressed_nits.py 17798 -> rc=0, « aucun nit non leve parmi les commentaires evalues ». Le seul commentaire NON EVALUE (jsboige, 17:46:53Z) est celui qui documente le rouge heredite, avec sa reproduction et son fix en vol : il n'adresse aucune demande et sa substance est mesuree au point 1 (resolue).

3. scope = pass : 2 fichiers, +84 / -0, check_pr_perimeter.py -> VERDICT OK ; aucun workflow CI touche, aucun mouvement de baseline ni de seuil.

  • scripts/check_adjoint_prevalidation.py (+28)
  • scripts/tests/test_check_adjoint_prevalidation.py (+56)

4. domain = not-applicable : un garde CI et son test — ni carnet, ni preuve Lean, ni metrique ML, ni backtest QC. Aucun crible de contenu n'est applicable.

Note que je dois a ai-01, et qui n'est PAS un blocage : cette PR modifie scripts/check_adjoint_prevalidation.py, l'instrument meme qui valide un dossier comme celui-ci. Mon attestation porte sur les checks, le B.0, le perimetre et le domaine de la tete ; elle ne porte pas sur la justesse du changement de garde. C'est la lecture d'ai-01, et c'est precisement le cas ou elle est la plus necessaire : ici l'attestant et l'artefact partagent le meme organe. Le diff est court (+28) et le test qui l'accompagne (+56) est le temoin a lire.

Absence de suite, justifiee par les declencheurs (et non pas constatee) : Twin parity n'apparait pas dans les 19 noms — cette PR ne touche aucun chemin de carnet ni de registre twin-pairs, donc le workflow ne la declenche pas. Une absence de jambe n'est un angle mort que si son paths: couvre le diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trivial-diff-advisory Diff trivial : grain META mecanique sans fournee ni exception ecrite (#15740) variation-genre-cap-exceeded light_genre > cap partage G-VAR-2 (#10020, advisory) variation-genre-run >= 2 grains consecutifs du meme genre LIGHT pour la lane (#10020, advisory) variation-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint) variation-tier-inflation declared LIGHT << effective LIGHT-genre (#10020, advisory)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(gate): le gate de prevalidation ne sait pas reconnaitre une PR hors flotte (claude/* + Hors flotte) -- impasse structurelle

2 participants