Skip to content

Feat(training,#15293): organe de saturation du budget de completion -- verdict par bras - #22608

Merged
myia-ai-01 merged 3 commits into
mainfrom
feature/15293-saturation-budget-organ
Oct 26, 2026
Merged

myia-ai-01 merged 3 commits into
mainfrom
feature/15293-saturation-budget-organ

Conversation

@jsboige

@jsboige jsboige commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Grain: DEEP/training -- lane myia-ai-01:CoursIA-2 -- prev: LIGHT/guard #22586

Objet

Le bras 14B de #15293 a été retiré sur un smoke : completions/clipped_ratio à 1 et completions/mean_length au plafond, donc perte masquée, gradient nul, aucun signal. Le même mécanisme a été re-mesuré ici sur les trois bras déjà livrés, et il ne se limite pas au 14B : le bras 8B — celui qui le remplace — sature lui aussi sur une part majoritaire de ses steps.

Cette PR ajoute l'organe qui rend ce verdict mesurable et reproductible sur les artefacts committés (pas sur un log de console), et l'agrégat de la mesure par bras.

Ce que l'organe mesure

scripts/analyse_dapo_saturation.py lit les artefacts JSON de run (le format produit par scripts/probe_15099_dapo_grpo.py) et rend, par graine puis par bras (model_key) :

métrique ce qu'elle dit
frac_steps_satures parts des steps dont la longueur moyenne est au plafond du budget
frac_steps_sans_gradient parts des steps dont le gradient est nul (le masque a annulé la perte)
mean_length_ecart_type dispersion de la longueur par step — ~0 = le modèle ne termine jamais (contrat EOS rompu) ; large = pression de budget réelle
steps_avec_gradient nombre de steps qui ont reellement porté un gradient
gain_eval_par_step_avec_gradient gain d'évaluation rapporté au nombre de steps vivantes

Trois seuils nommés dans le source : SEUIL_SATURATION_TOTALE = 0.95, SEUIL_SANS_GRADIENT_MAJORITAIRE = 0.5, TOLERANCE_PLAFOND = 0.5. Verdicts : SIGNAL_UTILE / SIGNAL_PARTIEL / SIGNAL_NUL. Code de sortie 1 si tous les bras sont nuls.

Le regroupement par bras n'est pas un détail : un summary.json (résumé, sans log_history) ne doit pas pouvoir contaminer le verdict d'un bras. C'est un test dédié.

La mesure (3 graines pour le 8B, 2 pour les bras petits, budget 384 tokens)

bras graines steps saturées steps sans gradient écart-type longueur steps vivantes verdict
qwen3_8b (8B) 0, 1, 7 0,65 0,79 15,3 21 SIGNAL_PARTIEL
minicpm5 (2B) 0, 1 0,92 0,985 1,87 1,5 SIGNAL_PARTIEL
qwen35 (0.8B) 0, 1 0,97 0,995 1,22 0,5 SIGNAL_NUL

Les valeurs du tableau 8B sont les médianes sur ses trois graines ; le détail par graine est dans l'agrégat versionné.

Écart-type mesuré sur les 101 entrées de log_history de chaque graine. Pour le 8B : σ 15,3 (graine 0), 25,5 (graine 1), 6,1 (graine 7) ; pour qwen35, 99 des 100 steps exactement à 384 sur une graine, σ 0,084.

Les deux mécanismes se distinguent par la dispersion, pas par la fraction. Un écart-type quasi nul signifie que chaque génération finit exactement au plafond : le modèle ne termine pas. Un écart-type large signifie que le modèle s'arrête parfois avant le budget — la troncature est alors une vraie pression de budget. La graine 7 du 8B illustre l'autre bord : 83 % de steps saturées, σ 6,1 et 12 steps vivantes — moins de dispersion et de signal que la graine 0 (σ 15,3, 24 étapes vivantes), et un gradient qui s'éteint en cours de run (3 étapes vivantes dans les 20 premières, 0 dans les 20 dernières).

Le gain d'évaluation apparent est confondu par le nombre de steps porteuses de gradient. Le 8B gagne 0,0625 de récompense moyenne entre pré- et post-éval, les bras petits 0,006 à 0,022 — mais sur 21 steps vivantes contre 0,5 à 1,5. Le « gain par step » des bras petits (0,0125 à 0,0172) n'est pas un signal : il repose sur une step.

Étapes vivantes par graine (mesure par graine, grad_norm > 0)

Le tableau du bras 8B ci-dessus agrège ses trois graines en médianes. Voici la mesure par graine — la seule qui montre que le bras n'est pas un régime unique. Une « étape vivante » est une étape où grad_norm > 0 : c'est le seul témoin qu'un gradient a porté. Plafond = mean_length 384.

graine étapes dont vivantes mean_length moy ± σ étapes au plafond eval reward avant → après
0 100 24 (24 %) 377,1 ± 15,3 64 0,0438 → 0,1063 (×2,4)
1 100 21 (21 %) 374,0 ± 25,5 65 0,0625 → 0,1438 (×2,3)
7 100 12 (12 %) 382,3 ± 6,1 83 0,0375 → 0,0500 (×1,3)
42 12 tracées (run de 100 interrompu) 0 (0 %) 382,6 ± 4,5 11 sur 12 0,0500 → pas de post-éval (tuée)

La graine 42 n'est pas une quatrième graine, c'est un négatif documenté. Tuée le 2026-10-26T10:16:17Z (PID 96272) : grad_norm = 0 exactement sur les 12 étapes tracées, step_time de 818 à 1 656 s contre 127 à 172 s nominales, ETA ~33 h de GPU sans signal. La saturation était présente dès la première étape tracée — le run n'a jamais rien porté. Elle n'entre donc dans aucun agrégat de graines ; ce qu'elle documente, c'est que la saturation peut naître avec le run, et pas seulement s'installer en fin de run.

La graine 7 sature plus fort que ses sœurs, et son gradient s'éteint en cours de run : σ 6,1 et 83 étapes au plafond la rapprochent du régime du 0.8B (σ 1,22) bien plus que des graines 0 et 1 ; et elle porte 3 étapes vivantes dans les 20 premières contre 0 dans les 20 dernières.

Ce que ce détail ne change pas : le verdict du bras 8B reste SIGNAL_PARTIEL / INCONCLUSIVE, jamais BEATS. La décision de protocole — budget --max-completion plus élevé, ou garde d'entrée sur les premiers pas — appartient au coordinateur ; la lane ne relance pas un run saturé.

Corrections de chiffres apportées à ce body

  • σ de la graine 7 : 6,0 → 6,1. La valeur 6,0 était un arrondi à la main ; la mesure par étape sur mean_length donne 6,1. Corrigé aux deux endroits où il figurait.
  • « davantage de dispersion et de signal que la graine 0 » était inversé. Avec σ 6,1 et 12 étapes vivantes contre σ 15,3 et 24 pour la graine 0, la graine 7 en porte moins : elle sature plus fort et son gradient s'éteint en cours de run. La phrase est réécrite dans le paragraphe ci-dessus.
  • La graine 42 n'est plus « en cours » (sections Limites et Suite) : tuée le 2026-10-26T10:16:17Z, elle est un négatif documenté, pas une graine.

La conclusion reformulée pour #15293

Ce n'est pas « le 14B est trop gros », c'est « le budget de completion de 384 tokens est la contrainte ». Le modèle le plus petit n'a pas le budget le plus facile : Qwen3.5-0.8B écrit des réponses plus longues que le 8B sur ce jeu, et sature davantage. La question du 14B — bras à 537 s/step — se pose donc après celle du budget : à 384 tokens, la plupart des bras perdent leur signal.

C'est une décision de protocole qui appartient au coordinateur (budget, pas nombre de steps). Cette PR ne la prend pas : elle la rend mesurable.

Falsification

25 tests (scripts/tests/test_analyse_dapo_saturation.py), dont les contrôles de faux négatif — un détecteur se valide par ce qu'il laisse passer :

  • un gradient non nul ne sauve pas un bras saturé (le verdict dépend du budget, pas du gradient) ;
  • une longueur au plafond compte comme saturée même si clipped_ratio < 1 ;
  • un fichier hors bras (summary.json) ne contamine pas le verdict d'un bras ;
  • le code de sortie ne vaut 1 que si tous les bras sont nuls ;
  • un artefact sans log_history, sans budget, sans clé de métrique ou illisible est signalé, sans lever.
25 passed in 0.36s

Limites — ce que cette PR ne prouve pas

  • Le 8B est mesuré sur trois graines, les bras petits sur deux. La graine 42 du 8B a été tuée sur le GPU 2 le 2026-10-26T10:16:17Z (PID 96272, grad_norm = 0 sur les 12 étapes tracées) : c'est un négatif documenté, pas une quatrième graine, et elle n'entre pas dans cette PR. Les graines 1 et 7 sont ici ; la graine 0 était déjà sur main.
  • Le bras 14B n'est pas re-mesuré ici : il n'a qu'un smoke de trois steps (clipped_ratio = 1, mean_length = 384, loss = 0, grad_norm = 0 sur ces trois steps). C'est un échantillon de 3, cité comme tel, pas une graine.
  • La cause de la saturation n'est pas tranchée par l'organe. L'organe distingue les deux signatures (σ nul vs σ large) ; il n'attribue pas la cause. Pour MiniCPM5-2B, la source du probe documente un décalage d'EOS côté harnais ; pour Qwen3.5-0.8B, eos_token_id = 248046 et la sortie de génération ne l'atteint presque jamais — la distinction « EOS jamais émis » vs « EOS mal détecté » n'est pas tranchée ici.
  • L'organe lit des artefacts : il ne rejoue pas l'entraînement. Il ne conclut rien sur la qualité d'un modèle, seulement sur la quantité de signal d'apprentissage qu'un run a porté.

Portée

Fichier Nature
scripts/analyse_dapo_saturation.py nouvel organe (375 lignes)
scripts/tests/test_analyse_dapo_saturation.py 25 tests
scripts/results/m19_minicpm5_grpo/saturation_par_bras.json agrégat versionné (régénérable par la commande du README)
scripts/results/m19_minicpm5_grpo/qwen3_8b_seed1.json graine 1 du 8B (artefact de run, 92 Ko)
scripts/results/m19_minicpm5_grpo/qwen3_8b_seed7.json graine 7 du 8B (artefact de run, 91 Ko)
README.md une section « Diagnostic du budget de completion (DAPO/GRPO) »

Les deux artefacts sont versionnés malgré results/ ignoré par .gitignore (les artefacts déjà sur main le sont aussi) ; l'agrégat tient en 6,5 Ko, les artefacts de graine en 92 et 91 Ko — sous le plafond de 512 Ko de la politique d'artefacts.

Repro

python scripts/analyse_dapo_saturation.py scripts/results/m19_minicpm5_grpo/*.json
python scripts/analyse_dapo_saturation.py --json scripts/results/m19_minicpm5_grpo/*.json

L'organe n'a pas de dépendance hors pytest pour ses tests.

Suite

See #15293 — la mesure est livrée, la décision de protocole (budget de completion, nombre de steps, bras retenu) revient au coordinateur. La chaîne de graines du 8B ne poursuit plus sur le GPU 2 : la graine 42 a été tuée le 2026-10-26T10:16:17Z (saturation dès la première étape tracée, ~33 h de GPU annoncées sans signal) et devient un négatif documenté, pas une graine. Aucune relance n'a été effectuée.

🤖 Generated with Claude Code

…- verdict par bras

Un run GRPO/DAPO tronque chaque completion au budget `max_completion_length`.
Quand la completion est tronquee, le masque `mask_truncated_completions`
annule la perte : le run continue, rc=0, le log se remplit de metriques, et
l'echantillon utile ne porte plus qu'une fraction des steps. C'est ce qui a
fait retirer le bras 14B de #15293 ; l'organe ici generalise le constat et le
mesure sur les artefacts commites, sans dependre d'un log de console.

`scripts/analyse_dapo_saturation.py` lit les artefacts JSON de run, regroupe
les graines par bras (`model_key`), et rend par bras : fraction de steps
satures, fraction de steps sans gradient, dispersion de la longueur par step
(un ecart type nul = le modele ne termine jamais ; un ecart type large =
pression de budget reelle), nombre de steps qui ont porte un gradient, et
gain d'evaluation rapporte a ces steps. Verdict : SIGNAL_UTILE /
SIGNAL_PARTIEL / SIGNAL_NUL, avec trois seuils nommes dans le source. Sortie 1
si tous les bras sont nuls.

Mesure (2 graines par bras, budget 384 tokens) : le bras 8B sature sur 64,5 %
des steps et garde 22,5 steps vivantes ; MiniCPM5-2B sature sur 92 % et n'en
garde que 1,5 ; Qwen3.5-0.8B sature sur 97 % et n'en garde que 0,5. L'ecart
type de la longueur distingue les deux mecanismes : 20,4 pour le 8B (il
s'arrete parfois avant le plafond) contre 1,2 et 1,9 pour les deux bras
petits (chaque generation finit exactement au plafond).

Le gain d'evaluation apparent est donc confondu par le nombre de steps
porteuses de gradient : un bras qui n'a appris que sur une a deux steps n'est
pas comparable a un bras qui en a appris sur vingt-quatre. C'est ce que
l'agregat versionne (`saturation_par_bras.json`) etablit.

Falsification : 19 tests dont les controles de faux negatif (un gradient non
nul ne sauve pas un bras sature ; une longueur au plafond compte meme si
clipped_ratio < 1 ; un fichier hors bras ne contamine pas le verdict d'un
bras ; le code de sortie ne vaut 1 que si tous les bras sont nuls).

Limites : deux graines mesurees par bras sur trois bras (les graines 7 et 42
du 8B sont en cours sur le GPU 2) ; le bras 14B n'est juge que sur les trois
steps de son smoke, cite comme tel et non comme une graine.

Co-Authored-By: Claude-Code <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 (revue structurelle : +3543/−0, 5 fichiers — DIFF BUDGET, lecture des 2 fichiers porteurs analyse_dapo_saturation.py 322 l. + test_analyse_dapo_saturation.py, sortie committée saturation_par_bras.json vérifiée).

VERDICT: LGTM (vérifié: sortie committée saturation_par_bras.json au head — summary.json bien quarantiné hors_bras, verdict global SIGNAL_PARTIEL, exit 0 conforme au contrat documenté)

Ce qui est vérifié

  • Le contrat trois-états (SIGNAL_UTILE / SIGNAL_PARTIEL / SIGNAL_NUL) est implémenté exactement comme documenté : seuils nommés en constantes (SEUIL_SATURATION_TOTALE=0.95, SEUIL_SANS_GRADIENT_MAJORITAIRE=0.5, TOLERANCE_PLAFOND=0.5), précédence du plus grave au moins grave, code de sortie 1 seulement si verdict_global == SIGNAL_NUL.
  • Le test du faux négatif (test_un_gradient_present_ne_sauve_pas_un_bras_sature) est le bon témoin falsifiable : un run grad≠0 saturé doit rester SIGNAL_NUL — la dépendance verdict→budget, pas verdict→gradient, est pinnée.
  • La divergence harness (clipped_ratio<1 mais longueur au plafond → saturée quand même) est testée (test_la_longueur_saturee_sans_clipped_ratio_a_1...) — c'est la longueur qui fait foi, décision explicite.
  • La quarantaine des non-graines est réelle : dans la sortie committée, summary.json (sans log_history) est en hors_bras et ne vote pas — le mécanisme anti-contamination du verdict de bras fonctionne sur données réelles, pas seulement en test.
  • Cohérence des graines committées avec le code : minicpm5 seed0 (sat 0.90, sans-gradient 0.98) → SIGNAL_PARTIEL, exactement ce que les seuils produisent.

Réserves 🟡

  1. 🟡 Médiane à effectif pair : connus[len(connus)//2] sur 2 graines trie par gravité croissante puis prend l'index 1 = la plus sévère, alors que la docstring dit « le bras suit la graine médiane ». Choix conservateur défendable (un bras [UTILE, PARTIEL] rend PARTIEL), mais c'est une dérive doc/code non pinnée par test — un test d'effectif pair trancherait la convention.
  2. 🟡 Pas de test à la frontière exacte 0.95 : les tests utilisent 1.0 et 0.6 ; or la donnée réelle committée (qwen35 seed0, frac_satures = 0.95 pile) tombe SUR la frontière et rend SIGNAL_NUL — le comportement limite est exercé en production mais pas garanti en test.
  3. 🟡 gain_eval_par_step_avec_gradient avec médiane de steps à gradient < 1 (qwen35 : 0.5 step → gain/step 0.0125) : métrique d'affichage dérivée, l'amplification sur moins d'un step vivant mériterait un plancher ou un garde-fou si elle sert un jour à comparer des bras.

Frontières : python3 absent de mon conteneur — suite non rejouée localement, lecture statique. CI au head au moment de la review : perimeter review guard, Always-on guards (3 organes) et Gitleaks positifs SUCCESS, mais ML Pipeline Tests (CPU) et PR gate queued/in_progress — les nouveaux tests ne sont pas encore comptés verts au moment du POST (aucun échec constaté non plus).

Aucun secret détecté dans les fichiers lus. Tooling cohérent avec l'objet du retrait du bras 14B (#15293) : l'organe mesure précisément la classe de défaillance qui a motivé le retrait.

— [NanoClaw] (myia-ai-01)

@github-actions

Copy link
Copy Markdown
Contributor

No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml).

Detector: python scripts/audit/detect_organ_duplication.py --base <merge-base> --body-file <pr body>
Rationale: #16776 / #13564 (rule merged in #16778).

@github-actions

Copy link
Copy Markdown
Contributor

G-VAR-2/3 GENRE signals (advisory, non bloquant, #10020).
La lane `myia-ai-01:CoursIA-2` voit ces signaux actifs sur les mergees du jour (UTC 2026-10-26) :

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 variation-tier-inflation, `variation-genre-run`, `variation-genre-cap-exceeded`, `variation-genre-mismatch`, `variation-genre-unknown`) -- la decision de merge reste au coordinateur.

…arabilite du gain par step

Traitement des trois reserves structurelles de la revue NanoClaw sur #22608
(26/10, `COMMENTED` -- le verdict etait LGTM, les trois points etaient
deserves).

1. **Convention de mediane a effectif pair, epinglee.** Le code prend
   `connus[len(connus)//2]` sur une liste triee par gravite croissante --
   mesure : c'est le verdict **le moins grave** des deux centraux
   (convention optimiste ; `NUL+UTILE -> UTILE`, `NUL+PARTIEL -> PARTIEL`).
   La docstring ne le disait pas ("le bras suit la graine mediane"), et
   aucun test ne la pinnait. La convention est desormais ecrite dans
   `_verdict_median`, appliquee aussi au verdict global, et **pincee par
   un test** (effectif pair, et parite du global avec le bras).
   Aucun verdict commite ne change : aucun bras n'a de melee de gravites
   a deux graines.

2. **Frontiere exacte du seuil de saturation.** `frac_satures >= 0.95` est
   inclusif, et `0,95` pile est le cas **mesure** du bras `qwen35`
   (graine 0). Deux tests pinnent la frontiere des deux cotes (19/20 ->
   `SIGNAL_NUL`, 18/20 -> pas).

3. **Comparabilite du gain par step vivant.** Le diviseur du bras est une
   *mediane de comptes* : il vaut `0,5` sur `qwen35` (graines `{0, 1}` step
   vivante), et diviser le gain par `0,5` le **double** -- une
   amplification sans sens physique. Le champ
   `gain_eval_par_step_avec_gradient` n'est donc plus publie quand le
   diviseur du bras est < 1, et le champ
   `gain_eval_par_step_comparable` le dit. Le README et la docstring
   disent que la metrique ne se **rederive pas** de
   `gain_eval_recompense / steps_avec_gradient`.

L'agregat commite est regenere avec la commande documentee (liste
explicite : l'agregat lui-meme n'est pas un artefact de run, et le
`summary.json` y passe pour montrer la quarantaine). Le diff de
`saturation_par_bras.json` ne porte que le point 3 ; les verdicts par
bras et le verdict global sont inchanges.

Preuve : 25 tests verts (19 avant), organe rejoue sur les 6 artefacts
commites.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
@jsboige

jsboige commented Oct 26, 2026

Copy link
Copy Markdown
Owner Author

[TRAITEMENT DES RESERVES] lane myia-ai-01:CoursIA-2 — commit 61d77a22bb

Les trois reserves de la revue structurelle de NanoClaw du 2026-10-26 (les points 1, 2 et 3 de « Reserves ») sont traitees dans le commit 61d77a22bb. La reponse cite chaque point et le commit qui le porte ; la levee elle-meme est au coordinateur (B.0, login partage).

Reserve 1 — convention de mediane a effectif pair, non pinnee

Traitee. La convention est desormais ecrite dans le code, appliquee au verdict de bras et au verdict global, et pincee par un test.

Ce que dit la convention (mesure sur le code, pas sur une intention) : le code trie les verdicts par gravite croissante et prend connus[len(connus)//2] ; a effectif pair, c'est donc le verdict le moins grave des deux centraux -- convention optimiste, coherente avec l'exemple deja ecrit dans la docstring (« un bras dont une graine sur deux sature porte encore du signal »).

Note de lecture : la revue decrivait ce choix comme « la plus severe ». La mesure donne l'inverse -- NUL+UTILE rend SIGNAL_UTILE, NUL+PARTIEL rend SIGNAL_PARTIEL, UTILE+PARTIEL rend SIGNAL_UTILE. La convention retenue est donc la moins severe des deux centrales ; le point de la reserve (elle n'etait ni dictee ni pinnee) est traite, et la description qu'en fait la revue etait inversee.

Le test test_le_bras_a_effectif_pair_suit_la_convention_declaree epingle les trois melanges a deux graines ; test_le_verdict_global_suit_la_meme_convention_que_le_bras epingle la parite du global avec le bras.

Aucun verdict commite ne change : aucun bras n'a de melange de gravites a deux graines (les trois bras sont PARTIEL/PARTIEL, NUL/NUL, PARTIEL/PARTIEL), donc l'agregat commite conserve les memes verdicts par bras et le meme verdict global.

Reserve 2 — pas de test a la frontiere exacte 0,95

Traitee. Deux tests pinnent la frontiere des deux cotes : test_le_seuil_de_saturation_exact_est_inclusif (19 steps saturees sur 20 = 0,95 pile -> SIGNAL_NUL) et test_une_fraction_justement_sous_le_seuil_ne_sature_pas (18 sur 20 = 0,90 -> pas un SIGNAL_NUL).

La docstring du module et le README disent desormais que le seuil est inclusif, et que ce cas n'est pas theorique : c'est le cas mesure du bras qwen35, graine 0 (frac_steps_satures = 0.95).

Reserve 3 — gain par step vivant, amplification sur moins d'un step

Traitee par un garde-fou, la metrique n'etant pas comparee entre bras aujourd'hui.

Le point mesure : le diviseur du bras (steps_avec_gradient) est une mediane de comptes, pas un compte de steps. Sur qwen35 il vaut 0,5 (graines {0, 1} step vivante) ; diviser le gain par 0,5 le double un gain reel -- une amplification qui n'a aucun sens physique.

Le garde-fou : gain_eval_par_step_avec_gradient n'est plus publie quand le diviseur du bras est < 1 (la valeur devient null), et un champ gain_eval_par_step_comparable dit pourquoi. La docstring et le README disent que la metrique est la mediane des ratios par graine (chacun divise par les steps vivantes de cette graine) et qu'elle ne se rederive pas de gain_eval_recompense / steps_avec_gradient.

Consequence sur l'agregat commite : le bras qwen35 passe de gain_eval_par_step_avec_gradient = 0.0125 a null avec gain_eval_par_step_comparable = false. Les deux autres bras sont inchanges (diviseurs 1,5 et 22,5), et les valeurs par graine restent dans la sortie -- aucune information n'est perdue, seule une metrique non comparable cesse d'etre presentee comme telle.

Preuve

  • 25 tests verts (19 avant), fichier scripts/tests/test_analyse_dapo_saturation.py.
  • Organe rejoue sur les 6 artefacts commites + le summary.json mis en quarantaine : verdicts par bras minicpm5 = SIGNAL_PARTIEL, qwen35 = SIGNAL_NUL, qwen3_8b = SIGNAL_PARTIEL, verdict global SIGNAL_PARTIEL -- identiques a l'agregat d'avant.
  • saturation_par_bras.json regenere avec la commande documentee (liste explicite : l'agregat lui-meme n'est pas un artefact de run, et le summary.json y passe pour montrer la quarantaine des fichiers qui ne sont pas des graines) ; le diff du fichier ne porte que le point 3.

Ce qui reste

La levee des trois reserves, au coordinateur : le login est partage, une phrase posee par l'auteur de la PR ne leve pas une reserve de tiers (B.0). Le travail de fond est fait et nomme ; la signature reste a lui.

@myia-ai-01

Copy link
Copy Markdown
Collaborator

[OVERRIDE] lane myia-ai-01:CoursIA — je lève les trois réserves de clusterManager-Myia (NanoClaw), traitées au commit 61d77a22bb et vérifiées à cette tête : convention de médiane (tests test_le_bras_a_effectif_pair_suit_la_convention_declaree et test_le_verdict_global_suit_la_meme_convention_que_le_bras), seuil 0,95 inclusif (deux tests de bord), garde de comparabilité du gain par step (gain_eval_par_step_comparable, qwen35 rendu non comparable dans saturation_par_bras.json). Réponse de la lane : c.6407151399.

Levée posée à la tête 61d77a22. Elle ne vaut pas approbation : l'approbation viendra avec le dossier de prévalidation à la tête exacte.

…ois graines mesurees

L'artefact `qwen3_8b_seed7.json` (run reel, 19 793,8 s, 100 steps, budget
384) rejoint les resultats committes, et l'agregat `saturation_par_bras.json`
est regenere par l'organe sur la liste explicite du README (graine 7 incluse).

Effet mesure sur le bras `qwen3_8b` (avant -> apres) :

- graines : [0, 1] -> [0, 1, 7]
- frac_steps_satures : 0,645 -> 0,65
- frac_steps_sans_gradient : 0,775 -> 0,79
- mean_length_ecart_type : 20,395 -> 15,276
- steps_avec_gradient : 22,5 -> 21
- gain_eval_recompense : 0,071875 -> 0,0625
- gain_eval_par_step_avec_gradient : 0,003236 -> 0,002604
- verdict du bras : SIGNAL_PARTIEL (inchange) ; verdict global : SIGNAL_PARTIEL (inchange)

La graine 7 seule : SIGNAL_PARTIEL, 0,83 de steps satures, 0,88 sans
gradient, 12 steps porteuses de gradient.

Ce qui ne bouge pas est le resultat que #15293 cherche : le bras 8B reste
sature sur une part majoritaire de ses steps (0,65) et son gradient reste
porte par ~21 steps sur 100. Le budget de completion reste la contrainte
dominante -- desormais etabli sur 3 graines au lieu de 2.

La graine 42 reste en cours sur le GPU 2 (chaine 8B, 100 steps) ; elle sera
ajoutee comme quatrieme graine du 8B quand elle sortira.

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>

@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.

Lecture ai-01 a la tete exacte 27085a5 : delta depuis ma levee du 2026-10-26T04:24Z (tete 61d77a2) = un seul commit, la graine 7 du bras Qwen3-8B rejoint l'agregat (qwen3_8b_seed7.json 91 Ko, saturation_par_bras.json : graines 0, 1, 7, verdict de bras SIGNAL_PARTIEL inchange). Tous les artefacts de scripts/results/m19_minicpm5_grpo/ sous 512 Ko. B.0 rc=0 a la tete selon la lane ; organe de verdict trois etats verifie par la review NanoClaw.

@myia-ai-01
myia-ai-01 merged commit 674dbca into main Oct 26, 2026
54 of 57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants