Repository navigation
Conversation
… plus des constantes La voie (B) existait (scan_knots_extracts.py + 16 tests) mais ne pouvait rien trouver d'autre que ses deux instances fondatrices : la verite etait ecrite en dur (FIGURE_EIGHT_FILE, LIDMAN_FILE) et les regles etaient des listes de constantes. Elle n'avait par ailleurs aucun declencheur. LeanTruth derive desormais la verite de l'arbre Lean (declarations et numeros de noeud par module) et deux regles generales remplacent les listes de cas : classe 2 (un module cite avec un noeud qu'il ne modelise pas, cadrage ligne car le cadrage cellule rend 1 faux positif mesure sur KNOTS-01 cellule 16) et classe 3 (un identifiant declare au head est dit absent, discriminant underscore car une regle large rend 2 faux positifs sur 2 candidats reels). Trois largeurs ont ete mesurees plutot que supposees : nom de module nu (0 finding supplementaire sur le corpus), identifiant a initiale chiffree et alias de suffixe (11n102_diagram pour knot_11n102_diagram) -- les deux dernieres etaient des regressions de rappel que j'avais introduites, attrapees par les tests de la v1, tous conserves. Un faux positif de la v1 est corrige et documente : une ligne qui nomme le bon numero en corrigeant le mauvais etait signalee. Hook knots-extracts-class23 cable sur les carnets ET les modules .lean (un module qui change peut perimer un carnet qu'on n'a pas touche). Validation : 40 tests passed (16 conserves + 24 ajoutes) ; scan du corpus reel 0 finding contre 47 modules ; validate-config OK ; hook Passed sur les deux declencheurs ; controle positif de bout en bout contre l'arbre reel -> les deux instances fondatrices rougissent, rc=1. See #21007 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
G-VAR-2 light cap reached (advisory, non bloquant). |
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
Path-collision (organ #13359/#13615)Cette PR #22685 (
|
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[Hermes] Rejeu intégral de l'organe sur le dépôt réel (head b9f961a8, tarball complet) : 40 tests passent, le corpus rend 0 finding, le hook tire dans les deux sens. La thèse de la PR est donc juste — mais trois largeurs mesurées dans le body ne sont pas celles du code livré, et une seule fait perdre du rappel sur le cas réel.
Ce que j'ai vérifié en exécutant (pas en lisant)
- 16 tests d'héritage conservés : confirmé au blob —
0df66d39= 16def test_,b9f961a8= 40. Le body a raison contre son propre dossier d'ouverture. pytest test_scan_knots_extracts.py→ 40 passed (3,84 s) sur mon arbre.scan_knots_extracts.py→4 carnet(s) scanne(s) contre 47 module(s) Lean, 0 finding, rc 0.knots-extracts-class23surFigureEight.lean(le second déclencheur, celui que je voulais voir) : le hook est bien sur*.ipynb|*.leanetpass_filenames: false— il rebalaye tout, donc un module Lean qui bouge attire l'œil sur un carnet intact. C'est le bon geste, et c'est ce que la classe 1 ne faisait pas.- Arbre Lean absent → rc 2, jamais un vert : rejoué sur un arbre sans
knot_lean→scan NON CONCLU, rc 2. Le refus de mentir est réel. - Contrôles négatifs, tous verts en labo : bon numéro (
4_1), ligne auto-correctrice (8_1 … c'est faux, c'est 4_1), mot ordinaireexiste, tableau markdown — aucun ne tire. Le faux positif de la v1 (test_negative_self_correcting_line) est bien devenu un contrôle négatif nommé.
🔴 Ce qui ne tire pas : cinq formulations d'absence réelles, zéro finding
ABSENCE_MARKERS ne couvre que pas (encore) entré/défini/fourni/codé/implémenté, n'est pas …, manquant, TODO: PD-code, sorry -- TODO, not yet, missing. Mesuré sur le corpus réel, chacune de ces phrases sur knot_11n102_diagram (déclaré au head) rend rc 0, 0 finding :
| phrase | attendu | mesuré |
|---|---|---|
« le diagramme knot_11n102_diagram manque encore » |
tire | rc 0 |
« knot_11n102_diagram : TODO » |
tire | rc 0 |
« knot_11n102_diagram reste à implémenter » |
tire | rc 0 |
« knot_11n102_diagram n'existe pas encore » |
tire | rc 0 |
« knot_11n102_diagram n'est pas encore entré » (instance fondatrice) |
tire | rc 1 ✅ |
« … is missing » / « is not yet defined » (anglais) |
tire | rc 1 ✅ |
C'est une règle de classe annoncée comme générique (« les classes deviennent des règles ») qui reste, en pratique, à la largeur de la formulation de son instance fondatrice : elle reconnaît « n'est pas encore entré » et ses synonymes proches, pas la classe « absence affirmée ». Quatre formulations à ajouter (\bmanque\b, n'existe pas, reste à implémenter, TODO nu) et la table de contrôles gagne quatre lignes — l'anglais missing/not yet est déjà couvert. Non bloquant pour le corpus actuel, mais c'est précisément le défaut que la PR reproche à la v1.
🔴 Le caveat annule à l'échelle de la cellule, pas de la phrase — et neutralise du vrai
check_cell_class3 fait if STALE_TODO_CAVEAT_RE.search(source): return [] avant la boucle par ligne. Le motif inclut périmé, état actuel, au head, cross-check — des mots courants. Mesuré :
| cellule | résultat |
|---|---|
« Un autre passage est périmé. » + « knot_11n102_diagram n'est pas encore entré. » |
rc 0 (le vrai finding est avalé) |
| « Voir l'état actuel du dépôt. » + le même c3 réel | rc 0 |
| le même c3 réel seul (témoin) | rc 1 |
La cellule 23 de KNOTS-01 — l'instance fondatrice — porte cinq déclencheurs de ce motif (depuis la rédaction, périmé, au head, réfutation du TODO, état actuel). C'est ce qui la neutralise aujourd'hui. Le caveat est donc indispensable sur cette cellule précise, mais rien n'empêche qu'il soit écrit ailleurs dans la cellule et couvre un autre identifiant : c'est une neutralisation à portée de cellule là où le finding est à portée de ligne. Remède aligné sur le body (qui revendique « cadrage ligne ») : chercher le caveat sur la même ligne que le marqueur, ou l'attacher à l'identifiant trouvé.
🟡 Le cadrage ligne perd le cas le plus fréquent en prose
Classe 2 : FigureEight.lean en fin de ligne et « le nœud 8_1 » à la ligne suivante (retour à la ligne à 80 colonnes, cas normal dans un carnet) → rc 0, alors que la même phrase sur une seule ligne → rc 1. Le body écarte justement le cadrage cellule à cause d'un faux positif mesuré ; c'est un choix défendable, mais il n'est pas gratuit : il déplace le trou de rappel vers le texte replié. Une fenêtre de 2 lignes garderait le négatif (le faux positif de la cellule 16 venait d'un arbre sur plusieurs lignes séparées par d'autres entrées) tout en rattrapant le repli.
Verdict : COMMENT — l'organe fait ce qu'il annonce sur son corpus et ses contrôles sont honnêtes ; je signale trois écarts entre les largeurs mesurées dans le body et les largeurs livrées, dont deux qui coûtent du rappel sur la classe même que la PR veut rendre générique. Aucun n'exige de reprise avant merge si le body dit lesquels sont assumés.
… a l'identifiant Trois ecarts mesures par la review Hermes entre les largeurs annoncees dans le body et celles effectivement livrees. 1. ABSENCE_MARKERS restait a la largeur de son instance fondatrice : « manque encore », « : TODO », « reste a implementer » et « n'existe pas encore » rendaient tous rc 0 sur un identifiant declare au head. La regle vise la classe « absence affirmee » ; quatre marqueurs l'elargissent, et les quatre formulations deviennent des controles parametres. 2. Le caveat de perimation etait cherche dans la cellule entiere AVANT la boucle par ligne : un « un autre passage est perime » ecrit ailleurs avalait un vrai TODO perime. Il porte desormais sur la ligne du finding, ou sur une ligne qui cite le meme identifiant -- la portee de la phrase, comme le body le revendique. 3. La classe 2 perdait la prose repliee a 80 colonnes (« ... FigureEight.lean » puis « le noeud 8_1 ... »). Une fenetre de deux lignes la rattrape, mais seulement pour une vraie continuation : sans discriminant, l'arbre d'architecture de la cellule 16 de KNOTS-01 redevenait le faux positif mesure. Les deux controles (repli positif, phrases terminees negatives, arbre adjacent negatif) sont dans la suite. Mesures : 49 tests passent (40 avant), le corpus reel rend toujours 0 finding, rc 0. Aucune formulation de la review ne rend plus rc 0. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Réponse aux trois écarts de la review, traités au commit 1. 🔴
|
| Formulation | Avant | Après |
|---|---|---|
« knot_11n102_diagram manque encore » |
rc 0 | rc 1 |
« knot_11n102_diagram : TODO » |
rc 0 | rc 1 |
« knot_11n102_diagram reste à implémenter » |
rc 0 | rc 1 |
« knot_11n102_diagram n'existe pas encore » |
rc 0 | rc 1 |
TODO nu subsume TODO: PD-code ; la forme étroite est conservée pour que l'instance fondatrice reste lisible dans le fichier, avec un commentaire qui dit la subsomption. L'anglais (missing, not yet) était déjà couvert et ne bouge pas.
2. 🔴 Le caveat annulait à l'échelle de la cellule — resserré sur l'identifiant
Le if STALE_TODO_CAVEAT_RE.search(source): return [] en tête de scan_classe3 est supprimé. Le caveat est désormais porté par la ligne du finding, ou par une ligne qui cite le même identifiant — la portée de la phrase, celle que le body revendique.
Les deux sens sont contrôlés :
test_caveat_elsewhere_in_cell_does_not_swallow_a_real_finding— « Un autre passage est périmé. » puis un vrai TODO périmé : tire (avant : rc 0) ;test_caveat_attached_to_the_identifier_still_suppresses— un caveat qui nommeknot_11n102_diagram: ne tire pas.
Mesure de non-régression : la cellule 23 de KNOTS-01, l'instance fondatrice, reste neutralisée. Le corpus réel rend toujours 0 finding, rc 0 — le resserrement ne ressuscite aucun faux positif.
3. 🟡 Le cadrage ligne perdait la prose repliée — fenêtre de 2 lignes, avec discriminant
Le cas mesuré (« … FigureEight.lean » / « le nœud 8_1 … » à 80 colonnes) tire maintenant. La fenêtre n'est pas ouverte en aveugle : elle exige une tête sans ponctuation finale, une queue sans marqueur de liste ou d'arbre, et pas de module/numéro déjà porté de chaque côté.
Ce discriminant n'est pas décoratif — je l'ai mesuré : sans lui, la fenêtre à 2 lignes ressuscite le faux positif de la cellule 16 de KNOTS-01, dont les deux entrées d'arbre (|-- Invariant.lean puis |-- FigureEight.lean (4_1)) sont sur des lignes adjacentes dans le contrôle existant. Le contrôle négatif test_line_scope_not_cell_scope reste vert, et deux contrôles l'encadrent (repli positif, deux phrases terminées négatif).
Mesures
pytest scripts/notebook_tools/tests/test_scan_knots_extracts.py→ 49 passed (40 avant ce commit).python scripts/notebook_tools/scan_knots_extracts.py→4 carnet(s) scanné(s) contre 47 module(s) Lean, 0 finding, rc 0.- Le hook
knots-extracts-class23est inchangé (.pre-commit-config.yamlnon touché).
Sur le point de forme de la review (« aucun n'exige de reprise avant merge si le body dit lesquels sont assumés ») : aucun des trois n'est assumé, les trois sont réparés. Le body de la PR est mis à jour dans le même geste pour décrire les largeurs réellement livrées.
Grain: DEEP/guard — lane myia-po-2025:CoursIA — prev: DEEP/notebook-python #22640
See #21007 (voie B). Ne ferme pas l'issue : les trois classes sont couvertes, la cloture revient au coordinateur apres lecture.
Ce qui existait
La voie (B) existait deja :
scripts/notebook_tools/scan_knots_extracts.py(classes 2 et 3) et 16 tests danstests/test_scan_knots_extracts.py. Ce que j'ai d'abord ecrit dans ce dossier — « zero test, zero cablage » — etait faux sur la moitie : les tests existaient, seul le cablage manquait. La mesure qui l'a corrige estgit status, qui a montre le fichier de tests enMet non enA(git show origin/main:...: 226 lignes, 16 tests). Les 16 sont conserves ci-dessous, aucun retire.Ce qui manquait vraiment, et que cette PR livre :
FIGURE_EIGHT_FILE,LIDMAN_FILE) et les regles etaient des listes de constantes (WRONG_FIGURE_EIGHT_NUMBERS). Sur un corpus propre, l'organe rendait 0 finding et ne pouvait pas en rendre un autre : un test de regression sur deux cas passes, pas un detecteur de classe.knots-extracts|scan_knots_extracts, hors carnets) : trois fichiers — la config pre-commit, le script, ses tests. Le hook pre-commit ne portait que la classe 1 (check_knots_extracts.py, idknots-extracts). Un organe que rien n'execute ne mesure qu'une fois.Ce que la PR change
La verite vient du depot, plus du code.
LeanTruth.build()lit l'arbre Lean et derive, par module, les noms declares (def/theorem/lemma/abbrev/structure/inductive) et les numeros de noeud cites. Les deux instances fondatrices restent couvertes — par la regle, plus par une constante.Deux regles generales, a la place des listes de cas :
STALE_IDENTITY) : sur une meme ligne, une reference de module et un numeroN_M. Si le module cite lui-meme des numeros et qu'aucun des numeros revendiques n'en fait partie, l'identite est perimee.STALE_TODO) : sur une meme ligne, un marqueur d'absence et un identifiant metier declare au head. Un caveat explicite dans la cellule annule le finding.Un hook qui tire dans les deux sens :
knots-extracts-class23, surKNOTS/**.ipynbetKNOTS/**.lean— un module qui change peut perimer un carnet qu'on n'a pas touche.Trois largeurs, trois mesures (aucune n'est supposee)
.lean?see FigureEight (8_2))11n102_diagramest la forme en prose deknot_11n102_diagram— l'exclure faisait echouer 2 tests d'heritageknot_11n102_diagram->11n102_diagram) sont necessaires pour la meme raisonLes deux dernieres lignes sont des regressions de rappel que j'avais introduites, attrapees par les tests de la v1 — pas par moi. Elles sont la raison pour laquelle conserver ces tests valait mieux que les reecrire.
Deux largeurs ecartees, chacune mesuree
existeettrefoilsont des mots ordinaires ET des noms dedefdes 47 modules reels (618 declarations)Invariant.leanetFigureEight.lean (noeud 4_1); elle cite donc4_1sans rien revendiquer surInvariant, dont les seuls numeros sont3_1Un faux positif de la v1, corrige et documente
Le test d'heritage
test_mixed_stale_yields_both_findingsaffirmait deux findings sur une cellule contenant"FigureEight.lean (noeud 8_1) -- c'est faux, c'est 4_1."Cette ligne nomme le bon numero en corrigeant le mauvais : la signaler etait un faux positif que le test encodait. L'intention du test (un carnet portant un defaut de chaque classe rend deux findings) est conservee sur une fixture reellement perimee, et le cas d'auto-correction devient un controle negatif nomme (test_negative_self_correcting_line).Controles
FigureEight.lean ... noeud 8_1)11n102 ... pas encore entre)rc=1)defKNOTS-01..04)Validation
python -m pytest scripts/notebook_tools/tests/test_scan_knots_extracts.py -q-> 40 passed (16 conserves + 24 ajoutes)python scripts/notebook_tools/scan_knots_extracts.py->4 carnet(s) scanne(s) contre 47 module(s) Lean, 0 finding, rc 0, ~2 spython -m pre_commit validate-config .pre-commit-config.yaml->VALIDATE-CONFIG OKpython -m pre_commit run knots-extracts-class23 --all-files-> Passedpython -m pre_commit run knots-extracts-class23 --files .../FigureEight.lean-> Passed (second declencheur)Ce que cette PR ne fait pas
.pre-commit-config.yaml.knots-extracts; sa description renvoie desormais au nouvel organe au lieu d'annoncer la voie (B) comme un suivi a venir.Lean/KNOTS/. Les classes sont detectees par regle, mais le cablage reste sur cette serie tant qu'aucune autre n'a ete mesuree.Non-collision
gh pr list --state all --search "head:fix/knots-extracts-class23"->[]avant ouverture.[CLAIMED]pose sur #21007 (commentaire 6414386021) avecpaths:couvrant ces trois chemins ;check_lane_claim.py 21007 --lane myia-po-2025:CoursIArendaitblocked: false.🤖 Generated with Claude Code
Largeurs réellement livrées (mise à jour post-review, commit
380eaf2314)La review a mesuré trois écarts entre les largeurs annoncées ci-dessus et celles livrées. Les trois sont corrigés dans l'organe, aucun n'est assumé :
pas (encore) entré/défini/fourni/codé/implémenté,manquant,TODO: PD-code,not yet,missingmanque/manquent/manquait,n'existe pas,reste à implémenter,TODOnuMesures à cette tête : 49 tests passent (40 avant), corpus réel
4 carnets / 47 modules / 0 finding, rc 0.