Repository navigation
Scripts Tests (CPU): point de triage unique - 4 modes de rouge documentes (infra vs contenu) #17299
Description
Activity
[CLAIMED] lane myia-po-2026:CoursIA-2 -- paths: docs/ci/scripts-tests-triage.md
Grain: MED/guard -- lane myia-po-2026:CoursIA-2 -- prev: MED/guard #17293
Livraison planifiee : convertir le memo de triage (4 modes documentes dans le body de l'issue) en fichier persistant
docs/ci/scripts-tests-triage.md, avec regle de triage 5 points, tableau des modes/tells/remedes/statut, et references croisees vers #17253 / #17292 / #17293.Pourquoi cette livraison maintenant : les PRs #17244 et #17261 (lane po-2026, cycle en cours) portent des rouges
Scripts Tests (CPU)qui sont base-inherited au sens du memo (modes 3 et 4 vraisemblables) -- le fichier permettra au coordinateur et aux futures lanes de ne pas traiter ces rouges comme des defauts de contenu et d'eviter les commits inutiles qui ne font que re-armer des timers.Verification first-hand : 4 mesures citees (po-2027 21/09, lanes #16219/#16464/#16405 triage 2026-09-21, main a8aafc3/b5c64988 a 3 min d'ecart), dont 2 reproduites ce cycle. Pas de speculation.
Worktree : D:/Dev/CoursIA-17299-scripts-tests-triage, branche feature/17299-scripts-tests-triage.
🤖 Generated with Claude Code
- added a commit that references this issue
on Sep 22, 2026 Mode 4, nouvelles occurrences du 23/09 :
mainrouge sur 3 commits de suite, 4 des 5 morts sur les runners WSL d'ai-01 (mesure ai-01)Job Commit / PR Runner Tell 107071049208 mainbcc8796myia-ai-01-wsl-3annotation Out of memory.107072690887 mainbddcdf8myia-ai-01-wsl-7The self-hosted runner lost communication with the server107113627826 main4023dddmyia-po-2024-linux-docker-1[gw1] node down: Not properly terminated, puisXDIST-WATCHDOG: 480 s de silence à 99 %107124988549 main4023ddd, re-runmyia-ai-01-wsl-7lost communication107124993959 #17240, re-run myia-ai-01-wsl-1BlockingIOError: [Errno 11] Resource temporarily unavailable. Trois échecs de sous-processus git, dans des tests que la PR ne touche pas (test_check_kernel_suffix_canon,test_scan_duplicate_test_pairs,test_check_pr_translation_drift)État de la VM WSL d'ai-01 à 10:10Z (lecture seule) : 128 Go, dont environ 100 Go disponibles ; 32 CPU ; le holder
sleep infinityest vivant depuis 4 j 22 h. Mais plusieursRunner.Listenern'ont qu'environ 10 minutes d'âge : des runners meurent et sont relancés.dmesgn'expose aucun OOM kill lisible depuis la distribution. La cause n'est donc pas identifiée : la pression n'est pas visible au niveau de la VM au moment de la lecture, elle frappe par rafales.Gestes faits : re-run des jobs échoués (le remède de ce mode), sans aucun push. #17267 est redevenue verte au 3e essai.
mainet #17240 sont re-lancés une fois de plus.Question pour l'arbitrage capacité : les 7 runners
myia-ai-01-wsl-*tournent sur la machine qui sert aussi vLLM et la majorité des services de la flotte. Le nombre de runners simultanés par hôte, multiplié par les workers xdist de chaque job, est le premier suspect à mesurer. C'est une piste, pas une conclusion.Mode 4, cause probable sur ai-01 : le pool
myia-ai-01-wsl-*tourne sous-dimensionné par rapport à la mesure que le dépôt prescrit lui-même (mesure ai-01, 23/09 ~10:40Z, lecture seule)Ce que le dépôt prescrit
scripts/ci/docker/linux-runner/supervise.sh, l.117-140, mesure #16643 du 18/09 : une rejouée du job mort, aux caps exacts du slot, a capturé les deux saturations.- pids : 384/384 atteints, puis
EAGAINau spawn (« Resource temporarily unavailable »). Le commentaire la nomme « la signature exacte du job mort ». - mémoire :
memory.peak == memory.maxà 3,0 Gio, pour une demande réelle d'environ 3,5 Gio.
Prescription pour les pools qui portent « Scripts Tests (CPU) » :
COURSIA_RUNNER_PIDS=512etCOURSIA_RUNNER_MEMORY=4g.Ce que le pool d'ai-01 porte réellement
Lu sur les 10 conteneurs vivants (
docker inspect, socketdocker-ce.sock) :Prescrit (#16643) ai-01 réel mémoire par slot 4g 3g ( 3221225472)pids par slot 512 384 (défaut, COURSIA_RUNNER_PIDSnon posé)CPU par slot 3 (mesure) 2 slots 8 (arithmétique l.139) 10 Le drop-in
/etc/systemd/system/coursia-runner.service.d/10-sizing.confdate du 09/09 : il précède la mesure du 18/09, et personne ne l'a mis à jour depuis. Son propre commentaire mémoire (« 6 x 3072 + 4 x 1024 ») ne décrit plus le pool, qui porte 10 slots et 16 waiters à 512m.Concordance avec les morts relevées ci-dessus
BlockingIOError: [Errno 11] Resource temporarily unavailable(feat(catalog,#14831): scientific_review mesure le risque, PRODUCTION devient un tampon signé #17240,wsl-1) : c'est la signature pids que Slotsmyia-ai-01-wsl-*: jobs tues par OOM dans la VM WSL pendant les drains de file (4 echecs mesures, vert jumeau sur un autre runner) #16643 a capturée.Out of memory.(wsl-3) : cap à 3g, sous la demande de 3,5 Gio.- « lost communication » et silence xdist de 480 s : c'est ce que produit un conteneur qui thrashe contre son cap avant de mourir.
Au niveau de la slice :
coursia-ci.sliceporteMemoryHigh=40GetMemoryMax=48G;memory.eventsrendmax 11880431etoom_kill 0(hiérarchique, 4 j 23 h de VM) ;memory.peakvaut 37G. La slice ne tue donc pas. La pression se joue par conteneur. La VM et l'hôte ne sont pas en cause : aucun événement 2004 d'épuisement de ressources côté Windows sur 14 h, et 97 Go disponibles dans la VM.Correctifs possibles (dry-run, rien n'est appliqué : il faut
sudo, que je n'ai pas)Consigne user du 22/09 (Q34) : ce n'est pas le moment de couper la capacité du CI. On la répartit, on ne la réduit pas. Les trois options ci-dessous gardent donc les 10 slots d'ai-01.
A.
COURSIA_RUNNER_PIDS=512seul. Coût en RAM : nul, puisqu'un plafond de pids ne réserve pas de mémoire. Cela lève la signatureEAGAIN. Le budget ne change pas, les slots non plus. Nouveau drop-in/etc/systemd/system/coursia-runner.service.d/20-pids.conf:# pids par slot : 384 -> 512 (#16643, supervise.sh l.133 : 384 mesures + agent ~60 + marge). # Retrait : supprimer ce fichier, daemon-reload, restart. [Service] Environment=COURSIA_RUNNER_PIDS=512
B. A, plus
COURSIA_RUNNER_MEMORY=4g, pour lever aussiOut of memory.. Il faut alors élargir la slice : 10 × 4096 + 16 × 512 = 49 152 Mo, au-dessus deMemoryHigh=40G. Deux voies :- porter la slice à
MemoryHigh=48GetMemoryMax=56G: +8 Go nominaux pour la CI. La VM a 97 Go disponibles et le pic de la slice est de 37G ; - ou réduire les waiters de 16 à 0 sur ai-01.
C. A, plus la répartition prévue par la consigne Q34 : les slots mémoire-lourds migrent vers po-2026, ai-01 garde 10 slots légers.
Recommandation : A tout de suite. Il ne coûte rien et vise la moitié des morts qui porte une signature univoque. B ne se décide que si
Out of memory.revient après A.Incertitude déclarée : je n'ai pas pu déterminer quel
COURSIA_RUNNER_BUDGET_GBle superviseur applique sur ai-01. Ni le wrapper ni l'unité ne l'exportent, et le défaut de 12 Go refuserait le pool actuel, qui tourne pourtant. A ne touche pas au budget mémoire ; B, si.Effet de bord, à annoncer :
systemctl daemon-reload && systemctl restart coursia-runnerarrête les slots, et les jobs en vol meurent. À faire dans un creux de file.[FRICTION]
supervise.shn'a pas de sous-commande qui évalue les gardes de budget (assert_memory_budget,assert_cpu_budget) avec des surcharges, sans démarrer de slot. Or un refus au démarrage fait rebouclerRestart=always: c'est l'incident du 09/09, poolfailedpendant environ 10 h. B ne peut donc pas être pré-validé par l'organe. A n'y touche pas.- pids : 384/384 atteints, puis
- added a commit that references this issue
on Sep 23, 2026 - addedcandidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)Referenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
on Sep 24, 2026 Mode 5 (candidat) : job
failureavec toutes les steps substantielles vertes — mesure po-2026, 2026-09-25 (~06:00Z), lecture seuleLe tell n'est couvert par aucune des 4 lignes de la table, et il est le plus trompeur des cinq : le check est rouge, la PR porte un diff légitime, et pourtant aucun test n'a échoué.
# Mode Tell Remède Statut 5 Job failuresans step fautive (runner démonté avant la sortie).steps[]: toutes les steps substantiellessuccess, mêmeRun tests; les stepsPost …sontnull(jamais exécutées, p. ex.Post Run actions/setup-python@v5,Post Run actions/checkout@v4) ; aucune annotation (output.titlevide,output.summaryvide) ; le log du job rendBlobNotFound(gh api …/jobs/<id>/logs) — le runner n'a rien téléversérien dans le contenu ; nommer le rouge comme infra (body de PR / dashboard) et ne pas relancer en boucle ; la preuve de contenu devient l'exécution locale de la suite sur la tête exacte candidat — variante probable de la famille infra (modes 2/4), tell distinct Mesure (toutes les valeurs relues firsthand à l'instant, pas reprises d'un status condensé) :
Champ Valeur Job 107958799623—Scripts Tests (CPU), run36099481347PR / tête #17755, 437df82a2d4fe6def9b62660bea9a3333870abf6Runner myia-po-2026-wsl-6(pool po-2026, pas le pool ai-01 des mesures du 23/09)Durée 05:42:00Z → 05:59:34Z= 17 min 34 sSteps 12 au total : 10 success(dontRun tests+ les 4 planchers de collection) + 2null(les deuxPost …)Annotation check-run 107958799623→conclusion: failure,output.title: null,output.summary: ""Log BlobNotFoundDiscriminant — ce qui prouve que ce n'est pas le contenu : la même suite, sur
main, est verte 4 fois dans la fenêtre exacte du rouge —04:22:56Z,04:55:35Z,05:45:08Z,05:56:56Z(gh run list --workflow scripts-tests.yml --branch main, succès consécutifs). Le dernier est postérieur au début de mon job. La suite partagée n'était donc pas cassée ; c'est l'instance de job qui l'était. Le diff de #17755 ne touche par ailleurs aucun chemin couvert par le triggerscripts/**.Lecture à faire : sur tout
failurede ce check, descendre d'abord au niveau des steps —gh api repos/jsboige/CoursIA/actions/jobs/<job_id> --jq '.steps[] | "\(.conclusion) :: \(.name)"'.Run testsvert = aucun test n'a échoué, quoi que dise la conclusion du job. Unfailurede job se lit souvent comme « la suite a un problème » ; ici c'est la sortie du job qui a échoué.Ce que je ne prétends pas : je n'ai pas identifié la cause racine (runner démonté au moment de la sortie ? perte de communication ?). Les deux
Post …nulles et le log absent sont cohérents avec un démontage de runner avant la phase post-job ; c'est une hypothèse, pas une conclusion. Si un lecteur sait que ce tell est déjà couvert par le mode 2 ou 4, cette ligne doit fusionner avec la sienne plutôt que rester une cinquième.Raison d'être de cette ligne : sans elle, le réflexe naturel est de pousser un commit « pour ré-armer » — exactement le geste que ce document existe pour éviter. Le rouge reste rouge sur la PR ; il est nommé, pas maquillé (le runner a par ailleurs été observé 2 fois sur ce même run : un
cancelledde concurrence à05:39:15Zpuis lefailureà05:39:36Z).See #17755(occurrence),See #17299(table)- removedcandidate-deliveredReferenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)Referenced by a merged PR with no post-merge activity -- candidate for close triage (#10466)
on Sep 25, 2026 [CLAIMED] lane myia-po-2026:CoursIA -- residu : integrer le mode 5 (mesure 25/09, encore absent de docs/ci/scripts-tests-triage.md) + documenter un 6e tell candidat (lock git orphelin, mesure firsthand du 02/10 sur #18864) -- paths: docs/ci/scripts-tests-triage.md
Grain: MED/docs-infra -- lane myia-po-2026:CoursIA -- prev: REPAIR/review
(Le claim CoursIA-2 du 21/09 a livre #17313/#17559 et est perime -- reprise du residu par la lane principale de la meme machine.)
Mode 6 (candidat) : lock git orphelin dans le workspace du slot (fetch impossible) — mesure po-2026 firsthand, 2026-10-02 (~20:xxZ), lecture + remède appliqués
Tell observé sur la jambe Kernel drift guard de #18864 (pas Scripts Tests — candidat par analogie de mécanisme : même phase checkout/fetch, même pool
CoursIA-runners-p0, même famille infra que le mode 2) :cannot lock ref 'refs/remotes/origin/fix/18457-pagmem-mru': Unable to create '/home/jesse/CoursIA-runners-p0/slot-5/_work/CoursIA/CoursIA/.git/refs/remotes/origin/fix/18457-pagmem-mru.lock': File exists(3 retries puis exit 1, échec en < 1 min — le tell temporel discrimine d'emblée d'un vrai défaut de contenu : la suite de tests n'a même pas commencé.)
Symptôme de pool : TOUT job atterrissant sur
myia-po-2026-wsl-5échouait au fetch sur ce même ref locké — le slot était en panne oupheline, pas le contenu.Diagnostic (sur la machine du pool) :
find <git-du-slot> -name '*.lock' -mmin -60→ le fichier lock précis ;pgrep -a git→ aucun process git vivant = lock orphelin (un process vivant = attendre, ne pas rm).
Remède :
rmdu fichier.lockprécis, rejeu des enfants (pas du gate parent — #15905). Appliqué le 02/10 : enfants verts, gate attempt 3 SUCCESS, #18864 MERGEABLE.Ce que je ne prétends pas : origine du lock non établie (kill de runner pendant un fetch ? fin de job interrompue ?). C'est le tell et le remède qui sont actionnables ; l'origine relève du suivi capacité (comme le mode 4).
Raison d'être de cette ligne : même réflexe coûteux que le mode 5 — sans elle, le réflexe est de pousser un commit « pour ré-armer » alors qu'un
rmciblé suffit et qu'aucun test n'a tourné.See #18864(occurrence + remède appliqué),See #17253(famille fetch/checkout, mode 2).- added a commit that references this issue
on Oct 3, 2026 [CLOSURE PREFLIGHT]
schema: 1
lane: myia-po-2027:CoursIA
issue: 17299
verdict: CLOSE
acceptance:- Point de triage unique documentant les 4 modes de rouge -> docs/ci/scripts-tests-triage.md present sur origin/main (verifie firsthand ce jour, 23 occurrences de mode couvrant les 4 rouges documentes)
- Livraisons mergees -> PR docs(ci,#17299): scripts-tests-triage.md -- point de triage unique des 4 modes de rouge Scripts Tests (CPU) #17313 (MERGED 2026-09-16, doc de triage, verifiee firsthand mergedAt non null) et PR fix(ci,#17299): --cgroup-parent = nom de slice sous le pilote systemd (10/10 slots ai-01 en rc=125) #17559 (MERGED, supervise.sh + test_supervise_guards.sh, verifiee firsthand mergedAt non null)
residue: none
open-prs: 0
comments-reviewed: 6
[/CLOSURE PREFLIGHT]
[RELEASED] lane myia-po-2027:CoursIA -- dossier de fermeture CLOSE (bloc 8 amendé, lot C #18089). Grain: LIGHT/guard -- lane myia-po-2027:CoursIA -- prev: MED/docs #19495
[RELEASED] lane myia-po-2027:CoursIA -- dossier NON ELIGIBLE (gate : self-attestation refusee, ma lane a touche cette issue). La verification firsthand ci-dessus reste exacte ; une lane tierce doit poser le dossier definitif. Rendue au lot.
[CLAIMED] lane myia-po-2026:CoursIA — tapis (tirage batch ai-01 du 07/10 21:05Z, tete du tapis) : arc CI runners : triage Scripts Tests, avec #18279
Grain: MED/guard -- lane myia-po-2026:CoursIA -- prev: MED/guard #17293
Pourquoi cette issue
Scripts Tests (CPU)est un check REQUIS dont le rouge a quatre causes distinctes mesurées à des dates différentes, par des lanes différentes, sans point de ralliement. Le réflexe coûteux observé : traiter un rouge d'infra comme un défaut de contenu (fixer un test qui n'est pas en cause, pousser un commit qui ne fait que ré-armer des timers et les re-stamps d'autres lanes). Cette issue est le point de triage unique : avant tout geste sur un rouge de ce check, identifier le mode par son tell, puis appliquer le remède qui lui correspond.Les 4 modes, leur tell, leur remède
prune_merged_worktreesparsait stdout avant sa préconditionJSONDecodeError: Expecting value: line 1 column 1avec stdout vide ;rc=1inatteignable par les chemins nommésrun()fait sortir les exceptions inattendues enrc=2+ traceback + marqueur ; le test distingue skip motivé / échec dur)git fetch(promisor), trace SIGKILLenv:du step contient le JSON d'erreur 403 devenuPR_BODY;tag_required/perimeteraccusent un manquement de contenu qui n'existe pas_fork_exec(BlockingIOError: [Errno 11] Resource temporarily unavailable) ; watchdog xdistworkers morts+ silence 480 s ;mainoscille success/failure en ~3 min sans commit pertinent ; le test passe en <1 s en localRègle de triage proposée (acceptance)
taildu log — le diagnostic est souvent en tête de step).mainoscille sans commit pertinent ET qu'un frère du même run meurt sur_fork_exec→ mode 4 : aucun commit, rerun, mesure capacité. Ne pas commenter une PR qui porte un dossier (le commentaire l'invalide).Ce qui n'est PAS cette issue
Références de mesure
_fork_exec, 403 dansenv:,maina8aafc3/b5c64988 à 3 min d'écart).See #17253(mode 2 en reste le suivi),See #17292(mode 1, corrigé).