[DTP-Worker 20260802_073526] Sprint 8 · buffer · Ledger d'invariants 2ᵉ FAMILLE : ancrage du COMPTE # INVn ·/validate_bundle de deploy_runbook (11) + acceptance (11) — dialecte « N familles d'invariants » qui avait glissé la clôture

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-02 07:45:26 +00:00
parent 655eeeb4a1
commit 0f4f1b533b
2 changed files with 151 additions and 0 deletions
+63
View File
@@ -1,5 +1,68 @@
# Activity log · 2026-08-02 · Claude Code DTP Worker
## Sprint 8 · buffer · Ledger d'invariants — 2ᵉ FAMILLE (`# INVn ·` / `validate_bundle` / « N familles d'invariants ») : ancrage du COMPTE de `deploy_runbook` (11) + `acceptance` (11)
**Contexte** — Série anti-dérive Sprint 8 (CLAUDE.md #6 « zéro invention de
chiffres »). La classe « ledger d'invariants » (recompute le nombre de contrôles CI
depuis le registre-source des marqueurs numérotés de la fonction `_validate`, jamais
une liste à la main) avait été **déclarée close à 8 générateurs** — mais sur le SEUL
dialecte `# N ·` / « N invariants » / `_validate`(`_validate_bundle`). La mémoire
`invariant-ledger-count-gate` consigne précisément le risque : « un prior *CLOSED
après 7* était FAUX — un style de marqueur différent avait glissé ; re-scanner LES
DEUX styles avant de croire la clôture ». Un **re-scan systématique** a exhumé une
**DEUXIÈME famille** entièrement HORS gate : marqueurs `# INVn ·` (préfixe `INV`)
dans `validate_bundle`, phrasé « N **familles d'**invariants ». DEUX générateurs la
portent :
- `devops/deploy_runbook/deploy_runbook_gen.py` — ledger `# INV1..INV11` dans
`validate_bundle`, compte **« 11 familles d'invariants »** recopié à **3 surfaces
vives** : générateur l.272 (message CLI de succès) · README l.73 (bloc de commande)
· suite tests l.4 (docstring) ;
- `qa/acceptance/acceptance_gen.py` — ledger `# INV1..INV11` dans `validate_bundle`,
compte à **2 surfaces vives** : README l.46 « 11 invariants » · suite tests l.4
« 11 familles d'invariants ». (Le `.py` acceptance ne porte AUCUN compte numéroté
→ surface non exigée.)
**Le « vert trompeur »** — ajouter un contrôle `# INV12 ·` à `validate_bundle` sans
toucher ces chaînes ⇒ README + self-reports + docstrings de test mentent en silence
pendant que la CI applique 12 contrôles. Ni `check_artifacts` (le `.py` source n'est
pas un `out/*.json`) ni les suites `tests/` (FONCTIONS de validation, jamais la prose)
n'attrapent la dérive. **Prouvé (M4 SILENT-GREEN)** : injecter `# INV12 ·` dans
`validate_bundle` (ledger→12, toute la prose reste 11) ⇒ les **3 surfaces
deploy_runbook mordent** « [11] MAIS ledger en compte 12 » — preuve que l'autorité
est le **CODE-registre**, pas la cohérence interne de la prose.
**Particularités** — Ledger PROPRE 1..N compté À PART du schéma (« schéma + N
invariants »). Les mentions NON numérotées de « invariants » (docstrings « invariants
de déploiement/recette », README « Un invariant refuse … ») ne sont pas ancrées par
un chiffre → **aucun faux positif**. Le compte-regex accepte les DEUX formes
(« N invariants » ET « N familles d'invariants ») via un préfixe optionnel
`(?:familles d')?`. Les `daily_reports`/`activity_log` (snapshots datés — ex.
acceptance « 10 » d'avant la croissance 10→11) ne sont PAS des surfaces vives et ne
sont volontairement pas ancrés (aucune dérive à surveiller sur un log figé).
**Gate ajouté** (`ci/check_readme_claims.sh`, bloc « DevOps deploy_runbook + QA
acceptance · IDENTITÉ du COMPTE d'INVARIANTS de `validate_bundle` », juste après le
bloc Mobile) — **paramétré sur les 2 modules** (zéro duplication). RECOMPUTE le
ledger depuis le SEUL registre-source (`# INVn ·` de `validate_bundle`, corps extrait
jusqu'au `def` suivant) et exige : **(a)** ledger CONTIGU 1..N (lacune OU doublon nu
= vrai défaut de registre) ; **(b)** CHAQUE surface déclarée porte ≥1 mention
« N [familles d']invariants » toutes == |ledger|. Une surface sans mention = self-report
ÉVAPORÉ (échec · anti-évaporation #6).
**Vérif** — 7 checks verts sur l'arbre propre (2 ledgers 1..11 + 5 surfaces).
**8 morsures** adversariales, gate lancé SEUL, reverts par `cp` ciblé (jamais
`git checkout` large — cf. incident consigné) : **M1** deploy `.py` 11→12 (b générateur)
· **M2** deploy README 11→12 (b) · **M3** deploy test 11→12 (b) · **M4 SILENT-GREEN**
`# INV12 ·` injecté ⇒ 3 surfaces deploy mordent (autorité = CODE) · **M5** `# INV7 ·`
supprimé ⇒ ledger non contigu (a) + 3 surfaces désync · **M6** acceptance README 11→12
(b) · **M7** acceptance test 11→12 (b) · **M8** compte retiré du README acceptance ⇒
self-report ÉVAPORÉ. Arbre restauré (`git status` propre). Suites unittest re-vertes :
deploy_runbook **29 tests OK** · acceptance **37 tests OK** (générateurs inchangés).
Suite complète re-verte : `check_artifacts` · `check_docs` · `guard_constraints` ·
`check_ci_integrity` · `check_regression` · `check_readme_claims` tous exit 0.
**Les DEUX familles de ledger sont désormais gatées ; re-scanner tout NOUVEAU
dialecte de marqueur (préfixe/phrasé) avant de re-déclarer la classe close.**
## Sprint 8 · buffer · RBAC SPEC §2 — ancrage de l'encadré « Défense en profondeur » (NOM du rôle détenteur de `set_user_permissions` · scope · famille) sur l'artefact byte-gaté
**Contexte** — Série anti-dérive Sprint 8 (CLAUDE.md #6 « zéro invention »). Le §2