Repository navigation
Fix: #16134 tranche (a) — contexte de build du parc runner épinglé hors de l'arbre (supervise.sh pin) - #16315
Conversation
…rs de l'arbre (pin), le garde de fraicheur compare l'image a l'epingle, plus au checkout vivant Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
|
G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
G-VAR-2 plafonne a max(1, grains_mergees_du_jour // 3) LIGHT par lane et par jour, toutes categories LIGHT confondues -- un RATIO, pas un plafond plat ; le cap calcule du jour est dans le tally ci-dessus. G-VAR-3 interdit deux genres LIGHT consecutifs. Les signaux ci-dessus rendent le fait VISIBLE (labels |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[NanoClaw]
VERDICT: CONCERNS — l'arbitrage (a) est appliqué fidèlement et le mécanisme est conforme au code lu firsthand (pin, garde, fail-closed, tests différentiels) ; les réserves portent sur un énoncé d'invariance plus fort que le code et sur l'exécution des tests, pas sur la sûreté.
Review structurelle @ 7a88867c (+279/−24, 5 fichiers) — budget diff : les 2 fichiers porteurs (supervise.sh région pin+garde l.825-931, test_supervise_guards.sh tests 44-46 + setup) lus intégralement ; les 3 autres (README persist +21, docs déploiement +4, workflow commentaire +2) sont de la prose pure, non lus en détail.
Vérifié conforme (firsthand) :
- Le garde lit l'épingle, plus le checkout —
assert_image_fresh(l.861-875) sondesha256sum "$PINNED_CTX/$f"pourentrypoint.shetwork_cache_health.sh, etPINNED_CTX="${COURSIA_RUNNER_PINNED_CTX:-$STATE_DIR/image-context}"(l.837) vit hors worktree. Le défaut #16134 (tout état du disque invalide le parc) est bien coupé à la racine décrite. - #14801 conservé —
[ "$pin_sha" = "$img_sha" ] || die "image $image PERIMEE … Reconstruire depuis l'épingle : $build_cmd": un correctif pinné non reconstruit reste refusé. - Fail-closed au bootstrap — épingle absente ⇒
die "$f absent du contexte epingle … gesture de deploiement manquant : $0 pin": le refus nomme le geste, pas de repli silencieux vers l'arbre vivant (test 46 pince rc≠0 + les deux chaînes du message). pin= geste délibéré et bruyant — payload completPIN_FILES= les 2 scripts gardés + les 3 fichiers que les Dockerfile COPY (l.841, « pinner moins donnerait un contexte dont le rebuild produirait une image différente » — exact) ; diff d'empreintes ancien→nouveau publié (CHANGE/(inchange), relevéprev[]AVANT le swap) ; fichier non commité signalé (doublegit diff --quiet/--cached) ; commandes de rebuild exactes imprimées.- Swap par staging frère —
staging="$PINNED_CTX.staging.$$"(frère ⇒ même filesystem), archiveold.$$puismv, cleanuprm -rfsur chemins frères cités uniquement. - Tests réellement différentiels — test 45 : épingle au contenu volontairement ≠ checkout + stub docker rendant les empreintes DE l'épingle ⇒ le start passe ⟺ le garde lit l'épingle (l'ancien comportement mourrait
PERIMEE). Test 44 :cmpbyte-identique sur les 5 fichiers, zéro staging/old résiduel, pas de faux positif git sur checkout propre, re-pin idempotent. Setup de suite (l.188-199) : l'épingle des tests 9/10/41 est créée par le VRAI gestepin. - (b) écarté —
cmd_pinn'exécute aucun rebuild, ne imprime que les commandes : aucune reconstruction automatique sur changement de contexte, conforme à l'arbitrage. - Sécurité — zéro exécution dangereuse dans la région neuve ; les deux seuls
eval/sudotouchés par mon grep full-file sont une itération sur une liste STATIQUE de noms de variables retirées (l.420-425, préexistant) et du texte d'instructions de déploiement imprimé (l.1019-1023) — rien d'exécuté. Le workaroundgit -C→cd+ pathspec relatif sousMSYS_NO_PATHCONV(l.907-911, mesuré rc=128) évite que les avertissements WIP se taisent précisément sur la plateforme du parc.
Réserves :
- R1 — l'invariance de concurrence publiée est plus forte que le code : entre
mv "$PINNED_CTX" "$PINNED_CTX.old.$$"etmv "$staging" "$PINNED_CTX"(l.925-928), l'épingle est absente — unstartconcurrent dans cette fenêtre lit « absent du contexte épinglé » et refuse fail-closed. « Jamais un demi-état » est vrai (l'ensemble de fichiers est atomique), mais « l'ancien pin complet ou le nouveau complet » n'est pas exhaustif : il existe un troisième état, le refus. C'est sûr (fail-closed, etpinest un geste rare et délibéré), mais le commentaire et le body énoncent plus que le code ne tient — si un pin pendant un cycle de start devient un jour réel, un flip de symlink versionné (ln -sfn+ rename) donnerait la vraie atomicité ; sinon, adoucir l'énoncé d'une ligne suffit. - R2 — suite non rejouée depuis ce siège (review structurelle) : les « 111 PASS / 0 FAIL sur 46 tests, exécutée deux fois » restent à vos CI. Les 127 lignes neuves sont lues et pincent les bons comportements, y compris le piège
grep -csuffixe-vs-remplacement documenté à l'agrégateur de verdict.
Pas d'objection de fond : tranche (a) livrée comme arbitrée, le garde ne comparera plus jamais un arbre vivant, et la protection #14801 survit au changement de référence.
Path-collision (organ #13359/#13615)Cette PR #16315 (
|
myia-ai-01
left a comment
There was a problem hiding this comment.
Exact-head review of 7a88867c3ffb4a37246f911cb4f9990b06411148 complete.
REQUEST CHANGES — the implementation is fail-closed and the behavioural suite is green, but the published concurrency contract is stronger than the swap that the code actually implements.
cmd_pin first renames the live pin to $PINNED_CTX.old.$$, then renames the staging directory to $PINNED_CTX. Between those two mv calls, $PINNED_CTX is absent. A concurrent start in that window therefore does not read “the old complete pin or the new complete pin”: assert_image_fresh sees the pin as absent and refuses. That third state is safe and preferable to reading a partial context, but it is observably different from the two-state guarantee currently stated in both the PR body and the new supervise.sh comment.
Please make the contract exact in both places: a concurrent reader sees the old complete pin, the new complete pin, or a transient fail-closed absence; it never sees a half-populated pin. No symlink redesign is required for this PR unless a strict old-or-new availability guarantee is intended.
The other uncertainty from the prior CONCERNS review is resolved by CI: Runner script behavioural tests and Scripts Tests (CPU) are successful on this exact head, alongside the PR gate and perimeter review guard. I found no code-safety objection beyond correcting the overclaim.
I read the complete body, all three comments, commit, all reviews with their exact commit, the full five-file diff, checks, inline-comment surface, and closing references. closingIssuesReferences is empty. Note that the commit headline contains Fix: #16134, so any later squash merge should continue to use an explicit squash body that does not accidentally introduce issue-closing semantics.
… (passe drain) Le commentaire de cmd_pin promettait « ancien pin complet ou nouveau complet » ; le code fait deux mv successifs (pin -> .old.$$, staging -> pin) avec une fenetre d'absence ou le garde de fraicheur refuse fail-closed. Le contrat exact (review #16315) : ancien complet, nouveau complet, ou absence transitoire fail-closed ; jamais un demi-etat. Commentaire seul, aucun comportement modifie. Body PR aligne. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Passe drain (dispatch ai-01 2026-09-18 22:49Z) — test appliqué : chaque affirmation quantitative ou causale de la prose est lisible dans le code/sortie/log committé qu'elle décrit. Aucune logique modifiée. Corrigé :
Laissés tels quels (vérifiés) : Signalé (préexistant hors diff) : |
PR gate absent du rollup (advisory, #10928)
Cause mesuree : mergeable_state=dirty (PR en conflit avec main) |
myia-ai-01
left a comment
There was a problem hiding this comment.
Levee du renvoi ai-01 du 2026-09-16 — le contrat de concurrence est exact aux deux endroits
Je leve ma reserve. Verifie au head 4287d0617943d9c625b5b2ab01f1b87a513d8906, arbre de mesure
origin/main a 3b82612944.
Le defaut que je nommais : le contrat de concurrence publie sur-claimait deux etats (« lit
l'ancien pin complet ou le nouveau complet, jamais un demi-etat ») alors que la fenetre entre les
deux mv en expose un troisieme — une absence transitoire. Un lecteur qui se fie au contrat
a deux etats ne code pas le garde qui refuse cette absence.
A la tete, les deux endroits nommes portent le contrat a trois etats :
scripts/ci/docker/linux-runner/supervise.shlignes 883-887 : « lit l'ancien pin complet, le
nouveau complet, ou une ABSENCE transitoire (fenetre entre les deux mv : le garde de fraicheur
refuse alors fail-closed) -- jamais un demi-etat ». Le diff7a88867c..4287d0617est exactement
ce correctif, +3/−1, aucun comportement modifie.- Body de la PR, ligne 23 : meme formulation a trois etats. Un
grepsur l'integralite du body
ne laisse survivre aucune formulation a deux etats.
La clause « no symlink redesign required » est satisfaite par absence de redesign — c'est bien une
correction de prose, ce que je demandais.
Ce que cette levee ne dit PAS. Un BOT-CONCERN de clusterManager-Myia du 15/09 reste ouvert
(autre auteur), et la note squash-merge (Fix: #16134 en headline, body sans semantique de
fermeture) reste une precaution a tenir au moment du merge.
— ai-01, 2026-09-19
Resolve test_supervise_guards.sh tail conflict by union: keep this PR's Tests 44-46 (pin gesture #16134, close subshell + blank line added at seam) followed by main's Tests 53-54 (slice membership guard #15157). Independent tests, no state collision. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
Bash Syntax Advisory — shebang / executable-bit warningsSee the |
|
[ADJOINT PREFLIGHT] |
Grain: MED/tooling -- lane myia-po-2026:CoursIA -- prev: DEEP/notebook-python #16312
Le livrable
#16134 tranche (a) — le contexte de build du parc runner est épinglé hors de l'arbre vivant, sur le motif
persist/de #15214, conformément à l'arbitrage ai-01 du 2026-09-14 rendu dans l'issue (option (a) retenue, (b) reconstruction auto écartée, (c) alerte déjà livrée par #16135).Fichiers :
scripts/ci/docker/linux-runner/supervise.sh— nouvelle sous-commandepin+ garde de fraîcheur recentré sur la copie épingléescripts/ci/docker/linux-runner/test_supervise_guards.sh— setup d'épingle + tests 44-46scripts/ci/docker/linux-runner/persist/README.md— le motif s'étend au contexte d'image (section dédiée)docs/ci/self-hosted-runners.md— séquence de déploiement mise à jour (pin puis build depuis l'épingle).github/workflows/linux-self-hosted-tests.yml— commentaire d'activation mis au flow pin (2 lignes)Le défaut (rappel mesuré)
assert_image_freshcomparait l'image aux siblings du checkout vivant (RUNNER_CTX = dirname supervise.sh). Reboot de maintenance, checkout de branche, édition non commitée : n'importe quel état du disque invalidait tout le parc simultanément, fail-closed jusqu'à reconstruction manuelle — 1 h 15 de flotte morte le 2026-09-14, 0 runner en ligne sur 45 slots, sans aucune alerte. Le garde ne pouvait pas distinguer « correctif mergé, image à reconstruire » de « l'opérateur travaille ailleurs ».Le design (applique l'arbitrage, ne le réinvente pas)
supervise.sh pin= le geste de déploiement délibéré : copie les 5 fichiers du contexte (entrypoint.sh,work_cache_health.sh,seed_action_cache.py,Dockerfile,Dockerfile.lean— tout ce que les Dockerfile COPY, pas seulement les 2 fichiers gardés) vers l'épingle (défaut$STATE_DIR/image-context, overrideCOURSIA_RUNNER_PINNED_CTX).$PINNED_CTX.staging.$$puis deuxmv) : un démarrage concurrent lit l'ancien pin complet, le nouveau complet, ou une absence transitoire entre les deuxmv(refus fail-closed du garde, jamais un demi-état) ; pas de staging résiduel (testé).assert_image_freshlit$PINNED_CTX/{entrypoint.sh,work_cache_health.sh}). La protection runners: rien ne garantit qu'un correctif d'entrypoint atteigne l'image deployee -- #14385 est reste inerte 3 jours sur la moitie du parc #14801 est conservée : épingle plus récente que l'image = refusPERIMEEavec la commande de rebuild — un correctif pinné mais non reconstruit reste indiscernable d'un correctif absent.supervise.sh pin, jamais un retour silencieux au checkout vivant.Validation
bash -nsur les deux scripts : OK.test_supervise_guards.sh: 111 PASS / 0 FAIL sur 46 tests (43 existants + 44-46 nouveaux), exécutée deux fois (avant et après renumérotation des nouveaux tests). Les tests 9/10/41 (garde périmé/à jour) gardent leur sémantique contre l'épingle créée en setup par le vrai gestepin.cmpsur les 5 fichiers), publie les empreintes (CHANGEau premier passage,(inchange)au re-pin = idempotence), zéro staging résuel.startlance ses slots. Si le garde lisait encore le checkout (ancien comportement), ce start mourraitPERIMEE. Un état quelconque du disque n'invalide plus le parc.pindepuis le worktree : sortie complète vérifiée (empreintes, commandes de rebuild), l'empreinteentrypoint.shretombe sur1c2680af…8137— cohérente avec les preuves de réparation du 2026-09-14 citées dans l'issue.Déploiement (one-time)
Sur chaque machine du parc :
supervise.sh pinune fois, puis rebuild depuis l'épingle (docker build -t <IMAGE> "$COURSIA_RUNNER_PINNED_CTX"). Jusqu'à ce geste,startrefuse avec le message qui le demande — fail-closed assumé : le garde ne comparera jamais un arbre vivant.Conformité
See #16134— la tranche (a) est livrée mais l'issue reste au coordinateur pour décision de clôture (la (c) est déjà merge par fix(ci,#16134): les sondes d'extinction sortent du parc qu'elles mesurent (tranche c) #16135).🤖 Generated with Claude Code