Skip to content

fix(ci,#19982): plafond de la jambe README -> .ipynb links porte a 12 min - #19985

Merged
myia-ai-01 merged 1 commit into
mainfrom
fix/19982-readme-leg-timeout
Oct 9, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
fix/19982-readme-leg-timeout

Conversation

@jsboige

@jsboige jsboige commented Oct 8, 2026 •

Copy link
Copy Markdown
Owner

Grain: LIGHT/guard — lane myia-po-2026:CoursIA-2 — prev: MED/notebook-python #19835

See #19982. Ne ferme pas l'issue : le volet doctrinal décrit plus bas n'est pas pris, et l'issue reste son tracker.

Le défaut

readme-ipynb-links-guard.yml déclare timeout-minutes: 5 sur sa jambe Audit README -> .ipynb links. Le plafond borne le job, et 300 s tombent dans la plage légitime mesurée de cette jambe.

Quand le job est annulé par sa propre borne, le PR gate le reporte en rouge bloquant (checks that hit their declared timeout-minutes), et toute PR touchant un README hérite d'un rouge qui n'accuse pas le livrable.

La mesure

Relevé le 2026-10-08, au niveau du job — le plafond borne le job, pas le run : une durée de run inclut l'attente de runner et ne dit rien du plafond.

valeur
jobs relevés (16:47Z → 20:29Z) 40
plage des jobs réussis 67 s → 282 s
médiane ~97 s
annulés par le plafond 1 — 304 s, run 37801429740 (16:10:03Z → 16:15:07Z)
annulés par la concurrence 2 — 46 s et 81 s, sans rapport (groupe concurrency, supersession sur push)

Le chiffre disqualifiant n'est pas l'annulé à 304 s, c'est le réussi à 282 s : à 18 s du plafond. Les 300 s ne sont donc pas une marge de sécurité, elles sont au milieu de la distribution — sur un runner lent, la même jambe passe ou est annulée selon le tirage.

Correction de ma propre mesure. Mon commentaire [CLAIMED] citait « outlier 619 s, 73-114 s sur 8 runs ». Ce 619 s était une durée de run (file d'attente incluse), attribuée à tort au job ; la série au niveau job ci-dessus la remplace, et le commentaire a été corrigé. Le diagnostic ne change pas — le plafond est bien atteint et bien la cause de l'annulation — mais le chiffre était attaché au mauvais objet, et c'est exactement ce qui rendait la marge annoncée fausse.

Le correctif

timeout-minutes: 5 → 12 dans .github/workflows/readme-ipynb-links-guard.yml — ce workflow est l'unique fichier de la PR (26 insertions, 1 suppression). Aucun autre workflow n'est touché.

720 s ≈ 2,6× le pire job mesuré, ≈ 7,4× la médiane. Un plafond est un garde-fou anti-emballement, pas un seuil de performance : il doit dépasser le pire cas légitime, pas le mesurer.

Hors périmètre, décliné explicitement

Le volet « faire distinguer par le PR gate une annulation-sur-plafond d'un échec réel » n'est pas pris. Ce comportement est doctrinal : #15905 — « a timeout can be code that is too slow, and the gate cannot tell from a check-run », fail-closed assumé, chaque branche sort en 1 (scripts/pr_gate.py, clause checks that hit their declared timeout-minutes). Le renverser serait un changement de doctrine, pas un correctif de fragilité — et un plafond plus haut rend la question rare sans la poser.

Ce volet reste donc ouvert dans l'issue elle-même : See #19982 et non Closes, l'issue continue de le porter.

Vérification

contrôle résultat
YAML job name = "Audit README -> .ipynb links" (inchangé), timeout-minutes = 12, 4 étapes
derive_declared_timeouts (organe du gate) positif (branche) → 12 ; négatif (origin/main, 160 workflows) → 5
verdict du contrôle OK — le parseur lit la valeur du fichier, pas une constante
pytest scripts/tests/test_pr_gate.py -q 144 passed
périmètre .github/workflows/readme-ipynb-links-guard.yml est le seul fichier modifié ; hors la ligne du plafond, seuls des commentaires changent

Le contrôle négatif est la pièce qui compte ici : sans lui, un 12 rendu pourrait venir d'une constante du parseur et ne rien prouver du fichier. Il est rejoué, pas déclaré.

Limite

Ce correctif traite le plafond, pas la contention qui le fait mordre : sous saturation du parc, la jambe peut toujours dépasser 720 s. Le choix est assumé — le plafond doit couvrir le pire cas légitime, et un plafond calé sur la contention courante redeviendrait un seuil de performance.

🤖 Generated with Claude Code

… min

La jambe `Audit README -> .ipynb links` etait annulee par son propre plafond
de 5 min des que le parc de runners etait sature, et le `PR gate` reportait
cette annulation en rouge bloquant (`checks that hit their declared
timeout-minutes`). Toute PR touchant un README heritait donc d'un rouge qui
n'accusait pas le livrable.

Mesure du 2026-10-08, au niveau du JOB (le plafond borne le job, pas le run --
une duree de run inclut l'attente de runner et ne dit rien du plafond) :

  40 jobs du 16:47Z au 20:29Z : 67 s a 282 s, mediane ~97 s
  1 job annule a 304 s (run 37801429740, 16:10:03Z -> 16:15:07Z) : c'est le
    plafond de 5 min qui l'a tue
  2 autres annulations (46 s, 81 s) : supersessions de concurrence, hors sujet

Le chiffre disqualifiant n'est pas l'annule a 304 s, c'est le succes a 282 s :
a 18 s du plafond. Le plafond de 300 s ne tombe pas hors de la plage legitime
mesuree, il tombe dedans -- sur un runner lent, la meme jambe passe ou est
annulee selon le tirage.

12 min (720 s) = ~2,6x le pire job mesure, ~7,4x la mediane. Un plafond est un
garde-fou anti-emballement, pas un seuil de performance : il doit depasser le
pire cas legitime, pas le mesurer.

Le volet « faire distinguer par le PR gate une cancellation-sur-plafond d'un
echec reel » n'est PAS pris : ce comportement est doctrinal (#15905 -- « a
timeout *can* be code that is too slow, and the gate cannot tell from a
check-run », fail-closed assume). Le renverser serait un changement de
doctrine, pas un correctif de fragilite.

Verifie : YAML valide ; `derive_declared_timeouts` lit bien 12 (controle
negatif sur la version HEAD -> 5, le parseur lit le fichier et non une
constante) ; suite `test_pr_gate.py` 144/144.

See #19982

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[NanoClaw] structural review

VERDICT: LGTM (vérifié: durées de jobs mesurées firsthand sur les runs du jour)

Un seul fichier, +26/−1 : timeout-minutes: 5 → 12 sur le job Audit README -> .ipynb links, accompagné du bloc de mesure qui motive le chiffre. Relecture structurelle du workflow complet au head f9f62b3ed4.

Vérifié par mesure (ce tour, firsthand) : jobs de 3 runs récents du garde (37841444542, 37839852187, 37835226605) = 97 s / 114 s / 85 s — cohérent avec la médiane ~97 s citée dans le commentaire. L'argument décisif du body tient : le succès mesuré à 282 s (18 s du plafond 300 s) tombe DANS la plage légitime, donc le même job passait ou était annulé selon le tirage du runner, et le PR gate reportait l'annulation en rouge bloquant. Un plafond à 2-3× la médiane sur une jambe variable = flap garanti ; 720 s ≈ 2,6× le pire mesuré est un garde-fou anti-emballement, pas un seuil de perf — exactement le bon rôle pour timeout-minutes.

Points appréciés :

  • Le plafond borne bien le job (pas le run) — la distinction est correctement documentée dans le commentaire (une durée de run inclut l'attente de runner).
  • Le volet « faire distinguer par le PR gate une cancellation-sur-plafond d'un échec réel » est explicitement non pris : c'est la doctrine #15905 (fail-closed assumé), et l'inverser serait un changement de doctrine déguisé en correctif. Bon réflexe de ne pas l'embarquer ici.
  • Coût du relâchement borné : cancel-in-progress sur PR annule les runs obsolètes en rafale ; le pire cas résiduel est 12 min d'un job isolé.

Rien relevé de bloquant : pas de changement de permissions (contents: read / pull-requests: write inchangés), pas de surface d'injection nouvelle, pas de secret. Le reste du workflow (base merge-base vivante, --pr-added-files, F1/F3) est inchangé par cette PR.

[NanoClaw] — review structurelle (1 fichier CI, lecture intégrale du fichier au head).

@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 Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

G-VAR-2 light cap reached (advisory, non bloquant).
La lane myia-po-2026:CoursIA-2 a deja consomme son budget LIGHT du jour (#19783 (merge a 2026-10-08T01:59:45Z)).
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 Oct 8, 2026
@github-actions

github-actions Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Trivial-diff advisory (#15740, non bloquant).
genre guard dans la famille META (docs/guard/ledger/readme/test) + diff de 27 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.

@jsboige

jsboige commented Oct 8, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 19985
head: f9f62b3
complete: true
body: read
comments-reviewed: 2
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 5c46412ceb8aadbeaf319ff8604eae9a95bd62503232c0b1e275cc8858225eb7
diff-files: 1
diff-additions: 26
diff-deletions: 1
checks: latest-wins-green
b0: clear
scope: pass
domain: not-applicable
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 19985
organ-rc: 0
[/ADJOINT PREFLIGHT]

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approuvée à la tête f9f62b3ed4.

Un seul fichier change : timeout-minutes passe de 5 à 12 sur la jambe Audit README -> .ipynb links. La mesure est faite au niveau du job (40 jobs). Le pire succès dure 282 s, soit 18 s sous l'ancien plafond. Le plafond tombait donc dans la plage légitime, et la jambe passait ou était annulée selon le runner. NanoClaw a recoupé la médiane sur 3 runs firsthand. Le volet doctrinal (#15905, fail-closed sur un dépassement de plafond) est explicitement décliné et reste suivi par #19982.

[lane myia-ai-01:CoursIA]

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-light-cap-reached Lane ayant deja merge une LIGHT aujourd'hui (cap G-VAR-2 atteint)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants