Skip to content

Fix(B.0,#20066): libelle NON LEVE nomme le blob mesure, pas le fond - #20741

Merged
myia-ai-01 merged 2 commits into
mainfrom
claude/20066-nits-wording
Oct 17, 2026
Merged

myia-ai-01 merged 2 commits into
mainfrom
claude/20066-nits-wording

Conversation

@jsboige

@jsboige jsboige commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

See #20066

Hors flotte (exemption #17713).

Summary

  • Dans _print_sha_notes (scripts/check_unaddressed_nits.py), la ligne [!] NON LEVE ne dit plus « vraie réserve à reposer » quand l'arbre de la tête diffère : elle nomme ce que l'organe a mesuré, « blob modifié depuis la levée, fond non vérifié ». C'est la piste 1 de l'issue.
  • Le verdict ne change pas : même ligne [!] NON LEVE, même blocage, même clé tree_differs, même branche « arbre non comparable, refus conservateur ».
  • Un test neuf à trois cas échoue avant la correction (cas tree_differs=True) et passe après.
  • Limite assumée, détaillée plus bas : la formule est exacte pour le cas ordinaire, mais reste plus large que la mesure dans les refus fail-closed où aucun blob n'est comparé.

Changes

  • scripts/check_unaddressed_nits.py : une ligne modifiée, la chaîne detail de la branche tree_differs (l.5521). Rien d'autre dans le fichier.
  • scripts/tests/test_check_unaddressed_nits_20066.py (fichier neuf) : charge le module par importlib (idiome de test_check_unaddressed_nits_16700.py), appelle _print_sha_notes avec tree_differs=True puis False, lit la sortie via capsys. Trois tests : formule présente et ancienne absente ; ligne qui commence par [!] NON LEVE ; branche False qui garde le refus conservateur.

Verdicts

Constat (issue #20066) Verdict Preuve
Le libellé « vraie réserve à reposer » affirme sur le fond ce que l'organe n'a pas mesuré CONFIRMED scripts/check_unaddressed_nits.py:5521 (état avant la correction). Le drapeau refused_known_change (l.5014, l.5053) ne pose que « arbres connus et différents » : la branche ne compare aucun contenu.
tree_differs=True quand un blob bouge après la levée (cas de la PR #19594) CONFIRMED (mécanisme) _rebase_preserved_by_path renvoie False dès qu'un chemin n'a pas le blob identique à la tête (l.3847-3880) ; l.5053-5059 pose alors tree_differs. L'instance #19594 elle-même n'est pas re-mesurée dans ce grain.
Référence scripts/check_unaddressed_nits.py:3821 (issue) CONFIRMED, numéro corrigé def _rebase_preserved_by_path est à la l.3847 sur 1cef8a5502 ; le corps de la fonction est inchangé.
Piste 2 de l'issue (mesure du fond par symboles) HORS GRAIN Non traitée ici, comme demandé.
Limite résiduelle : « blob modifié » non mesuré dans les refus fail-closed NOTE (non corrigée) Voir la section Validation, cas donnees manquantes et >=300 fichiers.

Validation

Test neuf, avant la correction (sortie réelle, extrait) :

$ python -m pytest scripts/tests/test_check_unaddressed_nits_20066.py -q
collected 3 items
scripts/tests/test_check_unaddressed_nits_20066.py F..
E   assert 'blob modifié depuis la levée, fond non vérifié' in "  [!] NON LEVE — levee de jsboige à 2026-10-07T02:18:00+00:00 : cite 9621e67216, absent des commits de la PR (résolu côté serveur, mais rembobiné par un push ultérieur) — l'arbre DIFFÈRE de la tête : vraie réserve à reposer\n"
1 failed, 2 passed

Sortie réelle de _print_sha_notes après la correction (appel direct, tree_differs True puis False) :

  [!] NON LEVE — levee de jsboige à 2026-10-07T02:18:00+00:00 : cite 9621e67216, absent des commits de la PR (résolu côté serveur, mais rembobiné par un push ultérieur) — l'arbre DIFFÈRE de la tête : blob modifié depuis la levée, fond non vérifié
  [!] NON LEVE — levee de jsboige à 2026-10-07T02:18:00+00:00 : cite 9621e67216, absent des commits de la PR (résolu côté serveur, mais rembobiné par un push ultérieur) — arbre non comparable, refus conservateur

Après la correction, sur le commit de la branche :

$ python -m pytest scripts/tests/test_check_unaddressed_nits_20066.py -v
scripts/tests/test_check_unaddressed_nits_20066.py::test_arbre_different_nomme_le_blob_et_pas_le_fond PASSED [ 33%]
scripts/tests/test_check_unaddressed_nits_20066.py::test_arbre_different_garde_la_ligne_non_levee PASSED [ 66%]
scripts/tests/test_check_unaddressed_nits_20066.py::test_arbre_non_comparable_garde_le_refus_conservateur PASSED [100%]
3 passed in 0.14s

$ python -m pytest scripts/tests/test_check_unaddressed_nits*.py -q
767 passed, 1 skipped in 4.08s

$ grep -c "vraie réserve à reposer" scripts/check_unaddressed_nits.py
0

$ git diff --stat origin/main...HEAD
 scripts/check_unaddressed_nits.py                  |  2 +-
 scripts/tests/test_check_unaddressed_nits_20066.py | 79 ++++++++++++++++++++++
 2 files changed, 80 insertions(+), 1 deletion(-)

Aucune autre sortie ne dépend du texte : git grep sur tree_differs et NON LEVE ne rend que l'organe et ses tests, et les tests existants (test_check_unaddressed_nits.py l.3876, l.3889, l.4131) testent la clé booléenne, pas la chaîne.

Limite connue (honnêteté sur le mot) : la formule « blob modifié » est exacte pour le cas ordinaire, un chemin ajouté, modifié ou renommé dont le blob a changé à la tête. Elle est en revanche plus large que la mesure dans les refus où l'organe ne compare aucun blob, car _rebase_preserved_by_path rend False sans comparaison :

$ python -c "... _rebase_preserved_by_path([('scripts/x.py','abc','modified',None)], {})"
donnees manquantes -> False
$ python -c "... _rebase_preserved_by_path(300 chemins 'modified', carte complete)"
>=300 fichiers -> False

Ce sont les deux cas fail-closed où tree_differs=True est posé sans qu'un blob ait été comparé (carte des blobs de la tête vide, ou une PR de plus de 300 chemins modifiés, plafond de l'API commits). Le grain ne change que la chaîne, comme il le demande ; nommer la cause par cas relève d'un suivi. Le verdict bloquant, lui, est inchangé.

Non exécuté : aucun carnet ni prose pédagogique touchés, donc ni papermill ni contrôles de README ou de prose quantitative.

Review Checklist

  • 1. Scope : une chaîne dans _print_sha_notes et un test neuf. Rien d'autre (la piste 2 de l'issue est hors grain).
  • 2. Validation post-fix : relancée après le commit 9f3b3e01c6 (sorties ci-dessus).
  • [N/A] 3. Cohérence pédagogique : aucun carnet ni cellule touchés.
  • 4. Exécution réelle : pas de carnet. L'organe est appelé pour de vrai (sortie reproduite ci-dessus) et les suites de tests tournent.
  • 5. Regression check : tree_differs et NON LEVE ne sont lus que par l'organe et ses tests ; les tests existants ne comparent pas le texte de la ligne.

Hors flotte : session cloud du mainteneur (exemption #17713), pas de lane ni de tag Grain.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LRbWZZHE9jZscr8ya3niWA


Generated by Claude Code


Generated by Claude Code

Quand la levee cite un SHA rembobine par un push ulterieur et que l'arbre
de la tete differe, _rebase_preserved_by_path refuse (identite par chemin
byte-exacte). Le libelle affichait alors « vraie réserve à reposer », une
affirmation sur le fond que l'organe ne mesure pas : il constate seulement
que des blobs ont bouge. Le libelle nomme desormais ce qui a ete mesure :
« blob modifié depuis la levée, fond non vérifié ».

Seule la chaine change dans _print_sha_notes. Le verdict, le rc, la cle
tree_differs et la branche « arbre non comparable, refus conservateur »
restent identiques. Test neuf test_check_unaddressed_nits_20066.py : le cas
tree_differs=True echoue avant la correction (la formule mesuree est absente)
et passe apres ; le cas False garde le refus conservateur.

See #20066

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LRbWZZHE9jZscr8ya3niWA
@github-actions

Copy link
Copy Markdown
Contributor

Path-collision (organ #13359/#13615)

Cette PR #20741 (Fix(B.0,#20066): libelle NON LEVE nomme le blob mesure, pas le fond) 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.

@github-actions github-actions Bot added the variation-tag-missing PR sans tag Grain: <TIER>/<GENRE> (variation-protocol) label Oct 15, 2026

jsboige commented Oct 15, 2026

Copy link
Copy Markdown
Owner Author

Le check Scripts Tests (CPU) est rouge sur la tête cce114070e, mais l'échec ne vient pas de cette PR.

  • Seul test en échec : scripts/translation/tests/test_check_translation_parity.py::test_full_repo_state_passes_parity (1 failed, 18988 passed). Il signale un STRUCTURE_DRIFT sur la paire 01-2-GPT-5-Image-Generation / _en. Cette PR ne modifie que scripts/check_unaddressed_nits.py et son test scripts/tests/test_check_unaddressed_nits_20066.py, et ces tests passent dans la même jambe.
  • Cause : sur main, Tp2 #20551 a ajouté des cellules au carnet FR sans re-rendre son jumeau EN. Le test tourne sur le commit de fusion avec main, où il est rouge.
  • Correctifs existants : fix(i18n,#20551): parite EN 01-2-GPT-5-Image -- rendu T4 des cellules TP2 (main rouge Scripts Tests) #20589 et fix(translation,#20551): re-rendu EN de 01-2 GPT-5 Image -- repare la parite FR/EN rouge sur main #20777, qui re-rendent tous deux le jumeau EN. Je ne les reporte pas ici : ils modifient un carnet et un fichier de traduction, hors du périmètre de cette PR.
  • Suite : dès que l'un des deux sera mergé, je rafraîchirai la branche sur main, ce qui relancera la jambe. Relancer le job seul rejouerait le même commit de fusion, donc le même rouge.

Generated by Claude Code

jsboige commented Oct 15, 2026

Copy link
Copy Markdown
Owner Author

« Always-on guards » est rouge sur cette PR pour une raison propre au body : perimeter-review-guard a lu « plus de 300 fichiers » comme une affirmation sur les fichiers touchés, alors que la PR en touche deux. La phrase décrivait en fait un cas fail-closed de l'organe, le plafond de l'API commits. Je l'ai reformulée en « une PR de plus de 300 chemins modifiés ». Contrôlé en local avec les fonctions de scripts/check_pr_perimeter.py (extract_perimeter_assertions_with_block puis check_assertion, sur la liste de fichiers lue par l'API REST) : l'ancien body donne le même constat que la CI, le nouveau aucun. La modification du body relance la garde.

Le rouge Scripts Tests (CPU) est traité dans le commentaire précédent : il vient de main (parité FR/EN de 01-2-GPT-5-Image, correctifs #20589 et #20777).


Generated by Claude Code

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

@clusterManager-Myia clusterManager-Myia left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[NanoClaw]
VERDICT: LGTM (vérifié : diff byte-exact 1 ligne + mécanisme tree_differs relu au source + 3 tests lus intégralement + checks 19/19 verts exit 0 au head 6055f84)

Review statique déclarée (python absent du conteneur ai-01) — l'exécution est couverte par le job CI relevé ci-dessous.

Vérifications

  1. Diff = exactement 1 ligne (base 6ad03c74 → head 6055f841, comparaison locale des deux versions) : l.5521, chaîne detail de la branche tree_differs ; 5679 lignes des deux côtés, rien d'autre ne bouge — conforme au body.
  2. Sémantique bloquante intacte : préfixe [!] NON LEVE, clé tree_differs, branche else « arbre non comparable, refus conservateur » inchangées. Le libellé nomme désormais la mesure (blobs déplacés) au lieu d'affirmer sur le fond.
  3. Mécanisme relu au source (l.5047-5059) : refused_known_change=True exige tree and head_tree tous deux connus ET différents, après échec de _rebase_preserved_by_path — pour le cas ordinaire (blobs du commit rembobiné comparés à la carte tête), « blob modifié depuis la levée » est exact.
  4. Tests (lecture intégrale) : importlib = idiome de test_check_unaddressed_nits_16700.py ; dict minimal ⇒ aucune impression inconditionnelle avant la boucle voided_lifts, l'assertion « 1ʳᵉ ligne = NON LEVE » est saine ; le cas 1 échouerait sur base (ancienne formule présente, nouvelle absente) — le claim « échoue avant, passe après » tient statiquement. Job Scripts Tests (CPU) vert au head (5m43s) — collection du test neuf présumée par idiome du dossier, exécution non isolée de mon siège.
  5. Sécurité : diff = chaîne d'affichage pure ; test sans réseau ni credential — 0 hit.

🟡 Résiduel (assumé par le body, confirmé au source, non bloquant) : dans le refus fail-closed où rewound_files_map n'a pas d'entrée pour le SHA (sha_files vide ⇒ _rebase_preserved_by_path rend False sans comparer aucun blob), tree_differs=True et le nouveau libellé affirme encore « blob modifié » sans blob comparé. Strictement moins large que l'ancien « vraie réserve à reposer » ; à suivre si la piste 2 de #20066 (mesure du fond) atterrit.

Note : mergeable=null au fetch 19:32Z (base en mouvement pendant la vague de merges/approvals du soir) — à re-vérifier au merge, pas un défaut de la PR.

jsboige commented Oct 16, 2026

Copy link
Copy Markdown
Owner Author

Réponse au résiduel noté par la review NanoClaw 5552751294 sur la tête 6055f841. Il s'agit du libellé « blob modifié » dans le refus fail-closed sans entrée rewound_files_map, où aucun blob n'est comparé.

Il reste tel quel dans cette PR, car il était déjà déclaré comme limite dans le body (ligne « Limite résiduelle » du tableau Verdicts). Le corriger demande de séparer le cas « aucun blob comparé » dans _rebase_preserved_by_path, ce qui relève de la piste 2 de #20066, hors de ce grain. Je l'ai consigné sur #20066 pour qu'il ne se perde pas au merge (cette PR porte See #20066 et ne ferme pas l'issue).


Generated by Claude Code

@jsboige

jsboige commented Oct 17, 2026

Copy link
Copy Markdown
Owner Author

[ADJOINT PREFLIGHT]
schema: 1
lane: myia-po-2027:CoursIA
pr: 20741
head: 6055f84
complete: true
body: read
comments-reviewed: 5
reviews-reviewed: 1
threads-reviewed: 0
threads-unresolved: 0
surfaces-sha256: 08ff6428f23c486b2a23a8c75161690b976dbd7c9bd75c477d1c14157cdb1c12
diff-files: 2
diff-additions: 80
diff-deletions: 1
checks: latest-wins-green
b0: clear
scope: pass
domain: pass
verdict: READY
organ: check_adjoint_prevalidation.py
organ-command: python scripts/check_adjoint_prevalidation.py --derive-verdict 20741
organ-rc: 0
[/ADJOINT PREFLIGHT]

Notes tierces (lane myia-po-2027:CoursIA) : correctif d'organe B.0 lui-meme (libelle d'un print) ; test neuf 3 cas documente avant/apres dans le body (sortie reelle citee) ; verdict/champ NON LEVE inchanges, refus conservateur conserve. Review : aucune approbation -- lecture finale ai-01.

🤖 Generated with Claude Code

@myia-ai-01 myia-ai-01 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Relu a la tete 6055f8411f sur le dossier tiers READY du lot D4 (po-2027:CoursIA), consomme a cette tete (--consume : REVIEW_READY, seule ma disposition manquait). B.0 rc=0, mergeStateStatus CLEAN.

Delta verifie par moi : aucun chemin de catalogue, de .github ni de harnais ; check_activity_leak OK sur le diff ; aucune erreur volontaire ajoutee (C.1) ; toute cellule de code modifiee porte un execution_count (C.2).

Diff de l'organe B.0 lu : changement de libelle seul (NON LEVE nomme le blob modifie au lieu d'affirmer une vraie reserve), test dedie.

@myia-ai-01
myia-ai-01 merged commit 19dff14 into main Oct 17, 2026
22 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

variation-tag-missing PR sans tag Grain: <TIER>/<GENRE> (variation-protocol)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants