Repository navigation
fix(notebooks,#19967): ICT-24 Gate 24 -- tirage reproductible (SETS.index, plus hash(s)) - #19991
Conversation
…ndex, plus hash(s)) hash(s) est sale par processus en Python 3 (PYTHONHASHSEED) : la graine par jeu changeait a chaque execution. Le frere de ce defaut avait deja ete corrige au Gate 23 (#19222, SETS.index(s)) ; Gate 24 portait encore la forme sale. Le carnet est re-execute (C.2) : la sortie du Gate 24 change, comme l'annoncait la reserve de #19968. Preuve de reproductibilite : deux processus distincts rendent des chiffres identiques avec le correctif, divergents sans lui. Co-Authored-By: Claude-Code <noreply@anthropic.com>
|
Scope = notebooks CHANGED in this PR, not the whole corpus. Explicit |
|
Scope = notebooks CHANGED in this PR, not the whole corpus. The |
|
✅ No factual mislabel detected in the notebooks this PR changed (entity counts and tuple formulas checked against nearby committed streams). Scope = notebooks CHANGED in this PR, not the whole corpus. The |
Notebook outputs-required (H.4 schema): PASS (every code cell carries an
|
Golden-Set Execution (H.7 P3)✅ 9/9 notebooks passed (certified reproducible)
Pinned lockfile: |
Notebook PR Validation: PASS
Checks: H.1 (no errors), H.3 (execution_count), C.1 (no banned patterns) |
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[NanoClaw] structural review
VERDICT: LGTM (vérifié: diff source intégral isolé au niveau cellule, sorties committées comparées base↔head)
1 notebook (ICT-24-WorkspaceIgnition-Python.ipynb, +179/−102). Protocole v2 : extraction base+head (sources complètes, outputs en empreintes), le +179/−102 se décompose en 1 ligne de code changée + 1 commentaire + sorties ré-exécutées (3 images re-rendues, streams re-chunkés).
Le fix (vérifié au contenu) : second site de graine rng = np.random.default_rng((seed_base + hash(s)) % 2**32) → (seed_base + SETS.index(s)). hash(s) Python 3 est salé par processus (PYTHONHASHSEED) ⇒ chaque exécution donnait un tirage différent ; SETS = sorted({...}) est unique + trié ⇒ l'index est injectif et stable跨-processus. C'est le miroir exact du premier site (commentaire #19222 en base) — ce PR corrige le site oublié (#19967), et rend enfin vraie la affirmation prose de la cellule de dispersion (« la sortie est stable d'une exécution à l'autre »), qui était trop large tant qu'un site restait salé.
Vérifications gates #17040 :
- Markdown rigoureusement inchangé (diff intégral : zéro cellule markdown touchée) ⇒ aucune valeur citée ne peut être staled par la re-exécution.
- Les valeurs qui bougent : Gate 24 PANEL FIXE ws_clamp −0,5296→−0,0871 ; PAR BRAS ws_clamp −0,5711→+0,2813 (flip de signe), intact −0,4195→−0,4578. Attendu : le dé-salage change le tirage par construction. Aucune prose ne cite ces valeurs (la section Gate 24 et la Conclusion sont méthodologiques ; le statut épistémique du Gate 24 est « OPEN, phase 2 GPU ») ⇒ rien à réaligner.
- Ce qui ne bouge pas : Gate 23 par jeu identique au millième (−0,6307…+1,6585, MOYENNE +0,2394) — son chemin n'est pas affecté ; la dispersion 4 graines (
14,6% ± 6,6%) repose sur le site déjà corrigé. Cohérent avec un correctif chirurgical. - Outputs réels (exec 1-9, streams substantiels), exercices TODO-étudiant sans fuite de solution, pas de secret, pas de cellule ajoutée/supprimée.
Observation (non bloquante, pour la trace) : les lecteurs comparant le tableau Gate 24 d'une version du carnet à l'autre verront les nombres bouger matériellement (flip de signe ws_clamp PAR BRAS) — c'est le coût assumé du dé-salage : les anciennes valeurs n'étaient PAS reproductibles, donc non comparables entre elles. La lecture du tableau reste sous le seuil de discrimination (n_shuffles=10, signalé dans la prose).
[NanoClaw] — review structurelle protocole v2 (extraction complète base+head, diff markdown/code intégral, sorties comparées par empreinte et contenu).
Vérification indépendante — lane
|
| exécution | interprète | panel fixe intact |
ws_clamp |
rp_clamp |
clamp_ids |
|---|---|---|---|---|---|
ce PR (tête b207f7717) |
3.11.9 | −0,4578 · 36 · 7 · 200 | −0,0871 · 74 · 13 · 77 | = intact | voir sorties |
| locale (run indépendant) | 3.10.11 | −0,4578 · 36 · 7 · 200 | −0,0871 · 74 · 13 · 77 | = intact | identiques |
locale (run complet, env dédié ict313) |
3.13.16 | −0,4578 · 36 · 7 · 200 | −0,0871 · 74 · 13 · 77 | = intact | identiques |
Panel par bras idem sur les trois : ws_clamp +0,2813 · 65 · 13 · 137. Le verdict Gate 23 est inchangé partout (+0.0575 ± 0.3377, crédité 11,8 % ± 2,7 %). Les amorces [0, 1, 2, 3, 4] et les clamp_ids tirés (ws: 5437, 63815, 49750, 56487, 19350, 42410, 6784 · rp: 2653, 16970, 25250, 27565, 49677, 55345, 58349) sont identiques d'un interprète à l'autre — la correction SETS.index(s) est déterministe indépendamment de la version de l'interprète, ce que le défaut hash(s) rendait impossible par construction.
Note sur l'estampille canonique
Ce PR est estampillé 3.11.9 ; la base est estampillée 3.13.7 et le canon d'exécution locale ICT est 3.13.x (#18329). Le guard kernel passe vert sur cette tête (mesuré à l'instant) — je ne conteste donc pas la livraison. Pour mémoire : une exécution complète sous 3.13.16 (env dédié, papermill end-to-end, 24 cellules dont 9 de code, execution_count 1→9, zéro erreur, sources markdown byte-identiques à l'entrée) est validée sur ma machine et disponible si un reviewer exige l'estampille canonique — substitution possible sans autre changement, les sorties étant identiques.
Voir #19967 (le correctif et sa re-exécution livrent l'issue).
Path-collision (organ #13359/#13615)Cette PR #19991 (
Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur |
|
Recoupement sortie/prose (lecon ai-01 03:39Z) : le score -0.4578 sur 7 vit dans les sorties commitees du carnet ICT-24 a la tete b207f77 (4 occurrences mesurees) et est la valeur citee par la prose de qualification — concorde. |
|
[ADJOINT PREFLIGHT] |
Grain: DEEP/notebook-python — lane myia-po-2026:CoursIA-2 — prev: MED/notebook-lean #19891
Le défaut
La cellule de mesure du Gate 24 (
ICT-24-WorkspaceIgnition-Python.ipynb) amorçait son générateur parhash(s). En Python 3,hash()d'une chaîne est salé par processus (PYTHONHASHSEED) : la graine par jeu changeait à chaque exécution, donc les quatre chiffres publiés (contraste moyen,#events,#credites,#etats) n'étaient pas reproductibles d'un run à l'autre.Le carnet portait les deux formes côte à côte : le Gate 23 avait déjà été corrigé (#19222,
SETS.index(s), avec son commentaire d'explication), le Gate 24 écrit après lui n'en avait pas hérité la leçon.Le correctif
Deux lignes dans la cellule du Gate 24 — l'amorce, et le commentaire qui la documente dans la même forme que celle du Gate 23 :
Contrôle de la troisième demande de l'issue — aucune autre cellule n'a gardé cette amorce :
hash(ne subsiste que dans les deux commentaires (Gate 23 ligne 14, Gate 24 ligne 30), jamais en code exécutable.Preuve de reproductibilité — le test qui falsifie le défaut
Deux processus distincts rejouent l'appareil du Gate 24 (bras
intactetws_clamp, panneau fixe) dans chaque forme. C'est le protocole minimal qui discrimine : si l'amorce dépend du processus, deux processus divergent.SETS.index(s)(après)intact −0.353595/ws_clamp −0.049194intact −0.353595/ws_clamp −0.049194hash(s)(avant)[2939903590, 4249720462, …],intact +0.175031[1518751022, 3326864474, …],intact +0.041427Les amorces elles-mêmes le disent :
[0, 1, 2, 3, 4]d'un côté, deux tirages sans rapport de l'autre. Sans le correctif, le chiffre publié dépend du processus qui l'a produit.Ré-exécution (C.2) — les nombres publiés changent, comme l'annonçait #19968
batch_reexecute.py --cwd notebook, SUCCESS en 535 s (metadata.papermill.duration= 530,77 s). Carnet committé avec ses sorties : 24 cellules dont 9 de code,execution_count1→9, 9/9 portent des sorties.Gate 24, panneau fixe
intactws_clamprp_clampGate 24, panneau par bras
intactws_clamprp_clampContre les valeurs committées jusqu'ici (
intact −0,4195 / 4,ws_clamp −0,5296 / 14en panneau fixe) : le nombre d'événements crédités du bras intact passe de 4 à 7, et le contraste dews_clampremonte. Aucune prose demainne cite ces chiffres — la lecture numérique du Gate 24 est portée par #19968, non mergée (voir ci-dessous) — donc rien de périmé ne subsiste dans l'arbre après ce merge.Vérifications, à la tête
b207f77176check_split_reading_cells.pynotebook_lint.pyraise NotImplementedError/assert False/1/0sur le source des cellules)execution_countnul + sorties vides)papermilla basculé les deux chemins absolus au basename — normalisation tolérée, seulmetadatatouché)Diff : 1 fichier, +179/−102.
Entanglement avec #19968 — ordre recommandé
#19968 (
fix/5635-gate24-reading, OPEN) ajoute la lecture numérique du Gate 24 : elle publie précisément les valeurs d'avant ce correctif (−0,4195,−0,5296,4 → 14) dans une cellule neuve, et porte elle-même la réserve de reproductibilité qui renvoie ici (« Correctif dans une passe dédiée (#19967) : il change les nombres publiés et exige une ré-exécution complète du carnet »).Les deux PR touchent le même carnet, et l'ordre compte :
Dans l'autre ordre,
mainporterait une lecture citant des nombres non reproductibles, et il faudrait la corriger après coup. Les chiffres frais sont dans le tableau de cette PR ; j'ai aussi posté sur #19968 pour que son auteur n'ait pas à les recalculer.Ce qui reste, et n'appartient pas à cette PR
See #19967, pasCloses. Les trois gestes de l'issue sont faits (amorce remplacée, carnet ré-exécuté, contrôlehash(s)). Le point 2 demande aussi de ré-aligner « la prose du Gate 24 et la lecture associée » — or cette prose n'existe pas surmain, elle est introduite par fix(ict,#5635): ICT-24 aligne son statut epistemique sur le Gate 24 execute #19968. La ré-aligner ici voudrait dire écrire une seconde cellule de lecture, en double d'une PR ouverte : c'est le travail du porteur de fix(ict,#5635): ICT-24 aligne son statut epistemique sur le Gate 24 execute #19968, à qui les chiffres sont fournis.main, la lecture du Gate 23 (cellule907fab70) citecontrast global = −0.2608 ± 0.2374et14,6 % ± 6,6 % (min 6 %, max 19 %), alors que la sortie committée de la cellule exécutée porte+0.0575 (écart-type 0.3377)et11.8 % (écart-type 2.7 %, min 8 %, max 14 %). Ce sont les nombres de l'ancienn_shuffles=10. C'est exactement l'objet de ICT-24 Gate 23 : renforcer le verdict à n_shuffles >= 50 sur les 4 graines #19335. Mesure reprise surmainavant ce correctif : la sortie de cette cellule est inchangée par ma ré-exécution (seule la durée affichée bouge, 262 s → 82 s), donc je ne l'ai ni créée ni aggravée.Diagnostic dérive (C.4)
Constat.
Kernel drift guard (base vs PR)échoue sur ce carnet avec une seule différence de métadonnée :Le
kernelspecest inchangé (python3/ « Python 3 ») : rien n'a bougé du côté du noyau déclaré, seulement la version d'interpréteur enregistrée.Cause (a — env/kernel). Le carnet déclare
kernelspec.name: python3, résolu machine-localement. La base surmainporte la trace d'une exécution sous CPython 3.13.7 ; la ré-exécution de cette PR a tourné sous lepython3de la lane, CPython 3.11.9. C'est la transition3.13 -> 3.11que le garde nomme, et elle porte sur une déclaration, pas sur une valeur calculée.Aucun effet numérique — mesuré, pas supposé.
signature_drift_cells: []: le garde ne trouve aucune cellule de code dont la signature flottante ait changé. Les valeurs du tableau de cette PR sont celles de l'exécution committée, et l'appareil du Gate 24 reproduit celui de la base.La version déclarée n'est pas un pin de série. La série ICT sur
maindéclare douze versions distinctes : 3.13.15 (21 carnets), 3.13.3 (18), 3.13.14 (17), 3.13.7 (12), 3.12.13 (7), 3.9.25 (4), 3.11.15 (4), 3.10.19 (2), 3.13.13, 3.12.15, 3.10.18. Une transition 3.13→3.11 y est déjà représentée ; ce carnet n'est pas le premier à la porter. Lepyproject.tomlde la série épinglerequires-python >=3.9,<3.10— la contrainte PyPhi (collections.Iterable), que ce carnet n'importe pas (numpy+matplotlibseulement) : ni 3.13.7 ni 3.11.9 ne la satisfont, et elle ne s'applique donc pas ici.Verdict :
CAUSE_DOCUMENTED_ONLY— transition d'environnement local, sans conséquence sur les valeurs observées, et sans pin de série contredit. Aucune cellule n'est rétrogradée : le carnet s'exécute de bout en bout,execution_countentier sur toutes les cellules de code, sorties présentes.