You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
check_exec_ratchet : sortir en « instrument indisponible » à l'épuisement EAGAIN au lieu d'un faux vert fail-open #16164
Dans les deux cas le CLI imprime changed notebooks : 0 et sort en succès. Le second cas est un faux vert : un garde annonce « rien à signaler » sur un arbre qu'il n'a jamais lu. C'est exactement la classe de défaut diagnostiquée sur #16125.
#16157 a corrigé la cause immédiate (reprise bornée EAGAIN : 3 tentatives, backoff 0,05/0,15 s) en conservant les sémantiques d'origine des deux côtés — ce qui était le bon choix pour un diff minimal. Mais la reprise ne fait que repousser le faux vert : au-delà d'environ 0,2 s de contention soutenue, l'épuisement retombe sur le même return None silencieux. Le canon (check_kernel_suffix_canon.py) est fail-closed sur le même épuisement, donc les deux gardes divergent toujours sur le cas limite.
Correctif proposé
Un code de sortie distinct pour « instrument indisponible » (par ex. exit 2), au lieu de confondre l'échec de mesure avec une mesure nulle :
le CLI imprime un message qui nomme l'échec de spawn (pas changed notebooks : 0) ;
le code de sortie est distinguable de « 0 changements » et de « régression détectée » ;
le contrat lenient actuel (None = pas de verdict) peut être préservé côté appelant, mais devient explicite au lieu d'être déduit d'un 0 ambigu.
Critères d'acceptation
Un échec de spawn git après épuisement des tentatives produit un code de sortie et un message distincts de « 0 changements ».
Un test couvre le cas « épuisement → instrument indisponible » et vérifie qu'il n'est pas confondu avec « 0 changements ».
Les appelants existants du contrat lenient sont recensés, et leur comportement sur le nouveau code est décidé explicitement (pas hérité par accident).
La décision « fail-open ou fail-closed sur instrument indisponible » est tranchée et écrite — les deux gardes doivent converger sur ce point.
Hors périmètre
La contention EAGAIN elle-même (pourquoi le spawn échoue sous -n 4) : #16157 la traite par reprise bornée, ce n'est pas remis en question ici.
Claim levé (myia-po-2023) : le critère « à l'épuisement des tentatives » présuppose la reprise EAGAIN de #16157, PR encore OPEN (rouge sur un organe, non mergée). Stacker dessus = piège #16194 (PR empilée perd les gardes always-on) ; réimplémenter la reprise ici = dupliquer le travail d'une autre lane et créer un conflit garanti sur git() des deux gardes. Re-claim naturel après merge de #16157. — 2026-09-14T21:58Z
The four acceptance criteria are now verified on PR #16255 head 27c4e79cf6e6663e0187f728f4663a1e61a9d96a:
exhausted git spawn retries raise InstrumentUnavailable; the CLI exits 2 with an explicit message and never prints changed notebooks : 0;
regression tests cover exhausted EAGAIN, non-transient OSError, the hidden git show path, and the distinct CLI exit;
the caller census is explicit: the workflow fails closed on exit 2, internal None retains only the “git answered negatively” meaning, and there are no external Python importers outside tests;
the fail-closed decision converges with the kernel-suffix canon.
Validation: exact-head review APPROVED; latest-by-name CI checks green; closingIssuesReferences contains only #16164. The issue body checklist is updated before merge, as required by the closure ratchet. Closure itself will be verified at least five minutes after the eventual merge before being reported.
Fermeture autorisée par le user le 2026-09-17 (relais du registre coordinateur ai-01, « OK pour toutes tes recos »).
L'autorisation porte sur la fermeture de cette issue une fois la PR #16255 mergée (portes techniques satisfaites : current main, checks, approval exact-head, merge vérifié, bloc Evidence, relecture ≥ 5 min après fermeture). Q16 ne porte que la fermeture, pas le merge de la PR.
La PR #16255 a été mergée exact-head le 2026-09-17T18:22:43Z, squash cffd4556021b2af89e7fcc9b17ea02d186a175f8. Son body porte See #16164, pas Closes, donc le merge ne ferme pas cette issue user-originated.
Critères vérifiés firsthand :
git() délègue la reprise EAGAIN bornée à fork_retry.run_with_fork_retry ;
un échec de spawn épuisé/non transitoire lève InstrumentUnavailable, au lieu de rendre une fausse mesure vide ;
le CLI sort 2 avec un message explicite et ne publie jamais changed notebooks : 0 dans ce cas ;
le chemin masqué git show échoue fermé au lieu de classer un notebook de base comme ABSENT ;
tests ciblés et checks requis verts au head exact ;
class InstrumentUnavailable vérifiée sur origin/main après merge.
Cette Evidence documente la livraison technique. Elle ne ferme pas l’issue et ne remplace pas l’autorisation user directe encore attendue pour la fermeture manuelle.
Fermeture sur autorisation user directe (2026-09-18), après vérification adverse indépendante.
Livré par #16255 (squash cffd455602, ancêtre de origin/main = fc8da0912e).
Critère
Preuve re-mesurée sur origin/main
Épuisement du spawn → code et message distincts de « 0 changements »
class InstrumentUnavailable l.47, levée dans git() l.73 ; main() rend sur stderr « instrument indisponible… ne pas lire ceci comme « 0 changements » » l.174 puis sys.exit(2) l.176 — 0/1/2 séparés. Preuve live : CLI du blob main exécutée sans git au PATH → EXIT=2, message explicite, et aucun « changed notebooks : 0 » en sortie
Test d'épuisement non confondu avec zéro
test_eagain_epuise_leve_instrument_indisponible, test_autre_oserror_sans_retry (ENOENT), test_verdict_at_base_ne_dit_pas_absent, test_cli_exit_2 (assert "changed notebooks" not in out/err) — 20/20 passed
Appelants du lenient recensés
notebook-exec-sequence-ratchet.yml:88 appelle le CLI sanscontinue-on-error ni always() → l'exit 2 rougit l'étape ; git grep des imports hors tests → 0 résultat. None ne survit plus que sur returncode != 0
Fail-open/fail-closed tranché et écrit
trois endroits : docstring InstrumentUnavailable l.47-58, docstring TestInstrumentIndisponible, section « Décision arbitrée » du body. Convergence vérifiée avec le canon : check_kernel_suffix_canon.py:281-292 fait retry EAGAIN borné puis raise — même fail-closed
Résidu documentaire seul, zéro impact comportemental : scripts/notebook_tools/fork_retry.py:28 (docstring mergée par #16217 le 15/09, donc avant#16255) décrit encore check_exec_ratchet comme fail-open « arbitrage en cours dans #16164 ». Phrase devenue fausse — à rafraîchir au prochain passage sur ce module, ne justifie pas de garder l'issue ouverte.
Activity
myia-po-2023 commentedon Sep 14, 2026
[CLAIMED] #16164 — myia-po-2023:CoursIA 2026-09-14T21:55Z
myia-po-2023 commentedon Sep 14, 2026
Claim levé (myia-po-2023) : le critère « à l'épuisement des tentatives » présuppose la reprise EAGAIN de #16157, PR encore OPEN (rouge sur un organe, non mergée). Stacker dessus = piège #16194 (PR empilée perd les gardes always-on) ; réimplémenter la reprise ici = dupliquer le travail d'une autre lane et créer un conflit garanti sur
git()des deux gardes. Re-claim naturel après merge de #16157. — 2026-09-14T21:58Zjsboige commentedon Sep 14, 2026
[CLAIMED] #16164 — myia-po-2023:CoursIA 2026-09-15T01:26Z. Re-claim naturel : #16157 MERGÉ (22:47Z) — la reprise EAGAIN prérequise est sur main. Plan : exit 2 « instrument indisponible » distinct de « 0 changements », convergence fail-closed écrite avec le canon, appelants du contrat lenient recensés.
fix(nb-tools,#16213): reprise EAGAIN partagee pour les deux derniers …
merge: origin/main (fork_retry #16217) dans la branche #16164
refactor(nb-tools,#16164): ratchet — migrer la reprise EAGAIN vers fo…
myia-ai-01 commentedon Sep 16, 2026
Evidence
The four acceptance criteria are now verified on PR #16255 head
27c4e79cf6e6663e0187f728f4663a1e61a9d96a:gitspawn retries raiseInstrumentUnavailable; the CLI exits 2 with an explicit message and never printschanged notebooks : 0;OSError, the hiddengit showpath, and the distinct CLI exit;Noneretains only the “git answered negatively” meaning, and there are no external Python importers outside tests;Validation: exact-head review APPROVED; latest-by-name CI checks green;
closingIssuesReferencescontains only #16164. The issue body checklist is updated before merge, as required by the closure ratchet. Closure itself will be verified at least five minutes after the eventual merge before being reported.fix(nb-tools,#16213): reprise EAGAIN partagee pour les deux derniers …
myia-ai-01 commentedon Sep 17, 2026
Fermeture autorisée par le user le 2026-09-17 (relais du registre coordinateur ai-01, « OK pour toutes tes recos »).
L'autorisation porte sur la fermeture de cette issue une fois la PR #16255 mergée (portes techniques satisfaites : current main, checks, approval exact-head, merge vérifié, bloc Evidence, relecture ≥ 5 min après fermeture). Q16 ne porte que la fermeture, pas le merge de la PR.
fix(nb-tools,#16164): check_exec_ratchet — exit 2 « instrument indisp…
myia-ai-01 commentedon Sep 17, 2026
Evidence technique — livraison #16255 (issue maintenue OPEN)
La PR #16255 a été mergée exact-head le 2026-09-17T18:22:43Z, squash
cffd4556021b2af89e7fcc9b17ea02d186a175f8. Son body porteSee #16164, pasCloses, donc le merge ne ferme pas cette issue user-originated.Critères vérifiés firsthand :
git()délègue la reprise EAGAIN bornée àfork_retry.run_with_fork_retry;InstrumentUnavailable, au lieu de rendre une fausse mesure vide ;changed notebooks : 0dans ce cas ;git showéchoue fermé au lieu de classer un notebook de base comme ABSENT ;class InstrumentUnavailablevérifiée surorigin/mainaprès merge.Cette Evidence documente la livraison technique. Elle ne ferme pas l’issue et ne remplace pas l’autorisation user directe encore attendue pour la fermeture manuelle.
jsboige commentedon Sep 18, 2026
Fermeture sur autorisation user directe (2026-09-18), après vérification adverse indépendante.
Livré par #16255 (squash
cffd455602, ancêtre deorigin/main=fc8da0912e).origin/mainclass InstrumentUnavailablel.47, levée dansgit()l.73 ;main()rend sur stderr « instrument indisponible… ne pas lire ceci comme « 0 changements » » l.174 puissys.exit(2)l.176 — 0/1/2 séparés. Preuve live : CLI du blob main exécutée sansgitau PATH →EXIT=2, message explicite, et aucun « changed notebooks : 0 » en sortietest_eagain_epuise_leve_instrument_indisponible,test_autre_oserror_sans_retry(ENOENT),test_verdict_at_base_ne_dit_pas_absent,test_cli_exit_2(assert"changed notebooks" not in out/err) — 20/20 passednotebook-exec-sequence-ratchet.yml:88appelle le CLI sanscontinue-on-errornialways()→ l'exit 2 rougit l'étape ;git grepdes imports hors tests → 0 résultat.Nonene survit plus que surreturncode != 0InstrumentUnavailablel.47-58, docstringTestInstrumentIndisponible, section « Décision arbitrée » du body. Convergence vérifiée avec le canon :check_kernel_suffix_canon.py:281-292fait retry EAGAIN borné puisraise— même fail-closedRésidu documentaire seul, zéro impact comportemental :
scripts/notebook_tools/fork_retry.py:28(docstring mergée par #16217 le 15/09, donc avant #16255) décrit encorecheck_exec_ratchetcomme fail-open « arbitrage en cours dans #16164 ». Phrase devenue fausse — à rafraîchir au prochain passage sur ce module, ne justifie pas de garder l'issue ouverte.fix(ci,#18324): la garde de chemins locaux ne rend plus de verdict su…