Compare commits
55 Commits
1a44dfe1c0
...
5ab362153c
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ab362153c | |||
| 52e8e81799 | |||
| b88b7051e0 | |||
| 27c2bd29ff | |||
| 11f158a9d2 | |||
| 55ff296ac8 | |||
| 40b023c2eb | |||
| 558225a74d | |||
| be36d6600f | |||
| 0393ea7b48 | |||
| 2ded65bbb4 | |||
| d074250084 | |||
| 27d1117a2d | |||
| fdb0632cf6 | |||
| caeb06be5f | |||
| 5d5e986fa6 | |||
| 04f4c21778 | |||
| 1839f521aa | |||
| bea5d49aab | |||
| 4aea5bddf7 | |||
| 6c05538efb | |||
| 27cfe2fe59 | |||
| 3710253c02 | |||
| d9668d6079 | |||
| e87f5f56af | |||
| 44712cbdfa | |||
| 9acd8441dc | |||
| 42d54b045f | |||
| def4706de3 | |||
| 4c741a7118 | |||
| ddcafc58c0 | |||
| e4b3488c7e | |||
| e786c128b2 | |||
| a678534b8b | |||
| 12ec9d0711 | |||
| 4bc98198b1 | |||
| b2749587c0 | |||
| 48276ee916 | |||
| 243523c6c2 | |||
| 354a68788d | |||
| b60d471030 | |||
| 34c8cd2e17 | |||
| a8342e97e2 | |||
| fe61207ca6 | |||
| c196e4183e | |||
| 21f55a9ed7 | |||
| 8903a4b774 | |||
| d6a8d73aec | |||
| d4f9289586 | |||
| cb3de786f8 | |||
| 9c7791f23a | |||
| 27c7d20449 | |||
| afa61657cb | |||
| c14305c170 | |||
| 1b99917f21 |
@@ -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**
|
||||
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
|
||||
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).
|
||||
|
||||
## Hand-off reçus (à appliquer sur le VPS, dans l'ordre)
|
||||
|
||||
@@ -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 |
|
||||
|---|---|---|---|---|---|
|
||||
| [`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 |
|
||||
|
||||
**Anti-invention (#6)** : `generator` et `bancable` ne **fabriquent aucun chiffre** — les figures
|
||||
|
||||
@@ -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** ·
|
||||
**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)
|
||||
La matière première est le **contrat RBAC** `05_deliverables_mvp/rbac/rbac_50_roles.json`,
|
||||
**jamais la spec de mise en page** :
|
||||
|
||||
@@ -32,7 +32,7 @@ périmètre — un auditeur ne s'audite jamais.
|
||||
**conformité** normative des hand-off.
|
||||
|
||||
## 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`,
|
||||
réutilisé sans duplication) — jamais compté à la main.
|
||||
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é) |
|
||||
|---|---|
|
||||
| `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_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). |
|
||||
|
||||
@@ -1,5 +1,168 @@
|
||||
# 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**
|
||||
|
||||
**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.
|
||||
|
||||
**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
@@ -71,7 +71,7 @@ et la cible plancher **4-5 semaines**.
|
||||
- ✅ 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.
|
||||
- **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).
|
||||
|
||||
### 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"]),
|
||||
"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 {
|
||||
|
||||
@@ -17,14 +17,6 @@
|
||||
"workflow_suivi_etapes": 6
|
||||
},
|
||||
"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",
|
||||
"erpnext_role_name": "OTO Compta Trésorier"
|
||||
@@ -32,6 +24,10 @@
|
||||
{
|
||||
"role_id": "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**,
|
||||
**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.
|
||||
|
||||
---
|
||||
|
||||
## 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.11 | Moyen de paiement | 🔴 | **Cardnet** (❌ Stripe · 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)
|
||||
|
||||
|
||||
@@ -93,8 +93,9 @@ Voir [`brief.schema.json`](./brief.schema.json). Les fixtures sont **synthétiqu
|
||||
python3 -m unittest discover -s tests -v
|
||||
```
|
||||
|
||||
16 tests `unittest` (stdlib pur, **zéro pip**) : scoring, rétrogradation,
|
||||
paramètres canoniques, et **round-trip end-to-end** generator → parser Publiciste
|
||||
17 tests `unittest` (stdlib pur, **zéro pip**) : scoring, rétrogradation,
|
||||
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
|
||||
validateur du Publiciste (aucune duplication · workflow #5). Un oracle
|
||||
`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é).
|
||||
# --------------------------------------------------------------------------- #
|
||||
# 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"]
|
||||
|
||||
|
||||
|
||||
@@ -175,6 +175,20 @@ class RoundTripTest(unittest.TestCase):
|
||||
errs = pub_validator.validate(version, _schema("version.schema.json"))
|
||||
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):
|
||||
# Génère 2 projets → parcours build_master → projets_master.json conforme.
|
||||
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)
|
||||
|
||||
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.set_defaults(func=cmd_build)
|
||||
|
||||
|
||||
@@ -373,8 +373,11 @@ class TestCLI(unittest.TestCase):
|
||||
self.assertTrue(os.path.exists(os.path.join(tmp, "MANIFEST.json")))
|
||||
|
||||
def test_validate_exits_zero(self):
|
||||
# cmd_validate ne lève pas sur le dépôt réel (sinon SystemExit).
|
||||
gen.main(["validate"])
|
||||
# cmd_validate ne lève pas sur le dépôt réel (sinon SystemExit via
|
||||
# _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__":
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
"criterion": "DOC",
|
||||
"weight": 20,
|
||||
"passed": true,
|
||||
"evidence": "README.md (4797 octets)"
|
||||
"evidence": "README.md (4870 octets)"
|
||||
},
|
||||
{
|
||||
"criterion": "CONTRAT",
|
||||
@@ -330,7 +330,7 @@
|
||||
"criterion": "TESTS",
|
||||
"weight": 25,
|
||||
"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",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"version": "1.0",
|
||||
"verdict": "PASS",
|
||||
"suites": 24,
|
||||
"test_methods": 624,
|
||||
"test_methods": 625,
|
||||
"coverage_ok": true,
|
||||
"artifacts": [
|
||||
"regression_plan.json"
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
"in_gate": true,
|
||||
"has_tests_dir": true,
|
||||
"test_files": 1,
|
||||
"test_methods": 16
|
||||
"test_methods": 17
|
||||
},
|
||||
{
|
||||
"id": "fiscal.ecf_dgii",
|
||||
@@ -295,7 +295,7 @@
|
||||
"totals": {
|
||||
"suites": 24,
|
||||
"test_files": 24,
|
||||
"test_methods": 624,
|
||||
"test_methods": 625,
|
||||
"min_methods": 10,
|
||||
"under_threshold": 0
|
||||
},
|
||||
|
||||
@@ -90,9 +90,9 @@
|
||||
{
|
||||
"id": "faisabilite.generator",
|
||||
"path": "faisabilite/generator",
|
||||
"expected_methods": 16,
|
||||
"ran": 16,
|
||||
"passed": 15,
|
||||
"expected_methods": 17,
|
||||
"ran": 17,
|
||||
"passed": 16,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 1,
|
||||
@@ -296,8 +296,8 @@
|
||||
"suites": 24,
|
||||
"green": 24,
|
||||
"red": 0,
|
||||
"ran": 624,
|
||||
"passed": 607,
|
||||
"ran": 625,
|
||||
"passed": 608,
|
||||
"failures": 0,
|
||||
"errors": 0,
|
||||
"skipped": 17
|
||||
|
||||
@@ -290,7 +290,7 @@ def main(argv: list[str] | None = None) -> int:
|
||||
p = argparse.ArgumentParser(description="Generateur SEO trilingue (Sprint 6 · SEO).")
|
||||
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("-o", "--out", default=_DEFAULT_OUT, help="dossier de sortie (defaut: ./out)")
|
||||
pb.set_defaults(func=cmd_build)
|
||||
|
||||
@@ -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`
|
||||
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).
|
||||
- **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*.
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
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
|
||||
ailleurs).
|
||||
|
||||
|
||||
@@ -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`) ·
|
||||
**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
|
||||
disparaître un chiffre est elle-même une régression de traçabilité). stdlib pur
|
||||
(bash/git/python3), zéro réseau.
|
||||
|
||||
@@ -9163,6 +9163,75 @@ if _rm_lines is not None:
|
||||
good(f"Traçabilité roadmap · {len(_rm_seen)} citation(s) ancrée(s), "
|
||||
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)
|
||||
PY
|
||||
rc=$?
|
||||
|
||||
+4
-1
@@ -6,6 +6,10 @@
|
||||
# Les schémas JSON (version.schema.json, projets_master.schema.json) sont le
|
||||
# contrat de données Faisabilité ↔ Publiciste : un JSON cassé bloque le
|
||||
# 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.
|
||||
# ============================================================================
|
||||
set -uo pipefail
|
||||
@@ -24,7 +28,6 @@ fi
|
||||
for f in "${files[@]}"; do
|
||||
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"
|
||||
# Si un $schema est déclaré, contrôle que 'draft' est reconnu (info seule).
|
||||
else
|
||||
printf ' \033[31m✗\033[0m %s\n' "$f"
|
||||
sed 's/^/ /' /tmp/jsonerr
|
||||
|
||||
Reference in New Issue
Block a user