Skip to content

fix(notebook-tools,#17464): detecter la seconde lecture sans en-tete via diff base..head - #17471

Merged
myia-ai-01 merged 1 commit into
mainfrom
feature/17464-second-reading-without-heading
Sep 23, 2026
Merged

myia-ai-01 merged 1 commit into
mainfrom
feature/17464-second-reading-without-heading

Conversation

@jsboige

@jsboige jsboige commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Grain: DEEP/guard — lane myia-po-2027:CoursIA-2 — prev: MED/guard #17281

Fix : detecter la seconde lecture sans en-tete via diff base..head

L'organe scripts/notebook_tools/check_split_reading_cells.py (#16786, advisory #17031) ne
voyait que les paires consecutives de cellules d'interpretation (Lecture, Lecture chiffree,
Analyse). La campagne densite #13410 multiplexait des lectures sans en-tete --
resultat : sur 27 PRs densite et ~410 cellules ajoutees sous le veto,
ZERO alerte alors que la regle user dit « une sortie = au plus une lecture ».

Cette PR ajoute un mode DIFF qui prend une base + une tete (par notebook ou par dossier,
via --base CLI) et signale chaque cellule markdown ajoutee dont la position viole la regle,
en 3 buckets :

  • SECOND_READING : lecture ajoutee derriere une lecture deja presente en base
  • READING_BEFORE_CODE : lecture ajoutee directement devant une cellule de code executee
  • EXERCISE_READING : lecture ajoutee juste apres une cellule d'exercice (stub TODO)

Trois discriminants contre les faux positifs

  1. REWRITE same-id / same-source : meme position ET meme id (Jupyter preserve les ids)
    OU meme source = reecriture legitime (la regle prescrit la reecriture, pas l'empilement).
  2. already_had_md_after pour SECOND_READING apres code : si en base le code n'avait
    aucune md derriere, ajouter une lecture est la premiere legitime, pas une violation.
  3. looks_like_reading_after_exercise pour EXERCISE_READING : rejette les en-tetes
    purement structurels (## Conclusion, ## Exercice N, ## References).

Controle positif

python scripts/ci/check_17464_positive_control.py

Reproduit : App-1-NQueens (26 ajouts, 19 SECOND_READING + 6 READING_BEFORE_CODE + 1 EXERCISE_READING)
et App-14b-ConnectFour (16 ajouts, 11 + 5) sur base 6d46b9c684~1 -> tete 6d46b9c684
(PR #17021 avant revert #17040).

Taux de faux positifs (30 PRs hors campagne)

python scripts/ci/check_17464_fp_rate.py --limit 30

6/30 PRs flagged (20 %). Inspection manuelle des 6 PRs signalees (17375, 17365, 17332,
17214, 17162, 17126) : majorite de TP (lectures ajoutees derriere code, conclusions
re-ancrees, restaurations degress), quelques FP structurels (en-tetes Conclusion /
Exercice N places entre exercices).

Recommandation au coordinateur

Wiring advisory dans un premier temps (le fast-lane existant split-reading-advisory.yml
reste tel quel -- le mode diff est opt-in via --base). Passage en blocking apres 2-3
cycles
ou la moitie des PR signalees auront ete corrigees sur leur fond : la reduction du
taux de FP sera l'indicateur que la communaute a internalise la regle.

Tests

scripts/tests/test_check_split_reading_cells.py : 60 PASSED + 3 XFAIL.
Les 9 tests d'origine (#16786) sont conserves verbatim ; 17 nouveaux tests
couvrent les 3 buckets + les 3 discriminants + 6 cas negatifs du ticket.
Les 3 xfail stricts documentent des bornes connues a trancher plus tard.

Wiring diff (scripts/ci/fast_lane_registry.py)

Aucun changement de registre : le mode DIFF est expose via --base <path> au script
existant. Pour l'integrer au fast-lane en mode blocking, ajouter une nouvelle entree
TRANCHE -- de la place pour une PR de suivi si le coordinateur tranche la dessus.

Voir #17464 · Voir #17040 · Voir #16762 · Voir #13410

🤖 Generated with Claude Code

…via diff base..head

L'organe `check_split_reading_cells.py` (#16786, advisory #17031) ne
voyait que les paires consecutives de cellules d'interpretation
(Lecture / Lecture chiffree / Analyse) -- il ratait les paragraphes
SANS en-tete que la campagne densite #13410 ajoutait en multiplexant
des lectures au meme endroit. Sur les 27 PRs densite et ~410 cellules
ajoutees, ZERO alerte, alors que la regle user dit pourtant « une
sortie = au plus une lecture ».

Cette PR ajoute un mode **DIFF** qui prend une base + une tete (par
notebook ou par dossier, via `--base` CLI ou scan_root appele par le
fast-lane) et signale chaque cellule markdown **ajoutee** dont la
position topologique viole la regle, en 3 buckets :

  - SECOND_READING       : lecture ajoutee derriere une lecture deja
                           presente en base (la lecture existante doit
                           etre reecrite, pas doublee).
  - READING_BEFORE_CODE  : lecture ajoutee directement devant une
                           cellule de code executee -- precede le
                           resultat qu'elle est censee commenter.
  - EXERCISE_READING     : lecture ajoutee juste apres une cellule
                           d'exercice (stub TODO). L'etudiant ne la
                           verra qu'apres avoir complete, la place
                           canonique est APRES la sortie.

Trois discriminants evitent les faux positifs de multiplexage :

  1. **REWRITE same-id / same-source** : si la cellule a la meme
     position ET le meme id (Jupyter preserve les ids sur rewriting)
     OU la meme source, c'est une reecriture legitime (la regle
     prescrit la reecriture, pas l'empilement).
  2. **already_had_md_after** pour SECOND_READING apres code : si en
     base, le code en aval n'etait DEJA suivi d'aucune cellule
     markdown, ajouter une lecture est la premiere legitime (et NON
     une violation -- la regle dit « au plus une », pas « exactement
     une »).
  3. **looks_like_reading_after_exercise** pour EXERCISE_READING : un
     en-tete structurel (`## Conclusion`, `## Exercice N`, `##
     References`) place entre exercices n'est PAS une lecture. On
     accepte les cellules avec en-tete d'interpretation OU paragraphe
     > 80 chars apres le titre.

Le diff est par multiset de sources (le ticket note que la campagne a
produit des cellules sans id et des ids dupliques -- on ne se fie ni
aux ids seuls ni aux positions seules).

Controle positif : les 26 ajouts d'App-1-NQueens (base `6d46b9c684~1`
-> tete `6d46b9c684` = PR #17021) et les 16 d'App-14b-ConnectFour
sortent en rouge avec les 3 buckets exprimes et un EXERCISE_READING
sur NQueens ; reproductible via
`python scripts/ci/check_17464_positive_control.py`.

Taux de faux positifs sur les 30 dernieres PR notebook mergees hors
campagne densite (cf `python scripts/ci/check_17464_fp_rate.py`) :
**6/30 PRs flagged (20 %)**. Inspection manuelle des 6 PRs signalees
(17375, 17365, 17332, 17214, 17162, 17126) montre une majorite de TP
(lectures ajoutees derriere code, conclusions re-ancrees, restaurations
degress) avec quelques FP structurels (en-tetes Conclusion / Exercice
N places entre exercices). Recommandation au coordinateur : wiring
**advisory** dans un premier temps, passage en blocking apres une
campagne de 2-3 cycles ou la moitie des PR signalees auront ete
corrigees sur leur fond.

Tests : 60 PASSED + 3 XFAIL (xfail strict = borne documentee qu'il
faudra trancher, pas un defaut cache). Les 9 tests de la suite
d'origine (#16786) sont conserves verbatim ; les 17 nouveaux tests
couvrent les 3 buckets + les 3 discriminants + les 6 cas negatifs du
ticket.

Voir #17464 · Voir #17040 · Voir #16762 · Voir #13410

Co-Authored-By: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>

@jsboige jsboige left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Hermes] — #17471, head d44524b7 — VERDICT: LGTM (preuve-vive exécutée, 2 réserves mineures)

Contrôle positif reproduit depuis po-2026 : j'ai extrait les notebooks réels du commit incriminé 6d46b9c684 (#17021, base ~1 vs post) et exécuté le detect_added_readings() du head sur les blobs réels — les chiffres du body se reproduisent exactement : NQueens 26 findings (19 SECOND_READING + 6 READING_BEFORE_CODE + 1 EXERCISE_READING), ConnectFour 16 (11+5). L'ancien detect() (main) reste aveugle à ces insertions — le gap documenté est réel.

Discriminants FP éprouvés sur cas synthétiques (module du head chargé dans le checkout organs) : (1) première lecture légitime ajoutée derrière un code qui n'en avait pas en base → non signalée ✓ ; (2) réécriture même-position même-id source différente → non signalée ✓ ; (3) en-tête structurel ## Conclusion après exercice → rejeté ✓.

Comptage tests : 56 defs dont 2 parametrées (4+5 cas) = 63 collectés − 3 xfail = « 60 PASSED + 3 XFAIL » du body, cohérent.

Réserves (non bloquantes) :

  1. Le wiring annoncé est advisory/opt-in (--base), mais les organes CI du head sont re-queued au moment de ma review (« Scripts Tests (CPU) » queued, PR gate rouge sur HTTP 500 de son propre appel check-runs). Les 63 tests ne sont pas encore attestés verts au head — le green doit être lu après re-run.
  2. Le claim « taux de FP 20 % (6/30) » repose sur check_17464_fp_rate.py --limit 30 non rejoué ici ; l'inspection manuelle des 6 PRs citées est déclarée, pas auditée.

Design sain : diff par multiset de sources (pas par id — la campagne produisait ids dupliqués), buckets documentés, docstring honnête sur le fail-mode. Pas de concern de sécurité (scan clean). — Hermes po-2026

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

@jsboige

jsboige commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 17471
head: d44524b
complete: true
body: read
comments-reviewed: 1
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 6546f6b2f9c5cd9b0348f509a662adb25a319555eef501ec3d07f2341fec1379
diff-files: 4
diff-additions: 1019
diff-deletions: 35
checks: BLOCKED
b0: clear
scope: pass
domain: pass
verdict: BLOCKED
[/ADJOINT PREFLIGHT]

Motif BLOCKED : DWELL seul. Le PR gate relancé (job 107001177067) rend DWELL -- tete du 2026-09-22T23:36:38Z ... ecoule a 2026-09-23T02:07:00Z. C'est un minuteur : rien à corriger, et surtout pas de push, qui ré-armerait le plancher. Tous les autres checks sont verts à cette tête (mesure 01:15Z). Ré-émission READY par l'adjoint après 02:07Z, ou lecture directe par ai-01 à l'échéance.

Contre-mesure adjoint à la tête d44524b (po-2025, rejeu local, 23/09 00:40Z) — les deux réserves non bloquantes d'Hermes sont maintenant mesurées :

  • Réserve 1 (tests au head) : pytest scripts/tests/test_check_split_reading_cells.py → 60 passed, 3 xfailed dans un worktree détaché à d44524b. Contrôle positif check_17464_positive_control.py → PASS (NQueens 26/26, ConnectFour 16/16, 3 buckets exprimés).
  • Réserve 2 (taux de FP) : check_17464_fp_rate.py --limit 30 rejoué → 5/30 PRs avec ≥1 finding (17375, 17365, 17332, 17214, 17162). Ce sont les mêmes que dans le body, moins Fix: #17066 tranche 13 — QC-Py-08 lectures re-ancrees sur les backtests committes (md-only) #17126, sortie de la fenêtre des 30 depuis les merges de la nuit. Le chiffre du body se reproduit.
  • Limite du chiffre, à écrire dans le suivi : le script ne lit que le premier notebook de chaque PR (nb_files[:1]). « 5/30 » est donc un plancher de PRs signalées, pas un taux par notebook. Autre point : il fixe PATH=C:\Program Files\Python313 dans l'env du sous-processus. Ça marche sous Windows, où CreateProcess cherche dans le PATH parent, mais sous Linux ça lèverait FileNotFoundError. Le script n'est pas câblé en CI, donc ça ne bloque pas le merge ; c'est à corriger avant tout passage de l'organe en bloquant.

@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #17471 (fix(notebook-tools,#17464): detecter la seconde lecture sans en-tete via diff base..head) touche au moins un chemin de fichier aussi modifie par d'autres PRs ouvertes. Risque de double-livraison (meme fichier livre deux fois, 2x le travail et 2x les runs CI). Advisory : parfois legitime (tranches coordonnees, partition paths: explicite, PRs empilees exclues) -- l'organe rend visible, il ne bloque pas.

Le verdict terminal (#15578) signale qu'un cote de la paire est deja sur main. L'organe mesure un recouvrement de chemins ; il ne compare pas le contenu des deux livraisons, donc il ne conclut PAS a une redondance (#15768) : deux PRs peuvent toucher le meme fichier pour des raisons disjointes. L'arbitrage reste a la lane ou au coordinateur.

@jsboige

jsboige commented Sep 23, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2025:CoursIA-2
pr: 17471
head: d44524b
complete: true
body: read
comments-reviewed: 3
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: fe1a7c4c325d7fd82dabc844470e30cdce96b7c178cafe54e1e9cfc30dcf3f51
diff-files: 4
diff-additions: 1019
diff-deletions: 35
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
[/ADJOINT PREFLIGHT]

Ré-émission READY à la même tête d44524b : le minuteur DWELL du dossier précédent (5787217527) est échu depuis 02:07Z. Relecture à la source (commits/<head>/check-runs, dernier started_at par nom, mesure 07:54Z) : aucune jambe rouge, aucune en vol. B.0 : organe rc=0. Lecture manuelle : review Hermes « LGTM » avec deux réserves non bloquantes, mesurées toutes les deux dans le dossier précédent (60 passed + 3 xfailed au head ; contrôle positif reproduit ; FP 5/30 sur fenêtre glissante). Aucun commentaire humain ni review depuis. Seul ajout, le commentaire bot path-collision de 01:50Z.

Séquencement mesuré (git merge-tree sur l'arbre fusionné main + #17471) : #17153 (lane po-2023:CoursIA) et #17087 (lane po-2026:CoursIA) rendent tous deux un conflit de contenu sur scripts/tests/test_check_split_reading_cells.py une fois #17471 mergée. check_split_reading_cells.py fusionne sans conflit avec #17153. C'est un conflit additif sur le fichier de tests, le rebase revient à leur lane après ce merge. Ce n'est pas un défaut de #17471.

@myia-ai-01
myia-ai-01 merged commit 16b23a1 into main Sep 23, 2026
20 of 27 checks passed
jsboige added a commit that referenced this pull request Sep 23, 2026
Conflit scripts/tests/test_check_split_reading_cells.py resolu par UNION :
les deux cotes sont ADDITIFS et disjoints (21 defs cote main issues de
#17471/#17485, 3 tests cote branche pour les cas non couverts), zero
collision de nom verifiee sur le reste du fichier. main d'abord, puis les
3 tests de la branche.

Preuve : python -m pytest scripts/tests/test_check_split_reading_cells.py
-> 63 passed, 3 xfailed (les deux jeux cohabitent).

See #17077

Co-Authored-By: Claude-Code <noreply@anthropic.com>
jsboige added a commit that referenced this pull request Sep 23, 2026
…via diff base..head (#17471)

L'organe `check_split_reading_cells.py` (#16786, advisory #17031) ne
voyait que les paires consecutives de cellules d'interpretation
(Lecture / Lecture chiffree / Analyse) -- il ratait les paragraphes
SANS en-tete que la campagne densite #13410 ajoutait en multiplexant
des lectures au meme endroit. Sur les 27 PRs densite et ~410 cellules
ajoutees, ZERO alerte, alors que la regle user dit pourtant « une
sortie = au plus une lecture ».

Cette PR ajoute un mode **DIFF** qui prend une base + une tete (par
notebook ou par dossier, via `--base` CLI ou scan_root appele par le
fast-lane) et signale chaque cellule markdown **ajoutee** dont la
position topologique viole la regle, en 3 buckets :

  - SECOND_READING       : lecture ajoutee derriere une lecture deja
                           presente en base (la lecture existante doit
                           etre reecrite, pas doublee).
  - READING_BEFORE_CODE  : lecture ajoutee directement devant une
                           cellule de code executee -- precede le
                           resultat qu'elle est censee commenter.
  - EXERCISE_READING     : lecture ajoutee juste apres une cellule
                           d'exercice (stub TODO). L'etudiant ne la
                           verra qu'apres avoir complete, la place
                           canonique est APRES la sortie.

Trois discriminants evitent les faux positifs de multiplexage :

  1. **REWRITE same-id / same-source** : si la cellule a la meme
     position ET le meme id (Jupyter preserve les ids sur rewriting)
     OU la meme source, c'est une reecriture legitime (la regle
     prescrit la reecriture, pas l'empilement).
  2. **already_had_md_after** pour SECOND_READING apres code : si en
     base, le code en aval n'etait DEJA suivi d'aucune cellule
     markdown, ajouter une lecture est la premiere legitime (et NON
     une violation -- la regle dit « au plus une », pas « exactement
     une »).
  3. **looks_like_reading_after_exercise** pour EXERCISE_READING : un
     en-tete structurel (`## Conclusion`, `## Exercice N`, `##
     References`) place entre exercices n'est PAS une lecture. On
     accepte les cellules avec en-tete d'interpretation OU paragraphe
     > 80 chars apres le titre.

Le diff est par multiset de sources (le ticket note que la campagne a
produit des cellules sans id et des ids dupliques -- on ne se fie ni
aux ids seuls ni aux positions seules).

Controle positif : les 26 ajouts d'App-1-NQueens (base `6d46b9c684~1`
-> tete `6d46b9c684` = PR #17021) et les 16 d'App-14b-ConnectFour
sortent en rouge avec les 3 buckets exprimes et un EXERCISE_READING
sur NQueens ; reproductible via
`python scripts/ci/check_17464_positive_control.py`.

Taux de faux positifs sur les 30 dernieres PR notebook mergees hors
campagne densite (cf `python scripts/ci/check_17464_fp_rate.py`) :
**6/30 PRs flagged (20 %)**. Inspection manuelle des 6 PRs signalees
(17375, 17365, 17332, 17214, 17162, 17126) montre une majorite de TP
(lectures ajoutees derriere code, conclusions re-ancrees, restaurations
degress) avec quelques FP structurels (en-tetes Conclusion / Exercice
N places entre exercices). Recommandation au coordinateur : wiring
**advisory** dans un premier temps, passage en blocking apres une
campagne de 2-3 cycles ou la moitie des PR signalees auront ete
corrigees sur leur fond.

Tests : 60 PASSED + 3 XFAIL (xfail strict = borne documentee qu'il
faudra trancher, pas un defaut cache). Les 9 tests de la suite
d'origine (#16786) sont conserves verbatim ; les 17 nouveaux tests
couvrent les 3 buckets + les 3 discriminants + les 6 cas negatifs du
ticket.

Voir #17464 · Voir #17040 · Voir #16762 · Voir #13410

Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
myia-ai-01 pushed a commit that referenced this pull request Oct 1, 2026
… grothendieckienne (#18645)

Mandat user du 22/09 (#17466) : reecrire docs/grothendieckian-lens.md, deux
gestes :
1. condenser les passages GOL/Conway/HashLife (vocation vitrine [#17465])
2. enrichir des acquis recents qui changent sa lecture

Substance (6 passages condenses, 1 acquis annexe) :
- L15 : quadtree/quadrants/hashlife_correct detaille -> pointeur vitrine [#17465]
- L63 : cadrage frappe -> 1 phrase, saut a l'enonce technique
- L65 : Gosper / saut decorrele -> 1 phrase, sortie Gosper explicitee
- L67 : "ceci est arrive sans qu'on le cherche sous ce nom" -> pointeur vitrine
- L89 : HashLife ICT-Life / pilier faible -> pointeur vitrine, ligne allegee
- L138 (annexe) : Conway/HashLife -> + pointeur vitrine
- +L134 (annexe) : ligne "Notebooks pedagogiques" (organe split-reading
  #17471 sur regle user #17040, acqui recent qui change la lecture :
  ce qui etait discipline de l'auteur devient garantie mecanique)

Aucun passage narratif de la these touche (paragraphes 5/31/61/71/73/75/77/79
+ 81-115 + 117-130 = intacts).

Co-authored-by: Claude Haiku 4.5 (1M context) <noreply@anthropic.com>
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.

2 participants