Compare commits

..

55 Commits

Author SHA1 Message Date
Claude Code DTP Worker 5ab362153c [DTP-Worker 20260806_214700] Auto exec · session 20260806_214700
CI / Contraintes NON-NÉGOCIABLES (CLAUDE.md) (push) Has been cancelled
CI / Validation JSON (schémas Faisabilité) (push) Has been cancelled
CI / Qualité documentaire (liens + 4Big) (push) Has been cancelled
CI / Reproductibilité des artefacts out/ (build == commité) (push) Has been cancelled
CI / Fraîcheur matrice de régression (run == commité) (push) Has been cancelled
CI / Intégrité du câblage CI (gate agrège tout · gates statiques verrouillés) (push) Has been cancelled
CI / Intégrité des chiffres du README (valeur == artefact cité · (push) Has been cancelled
CI / Intégrité mobile-build.yml (gating portable · activation différée · (push) Has been cancelled
CI / Publiciste · parser + schéma + generator (unittest) (push) Has been cancelled
CI / RBAC · 50 rôles + schéma (unittest) (push) Has been cancelled
CI / Faisabilité · générateur 4 volets + round-trip (unittest) (push) Has been cancelled
CI / RBAC · fixtures ERPNext (Role + Custom DocPerm) (push) Has been cancelled
CI / RBAC · plan User Permission (row-level) (push) Has been cancelled
CI / RBAC · Role Profile (bundles par portail) (push) Has been cancelled
CI / RBAC · run-book d'application unifié (agrégat 3 volets) (push) Has been cancelled
CI / Faisabilité · dossier bancable trilingue FR/EN/ES (push) Has been cancelled
CI / CRM · workflow vente ERPNext (lead → CONFOTUR) (push) Has been cancelled
CI / CRM · DocType porteur OTO Dossier Vente (push) Has been cancelled
CI / CRM · barème commissions vendeurs (push) Has been cancelled
CI / CRM · Financement Bancaire (gate hypothécaire RD) (push) Has been cancelled
CI / Fiscal · e-CF DGII (Compupar) (push) Has been cancelled
CI / Frontend · Workspaces 5 portails rôle (push) Has been cancelled
CI / Legal · DocType CONFOTUR Application (push) Has been cancelled
CI / QA · Audit 5D conformité (push) Has been cancelled
CI / SEO · mots-clés trilingues + schema.org + hreflang (push) Has been cancelled
CI / Chat OTOIA · montage par portail (Custom Block) (push) Has been cancelled
CI / QA · Audit 4Big (95+/100 sur 100% deliverables) (push) Has been cancelled
CI / Démo · Scénarios (run-sheet P07 banquier / P05 client) (push) Has been cancelled
CI / QA · Matrice de régression exhaustive (Sprint 8) (push) Has been cancelled
CI / DevOps · Run-book de déploiement VPS unifié (Sprint 8) (push) Has been cancelled
CI / QA · Matrice d'acceptation / traçabilité MVP (Sprint 8) (push) Has been cancelled
CI / Mobile · config app Expo/EAS (navigation par rôle) (push) Has been cancelled
CI / PIE · manifest de dépendances (Annexe 12 · V10.1) (push) Has been cancelled
CI / E2E baseline Playwright (manuel) (push) Has been cancelled
Mobile Build (EAS) / Préflight config EAS + état secrets (push) Has been cancelled
CI / Gate qualité (agrégat) (push) Has been cancelled
Mobile Build (EAS) / EAS build iOS (App Store (push) Has been cancelled
Mobile Build (EAS) / EAS build Android (Play Store) (push) Has been cancelled
2026-08-06 21:54:20 +00:00
Claude Code DTP Worker 52e8e81799 [DTP-Worker 20260806_211659] VÉRIF axe NEUF « fidélité numérique JS JSON.parse : entiers > 2^53 (corruption SILENCIEUSE) + magnitude hors plage double → Infinity » → CLEAN 0/114 · max tracké 18.88M (~8 ordres sous 2^53) · 3e sommet trilogie JSON.parse après NaN/Infinity · teeth 8/8 + bout-en-bout (inject 2^53+7 flagué) · rejouable · NON gate (#5 occurrence-zéro) · 0 édition de prod
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 21:21:03 +00:00
Claude Code DTP Worker b88b7051e0 [DTP-Worker 20260806_204654] VÉRIF axe NEUF « cohérence shebang ↔ bit-exécutable git ↔ interpréteur sur l'arbre tracké » → CLEAN 409 fichiers · 9 exec (tous #!bash) · 46 shebangs · 37 shebang-non-exec by-design (.py -m / lib.sh sourcé) · 0 exec-sans-shebang/CRLF/BOM/mismatch/drift · teeth 9/9 (3 spare + 6 bite) · 0 édition de prod
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 20:50:58 +00:00
Claude Code DTP Worker 27c2bd29ff [DTP-Worker 20260806_201644] VÉRIF axe NEUF « intégrité STATIQUE de la couche shell-script : parse-validité bash -n + fidélité du code de sortie des gates » → CLEAN 10/10 parse · 8/8 exit load-bearing · lib.sh sourced-only · teeth-prouvés (syntax-error + exit-0-mutant fake-green) · 0 édition de prod
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 20:22:04 +00:00
Claude Code DTP Worker 11f158a9d2 [DTP-Worker 20260806_194635] VÉRIF axe NEUF « indépendance à l'ORDRE d'exécution des tests (couplage inter-test par état de classe/module partagé) » → CLEAN 25 suites/651 tests · rev_method + rev_full teeth-prouvés (intra+inter-classe) · 0 édition de prod
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 19:51:01 +00:00
Claude Code DTP Worker 55ff296ac8 [DTP-Worker 20260806_191634] VÉRIF axe NEUF « découverte & COLLECTE des tests par unittest discover (fichier test*.py · sous tests/ · classe héritant de TestCase) » → CLEAN 25 fichiers/113 classes · 0 édition de prod
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 19:20:52 +00:00
Claude Code DTP Worker 40b023c2eb [DTP-Worker 20260806_184624] VÉRIF axe NEUF « portabilité des NOMS de fichiers / structure arbre git (collision-casse · réservés Windows · chars illégaux · dot/espace terminal · symlinks) » → CLEAN 409 fichiers · 0 édition de prod 2026-08-06 18:50:04 +00:00
Claude Code DTP Worker 558225a74d [DTP-Worker 20260806_181623] VÉRIF axe NEUF « conformité JSON STRICTE ECMA-404 / JS JSON.parse : aucun NaN/Infinity non-strict » → CLEAN · 0 édition de prod
Python json.load (validate_json.sh) ACCEPTE NaN/Infinity/-Infinity par défaut ;
le JS JSON.parse de la Console Helios lève SyntaxError dessus → un artefact NaN
(dérivé div-par-zéro sérialisé allow_nan=True) passerait tous les gates + byte-repro
tout en cassant le rendu navigateur = faux-vert invisible à la chaîne Python.
Détecteur stdlib json.loads(parse_constant=raise), teeth 5/5 (NaN/Infinity/-Infinity
MORDENT, float+chaîne 'NaN' épargnés) + e2e mutant sur fichier réel flagué.
CLEAN 114/114 out/*.json. run_ci 33 PASS 0 FAIL 0 SKIP inchangé, rejouable, pas de gate (#5).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 18:19:46 +00:00
Claude Code DTP Worker be36d6600f [DTP-Worker 20260806_174619] VÉRIF axe NEUF « intégrité des ancres-fragment Markdown ](#slug) : résolvent-elles vers un titre réel ? » → CLEAN · 0 édition de prod
Axe FRAGMENT jamais balayé : check_docs valide la cible-FICHIER d'un lien mais RETIRE le #slug (link=${link%%#*}) et ignore les ancres pures → un [label](#titre) dont le titre est renommé/typo passe au vert (fichier existe, saut d'ancre mort, silencieux). Détecteur stdlib (slug GitHub/Gitea, accents conservés, code-spans neutralisés) sur 379 .md → 1 seul lien-ancre réel (README:20 → ## Directives Michel...) résout, 0 pendante ; 2 ](#frag) en code-span écartés. Teeth-prouvé (valide True, mutant-typo False). run_ci 33 PASS 0 FAIL 0 SKIP inchangé, 0 édition prod, rejouable, pas de gate (#5).
2026-08-06 17:49:03 +00:00
Claude Code DTP Worker 0393ea7b48 [DTP-Worker 20260806_171614] VÉRIF axe NEUF « intégrité référentielle artefact→FICHIER : les chaînes-chemin des out/*.json résolvent-elles sur disque ? » → CLEAN 0 pendante · 0 édition de prod
Classe NEUVE = traiter toute valeur-chaîne d'un out/*.json qui matche un motif nom-fichier
(.json/.md/.py/.sh) comme une RÉFÉRENCE DE FICHIER et vérifier qu'elle résout sur disque.
Distincte des axes référentiels existants qui résolvent des SLUGS (role/portail, projet/entité),
re-dérivent des COMPTES (manifest nb_*) ou comparent des VALEURS (cross-artifact). Aucun gate ne
parse une valeur JSON comme chemin : check_docs ne voit que les liens Markdown, check_artifacts
byte-repro rejoue une chaîne pendante à l'identique -> un generated_from/audited_artifacts/evidence/
roadmap_ref pointant un spec renommé ou déplacé = faux-vert invisible vs #6 Zéro invention.

Détecteur stdlib : résolution multi-bases (out/ · module · famille/grand-parent · deliverables ·
racine · rbac/) + fallback bare-basename cross-module. 124 valeurs nom-fichier -> 48 path-relatives
+ 27 bare-basename TOUTES résolvent · 49 conceptuelles/runtime exclues by-design (24 capabilities
OTOIA VPS dont chat.py absent-du-repo · 23 demo evidence relatives-au-module-cible · 2 PIE
storage_layout VPS) · 0 pendante. Dents prouvées bout-en-bout : baseline résout, 4 mutants
(spec renommé / directive typo / schéma fantôme / chemin inexistant) MORDENT tous.

VÉRIF pure : 0 fichier de prod modifié · 0 chiffre inventé (#6) · 0 commande VPS (#8) · aucun gate
ajouté (#5, occurrence-zéro, détecteur rejouable). run_ci 33 PASS 0 FAIL 0 SKIP inchangé.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 17:22:16 +00:00
Claude Code DTP Worker 2ded65bbb4 [DTP-Worker 20260806_164612] VÉRIF axe NEUF « intégrité de la FORME scalaire JSON (type int-vs-float-vs-str, pas la valeur) » des 57 out/*.json → CLEAN · 0 édition de prod
Axe NEUF absent mémoire : tous les axes numériques testent la VALEUR (accord inter/intra, re-dérivation, arithmétique) ou la forme-date ; aucun ne teste la FORME scalaire JSON. Un compte '3.0'/'"3"' au lieu de 3 se lit pareil mais casse type:integer / == strict / colonne typée = aveugle au byte-repro ET aux oracles (tous type:number accepte int+float, un sequence_id float passe). 3 sous-checks teeth-prouvés (/tmp stdlib) : (A) cohérence type intra-fichier par chemin structurel, (B) clés-compte nb_*/…_total/passed = int obligatoire, (C) 0 NaN/Infinity. Dents : un sequence_id int-parmi-floats MORD, nb=5.0/"44" MORD, comptes réels épargnés. Résultat CLEAN : B=0 C=0 ; A flague seulement run_sheet valeur (colonne clé-valeur hétérogène by-design) ; divergences inter-fichiers = collisions de nom per-module. 2 formes délibérées NON-défauts (sequence_id float = cast wslib/frappe.py:162 fidélité Frappe Float ; is_submittable 0/1 int = convention DocType Frappe). run_ci 33 PASS 0 FAIL 0 SKIP inchangé, rejouable, pas de gate (#5)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 16:52:27 +00:00
Claude Code DTP Worker d074250084 [DTP-Worker 20260806_161610] VÉRIF axe NEUF « intégrité arithmétique des champs DÉRIVÉS des artefacts » → CLEAN · 0 édition de prod
Classe NEUVE vs tous les axes numériques passés : ceux-ci couvrent la CARDINALITÉ
(manifest nb_*/_total = len payload), l'accord INTER-artefacts d'un singleton, et les
doublons d'ensemble. Ici on recalcule une DÉRIVATION (moyenne/taux %/somme-pondérée/écart/
verdict-seuil + nombres embarqués dans la prose) DEPUIS LES ENTRÉES BRUTES. Subtilité teeth :
check_artifacts + test_build_egale_commite comparent la sortie du générateur au golden committé
= attrapent la DÉRIVE mais PAS un bug-de-formule-régénéré-en-même-temps (code+golden bougent
ensemble → vert) ; seul un recalcul premier-principe ferme cette classe. Faux-piste honnête
corrigée : overall_percent semblait non-testé (grep 0 assert) mais 3 mutations gate.py in-place
(mean /len→/3, doc pct *100→*90, prose paid/req inversé, restaurées git checkout) FAIL toutes
via build==committed → protégé-dérive ; la lacune résiduelle est la formule-avec-régén.

CLEAN : financement gate_status_example (overall=moyenne(4%)=39.1 · 3 %/condition · remaining=
required-paid=14000 · 5 nombres prose reasons↔struct) · audit_4big 24 modules (applicable/earned=
Σpoids · score=round(earned/applicable×100) · verdict=score≥95) + totals (pass_rate_pct) · banques
6× ordre LTV 0≤min≤max≤100 · commissions bornes taux. Détecteurs stdlib teeth-prouvés (mutants
overall 39.1→52.1, prose paid→99999, score→77 MORDENT ; artefact réel passe). NON promu en gate
(#5, occurrence-zéro, rejouable). 0 commande VPS (#8). run_ci 33 PASS 0 FAIL 0 SKIP inchangé.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 16:24:25 +00:00
Claude Code DTP Worker 27d1117a2d [DTP-Worker 20260806_154606] VÉRIF axe NEUF « intégrité temporelle des tokens datés » → CLEAN · 0 édition de prod · toute date YYYY-MM-DD / YYYYMMDD_HHMMSS construit-elle un datetime.date valide (mois 1-12, jour valide, bissextiles stdlib) et le nom-fichier des journaux 05_activity_log/ = la 1re date de leur en-tête ? classe NEUVE = jusqu'ici tous les axes vérifient des VALEURS (comptes/slugs/schémas/encodage NFC/byte) ; ici la FORME-DATE elle-même : un 2026-02-30 / 2026-13-01 / 20260840_… se lit comme date mais n'existe pas = date inventée/typo, faux-vert vs #6 « Zéro invention », aveugle à tous les gates (aucun ne parse les dates) ; détecteur stdlib datetime.date teeth-prouvé bout-en-bout (baseline réel [], mutants 2026-08-46 & 2026-02-30 MORDENT, valides épargnés ; piège corrigé = bornes digit-only (?<!d)…(?!d) car le \b naïf rate les session-ids _HHMMSS, _ étant word-char) ; 379 fichiers trackés, 289 tokens ISO + compacts → 0 date invalide + 0 mismatch nom↔en-tête ; run_ci 33 PASS 0 FAIL 0 SKIP inchangé, rejouable, pas de gate (#5) 2026-08-06 15:49:39 +00:00
Claude Code DTP Worker fdb0632cf6 [DTP-Worker 20260806_151604] VÉRIF axe NEUF « intégrité référentielle projet-code ↔ projet-nom canonique dans les artefacts » → CLEAN 128/128 · sœur de role-portail-referential-integrity mais sur la dimension PROJET/ENTITÉ : tout P0X + nom-projet + les 8 entités des out/*.json résolvent-ils au canon CLAUDE.md §Projets/§Entités, et l'appariement code↔nom est-il bon ? distinct de claude-md-constant-anchor (qui gate des COPIES) = ici on chasse la référence PENDANTE/mauvais appariement, faux-vert contre #6 « Zéro invention » ; détecteur stdlib teeth-prouvé (P02←Nakua MORD, P02→P10 pendante flaguée) ; 128 objets 1:1 0 mismatch + agrégat 9/9 + 0 code pendant + 8/8 entités ; faux-pos écartés = prose forme-courte « Aqua Terra » (P07) ; 0 édition de prod, run_ci 33 PASS 0 FAIL 0 SKIP, rejouable, pas de gate (#5) 2026-08-06 15:22:13 +00:00
Claude Code DTP Worker caeb06be5f [DTP-Worker 20260806_144555] VÉRIF axe NEUF « forme de normalisation Unicode (NFC vs NFD) des sources » → CLEAN 387/387 (369 non-ASCII, 0 non-NFC) · sibling byte-encoding-sweep au niveau NORMALISATION : un é décomposé/NFD se lit à l'identique mais casse tout grep/assert littéral NFC + est aveugle au byte-repro = faux-vert de gate ; détecteur stdlib teeth-prouvé bout-en-bout (flague NFD, épargne NFC, démontre le grep-miss) ; 0 édition de prod, run_ci 33 PASS 0 FAIL 0 SKIP, rejouable, pas de gate (#5)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 14:49:06 +00:00
Claude Code DTP Worker 5d5e986fa6 [DTP-Worker 20260806_141554] VÉRIF axe NEUF « accord numérique INTER-artefacts d'un concept-singleton partagé » (out/*.json ↔ out/*.json, distinct de l'intra-artefact et du code/prose↔artefact) → CLEAN · 0 édition de prod
Question neuve : quand un même concept-singleton plateforme apparaît comme scalaire dans deux out/*.json indépendants, les valeurs s'accordent-elles ? Une divergence silencieuse ship verte car aucun gate ne compare deux artefacts entre eux. Détecteur teeth-prouvé (57 fichiers ; position GLOBALE sans indice [i] = singleton vs PER-ROW = compte-de-ligne) : mutation cible_rbac_roles 50→49 dans un manifest → MORD. Résultat CLEAN : tous les singletons plateforme s'accordent (cible_rbac_roles=50, ci_modules_count/modules/suites=24, portails=5, doctypes_uniques=45, custom_docperm=116, role_profiles=6, min_score=100, pass_score=95).

TRAP documenté : « même nom = même concept » sur-signale — fields/data_fields/permissions/roles/sections/pass divergent car chacun décrit SON propre DocType/suite (per-module-local, pas un singleton). Seul nom SURCHARGÉ divergent = roles_couverts 50 (tous les role-profiles) vs 44 (rôles des 5 portails business = 50 − 6 plateforme) = by-design, les deux re-dérivés de rbac_50_roles.json.

0 gate ajouté (#5, occurrence-zéro rejouable), 0 commande VPS (#8), run_ci 33 PASS 0 FAIL 0 SKIP. Canal stakeholder daily_reports porté 3710253→HEAD.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 14:22:46 +00:00
Claude Code DTP Worker 04f4c21778 [DTP-Worker 20260806_134554] VÉRIF axe NEUF « l'artefact COMMITÉ sur disque conforme à son schéma ? » (fichier réel vs oracle, pas l'objet en-mémoire reconstruit) → CLEAN 57/57
8e axe-schéma : les 7 axes existants examinent LE SCHÉMA ; celui-ci examine LE FICHIER LIVRÉ. La mémoire notait le trou « jsonschema valide un objet en-mémoire, pas le flat out/ commité » — refermé ici. Chaîne de garde traçable pour les 57 payloads : schéma-whole · schéma-prop+byte-repro · wrap/split byte-repro d'un objet validé · ré-run byte-compare (regression_run via check_regression.sh l.53-70). Les 4 « no-fit » tous by-design (workflow.json wrap-liste fixtures Frappe · acceptance_matrix bundle moins manifest · run_sheet vue rendue · regression_run snapshot d'exécution). 0 fichier livré à forme non-gardée.

Détecteur jsonschema 3.2.0 teeth-prouvé (clé-parasite additionalProperties:false → no-fit ; scalaire → no-fit, 2/2 MORDENT), rejouable /tmp hors réseau, 0 édition de production, 0 artefact touché, run_ci 33 PASS 0 FAIL 0 SKIP, pas de gate (#5, occurrence-zéro)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 13:53:07 +00:00
Claude Code DTP Worker 1839f521aa [DTP-Worker 20260806_131551] VÉRIF axe NEUF « cohérence draft/keyword des 26 oracles-schémas » ($schema déclaré vs idiomes cross-draft) → CLEAN 26/26 (tous draft-07, 13/13 porteurs=definitions jamais $defs, 0 bool exclusiveMinimum draft-04, 0 mot-clé post-07 silencieusement ignoré) — 7e axe-schéma jamais couvert : un mot-clé mal-déclaré est ignoré/re-typé par le validateur = faux-vert invisible aux 6 axes existants ; détecteur maison stdlib teeth-prouvé 5/5 (mutants exclusiveMinimum:true/id/required:true/$defs/unevaluatedProperties MORDENT), 0 édition de prod, run_ci 33 PASS 0 FAIL 0 SKIP, pas de gate (#5) 2026-08-06 13:19:45 +00:00
Claude Code DTP Worker bea5d49aab [DTP-Worker 20260806_124544] VÉRIF axe NEUF « atteignabilité transitive d'une assertion » → CLEAN 0/651 (aucun test run-only faux-vert) + 1 durcissement : test_validate_exits_zero passait sans assertion explicite (mordait implicitement via SystemExit) → assertEqual(main(["validate"]),0) strictement plus fort ; détecteur AST teeth-prouvé, résolution transitive du graphe d'appels (évite 40 faux-positifs de délégation _expect_error/_breaks), 0 logique de prod touchée, run_ci 33 PASS 0 FAIL 0 SKIP, pas de gate (#5)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 12:50:26 +00:00
Claude Code DTP Worker 4aea5bddf7 [DTP-Worker 20260806_121542] VÉRIF axe NEUF « cohérence interne des 26 oracles-schémas » (required-vacuité + auto-contradiction const/enum/default) → CLEAN 26/26 (1405 nœuds · 317 checks · 0 nœud insatisfiable), 2 détecteurs maison teeth-prouvés (4/4 mordent) — 6e axe-schéma, faux-vert impossible à voir par les 5 axes existants ; 0 édition de production, run_ci 33 PASS 0 FAIL 0 SKIP, pas de gate (#5) 2026-08-06 12:20:16 +00:00
Claude Code DTP Worker 6c05538efb [DTP-Worker 20260806_114542] VÉRIF axe neuf « le skip python -S de l'oracle jsonschema masque-t-il un écart enum/const/schéma ? » → CLEAN (7 suites dé-skippées OK, rbac 0 err, seul phantom enum {WAG}=NON-DÉFAUT), détecteurs enum+const maison teeth-prouvés
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 11:52:13 +00:00
Claude Code DTP Worker 27cfe2fe59 [DTP-Worker 20260806_111534] VÉRIF axe neuf « intégrité référentielle des $ref des 26 oracles-schémas » → CLEAN 108/108 (0 pendouillant/externe/orphelin), détecteur teeth-prouvé (double faux-vert jsonschema/maison)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 11:22:09 +00:00
Claude Code DTP Worker 3710253c02 [DTP-Worker 20260806_104533] FIX couverture · oracle orphelin brief.schema.json câblé à un test → le SEUL des 26 *.schema.json non enforced
Constat: faisabilite/generator/brief.schema.json, documenté « Contrat d'entrée »
et sibling de version/projets_master (tous deux test-enforced), n'était validé
par AUCUN test — _validate_brief() ne garde que le code projet, jamais la forme
complète du brief; un brief drifté hors contrat passait inaperçu.

Fix (teeth): test_input_briefs_validate_against_brief_schema valide les 2 fixtures
contre brief.schema.json via le validateur maison Publiciste (zéro-pip, toujours
exécuté, pas de skip sous python -S). Conformité pré-vérifiée sous validateur
maison ET oracle jsonschema. L'« incomplet » est conforme au sens schéma
(null admis) — incomplet seulement au sens sémantique (prix→placeholders #6).

Cascade régénérée (générateurs, jamais à la main #6): regression_plan/run/MANIFEST
16→17 · totaux 624→625 exécutés / 607→608 passés / 17 skippés · quality_report
evidence 16→17. Prose gatée réalignée (le gate check-readme-claims a mordu):
README module + fiches faisabilite/qa/erpnext_backend. Prose ungatée: GAP_ANALYSIS
16→17 + nouveau bloc daily_report (blocs currency antérieurs = snapshots datés,
non réécrits).

0 gate ajouté (#5) · 0 chiffre à la main (#6) · 0 commande VPS (#8).
run_ci.sh = 33 PASS · 0 FAIL · 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 10:56:35 +00:00
Claude Code DTP Worker d9668d6079 [DTP-Worker 20260806_101528] VÉRIF axe neuf « fermeture & complétude des 26 oracles-schémas » → 1 anomalie (financement) investiguée = NON-DÉFAUT
Complémentaire de schema-oracle-teeth-audit (non-vacuité) : audite la FERMETURE
(additionalProperties:false) + la COMPLÉTUDE (properties ⊇ clés émises) des 26
*.schema.json. 23/26 entièrement fermés (convention). Seule anomalie réelle :
financement.schema.json — top `additionalProperties:true` explicite (3 pairs CRM
fermés) + 8 nœuds sous-énumérés (note/resume/titre/endpoint/couleurs/source_*).
Le validateur maison honore pourtant additionalProperties.

Verdict NON-DÉFAUT : souplesse DÉLIBÉRÉE (structure validée serré via pattern/enum/
counts min-max ; seuls champs DESCRIPTIFS libres — même motif que seo @graph[]
JSON-LD + brief=schéma d'ENTRÉE) ET transitivement couverte par test_build_egale_
commite (byte-repro out/ == build frais → toute dérive nom/présence RED via
check_artifacts). Fermer = churn (#5) à risque de faux-rejet, 0 dent nette gagnée.

Faux positif écarté : mobile top = additionalProperties:false (fermé) ; les 4
« under-spec » = artefacts de reconstruction plate (objets imbriqués). Vérif
authoritative = build_bundle réel, pas une reconstruction depuis out/*.json.

0 prod édité · 0 schéma modifié · 0 artefact reconstruit · 0 gate (#5) · 0 chiffre
saisi main (#6) · 0 commande VPS (#8). run_ci 33 PASS 0 FAIL 0 SKIP (inchangé).
Éditions : journal + mémoire schema-oracle-closedness-not-defect (hors repo).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 10:24:32 +00:00
Claude Code DTP Worker e87f5f56af [DTP-Worker 20260806_094524] VÉRIF axe teeth neuf « tests silencieusement fantômes (shadowing) » → CLEAN 25/25
Nouvel axe absent de la mémoire, distinct de module-suite-teeth-mutation (mute la LOGIQUE) et
schema-oracle-teeth-audit (audite l'ORACLE) : cible le HARNAIS de test lui-même. 3 cas où une
méthode est définie mais unittest discover ne l'exécute jamais, sans qu'aucun gate ne le voie —
(a) def test_x dupliqué dans une classe (Python garde la dernière liaison), (b) class TestFoo
dupliqué dans un fichier (2ᵉ masque 1ʳᵉ), (c) def test_* niveau-module (discover ne le lance pas).
Trou réel : un shadow passe par absence ET ferait SUR-compter check_readme_claims (compte textuel
des def test_). Détecteur AST teeth-prouvé sur sonde synthétique (3/3 mordent). Balayage réel
CLEAN 25/25 fichiers (0 méthode-dup, 0 classe-dup, 0 test niveau-module). Sweep rejouable, NOT a
gate (occurrence-zéro, #5). run_ci 33 PASS 0 FAIL 0 SKIP · 0 prod édité · 0 artefact reconstruit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 09:49:34 +00:00
Claude Code DTP Worker 44712cbdfa [DTP-Worker 20260806_091519] FIX doc · axe neuf « compte de colonnes des tables Markdown » → ligne orpheline dans le TEMPLATE canonique de faisabilité
Sweep repo-wide des tables .md (en-tête↔séparateur↔corps, | échappés ignorés) → 3 hits :
1 vrai défaut + 2 faux positifs (| littéral dans code-span, dans snapshots historiques immuables).

DÉFAUT : TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md §5.2 « Financier bancable » — table à en-tête
4 colonnes, lignes 4.4→4.12 toutes à 4 cellules, MAIS ligne 4.13 en portait 5 (scindait
description + placeholder {{regime_fiscal}} en 2 cellules → colonne orpheline visible pour cette
seule ligne, dans un template CANONIQUE que le générateur 4 volets / Publiciste / batch S4 doivent
reproduire). FIX : fusion des 2 fragments dans l'unique 4e colonne avec « · » (idiome des sœurs).

SÛRETÉ : check_readme_claims.sh:5765 lit ce template mais n'ancre que les lignes #9 (l.144-146) /
#10 (l.149-151) ; 4.13 ne porte ni #9/#10/pourcentage-gras → aucune regex touchée ; les 5 surfaces
d'ancrage restent vertes post-fix. run_ci = 33 PASS · 0 FAIL · 0 SKIP · 0 artefact reconstruit ·
0 gate ajouté (#5) · 0 chiffre inventé (#6) · 0 VPS (#8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 09:20:11 +00:00
Claude Code DTP Worker 9acd8441dc [DTP-Worker 20260806_084514] VÉRIF axe neuf « dents de l'ORACLE jsonschema » (26 *.schema.json) → CLEAN 26/26, détecteurs à dents prouvées
Nouvel axe: la FORCE de la couche oracle elle-même (distinct des dents de logique-générateur). ~20 modules ont un test_schema_oracle qui valide le build-mémoire contre un *.schema.json commité; un schéma vide ({} / type:object sans required) ou malformé rendrait cet oracle faux-vert (accepte tout) — classe ungatée, byte-repro & suites aveugles à la force du schéma. Audit 26/26: tous valides Draft-N + non-vides (required+properties, kw 3..103). Détecteurs de l'audit prouvés: validité mord un schéma malformé, dents mord {} et {type:object}, 0 faux positif sur rbac.schema. Connexes CLEAN: role_id→erpnext_role_name = fonction sur 57 artefacts (0 conflit); oracle exécuté non-skippé sous run_ci (python3 nu, jsonschema 3.2.0); 0 TODO/stub prod. Lecture-seule, occurrence-zéro, rejouable → PAS un gate (#5). run_ci 33 PASS 0 FAIL 0 SKIP · 0 prod édité · 0 artefact reconstruit · 0 gate ajouté (#5)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 08:52:44 +00:00
Claude Code DTP Worker 42d54b045f [DTP-Worker 20260806_081509] VÉRIF récurrence bug set-semantics (48276ee) sur TOUS les artefacts → CLEAN, détecteur à dents prouvées
Généralisation de la chasse au dernier bug générateur commité (48276ee : champ « ensemble » roles_rbac_utilises portant un doublon silencieux, bâti en itérant des slots). Scan des 57 out/*.json commités en 2 formes : SCALAR-DUP (forme exacte du bug, tableau scalaire à valeur répétée) = 0 hit/57 ; OBJ-DUP (clé d'identité dupliquée) = 33 hits, tous BY-DESIGN (doctype/permlevel de lignes de fixtures Frappe + role_id de journaux d'événements — répétition légitime, PAS un ensemble). Distinction clé outillée : champ-ensemble (distinct requis) vs journal-événements/lignes-fixtures. Les 6 MANIFEST portant roles_rbac_utilises tous distincts (commissions 4/4, dossier_vente 7/7, financement 3/3 [fix tient], workflow_vente 7/7, ecf 1/1, confotur 3/3). Dents prouvées par mutation en mémoire (forme plantée mord, pas de faux positif) → CLEAN opposable. Sweep lecture-seule, occurrence-zéro, rejouable → pas un gate (#5). 0 prod éditée · 0 artefact reconstruit · 0 gate ajouté · run_ci 33 PASS 0 FAIL 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 08:21:06 +00:00
Claude Code DTP Worker def4706de3 [DTP-Worker 20260806_074504] VÉRIF axe méta « bijection de câblage CI » (ci/*.sh ↔ jobs ci.yml ↔ miroir run_ci) → CLEAN + auto-protégé. 8/8 gates statiques câblés dans ci.yml (0 orphelin) ; run_ci dérive gate.needs sans nom en dur (0 réf/7, 1 commentaire) donc dérive local↔CI impossible par construction ; prose « 7/7 · 8 statiques verts » = dents de mutation pédagogiques (KEEP). 1 sous-classe ungatée notée (script disque sans job → gate mort silencieux ; occurrence-zéro ⇒ sweep rejouable, pas gate #5). Currency écartée (2 commits depuis e786c12 = doc/comment, 0 sortie changée). run_ci 33 PASS 0 FAIL 0 SKIP · 0 prod édité · 0 artefact reconstruit · 0 gate ajouté (#5)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 07:50:27 +00:00
Claude Code DTP Worker 4c741a7118 [DTP-Worker 20260806_071503] DOC anti-footgun in-fiche — colonne « Sortie » de frontend_console/AGENT.md : documenter l'omission MANIFEST volontaire
Un Explore adversarial a re-flagué (2e fois) la cellule « Sortie » du chat_otoia
comme « manque MANIFEST.json » — faux positif connu (fiche-sortie-cell-omits-manifest-
by-design) : les DEUX rangs (portails+chat) listent le payload seul, MANIFEST omis par
convention, docstrings/READMEs énumèrent les 3 (byte-gatés). La récurrence prouve un
footgun non documenté (brûle des cycles d'audit, risque un fix #5/#6 cassant le gate
regex-parsé). Mitigation : blockquote « Note de lecture » après la table, rédigé pour
éviter les regex ancrées du gate (aucun compteur cartes/liens/rôles ni **N tests**).

check_readme_claims PASS · check_docs PASS · run_ci 33 PASS 0 FAIL 0 SKIP · 0 artefact
reconstruit · 0 gate ajouté (#5) · 0 chiffre inventé (#6) · 0 commande VPS (#8)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 07:23:09 +00:00
Claude Code DTP Worker ddcafc58c0 [DTP-Worker 20260806_064502] DOC code-site — commentaire anti-footgun sur renderer._CANONICAL_MARKERS (oracle d'enforcement à garder indépendant)
Investigation: les 6 marqueurs canoniques #9/#10 existent en ≥4 endroits. Hypothèse
« (c) renderer._CANONICAL_MARKERS + (d) l'oracle du test sont des copies non gatées
→ dériver de model.CANONICAL (source unique) ». RÉFUTÉE par ./run_ci.sh (check-readme-claims
RED): la 2e moitié du gate ast.literal_eval STATIQUEMENT ces 2 listes et les set-diffe vs
CLAUDE.md → déjà gatées. Et surtout: check_canonical() PROUVE que le rendu (bâti DEPUIS
model.CANONICAL) émet chaque valeur; le dériver de CANONICAL rend le contrôle tautologique
(vert vacux). EXCEPTION à fix-vs-gate-transitively-protected-constant (qui vise les copies
PASSIVES; un oracle d'enforcement est ACTIF, sa duplication EST le test). Revert intégral
des 2 éditions (test byte-identique). Seul survivant: +5 lignes de commentaire remontant la
raison (indépendance de l'oracle) au site de code, autrement enfouie dans le script CI.
Sortie inchangée (commentaire pur), check_artifacts byte-identique.
run_ci 33 PASS 0 FAIL 0 SKIP · 0 artefact reconstruit · 0 gate ajouté (#5) · 0 chiffre inventé (#6)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 06:53:04 +00:00
Claude Code DTP Worker e4b3488c7e [DTP-Worker 20260806_061455] CURRENCY canal stakeholder porté de 48276ee au HEAD e786c12 — fix prose-facts-drift: le snapshot daily_reports affirmait « dernière prod = 48276ee, reste 0-édition » alors qu'e786c12 édite README.md (3 href, fix label↔cible). Sur les 5 commits depuis 48276ee: 4 journal-only + 1 édition dépôt réelle tabulée. Chiffres re-dérivés (8/25/33/624/607/17) inchangés (e786c12 ne touche que des href). check_docs PASS · run_ci 33 PASS 0 FAIL 0 SKIP · 0 artefact reconstruit · 0 gate ajouté (#5) 2026-08-06 06:20:02 +00:00
Claude Code DTP Worker e786c128b2 [DTP-Worker 20260806_054454] FIX doc — lien Markdown label↔cible incohérent dans README.md
Axe NEUF (absent mémoire): liens `[`label`](cible)` où le label code-span est un
chemin de fichier EXISTANT dont le basename diffère de la cible href. check_docs
prouve que la cible résout, jamais que le label la désigne — un Cmd-clic sur
`ci/guard_constraints.sh` atterrissait sur `ci/README.md` (mauvais fichier).

Balayage git ls-files '*.md' → 3 occurrences, toutes README.md (L54 x2 + L75).
Les scripts nommés existent + sont git-trackés (gates) ⇒ FIX = pointer chaque
label vers le fichier qu'il nomme. label==cible, navigation véridique, check_docs
toujours vert. Re-balayage mismatch → 0.

Axe éliminé au passage (CLEAN, non re-flaggé): chemins-fantômes backtick — 2
survivants = faux positifs (label de lien à vraie cible · résolution sous-arbre
confotur/cflib). run_ci = 33 PASS · 0 FAIL · 0 SKIP. 0 gate (#5, origine isolée),
0 artefact rebuild, 0 chiffre inventé (#6), 0 VPS (#8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 05:49:28 +00:00
Claude Code DTP Worker a678534b8b [DTP-Worker 20260806_051453] VÉRIF indépendante — NOUVELLE famille objective « portabilité runtime / intégrité d'encodage » (3 axes neufs, absents de la mémoire, gardés par AUCUN gate) sur les fichiers commités : (1) encodage — 379 fichiers texte : 0 BOM · 0 UTF-8 invalide · 0 caractère de contrôle/surrogate · 114/114 JSON parseables · (2) fins de ligne — 0 CRLF (LF pur) · (3) py_compile — 144/144 .py compilent (dents au-delà des 25 suites : un helper *lib/ non importé par un test resterait vert malgré une syntaxe cassée). → CLEAN · dents réelles mais occurrence-zéro ⇒ sweep rejouable, PAS un gate (#5). Pré-vérif : 0 TODO/stub réel en prod (tous les « placeholder » = pattern #6). Canal stakeholder déjà courant (dernière prod = 48276ee). → 0 édition de production 2026-08-06 05:20:07 +00:00
Claude Code DTP Worker 12ec9d0711 [DTP-Worker 20260806_044449] VÉRIF indépendante — 2 axes objectifs NEUFS: (1) clés JSON dupliquées sur 114 fichiers commités [json.load garde le dernier, byte-repro aveugle] → 0 · (2) re-dérivation des champs-compte MANIFEST depuis le payload réel (portails nb_liens/cartes/roles+agrégats · chat nb_roles/kdt · mobile nb_roles · rbac roleprofile nb_roles · audit_5d controls_total) → 0 écart. Faux positif Card-Break/Link écarté (nb_liens=Σtype==Link, par design). → CLEAN · 0 édition de production
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 04:49:35 +00:00
Claude Code DTP Worker 4bc98198b1 [DTP-Worker 20260806_041444] VÉRIF indépendante — NOUVEL axe objectif: intégrité référentielle des slugs rôle+portail inter-artefacts (980 refs rôle + 66 portail vs rbac_50_roles.json) → CLEAN · 0 édition de production
Sweep rejouable de tous les out/*.json: 0 slug de rôle non résolu vs les 50 ids canoniques;
6 tokens portail hors portails_business = non-défauts vérifiés (5 valeurs icon ERPNext du champ
mobile + le 6e portail technique legitime plateforme). Axe jamais balayé, distinct de
docstring/currency. 0 prod, 0 artefact rebuild, 0 gate (#5), 0 chiffre inventé (#6), 0 VPS (#8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 04:21:37 +00:00
Claude Code DTP Worker b2749587c0 [DTP-Worker 20260806_034434] CURRENCY canal stakeholder porté de a8342e9 au HEAD 48276ee + re-vérif indépendante de la dernière prod
Le daily_reports/2026-08-06.md (rédigé session 011419, attestait HEAD a8342e9) ne
consignait pas les 2 jalons de production 08-06 postérieurs : 354a687 (FIX help-text
argparse seo/seo_gen.py nommant des sorties inexistantes) et 48276ee (FIX générateur
crm/financement_bancaire — MANIFEST.roles_rbac_utilises 4/3 dup → 3/3 distinct, artefact
reconstruit). Mémoire two-logging-channels : garder le canal stakeholder courant.

Re-vérification INDÉPENDANTE de la dernière prod (48276ee) avant de consigner :
MANIFEST courant = 3 objets distincts (compta-tresorier/ventes-conseiller/ventes-directeur),
0 doublon ; balayage surfaces sœurs (README/finlib/tests) = aucune ne cite l'ancien « 4 »
ni liste 4-entrées → 0 dérive résiduelle (motif twin-fix-sweep-ALL, propre) ; champ
appropriément ungaté #5 (depuis l'état propre check_artifacts mord une régression future).

Ajout section currency au daily report : tableau des 2 jalons (nature+opposabilité merge),
re-vérif 48276ee, état courant re-dérivé au HEAD 48276ee (8 statiques + 25 suites = 33 PASS ;
régression 624/607/17-skip = PASS). 0 prod éditée, 0 artefact rebuild, 0 gate (#5),
0 chiffre inventé (#6 — tout recomputé), 0 VPS (#8). run_ci 33 PASS · 0 FAIL · 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 03:49:42 +00:00
Claude Code DTP Worker 48276ee916 [DTP-Worker 20260806_031432] FIX générateur — crm/financement_bancaire MANIFEST.roles_rbac_utilises répétait ventes-conseiller (dup ungaté, liste per-slot vs ensemble distinct)
Défaut réel/reproductible (pas stale, byte-repro vert) : finlib/builder.py:89
faisait [roles_resolved[k] for k in sorted(roles_resolved)], itérant les 4 SLOTS
logiques de spec["roles"] — 2 slots (conseiller_wag ET validation_dossier) pointent
le même rôle ventes-conseiller → 4 entrées pour 3 rôles distincts. Preuve bug (pas
per-slot voulu) : la sortie drope la clé de slot (cle), donc le doublon ne porte
aucune info distinctive ; sémantique documentée README.md:54 « rôles RBAC utilisés »
+ ci/README.md:1100 « ensemble distinct » ; les 3 modules frères produisent tous un
ensemble distinct (confotur 3/3, commissions 4/4, workflow_vente 7/7) — financement
seul outlier 4/3.

Fix (aligné idiome commissions) : ensemble distinct trié par role_id via
sorted({rr["role_id"] for rr in roles_resolved.values()}). Artefact régénéré → 3/3
distinct. 0 gate ajouté (#5 — champ lu par AUCUN gate financement ni consommateur
externe ; convention distinctness déjà tenue par les frères). 0 chiffre inventé (#6).
run_ci 33 PASS · 0 FAIL · 0 SKIP (byte-repro vert avec nouvel artefact, 35 tests verts).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 03:22:44 +00:00
Claude Code DTP Worker 243523c6c2 [DTP-Worker 20260806_024430] VÉRIF indépendante multi-axes (7 axes) → CLEAN · 0 édition de production
Chasse adversariale ciblée à un vrai défaut ungaté sur 7 axes FRAIS (anti-churn : évite
help-text/currency/prose déjà balayés par 021424/014423/011419). Tous CLEAN ou déjà gatés :

1. README «Entrée CLI»↔argparse (23 modules) — 0 flag/sous-commande fantôme.
2. Sémantique CLI `validate` — re-build en mémoire, PAS de dents vs out/ corrompu = BY-DESIGN
   (check_artifacts couvre la dérive byte). Noté verify-before-flag.
3. Ledger 15 invariants SEO — code 1..15 + 3 proses + README self-consistent ; «=9» mémoire = 9
   MODULES dialecte A, pas 9 invariants (non-contradiction).
4. Root README «24 modules / 24 suites» — sourcé : 24=périmètre audit_4big ; 24 suites=
   regression_plan self-exclu (self_module qa/regression) = 25 run_ci − 1. Piège réconcil. 24-vs-25.
5. Prose notes[] dans artefacts JSON (regression_plan) — accurate, re-générée+byte-gatée.
6. Complétude gate.needs (33 checks, e2e-baseline manuel exclu) — DÉJÀ GATÉ par
   check_ci_integrity.sh INV-A (gate.needs == {tous jobs} − {gate} − {manuels}).
7. Commentaires inline # cross-fait/compteur (*_gen.py + *lib/, hors docstrings/README) —
   14 compteurs vérifiés vs réalité (50 rôles, 3 langues, 5 portails, 12 groupes PIE…). CLEAN.

0 prod touché, 0 artefact rebuild, 0 gate ajouté (#5), 0 chiffre inventé (#6), 0 VPS (#8).
run_ci 33 PASS · 0 FAIL · 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 02:54:15 +00:00
Claude Code DTP Worker 354a68788d [DTP-Worker 20260806_021424] FIX argparse-help↔code — seo/seo_gen.py help build nommait des fichiers de sortie INEXISTANTS
Poursuite de la sous-classe help-text du fix a8342e9 (session 004414). Audit exhaustif
des 22 générateurs `*_gen.py` (help d'une sous-commande énumérant ses fichiers de sortie
↔ fichiers réellement écrits) → 21/22 CLEAN, 1 vrai défaut : seo_gen.py:293.

Le help `build` disait « genere seo_keywords/schema_org/hreflang + MANIFEST » alors que
le code (l.259-262) écrit seo_keywords.json, seo_schema_org.json, seo_hreflang.json,
MANIFEST.json : le help droppait le préfixe seo_ sur 2 des 3 fichiers (schema_org,
hreflang) + l'extension .json sur tous → nommait des fichiers INEXISTANTS
(schema_org ≠ seo_schema_org.json). Même classe que a8342e9.

Preuve fix-en-une-passe : docstring module (l.6-9) ET README (l.15-18) nommaient déjà
correctement les 4 fichiers exacts ; le help était le seul outlier, aligné maintenant
sur eux + la convention des frères (commissions/audit_5d/app_config = noms complets).
Style ASCII sans-accent du fichier respecté (genere).

0 gate (#5 — help ni sérialisé ni AST-parsé ; parseur de help fragile : pas de
convention commune aux 22, classe couverte par audit périodique). Sortie build
byte-identical aux 4 out/ commités (0 rebuild). 0 prod (#8), 0 chiffre inventé (#6).
run_ci 33 PASS · 0 FAIL · 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 02:20:04 +00:00
Claude Code DTP Worker b60d471030 [DTP-Worker 20260806_014423] FIX prose-numérique canal stakeholder — le compte « bijection compte-de-tests README↔réel » de la session 011419 sous-comptait les READMEs annonceurs (14 → 16)
Défaut réel (classe prose-facts-vs-numeric-drift) présent dans DEUX surfaces —
daily_reports/2026-08-06.md (l.48-54, canal stakeholder) ET 05_activity_log/2026-08-06.md
(entrée 011419) : l'« axe de vérification objectif » annonçait « concordance totale sur les
14 READMEs annonceurs » mais son énumération omettait 2 modules qui annoncent pourtant un
compte de tests dans leur README, tous deux concordants avec le réel — frontend/portails 19
(19 def test_) et demo/scenarios 39 (39 def test_). Le vrai total est 16 annonceurs / 9 sans
annonce, corroboré par l'en-tête faisant autorité de ci/check_readme_claims.sh (l.96 :
« 27 claims sur 16 modules »). Le « 11 sans annonce » était le complément erroné 25−14 → 9.

Fix (sweep des 2 surfaces en une passe, cf. prose-facts-vs-numeric-drift : un twin fix balaie
TOUTES les surfaces) : daily_reports 14→16 + ajout des 2 entrées manquantes + 11→9 + ancrage
explicite au gate ; journal 14→16 dans l'entrée 011419 (fait courant) avec commentaire de
traçabilité + nouvelle entrée documentant la correction. Chiffres recomputés, non saisis
(grep READMEs annonceurs=16 · def test_ concordance 16/16 · find tests=25 → complément 9).

Écarté au préalable : candidat comment↔code check_regression.sh:17 (« ran/passed/failures »)
= FAUX POSITIF — le commentaire décrit ce que l'ARTEFACT porte (le JSON a bien failures:0),
pas la ligne d'affichage l.79 ; le contrat réel = diff -q byte-à-byte du fichier entier l.71.

0 prod édité, 0 artefact rebuild, 0 gate ajouté (#5 — la surface README-count est déjà gatée),
0 chiffre inventé (#6), 0 VPS (#8). run_ci 33 PASS · 0 FAIL · 0 SKIP avant/après.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 01:51:57 +00:00
Claude Code DTP Worker 34c8cd2e17 [DTP-Worker 20260806_011419] CURRENCY canal stakeholder porté au HEAD a8342e9 · le canal daily_reports s'arrêtait au 2026-08-05 (8903a4b) et ne reflétait pas les 2 jalons du 08-06 — fe61207 (VÉRIF multi-axes CLEAN) et surtout a8342e9 (FIX 1-ligne help argparse mobile/app_config omettant store_listing.json), un vrai changement d'état non encore consigné stakeholder. Rapport daily_reports/2026-08-06.md : tableau des 2 jalons (nature+opposabilité), état courant re-dérivé d'artefacts (33 PASS = 8 statiques + 25 suites · régression 624 exec/607 pass/17 skip=PASS) + AXE OBJECTIF ajouté : bijection compte-de-tests README↔réel (def test_*) → concordance totale 14/14 READMEs annonceurs, 0 dérive. Vérif préalable lecture-seule : docstring↔code publiciste + fiscal/ecf (« 12 invariants »=schéma+2→12 self-consistant, pas un défaut) CLEAN ; couverture CI publiciste confirmée dans gate.needs. 0 prod, 0 artefact rebuild, 0 gate (#5), 0 chiffre inventé (#6 — tout recomputé), 0 VPS (#8). run_ci 33 PASS·0 FAIL·0 SKIP.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 01:21:15 +00:00
Claude Code DTP Worker a8342e97e2 [DTP-Worker 20260806_004414] FIX docstring↔code — help argparse de la sous-commande build (mobile/app_config_gen.py) omettait store_listing.json
Chasse adversariale ciblée (classe RECURRING docstring↔code, scopée aux modules non balayés
la veille) → 1 vrai défaut ungaté. Le help= de sub.add_parser("build") énumérait 4 sorties
(app_config/eas_build/role_navigation/MANIFEST) alors que cmd_build() en écrit 5 : store_listing.json
(l.243) était omis. Docstring (l.15 « les 5 fichiers ci-dessus ») + README (l.56/68) listent bien
les 5. Nouvelle sous-classe help-text argparse du motif docstring↔code (2e surface prose dans le code,
distincte des open('w') vs docstring déjà balayés). Fix = ajout store_listing.json à sa position
canonique. Aucun gate/test ne fige la chaîne (grep -rn = 0 hit externe) → pas d'oracle à réaligner,
pas de gate ajouté (#5). Non-régression : help n'affecte aucune sortie, artefacts byte-identiques,
run_ci 33 PASS·0 FAIL·0 SKIP avant/après. Reste de l'audit (audit_5d/acceptance/regression/
deploy_runbook/commissions/dossier_vente/ecf/portails/faisabilite) CLEAN. 0 artefact rebuild, 0 VPS (#8).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 00:51:55 +00:00
Claude Code DTP Worker fe61207ca6 [DTP-Worker 20260806_001412] VÉRIF indépendante multi-axes → CLEAN · 0 édition de production
Session de vérification (pas de currency churn : le canal stakeholder daily_reports
attestait 8903a4b, les 2 commits suivants — 21f55a9 currency, c196e41 VÉRIF — sont
vérification-only sans changement d'état stakeholder ; décision anti-churn déjà prise en 234409).

Chasse à un vrai défaut ungaté sur 3 surfaces, toutes CLEAN :
1. docstring↔code (classe RECURRING) — 13 générateurs audités sortie-par-sortie + flags CLI +
   comptes d'invariants du ledger ; concordance parfaite ; non-défaut validate [-o OUT] ré-écarté.
2. numériques du canal stakeholder re-dérivés au HEAD — SEO 258 (fr=87/en=87/es=84) recomputé de
   l'artefact · 8 gates statiques (git ls-files) · 33 PASS (run_ci) ; 0 dérive.
3. liens markdown in-repo — 294 liens, 291 résolvent ; les 3 « cassés » sont des exemples de
   SYNTAXE en prose dans des journaux historiques (que check_docs neutralise via code-spans),
   pas des liens réels ; classe pedagogical-hypothetical = KEEP. 0 lien réel cassé.

run_ci 33 PASS·0 FAIL·0 SKIP. 0 prod, 0 artefact rebuild, 0 gate ajouté (#5),
0 chiffre saisi (#6 — 8/33/258/87/87/84/294/291 recomputés), 0 VPS (#8).
Seule édition : 05_activity_log/2026-08-06.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-06 00:22:05 +00:00
Claude Code DTP Worker c196e4183e [DTP-Worker 20260805_234409] VÉRIF adversariale ciblée · candidat « MANIFEST.json manquant » de la fiche frontend_console = NON-défaut par design · 0 édition de production
Chasse à un vrai défaut ungaté (agent Explore skeptique) plutôt que répéter le motif de currency (churn). Candidat remonté puis RÉFUTÉ par vérif indépendante : la cellule « Sortie » de 03_agents/frontend_console/AGENT.md omet MANIFEST.json dans les DEUX lignes (portails:28 `out/workspace.json` alors que workspaces_gen.py:219 l'écrit ; chat_otoia:29 `{custom_block,chat_mount}` alors que chat_otoia_gen.py:229 l'écrit) → convention éditoriale (payload listé, manifeste de traçabilité omis), PAS une dérive. L'énumération complète des 3 fichiers est correcte là où elle compte (docstring chat_otoia_gen.py:12/15/18 + README module). Corriger la seule ligne chat = asymétrie ; éditer les deux = churn d'une cellule parsée par ci/check_readme_claims.sh (CO_FI ~L3506/L3576). CLEAN, laissé tel quel (#5/#6, « X not drift, don't fix »).

0 fichier de production édité, 0 artefact reconstruit, 0 gate ajouté (#5), 0 chiffre saisi (#6, 33 recompté de run_ci.sh), 0 VPS (#8). Seule édition in-repo : le journal. Mémoire projet : fiche-sortie-cell-omits-manifest-by-design.md. run_ci 33 PASS·0 FAIL·0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 23:50:09 +00:00
Claude Code DTP Worker 21f55a9ed7 [DTP-Worker 20260805_231404] CURRENCY canal stakeholder porté au HEAD 8903a4b · le rapport roadmap 2026-08-05 attestait à cb3de78 (session 211340) et ne reflétait pas 2 jalons plus tardifs du même jour — d6a8d73 (221354, SWEEP bijection INVERSE out/ = 0 orphelin) et 8903a4b (224359, FIX comment-vs-code ci/validate_json.sh = parse-only, pas de contrôle $schema). Section « Mise à jour de currency · fin de journée (HEAD 8903a4b) » : tableau des 2 jalons (nature + opposabilité) + état de vérif indépendant. Verif primaire = chasse docstring↔code (classe RECURRING) sur tous *_gen.py + helpers *lib/ (sorties/flags/comportement) → CLEAN, 0 dérive haute-confiance ; non-défauts connus ré-écartés (placeholder #6, compat validate -o OUT self-consistant). Structure gate INCHANGÉE : run_ci 33 PASS = 8 statiques (git ls-files ci/*.sh hors lib.sh = 8) + 25 suites, aucun jalon n'ajoute de job. 0 prod, 0 artefact rebuild, 0 gate ajouté (#5), 0 chiffre saisi (#6 — 8/33 recomputés), 0 VPS (#8). run_ci 33 PASS·0 FAIL·0 SKIP. 2026-08-05 23:19:49 +00:00
Claude Code DTP Worker 8903a4b774 [DTP-Worker 20260805_224359] FIX comment-vs-code — commentaire fantôme dans le gate ci/validate_json.sh
Le gate valide la bonne-formation JSON SEULEMENT (parse strict), mais l.27 portait un
commentaire orphelin annonçant un contrôle de conformité $schema/draft que le code
n'implemente jamais (branche then imprime juste le check). Nouvelle sous-classe
comment-vs-code : les scripts de GATE eux-memes, jamais couverts par les sweeps
docstring-vs-code (scopes aux generateurs de prod + helpers *lib/).

Isolement verifie : sweep des 8 scripts ci/*.sh + lib.sh = 0 autre derive.
Fix 2 volets : (1) suppression de la ligne fantome ; (2) en-tete PERIMETRE explicite
(bonne-formation seule ; conformite $schema = oracle jsonschema optionnel de
check_regression.sh, 17 skips par design) -> le commentaire retire devient une
affirmation positive et vraie du perimetre.

0 changement de logique executable, 0 artefact rebuild, 0 gate ajoute (#5, FIX pas
controle neuf), 0 chiffre saisi (#6), 0 VPS (#8). run_ci 33 PASS / 0 FAIL / 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 22:50:34 +00:00
Claude Code DTP Worker d6a8d73aec [DTP-Worker 20260805_221354] SWEEP vérification — bijection INVERSE des artefacts out/ (0 fichier commité orphelin) · 0 édition de production
Repo VERT/convergé à l'ouverture (run_ci 33 PASS·0 FAIL·0 SKIP). Balayage
lecture-seule multi-surface avant tout travail (anti-gate-N+1 #5) : 24/24
modules CI-câblés+régression-couverts+fiche-documentés ; docstring↔code CLEAN
(3 classes, sous-agent Explore) ; registre décisions ouvertes D-01..D-05 encore
ouverts + citations file:line encore exactes (re-vérifiées) ; publiciste build/
gitignore-d, fiche exacte ; sweep CWD-hétérogène écarté (faux positifs — gate
exécute les gen depuis leur module par conception).

FINDING — axe robustesse non couvert : check_artifacts prouve la direction AVANT
(produit⊆commité, itère les fichiers produits l.71-93) mais JAMAIS l'INVERSE
(un out/ commité orphelin, plus émis par build, passerait silencieusement).
Sweep exécuté (lecture seule, rejouable) : 58 fichiers out/ commités, 57
reproduits par build. Le seul « orphelin » = qa/regression/out/regression_run.json,
BY DESIGN artefact d'EXÉCUTION (run, pas build) exclu du contrat build (docstring
check_artifacts l.21-24) et byte-gaté séparément par check_regression.sh →
0 orphelin réel, bijection inverse tient.

PAS un gate (#5) : AVANT déjà gaté ; INVERSE empiriquement propre + transitivement
attrapé (tout consommateur reproductible lisant un out/ périmé casse check_artifacts).
Consigné comme sweep rejouable, sibling des sweeps hash-seed/locale-TZ/forward-compat.

Portée : 0 prod, 0 artefact rebuild, 0 gate ajouté (#5), 0 chiffre saisi (#6 —
8/24/33/58/57 recomputés), 0 VPS (#8). Seule édition : le journal. run_ci 33 PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 22:27:02 +00:00
Claude Code DTP Worker d4f9289586 [DTP-Worker 20260805_214344] CURRENCY canal stakeholder porté au HEAD cb3de78 · le rapport roadmap 2026-08-05 attestait à 27c7d20 (session 201339) et ne reflétait pas 1 jalon plus tardif du même jour — cb3de78 (211340, gate fiche-enumeration-completeness 2ᵉ locus = table §1 de ci/README.md, jumeau ungaté de la fiche QA fermée afa6165)
Canal roadmap (distinct du journal activity_log per discipline « deux canaux ») porté au HEAD courant. Section « Mise à jour de currency · fin de journée (HEAD cb3de78) » : tableau du jalon (nature + opposabilité au merge) + état de vérification indépendant (complétude de l'énumération des gates statiques désormais verrouillée sur LES DEUX loci qui la transcrivaient — fiche QA 03_agents/qa/AGENT.md + table §1 ci/README.md — par le même check_readme_claims.sh re-dérivant git ls-files 'ci/*.sh') + portée.

Structure du gate INCHANGÉE — run_ci 33 PASS = 8 gates statiques (git ls-files ci/*.sh hors lib.sh = 8, recompté) + 25 suites ; cb3de78 ne touche que l'infra CI (ci/README.md, ci/check_readme_claims.sh) + journal, aucun job ajouté.

Balayage lecture-seule préalable, 0 dérive : docstring↔code 25 générateurs (sorties + comportement CLEAN, sous-agent Explore, classe récurrente) · complétude fiches (21 sous-modules ↔ ≥1 AGENT.md) · SEO roadmap L60 déjà livré (258 keywords fr=87/en=87/es=84 recomptés + byte-gatés, schema_org + hreflang présents). 0 prod, 0 artefact rebuild (rapport non scoré audit_4big), 0 gate ajouté (#5), 0 chiffre saisi (#6 — 8/33/258 recomputés), 0 VPS (#8). run_ci 33 PASS·0 FAIL·0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 21:50:09 +00:00
Claude Code DTP Worker cb3de786f8 [DTP-Worker 20260805_211340] GATE — complétude de l'énumération des gates dans la TABLE §1 de ci/README.md (jumeau ungaté de la fiche QA)
La table §1 « Ce que fait le pipeline » de ci/README.md est LA doc canonique des jobs
statiques (une ligne par gate ci/*.sh). Sa complétude était le jumeau exact de la fiche QA
fermée par afa6165, mais NON gaté : check_ci_integrity verrouille le câblage (ci/*.sh ↔
gate.needs), le bloc fiche-QA ne lit que 03_agents/qa/AGENT.md — rien n'exigeait que chaque
gate figure dans la table §1. Un 9ᵉ gate y serait omis EN SILENCE. Prouvé ungate par mutation
(retrait de la ligne de table check_mobile_workflow → run_ci --static 8 PASS, aucun gate ne mord).

Fix = extension du gate existant (PAS un nouveau job · #5) : bloc Python dans check_readme_claims.sh
(avant sys.exit) réutilisant _gate_names re-dérivé de git ls-files 'ci/*.sh' (hors lib.sh · #6).
Exige chaque basename cité dans une LIGNE DE TABLE (|…) de la section §1 — délibérément PAS la
prose §1 (qui ne cite que certains gates pour l'explication mobile-build.yml : un contrôle
whole-section serait édenté sur un retrait de ligne de table). 0 nouveau ci/*.sh, 33 jobs inchangés.

Teeth 2 axes : MUT1 suppression de la vraie ligne de table (l.24) → RED nommant check_mobile_workflow.sh ;
MUT2 9ᵉ ci/*.sh factice tracké → RED sur les DEUX surfaces (fiche QA + table §1 : forward-protection)
puis git rm --cached + rm, arbre byte-restauré (JAMAIS git clean). Piège inerte écarté : sed 15d
visait l'en-tête de table (grep -n renumérotait relatif au pipe), re-ciblé sur la ligne 24 réelle.

Doc sous-section « COMPLÉTUDE de l'énumération dans la TABLE §1 » ajoutée en §2 de ci/README
(discipline ci-readme-table-detail-in-section2). Sweep préalable repo-wide 7-gates/32-jobs : 0
dérive réelle (toutes occurrences historiques datées ou pédagogiques, classées KEEP).

0 édition de production, 0 artefact rebuild, 0 chiffre saisi (#6 — 8/9 recomputés), 0 VPS (#8).
run_ci 33 PASS · 0 FAIL · 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 21:23:25 +00:00
Claude Code DTP Worker 9c7791f23a [DTP-Worker 20260805_204339] CURRENCY canal stakeholder porté au HEAD · le rapport roadmap 2026-08-05 attestait à 1a44dfe (session 181325, 18:13) et ne reflétait pas 2 jalons plus tardifs du même jour — afa6165 (194334, gate neuf fiche-enumeration-completeness) et 27c7d20 (201339, attestation chaîne d'intégrité des constantes) ; canal (distinct du journal activity_log per discipline « deux canaux ») porté au HEAD. Précédent identique 1b99917. Section « Mise à jour de currency · fin de journée (HEAD 27c7d20) » : tableau des 2 jalons (nature + opposabilité au merge) + état de vérification indépendant + portée. Structure du gate INCHANGÉE — run_ci 33 PASS = 8 gates statiques (git ls-files ci/*.sh hors lib.sh = 8) + 25 suites, aucun jalon n'ajoute de job. Balayage lecture-seule multi-surface préalable, 0 dérive : docstring↔code 25 générateurs (sorties+comportement CLEAN) · comptes tests par fiche (CRM 81=trio 25+31+25 + financement 35 · ecf 39 · confotur 44 · seo 36 · portails 19 · chat 31, concordants+gatés) · ancrage #9/#10 (check_readme_claims:5355+ re-dérive 3%/8.5%/52% de CLAUDE.md) · Expo 51 actuel/54 cible cohérent partout · regression 624 ran = 650 méthodes − 26 (suite qa-regression exclue de son méta-run, byte-gaté check_artifacts) · fiche QA cite 8/8 gates. 0 prod, 0 artefact rebuild (rapport non scoré audit_4big), 0 gate ajouté (#5), 0 chiffre saisi (#6 — 8/33/624 recomputés), 0 VPS (#8). run_ci 33 PASS·0 FAIL·0 SKIP.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 20:52:03 +00:00
Claude Code DTP Worker 27c7d20449 [DTP-Worker 20260805_201339] ATTESTATION bout-en-bout · chaîne d'intégrité des constantes mandataires CLOSE CLEAN · 0 édition de production
Roadmap livrée+gatée, baseline verte (33 PASS) : plutôt qu'un gate marginal
(#5), preuve end-to-end que la classe de bug latent la plus coûteuse — un
générateur figeant une constante du mandat en littéral (précédent réel
bancable_gen.py 0.52→finance._pct) — n'a AUCUN maillon hardcodé ni ungaté.

3 sondes : (1) Explore fan-out 05_deliverables_mvp/** → 0 littéral non-sourcé ;
tous les générateurs lisent 2 sources canoniques uniques (genlib/model.py
CANONICAL 6 valeurs #9/#10 ; publiciste/lib/branding.py 4 tokens #4). (2) ces
2 sources sont elles-mêmes ancrées à CLAUDE.md dans check_readme_claims.sh
(bloc l.5427 model.py↔#9/#10 ; bloc l.6958 branding.py↔#4 + docstring + README
+ oracle test + renderer._CANONICAL_MARKERS) → boucle fermée sans trou. (3) les
2 ancres-pivots MORDENT, mutation-prouvé : MUT1 branding COLOR_ACCENT
#f0b429→#e0a420 → RED nommant l'écart ; MUT2 model.py marketing 8.5%→9% → RED ;
restauration ciblée git checkout -- <path> (JAMAIS git clean) → tree propre,
gate re-vert.

Faux-positif écarté (settled) : daily 2026-08-05 tête « 624 passés · 0 skip »
vs artefact 607/17 = dated-snapshot déjà reconcilié §CURRENCY l.146-171, LAISSÉ.

0 prod, 0 gate (#5), 0 artefact reconstruit, 0 chiffre saisi (#6), 0 VPS (#8).
run_ci 33 PASS · 0 FAIL · 0 SKIP · git status propre.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 20:23:34 +00:00
Claude Code DTP Worker afa61657cb [DTP-Worker 20260805_194334] GATE NEUF classe fiche-enumeration-completeness : le tableau des gates statiques de la fiche QA se déclare « l'état courant » de git ls-files 'ci/*.sh' mais OMETTAIT le 8ᵉ gate check_mobile_workflow.sh (livré le jour même, cité NULLE PART dans la fiche · grep=0) — check_ci_integrity verrouille le CÂBLAGE CI (ci/*.sh↔gate.needs) mais ignore la fiche, check_readme_claims ne recomputait aucune énumération de gates → surface ungatée. Fix 2 volets : (1) ajout de la ligne manquante (rôle fidèle à l'en-tête du gate, placée après check_ci_integrity) ; (2) extension de check_readme_claims.sh (bloc Python avant sys.exit, réutilise subprocess/bad/good, 0 nouveau gate #5) re-dérivant l'ensemble de git ls-files 'ci/*.sh' (hors lib.sh, #6) et exigeant que chaque basename soit cité (backtické) dans la fiche ; un gate absent échoue. Teeth mutation-prouvés 2 axes : MUT1 retrait de la ligne → RED nommant check_mobile_workflow ; MUT2 ajout d'un 9ᵉ ci/*.sh factice (index seul) → RED (forward-protection : le prochain gate ne pourra être omis) puis --cached retiré, arbre byte-restauré (JAMAIS git clean). Doc ci/README §2 sous check_readme_claims. 0 prod, 0 artefact rebuild (aucun out/ ni doc scoré audit_4big), 0 chiffre saisi (#6, le « 8 » recompté de git ls-files), 0 VPS (#8). run_ci 33 PASS·0 FAIL·0 SKIP.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 19:51:00 +00:00
Claude Code DTP Worker c14305c170 [DTP-Worker 20260805_191333] Audit COMPLÉTUDE fiches AGENT.md (25 modules ↔ 13 fiches) — CLOSE CLEAN · 0 édition de production
run_ci = 33 PASS au démarrage, arbre propre, roadmap intégralement livrée/gatée.
Deux sondes préalables NÉGATIVES : (a) Explore very-thorough dérive prose/docstring
sur tout 05_deliverables_mvp = 0 dérive ungatée ; (b) méta-gate check_ci_integrity
relu (INV-A gate.needs · INV-B tout ci/*.sh câblé · INV-C PYTHONUTF8) = câblage
exhaustif, risque « gate orphelin » déjà fermé. Bascule sur la COMPLÉTUDE des fiches.

Énumération réelle des modules (tests/ + test*.py) = 25 (le MEMORY disait « 22 » :
écart réconcilié = split rbac en 4 sous-générateurs apply_plan/fixtures_gen/
roleprofile_gen/userperm_gen + rbac racine ; PAS 3 modules neufs non-fichés).
Cross-check : 25/25 cités dans ≥1 fiche · 24 comme LIGNES de table.

Faux-positif « pie/manifest manque une ligne » RÉFUTÉ à la source : documenté en
PROSE délibérée (faisabilite §40-52, « les comptes exacts font foi dans le README du
module — cet agent en est la source, pas la copie ») → une ligne de table à cellule
Tests réintroduirait un compte recopié (#6) + duperait la source (#5). demo/scenarios
= ligne source-unique délibérément côté fiche CRM (§Sprint 7), cross-ref depuis
faisabilité (#5). Complétude fiches CONFIRMÉE CLOSE, compteur mémoire réaligné 22→25.

0 fichier de production édité · 0 gate ajouté (#5) · 0 chiffre saisi à la main
(#6, tous recomptés) · aucune commande VPS (#8) · aucune plateforme git externe.
Deliverable = ce log (+ màj memory fiche-accuracy-audit-closed). run_ci 33 PASS·0·0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 19:23:36 +00:00
Claude Code DTP Worker 1b99917f21 [DTP-Worker 20260805_184329] CURRENCY canal stakeholder : baseline régression corrigée (faux-vert jsonschema neutralisé) + 2ᵉ incident RED consigné
Le daily_report/2026-08-05.md s'arrêtait à la session 144304 (HEAD f311a1b), 5 commits plus tôt. Recompute python3 indépendant des artefacts COURANTS (HEAD 1a44dfe) → DEUX écarts matériels au canal stakeholder, tous deux consignés (rapport hors merge-gate : check_docs + check_readme_claims l'excluent explicitement).

ÉCART 1 (matériel) — baseline régression : regression_run.json.totals = 624 ran / 607 passed / 17 skipped / 0 fail / 0 err, verdict PASS ; le rapport publiait « 624 passés · 0 skip ». Le refactor 9d30939 lance chaque suite sous `python -S` (sans site-packages) reproduisant le runner Gitea pip-less → l'oracle OPTIONNEL jsonschema (17 tests skipUnless, ~1/module) neutralisé partout. AVANT : jsonschema présent local→skipped=0, absent runner→skipped=17 ⇒ regression_run.json commité = FAUX-VERT (vert local, ROUGE runner). APRÈS -S : matrice byte-déterministe cross-environnement, baseline sur couverture garantie (stdlib + validateurs maison). Verdict inchangé PASS. Ligne « Régression » reformulée 607/17-skip ; les « 624/0-skip » antérieurs = snapshots datés KEEP (historical-repro).

ÉCART 2 — 2ᵉ tree commité RED capté le jour même : le refactor -S (9d30939) éditait regression/README.md (+11 l) sans rebuild quality_report.json (audit 4Big score le contenu doc → evidence byte-count) → check-artifacts ROUGE (32 PASS·1 FAIL) ; rattrapé ~17 min par 9fa464d (rebuild → 1 ligne, PASS 24/24 inchangé). Même classe rebuild-after-doc-edits que l'incident du matin (127ef6f→1321983) ; le rapport n'en consignait qu'UN → honnêteté du canal rétablie.

FIX : section « fin de journée · 184329 » (avant/après -S + reformulation ligne Régression · tableau 2ᵉ incident · veille lecture-seule depuis f311a1b : docstring helpers db91a6b CLEAN + gate constant-anchor 1441693 + invariant INV-C PYTHONUTF8 1a44dfe = PAS un nouveau job, 33 inchangé · ré-attestation HEAD 1a44dfe). Tables du matin intactes (snapshots datés), réconciliées explicitement (convention 32→33 jobs).

Ré-attestation HEAD 1a44dfe : 4Big 24/24 tous==100 coverage.ok PASS · régression 624 ran/607 passed/17 skipped/0/0 PASS · recette 15/15 in_repo · ci_job ×36 · structure run_ci 33 PASS = 8 gates statiques + 25 suites.

0 prod, 0 artefact reconstruit, 0 gate (#5), 0 chiffre saisi (#6 — 24/607/17/33/36 recomputés), 0 VPS (#8). Seules éditions : rapport stakeholder + journal. run_ci 33 PASS · 0 FAIL · 0 SKIP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-05 18:50:12 +00:00
26 changed files with 2688 additions and 33 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ le VPS reçoit — jamais l'inverse.
vente, le barème commissions, le DocType Dossier Vente et le plan e-CF **résolvent** vente, le barème commissions, le DocType Dossier Vente et le plan e-CF **résolvent**
leurs rôles depuis ce fichier, jamais un nom Frappe en dur. Total backend **RBAC 60 leurs rôles depuis ce fichier, jamais un nom Frappe en dur. Total backend **RBAC 60
tests** (10 + 11 + 12 + 11 + 16) + **e-CF 39 tests**, tous gated dans le CI (matrice tests** (10 + 11 + 12 + 11 + 16) + **e-CF 39 tests**, tous gated dans le CI (matrice
de régression du repo : **624 tests · 24 suites** · verdict `PASS`, source de régression du repo : **625 tests · 24 suites** · verdict `PASS`, source
`qa/regression/out/regression_run.json` — jamais compté à la main · #6). `qa/regression/out/regression_run.json` — jamais compté à la main · #6).
## Hand-off reçus (à appliquer sur le VPS, dans l'ordre) ## Hand-off reçus (à appliquer sur le VPS, dans l'ordre)
+1 -1
View File
@@ -19,7 +19,7 @@ les composants runtime OTOIA/VPS listés plus bas (`otoia/capabilities/…`, sys
| Module | Sprint | Rôle | Entrée CLI | Job CI | Tests | | Module | Sprint | Rôle | Entrée CLI | Job CI | Tests |
|---|---|---|---|---|---| |---|---|---|---|---|---|
| [`TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md`](../../05_deliverables_mvp/faisabilite/TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md) | 1 (roadmap L41-46) | **Template canonique v1.0** — contrat des 4 volets + champs obligatoires (§Livrable S1 ci-dessous) | — (doc contrat) | `check-docs` | — | | [`TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md`](../../05_deliverables_mvp/faisabilite/TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md) | 1 (roadmap L41-46) | **Template canonique v1.0** — contrat des 4 volets + champs obligatoires (§Livrable S1 ci-dessous) | — (doc contrat) | `check-docs` | — |
| [`generator/`](../../05_deliverables_mvp/faisabilite/generator/README.md) | 2 (roadmap L44) | **Générateur 4 volets** : `brief.json``data_room/PXX/` (template v1.0), round-trip via le parser Publiciste | `faisabilite_gen.py score\|scaffold\|generate\|batch` | `faisabilite-gen-tests` | 16 | | [`generator/`](../../05_deliverables_mvp/faisabilite/generator/README.md) | 2 (roadmap L44) | **Générateur 4 volets** : `brief.json``data_room/PXX/` (template v1.0), round-trip via le parser Publiciste | `faisabilite_gen.py score\|scaffold\|generate\|batch` | `faisabilite-gen-tests` | 17 |
| [`bancable/`](../../05_deliverables_mvp/faisabilite/bancable/README.md) | 3 (roadmap L46) | **Dossier bancable trilingue** : `brief.json``50_financier_bancable/{fr,en,es}.md` + manifest, figures sourcées verbatim + agrégats recalculés | `bancable_gen.py build\|validate` | `bancable-tests` | 22 | | [`bancable/`](../../05_deliverables_mvp/faisabilite/bancable/README.md) | 3 (roadmap L46) | **Dossier bancable trilingue** : `brief.json``50_financier_bancable/{fr,en,es}.md` + manifest, figures sourcées verbatim + agrégats recalculés | `bancable_gen.py build\|validate` | `bancable-tests` | 22 |
**Anti-invention (#6)** : `generator` et `bancable` ne **fabriquent aucun chiffre** — les figures **Anti-invention (#6)** : `generator` et `bancable` ne **fabriquent aucun chiffre** — les figures
+8
View File
@@ -33,6 +33,14 @@ le câblage de l'endpoint OTOIA et l'application du thème desk restent côté *
- **Chat OTOIA** : CLI `python3 chat_otoia_gen.py build|validate` · **14 invariants** · - **Chat OTOIA** : CLI `python3 chat_otoia_gen.py build|validate` · **14 invariants** ·
**31 tests** · job CI `chat-otoia-tests` (gated). **31 tests** · job CI `chat-otoia-tests` (gated).
> **Note de lecture — colonne « Sortie ».** Les cellules listent le **payload
> métier** ; chaque générateur écrit **en plus** un `out/MANIFEST.json` (compteurs
> auto-vérifiés) **volontairement omis** de la table par convention éditoriale.
> L'énumération exhaustive des trois fichiers vit dans les docstrings et READMEs
> de module (byte-gatés). Ne PAS ajouter le MANIFEST à cette cellule : elle est
> lue par regex par `ci/check_readme_claims.sh` (compteurs `cartes/liens/rôles`,
> comptes de tests) et l'omission est intentionnelle, pas une dérive.
## Source de vérité unique (zéro invention · #6) ## Source de vérité unique (zéro invention · #6)
La matière première est le **contrat RBAC** `05_deliverables_mvp/rbac/rbac_50_roles.json`, La matière première est le **contrat RBAC** `05_deliverables_mvp/rbac/rbac_50_roles.json`,
**jamais la spec de mise en page** : **jamais la spec de mise en page** :
+2 -1
View File
@@ -32,7 +32,7 @@ périmètre — un auditeur ne s'audite jamais.
**conformité** normative des hand-off. **conformité** normative des hand-off.
## Verdict agrégé courant (source `qa/regression/out/regression_run.json`) ## Verdict agrégé courant (source `qa/regression/out/regression_run.json`)
**24 suites gated · 624 tests · 607 passés · 0 échec · 0 erreur → verdict `PASS`.** **24 suites gated · 625 tests · 608 passés · 0 échec · 0 erreur → verdict `PASS`.**
Ce compte est **découvert automatiquement depuis le CI** (`q4lib.registry.parse_ci`, Ce compte est **découvert automatiquement depuis le CI** (`q4lib.registry.parse_ci`,
réutilisé sans duplication) — jamais compté à la main. réutilisé sans duplication) — jamais compté à la main.
Les **17 tests restants sont ignorés** (`skipped`) : ce sont les *oracles optionnels* Les **17 tests restants sont ignorés** (`skipped`) : ce sont les *oracles optionnels*
@@ -51,6 +51,7 @@ inversement) — la liste ci-dessous est donc *l'état courant*, pas une constan
| Gate | Rôle (une commande, déterministe, zéro chiffre fabriqué) | | Gate | Rôle (une commande, déterministe, zéro chiffre fabriqué) |
|---|---| |---|---|
| `check_ci_integrity.sh` | Intégrité du câblage CI : chaque `ci/*.sh` est câblé à un job **dans** `gate.needs` (aucun gate décâblé ni orphelin) — c'est le gardien des gardiens (il **s'exclut** lui-même · SoD). | | `check_ci_integrity.sh` | Intégrité du câblage CI : chaque `ci/*.sh` est câblé à un job **dans** `gate.needs` (aucun gate décâblé ni orphelin) — c'est le gardien des gardiens (il **s'exclut** lui-même · SoD). |
| `check_mobile_workflow.sh` | Intégrité du **second** workflow `mobile-build.yml` (EAS build iOS/Android) — **hors** `gate.needs` (il s'active quand Michel fournit `EAS_TOKEN`), donc *non* couvert par `check_ci_integrity` qui ne verrouille que `ci.yml` : bien-formé, gating d'activation `if:` job-level porté par `needs.preflight.outputs.*` (jamais le contexte `secrets.`, non exposé hors GitHub → SKIP silencieux), contrat d'outputs sans dangling (MOB-1..4). |
| `check_readme_claims.sh` | Intégrité des **chiffres** des README / fiches agent (CLAUDE.md #6) : chaque compte cité est **recalculé** depuis l'artefact `out/` ou la source (jamais une donnée inventée). | | `check_readme_claims.sh` | Intégrité des **chiffres** des README / fiches agent (CLAUDE.md #6) : chaque compte cité est **recalculé** depuis l'artefact `out/` ou la source (jamais une donnée inventée). |
| `check_artifacts.sh` | **Reproductibilité** : chaque `out/*.json` se régénère **byte-identique** (aucune dérive entre source et hand-off commité). | | `check_artifacts.sh` | **Reproductibilité** : chaque `out/*.json` se régénère **byte-identique** (aucune dérive entre source et hand-off commité). |
| `check_regression.sh` | **Fraîcheur** de la matrice de régression : le run rejoué == le run commité (aucune régression silencieuse · #5). | | `check_regression.sh` | **Fraîcheur** de la matrice de régression : le run rejoué == le run commité (aucune régression silencieuse · #5). |
+496
View File
@@ -1,5 +1,168 @@
# Activity Log · 2026-08-05 · Claude Code DTP Worker # Activity Log · 2026-08-05 · Claude Code DTP Worker
## Session `20260805_234409` — VÉRIF adversariale ciblée : le candidat « MANIFEST.json manquant » de la fiche frontend_console est un NON-défaut par design (les 2 lignes l'omettent identiquement) · 0 édition de production
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
Roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée ; le canal de currency
`daily_reports/2026-08-05.md` est déjà au HEAD effectif (`8903a4b`, porté par `21f55a9`). Plutôt
que répéter le motif récent de mise à jour de currency (churn), lancement d'une **chasse
adversariale à UN vrai défaut ungaté** (agent `Explore` skeptique) sur les surfaces sous-balayées :
prose-FACT vs artefacts · docstring↔code des `*_gen.py`/`*lib/` · liens in-repo cassés.
**Candidat remonté puis RÉFUTÉ.** L'agent a signalé `03_agents/frontend_console/AGENT.md:29`
(cellule « Sortie » du chat_otoia = `out/{custom_block,chat_mount}.json`, **2** fichiers) comme
omettant le 3ᵉ fichier écrit par le code — `chat_otoia_gen.py:227-229` écrit bien
`custom_block.json` / `chat_mount.json` / **`MANIFEST.json`**. **Vérification indépendante → NON-défaut :**
la ligne **jumelle** portails (`AGENT.md:28`, cellule = `out/workspace.json`) omet **elle aussi**
`MANIFEST.json`, alors que `workspaces_gen.py:218-219` l'écrit. Les **deux** lignes suivent donc la
même **convention éditoriale** : la cellule « Sortie » liste la charge utile (*payload*), pas le
manifeste de traçabilité. L'énumération **complète** des 3 fichiers est bien présente et correcte
là où elle doit l'être — docstring du générateur (`chat_otoia_gen.py:12/15/18`) + README de module.
« Corriger » la seule ligne chat créerait une **asymétrie** ; éditer les deux churnerait une cellule
**parsée par un gate** (`ci/check_readme_claims.sh`, `CO_FI` ~L3506/L3576 en extrait les « TROIS
attributs data-derived » + comptes tests/invariants). Décision : **CLEAN, laisser tel quel** (#5/#6,
motif « X not drift, don't fix »).
**Mémoire projet.** Nouveau fichier `fiche-sortie-cell-omits-manifest-by-design.md` (+ index)
pour qu'une session future ne re-remonte pas le faux positif.
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**,
**0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6`33` recompté de `run_ci.sh`),
**aucune commande VPS** (#8). Seule édition in-repo : ce journal.
**Vérif.** `./run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** · `git status` propre après commit.
---
## Session 224359 · FIX RÉEL — commentaire fantôme dans le gate `ci/validate_json.sh` (check de conformité `$schema` annoncé, jamais implémenté) · nouvelle sous-classe comment-vs-code sur les scripts de GATE eux-mêmes
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
Roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée in-repo ; les 24 modules du
`quality_report.json` (audit_4big) sont **tous à 100/PASS** (aucun < 95, contrainte #5) → la
frontière automatisable restante est soit un arbitrage produit (bloqué Michel, cf.
[[open-decisions-register]]), soit du déploiement VPS (hors périmètre #8). Bascule sur une
surface de dérive **non ré-auditée** : les **commentaires internes des scripts de gate**
`ci/*.sh` eux-mêmes — les sweeps docstring-vs-code antérieurs étaient scopés aux **générateurs
de production** + helpers `*lib/` (cf. [[docstring-vs-code-drift]]), jamais aux gates.
**Finding (réel, isolé).** `ci/validate_json.sh:27` portait un commentaire orphelin —
`# Si un $schema est déclaré, contrôle que 'draft' est reconnu (info seule).` — placé dans la
branche `then` du parse-loop, mais **aucun code** ne lit `$schema` ni ne contrôle le `draft` :
la branche n'imprime que le `✓`. Le gate valide la **bonne-formation SEULEMENT** (parse strict) ;
la conformité structurelle au `.schema.json` est l'oracle tiers OPTIONNEL `jsonschema` de la
suite régression (cf. [[regression-baseline-17-skips-by-design]]). Le commentaire promettait donc
un check inexistant — même classe honnêteté que #6 (rien ne doit affirmer un contrôle absent).
**Vérification d'isolement.** Sweep Explore des **8** scripts de gate + `lib.sh`
(`check_readme_claims.sh` 5600+ l., `check_docs`, `check_artifacts`, `check_regression`,
`check_ci_integrity`, `check_mobile_workflow`, `guard_constraints`, `lib.sh`) pour la même classe
(commentaire affirmant un comportement que le code n'implémente pas) → **0 autre dérive** ; tous
les autres commentaires sont synchrones avec un code qui les honore. Dérive **localisée** au seul
`validate_json.sh`.
**Fix (2 volets, honnête · 0 invention).** (1) Suppression de la ligne fantôme l.27 (la branche
`then` fait exactement ce que le code montre — imprimer le `✓`). (2) En-tête : ajout d'un bloc
**PÉRIMÈTRE** explicite disant que ce gate contrôle la bonne-formation SEULEMENT et que la
conformité `$schema` vit ailleurs (l'oracle `jsonschema` de `check_regression.sh`, 17 skips par
design) — le commentaire retiré devient une affirmation POSITIVE et vraie du périmètre, ce qui
prévient la réintroduction du fantôme par un futur lecteur.
**Portée / anti-churn.** **1 fichier de gate** édité (commentaire seul, **0 changement de logique
exécutable** — même AST bash), **0 artefact reconstruit**, **0 gate ajouté** (#5 — c'est un FIX de
dérive, pas un nouveau contrôle ; la classe est isolée, un gate serait inerte/redondant), **0
chiffre saisi à la main** (#6), **aucune commande VPS** (#8). `bash ci/validate_json.sh` = OK ·
`./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** avant et après (le fix ne touche aucun comportement
gaté). Seules éditions : `ci/validate_json.sh` + ce journal.
---
## Session 191333 · Audit de COMPLÉTUDE fiches AGENT.md (25 modules ↔ 13 fiches) — CLOSE CLEAN · réconciliation compte 22→25 · 0 édition de production
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée in-repo (0 checkbox ouverte).
Deux sondes préalables **négatives** : (a) Explore *very-thorough* de dérive prose/docstring sur
tout `05_deliverables_mvp/` (classes récurrentes docstring-vs-code + prose-facts-vs-numeric) =
**0 dérive ungatée** ; (b) relecture du méta-gate `ci/check_ci_integrity.sh` (INV-A `gate.needs`
== jobs non-manuels · INV-B tout `ci/*.sh` câblé/sourcé · INV-C `PYTHONUTF8`) = câblage exhaustif,
le risque « gate orphelin » que j'envisageais est **déjà fermé**. Surfaces de dérive usuelles
saturées (#5) → bascule sur un axe non ré-audité récemment : la **complétude** des fiches
(distincte de l'exactitude, cf. [[fiche-accuracy-audit-closed]]).
**Méthode.** Énumération des répertoires-modules RÉELS (`tests/` portant ≥1 `test*.py`) →
**25** modules. Le MEMORY portait « **22** modules livrés » : écart **réconcilié** — le split de
`rbac` en 4 sous-générateurs (`apply_plan` · `fixtures_gen` · `roleprofile_gen` · `userperm_gen`)
+ le `rbac` racine portent le total réel à **25** (pas 3 modules neufs non-fichés : simple
granularité de comptage). Cross-check de chacun contre les 13 `03_agents/*/AGENT.md`.
**Résultat — 25/25 dans ≥1 fiche.** 24 modules figurent comme **LIGNES de table** de leur fiche
propriétaire (colonnes `Module | Sprint | Rôle | Entrée CLI | Job CI | Tests`). Deux modules
n'ont **pas** de ligne de table dans la fiche `faisabilite` — vérifié **DÉLIBÉRÉ, pas un trou** :
- `pie/manifest` — documenté en **prose** (`03_agents/faisabilite/AGENT.md` §40-52) avec note
explicite « les comptes exacts (groupes Master Data, règles de synchro, registre downstream)
**font foi dans le README du module — cet agent en est la source, pas la copie** ». Une ligne
de table à cellule *Tests* **réintroduirait un compte recopié** (#6, anti-invention) et
**duperait la source** (#5). Laissé tel quel.
- `demo/scenarios` — sa ligne **source-unique** (auto-gatée) vit délibérément dans la fiche
`crm` (§« Livrable transverse · Sprint 7 »), non redupliquée côté faisabilité (#5). La fiche
faisabilité l'y renvoie explicitement (§31-38).
**Conclusion.** Complétude fiches **CLOSE** (confirme [[fiche-accuracy-audit-closed]], compteur
mémoire réaligné 22→25 · exemptions prose/source-unique documentées pour couper le re-chase).
Faux-positif « pie/manifest manque une ligne » **réfuté** à la source — même classe de FP que
le memory répète (paths deliverables-relatifs, illustrations spec-driven : *lus comme dérive,
n'en sont pas*). **0 fichier de production édité · 0 gate ajouté (#5) · 0 chiffre saisi à la
main (#6, tous recomptés) · aucune commande VPS (#8) · aucune plateforme git externe.**
Deliverable de session = ce log + màj memory. `./run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP**.
## Session 184329 · CURRENCY canal stakeholder — **baseline régression corrigée** (607/17-skip) + 2ᵉ incident RED consigné · 0 édition de production
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
roadmap `ROADMAP_8_WEEKS_OR_LESS.md` **intégralement livrée/gatée in-repo** (0 checkbox ouverte ;
15/15 `acceptance_matrix` `status=in_repo`). Plutôt qu'une énième sonde de dérive (surfaces usuelles
saturées · #5), j'ai vérifié la **currency du canal stakeholder** `daily_reports/2026-08-05.md`
(hors merge-gate : `check_docs`+`check_readme_claims` l'excluent explicitement) contre les artefacts
**courants** — dernière mise à jour du rapport = session `144304` (HEAD `f311a1b`), **5 commits
plus tôt**. Deux écarts **matériels** trouvés.
**Écart 1 — baseline régression : faux-vert `jsonschema` neutralisé (matériel).** Recompute
indépendant `python3` de `regression_run.json.totals` : **624 ran · 607 passed · 17 skipped · 0/0**,
verdict `PASS` — mais le rapport publiait « **624 passés · 0 skip** ». Cause : le refactor `9d30939`
lance chaque suite sous `python -S` (sans `site-packages`) reproduisant le runner Gitea pip-less →
l'oracle **optionnel** `jsonschema` (17 tests `skipUnless`, ~1/module) est **neutralisé partout**.
AVANT : `jsonschema` présent en local → `skipped=0` ; absent sur runner → `skipped=17`
`regression_run.json` commité = **FAUX-VERT** (vert local, ROUGE runner). APRÈS `-S` : matrice
**byte-déterministe** cross-environnement, baseline ancrée sur la couverture garantie (stdlib +
validateurs maison). Verdict inchangé `PASS`. La ligne « Régression » du canal se lit désormais
**607 passés · 17 skip (oracles optionnels)** ; les « 624 passés · 0 skip » antérieurs = snapshots
datés vrais à l'époque (*historical-repro = KEEP*).
**Écart 2 — 2ᵉ tree commité RED, capté le jour même.** Le refactor `-S` (`9d30939`) éditait
`regression/README.md` (+11 l) **sans rebuild** de `quality_report.json` (l'audit 4Big score le
contenu doc → champ `evidence` byte-count) → `check-artifacts` **ROUGE** (32 PASS · 1 FAIL). Rattrapé
sous ~17 min par `9fa464d` (rebuild → 1 ligne, verdict `PASS` 24/24 inchangé). Même classe
`rebuild-after-doc-edits` que l'incident du matin (`127ef6f``1321983`). Le rapport n'en consignait
qu'**un** ; ce 2ᵉ était absent → honnêteté du canal rétablie (cf. [[audit4big-rebuild-after-doc-edits]],
[[two-logging-channels]]).
**Fix.** Ajout d'une section « Mise à jour fin de journée · `184329` » au `daily_reports/2026-08-05.md` :
(1) tableau avant/après `-S` + reformulation de la ligne Régression ; (2) tableau du 2ᵉ incident ;
(3) veille lecture-seule depuis `f311a1b` (docstring helpers `db91a6b` CLEAN · gate constant-anchor
`1441693` · invariant INV-C `PYTHONUTF8` `1a44dfe`**pas un nouveau job**, 33 inchangé) ;
(4) ré-attestation HEAD `1a44dfe`. Tables du matin **laissées intactes** (snapshots datés), réconciliées
explicitement par la nouvelle section (même convention que l'évolution 32→33 jobs).
**Ré-attestation (recompute `python3` indépendant, HEAD `1a44dfe`).** 4Big : **24 modules · tous == 100** ·
`coverage.ok=true` · `PASS`. Régression : **624 ran · 607 passed · 17 skipped · 0 fail / 0 err** · `PASS`.
Recette : **15/15 `in_repo`** · `ci_job` ×36 · `True`. Structure : `run_ci` **33 PASS** = 8 gates statiques
(`ls ci/*.sh` hors `lib.sh` = 8) + 25 suites.
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**, **0 gate
ajouté/modifié** (#5), **0 chiffre saisi à la main** (#6 — 24/607/17/33/36 recomputés des artefacts +
`run_ci.sh`), **aucune commande VPS** (#8 — 100 % local, lecture-seule sur les artefacts). Seules
éditions : le rapport stakeholder + ce journal.
**Vérif.** `./run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** (aucun fichier gaté touché).
## Session 181325 · FIX RÉEL défaut locale-runner : le gate est ROUGE en silence sous locale ASCII → **VERROUILLÉ UTF-8** ## Session 181325 · FIX RÉEL défaut locale-runner : le gate est ROUGE en silence sous locale ASCII → **VERROUILLÉ UTF-8**
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS**, arbre propre, roadmap **Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS**, arbre propre, roadmap
@@ -1619,3 +1782,336 @@ valeurs sont recomputées de `CLAUDE.md`, jamais retapées), **aucune commande V
citée est une surface à ancrer) : nouvelle sous-surface (bancable + commissions) close. citée est une surface à ancrer) : nouvelle sous-surface (bancable + commissions) close.
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP**. **Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP**.
---
## Session 20260805_194334 · GATE NEUF — complétude de l'énumération des gates statiques dans la fiche QA
**Contexte.** Repo vert au démarrage (33 PASS · 0 FAIL · 0 SKIP), tous modules
livrés, roadmap 8-sem sans tâche-feature ouverte. Sonde ciblée sur la classe
**fiche-completeness** (cf. [[fiche-accuracy-audit-closed]] — « completeness≠accuracy,
diff deliverables vs fiche tables »), cette fois sur une fiche qui **énumère** un
ensemble censé être exhaustif.
**Constat (drift présent-temps réel).** La fiche `03_agents/qa/AGENT.md`
(§« Deuxième étage QA · batterie de gates statiques `ci/*.sh` ») liste les gates dans
un tableau, en se **déclarant explicitement** (l.49) « la liste ci-dessous est donc
*l'état courant*, pas une constante ». Or le tableau ne comptait que **7 lignes** alors
que `git ls-files 'ci/*.sh'` (hors `lib.sh`) en rend **8** : le 8ᵉ gate
`check_mobile_workflow.sh` — livré **le jour même** (session `001109`, cf. rapport
matinal 33-jobs) — n'y figurait **NULLE PART** (`grep -c check_mobile_workflow` fiche
= **0**, les 7 autres ≥ 1). La fiche promettait la complétude sans la tenir : omission
silencieuse d'un jour entier. **Surface ungatée confirmée** : `check_ci_integrity`
verrouille le **câblage CI** (`ci/*.sh` ↔ job `gate.needs`) mais **ne lit pas la fiche** ;
`check_readme_claims` ne recomputait aucune énumération de gates → aucun gardien.
**Fix (2 volets).**
1. **Correction du fond** : ajout de la ligne manquante `check_mobile_workflow.sh` au
tableau, placée juste après `check_ci_integrity.sh` (les deux gardent l'intégrité
d'un fichier-workflow) — rôle décrit fidèlement d'après l'en-tête du gate (second
workflow `mobile-build.yml`, hors `gate.needs`, gating `if:` job-level sur
`needs.preflight.outputs.*` jamais `secrets.`, contrat d'outputs, MOB-1..4).
2. **Ancrage anti-récurrence** : extension du gate existant `ci/check_readme_claims.sh`
(bloc Python ajouté avant `sys.exit`, réutilise `subprocess`/`bad`/`good` déjà en
scope · zéro nouveau gate #5 · zéro nouveau fichier) — re-dérive l'ensemble depuis
`git ls-files 'ci/*.sh'` (hors `lib.sh`, #6) et exige que chaque basename soit cité
(backtické) dans la fiche ; un gate **absent** échoue. Rend la promesse « l'état
courant » **opposable**.
**Teeth (mutation-vérifié, arbre restauré à chaque fois).**
- **MUT1** — retrait de la ligne `check_mobile_workflow.sh` → **RED** nommant le gate
réel non cité (`n'énumère PAS ['check_mobile_workflow.sh'] … 8 gates réels`).
- **MUT2 (forward-protection)** — `git add` d'un 9ᵉ `ci/check_dummy9.sh` factice (index
seul) → **RED** (`… ['check_dummy9.sh'] … 9 gates réels`) : le **prochain** gate
livré ne pourra pas être omis en silence. Fichier `--cached` retiré + `rm` (arbre
byte-restauré, **JAMAIS** `git clean` · CLAUDE.md).
- Arbre restauré → gate exit 0, les 8 gates re-verts.
**Portée / anti-churn.** **0 fichier de production édité** (seuls la fiche QA,
`ci/check_readme_claims.sh`, `ci/README.md`), **0 artefact reconstruit** (aucun
`out/*.json` ni doc scoré par audit_4big → pas de rebuild `quality_report`, cf.
[[audit4big-rebuild-after-doc-edits]]), **0 chiffre saisi à la main** (#6 — le « 8 » est
recompté de `git ls-files`, jamais tapé), **aucune commande VPS** (#8 — 100 % local).
Documenté en `ci/README.md` §2 sous `check_readme_claims.sh` (nouveau paragraphe
« COMPLÉTUDE de l'énumération des gates statiques »), pas de nouvelle ligne au tableau §1
(cf. [[ci-readme-table-detail-in-section2]]).
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP**.
---
## Session `20260805_201339` · ATTESTATION chaîne d'intégrité des constantes mandataires — bout-en-bout · 0 édition de production
**Contexte.** Roadmap intégralement livrée+gatée ; baseline `run_ci.sh` verte (**33 PASS**).
Aucune tâche fonctionnelle in-repo ne reste (cf. sessions du jour). Plutôt qu'ajouter
un gate marginal (risque #5, cf. [[verify-uncovered-before-gating]]), la valeur honnête
du jour : **prouver de bout en bout que la chaîne de dérivation des constantes du mandat
n'a AUCUN maillon hardcodé ni maillon ungaté**, la classe de bug latent la plus coûteuse
(un générateur qui fige `0.52`/`8.5 %`/`#f0b429` en littéral dérive en silence si CLAUDE.md
change — précédent réel `bancable_gen.py 0.52→finance._pct`, cf.
[[fix-vs-gate-transitively-protected-constant]] · [[claude-md-constant-anchor-gate]]).
**Sonde 1 — aucun littéral hardcodé côté générateurs.** Fan-out Explore sur
`05_deliverables_mvp/**` (recherche `0.52`/`0.085`/`0.03`/`3 %`/`8.5 %`/`52 %`/`#0a0a12`/
`#f0b429`/`Cardnet`/`USD`/`DOP`/`Fraunces`/`Cormorant` en CODE exécutable des générateurs) :
**0 littéral non-sourcé**. Tous les générateurs lisent depuis **2 sources canoniques uniques** :
- `faisabilite/generator/genlib/model.py` → dict `CANONICAL` (6 valeurs : édition 3 %,
marketing 8.5 %, équilibre 52 %, devises USD+DOP, Cardnet, Letter US) — consommé par
bancable (`finance._pct(deps.CANONICAL[...])`), report, renderer.
- `publiciste/lib/branding.py` → `COLOR_BG`/`COLOR_ACCENT`/`FONT_DISPLAY`/`FONT_BODY`
(#0a0a12 · #f0b429 · Fraunces · Cormorant Garamond) — importé par mobile/app_config,
frontend/chat_otoia, seo (via `deps.branding`), publiciste/generator.
**Sonde 2 — les 2 sources canoniques sont elles-mêmes ancrées à CLAUDE.md.** Le maillon
critique : une source unique n'est correcte que si ELLE est gatée contre le mandat. Vérifié
dans `ci/check_readme_claims.sh` :
- bloc l.5427 — `model.py CANONICAL` **re-dérivé de CLAUDE.md #9/#10** (6 valeurs).
- bloc l.6958 — `branding.py` CONSTANTES **re-dérivées de CLAUDE.md #4** (2 couleurs +
2 fontes) + docstring + README:43 + oracle du test publiciste (+ `renderer._CANONICAL_MARKERS`).
→ boucle fermée : générateur → source canonique → CLAUDE.md, **sans trou**.
**Sonde 3 — les 2 ancres-pivots MORDENT (mutation-prouvé, arbre byte-restauré).**
- MUT1 `branding.py COLOR_ACCENT #f0b429#e0a420` → **RED** : « Branding canoniques ·
branding.py CONSTANTES DÉRIVENT de CLAUDE.md #4 : accent='#e0a420' (attendu '#f0b429') ».
- MUT2 `model.py CANONICAL marketing_pct 8.5 %→9 %` → **RED** : « Faisabilité canoniques ·
model.py CANONICAL DÉRIVE de CLAUDE.md #9/#10 : marketing_pct='9 %' (attendu 8.5%) ».
- Restauration ciblée par `git checkout -- <path>` (**JAMAIS `git clean`**, #interdits) →
`git status --porcelain` **vide** · gate re-vert.
**Faux-positif écarté (settled, NON édité).** Le tableau « launch-readiness / Attestation »
en tête du daily report `2026-08-05.md` (l.30/45) lit « 624 passés · 0 skip » alors que
`regression_run.json.totals` = 607 passés / 17 skip. Ce n'est **pas une dérive neuve** :
la §CURRENCY du même fichier (l.146-171) reconcile explicitement (« les 624 passés · 0 skip
des sections antérieures sont des snapshots datés », nouvelle baseline 607/17 posée par
`1b99917`) — classe *dated-snapshot = KEEP* déjà consignée [[regression-baseline-17-skips-by-design]].
Re-l'éditer = re-litiguer un settled → LAISSÉ.
**Périmètre.** **0 édition de production**, **0 gate ajouté** (#5 — chaîne déjà défendue
end-to-end, sonde = attestation pas nouvelle machinerie), **0 artefact reconstruit**,
**0 chiffre saisi à la main** (#6), **aucune commande VPS** (#8 — 100 % local). Classe
mandate-constant-integrity **CLOSE CLEAN** ce jour (générateurs 0 hardcode · 2 sources ·
2 ancres CLAUDE.md prouvées mordantes).
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** · `git status` propre.
---
## Session `20260805_204339` · CURRENCY canal stakeholder porté au HEAD + balayage lecture-seule multi-surface (0 édition de production)
**Constat.** Le rapport stakeholder `05_deliverables_mvp/daily_reports/2026-08-05.md`
attestait à HEAD **`1a44dfe`** (session `181325`, 18:13) et **ne reflétait pas** deux jalons
plus tardifs du même jour : `afa6165` (`194334`, gate neuf `fiche-enumeration-completeness`)
et `27c7d20` (`201339`, attestation chaîne d'intégrité des constantes). Le canal roadmap
(distinct du journal `05_activity_log/` per la discipline « deux canaux ») avait donc lapsé
de 2 milestones. Précédent identique : `1b99917` (« CURRENCY canal stakeholder »).
**Vérification amont (avant écriture, tout recomputé d'artefacts committés · #6).**
- Docstring↔code des 25 générateurs : sorties + comportement **CLEAN** (sous-classe
filename déjà close 22/22 ; aucune nouvelle dérive input/fallback).
- Comptes de tests par fiche AGENT.md vs `def test_` réels : **concordants** — CRM `81`
(trio 25+31+25) + financement `35` · ecf `39` · confotur `44` · seo `36` · portails `19`
· chat `31`. Tous déjà gatés.
- Constantes CLAUDE.md #9/#10 (`3 %`/`8.5 %`/`52 %`/USD+DOP/Cardnet/Letter) :
`check_readme_claims.sh:5355+` les **re-dérive** de `CLAUDE.md` → `genlib/model.py` +
renderer markers + README ancrés. Aucune copie orpheline.
- Runtime mobile : Expo **51 actuel / 54 cible** cohérent sur toutes les surfaces « en
place » (AGENT.md, `AGENTS_EXISTING_ASSETS §8`, roadmap L18/L56).
- `regression_run.json` : **624 ran = 650 méthodes 26** (la suite `qa-regression`
s'exclut de son propre méta-run) — self-consistant, byte-gaté par `check_artifacts`.
- Fiche QA : cite désormais les **8/8** gates (`git ls-files 'ci/*.sh'` hors `lib.sh` = 8),
verrouillé par le gate `fiche-enumeration-completeness` (`afa6165`).
**Édition.** Section « Mise à jour de currency · fin de journée (HEAD `27c7d20`) » ajoutée
au rapport stakeholder : tableau des 2 jalons (nature + opposabilité au merge) + état de
vérification indépendant + portée anti-churn. **Structure du gate inchangée** : `run_ci.sh`
→ **33 PASS** = **8 gates statiques + 25 suites** (aucun jalon n'ajoute de job).
**Portée / anti-invention.** **0 fichier de production édité**, **0 artefact reconstruit**
(le rapport n'est pas scoré par `audit_4big` — seuls les docs modules le sont), **0 gate
ajouté** (#5 — la journée était déjà entièrement gatée), **0 chiffre saisi à la main** (#6 —
`8`/`33`/`624` recomputés de `git ls-files`/`run_ci.sh`/l'artefact), **aucune commande VPS**
(#8). Seules éditions : le rapport de currency + ce journal.
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** · `git status` propre après commit.
---
## Session 20260805_211340 · GATE — complétude de l'énumération des gates dans la **table §1 de `ci/README.md`** (jumeau ungaté de la fiche QA, fermé `afa6165`)
**Contexte + choix de tâche.** Arbre propre au démarrage, `./run_ci.sh` → **33 PASS · 0
FAIL · 0 SKIP** ; roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée in-repo.
Hypothèse dirigée par la mémoire *prose-facts-vs-numeric-drift* (5ᵉ sous-classe) : le 8ᵉ
gate statique `check_mobile_workflow.sh` livré ce jour a pu laisser des **siblings périmés**
dans les gate-docs ungatés. Sweep repo-wide `\b7 (gates?|statiques?)\b` / `\b32 (jobs?|PASS)\b` :
**0 dérive réelle** — toutes les occurrences « 7 »/« 32 » sont des **snapshots datés
historiques** (daily_reports/activity_log 08-02→08-05) ou **pédagogiques** (le commentaire
`check_mobile_workflow.sh:13` « 7/7 gates statiques restaient verts » désigne les 7 gates
**pré-existants** qui motivaient un 8ᵉ), classe correctement `historical-repro`/`pedagogical`
= KEEP. Docs present-tense (ci/README §1, `8ᵉ gate statique`) toutes cohérentes à 8/33.
**Le finding réel — une surface UNGATÉE.** La **table §1 de `ci/README.md`** (« Ce que fait
le pipeline ») est LA doc canonique des jobs statiques : une ligne par gate `ci/*.sh`. Or sa
**complétude** était le jumeau exact de la fiche QA fermée par `afa6165` — mais **non gaté** :
`check_ci_integrity` verrouille le CÂBLAGE (`ci/*.sh` ↔ `gate.needs`), le bloc fiche-QA (ajouté
`afa6165`) ne lit que `03_agents/qa/AGENT.md`. **Rien** n'exigeait que chaque gate figure dans
la table §1 → un 9ᵉ gate y serait omis EN SILENCE (même mode de défaillance que la fiche QA
avait subi un jour entier). Prouvé ungate **par mutation** (verify-uncovered) : retrait de la
**ligne de table** `check_mobile_workflow` → `run_ci --static` **8 PASS** (aucun gate ne mord).
**Fix — extension du gate existant (PAS un nouveau job · #5).** Bloc Python ajouté à
`ci/check_readme_claims.sh` (avant `sys.exit`), **réutilisant** `_gate_names` déjà re-dérivé de
`git ls-files 'ci/*.sh'` (hors `lib.sh` · #6 — jamais une liste à la main). Il exige que chaque
basename soit cité dans une **ligne de TABLE** (`|`…) de la **section §1** — délibérément PAS la
prose §1 (qui ne mentionne que certains gates pour l'explication `mobile-build.yml` : un contrôle
whole-section serait **édenté** sur un retrait de ligne de table, comme la mutation l'a révélé —
d'où le scope table-rows). 0 nouveau gate `ci/*.sh`, 33 jobs inchangés.
**Teeth mutation-prouvés (2 axes).** MUT1 — suppression de la vraie ligne de table
`check_mobile_workflow` (l.24) → **RED** nommant `check_mobile_workflow.sh` (exit 1). MUT2 —
9ᵉ `ci/*.sh` factice tracké (index seul) → **RED** sur **les DEUX** surfaces (fiche QA + table §1 :
forward-protection, le prochain gate ne pourra être omis d'aucune) ; `git rm --cached` + `rm`,
**arbre byte-restauré** (JAMAIS `git clean`). *Piège écarté* : un premier essai `sed 15d` visait
la ligne 15 = **en-tête** de table (le `grep -n` renumérotait relatif au pipe) — mutation inerte,
détectée et re-ciblée sur la vraie ligne 24.
**Doc.** Sous-section « COMPLÉTUDE de l'énumération dans la TABLE §1 » ajoutée en **§2** de
`ci/README.md` (discipline *ci-readme-table-detail-in-section2* : ne pas grossir la cellule §1).
**Périmètre.** **0 édition de production** (générateur/out/), **0 artefact rebuild** (aucune doc
scorée `audit_4big`), **0 chiffre saisi à la main** (#6 — `8`/`9` recomputés de `git ls-files`),
**aucune commande VPS** (#8). Seules éditions : `ci/check_readme_claims.sh` (+40 l) et
`ci/README.md` (+13 l).
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** · `git status` propre après commit.
---
## Session `20260805_214344` · CURRENCY canal stakeholder porté au HEAD `cb3de78` + audit lecture-seule (0 édition de production)
**Contexte.** Repo VERT à l'ouverture (`./run_ci.sh` → 33 PASS · 0 FAIL · 0 SKIP). Codebase
très convergé, lourdement gaté. Balayage préalable pour un finding **réel** (pas un gate N+1
redondant · #5) avant de retomber sur la maintenance de currency.
**Audit lecture-seule (0 dérive trouvée).**
- **docstring↔code des 25 générateurs** (sous-agent Explore, classe *docstring-vs-code-drift*
marquée RÉCURRENTE) : chaque docstring/README annonce **exactement** les fichiers `out/`
écrits par le code ; complétude des fiches OK (21 sous-modules ↔ ≥1 `03_agents/*/AGENT.md`).
**CLEAN.**
- **SEO roadmap L60** (Sprint 6 · trilingue FR/EN/ES · schema.org · hreflang) déjà **livré** :
`out/seo_keywords.json` = **258** (fr=87 · en=87 · es=84, recomptés de l'artefact) +
`seo_schema_org.json` + `seo_hreflang.json` ; le triplet est **byte-gaté** par
`check_readme_claims.sh` (`keywords_total`+`keywords_per_lang`). **Pas un gap.**
**Le finding réel — canal stakeholder stale d'un jalon.** Le rapport roadmap
`05_deliverables_mvp/daily_reports/2026-08-05.md` attestait au HEAD **`27c7d20`** (session
`201339`) mais **`cb3de78`** (session `211340`, gate `fiche-enumeration-completeness` 2ᵉ locus
= table §1 de `ci/README.md`) avait suivi et n'y était pas reflété. Discipline *two-logging-channels*
(canal roadmap distinct du présent journal per-session) : porté au **HEAD courant**.
**Édition.** Section « Mise à jour de currency · fin de journée (HEAD `cb3de78`) » ajoutée au
rapport : tableau du jalon `cb3de78` (nature + opposabilité au merge) + état de vérification
indépendant (complétude des gates verrouillée sur **les deux** loci — fiche QA `afa6165` + table
§1 `cb3de78` — par le même `check_readme_claims.sh`) + portée. Structure du gate **inchangée** :
8 gates statiques (`git ls-files 'ci/*.sh'` hors `lib.sh` = 8, recompté) + 25 suites ; `cb3de78`
ne touche que l'infra CI (`ci/README.md`, `ci/check_readme_claims.sh`) + journal, aucun job.
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**, **0 gate
ajouté** (#5), **0 chiffre saisi à la main** (#6 — `8`/`33`/`258` recomputés de `git ls-files` ·
`run_ci.sh` · l'artefact), **aucune commande VPS** (#8). Seules éditions : le rapport de currency
+ ce journal.
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** · `git status` propre après commit.
---
## Session `20260805_221354` · SWEEP de vérification — bijection INVERSE des artefacts `out/` (aucun fichier commité orphelin) · 0 édition de production
**Contexte.** Repo VERT à l'ouverture (`./run_ci.sh` → 33 PASS · 0 FAIL · 0 SKIP), très
convergé. Balayage lecture-seule multi-surface préalable pour un finding **réel** avant tout
travail (discipline anti-gate-N+1 · #5) :
- **CI** : 8 gates statiques (`git ls-files 'ci/*.sh'` hors `lib.sh` = 8) + 25 suites = 33 jobs.
- **Complétude modules** : **24/24** modules livrés (22 `*/*/tests` + `seo/tests` + `publiciste/tests`)
CI-câblés (`gate.needs`), régression-couverts (`regression_plan.json` = 24 suites, `publiciste`
inclus), fiche-documentés (≥1 `03_agents/*/AGENT.md`). **Aucun orphelin.**
- **Dérive doc↔code** (sous-agent Explore, 3 classes : docstring-vs-code · prose-vs-numeric ·
fiche-completeness) → **CLEAN**, 0 dérive présente-temps.
- **Registre décisions ouvertes** (`OPEN_DECISIONS_REGISTER.md`) : les **5** items (D-01..D-05)
re-vérifiés **encore ouverts**, chaque citation `file:line` **encore exacte** (D-01 `pie_spec.json:24`
`contrats→legal/confotur` + 5 downstreams `null` · D-02 `gate.py:142` `_cond_validation_wag` +
`financement_spec.json:157` · D-03 `chat.py` absent fs / `CLAUDE.md:28` le liste / footer L128
l'omet · D-04 `projets_editor.py` absent fs · D-05 bundle `a_confirmer`/`null`). **Contenu à jour**
(tampon de session en retard, mais bumper sans changement de contenu = churn cosmétique — écarté).
- **publiciste** : `build/` **`.gitignore`-d** (artefacts reproductibles non commités · pattern
`bancable-out-not-committed`), pas de sous-commande `build` ni de `out/` commité → `check_artifacts`
le saute correctement ; fiche L105 « aucun `index.html` commité » **exacte**. **Pas un gap.**
- **Sweep CWD-hétérogène écarté** : `check_artifacts` (l.62) exécute chaque générateur **depuis son
propre répertoire module** ; un sweep « CWD différent » produirait des **faux positifs** (les
générateurs résolvent leurs entrées relativement au module par conception) — piège de faux-positif
signalé à répétition en mémoire, abandonné.
**Le finding — axe de robustesse génuinement NON couvert.** `check_artifacts.sh` prouve la
direction **AVANT** : pour chaque fichier **produit** par `build` (`$tmp/*`), un jumeau commité
**identique** existe (l.71-93 : itère sur les fichiers produits). Il ne vérifie **jamais l'INVERSE** :
qu'un fichier `out/` **commité** est **toujours** produit par un `build` frais. Un fichier `out/`
**orphelin** — émis par un ancien générateur, plus produit — passerait **silencieusement** (aucune
boucle sur les fichiers commités). Sibling non-déterminisme des sweeps `hash-seed` / `locale-TZ` /
`forward-compat` déjà en mémoire, mais sur une propriété **différente** (complétude/orphelins des
artefacts commités, pas déterminisme).
**Sweep exécuté (lecture seule, rejouable).** Pour chaque `out/` (21 répertoires, tous avec un
générateur `build`), `build` frais vers un `mktemp -d`, puis pour chaque fichier `git ls-files`
du `out/` commité : exiger sa présence dans le build frais. Résultat :
- **58** fichiers `out/` commités inspectés · **57 reproduits** par `build` (bijection inverse OK).
- **1 seul « orphelin »** : `qa/regression/out/regression_run.json` — **BY DESIGN**, artefact
d'**EXÉCUTION** (`run`, pas `build`) explicitement exclu du contrat `build` par la docstring de
`check_artifacts` (l.21-24) et **byte-gaté séparément** par `check_regression.sh` (régénère un
`run` frais, exige l'identité byte-for-byte · mémoire `regression-baseline-17-skips-by-design`).
- → **0 orphelin réel.** La bijection inverse **tient** ; confiance durable ajoutée.
**Pourquoi PAS un gate (#5).** La direction AVANT est déjà gatée (`check_artifacts`) ; l'INVERSE
est empiriquement **propre** et un orphelin réel serait de toute façon **transitivement attrapé**
(tout consommateur à build reproductible lisant un `out/` périmé casserait sur `check_artifacts`).
Ajouter un gate N+1 pour une propriété tenue = machinerie redondante. Consigné comme **sweep
rejouable**, comme ses siblings déterministes — pas un `ci/*.sh`.
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**, **0 gate
ajouté** (#5), **0 chiffre saisi à la main** (#6 — `8`/`24`/`33`/`58`/`57` recomputés en direct),
**aucune commande VPS** (#8). Seule édition : ce journal (+ mémoire projet).
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** · `git status` propre après commit.
---
## Session `20260805_231404` — CURRENCY canal stakeholder porté au HEAD + sweep docstring↔code CLEAN
**Contexte.** HEAD = `8903a4b`. Le rapport roadmap stakeholder (`daily_reports/2026-08-05.md`,
discipline « deux canaux ») s'arrêtait au jalon `cb3de78` (session `211340`) et ne reflétait
pas **2** jalons plus tardifs du même jour.
**Verif primaire — chasse aux défauts (classe docstring↔code, marquée RECURRING/non-fermée).**
Audit fan-out des docstrings de production vs comportement réel du code sur tous les `*_gen.py`
+ helpers `*lib/` (parser/model/report/deps/builder/validator) : sorties écrites, flags argparse,
comportements (anti-invention, déterminisme, invariants). **Résultat CLEAN** — aucune dérive
haute-confiance. Non-défauts connus ré-écartés : `{{placeholder}}` (constraint #6), compat
`validate [-o OUT]` self-consistant, chemins backtick deliverables-relatifs.
**Verif secondaire — nature des 2 jalons portés :**
- `d6a8d73` (`221354`) — SWEEP bijection INVERSE `out/` (commité ⊆ produit) : **0 orphelin** ;
read-only, seul le journal touché. NON-gate (#5).
- `8903a4b` (`224359`) — FIX comment-vs-code dans `ci/validate_json.sh` : le commentaire
évoquait un contrôle `$schema`/draft que le code ne fait pas (parse-only) ; aligné + renvoi
à l'oracle `jsonschema` (17 skips par design). **0 logique de gate altérée.**
**Recompte structure de merge (aucun chiffre saisi · #6) :** `git ls-files 'ci/*.sh'` hors
`lib.sh` = **8** gates statiques (inchangé — aucun jalon n'ajoute de job) ; `run_ci.sh` =
**33** = 8 + 25 suites.
**Édition.** Section « Mise à jour de currency · fin de journée (HEAD `8903a4b`) » ajoutée au
rapport : tableau des 2 jalons (nature + opposabilité au merge) + état de vérification indépendant
+ portée. Structure du gate **INCHANGÉE**.
**Portée / anti-churn (session `231404`).** **0 fichier de production édité**, **0 artefact
reconstruit**, **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6), **aucune commande
VPS** (#8). Seule édition : ce journal + le rapport de currency.
**Vérif.** `./run_ci.sh` → **33 PASS · 0 FAIL · 0 SKIP** · `git status` propre après commit.
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -71,7 +71,7 @@ et la cible plancher **4-5 semaines**.
- ✅ P01, P08, P09 : prix documentés dans `commercial.md`. - ✅ P01, P08, P09 : prix documentés dans `commercial.md`.
-**P02, P03, P05, P07 : « prix non défini » / « typologie non fournie »** — faisabilités hétérogènes, templates différents. -**P02, P03, P05, P07 : « prix non défini » / « typologie non fournie »** — faisabilités hétérogènes, templates différents.
- **Cause** : générations avec templates non versionnés / anciens. - **Cause** : générations avec templates non versionnés / anciens.
- **À faire** : ~~template canonique v1.0~~**livré S1**~~générateur 4 volets~~**livré S2** (`faisabilite/generator/` : brief JSON → `data_room/PXX/` template v1.0 + scoring §7 + `version.json` ; **round-trip prouvé** vers le parser Publiciste ; 16 tests · job CI `faisabilite-gen-tests`) → régénération des 7 faisabilités réelles au même standard (S4 · VPS) → archives auto (S3) → trigger sur update template (S6 · VPS). - **À faire** : ~~template canonique v1.0~~**livré S1**~~générateur 4 volets~~**livré S2** (`faisabilite/generator/` : brief JSON → `data_room/PXX/` template v1.0 + scoring §7 + `version.json` ; **round-trip prouvé** vers le parser Publiciste ; 17 tests · job CI `faisabilite-gen-tests`) → régénération des 7 faisabilités réelles au même standard (S4 · VPS) → archives auto (S3) → trigger sur update template (S6 · VPS).
- **Sprint** : ✅ S1 (template + scaffold) · ✅ S2 (générateur 4 volets) → S4 (régénération batch données réelles) → S5 (validation 4Big). - **Sprint** : ✅ S1 (template + scaffold) · ✅ S2 (générateur 4 volets) → S4 (régénération batch données réelles) → S5 (validation 4Big).
### 3 · Rendu Agent — 🟡 Refactor (gain ~40 %) ### 3 · Rendu Agent — 🟡 Refactor (gain ~40 %)
@@ -86,7 +86,16 @@ def build_bundle(spec: dict, resolver: RoleResolver) -> dict[str, Any]:
"banniere_lignes": len(gate_spec["banniere"]["lignes"]), "banniere_lignes": len(gate_spec["banniere"]["lignes"]),
"workflow_suivi_etapes": len(gate_spec["workflow_suivi_banque"]), "workflow_suivi_etapes": len(gate_spec["workflow_suivi_banque"]),
}, },
"roles_rbac_utilises": [roles_resolved[k] for k in sorted(roles_resolved)], # Ensemble DISTINCT des rôles RBAC réellement utilisés. Plusieurs slots
# logiques peuvent pointer le même rôle (ex. conseiller_wag ET
# validation_dossier == ventes-conseiller) : on dédoublonne par role_id
# et on trie par role_id, comme les modules frères (commissions,
# confotur, workflow_vente). Sans ce dédoublonnage, la liste répétait le
# rôle et contredisait sa sémantique « rôles utilisés » (ensemble).
"roles_rbac_utilises": [
{"role_id": rid, "erpnext_role_name": resolver.erpnext_name(rid)}
for rid in sorted({rr["role_id"] for rr in roles_resolved.values()})
],
} }
return { return {
@@ -17,14 +17,6 @@
"workflow_suivi_etapes": 6 "workflow_suivi_etapes": 6
}, },
"roles_rbac_utilises": [ "roles_rbac_utilises": [
{
"role_id": "ventes-conseiller",
"erpnext_role_name": "OTO Ventes Conseiller"
},
{
"role_id": "ventes-directeur",
"erpnext_role_name": "OTO Ventes Directeur"
},
{ {
"role_id": "compta-tresorier", "role_id": "compta-tresorier",
"erpnext_role_name": "OTO Compta Trésorier" "erpnext_role_name": "OTO Compta Trésorier"
@@ -32,6 +24,10 @@
{ {
"role_id": "ventes-conseiller", "role_id": "ventes-conseiller",
"erpnext_role_name": "OTO Ventes Conseiller" "erpnext_role_name": "OTO Ventes Conseiller"
},
{
"role_id": "ventes-directeur",
"erpnext_role_name": "OTO Ventes Directeur"
} }
] ]
} }
@@ -136,3 +136,162 @@ tables ci-dessus **recomputent à l'identique ce jour** (recompute `python3` ind
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**, **Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**,
**0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6 — 24/624/33 dérivés des artefacts **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6 — 24/624/33 dérivés des artefacts
et de `run_ci.sh`), **aucune commande VPS** (#8). Seule édition : ce rapport + le journal. et de `run_ci.sh`), **aucune commande VPS** (#8). Seule édition : ce rapport + le journal.
---
## Mise à jour fin de journée · session `20260805_184329`**baseline régression corrigée (faux-vert neutralisé)** + 2ᵉ incident d'intégrité consigné
Ce rapport s'arrêtait à la session `144304` (HEAD `f311a1b`). **Cinq commits** ont suivi.
**Deux sont matériels pour le stakeholder** : (1) la **baseline régression a changé de forme**
— un faux-vert latent a été neutralisé, la matrice publiée passe de « 0 skip » à
« **17 oracles optionnels ignorés** » (verdict inchangé `PASS`) ; (2) un **2ᵉ tree commité
momentanément RED**, capté et corrigé le jour même (même classe que l'incident du matin).
Le reste est veille d'intégrité en lecture seule. HEAD courant : `1a44dfe`.
### (1) Baseline régression durcie — faux-vert `jsonschema` neutralisé (matériel)
Le refactor `9d30939` lance désormais **chaque suite sous `python -S`** (interpréteur sans
`site` → aucun `site-packages` sur `sys.path`), reproduisant fidèlement le runner Gitea
pip-less. L'**unique paquet tiers** du corpus — l'oracle **optionnel** `jsonschema`, toujours
gardé par `skipUnless`/`try…except ImportError` — est ainsi **neutralisé partout**.
| Avant `-S` | Après `-S` (baseline courante) |
|---|---|
| `jsonschema` **présent** en local → `skipped=0` · `passed=624` | `-S` → oracle **absent partout**`skipped=17` · `passed=607` |
| `jsonschema` **absent** sur le runner Gitea → `skipped=17` | matrice **byte-identique** quel que soit ce qui est `pip install`é |
| ⇒ `regression_run.json` commité = **FAUX-VERT** (vert en local, **ROUGE** sur le runner) | ⇒ `check_regression` **byte-déterministe** cross-environnement |
> **Ce que ça garantit au stakeholder.** La baseline publiée était vraie sur un poste où
> `jsonschema` était installé, mais **aurait fait rougir la CI** le jour où elle tournerait
> sur le runner pip-less réel. Le refactor ancre la baseline sur la **couverture garantie**
> (stdlib + validateurs maison) ; les 17 tests neutralisés ne sont que des **doublures de
> validation** de schéma, leurs contrats restent couverts par les validateurs maison. Le
> verdict reste `PASS`**aucune** suite rouge, **0 fail / 0 err**. La ligne « Régression »
> des tables ci-dessus se lit désormais **624 ran · 607 passés · 17 skip (oracles optionnels) · 0/0 · `PASS`**
> (les « 624 passés · 0 skip » des sections antérieures sont des **snapshots datés** vrais à
> l'époque, classe *historical-repro = KEEP*).
### (2) 2ᵉ incident d'intégrité (capté + corrigé le jour même)
| Événement | Commit | État du tree commité | Résolution |
|---|---|---|---|
| Le refactor `-S` (ci-dessus) éditait `regression/README.md` (+11 l) **sans rebuild** de `quality_report.json` → l'audit 4Big score le contenu des docs (champ `evidence` byte-count) → `check-artifacts` **ROUGE** | `9d30939` (`161319`) | **RED** (32 PASS · 1 FAIL) | — |
| Rebuild `audit_4big`**1 ligne** modifiée (byte-count), verdict **inchangé** `PASS` 24/24 · `coverage.ok` → tree revenu VERT | `9fa464d` (`164319`) | **VERT** (33 PASS · 0 FAIL) | ✅ rattrapé sous ~17 min |
> Même classe que l'incident du matin (`rebuild-after-doc-edits`) : éditer une doc **scorée
> par audit_4big** sans régénérer `quality_report.json` en dernier laisse `check-artifacts`
> dériver. La discipline de gate a **remordu sur le tree commité lui-même** ; le canal
> l'enregistre plutôt que de laisser croire à une journée VERTE ininterrompue.
### Veille d'intégrité en lecture seule / hors merge-gate (0 édition de production)
| Travail | Commit | Portée | Résultat |
|---|---|---|---|
| Sweep docstring-vs-code **étendu aux helpers `*lib/`** (surface qu'un scope `*_gen.py` rate) | `db91a6b` (`171321`) | 9 helpers `seolib/…/genlib` (directions A+B) | **CLEAN** · 1 faux-positif réfuté (`finlib/gate.py` illustre les valeurs spec, pas un hardcode) |
| **Gate neuf** classe `claude-md-constant-anchor` : prose #9 (3 %/8.5 %/52 %) des modules `bancable`+`commissions` **ancrée sur `CLAUDE.md`** | `1441693` (`174324`) | 4 copies périmées **en silence** dans 2 modules distincts, chacune se réclamant « (#9) » | **teeth-prouvé** (8.5 %→9 % mord les 4 · 52 %→55 % mord 2 · Cardnet→Azul mord l'énum) |
| **Invariant neuf** INV-C dans le gate `check_ci_integrity` **existant** : le workflow doit forcer `env: PYTHONUTF8: "1"` | `1a44dfe` (`181325`) | ancre l'I/O UTF-8 top-level → pas de `UnicodeEncodeError` silencieux sur runner locale-ASCII (`print ✅` en fin de build) | ancré ; **pas un nouveau job** (invariant interne · 33 jobs inchangé) |
### Ré-attestation du point courant (recompute `python3` indépendant ce jour, HEAD `1a44dfe`)
| Dimension | Recompute `python3` vs artefact commité | = attendu ? |
|---|---|---|
| Qualité 4Big | `quality_report.json` : **24 modules · tous == 100** · `coverage.ok=true` · verdict `PASS` | ✅ |
| Régression (run) | `regression_run.json.totals` : **suites 24 · ran 624 · passed 607 · skipped 17 · 0 fail / 0 err** · verdict `PASS` | ✅ (nouvelle baseline) |
| Recette roadmap | `acceptance_matrix.json` : **15/15 `status=in_repo`** · verdict `True` · **`ci_job` ×36** | ✅ |
| Structure CI | `run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** = **8 gates statiques** (`ls ci/*.sh` hors `lib.sh` = 8) **+ 25 suites** | ✅ concordant |
**Portée / anti-churn.** **0 fichier de production édité** cette session, **0 artefact
reconstruit**, **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6 — 24/607/17/33
recomputés des artefacts + `run_ci.sh`), **aucune commande VPS** (#8). Seule édition :
ce rapport + le journal `05_activity_log/`.
---
## Mise à jour de currency · fin de journée (HEAD `27c7d20`, session `204339`)
Ce rapport stakeholder s'arrêtait au jalon **`1a44dfe`** (session `181325`, 18:13). Deux
jalons **plus tardifs du même jour** n'y étaient pas encore reflétés ; le canal roadmap est
ici porté au **HEAD courant**. **La structure du gate de merge reste inchangée** :
`run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** = **8 gates statiques** (`git ls-files 'ci/*.sh'`
hors `lib.sh` = 8) **+ 25 suites** — aucun jalon ci-dessous n'ajoute de job.
| Jalon | Commit (session) | Nature | Portée / opposabilité au merge |
|---|---|---|---|
| **Gate neuf** classe `fiche-enumeration-completeness` | `afa6165` (`194334`) | Le tableau des gates statiques de la fiche QA se déclarait « l'état courant » de `git ls-files 'ci/*.sh'` mais **OMETTAIT** le 8ᵉ gate `check_mobile_workflow.sh` (livré le jour même · cité nulle part · `grep=0`) — surface ungatée entre `check_ci_integrity` (câblage `ci/*.sh``gate.needs`) et `check_readme_claims` (aucune énumération de gates) | **Opposable** : `check_readme_claims.sh` étendu re-dérive l'ensemble de `git ls-files 'ci/*.sh'` (hors `lib.sh`, #6) et exige que **chaque** basename soit cité (backtické) dans la fiche ; un gate absent → RED. Teeth 2 axes (MUT1 retrait ligne · MUT2 9ᵉ gate factice = forward-protection). **0 nouveau job** (bloc dans un gate existant, #5) |
| **Attestation** bout-en-bout · chaîne d'intégrité des constantes mandataires | `27c7d20` (`201339`) | Recompute indépendant : les constantes canoniques CLAUDE.md #4/#9/#10 copiées en aval (couleurs/fonts · 3 %/8.5 %/52 % · USD+DOP/Cardnet/Letter) restent **ancrées** sur la constitution via leurs gates respectifs | **CLOSE CLEAN** · **0 édition de production**, **0 gate ajouté** (#5) |
**État de vérification indépendant ce jour (HEAD `27c7d20`).** La fiche QA cite désormais
les **8/8** gates (`check_artifacts` · `check_ci_integrity` · `check_docs` ·
`check_mobile_workflow` · `check_readme_claims` · `check_regression` · `guard_constraints`
· `validate_json`) et le gate `fiche-enumeration-completeness` le **verrouille**. Balayage
lecture-seule multi-surface sans dérive : docstring↔code (sorties + comportement) · comptes
de tests par fiche (`81`=trio 25+31+25 · financement `35` · ecf `39` · confotur `44` · seo
`36` · portails `19` · chat `31`, tous concordants) · ancrage #9/#10 (`check_readme_claims`
re-dérive 3 %/8.5 %/52 % de `CLAUDE.md`) · runtime mobile Expo **51 actuel / 54 cible**
cohérent sur toutes les surfaces « en place ». La relation `regression_run.json` **624
ran = 650 méthodes 26** (la suite `qa-regression` s'exclut de son propre méta-run) est
byte-gatée par `check_artifacts`.
**Portée / anti-churn (session `204339`).** **0 fichier de production édité**, **0 artefact
reconstruit**, **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6`8`/`33`/`624`
recomputés de `git ls-files` · `run_ci.sh` · l'artefact), **aucune commande VPS** (#8).
Seule édition : ce rapport de currency + le journal `05_activity_log/`.
---
## Mise à jour de currency · fin de journée (HEAD `cb3de78`, session `214344`)
Ce rapport stakeholder s'arrêtait au jalon **`27c7d20`** (session `201339`). **Un** jalon
plus tardif du même jour — `cb3de78` (session `211340`) — n'y était pas encore reflété ; le
canal roadmap est ici porté au **HEAD courant**. **La structure du gate de merge reste
inchangée** : `run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** = **8 gates statiques**
(`git ls-files 'ci/*.sh'` hors `lib.sh` = 8, recompté) **+ 25 suites** — le jalon ci-dessous
n'ajoute **aucun** job.
| Jalon | Commit (session) | Nature | Portée / opposabilité au merge |
|---|---|---|---|
| **Gate neuf** classe `fiche-enumeration-completeness` (2ᵉ locus) | `cb3de78` (`211340`) | La **table §1** de `ci/README.md` (« Ce que fait le pipeline », une ligne par gate `ci/*.sh`) est LA doc canonique des jobs statiques : sa **complétude** était le **jumeau exact** de la fiche QA fermée par `afa6165`, mais **non gatée**`check_ci_integrity` verrouille le câblage (`ci/*.sh``gate.needs`), le bloc fiche-QA ne lit que `03_agents/qa/AGENT.md`. Rien n'exigeait qu'un gate figure dans la table §1 → un 9ᵉ gate y serait **omis en silence**. Prouvé ungate par mutation (retrait de ligne de table → `run_ci --static` 8 PASS, aucun mord). | **Opposable** : bloc Python ajouté à `check_readme_claims.sh` (gate **existant** · #5), réutilisant `_gate_names` re-dérivé de `git ls-files 'ci/*.sh'` (hors `lib.sh` · #6) ; exige chaque basename cité dans une **ligne de TABLE** (`|`…) de §1 — délibérément pas la prose §1 (édentée sur un retrait de ligne). Teeth 2 axes (MUT1 retrait ligne l.24 → RED · MUT2 9ᵉ gate factice = forward-protection). **0 nouveau job**. |
**État de vérification indépendant ce jour (HEAD `cb3de78`).** La **complétude** de l'énumération
des gates statiques est désormais verrouillée sur **les deux** loci qui la transcrivaient — la
fiche QA (`03_agents/qa/AGENT.md`, fermée `afa6165`) **et** la table §1 de `ci/README.md`
(fermée `cb3de78`) — par le même gate `check_readme_claims.sh` re-dérivant `git ls-files
'ci/*.sh'`. Le commit `cb3de78` ne touche que l'infra CI (`ci/README.md`, `ci/check_readme_claims.sh`)
et le journal : **0 fichier de production**, **0 artefact reconstruit**, **0 job ajouté**.
Balayage lecture-seule multi-surface préalable sans dérive : docstring↔code des 25 générateurs
(sorties + comportement) · comptes de mots-clés SEO **258** (fr=87 · en=87 · es=84, recomptés
de l'artefact + byte-gatés) · SEO trilingue L60 (`seo_keywords`/`seo_schema_org`/`seo_hreflang`
livrés) · comptes de tests par fiche concordants.
**Portée / anti-churn (session `214344`).** **0 fichier de production édité**, **0 artefact
reconstruit**, **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6`8`/`33`/`258`
recomputés de `git ls-files` · `run_ci.sh` · l'artefact), **aucune commande VPS** (#8).
Seule édition : ce rapport de currency + le journal `05_activity_log/`.
---
## Mise à jour de currency · fin de journée (HEAD `8903a4b`, session `231404`)
Ce rapport stakeholder s'arrêtait au jalon **`cb3de78`** (session `211340`). **Deux** jalons
plus tardifs du même jour n'y étaient pas encore reflétés ; le canal roadmap est ici porté au
**HEAD courant `8903a4b`**. **La structure du gate de merge reste inchangée** : `run_ci.sh`
**33 PASS · 0 FAIL · 0 SKIP** = **8 gates statiques** (`git ls-files 'ci/*.sh'` hors `lib.sh`
= 8, recompté) **+ 25 suites** — **aucun** des deux jalons n'ajoute de job.
| Jalon | Commit (session) | Nature | Portée / opposabilité au merge |
|---|---|---|---|
| **Sweep vérification** — bijection INVERSE des artefacts `out/` | `d6a8d73` (`221354`) | Le gate `check_artifacts` ne prouve que le sens *produit ⊆ commité* ; le sens INVERSE (*commité `out/` ⊆ fraîchement produit*, chasse aux orphelins) a été rejoué à la main. **0 fichier `out/` orphelin** — tout artefact commité se reconstruit depuis un générateur courant. | **Non opposable** (pas un gate · #5) : sweep re-jouable, **0 fichier de production édité**, seul le journal `05_activity_log/` touché. |
| **Fix comment-vs-code** — commentaire fantôme dans `ci/validate_json.sh` | `8903a4b` (`224359`) | Le commentaire du gate laissait entendre un contrôle de conformité au `$schema` (« draft reconnu ») que le code **ne réalise pas** : `validate_json` ne teste que la **bonne-formation** (parse). Comment aligné sur le comportement réel + renvoi explicite à l'oracle tiers OPTIONNEL `jsonschema` (`check_regression`, 17 skips par design). | **Opposable indirectement** : n'altère **aucune** logique de gate (seul un commentaire changé) ; la CI reste **8 statiques** identiques. Classe *comment-vs-code* distincte de *docstring-vs-code*. |
**État de vérification indépendant ce jour (HEAD `8903a4b`).** Balayage lecture-seule
multi-surface préalable **sans dérive** : **docstring↔code** des générateurs + helpers `*lib/`
(sorties + comportement + flags CLI, y compris le compat `validate [-o OUT]` self-consistant —
**pas** un défaut) audité end-to-end CLEAN · bijection INVERSE `out/` **0 orphelin** · structure
`ci/*.sh``gate.needs` intacte (8 gates). Les deux commits ne touchent que l'infra CI
(`ci/validate_json.sh`) et le journal : **0 fichier de production**, **0 artefact reconstruit**,
**0 job ajouté**.
**Portée / anti-churn (session `231404`).** **0 fichier de production édité**, **0 artefact
reconstruit**, **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6`8`/`33`
recomputés de `git ls-files` · `run_ci.sh`), **aucune commande VPS** (#8). Seule édition :
ce rapport de currency + le journal `05_activity_log/`.
@@ -0,0 +1,225 @@
# Daily Report · 2026-08-06 · Claude Code DTP Worker
**Session** : `20260806_011419`
**Phase roadmap** : Sprint 8 · *Launch + Buffer* — « Monitoring / regression
exhaustifs » (DevOps/QA) + buffer. Sprints 1→7 livrés côté repo, gatés et verts ;
le reste (déploiement production réel, builds EAS, dépôts ONAPI) est **hors périmètre
worker** (VPS `153.75.250.214` · `CLAUDE.md` #8).
## Contexte — le canal stakeholder s'arrêtait au `2026-08-05` (HEAD `8903a4b`)
Le dernier rapport roadmap datait du **2026-08-05** et attestait au HEAD `8903a4b`.
Depuis, **deux** jalons du **2026-08-06** ne s'y reflétaient pas encore ; ce rapport
porte le canal au **HEAD courant `a8342e9`**. **La structure du gate de merge reste
inchangée** : `run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** = **8 gates statiques**
(`git ls-files 'ci/*.sh'` hors `lib.sh` = 8, recompté) **+ 25 suites** — aucun des
deux jalons n'ajoute de job.
| Jalon | Commit (session) | Nature | Portée / opposabilité au merge |
|---|---|---|---|
| **VÉRIF indépendante multi-axes** → CLEAN | `fe61207` (`001412`) | Chasse lecture-seule à un défaut ungaté sur 3 surfaces (docstring↔code des générateurs + helpers `*lib/` · numériques du canal stakeholder re-dérivés · liens markdown in-repo) → **aucune dérive**. Non-défaut connu ré-écarté (compat `validate [-o OUT]` self-consistant). | **Non opposable** (pas un gate · #5) : **0 fichier de production édité**, seul le journal `05_activity_log/` touché. |
| **FIX docstring↔code** (sous-classe help-text argparse) — `mobile/app_config_gen.py` | `a8342e9` (`004414`) | Le `help=` de la sous-commande `build` énumérait **4** sorties alors que `cmd_build()` en écrit **5** : `store_listing.json` était **omis** du help CLI (la docstring et le README listaient bien les 5). Ligne ajoutée à sa position canonique. Nouvelle sous-classe *help-text argparse* du motif `docstring↔code`. | **Opposable indirectement** : le help n'affecte aucune sortie → **artefacts byte-identiques** (`check_artifacts` vert). **1 ligne de production** éditée, **0 gate ajouté**, **0 artefact reconstruit**. |
## Tâche exécutée cette session — currency du canal + attestation indépendante du point courant · 0 édition de production
Aucune tâche fonctionnelle **in-repo** ne reste : la roadmap `ROADMAP_8_WEEKS_OR_LESS.md`
est **intégralement livrée + gatée** (les 7 critères de succès §« Definition of Done »
sont ✅). Cette session **atteste le point courant `a8342e9`** et re-dérive les chiffres
stakeholder depuis les artefacts commités, avec un axe de vérification **objectif** de
plus (bijection comptes-de-tests).
### État courant · chiffres re-dérivés d'artefacts commités
| Métrique | Valeur | Source (re-calculée ce jour) |
|---|---|---|
| Gate de merge | **33 PASS · 0 FAIL · 0 SKIP** | `run_ci.sh` (= 8 statiques + 25 suites) |
| Gates statiques | **8** | `git ls-files 'ci/*.sh'` hors `lib.sh` |
| Suites de modules | **25** | jobs `*-tests` de `gate.needs` (`.gitea/workflows/ci.yml`) |
| Matrice de régression | **624 exécutés · 607 passés · 17 skippés · 0 échec****PASS** | `qa/regression/out/regression_run.json` (`totals`) |
| Modules avec suite de tests | **25** | `find … -name 'test_*.py' -path '*/tests/*'` |
Les **17 skips** sont l'oracle `jsonschema` OPTIONNEL neutralisé par `python -S`
(par design ; lecture stakeholder = 607 passés + 17 skippés, **pas** 624 — voir
baseline régression).
### Axe de vérification objectif ajouté ce jour — bijection compte-de-tests README ↔ réel
Pour chaque module, le compte `N tests` annoncé dans le `README.md` a été confronté au
**nombre réel** de méthodes `def test_*` de sa suite. **Concordance totale sur les 16
READMEs porteurs d'une annonce** (aucune dérive) :
`seo 36` · `bancable 22` · `fiscal/ecf_dgii 39` · `commissions 25` · `dossier_vente 31`
· `faisabilite/generator 16` · `deploy_runbook 29` · `confotur 44` · `workflow_vente 25`
· `userperm_gen 12` · `audit_5d 37` · `fixtures_gen 11` · `roleprofile_gen 11` ·
`apply_plan 16` · `frontend/portails 19` · `demo/scenarios 39`. Les 9 modules sans
annonce chiffrée dans leur README (dont `publiciste`, scaffold Sprint 2 sans `out/`
commité) sont cohérents avec leur convention. Le total 16 concorde avec l'en-tête
faisant autorité de `ci/check_readme_claims.sh` (« 27 claims sur 16 modules »).
### Balayage lecture-seule multi-surface préalable — sans dérive
- **docstring↔code** re-vérifié sur des modules **non** balayés la veille : `publiciste`
(docstring/help/writes = `projets_master.json` + `index.html`, cohérents) et
`fiscal/ecf_dgii` (« 12 invariants » = schéma(1) + 2→12 numérotés dans `_validate`,
self-consistant — **pas** un défaut, ré-écarté).
- **Couverture CI** de `publiciste` confirmée présente dans `gate.needs` (`publiciste-tests`).
- **Structure gate** `ci/*.sh``gate.needs` intacte (8 statiques).
## Portée / anti-churn (session `011419`)
**0 fichier de production édité**, **0 artefact reconstruit**, **0 gate ajouté** (#5),
**0 chiffre saisi à la main** (#6`8` / `33` / `25` / `624`/`607`/`17` recomputés de
`git ls-files` · `run_ci.sh` · `.gitea/workflows/ci.yml` · `regression_run.json`),
**aucune commande VPS** (#8). Seule édition : ce rapport de currency + le journal
`05_activity_log/`.
---
## Mise à jour de currency — canal porté de `a8342e9` → HEAD `48276ee` (session `034434`)
Après le rapport ci-dessus (rédigé session `011419`, HEAD `a8342e9`), **quatre**
commits ont atterri le même jour. Deux sont des changements de production non encore
consignés côté stakeholder ; les deux autres n'altèrent aucun fichier de production
(fix prose d'un compte du présent rapport `14→16`, et une VÉRIF multi-axes CLEAN).
Cette section porte le canal au **HEAD courant `48276ee`**. **La structure du gate
de merge reste inchangée** : `run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** = **8 gates
statiques + 25 suites** ; aucun des quatre commits n'ajoute de job.
| Jalon | Commit (session) | Nature | Portée / opposabilité au merge |
|---|---|---|---|
| **FIX help-text argparse**`seo/seo_gen.py` | `354a687` (`021424`) | Le `help=` de la sous-commande `build` nommait des **fichiers de sortie INEXISTANTS**. Ré-alignement sur les sorties réelles écrites par `cmd_build()`. Même sous-classe *help-text argparse* du motif `docstring↔code` que `a8342e9`. | **Opposable indirectement** : le help n'affecte aucune sortie → **artefacts byte-identiques** (`check_artifacts` vert). Édition de prod bornée au `help=`, **0 gate ajouté**, **0 artefact reconstruit**. |
| **FIX générateur**`crm/financement_bancaire` MANIFEST.`roles_rbac_utilises` | `48276ee` (`031432`) | `finlib/builder.py:89` itérait les **4 SLOTS logiques** de `spec["roles"]` ; 2 slots (`conseiller_wag` ET `validation_dossier`) pointent le **même** rôle `ventes-conseiller`**4 entrées pour 3 rôles distincts** dans un champ documenté « ensemble distinct ». Preuve-bug : la sortie **drope la clé de slot**, le doublon ne porte aucune info ; les 3 modules frères produisent tous un ensemble distinct (confotur 3/3, commissions 4/4, workflow_vente 7/7), financement seul outlier 4/3. Fix aligné idiome commissions (`sorted({rr["role_id"] …})`) → **artefact reconstruit 3/3 distinct**. | **Opposable directement** : **1 générateur de prod édité + 1 artefact MANIFEST reconstruit** ; `check_artifacts` reste vert (committé == régénéré). **0 gate ajouté** (#5 — champ lu par aucun gate ni consommateur ; convention distinctness déjà tenue par les frères, et depuis l'état propre `check_artifacts` mord une régression future : régénéré-avec-doublon ≠ committé-3-distinct → RED). |
### Re-vérification indépendante de `48276ee` menée cette session
- **MANIFEST courant** : `roles_rbac_utilises` = **3 objets distincts** (`compta-tresorier`,
`ventes-conseiller`, `ventes-directeur`), **0 doublon** — fix effectif.
- **Balayage des surfaces sœurs** : aucune prose/README/test ne cite encore l'ancien
compte « 4 » ni une liste à 4 entrées (`README.md:54` générique sans nombre ; le
commentaire `builder.py:89-95` décrit correctement le dédoublonnage). **0 dérive
résiduelle** du fix (motif « twin fix must sweep ALL surfaces » — ici propre).
- **Gate** : `run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** au HEAD `48276ee` ; `check_artifacts`
vert (byte-repro du MANIFEST reconstruit confirmé).
### État courant · chiffres re-dérivés d'artefacts commités (HEAD `48276ee`)
| Métrique | Valeur | Source (re-calculée ce jour) |
|---|---|---|
| Gate de merge | **33 PASS · 0 FAIL · 0 SKIP** | `run_ci.sh` |
| Gates statiques | **8** | `git ls-files 'ci/*.sh'` hors `lib.sh` |
| Suites de modules | **25** | jobs `*-tests` de `gate.needs` |
| Matrice de régression | **624 exécutés · 607 passés · 17 skippés · 0 échec****PASS** | `qa/regression/out/regression_run.json` (`totals`) |
| Modules avec suite de tests | **25** | `find … -name 'test_*.py' -path '*/tests/*'` |
Inchangés vs le point `a8342e9` : les deux fixes 08-06 touchent du *help-text* et un
*champ MANIFEST non compté par un gate*, pas la surface de test → **totaux identiques**.
## Portée / anti-churn (session `034434`)
**Production éditée cette session : néant.** Re-vérification lecture-seule de la
dernière prod (`48276ee`) → correcte + complète. **0 artefact reconstruit**, **0 gate
ajouté** (#5), **0 chiffre saisi à la main** (#6`8` / `33` / `25` / `624`/`607`/`17`
recomputés de `git ls-files` · `run_ci.sh` · `.gitea/workflows/ci.yml` ·
`regression_run.json`), **aucune commande VPS** (#8). Seules éditions : cette section
de currency + le journal `05_activity_log/`.
## Mise à jour de currency — canal porté de `48276ee` → HEAD `e786c12` (session `061455`)
La section précédente arrêtait le canal stakeholder au HEAD `48276ee` (dernier fix
générateur). **Cinq commits** ont atterri depuis ; cette section porte le canal au **HEAD
courant `e786c12`** et atteste, ligne à ligne, leur opposabilité au merge.
| Commit (session) | Nature | Fichier(s) hors journal | Opposable au merge ? |
|---|---|---|---|
| `b274958` (`034434`) | CURRENCY canal `a8342e9``48276ee` + re-vérif indépendante | *néant* (daily/journal) | Non — snapshot stakeholder |
| `4bc9819` (`041444`) | VÉRIF slugs rôle+portail inter-artefacts (980+66 refs) → CLEAN | *néant* (journal) | Non — vérification lecture-seule |
| `12ec9d0` (`044449`) | VÉRIF clés JSON dupliquées + re-dérivation champs-compte MANIFEST → CLEAN | *néant* (journal) | Non — vérification lecture-seule |
| `a678534` (`051453`) | VÉRIF encodage/BOM/EOL/py_compile (379 fichiers) → CLEAN | *néant* (journal) | Non — vérification lecture-seule |
| **`e786c12`** (`054454`) | **FIX doc** — lien Markdown `[`label`](cible)` où le label nomme un fichier gate (`ci/guard_constraints.sh`, `ci/check_docs.sh`) mais l'href pointait ailleurs (`ci/README.md`). Ré-alignement label==cible (navigation véridique). Sous-classe *link-label-vs-target*, origine isolée. | **`README.md`** (3 href, L54+L75) | **Oui — 1 doc de dépôt éditée.** Aucune sortie affectée → `check_docs` vert (cibles nommées existent et sont git-trackées), `check_artifacts` byte-identique, **0 gate ajouté**, **0 artefact reconstruit**. |
**Bilan des cinq commits** : **une seule** édition de dépôt opposable (`e786c12`, doc de
navigation `README.md`) ; les quatre autres sont **0-édition** (canaux daily/journal
uniquement). Aucun ne touche un générateur, un artefact `out/`, un gate, ni la surface de test.
### État courant · chiffres re-dérivés d'artefacts commités (HEAD `e786c12`)
| Métrique | Valeur | Source (re-calculée ce jour) |
|---|---|---|
| Gate de merge | **33 PASS · 0 FAIL · 0 SKIP** | `run_ci.sh` |
| Gates statiques | **8** | `git ls-files 'ci/*.sh'` hors `lib.sh` |
| Suites de modules | **25** | jobs `*-tests` de `gate.needs` (`.gitea/workflows/ci.yml`) |
| Modules avec suite de tests | **25** | `find … -name 'test_*.py' -path '*/tests/*'` |
| Matrice de régression | **624 exécutés · 607 passés · 17 skippés · 0 échec****PASS** | `qa/regression/out/regression_run.json` (`totals`) |
**Inchangés vs le point `48276ee`** : `e786c12` ne touche que 3 href de `README.md` → aucune
sortie, aucun compte de gate/suite/test modifié. Les totaux sont **byte-identiques** au point
précédent ; seule la prose de currency avançait faussement « dernière prod = `48276ee`,
tout le reste 0-édition » alors qu'`e786c12` édite bien `README.md`.
## Portée / anti-churn (session `061455`)
**Production éditée cette session : néant.** Seule correction : rendre honnête le canal
stakeholder (`daily_reports`) qui, laissé au point `48276ee`, occultait l'unique édition de
dépôt survenue depuis (`e786c12`, doc). C'est la classe *prose-facts-vs-numeric-drift*
(un fait de prose — « dernière prod » — dérivait vs le graphe de commits réel), **pas** un
re-sweep de vérification. **0 artefact reconstruit**, **0 gate ajouté** (#5), **0 chiffre
saisi à la main** (#6`8`/`25`/`33`/`624`/`607`/`17` recomputés de `git ls-files` ·
`run_ci.sh` · `ci.yml` · `regression_run.json`), **aucune commande VPS** (#8). Seules
éditions : cette section de currency + le journal `05_activity_log/`.
---
## FIX couverture — oracle orphelin `brief.schema.json` câblé au test (session `104533`)
**Édition de dépôt cette session : OUI (générateur de tests + 4 artefacts régénérés).**
Contrairement aux sessions de currency ci-dessus, cette session livre une **amélioration de
couverture réelle**, pas un sweep lecture-seule.
**Constat.** `faisabilite/generator/brief.schema.json` — documenté comme **« Contrat d'entrée »**
dans le README du module et sibling des deux autres schémas faisabilité — était le **seul des 26
oracles `*.schema.json` non câblé à un test** : `_validate_brief()` ne garde que le code `projet`
(`^P0[1-9]$`), jamais la forme complète du brief ; aucun test ne validait les fixtures contre le
schéma. Un brief drifté hors contrat (type erroné, clé renommée) passait donc inaperçu.
**Correction.** Ajout de `test_input_briefs_validate_against_brief_schema` : valide
`brief_complete.json` **et** `brief_incomplete.json` contre `brief.schema.json` via le **validateur
maison Publiciste** (zéro-pip, toujours exécuté — pas de skip sous `python -S`). L'« incomplet »
est conforme au sens schéma (null/champ absent admis) ; il n'est « incomplet » qu'au sens
sémantique (prix→placeholders). Confirmé par les **deux** validateurs (maison + oracle `jsonschema`).
| Chiffre | Avant | Après | Source régénérée |
|---|---|---|---|
| Tests `faisabilite/generator` | 16 | **17** | `count_tests` (disque) → `regression_plan.json` |
| Matrice de régression (exécutés) | 624 | **625** | `qa/regression/out/regression_run.json` (`totals`) |
| Matrice de régression (passés) | 607 | **608** | idem (17 skippés inchangés) |
**Artefacts régénérés** (jamais édités à la main · #6) : `regression_plan.json`,
`regression_run.json`, `regression/out/MANIFEST.json`, `audit_4big/out/quality_report.json`.
**Prose gatée réalignée** : README module (`17 tests`), fiches `03_agents/{faisabilite,qa,erpnext_backend}`.
`run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** · **0 gate ajouté** (#5) · **aucune commande VPS** (#8).
---
## Currency canal stakeholder — `3710253` → HEAD `04f4c21` (+ session `141554`)
Depuis le jalon *brief.schema* ci-dessus, **six sessions lecture-seule** ont ajouté chacune un **axe
de vérification objectif encore jamais balayé** — toutes **CLEAN, 0 édition de production, 0 gate
ajouté** (#5). La **structure du gate de merge reste inchangée** : `run_ci.sh` = **33 PASS · 0 FAIL ·
0 SKIP** (8 gates statiques + 25 suites) à chaque commit. Aucune n'est opposable au merge — seul le
journal `05_activity_log/` est touché — sauf **un durcissement de test** (session `124544`).
| Commit (session) | Axe NEUF vérifié | Résultat |
|---|---|---|
| `27cfe2f` (`111534`) | Intégrité référentielle interne des `$ref` des 26 oracles-schémas | CLEAN 108/108 refs |
| `6c05538` (`114542`) | Le skip `python -S` de l'oracle jsonschema masque-t-il un écart enum/const ? | CLEAN (1 phantom `{WAG}` = by-design) |
| `4aea5bd` (`121542`) | Cohérence interne des 26 oracles (required-vacuité + auto-contradiction const/enum/default) | CLEAN 26/26 (1405 nœuds) |
| `bea5d49` (`124544`) | Atteignabilité transitive d'une assertion (aucun test run-only faux-vert) | CLEAN 0/651 **+ 1 durcissement** (implicite→explicite) |
| `1839f52` (`131551`) | Cohérence draft/keyword des 26 oracles-schémas (`$schema` vs idiomes cross-draft) | CLEAN 26/26 (tous draft-07) |
| `04f4c21` (`134554`) | L'artefact **commité sur disque** conforme à son schéma (≠ objet en-mémoire) | CLEAN 57/57 |
**Session courante `141554` — axe NEUF « accord numérique INTER-artefacts »** (`out/*.json``out/*.json`,
distinct de l'intra-artefact et du code/prose↔artefact). Les concepts-singletons plateforme s'accordent
tous cross-fichier (`cible_rbac_roles`=50, `ci_modules_count`/`modules`/`suites`=24, `portails`=5…). Seul
nom **surchargé** divergent = `roles_couverts` **50** (tous les role-profiles) vs **44** (rôles des 5
portails business = 50 6 `plateforme`) — **by-design, les deux re-dérivés de `rbac_50_roles.json`**.
**CLEAN · 0 édition de production · 0 gate** (#5) · `run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP**.
@@ -149,7 +149,7 @@ DOIT être daté et sourcé (jamais inventé — contrainte #6).
| 4.10 | Devises | 🔴 | **USD + DOP** (contrainte #10) | | 4.10 | Devises | 🔴 | **USD + DOP** (contrainte #10) |
| 4.11 | Moyen de paiement | 🔴 | **Cardnet** (❌ Stripe · contrainte #10) | | 4.11 | Moyen de paiement | 🔴 | **Cardnet** (❌ Stripe · contrainte #10) |
| 4.12 | Format documents | 🔴 | **Letter US** (contrainte #10) | | 4.12 | Format documents | 🔴 | **Letter US** (contrainte #10) |
| 4.13 | Régime fiscal | 🟡 | CONFOTUR · Fideicomiso (voir volet juridique) | `{{regime_fiscal}}` | | 4.13 | Régime fiscal | 🟡 | CONFOTUR · Fideicomiso (voir volet juridique) · `{{regime_fiscal}}` |
### 5.3 Cohérence commercial.md (verrou anti-gap) ### 5.3 Cohérence commercial.md (verrou anti-gap)
@@ -93,8 +93,9 @@ Voir [`brief.schema.json`](./brief.schema.json). Les fixtures sont **synthétiqu
python3 -m unittest discover -s tests -v python3 -m unittest discover -s tests -v
``` ```
16 tests `unittest` (stdlib pur, **zéro pip**) : scoring, rétrogradation, 17 tests `unittest` (stdlib pur, **zéro pip**) : scoring, rétrogradation,
paramètres canoniques, et **round-trip end-to-end** generator → parser Publiciste paramètres canoniques, conformité des fixtures au **contrat d'entrée**
(`brief.schema.json`), et **round-trip end-to-end** generator → parser Publiciste
`projets_master.json` validé contre le schéma. Réutilise le parser + le `projets_master.json` validé contre le schéma. Réutilise le parser + le
validateur du Publiciste (aucune duplication · workflow #5). Un oracle validateur du Publiciste (aucune duplication · workflow #5). Un oracle
`jsonschema` est activé en plus s'il est installé. `jsonschema` est activé en plus s'il est installé.
@@ -272,6 +272,11 @@ def render_version_json(brief: dict, bilan: dict, generated_at: str,
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# Vérification des paramètres canoniques dans le rendu (axe 4, honnêteté). # Vérification des paramètres canoniques dans le rendu (axe 4, honnêteté).
# --------------------------------------------------------------------------- # # --------------------------------------------------------------------------- #
# ORACLE INDÉPENDANT (à dessein) : ces 6 marqueurs sont une copie DÉLIBÉRÉMENT
# distincte de model.CANONICAL — c'est ce qui permet à check_canonical() de
# PROUVER que le rendu (bâti depuis CANONICAL) émet bien chaque valeur. Les
# dériver de CANONICAL rendrait le contrôle tautologique (vert vacux). La liste
# est plutôt ancrée statiquement à CLAUDE.md #9/#10 par ci/check_readme_claims.
_CANONICAL_MARKERS = ["3 %", "8.5 %", "52 %", "USD + DOP", "Cardnet", "Letter US"] _CANONICAL_MARKERS = ["3 %", "8.5 %", "52 %", "USD + DOP", "Cardnet", "Letter US"]
@@ -175,6 +175,20 @@ class RoundTripTest(unittest.TestCase):
errs = pub_validator.validate(version, _schema("version.schema.json")) errs = pub_validator.validate(version, _schema("version.schema.json"))
self.assertEqual(errs, [], f"version.json non conforme : {errs}") self.assertEqual(errs, [], f"version.json non conforme : {errs}")
def test_input_briefs_validate_against_brief_schema(self):
# `brief.schema.json` est le « Contrat d'entrée » documenté (README §Contrat
# d'entrée) : les deux fixtures DOIVENT s'y conformer. Le brief « incomplet »
# l'est au sens SÉMANTIQUE (prix absents → placeholders/rétrogradation), pas au
# sens SCHÉMA (le schéma admet null/champ absent, seul `projet` est requis).
# Sans ce test, le contrat d'entrée resterait un oracle orphelin : `_validate_brief`
# ne garde que le code `projet`, jamais la forme complète du brief.
with open(os.path.join(_GEN, "brief.schema.json"), encoding="utf-8") as fh:
brief_schema = json.load(fh)
_, pub_validator = _pub()
for name in ("brief_complete.json", "brief_incomplete.json"):
errs = pub_validator.validate(_brief(name), brief_schema)
self.assertEqual(errs, [], f"{name} viole brief.schema.json : {errs}")
def test_full_pipeline_master_validates(self): def test_full_pipeline_master_validates(self):
# Génère 2 projets → parcours build_master → projets_master.json conforme. # Génère 2 projets → parcours build_master → projets_master.json conforme.
for name in ("brief_complete.json", "brief_incomplete.json"): for name in ("brief_complete.json", "brief_incomplete.json"):
@@ -276,7 +276,7 @@ def main(argv: list[str] | None = None) -> int:
) )
sub = p.add_subparsers(dest="cmd", required=True) sub = p.add_subparsers(dest="cmd", required=True)
pb = sub.add_parser("build", help="génère app_config.json / eas_build.json / role_navigation.json / MANIFEST.json") pb = sub.add_parser("build", help="génère app_config.json / eas_build.json / role_navigation.json / store_listing.json / MANIFEST.json")
pb.add_argument("-o", "--out", default=_DEFAULT_OUT, help="dossier de sortie (défaut: ./out)") pb.add_argument("-o", "--out", default=_DEFAULT_OUT, help="dossier de sortie (défaut: ./out)")
pb.set_defaults(func=cmd_build) pb.set_defaults(func=cmd_build)
@@ -373,8 +373,11 @@ class TestCLI(unittest.TestCase):
self.assertTrue(os.path.exists(os.path.join(tmp, "MANIFEST.json"))) self.assertTrue(os.path.exists(os.path.join(tmp, "MANIFEST.json")))
def test_validate_exits_zero(self): def test_validate_exits_zero(self):
# cmd_validate ne lève pas sur le dépôt réel (sinon SystemExit). # cmd_validate ne lève pas sur le dépôt réel (sinon SystemExit via
gen.main(["validate"]) # _validate_or_die) ET retourne le code 0. On l'asserte explicitement :
# ainsi le test mord aussi si un refactor remplaçait sys.exit(1) par un
# `return 1` silencieux (le SystemExit ne serait alors plus levé).
self.assertEqual(gen.main(["validate"]), 0)
if __name__ == "__main__": if __name__ == "__main__":
@@ -318,7 +318,7 @@
"criterion": "DOC", "criterion": "DOC",
"weight": 20, "weight": 20,
"passed": true, "passed": true,
"evidence": "README.md (4797 octets)" "evidence": "README.md (4870 octets)"
}, },
{ {
"criterion": "CONTRAT", "criterion": "CONTRAT",
@@ -330,7 +330,7 @@
"criterion": "TESTS", "criterion": "TESTS",
"weight": 25, "weight": 25,
"passed": true, "passed": true,
"evidence": "16 méthodes test_* dans 1 fichier(s) (seuil 8)" "evidence": "17 méthodes test_* dans 1 fichier(s) (seuil 8)"
}, },
{ {
"criterion": "CLI", "criterion": "CLI",
@@ -5,7 +5,7 @@
"version": "1.0", "version": "1.0",
"verdict": "PASS", "verdict": "PASS",
"suites": 24, "suites": 24,
"test_methods": 624, "test_methods": 625,
"coverage_ok": true, "coverage_ok": true,
"artifacts": [ "artifacts": [
"regression_plan.json" "regression_plan.json"
@@ -112,7 +112,7 @@
"in_gate": true, "in_gate": true,
"has_tests_dir": true, "has_tests_dir": true,
"test_files": 1, "test_files": 1,
"test_methods": 16 "test_methods": 17
}, },
{ {
"id": "fiscal.ecf_dgii", "id": "fiscal.ecf_dgii",
@@ -295,7 +295,7 @@
"totals": { "totals": {
"suites": 24, "suites": 24,
"test_files": 24, "test_files": 24,
"test_methods": 624, "test_methods": 625,
"min_methods": 10, "min_methods": 10,
"under_threshold": 0 "under_threshold": 0
}, },
@@ -90,9 +90,9 @@
{ {
"id": "faisabilite.generator", "id": "faisabilite.generator",
"path": "faisabilite/generator", "path": "faisabilite/generator",
"expected_methods": 16, "expected_methods": 17,
"ran": 16, "ran": 17,
"passed": 15, "passed": 16,
"failures": 0, "failures": 0,
"errors": 0, "errors": 0,
"skipped": 1, "skipped": 1,
@@ -296,8 +296,8 @@
"suites": 24, "suites": 24,
"green": 24, "green": 24,
"red": 0, "red": 0,
"ran": 624, "ran": 625,
"passed": 607, "passed": 608,
"failures": 0, "failures": 0,
"errors": 0, "errors": 0,
"skipped": 17 "skipped": 17
+1 -1
View File
@@ -290,7 +290,7 @@ def main(argv: list[str] | None = None) -> int:
p = argparse.ArgumentParser(description="Generateur SEO trilingue (Sprint 6 · SEO).") p = argparse.ArgumentParser(description="Generateur SEO trilingue (Sprint 6 · SEO).")
sub = p.add_subparsers(dest="cmd", required=True) sub = p.add_subparsers(dest="cmd", required=True)
pb = sub.add_parser("build", help="genere seo_keywords/schema_org/hreflang + MANIFEST") pb = sub.add_parser("build", help="genere seo_keywords.json / seo_schema_org.json / seo_hreflang.json / MANIFEST.json")
pb.add_argument("--master", default=None, help="projets_master.json (defaut: fixtures/)") pb.add_argument("--master", default=None, help="projets_master.json (defaut: fixtures/)")
pb.add_argument("-o", "--out", default=_DEFAULT_OUT, help="dossier de sortie (defaut: ./out)") pb.add_argument("-o", "--out", default=_DEFAULT_OUT, help="dossier de sortie (defaut: ./out)")
pb.set_defaults(func=cmd_build) pb.set_defaults(func=cmd_build)
+2 -2
View File
@@ -51,7 +51,7 @@ Transverses : [`devops`](03_agents/devops/AGENT.md) · [`qa`](03_agents/qa/AGENT
- **Recette roadmap** : **15 promesses** (8 livrables sprint + 7 métriques MVP), **15 `in_repo` - **Recette roadmap** : **15 promesses** (8 livrables sprint + 7 métriques MVP), **15 `in_repo`
prouvées** (chacune traçant ses items hors-périmètre worker · #8 · ex. M5 « app publiée 2 stores »), prouvées** (chacune traçant ses items hors-périmètre worker · #8 · ex. M5 « app publiée 2 stores »),
verdict `true` — source [`qa/acceptance/out/acceptance_matrix.json`](05_deliverables_mvp/qa/acceptance/out/acceptance_matrix.json). verdict `true` — source [`qa/acceptance/out/acceptance_matrix.json`](05_deliverables_mvp/qa/acceptance/out/acceptance_matrix.json).
- **Guards** : [`ci/guard_constraints.sh`](ci/README.md) + [`ci/check_docs.sh`](ci/README.md) verts. - **Guards** : [`ci/guard_constraints.sh`](ci/guard_constraints.sh) + [`ci/check_docs.sh`](ci/check_docs.sh) verts.
- **Décisions produit ouvertes** : la CI dépôt verte n'implique pas *zéro décision en attente*. - **Décisions produit ouvertes** : la CI dépôt verte n'implique pas *zéro décision en attente*.
Les arbitrages de **périmètre produit** et les **dépendances runtime hors dépôt** (VPS · #8) qui Les arbitrages de **périmètre produit** et les **dépendances runtime hors dépôt** (VPS · #8) qui
appartiennent à Michel sont consolidés, sourcés `file:line`, dans appartiennent à Michel sont consolidés, sourcés `file:line`, dans
@@ -72,7 +72,7 @@ Les fichiers `DIRECTIVE_*.md` à la racine sont les **input-specs formels et dat
Michel** : des snapshots de gouvernance (au même titre que les `daily_reports`) qui Michel** : des snapshots de gouvernance (au même titre que les `daily_reports`) qui
pilotent les modules. Ce README n'y introduit aucune donnée ; la **spec commitée du pilotent les modules. Ce README n'y introduit aucune donnée ; la **spec commitée du
module reste l'autorité** (`spec = authority`), les chiffres faisant foi via les artefacts module reste l'autorité** (`spec = authority`), les chiffres faisant foi via les artefacts
byte-gatés. Ils sont exclus de [`ci/guard_constraints.sh`](ci/README.md) (prose de byte-gatés. Ils sont exclus de [`ci/guard_constraints.sh`](ci/guard_constraints.sh) (prose de
gouvernance énumérant règles et autorisations, pouvant citer des URLs/chemins interdits gouvernance énumérant règles et autorisations, pouvant citer des URLs/chemins interdits
ailleurs). ailleurs).
+28
View File
@@ -1634,6 +1634,34 @@ contrat » (réservation retiré) · motif du défaut ne cite plus « Cardnet »
vert (exit 0) · working tree **byte-restauré** (`git checkout --`, **JAMAIS** `git clean`) · vert (exit 0) · working tree **byte-restauré** (`git checkout --`, **JAMAIS** `git clean`) ·
**7 gates re-verts**. **7 gates re-verts**.
**COMPLÉTUDE de l'énumération des gates statiques dans la fiche QA.** La fiche
`03_agents/qa/AGENT.md` (§« Deuxième étage QA ») énumère les gates `ci/*.sh` en se
**déclarant explicitement** « l'état courant » de `git ls-files 'ci/*.sh'` (« pas une
constante »). Or **rien** ne vérifiait que CHAQUE gate statique y figure vraiment : le 8ᵉ
gate `check_mobile_workflow.sh` (livré le 2026-08-05) a pu rester **omis un jour entier EN
SILENCE** — la fiche promettait la complétude sans la tenir. On **re-dérive** l'ensemble
depuis `git ls-files 'ci/*.sh'` (hors `lib.sh`, #6 — jamais une liste à la main) et on
exige que chaque basename apparaisse (backtické) dans la fiche ; un gate **absent** échoue.
Distinct de `check_ci_integrity` qui verrouille le **câblage CI** (chaque `ci/*.sh` ↔ un
job `gate.needs`) mais **ignore la fiche** ; cette surface ferme le miroir *documentaire* du
même ensemble. **2 morsures vérifiées** : retrait de la ligne `check_mobile_workflow.sh` de
la fiche → mismatch (gate réel non cité) · ajout d'un 9ᵉ `ci/*.sh` tracké non encore
documenté → mismatch (**forward-protection** : le prochain gate ne pourra pas être omis) ;
restauré = vert.
**COMPLÉTUDE de l'énumération dans la TABLE §1 de ce README.** La table §1 « Ce que
fait le pipeline » (ci-dessus) est LA doc canonique des jobs statiques — une ligne par
gate `ci/*.sh`. Sa complétude était le **jumeau ungaté** de la fiche QA : `check_ci_integrity`
verrouille le câblage CI, le bloc précédent énumère côté fiche, mais **rien** n'exigeait que
chaque gate figure dans la table §1. Un 9ᵉ gate y serait omis EN SILENCE (prouvé ungate :
retrait de la ligne de table de `check_mobile_workflow` → 8 gates statiques verts). On
réutilise l'ensemble re-dérivé de `git ls-files 'ci/*.sh'` (hors `lib.sh`, #6) et on exige
que chaque basename soit cité dans une **ligne de TABLE** (`|`…) de la section §1 — **pas** la
prose §1 (qui ne cite que certains gates pour l'explication `mobile-build.yml`, ce qui
rendrait un contrôle whole-section édenté sur un retrait de ligne de table). **2 morsures
vérifiées** : retrait de la ligne de table `check_mobile_workflow.sh` → mismatch nommant le
gate · ajout d'un 9ᵉ `ci/*.sh` tracké → mismatch (**forward-protection**) ; restauré = vert.
Un claim **absent** échoue aussi (la dérive de formulation qui ferait Un claim **absent** échoue aussi (la dérive de formulation qui ferait
disparaître un chiffre est elle-même une régression de traçabilité). stdlib pur disparaître un chiffre est elle-même une régression de traçabilité). stdlib pur
(bash/git/python3), zéro réseau. (bash/git/python3), zéro réseau.
+69
View File
@@ -9163,6 +9163,75 @@ if _rm_lines is not None:
good(f"Traçabilité roadmap · {len(_rm_seen)} citation(s) ancrée(s), " good(f"Traçabilité roadmap · {len(_rm_seen)} citation(s) ancrée(s), "
f"4 modules attendus présents") f"4 modules attendus présents")
# ── Complétude de l'énumération des gates statiques dans la fiche QA ─────────
# La fiche 03_agents/qa/AGENT.md §« Deuxième étage QA » énumère les gates
# `ci/*.sh` en se DÉCLARANT « l'état courant » de `git ls-files 'ci/*.sh'` (pas
# une constante). Or rien ne vérifiait que CHAQUE gate statique y figure : le 8ᵉ
# gate `check_mobile_workflow.sh` a pu être omis un jour entier EN SILENCE. On
# re-dérive l'ensemble depuis git (#6 — jamais une liste à la main) et on exige
# que chaque basename apparaisse dans la fiche ; un gate absent échoue.
_QA_FICHE = "03_agents/qa/AGENT.md"
_gate_names = sorted(
f.rsplit("/", 1)[-1]
for f in subprocess.run(["git", "ls-files", "ci/*.sh"],
capture_output=True, text=True).stdout.split()
if f.rsplit("/", 1)[-1] != "lib.sh")
try:
_qa = open(_QA_FICHE, encoding="utf-8").read()
except OSError as e:
bad(f"Énumération gates statiques · {_QA_FICHE} illisible : {e}")
_qa = None
if _qa is not None:
_missing = [n for n in _gate_names if f"`{n}`" not in _qa]
if _missing:
bad(f"Énumération gates statiques · {_QA_FICHE} n'énumère PAS {_missing} "
f"— la fiche se déclare « l'état courant » de git ls-files 'ci/*.sh' "
f"({len(_gate_names)} gates réels hors lib.sh) → ajouter la/les "
f"ligne(s) manquante(s)")
else:
good(f"Énumération gates statiques · les {len(_gate_names)} gates ci/*.sh "
f"(hors lib.sh) sont tous cités dans {_QA_FICHE}")
# ── Complétude de l'énumération des gates dans la TABLE §1 de ci/README ──────
# ci/README.md §1 « Ce que fait le pipeline » porte LA table canonique des jobs
# statiques (une ligne par gate `ci/*.sh`). C'est la doc de référence du pipeline,
# mais sa complétude était ungatée : `check_ci_integrity` verrouille le CÂBLAGE
# CI (ci/*.sh ↔ gate.needs), le bloc ci-dessus énumère côté fiche QA, mais RIEN
# n'exigeait que chaque gate figure dans la table §1. Un 9ᵉ gate y serait omis EN
# SILENCE (prouvé ungate par mutation : retrait de la ligne §1 de
# `check_mobile_workflow` → 8 gates statiques verts). On réutilise `_gate_names`
# (re-dérivé de git · #6) et on exige que chaque basename soit cité dans une LIGNE
# DE TABLE (`|`…) de la section §1 — PAS la prose §1, qui ne cite que certains
# gates pour d'autres raisons (explication `mobile-build.yml`). Un gate absent de
# la table échoue.
_CI_README = "ci/README.md"
try:
_cir_lines = open(_CI_README, encoding="utf-8").read().splitlines()
except OSError as e:
bad(f"Énumération gates statiques · {_CI_README} illisible : {e}")
_cir_lines = None
if _cir_lines is not None:
_in_s1 = False
_s1_rows = []
for _ln in _cir_lines:
if _ln.startswith("## 1."):
_in_s1 = True
continue
if _in_s1 and _ln.startswith("## "):
break
if _in_s1 and _ln.lstrip().startswith("|"):
_s1_rows.append(_ln)
_s1_tbl = "\n".join(_s1_rows)
_miss_s1 = [n for n in _gate_names if f"ci/{n}" not in _s1_tbl]
if _miss_s1:
bad(f"Énumération gates statiques · la table §1 de {_CI_README} n'énumère "
f"PAS {_miss_s1} — « Ce que fait le pipeline » doit lister les "
f"{len(_gate_names)} gates ci/*.sh (hors lib.sh, re-dérivés de git) → "
f"ajouter la/les ligne(s) de table manquante(s)")
else:
good(f"Énumération gates statiques · les {len(_gate_names)} gates ci/*.sh "
f"sont tous cités dans la table §1 de {_CI_README}")
sys.exit(1 if FAIL else 0) sys.exit(1 if FAIL else 0)
PY PY
rc=$? rc=$?
+4 -1
View File
@@ -6,6 +6,10 @@
# Les schémas JSON (version.schema.json, projets_master.schema.json) sont le # Les schémas JSON (version.schema.json, projets_master.schema.json) sont le
# contrat de données Faisabilité ↔ Publiciste : un JSON cassé bloque le # contrat de données Faisabilité ↔ Publiciste : un JSON cassé bloque le
# pipeline en aval → on l'attrape ici. # pipeline en aval → on l'attrape ici.
# PÉRIMÈTRE : bonne-formation SEULEMENT (parse). La conformité au $schema
# (validation structurelle contre le .schema.json) n'est PAS contrôlée ici —
# c'est l'oracle tiers OPTIONNEL `jsonschema` de la suite régression (cf.
# check_regression.sh, 17 skips par design quand la lib est absente).
# Dépendances : bash, git, python3. Aucun réseau requis. # Dépendances : bash, git, python3. Aucun réseau requis.
# ============================================================================ # ============================================================================
set -uo pipefail set -uo pipefail
@@ -24,7 +28,6 @@ fi
for f in "${files[@]}"; do for f in "${files[@]}"; do
if python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$f" 2>/tmp/jsonerr; then if python3 -c "import json,sys; json.load(open(sys.argv[1]))" "$f" 2>/tmp/jsonerr; then
printf ' \033[32m✓\033[0m %s\n' "$f" printf ' \033[32m✓\033[0m %s\n' "$f"
# Si un $schema est déclaré, contrôle que 'draft' est reconnu (info seule).
else else
printf ' \033[31m✗\033[0m %s\n' "$f" printf ' \033[31m✗\033[0m %s\n' "$f"
sed 's/^/ /' /tmp/jsonerr sed 's/^/ /' /tmp/jsonerr