[DTP-Worker] Sprint 8 · buffer · Faisabilité/generator : ANCRAGE des 3 copies aval des 6 marqueurs canoniques (#9/#10) — l'oracle d'enforcement renderer._CANONICAL_MARKERS (que check_canonical parcourt) ⨯ les 2 docstrings scorer.py ⨯ l'oracle du test test_generator.py, recomputés de CLAUDE.md #9/#10 (réutilise exp)

Le bloc « paramètres canoniques » n'ancrait que model.py::CANONICAL + le README ;
son propre commentaire nommait pourtant le défaut (« marqueurs hardcodés dans le
test, une copie de plus jamais comparée à CLAUDE.md ») sans le fermer. Nouveau bloc :
helper _list_vs_want6 (set-diff EXACT absent/en-trop) pour les copies-LISTES
renderer._CANONICAL_MARKERS + oracle du test ; substring normalisé (USD+DOP==USD + DOP)
pour les 2 docstrings scorer. 4 morsures vérifiées dont CLAUDE.md #10 Cardnet→Azul
mordant SIMULTANÉMENT model+renderer+test+2 docstrings (valeur de l'ancrage) ;
restauré vert · 7 gates re-verts. ci/README.md + activity log mis à jour.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-01 14:42:30 +00:00
parent 8667cdf4de
commit 9963279879
3 changed files with 166 additions and 1 deletions
+18 -1
View File
File diff suppressed because one or more lines are too long
+85
View File
@@ -3877,6 +3877,91 @@ if exp is not None:
bad(f"Faisabilité canoniques · {FG_RD} — prose énumère {sorted(got)} MAIS "
f"CLAUDE.md {sorted(want)}{detail} → régénérer le README")
# ============================================================================
# Faisabilité/generator (2e surface du MÊME module) · l'ORACLE D'ENFORCEMENT
# `_CANONICAL_MARKERS` + les DEUX docstrings du scorer + l'oracle du TEST — trois
# copies DE PLUS des 6 marqueurs canoniques, ancrées sur CLAUDE.md #9/#10.
# ----------------------------------------------------------------------------
# Le bloc ci-dessus ancre model.py `CANONICAL` + le README à CLAUDE.md #9/#10.
# Restent, dans le MÊME module, TROIS surfaces data-derived qui RECOPIENT les
# mêmes 6 marqueurs, toutes NON gatées :
# (c) genlib/renderer.py `_CANONICAL_MARKERS` — la liste que `check_canonical()`
# PARCOURT pour PROUVER que le rendu du volet ingénierie contient les 6
# marqueurs (l'oracle de l'« axe 4 honnêteté »). C'est l'enforcement même :
# si cette liste DÉRIVE de CANONICAL (donc de #9/#10), le contrôle devient
# FAUX — soit il exige un marqueur périmé (« Cardnet » alors que le rendu,
# issu d'un CANONICAL mis à jour, porterait « Azul » → faux rouge), soit on
# en retire un et le contrôle NE VÉRIFIE PLUS RIEN (vert vacux).
# (d) genlib/scorer.py — DEUX docstrings (barème axe 4 en tête · fonction
# `_score_parametres_canoniques`) énumèrent « 3 % / 8.5 % / 52 % · USD+DOP ·
# Letter US · Cardnet ». Prose recopiée, jamais confrontée à #9/#10.
# (e) tests/test_generator.py — la liste `for marker in [...]` : l'oracle du
# test lui-même. Le commentaire du bloc ci-dessus (« ces marqueurs sont
# HARDCODÉS DANS LE TEST, une copie de plus, JAMAIS comparée à CLAUDE.md »)
# NOMMAIT ce défaut sans le gater — on ferme la boucle ici.
# La suite tests/ teste des FONCTIONS (dont `check_canonical` — AVEC son propre
# oracle hardcodé), jamais l'ancrage à CLAUDE.md. Même classe EXACTE que le tuple
# d'oracle du test publiciste/branding ancré sur #4. On RÉUTILISE `exp` (6 valeurs
# recomputées de #9/#10 ci-dessus · zéro duplication) : les LISTES (c)/(e) sont
# parsées puis comparées à l'ensemble EXACT (set-diff : absent ET en trop) ; les
# DOCSTRINGS (d) doivent porter CHAQUE valeur normalisée (drift d'un marqueur ⇒
# ROUGE). Un claim/ligne absent échoue AUSSI (traçabilité).
# ============================================================================
if exp is not None:
_want6 = {_pnorm(exp[k]) for k in _num_keys} | {_ai(exp[k]) for k in _txt_keys}
def _norm_marker(tok):
p = _pct(tok)
return _pnorm(p) if p is not None else _ai(tok)
def _list_vs_want6(path, var_re, label):
try:
src = open(path, encoding="utf-8").read()
m = re.search(var_re, src, re.S)
items = ast.literal_eval(m.group(1))
except (OSError, ValueError, SyntaxError, AttributeError) as e:
bad(f"Faisabilité canoniques · {path} {label} illisible/inattendu : {e}")
return
got = {_norm_marker(x) for x in items}
if len(got) != len(items):
bad(f"Faisabilité canoniques · {path} — {label} contient un DOUBLON ({items})")
elif got == _want6:
good(f"Faisabilité canoniques · {path} — {label} == CLAUDE.md #9/#10 (6 marqueurs)")
else:
miss = sorted(_want6 - got); extra = sorted(got - _want6)
detail = (f" · absents={miss}" if miss else "") + \
(f" · en trop={extra}" if extra else "")
bad(f"Faisabilité canoniques · {path} — {label} {sorted(got)} MAIS "
f"CLAUDE.md {sorted(_want6)}{detail} → aligner (ou CLAUDE.md)")
# (c) l'oracle d'enforcement renderer._CANONICAL_MARKERS
_list_vs_want6(f"{D}/faisabilite/generator/genlib/renderer.py",
r"_CANONICAL_MARKERS\s*=\s*(\[.*?\])",
"_CANONICAL_MARKERS (oracle check_canonical)")
# (e) l'oracle du test tests/test_generator.py (for marker in [...])
_list_vs_want6(f"{D}/faisabilite/generator/tests/test_generator.py",
r"for marker in (\[[^\]]*\])",
"oracle du test check_canonical")
# (d) les DEUX docstrings du scorer : chaque valeur normalisée présente dans la ligne
SC = f"{D}/faisabilite/generator/genlib/scorer.py"
try:
sc_lines = open(SC, encoding="utf-8").read().splitlines()
except OSError as e:
bad(f"Faisabilité canoniques · {SC} illisible : {e}"); sc_lines = None
if sc_lines is not None:
# ligne d'énumération = contient un « % » ET « USD » (barème axe 4 + fonction)
enum = [ln for ln in sc_lines if "%" in ln and "USD" in ln]
if len(enum) < 2:
bad(f"Faisabilité canoniques · {SC} — attendu ≥2 énumérations des 6 marqueurs "
f"(barème axe 4 + _score_parametres_canoniques), trouvé {len(enum)}")
else:
for ln in enum:
ai = _ai(ln) # espaces/accents retirés ⇒ « USD+DOP » == « USD + DOP »
miss = sorted(v for v in _want6 if v not in ai)
if miss:
bad(f"Faisabilité canoniques · {SC} — docstring « {ln.strip()[:56]}… » "
f"n'énumère plus {miss} (attendu les 6 de CLAUDE.md #9/#10)")
else:
good(f"Faisabilité canoniques · {SC} — docstring énumère les 6 marqueurs "
f"== CLAUDE.md #9/#10")
# ============================================================================
# Fiches agents · CITATION des constantes CLAUDE.md #10 (devises/format/paiement)
# — même classe d'ANCRAGE que le bloc « paramètres canoniques » ci-dessus, mais