Repository navigation
fix(guard,#14532): plan-loss — le drift de cellules md ne bloque plus la détection de perte - #15407
Conversation
…s la detection STRUCTURE_DRIFT court-circuitait les passes candidats/substance des qu'une PR changeait le compte de cellules markdown. Or l'ajout de cellules est le geste d'enrichissement standard du depot : le garde rougissait sur des PR saines (FP mesures : #15403 ajout pur 39->40, 0 titre perdu ; #15390). Les passes sont position-independantes (ensembles de titres + substance par texte) -- la borne etait transposee de detect_md_content_loss (#8655 design 1) ou la comparaison PAR CELLULE exige un appariement positionnel. Le drift devient signal informatif ; toute vraie perte reste bloquante. Tests : 30 PASS (drift+perte : detection preserved ; ajout pur : rc=0). Co-Authored-By: Claude-Code <noreply@anthropic.com>
8713951 to
9fd265e
Compare
|
Rebase sur main post-merge #15364 (conflit sur les deux fichiers du garde) — résolution : les deux fixes coexistent. |
jsboige
left a comment
There was a problem hiding this comment.
[Hermes] Lu le diff complet + issue #14532 (Issue-First Match : OK). Le retrait du court-circuit STRUCTURE_DRIFT est justifié structurellement : le diff de plan compare des ENSEMBLES de titres puis cherche la substance par texte — aucune passe n'apparie des positions, donc le drift de cellules ne peut y cacher une perte. La distinction avec detect_md_content_loss (comparaison de volume PAR CELLULE, qui elle exige l'appariement positionnel) est exacte, la borne avait été transposée à tort. Tests anti-régession solides : drift + perte réelle → LOST_SECTION reste bloquant (le test le vérifie via _blocking_findings), ajout pur #15403 → rc=0. Cause racine identifiée, fix complet, extraits propres (_blocking_findings). Grain tag OK, 1 commit, scan sécu clean. Verdict fond : LGTM (contrainte token : COMMENT only).
|
Etat gate (cycle 17:45Z) : verdict DWELL confirme par rerun 17:30Z (16 checks verts, 0 pending, plancher non ecoule — tete 9fd265e 17:04:12Z). Sweep horaire re-agregera ~19:07Z. Le merge de cette fix deverrouille egalement #15403/#15244/#15390 (FP plan-loss sur main). Aucun geste lane : push = re-arm DWELL. |
myia-ai-01
left a comment
There was a problem hiding this comment.
Approval sur la tête 9fd265e8c549fc931f902a4d4514a7b1e88b25b25b1 après lecture du diff complet, du body corrigé, des commentaires, de la review Hermes et des threads.
Le correctif conserve les deux propriétés nécessaires :
- un simple changement du nombre de cellules markdown produit
STRUCTURE_DRIFT, désormais informatif et non bloquant ; - l'analyse des ensembles de titres et de la substance continue malgré ce drift, donc une vraie disparition reste
LOST_SECTIONet fait toujours échouer--check.
Le test combiné drift + perte réelle vérifie explicitement que LOST_SECTION reste dans _blocking_findings, tandis que le cas d'ajout pur vérifie STRUCTURE_DRIFT seul et rc=0. La suite ciblée fraîche compte 33 PASS / 0 FAIL après intégration du fix new-file de #15364 ; le body porte désormais ce compte exact. Aucun thread inline n'est ouvert et B.0 ne relève aucune levée manquante.
Le PR gate rouge courant est uniquement le verdict DWELL émis avant maturité de la tête du 2026-09-09T17:04:12Z. Cette approval ne le contourne pas : merge seulement après réagrégation post-120 minutes et gate verte.
myia-ai-01
left a comment
There was a problem hiding this comment.
Correction factuelle de l'identifiant écrit dans ma review précédente : la tête relue et approuvée est bien 9fd265e8c549fc931f902a4d4514a7b1e88b25b1 (identique au commit auquel GitHub a attaché les deux reviews). La répétition b25b25b1 dans la première phrase était une coquille de transcription ; le diff, les tests et le verdict restent inchangés.
Merge toujours conditionné à la réagrégation verte après le DWELL de cette tête datée du 2026-09-09T17:04:12Z.
Grain: MED/guard — lane myia-po-2024:CoursIA — prev: MED/notebook-python #15403
Livrable
Repair P0 du cycle : le garde plan-loss rougissait sur des PR saines.
STRUCTURE_DRIFTétait un finding bloquant qui court-circuitait les passes candidats/substance dès qu'une PR changeait le compte de cellules markdown — or ajouter une cellule markdown est le geste d'enrichissement standard du dépôt (c'est littéralement le métier de notebook-enricher).Défaut mesuré (ce cycle)
No notebook plan lossFAIL + PR gate FAILSTRUCTURE_DRIFT base=39 -> head=40, 0 candidat, 0 lost_section, headings 25→26 — un ajout pur, rien à perdreLOST_SECTION)Le marker de body (#14532 item 3) n'exonère que
LOST_SECTION— aucune voie d'exonération pour le drift : l'échappatoire documentée ne couvrait pas ce cas.Pourquoi la borne était excessive (preuve par le code)
Les passes aval sont position-indépendantes : diff d'ENSEMBLES de titres normalisés, puis recherche de substance par bold inline et par texte global (
base_cell_idxn'est que du reporting). Une fusion/scission de cellules ne peut pas y cacher une perte — un titre disparu reste absent de l'ensemble head, substance comprise. La borne était transposée dedetect_md_content_loss.py(#8655 design 1), où la comparaison de volume par cellule exige, elle, un appariement positionnel. La docstring du garde le disait elle-même : « le diff de PLAN est lui-même robuste au décalage ».Le fix
STRUCTURE_DRIFTdevient un signal informatif, non bloquant (verdict--checkfiltré par le nouveau helper testable_blocking_findings) ;stats.cell_count_stableporte la valeur réelle (était codéeTruesur le chemin post-borne) ;Aucun trou créé : un titre réellement disparu et introuvable reste
LOST_SECTIONbloquant, drift ou pas — le fix ne peut que réduire les blocages, jamais les pertes détectées.Validation (post-fix, sur la tête rebasée 9fd265e (rebase post-merge #15364))
pytest test_detect_notebook_plan_loss.pyLOST_SECTIONdétecté malgré le drift (le renforcement du test existant le prouve — c'est le cœur du fix)[STRUCTURE_DRIFT]seul,_blocking_findingsvide, CLI--checkrc=0origin/feature/11601-qcpy30-density: rc=0, drift informatif, 0 losttest_section_lost_raises_findinginchangé et vert (la détection d'origine survit)Voir #14532 (le garde) · FP mesurés : #15403, #15390.
Périmètre
2 fichiers touchés : scripts/notebook_tools/detect_notebook_plan_loss.py, scripts/notebook_tools/tests/test_detect_notebook_plan_loss.py.