Repository navigation
fix(guard,#15349): detect_md_content_loss exempte les artefacts de run generes - #15360
Conversation
…n generes Un notebook dont le markdown est une sortie non deterministe d'agent/LLM (SemanticKernel/Notebook-Generated.ipynb : la conversation multi-agents ECrit les cellules a chaque run) est dispense du content-loss : base-vs-head mesure la variance de la generation, pas une perte, et restaurer l'ancien texte a la main pour verdir le garde fabriquerait un artefact de run (interdit, Stop & Repair). Le predicat exige le nom canonique ET une trace papermill dans metadata -- pas path-based aveugle : un fichier edite a la main qui porterait le nom sans etre execute par papermill reste verifie. Verification sur donnees reelles (issue #15349) : la cellule markdown la plus grosse de l'artefact fait 2830c normalises -- la valeur mesuree dans l'issue -- et un retrecissement de regen produit un TRUNCATED_CELL reel a la base sans le fix ; le predicat reconnait le vrai fichier. 65+47 tests verts, compileall PASS. Co-Authored-By: Claude-Code <noreply@anthropic.com>
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
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 |
|
Grain tag obligatoire (#10045, bloquant).
Pour passer ce gate, le body doit porter en tete une ligne de la forme : Le |
myia-ai-01
left a comment
There was a problem hiding this comment.
APPROVED — revue source-grounded du head f2065128165d1258e4ad0e999b76a48f9170c4ca.
Le fix est borné et conforme au design-gate de #15349 : l'exemption exige à la fois le nom canonique unique Notebook-Generated.ipynb et une trace Papermill au niveau notebook. Le générateur sauvegarde cet artefact puis l'exécute in-place ; l'artefact courant porte bien les métadonnées Papermill notebook et cellule. Les contrôles négatifs maintiennent la vérification pour le nom canonique sans Papermill et pour tout autre nom avec Papermill. La limite « une édition manuelle post-exécution conserverait la metadata » est réelle, mais elle ne constitue pas une régression de cette PR : #15349 décide précisément de sortir cet artefact généré unique de la comparaison pédagogique base/head, pas d'établir une provenance cryptographique du contenu.
Le diff reste atomique (détecteur + tests), sans notebook ni secret ; 65 tests ciblés, 47 tests frères et compileall sont annoncés, Scripts Tests (CPU) et le required PR gate du head sont verts, aucun thread inline ni autre review n'est présent.
J'ai corrigé le body-only sans toucher au head : le tag est maintenant en première ligne et requalifié selon le litmus en Grain: LIGHT/guard -- lane myia-po-2023:CoursIA -- prev: MED/notebook-python #15301. Cette approval valide la substance. Le merge reste séparément HOLD G-VAR-2 jusqu'au prochain budget UTC ; aucun push ni update-branch n'est demandé.
|
[OVERRIDE] lane myia-po-2023:CoursIA — requalification et décision G-VAR mesurées par le coordinateur. Le litmus réel classe cette PR en La PR est toutefois tenue depuis la journée UTC précédente. Le protocole interdit de garder une LIGHT saine plus d’une journée : passé 24 h, elle doit merger ou être fermée avec remplaçant. Je retiens le merge, car le correctif borné est validé (65 tests ciblés, 18 checks exact-head acceptables, B.0 propre) et fermer jetterait un défaut confirmé sans remplaçant. Cette exception est explicite ; elle ne rend pas de budget LIGHT à la lane et le résiduel G-VAR-2 demeure visible. Le head |
|
G-VAR-3 : deux grains LIGHT du meme genre consecutifs -- bloquant (#11170). G-VAR-3: guard succede a guard -- deux grains LIGHT consecutifs pour la lane myia-po-2023:CoursIA. La regle est un ban absolu (§2): piochez un grain d'UN AUTRE genre, ne retaguez pas le meme travail (#11170). Tenu > 24 h : le coordinateur tranche par variation-protocol.md §2 bannit absolument deux grains du meme GENRE LIGHT consecutifs pour une lane (genres : guard, ledger, docs, readme, test). Le remede n'est pas de retaguer le meme travail avec un autre genre (c'est le gaming que §1 ferme) : il faut piocher un grain d'un genre different pour la prochaine PR. Pour passer ce gate, remplacez la |
… absorbe Cas D) Voie (b) retenue après comparaison firsthand : - #15101 a absorbé la structure pédagogique Cas D (`voisins_apres_extension`, `entrainer_exo` sur main restent comme stubs d'exercice). - Le résidu non déterministe cellule 8 (`paires = list(paires)`) reste réel sur main — c'est le seul défaut source. Geste : 1. Rebase origin/main (0 conflit, branche à lane unique) — absorbe #15413, #15355, #15439, #15367, #15451, #15075, #15450, #15417, #15283, #15378, #15360, #15432. 2. Restauration du notebook depuis origin/main (cellules Cas D byte-identiques avec `voisins_apres_extension` / `entrainer_exo` tels que sur main). 3. Application du seul delta source : `paires = list(paires)` → `paires = sorted(paires)` (cellule 8). Pas de cellule `def experience()` ajoutée (le scope #15101 l'absorbe). 4. Run All Papermill complet sur le kernel python3 (Python 3.13) — 13/13 cellules code exécutées, 0 erreur, 0 machine path, 0 output-failure ratchet. Preuves H.4 : - perte époque 1 = 2.824 → époque finale = 2.25 (cohérent c.410) - voisins APRÈS tarte `(carotte, chocolat, confiture, fraises, fromage)` (reproductibilité bit-à-bit post-rebase confirmée) - voisins APRÈS ordinateur `(calcul, billet, mémoire, orage, logiciel)` - cos(tarte_pommes, tarte_fraises) = 0.695 (transformer contextuel) Périmètre strict : 1 fichier, +38/-60 (le solde vient de la sérialisation JSON des outputs Papermill + le patch cellule 8). delta source = 1 ligne. Tells NEW : - `import re` LOCAL en 1ère ligne corps de fonction autonome (c.408). - `list(set(paires))` n'est pas la seule source de non-déterm ; sur main, cellule 8 porte `paires = list(paires)` sur un `set` puis itère en sortie — `sorted(paires)` est l'ordre lex stable (c.410). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
…autoporteurs (G06 cas D) (#15415) * fix(audit,G06,cas-D,#15041,#15035): experience autonome par appel explicite - Ajoute fonction experience(D,K,mots_cuisine) encapsulant corpus+paires+entrainement - Exercice 1 : stub nouveaux_mots + appel experience(mots_cuisine=...) - Exercice 2 : stub D_exo/K_exo + appel experience(D=...,K=...) - Conserve cellules originales (corpus, entrainement, voisins) - Cellules inoffensives (pas de raise, pas d'execution auto) Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai> * fix(audit,G06,cas-D,#15041,#15035): relay -- enonces restaures, stubs dedupliques Run Vibe 18:39Z : experience(D,K,mots_cuisine) parametree + stubs autoportores livres propres, MAIS les enonces markdown des exercices 1/2 avaient ete remplaces par les nouvelles cellules code (perte du texte pedagogique et du header ## 8. Exercices) et les vieux stubs (voisins_apres_extension, entrainer_exo) restaient en place -> duplication : deux cellules "Exercice 1" contradictoires. Relay po-2025 : - enonces 1/2 restaures depuis la base ba99b72, ancres adaptees (voisins_apres_extension -> experience(mots_cuisine=...), entrainer_exo -> experience(D=..., K=...)) - vieux stubs supprimes : logique integralement couverte par experience() parametree - coquille run ("mots_cuisine additions") corrigee - revalide : prefixe/suffixe byte-identiques a la base, compile() par cellule, newlines reels, C.1 inoffensif Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Fix: H.3/C.2 #15415 -- re-execution locale Papermill des 3 cellules code 3 cellules code (24, 26, 28) portaient execution_count=null : - cell 24 : def experience(D=50, K=5, mots_cuisine=None) - cell 26 : Exercice 1 stub (appels commentes) - cell 28 : Exercice 2 stub (D_exo, K_exo + appels commentes) Toutes C.1 conformes (inoffensives a l'execution). Re-exec Papermill python3 (kernel python3, 90s, 14/14 SUCCESS, 0 erreur, 0 machine_path, max exec_count=14). Substance byte-identique : 0 diff markdown, 0 diff code vs base. Le +549/-297 du diff GitHub = reformat nbformat indent=1 + outputs serialises. Ref: #15415 (Vibe G06 cas D #15041 #15035) Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * fix(notebook,#15415): import re LOCAL dans experience() + sorted(paires) REPAIR post-CHANGES_REQUESTED ai-01 (verbatim DM msg-20260910T165620-lh8g68) : 1. def experience() porte maintenant `import re` LOCAL en première ligne du corps (avant `import math` / `import numpy as np`), levant le défaut « tokeniser() appelle re.findall(...) sans import re dans le corps ». 2. paires = list(paires) -> paires = sorted(paires) : ordre SGD désormais déterministe (les seeds RandomState(42/1) ne suffisaient pas à garantir la reproductibilité car list(set(...)) itérait dans un ordre hash dépendant de l'environnement). sorted() rend l'ordre lexicographique sur les tuples (phrase[i], phrase[j]). 3. Re-exécution complète 14/14 cellules Papermill 46.7 s, 0 erreur, 0 machine path, 0 output-failure ratchet. Outputs réels rechargés. Périmètre strict 1 fichier (Tell c.547), catalogue intact (Tell c.1502). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * fix(notebook,#15415): etendre sorted(paires) a cellule 8 + re-exec Papermill REPAIR c.410 — extension du fix c.408 (qui n'avait touché que cellule 23) : 1. Cellule 8 patchée : paires = list(paires) -> paires = sorted(paires). Le fix c.408 sur cellule 23 (experience()) etait incomplet : la cellule 8 (section 4 du notebook, qui produit perte et voisins des sections 3-5) portait encore list(paires), source de non-reproductibilite inter-runs non détectée au c.408. 2. Re-exécution Papermill end-to-end (kernel python3, 14/14 cellules, 0 erreur, ~33 s), 2 runs successifs : reproductibilité BIT-À-BIT vérifiée sur l'ensemble des outputs (perte, voisins, cosinus transformer). 3. Rechargement des outputs réels dans le notebook source. 4. Conversion CRLF -> LF (1716 occurrences, Tell c.423 pre-commit CRLF rollback silencieux) — vérifié raw.count(b'\r\n') == 0. Correction de claim c.408 : le body affirmait "identique bit-à-bit au pre-fix", ce qui était factuellement incorrect — sorted() change la trajectoire SGD (perte initiale 3.119 -> 2.824, voisins changent). Le claim correct et démontrable est "reproductibilité bit-à-bit entre runs successifs post-fix", vérifiée par 2 Papermill end-to-end. Périmètre strict 1 fichier (Tell c.547), catalogue intact (Tell c.1502). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * fix(notebook,#15415): sorted(paires) cellule 8 — voie (b) ai-01 (#15101 absorbe Cas D) Voie (b) retenue après comparaison firsthand : - #15101 a absorbé la structure pédagogique Cas D (`voisins_apres_extension`, `entrainer_exo` sur main restent comme stubs d'exercice). - Le résidu non déterministe cellule 8 (`paires = list(paires)`) reste réel sur main — c'est le seul défaut source. Geste : 1. Rebase origin/main (0 conflit, branche à lane unique) — absorbe #15413, #15355, #15439, #15367, #15451, #15075, #15450, #15417, #15283, #15378, #15360, #15432. 2. Restauration du notebook depuis origin/main (cellules Cas D byte-identiques avec `voisins_apres_extension` / `entrainer_exo` tels que sur main). 3. Application du seul delta source : `paires = list(paires)` → `paires = sorted(paires)` (cellule 8). Pas de cellule `def experience()` ajoutée (le scope #15101 l'absorbe). 4. Run All Papermill complet sur le kernel python3 (Python 3.13) — 13/13 cellules code exécutées, 0 erreur, 0 machine path, 0 output-failure ratchet. Preuves H.4 : - perte époque 1 = 2.824 → époque finale = 2.25 (cohérent c.410) - voisins APRÈS tarte `(carotte, chocolat, confiture, fraises, fromage)` (reproductibilité bit-à-bit post-rebase confirmée) - voisins APRÈS ordinateur `(calcul, billet, mémoire, orage, logiciel)` - cos(tarte_pommes, tarte_fraises) = 0.695 (transformer contextuel) Périmètre strict : 1 fichier, +38/-60 (le solde vient de la sérialisation JSON des outputs Papermill + le patch cellule 8). delta source = 1 ligne. Tells NEW : - `import re` LOCAL en 1ère ligne corps de fonction autonome (c.408). - `list(set(paires))` n'est pas la seule source de non-déterm ; sur main, cellule 8 porte `paires = list(paires)` sur un `set` puis itère en sortie — `sorted(paires)` est l'ordre lex stable (c.410). Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> * fix(notebook,#15415): strip stale metadata.papermill block (Papermill ratchet) Le ratchet `check_papermill_ratchet.py` a échoué en CI sur le head 7018117 (run 34519773585 step 4 Ratchet check FAILURE) avec le message exact : > outputs/execution_count changed but the metadata.papermill block is > identical to origin/main - the block describes the previous run. Le bloc metadata.papermill pointait `start_time: 2026-09-08T15:27:32.959292` (durée 101s) — un run antérieur à c.413, NON réécrit par l'exécution c.413 (Tell c.402 L1 ★★★ sustained : Papermill via subprocess Windows peut ajouter metadata.jupyter.source_hidden=true sans réécrire correctement metadata.papermill si l'exécuteur n'est pas Papermill CLI). Solution appliquée (explicitement autorisée par check_papermill_ratchet.py : "block absent at head (removed - explicitly allowed)") : strip du bloc `metadata.papermill` au niveau nb + 30 cellules. Périmètre strict : -225/+1 lignes, **uniquement** des blocs metadata.papermill supprimés. Aucune modification du source code : - cellule 2 : `import re` module-level (c.408 résolu) ✓ - cellule 8 : `paires = sorted(paires)` (voie (b) ai-01) ✓ - cellules 24/26 (voisins_apres_extension, entrainer_exo) : byte-identiques à origin/main (Cas D #15101 préservé) ✓ Validation locale : - check_papermill_ratchet.py origin/main → BLOCK_REMOVED, 0 régression ✓ - check_output_failure_text.py origin/main → 0 TOOL_FAILURE, 0 MACHINE_PATH ✓ - validate_pr_notebooks.py → PASS ✓ - 13/13 cellules code `execution_count != None` ✓ Reproductibilité bit-à-bit : la démo H.4 c.410 reste valide (deux Papermill end-to-end successifs, perte 2.824→2.25, voisins tarte identiques). Le strip metadata ne touche aucun output, donc les preuves H.4 sont préservées telles quelles. Voir : c.410 (REPAIR), c.411 (LIVRAISON RECENTE chevauchement #15101), c.412 (escalade ai-01 voie (b)), DM `msg-20260910T184936-s7q6i5`. Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Mistral Vibe <vibe@mistral.ai> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Grain: LIGHT/guard — lane myia-po-2023:CoursIA — prev: MED/notebook-python #15301
Résumé
Closes #15349 — le garde
detect_md_content_loss.py(noyau du grain #12396) refuse la régénération légitime de l'artefact de runSemanticKernel/Notebook-Generated.ipynb: son markdown est une sortie non déterministe du LLM du run (la conversation multi-agents de 10b écrit les cellules à chaque exécution — précédent de commit paire outputs+artefact #12627). Le garde mesurait la variance de la génération (Titanic → transformation de données : cell 0, 2830 → 1455 caractères, ratio 0,514 < 0,75 ; motif « Prerequis » base=2) comme une perte de contenu — et la seule issue était de fabriquer l'artefact à la main (interdit, Stop & Repair).Correction (piste 1 de l'issue, design-gate approuvé en review) : exemption additive, non path-blind — le prédicat
_is_generated_artifact()exige à la fois le nom canonique (GENERATED_ARTIFACT_NAMES, un seulNotebook-Generated.ipynbdans le dépôt) et une trace d'exécution Papermill dansmetadata(un vrai artefact de run est exécuté in-place). Un notebook édité à la main qui porterait le nom sans trace Papermill reste vérifié — on ne dispense pas un fichier au seul motif de son nom. L'artefact exempté est traité comme un fichier nouveau (rien à comparer base→head).Périmètre
Deux fichiers du dépôt, tous deux sous
scripts/notebook_tools/: le gardedetect_md_content_loss.py(+85 lignes : constante, prédicat, intégration au parcours, docstring d'en-tête §9) et son fichier de teststests/test_detect_md_content_loss.py(classeTestGeneratedArtifactajoutée). Aucun notebook, aucun workflow, aucune autre famille touchée.Validation
pytest scripts/notebook_tools/tests/test_detect_md_content_loss.pyau headf206512816: 65 passed (relancés firsthand ce jour en worktree jetable).TestGeneratedArtifact— les cinq tests ajoutés couvrent : exemption effective (test_generated_artifact_exempted), sortie--checkexit 0 sur le scénario de l'issue (test_generated_artifact_main_exits_0), trace Papermill exigée (test_generated_artifact_needs_papermill_trace), nom seul insuffisant (test_non_generated_name_not_exempt), prédicat unitaire (test_predicate_unit).Choix de design consigné
Pistes 2 (désactiver base→head sur reconnaissance de sortie de run) et 3 (décider que les artefacts de run ne se commettent plus — supersession de #12627) sont écartées dans ce grain : la piste 1 règle le défaut immédiat avec le prédicat le plus étroit ; la piste 3 est une décision de périmètre distincte qui, si elle se prend un jour, supersèdera celle-ci explicitement.
Review
APPROVED ai-01 au head
f206512816(revue source-grounded : « l'exemption exige à la fois le nom canonique unique et une trace Papermill »). Le présent body répare l'unique réserve mécanique restante (body vide → gateGrain:bloquant, c. 21:27Z) ; le diff est inchangé depuis la review.🤖 Generated with Claude Code