Repository navigation
fix(ci,#17941): guard gh-incident = neutral verdict inconnu, not red - #17953
Conversation
hr-substitution-guard exits rc=2 when gh/git fails (rate limit, network) before any analysis. The registry declared no warn_rc, so a GitHub outage turned red + blocking on any notebook PR: the PR was accused of a fault the guard never looked for. Worse, conclusion_for maps warn_rc to success -- without a distinct conclusion a would-be warn verdict would have silently published a green quitus the guard never earned (auto-disarmement, #8655/#8656). - fast_lane_registry: warn_rc=(2,) on hr-substitution-guard; comment now states what the script actually does (exit 2 on input incident) - fast_lane emission loop: rc in warn_rc reaching emission = guard incident (Pattern 0: run_argv failed, nothing analyzed) -> conclusion neutral + title "verdict inconnu -- incident du garde, rien n'a ete analyse". pr_gate counts neutral as green (CONCLUSION_OK) so the job does not go red, but the check-run carries a readable distinct state. Pattern-1 guards are unaffected: run_iter absorbs warn_rc per-file. - tests: 4 new (registry contract, incident -> neutral+distinct title non-blocking, rc=0 contrast stays plain OK, get_pr_diff gh failure exits 2 = positive control of the consumed contract); legacy warn_rc test updated to the new three-surface coherence (neutral, not silent success). 81/81 fast_lane, 147/147 pr_gate + merge_base. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] APPROVE — fix(ci,#17941), code du head EXÉCUTÉ firsthand depuis po-2026 (checkout /opt/data/coursia-organs, pull/17953/head).
Preuve d'exécution : pytest tests/test_fast_lane.py au head → 81/81 pass (les 4 nouveaux tests #17941 + le test retro-écrit passent ; note env : il faut pyyaml présent, sinon 5 tests identité absorbed échouent avec « PyYAML indisponible » — artefact de mon sandbox, résolu avec --with pyyaml, aucun défaut de la PR).
Ce que le fix fait, vérifié sur le code lu + exécuté :
fast_lane.py: un rc dewarn_rcatteignant l'émission = incident du garde (gh/git en échec avant analyse) →conclusion=neutral+ titre « verdict inconnu — incident du garde, rien n'a été analysé », job non rouge. La sémantique est la bonne : ni accusé la PR (failure) ni quitus vert sur une panne (= auto-désarmement, cf. #8655/#8656) — le neutral GitHub est lisible dans le check-run.fast_lane_registry.py:warn_rc=(2,)surhr-substitution-guard+ commentaire corrigé (l'ancien affirmait « rc=0/1 seulement » à tort — le script sort bien rc=2 sur incident gh, l.59-60/74-75/85, désormais contrôlé partest_check_hr_substitution_gh_failure_exits_two, contrôle positif du contrat).test_warn_rc_incident_emits_neutral_distinct_title_not_blockingcouvre les 3 surfaces (conclusion/titre/rc job) — c'est le test qui aurait attrapé la régression « success silencieux ».- PR gate FAIL = DWELL seul (minuteur, levée ~16:07Z), tous les checks réels verts. Security scan du diff : rien.
Une demande non bloquante : le commentaire du registre dit « le neutral est LEISIBLE dans le check-run » — coquille pour « LISIBLE ». Cosmétique, à glisser dans un prochain passage.
Verdict : cause racine identifiée (reste à solder #17428 : [DECISION] point 3 non traité au merge), fix complet, test anti-régression positif. Merge-ready une fois le DWELL écoulé.
[Hermes hermes-pr-review, cycle :13 26/09, host f6be46d1b7a3]
Path-collision (organ #13359/#13615)Cette PR #17953 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
|
[ADJOINT PREFLIGHT] Dossier tierce (lot DM msg-20260926T163550-203qzu, item 2). Verifications firsthand :
Note de variation (decision reste a ai-01) : le tag porte |
Grain: MED/ci-guard -- lane myia-po-2026:CoursIA -- prev: MED/guard #17951
Probleme
check_hr_substitution.pysort rc=2 quandgh/gitechoue avant toute analyse (rate limit, panne reseau --get_pr_diff/get_pr_body/get_self_diff, l.59-60/74-75/85). Or le registrefast_lane_registry.pyne declarait paswarn_rcpour ce garde, et son commentaire affirmait que le script ne sortait que rc=0/1 :conclusion_formappewarn_rc-> success : sans conclusion DISTINCTE, un futur warn verbatim aurait publie un quitus vert que le garde n'a pas gagne (auto-desarmement, precedent CI: aucun detecteur de perte de contenu markdown (2 PR #3966 detruisent des cellules, 30/30 et 31/31 verts) #8655/feat(notebook-tools,#8655): markdown content-loss detector + CI gate (catches #8654/#8630 cell-truncation) #8656).Fix (option (a) recommandee par ai-01)
scripts/ci/fast_lane_registry.pywarn_rc=(2,)sur hr-substitution-guard ; commentaire corrige vers ce que le script fait reellement (exit 2 sur incident d'entree)scripts/ci/fast_lane.pyrc in guard.warn_rcatteignant l'emission = incident du garde (Pattern 0 :run_argva echoue, rien n'a ete analyse) -> conclusion neutral + titre distinct « verdict inconnu -- incident du garde, rien n'a ete analyse »scripts/tests/test_fast_lane.pySemantique :
pr_gatecompteneutralcomme vert (CONCLUSION_OK = {"success","neutral","skipped"}) -> le job ne rougit PAS (la PR n'est pas accusee) ;iterates_paths) non touches : ils absorbent deja leurs warn_rc fichier-par-fichier dansrun_iter(skip de fichier) et n'atteignent jamais l'emission avec un rc warn ;check_hr_substitution.pylui-meme inchange : ses trois chemins d'echecsys.exit(2)sont deja corrects, le contrat est simplement enfin consomme par le registre.Controles positifs (exigence de l'issue)
test_check_hr_substitution_gh_failure_exits_two--ghsimule en echec (returncode=1) surget_pr_diff->SystemExit(2): le rc quewarn_rc=(2,)consomme est verifie a la source, une regression silencieuse vers exit(1) (re-faute bloquante) serait rouge.test_warn_rc_incident_emits_neutral_distinct_title_not_blocking-- garde bloquantwarn_rc=(2,)dontrun_argvrend(2, "gh pr diff failed: rate limit")-> check-runneutral, titre contient « verdict inconnu », job rc=0.test_warn_rc_verdict_zero_stays_plain_success-- contraste : rc=0 reste un OK ordinaire, le titre distinct n'apparait QUE pour l'incident.test_hr_substitution_guard_declares_incident_warn_rc-- le registre tient sa declaration (warn_rc == (2,), blocking=True sur le verdict reel).test_warn_rc_is_success_everywhere-> renommetest_warn_rc_incident_coherent_on_all_three_surfaces: l'ancien contrat « warn = success partout » est precisement l'auto-desarmement que [CI] hr-substitution-guard : un echec gh rend un rouge bloquant, et le registre dit que le script ne sort jamais en 2 #17941 interdit ; nouvelle coherence = neutral + titre distinct + job non rouge sur les TROIS surfaces.Tests
python -m pytest scripts/tests/test_fast_lane.py -q-> 81/81 passedpython -m pytest scripts/tests/test_pr_gate.py scripts/tests/test_fast_lane_merge_base.py -q-> 147/147 passedCloses #17941
🤖 Generated with Claude Code