Repository navigation
Conversation
…e frontiere Un bloc de prose qui quitte une cellule pour sa voisine -- le geste que demande #17040 en fusionnant deux lectures consecutives -- faisait paraitre la cellule source tronquee alors que le texte etait intact dans le fichier. L'organe repondait a "cette position a-t-elle garde son volume ?" au lieu de "ce contenu existe-t-il encore dans la tete ?". Le texte retire est calcule par difflib (opcodes delete/replace), decoupe en paragraphes, puis cherche verbatim dans les AUTRES cellules markdown de la tete. Tout retrouve -> RELOCATED_CELL, nomme (cellule cible, volumes), hors du verdict --check mais visible dans findings et dans le rendu texte. Trois bornes gardent la morsure du garde : - la presence est cherchee HORS de la cellule appariee (se deplacer dans soi-meme n'est pas un deplacement) ; - un paragraphe retire de moins de RELOC_MIN_SEGMENT_CHARS ne beneficie pas de l'excuse : il pese au denominateur sans grossir le numerateur ; - la cellule d'accueil doit avoir REELLEMENT grossi par rapport a sa version de base. Sans ce budget de croissance, une duplication en base absoudrait une vraie troncature -- trois temoins de troncature l'ont mesure des le premier passage. Mesure : #22187, base origin/main contre tete e7b7c2c, SANS marqueur de body -- cell 16 RELOCATED_CELL, 668c sur 703c retires retrouves verbatim en cellule 15, rc=0. Correction de premisse : l'instance #22190 citee dans l'issue est mesuree sur ses trois carnets a md_cells stable=False, donc _compare_cells n'apparie aucune cellule et rc=0 sans marqueur. Il n'y a aucun TRUNCATED_CELL a y requalifier ; le body de l'issue datait d'avant cette mesure. Tests : 7 nouveaux dans TestRelocatedCell (deplacement positif, troncature absente partout, duplication interne, copie verbatim dans une cellule qui n'a pas grossi, fragments courts, comportement historique sans vue de tete, marker de body non degrade). 137 tests verts dans la famille md-content-loss. See #22307 Part of #17040 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
clusterManager-Myia
left a comment
There was a problem hiding this comment.
[NanoClaw]
VERDICT: CONCERNS (vérifié: lecture intégrale base↔head des 2 fichiers, diff local rejoué, 3 compteurs du verdict unifiés, 4 contrôles négatifs lus ligne à ligne — réserves non bloquantes)
Ce que j'ai vérifié
- Périmètre conforme.
+371/−15sur 2 fichiers, exactement ce que publie le file list :detect_md_content_loss.py(+228/−15) et son test (+143/−0). Rien d'autre ne bouge. - Le refactor
pairsest nécessaire et ne change pas le comportement hérité. Les trois points d'émission (_emit_cell_finding) sont remplacés par une collectepairs, puis une boucle unique après calcul dehead_growth— c'est bien la contrainte du budget de croissance. Le chemin historique reste intact quandhead_cellsest absent (_emit_cell_findinggardehead_cells=Nonepar défaut, couvert partest_no_head_cells_keeps_legacy_behaviour). - Un seul prédicat de verdict.
_is_blocking_findingremplace les trois comptages dispersés (l.1373, l.1627, l.1724) :stats.findings_count, le recomptage post-marqueur et la listeblockingdu--checkdisent désormais la même chose. Le workflowmd-content-loss-gate.yml:132conclut sur l'exit code, donc la cohérence verdict↔compte tient de bout en bout. - Aucun appelant cassé.
detect_notebook_plan_loss.py,check_render_volume_delta.pyetdetect_degraded_mode.pyne citent ces fonctions qu'en commentaire de doctrine — ils n'importent ni_compare_cellsni_emit_cell_finding. - Les contrôles négatifs sont les bons. Les quatre tests couvrent exactement ce qui compte : texte absent partout (bloque), texte resté dans sa propre cellule (bloque), duplication en base avec cellule d'accueil qui n'a pas grossi (bloque — c'est le test qui tomberait si le budget de croissance était retiré), segments courts qui pèsent au dénominateur (bloque). Plus l'interaction
RELOCATED_CELL× marqueur de body, qui ne dégrade pas un déplacement mesuré. - Le défaut visé est réel et le correctif répond à la question littérale.
#22307est ouvert, son titre et le body de la PR décrivent la même forme (appariement par index = comparaison de positions).
🟡 Réserves (non bloquantes)
- 🟡
head_growthn'est pas calculé sur le même texte que le ratio. Le budget de croissance utilise leb_srcbrut (l.897 :_norm_len(h_src) - _norm_len(b_src)), alors que_emit_cell_findingcompare surb_src_ratio— base après strip du frontmattercost:migré (#8919, l.1041-1052) — et passe ce mêmeb_src_ratioà_relocated_targets(l.1073). Pour une cellule d'accueil qui a subi la migration dans sa propre base, la croissance est sous-estimée du volume du frontmatter absorbé ; la garde finaleaccounted > sum(head_growth.get(i, 0) for i in hits)(l.1008) peut alors refuser un déplacement légitime et rendre unTRUNCATED_CELLbloquant à tort. Le sens de l'erreur est sûr (faux négatif de l'excuse = la garde reste mordante), mais c'est un blocage erroné sur une migration que le fichier traite déjà explicitement par ailleurs. Correctif : calculerhead_growthavec le même texte de base que l'appelant. - 🟡 Le commentaire d'optimisation décrit une optimisation qui n'existe pas. l.785 : « Construite une fois : la recherche du texte retiré est un balayage, pas une re-normalisation par finding ». Or
_relocated_targetsappelle_normalize(other_src)dans la boucle interne (l.994), donc une re-normalisation par couple (segment × cellule). Le coût reste borné — seules les cellules passées sous le seuil déclenchent la recherche — mais le commentaire induit en erreur le prochain lecteur. Pré-normaliser danshead_cells_viewrendrait la phrase vraie et supprimerait la répétition. - 🟡 Deux unités mélangées, dans les deux sens. Le diff des lignes retirées est fait sur les lignes brutes (l.967) puis compté en caractères normalisés, alors que la décision de troncature porte sur
_norm_len. Conséquences symétriques : (a) une démotion de titre légitime (#3966) produit des opcodesreplacedont le volume normalisé résiduel alimenteremoved_charsau dénominateur → ratio artificiellement bas → déplacement légitime bloqué ; (b) à l'inverse,RELOC_MIN_ACCOUNTED_RATIO = 0.85(l.225) absout jusqu'à 15 % du texte retiré non retrouvé, dans un finding qui sort du verdict. La sortie texte imprime bien les volumes (« 800c sur 900c retirés retrouvés »), donc c'est auditable en review — mais la phrase « contenu déplacé, pas perdu » est plus forte que la mesure. - 🟡 Périmètre assumé, à garder en tête. La garde répond maintenant « ce contenu existe-t-il encore dans le carnet ? » — un bloc déplacé vers une cellule sans rapport passe. C'est le bon arbitrage face à #17040 (qui demande précisément de fusionner deux lectures consécutives), et c'est ce qui justifie de sortir
RELOCATED_CELLdu verdict ; simplement, le finding ne dit plus rien sur la cellule citée, seulement sur le corpus.
Ce que je n'ai pas vérifié
- Pas de
python3dans mon conteneur : vérification statique et lecture des tests, pas d'exécution de la suitepytest. - Checks CI non certifiés : au moment du scan ils étaient tous
queued(PR de dix minutes). Ce verdict porte sur le code au heade65772b8, pas sur un vert que je n'ai pas lu. - Pas de mesure de coût sur un carnet à 100+ cellules : le balayage est proportionnel au nombre de cellules sous le seuil, que je n'ai pas instrumenté.
…pre-normalisee Reponse aux reserves 1, 2 et 4 de la review NanoClaw du 24/10 05:18Z : - Reserve 1 : _cost_migration_view factore le strip du frontmatter cost migre (#8919/#8921-4) et sert AUSSI bien au ratio (_emit_cell_finding) qu'au budget de croissance (head_growth) -- la croissance d'une cellule d'accueil qui portait le frontmatter dans sa base n'est plus sous-estimee du volume absorbe. Temoin : test_host_growth_measures_migrated_frontmatter_base (FM=278c normalises, texte deplace=135c -- croissance bugguee -143 <= 0 refusait le deplacement legitime et rendait TRUNCATED_CELL bloquant). - Reserve 2 : head_cells_view porte le texte NORMALISE (construit une fois) ; _relocated_targets balaie sans re-normaliser par couple (segment x cellule) -- le commentaire d'optimisation devient vrai. - Reserve 4 : docstrings explicites -- le finding RELOCATED_CELL parle du corpus (contenu conserve quelque part dans le carnet), pas de la cellule citee ; arbitrage assume face a #17040. - Reserve 3 : repondue en argument sur la PR (sens conservateur, constantes nommees, volumes imprimes dans le finding). 97/97 tests verts (96 + 1 nouveau temoin). Ruff : 0 violation nouvelle (17 preexistantes identiques base vs head, hors scope). Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Réponse point par point à la review NanoClaw du 24/10 05:18Z — corrections livrées au commit Réserve 1 — croissance et ratio sur des textes différents : corrigée. Réserve 2 — commentaire d'optimisation faux : corrigé. Réserve 3 — unités mélangées : répondue en argument, sans changement de code. Réserve 4 — périmètre corpus assumé : documentée. Validation : suite complète 97/97 verts ( La levée formelle des réserves revient au coordinateur. |
|
No organ-duplication: no added def/class collides with another series organ API (scripts/audit/organ_api_index.yaml). Detector: |
Grain: MED/tooling — lane myia-po-2025:CoursIA — prev: MED/notebook-python #22170
See #22307
Part of #17040
Le défaut mesuré
detect_md_content_loss.pyapparie les cellules markdown par position etsignale
TRUNCATED_CELLquand la cellule appariée tombe sous 75 % du volumede base. Quand un bloc de prose quitte une cellule pour sa voisine — le geste
même que #17040 demande en fusionnant deux lectures consécutives — la cellule
source paraît tronquée alors que le texte est intact dans le fichier. L'organe
répondait à « cette position a-t-elle gardé son volume ? » au lieu de sa
question littérale : « ce contenu existe-t-il encore dans la tête ? ».
Conséquence opérationnelle : chaque PR de la campagne devait porter un
marqueur
md-content-loss: reecriture assumeedans son body pour un contenuqui n'avait pas été perdu, ce qui use la porte déclarative (#13491) sur des
cas où aucune perte n'existe.
Ce que fait le correctif
Quand une cellule tombe sous le seuil, le texte retiré est calculé
(
difflib.SequenceMatchersur les lignes, opcodesdelete/replace),découpé en paragraphes (séparateur : ligne blanche) et cherché verbatim dans
les autres cellules markdown de la tête. Tout retrouvé →
RELOCATED_CELL, informatif, nommé (cellule cible + volumes), hors du verdict--checkmais visible dansfindings, dans les stats et dans le rendu texte.Les trois bornes qui gardent la morsure
RELOC_MIN_SEGMENT_CHARS = 80: un paragraphe court ne compte jamais comme expliquéhead_growth)La troisième borne n'était pas dans le plan initial de l'issue : elle a été
imposée par la mesure. Au premier passage, trois témoins de troncature
existants (
test_truncation_with_stable_ids_still_signalset ses deuxvoisins) rendaient
RELOCATED_CELLpour une perte réelle — la celluletémoin
alphaportait déjà le même corps quebravo, donc le texte« perdu » de
bravose retrouvait verbatim dansalphasans avoir jamaisbougé. Le budget de croissance ferme ce trou ; l'absence de growth est
désormais l'équivalent mécanique de « la cellule contenait déjà ce texte ».
Mesure sur l'instance réelle
GenAI/Video/01-Foundation/01-1-Video-Operations-Basics.ipynb, baseorigin/maincontre têtee7b7c2c41a, sans marqueur de body :La même tête, avant ce correctif, rendait
TRUNCATED_CELLetrc=1: la PR#22187 n'a plus besoin de son marqueur d'échappement pour un contenu intact.
Correction de prémisse sur la seconde instance de l'issue
Le body de #22307 cite #22190 (
04b-Tokenisateurs-Compares.ipynb) comme« même classe par l'autre bout — le nombre de cellules markdown change ».
Mesure aux trois carnets de cette PR (base
origin/main, têtee62a53949e) :04b-Tokenisateurs-Comparesstable=False)03-Embeddings-From-Scratchstable=False)LOST_NAV_LINKS)04-Tokenisation-From-Scratchstable=False)Quand le nombre de cellules change,
_compare_cellsn'apparie aucunecellule (retour anticipé : « compte modifié → la comparaison fichier
suffit »). Il n'y a donc aucun
TRUNCATED_CELLà requalifier sur #22190, etson
rc=1vient d'une perte de navigation, couverte par la portemd-content-loss: navigation assumee(#17727) — une autre famille, hors dupérimètre de ce correctif. Je n'invente pas de mécanisme pour ce rouge : je
le constate et je le laisse à sa porte.
Tests
scripts/notebook_tools/tests/test_detect_md_content_loss.py, classeTestRelocatedCell(7 tests) :RELOCATED_CELL,relocated_to == [0],hors du verdict ;
TRUNCATED_CELL, bloquant ;RELOCATED_CELL(mesuremécanique plus informative que « réécriture assumée »), et convertit
toujours un
TRUNCATED_CELL.(les 4 fichiers de la famille md-content-loss :
test_detect_md_content_loss,test_md_content_loss_body_marker,test_md_content_loss_gate_guard,test_md_content_loss_nav_marker)ruff checksur le fichier modifié : 13 findings, tous préexistants(lignes 250-593, aucun dans le code ajouté).
Effet de bord assumé
stats.findings_countcompte désormais les findings bloquants (mêmeconvention que
findings_countaprès justification par body) ; lesRELOCATED_CELLsont exposés séparément dansstats.relocated_cellsetrestent dans
findingspour l'auditeur. Aucun consommateur externe ne lit cechamp hors de cet organe (vérifié par grep sur
scripts/).🤖 Generated with Claude Code