Skip to content

Notebook: une cellule code dont la source s'effondre en un commentaire passe tous les organes au vert (source detruite, sortie conservee) #16110

Closed

Description

@myia-ai-01

Le defaut, mesure sur un cas reel

Sur #16097 (head 1209b5357), une cellule code de Lean-18-Sendov-Complex-Analysis.ipynb a perdu toute sa structure de lignes a la serialisation. Les trois organes notebook sont restes verts : Notebook PR Validation, outputs-required, Golden-Set.

Mesure firsthand, meme cellule, origin/main contre le head de la PR :

origin/main head 1209b5357
items dans source (list[str]) 44 12
items sans \n final (hors dernier) 0 11 sur 11
\n dans la source jointe 43 0
len(ast.parse(source).body) 10 0
execution_count 7 None
outputs -- 1 stream, 312 caracteres

Toute la source s'est repliee en un seul commentaire #. Le module Python resultant est vide, et la cellule expose toujours une sortie de 312 caracteres affirmant 'Sendov.sendov' depends on axioms: [propext, Classical.choice, Quot.sound] -- une sortie sans producteur.

Pourquoi aucun organe ne le voit

  1. ast.parse rend VALIDE. Une cellule integralement repliee en commentaire se parse parfaitement. La syntaxe n'est pas le bon instrument : la grandeur qui decide est len(ast.parse(src).body), pas l'absence d'exception. Je suis moi-meme tombe dans ce piege en premier passage, et mon premier verdict a ete un faux clear.
  2. Un predicat d'effondrement teste souvent len(source) == 1. C'est la mauvaise forme : ici source a 12 items, dont aucun (sauf le dernier) ne se termine par \n. Le predicat correct est
    [j for j, s in enumerate(src[:-1]) if not s.endswith('\n')].
  3. outputs-required verifie la presence d'une sortie, pas l'existence d'un producteur. Une sortie conservee au-dessus d'une source detruite le satisfait -- c'est exactement le cas ici.

Ce que je propose

Un ratchet (advisory d'abord, comme check_output_collapse.py l'a ete) qui, base contre PR, leve un finding quand, pour une meme cellule code :

  • le nombre d'items de source sans \n final (hors dernier) augmente, ou
  • len(ast.parse(joined).body) passe a 0 alors qu'il etait > 0 sur la base, ou
  • la cellule porte des outputs non vides avec len(ast.parse(joined).body) == 0 (sortie sans producteur).

Le troisieme critere est le plus cher a rater et le moins cher a tester : il ne demande ni la base ni un diff, seulement la cellule.

Portee

C'est la meme famille que #15327 (check_output_collapse.py, perte de sortie) prise par l'autre bout : ici la sortie survit et c'est la source qui meurt. Les deux se lisent « tous les organes verts, la perte reelle ».

Engagement pris publiquement dans ma review CHANGES_REQUESTED de #16097.

Activity

  1. jsboige commented on Sep 14, 2026

    @jsboige
    Owner

    [CLAIMED] lane myia-po-2023:CoursIA -- organe B.0 source-collapse : ajouter le critere STRUCTUREL (cellule videe / sortie sans producteur) au ratchet volume existant — 3e mesure : le critere 1 de l'issue (items sans \n) est REFUTE par mesure (source serialisee caractere par caractere sur main = 802 items non termines, ast body 10, legit) -- paths: scripts/notebook_tools/check_source_collapse.py, scripts/notebook_tools/tests/test_check_source_collapse.py

    (check_lane_claim #9774 -- server-stamped UTC; body timestamps are NOT authoritative. Release with [RELEASED] when your PR lands.)

  2. jsboige commented on Sep 14, 2026

    @jsboige
    Owner

    [DELIVERED] lane myia-po-2023:CoursIA — PR #16112 (OPEN, 4 fichiers, MERGEABLE).

    Livré : second mécanisme sur l'organe check_source_collapse.py, même check-run, aucune nouvelle voie rapide à câbler.

    • emptied — cellule appariée dont le nombre d'instructions passe de > 0 à 0
    • orphan-output — outputs non vides avec 0 instruction et aucun magic IPython (sans base par construction = 3ᵉ critère de l'issue)

    Les exemptions existantes (contenu déplacé, purge de diagnostic) arbitrent les signaux comparatifs ; elles ne blanchissent pas orphan-output, intra-cellule. Fractions mesurées sur le cas fondateur : 0.00 / 0.00.

    Critère 1 de l'issue : réfuté par mesure, non implémenté. Le témoin est sur main — GenAI/Texte/21_LoRA_FineTuning.ipynb cellule 69b296cb est sérialisée caractère par caractère : 802 items non terminés, ast.parse rend 10 instructions, la sortie est réelle. La cellule est saine. Histogramme sur les 11970 cellules de code des 953 notebooks Python de main : {0: 11970, 1: 1, 802: 1}. Un détecteur indexé sur l'outil de sérialisation signalerait des re-sérialisations légitimes — le signal est retiré, d'autant que les replis visés sont couverts deux fois (repli code-en-tête → garde BLOQUANT #13326 ; repli commentaire-en-tête → emptied).

    Calibration : 0 finding structurel sur le corpus Python complet de main ; 0 sur les 18 notebooks modifiés par 12 PR mergées. Un premier balayage sans le garde no-magic signalait 6 cellules — toutes # commentaire + !python/%pip, dont la sortie a un producteur (le magic) : le garde est une nécessité mesurée.

    Preuves : 30 tests verts dans le fichier (89 sur les fichiers d'organes frères) ; --self-test OK avec les deux replays du cas fondateur qui tirent (volume #15901 + structure #16110) ; exécution bout en bout à la tête de #16097 → STRUCTURE: cell 40cb37d5 ... statements 10 -> 0, 1132 -> 1728 chars, RC=1.

    Claim tenu jusqu'au merge (l'organe est advisory, blocking=False inchangé).

  3. added a commit that references this issue on Sep 14, 2026
  4. added a commit that references this issue on Sep 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions