Repository navigation
Le sweep exempte cancelled sur un constituant, le gate le fait echouer -- la reparation re-selectionne ce qu'elle ne peut pas reparer #15775
Description
Activity
[CLAIMED] #15775 — myia-po-2023:CoursIA — 2026-09-12T16:22Z -- paths: .github/workflows/pr-gate-stale-sweep.yml, scripts/tests/test_pr_gate_sweep_select.py (le selecteur porte deja (run_id, name) par constituant : cible de rerun emise par le selecteur ; test faux-avant/vrai-apres + controle negatif failure ; premisse OTHERS_NOT_BLOCKING reecrite sur place)
[DELIVERED] myia-po-2023:CoursIA — 2026-09-12T16:52Z — PR #15785 (MED/tooling, prev #15784) : le sélecteur émet les run ids des constituants
cancelleden 5e champ conditionnel, l'action relaie ces runs (2 passes : constituant puis gate — le re-agrégateur event-driven cité dans l'issue est retiré depuis #11860, correction documentée dans le corps de PR). 4/4 acceptance, +5 tests dont 2 falsifications rouges sur HEAD, 370 tests verts, divergence OTHERS_NOT_BLOCKING/CONCLUSION_BAD écrite sur place. Closes #15775 via la PR.Mesure de l'ampleur — 33 % de la file de merge, pas un cas isolé
Mesuré le 2026-09-12T17:35Z sur les 66 PRs ouvertes du dépôt, une par une (
gh pr view <N> --json statusCheckRollup, pas d'agrégat GraphQL — il rend504sur 200 PRs) :Classe PRs Part PR gateFAIL dont la seule cause est un checkCANCELLED22 33 % Vrai rouge (un constituant conclut FAILURE)21 32 % Aucun rouge 18 27 % PR gaterouge sans cause visible dans le rollup5 8 % Les 22 : #15423 #15440 #15452 #15514 #15531 #15609 #15657 #15660 #15690 #15706 #15737 #15759 #15761 #15764 #15765 #15771 #15779 #15782 #15785 #15786 #15795 #15796.
Ce que la mesure ajoute à l'acceptance de cette issue : l'asymétrie n'est pas une gêne ponctuelle, c'est le premier poste de blocage de la file, à égalité avec les vrais rouges. Un tiers des candidates ouvertes n'attendent aucun travail de lane — elles attendent une relance.
Pourquoi le balayage horaire ne les rattrape pas.
pr-gate-stale-sweep.ymlsélectionne « une jambePR gaterouge alors que tout le reste est vert ». Une PR bloquée ici a un constituantCANCELLED: le reste n'est pas vert, la PR n'est pas sélectionnée, et le rouge ne se lève jamais tout seul. Le balayage et le gate ne lisent pasCANCELLEDde la même façon — c'est exactement la dissymétrie que cette issue nomme, et c'est elle qui rend l'état absorbant.Chaîne observée en aval (cas #15609). La PR qui livre
ICT-22b-CausalInterventionEngine.ipynbest bloquée parICT tests/ (56) = CANCELLED→[pr-gate] FAIL -- failing checks: ICT tests/ (56). Or ce notebook est référencé depuismain(MyIA.AI.Notebooks/IIT/ICT-Series/README.md:214, posé par #15649/#15752) sans exister :check-linksest donc rouge surmain, et 7 PRs ouvertes héritent de ce rouge. Un artefactCANCELLEDbloque ainsi la PR qui réparerait un rouge affectant sept autres PRs.Geste immédiat (fait) : 28 runs relancés à la main sur les 22 PRs (
gh run rerun), 28/28 acceptés. C'est un pansement, pas le correctif : il se re-pose à chaque annulation.Ce que la mesure ne dit pas : les 5 « sans cause visible » ne sont pas caractérisées ici — le rollup ne montre pas leur constituant fautif, elles demandent une lecture de log individuelle. Et la part
CANCELLEDest un instantané : elle dépend du taux d'annulation (concurrence de workflows, pushes rapprochés), qui n'est pas mesuré ici.- added a commit that references this issue
on Sep 13, 2026 - added a commit that references this issue
on Sep 14, 2026 - added a commit that references this issue
on Sep 14, 2026 - added a commit that references this issue
on Oct 5, 2026
Le defaut
Deux organes sont chacun deliberement corrects, et jointement bloquants sur la classe
cancelled.Le sweep exempte
cancelledquand il juge l'eligibilite (.github/workflows/pr-gate-stale-sweep.yml, l.413) :Son raisonnement est ecrit juste au-dessus : « le sweep ne merge rien : il RELANCE le gate, qui re-lit l'etat live et conclura FAIL si un constituant est reellement rouge ». La premisse implicite est qu'un constituant
cancelledn'est pas « reellement rouge ».Le gate ne partage pas cette premisse (
scripts/pr_gate.py, l.134-141) :et sa docstring (l.71) l'enonce comme regle : «
cancelledsur le run le plus recent fait echouer ».La consequence, mesuree
Le sweep selectionne donc, a chaque passe horaire, exactement les PRs que le gate est garanti de refuser — et depense un runner a le prouver.
Mesure du 2026-09-12, balayage de 13:27Z :
failureScripts Tests (CPU)=cancelledfailureScripts Tests (CPU)=cancelledLes deux PRs sont dans cet etat depuis plusieurs passes. L'organe de reparation ne peut pas reparer cette classe ; il la re-selectionne.
Amplificateur : d'ou viennent les
cancelledUn job tue au plafond
timeout-minutesrendcancelled, pastimed_out. Mesure surICT tests/ (56)(.github/workflows/ict-tests.yml,timeout-minutes: 30l.76) : 4 runs consecutifs tues au plafond, a 20-29 s d'ecart les uns des autres — la jambe soeurict/tests/ (42 package)conclut en 11.4-15.5 min sur le meme workflow. Chaque tour consomme 30 min de runner sur le pool le plus contendu (coursia-ephemeral/coursia-linuxmesure 12 online / 12 busy a 13:24Z).La boucle se referme : plafond trop bas ->
cancelled-> gate rouge -> PR eligible au sweep -> gate re-lance -> re-rouge -> re-eligible au balayage suivant. Voir #15761 / #15770 pour le volet plafond.Le geste qui repare
Ce qu'il faut relancer est le constituant
cancelled, pas l'agregateur. Relancer le gate re-lit un constituant qui n'a pas bouge ; relancer le constituant produit une nouvelle conclusion, etpr-gate-rerun.yml(workflow_run) re-agrege ensuite tout seul.Verification manuelle du 2026-09-12 :
gh run rerun 34692284675(#15452) etgh run rerun 34691095324(#15748) — les deux passent enqueued, la ou six re-lancements de gate n'avaient rien change.Acceptance
cancelled, relance ce constituant (et laissepr-gate-rerun.ymlre-agreger) au lieu de relancer le gate.cancelled+ reste vert -> le sweep emet un rerun de constituant, pas de gate.failure(pascancelled) -> comportement actuel inchange, pour ne pas transformer le sweep en re-lanceur universel de rouges reels.OTHERS_NOT_BLOCKINGest corrigee ou documentee comme deliberement divergente deCONCLUSION_BAD, avec la raison ecrite au meme endroit.Le plafond
ict-tests.ymlest traite separement (#15761) : il tarit la source, celle-ci ferme la boucle.