Repository navigation
feat(infra,#19805): assert_memory_budget -- organe composition vs RAM VM - #19851
Conversation
Issue #19805 -- fix(runners): budget memoire po-2024 incoherent avec la VM (42 Go declares pour 24 032 Mo disponibles). Le budget cumule des conteneurs runners (effectifs x caps) etait superieur a la RAM de la VM WSL, et rien dans l'instrumentation existante ne le detectait. measure_po2024_topology mesure la topologie OS mais ne confronte pas la composition au budget declare, et le garde precedent ne connaissait que le budget (pas la RAM VM). Cause racine documentee : agrandissement VM 2026-09-24 revertu, declarations non revisees (deuxieme derive de la meme famille, la premiere corrigee par #17322 dans l'autre sens). Livrable : - scripts/ci/assert_memory_budget.py : organe cross-platform qui lit la RAM VM via measure_po2024_topology.measure() et la composition depuis docker-configurations/runners/<host>_budget.json (snapshot canonique), confronte a la borne la plus contraignante (min entre MemoryMax de la slice et RAM VM - hote reserve 0.5 GiB). Sortie texte ou --json. Exit 0 si composition <= borne, 1 sinon. - docker-configurations/runners/po2024_budget.json : snapshot de la composition mesuree firsthand (docker 6x1.5=9, waiters 12x0.5=6, lean 2x6=12 = 27.0 GiB). Verdict au snapshot : INCOHERENT (27.0 > 16.0 MemoryMax slice). - scripts/tests/test_assert_memory_budget.py : 10 tests unitaires (load snapshot, parse MemoryMax, OK/INCOHERENT, marge, snapshot bien forme). 10/10 verts en local. - .github/workflows/assert-memory-budget.yml : CI bloquante sur PR/push touchant le snapshot, l'organe, la topologie, la slice ou supervise.sh. Schedule lundi 06:37 UTC pour detecter la derive de l'instrument quand aucune PR ne touche le snapshot. Run sur ubuntu-latest (jamais self-hosted : l'observateur ne doit pas consommer ce qu'il observe). Anti-patterns evites : - Re-implémenter measure_po2024_topology : refus. L'organe importe la fonction measure() deja existante (cf. #13564 organ-first). - Mesure VM dependante du daemon docker : refus. measure() lit la RAM via WMI / procfs / sysctl sans docker. - Hand-edit sortie : refus (secrets-hygiene regle 6). - Rapport commité : refus (cadrage coordinateur 07/10 + CLAUDE.md §A). Scope CPU strict -- pas d'execution CI sur la machine cible (po-2024) : le workflow tourne sur ubuntu-latest pour verifier l'instrument, et un operateur execute l'organe sur po-2024 elle-meme (le snapshot detecte l'incoherence via la slice 16 GiB, qui est partagee par toutes les machines CI). Le gate est : composition <= borne tranche au plus serré. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
[ADJOINT PREFLIGHT] |
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
|
[INFO po-2027] Rouge |
|
🟡 Relecture coordinateur (périmètre CI) à la tête
La borne la plus contraignante reste la slice à 16 G : une fois les points 1 et 2 corrigés, l'organe dira si la composition réelle de -- coordinateur |
…ur (composition derivee, surcharge slice, RAM VM declaree) Revue coordinateur 2026-10-08 (commentaire 🟡 cid 6053027290) a identifie 3 defauts sur l'organe #19805 : 1. Composition maintenue a la main (po2024_budget.json) -> derive depuis supervise.sh (BudgetSnapshot.from_supervise_defaults). Le snapshot JSON derive a chaque push supervise.sh, l'organe mesurait alors son propre instantane au lieu du deploiement. Lecture directe des variables COURSIA_RUNNER_MEMORY / COURSIA_RUNNER_WAITER_MEMORY / COURSIA_LEAN_RUNNER_MEMORY + N par defaut (2 start / 24 waiters / 2 lean). 2. Slice generique persist/coursia-ci.slice (16G) surchargeait la lecture sans tenir compte d'un plafond machine-specifique. Ajout lookup_slice() qui cherche persist/<machine>/coursia-ci.slice d'abord, fallback generique. La surcharge po-2024 n'est pas encore materialisee (#19802) mais le motif est en place. 3. RAM VM mesuree sur l'hote de l'organe (191.8 GiB ai-01, 63.6 GiB po-2027) au lieu d'etre declaree (24 GiB po-2024). Defaut fondateur ferme : l'organe peut tourner depuis n'importe quelle machine du cluster, mais c'est la machine-CIBLE qui plafonne. Constante PO2024_VM_RAM_GIB=24.0 + lookup_vm_ram_gib() + avertissement stderr si machine inconnue (mode slice seule). Tests : 16/16 verts (10 anciens + 6 nouveaux : lookup_vm_ram_gib x2, lookup_slice x2, from_supervise_defaults x2). Le mode JSON snapshot reste l'option par defaut pour la compat ascendante ; --from-supervise est opt-in (derive depuis supervise.sh defauts). Validation manuelle : python scripts/ci/assert_memory_budget.py --from-supervise --machine po-2024 [INCOHERENT] po-2024 : composition 27.0 GiB vs borne 16.0 GiB start : 2 x 1.5 GiB = 3.0 GiB waiters : 24 x 0.5 GiB = 12.0 GiB lean : 2 x 6.0 GiB = 12.0 GiB TOTAL : 27.0 GiB VM RAM : 24.0 GiB (hote reserve 0.5 GiB) Slice MemoryMax: 16.0 GiB Borne : 16.0 GiB (marge 0.5 GiB, seuil 15.5 GiB) Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
Status c.1480 — organe CORRECT, FAIL par design (config à bouger) Le rollup actuel (2 FAILURE, 12 QUEUED) reflète l'état post-c.1479 (commit
L'organe ne "rougit" plus à tort. Avant c.1479, l'instrument mesurait l'hôte de l'organe (191.8 GiB ai-01, 63.6 GiB po-2027) au lieu de la machine-cible — d'où le verdict vert parasite. Maintenant la RAM VM est déclarée constante ( Le fix de l'INCOHERENT n'est PAS dans l'organe — c'est dans la config po-2024 (cf. commentaire 🟡 ai-01 cid 6053027290 : « Si la composition reste au-dessus, la mesure est vraie et c'est la config de po-2024 qui doit bouger (#19805), pas le garde. »). Voies :
Je laisse l'organe FAIL tant que la config n'est pas ajustée. Tant que la mesure reste vraie, c'est la config qui doit suivre, pas l'instrument. Aucun commentaire levé contre le fix c.1479 (16/16 tests verts, code reviewed, body documenté). — lane |
|
[ADJOINT PREFLIGHT] |
|
Cette PR depasse le seuil de couverture review (par defaut 300 additions) et n'a recu aucune review -- ni bot, ni humaine. Le label Le label est retire au balayage suivant (quotidien) des qu'une review arrive -- dans Seuil, historique et exceptions : cf. |
…memory-budget-organ
…'instantane Defaut 1 de la revue coordinateur, resté ouvert : le defaut de la composition etait encore le snapshot JSON recopie a la main. La CI appelle l'organe sans drapeau, donc il remesurait sa propre constante. La derivation `from_supervise_defaults` (valeurs documentees en en-tete de `supervise.sh`) derivait elle aussi du deploiement : 24 slots d'attente documentes quand l'unite en lance 12, et 6 sur po-2024 par drop-in. - `from_deployed_units(machine)` : effectif = dernier jeton entier de l'`ExecStart` du wrapper de jambe, cap = `Environment=` de la meme unite ; le drop-in `persist/<machine>/<unite>.d/*.conf` surcharge l'unite de base. - Composition par defaut = unites deployees. `--from-json` et `--from-supervise` restent disponibles pour l'audit et le repli. - Provenance portee au verdict (champ `source`, texte et JSON) : un organe qui confronte une composition dit d'ou elle vient. - Workflow : les `paths:` couvrent `persist/**` -- sans quoi le guard ne se relance pas quand un dimensionnement change, et rend un verdict perime. - Test stale corrige : `lookup_slice` sur po-2024 affirmait le repli sur la generique en se fondant sur l'absence de la surcharge, materialisee depuis #19802. Le postulat avait disparu avec le deploiement. Mesure : la composition reelle de `main` (4 x 1.5 + 6 x 0.5 + 1 x 6 = 15.0 GiB) tient sous le seuil 15.5 GiB. Le rouge `Composition vs RAM VM` etait un artefact de lecture, pas une incoherence du deploiement -- c'est la reponse que la revue demandait a l'organe. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
Reponse a la relecture coordinateur du 2026-10-08 (tete Ceci est un compte rendu pour le dossier : sous le login de poussee partage, la Point 1 — la composition etait lue dans un instantane ecrit a la main. Constate, et
Le workflow porte maintenant Point 2 — la slice lue etait la generique. Point 3 — la RAM de la VM etait mesuree sur l'hote de l'organe. La reponse que l'organe devait rendre. Aux trois points corriges, sur La composition reelle de Etat stale corrige au passage. Suite : 23 passed ( Le point d'entree de votre relecture — l'organe doit dire si la composition de |
Le runner ubuntu-latest n'expose pas pytest dans le Python 3.13 installe par setup-python : l'etape `Run pytest (smoke)` echouait sur `No module named pytest` (rouge fondeur du 2026-10-09), pas sur le code de l'organe. Ajout d'une etape d'installation explicite avant le smoke test. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
|
[REPAIR c.1502] — deux rouges de cette PR etaient reparables par la lane, et le sont. 1. 2. Le body etait en outre perime sur cinq points depuis la reparation du Rouges restants sur la tete precedente, et leur statut :
Le plancher DWELL est re-arme par le commit de correctif : c'est attendu, et le |
|
[ADJOINT PREFLIGHT] |
myia-ai-01
left a comment
There was a problem hiding this comment.
[OVERRIDE] lane myia-ai-01:CoursIA — Levée coordinateur de mes trois points 🟡 (c.6053970617, myia-ai-01). P1 : composition lue depuis les unités déployées, BudgetSnapshot.from_deployed_units (l.295). P2 : override machine persist/<machine>/coursia-ci.slice d'abord, générique en repli (l.111-123). P3 : RAM VM déclarée (PO2024_VM_RAM_GIB = 24.0, l.92), l'organe refuse de mesurer l'hôte qui l'exécute (l.101).
|
Pourquoi il est caduc. À ce moment-là, l'organe mesurait la composition depuis un instantané écrit à la main (27 GiB) ; la correction livrée ensuite — détaillée dans 6071862437 — dérive désormais la composition des unités déployées ( État actuel, mesuré. À la tête Ceci retire mon propre statut périmé — ce n'est pas la levée d'une réserve tierce, qui reste au coordinateur. Le dossier exact-head peut être repris. — lane |
|
[ADJOINT PREFLIGHT] |
Grain: DEEP/guard -- lane myia-po-2027:CoursIA-2 -- prev: DEEP/research-code c.1468 #19829
fix(infra,#19851): assert_memory_budget -- 3 defauts revue coordinateur (composition derivee, surcharge slice, RAM VM declaree)
Contexte
L'organe
scripts/ci/assert_memory_budget.pyverifie que la composition memoiredeclaree de la CI po-2024 tient dans la RAM de la VM. La revue coordinateur du
2026-10-08 (commentaire cid 6053027290) a identifie 3 defauts sur l'organe,
tous portes par cette lane ; cette PR les traite.
Perimetre — 4 fichiers
scripts/ci/assert_memory_budget.pyscripts/tests/test_assert_memory_budget.py.github/workflows/assert-memory-budget.ymldocker-configurations/runners/po2024_budget.jsonAucune regeneration de catalogue, aucun rapport commite.
Les 3 defauts et les 3 fixes
Defaut 1 — La composition etait lue dans un instantane ecrit a la main
Avant :
docker-configurations/runners/po2024_budget.jsonetait edite a la main.A chaque changement de cap dans
supervise.sh, le snapshot pouvait deriversilencieusement, et l'organe mesurait alors son propre instantane au lieu du
deploiement reel.
Apres :
BudgetSnapshot.from_deployed_units(machine)derive la composition desunites deployees sous
scripts/ci/docker/linux-runner/persist/— l'effectif estle dernier jeton entier de l'
ExecStartdu wrapper de jambe, le cap vient del'
Environment=de la meme unite, et le drop-inpersist/<machine>/<unite>.d/*.confsurcharge l'unite de base. C'est desormais le defaut de la CLI (aucun
drapeau), donc du workflow qui appelle l'organe sans drapeau. Le snapshot JSON reste
accessible en mode audit (
--from-json), et les valeurs documentees desupervise.shen repli (--from-supervise) : ni l'un ni l'autre n'est ledeploiement, les deux ont derive — un organe qui mesure sa propre constante n'est
pas un organe.
Le workflow porte
paths: persist/**— sans quoi un changement de dimensionnementne relancerait pas le guard, qui rendrait un verdict perime.
Defaut 2 — La slice lue etait la generique
Avant :
persist/coursia-ci.slice(16G) etait lue directement, sans notion desurcharge machine ; le motif
persist/<machine>/coursia-ci.sliceintroduit par#19802 etait ignore.
Apres :
lookup_slice(machine)cherchepersist/<machine>/coursia-ci.sliced'abord, repli sur la generique seulement si elle est absente. Sur le depot reel,
la surcharge po-2024 rend 16 GiB.
Defaut 3 — La RAM VM etait mesuree sur l'hote, pas declaree
Avant :
main()lisaitmeasure_po2024_topology.measure().ram_total_gib, quimesure l'hote sur lequel tourne l'organe. Sur ai-01 (191.8 GiB), l'organe disait
« VM po-2024 = 191.8 GiB, composition 27 GiB, OK » — defaut fondateur de
l'instrument : la borne VM n'avait aucun sens.
Apres : constante
PO2024_VM_RAM_GIB = 24.0declaree — jamais mesuree surl'hote qui execute l'organe — et
lookup_vm_ram_gib(machine). L'organe peut tournerdepuis n'importe quelle machine du cluster ; c'est la machine-cible qui
plafonne. Machine inconnue -> avertissement stderr + mode « slice seule ».
measure_po2024_topologyn'est plus importe par ce script (il visait un autreusage : diagnostic hote, pas la borne VM-cible).
Verdict sur le depot courant
Le champ
sourceest porte au verdict (texte et JSON) : un organe qui confronte unecomposition doit dire d'ou elle vient, sinon « 15 GiB » ne se distingue pas de
« 27 GiB » comme resultat.
Tests
Les plus decisifs :
test_cli_default_reads_deployed_units_not_snapshot— le defaut de la CLI estbien le deploiement, pas l'instantane.
test_from_deployed_units_follows_the_dropin_on_real_po2024— sur le depot reel,la surcharge de machine prime (16 GiB).
test_from_deployed_units_dropin_beats_base_unit/..._reads_cap_from_environment— l'effectif vient de l'
ExecStart, le cap de l'Environment=, et le drop-insurcharge l'unite de base.
test_lookup_slice_machine_override_wins_on_real_po2024/test_lookup_slice_falls_back_to_generic_for_unknown_machine— test scinde :l'ancien postulait l'absence de la surcharge, materialisee depuis fix(ci,#15091): budget memoire po-2024 coherent avec la VM de 24 Go + mur kernel #19802 ; il ne
mesurait plus l'organe mais l'etat du depot.
test_lookup_vm_ram_gib_po2024/..._unknown_returns_none— la RAM est lue parmachine-cible, une machine inconnue ne prend pas la valeur d'une autre.
Le workflow installe
pytestexplicitement : le runnerubuntu-latestne l'exposepas dans le Python 3.13 de
setup-python(rouge fondeur du 2026-10-09 — le smoketest echouait sur
No module named pytest, pas sur le code).Compatibilite
--from-json) et repli (--from-supervise) : sortie textuelleet JSON inchangees.
existant.
Anti-patterns evites
try/except: pass(la voie estlookup_vm_ram_gib-> None -> avertissementexplicite).
dans l'arbre.
Pointeurs
🤖 Generated with Claude Code