def4706de3
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
671 lines
51 KiB
Markdown
671 lines
51 KiB
Markdown
# Activity Log · 2026-08-06 · Claude Code DTP Worker
|
||
|
||
## Session `20260806_054454` — FIX doc · lien Markdown label↔cible incohérent (label = chemin de fichier, href pointant ailleurs) → 3 corrigés
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée/gatée. Les **6+ derniers commits** sont des sweeps vérification-only
|
||
(`0 édition`) — rendement décroissant, du churn. Objectif : trouver un **défaut réel actionnable**
|
||
sur un axe **non couvert** par la mémoire, sinon améliorer une doc (fallback).
|
||
|
||
**Axe éliminé (CLEAN, non re-flaggé).** Chasse aux **chemins-fantômes dans les code-spans backtick**
|
||
(classe `backtick-path-escapes-check-docs` — les backticks neutralisent le link-check). Résolution
|
||
contre racine dépôt **+ racine deliverables + sous-arbres modules**, en excluant les snapshots
|
||
historiques (`05_activity_log/`, `daily_reports/`), les globs `*/AGENT.md` et les chemins
|
||
runtime/VPS (`otoia/`, `out/`, `vente.otov7.com`). Les 2 candidats survivants
|
||
(`crm/commissions/README.md` `banclib/finance.py` · `onapi_legal/AGENT.md` `cflib/*.py`) sont des
|
||
**faux positifs** : le premier est un **label** de lien dont la vraie cible
|
||
`../../faisabilite/bancable/banclib/finance.py` **existe** ; le second résout sous
|
||
`legal/confotur/cflib/`. → dimension **CLEAN**, mémoire confirmée.
|
||
|
||
**Axe NEUF (absent de la mémoire) → défaut réel.** Liens Markdown de la forme `[`label`](cible)`
|
||
où le **label** (code-span) est un **chemin de fichier existant** mais dont le **basename diffère**
|
||
de celui de la **cible** href. `check_docs` prouve que la cible **résout**, **jamais** que le label
|
||
la **désigne** : un lecteur qui Cmd-clique `ci/guard_constraints.sh` atterrit sur `ci/README.md`
|
||
(mauvais fichier). Balayage `git ls-files '*.md'` → **3 occurrences**, toutes dans `README.md` :
|
||
- L54 `[`ci/guard_constraints.sh`](ci/README.md)` et `[`ci/check_docs.sh`](ci/README.md)`
|
||
- L75 `[`ci/guard_constraints.sh`](ci/README.md)`
|
||
|
||
Les scripts nommés **existent et sont git-trackés** (ce sont des gates) ⇒ **FIX** = pointer chaque
|
||
label vers le fichier qu'il **nomme** (`ci/guard_constraints.sh` / `ci/check_docs.sh`). Résultat :
|
||
label == cible, navigation véridique, `check_docs` toujours vert (les cibles existent).
|
||
|
||
**Vérif.** Cibles existent ✓ · re-balayage mismatch → **0** · `ci/check_docs.sh` **PASS** ·
|
||
`./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP**.
|
||
|
||
**Portée / anti-churn.** Édité : `README.md` (3 href) + ce journal. **0 artefact reconstruit**,
|
||
**0 gate ajouté** (#5 — origine isolée, pas une classe récurrente, cf. `confotur 8-négatifs`),
|
||
**0 chiffre inventé** (#6), **0 VPS** (#8). Structure du gate inchangée (33 checks).
|
||
|
||
## Session `20260806_051453` — VÉRIF indépendante · NOUVELLE famille objective « portabilité runtime / intégrité d'encodage » (3 axes neufs) → CLEAN · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée (Sprints 1→7 côté
|
||
repo ; le reste — déploiement prod, builds EAS, dépôts ONAPI — est **hors périmètre worker**,
|
||
VPS `153.75.250.214` · `CLAUDE.md` #8). Les 3 derniers commits sont vérification/currency-only
|
||
(`12ec9d0` MANIFEST+dup-keys, `4bc9819` slugs, `b274958` currency). **Le canal stakeholder est
|
||
déjà courant** : la dernière **prod** est `48276ee` (FIX financement), attesté par le rapport
|
||
`daily_reports/2026-08-06.md` §034434 ; les 3 commits suivants sont non-opposables (0 édition
|
||
de prod). Re-porter la currency ou refaire un sweep déjà couvert serait du churn.
|
||
|
||
**Pré-vérif — aucun travail incomplet.** Grep `TODO|FIXME|XXX|stub|NotImplemented|à compléter`
|
||
sur tout `.py` de prod (hors `tests/`) → **0** marqueur réel ; tous les hits « placeholder »
|
||
sont le pattern #6 zéro-invention **intentionnel** (`{{…}}` documenté). Le code de prod est
|
||
complet. Le registre `OPEN_DECISIONS_REGISTER.md` (D-01→D-05) reste des **arbitrages produit**
|
||
Michel / dépendances hors dépôt, non-actionnables worker (ne pas re-surfacer, #5).
|
||
|
||
**Axes ungatés cartographiés avant de chasser.** `check_docs` gate **tous** les liens md relatifs
|
||
(`git ls-files '*.md'`, code-spans neutralisés, ancres strippées) → liens couverts ; l'unique
|
||
ancre intra-doc (`README.md:20` → `## Directives Michel (input-specs datés)`) **résout** — 1 seule
|
||
occurrence, pas de gate (#5). Reste **non couvert par aucun gate** : l'intégrité **d'octets**
|
||
des fichiers texte (encodage, BOM, fins de ligne) et la **compilabilité** des `.py` non testés.
|
||
Le CI se soucie déjà de l'encodage runtime (`PYTHONUTF8=1`, cf. en-tête `ci.yml`) mais ne
|
||
**vérifie** rien côté fichiers commités. D'où cette famille neuve, absente de la mémoire
|
||
(hash-seed / locale-TZ / forward-compat testent le *rebuild*, pas les *octets sources*).
|
||
|
||
**Axe 1 — intégrité d'encodage des fichiers texte commités.** Parse binaire des **379** fichiers
|
||
texte commités (`.json/.md/.py/.sh/.yml/.yaml/.txt/.cfg/.toml`) :
|
||
- **BOM UTF-8** (`\xef\xbb\xbf` en tête, casse `json.load` strict / rend `""+clé`) → **0**.
|
||
- **UTF-8 invalide** (`bytes.decode('utf-8')` lève) → **0**.
|
||
- **Caractères de contrôle parasites** (`< 0x20` hors `\t\n\r`, + `U+2028/2029`, + surrogates
|
||
`D800–DFFF`) → **0**.
|
||
- **JSON non-parseable** (`json.loads` sur les **114** `.json`) → **0**.
|
||
|
||
**Axe 2 — fins de ligne (portabilité cross-plateforme).** Un `CR` dans un fichier commité
|
||
introduit une dérive d'octets invisible (diff byte / `check_artifacts` d'un runner à `autocrlf`).
|
||
Balayage `\r` sur tous les fichiers texte → **0 CRLF** (LF pur partout).
|
||
|
||
**Axe 3 — compilabilité de tout `.py` commité (dents réelles).** `python3 -m py_compile` sur les
|
||
**144** `.py` versionnés. Contrairement aux 25 suites unittest (qui n'importent que les modules
|
||
qu'elles exercent) et à forward-compat (`-W error` sur les suites), ceci prouve que **chaque**
|
||
fichier — y compris un helper `*lib/` jamais importé par un test — est syntaxiquement sain : une
|
||
erreur de syntaxe latente dans un chemin non couvert passerait **verte** aujourd'hui. → **0 erreur**.
|
||
|
||
**Verdict.** Repo **CLEAN** sur les 3 axes de la famille « portabilité runtime / intégrité
|
||
d'encodage ». **Aucun défaut de production.** Ces axes sont **réellement gardés par aucun gate**
|
||
(teeth réelles : un BOM, un octet non-UTF-8, un CRLF ou une syntaxe cassée serait détecté ici et
|
||
nulle part ailleurs), mais l'occurrence-zéro observée ne justifie **pas** un gate permanent (#5) :
|
||
consigné comme sweep **rejouable** (mémoire `runtime-encoding-integrity-sweep`), pas comme job CI.
|
||
|
||
**Portée / anti-churn.** **Production éditée : néant.** Seul ce journal touché. **0 artefact
|
||
reconstruit**, **0 gate ajouté** (#5), **0 chiffre inventé** (#6 — 379/114/144 tous recomputés
|
||
par balayage), **0 commande VPS** (#8). Structure du gate **inchangée** : `run_ci.sh` = 33 PASS
|
||
= 8 statiques + 25 suites, aucun jalon n'ajoute de job.
|
||
|
||
## Session `20260806_044449` — VÉRIF indépendante · NOUVEL axe objectif « re-dérivation des champs-compte MANIFEST depuis le payload réel » + clés JSON dupliquées → CLEAN · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée. Les 3 derniers
|
||
commits sont vérification-only (`4bc9819` intégrité slugs, `b274958` currency, `243523c` multi-axes).
|
||
Pour éviter le churn, **chasse à un vrai défaut ungaté sur deux axes objectifs réellement neufs**,
|
||
non couverts par les sweeps passés (mémoire : hash-seed, locale/TZ, forward-compat, intégrité
|
||
référentielle rôle/portail = *résolution de slugs*, bijection inverse, docstring↔code, liens md).
|
||
|
||
**Axe 1 — clés JSON dupliquées (classe neuve).** `json.load` garde silencieusement la **dernière**
|
||
valeur sur clé dupliquée ; la byte-repro est **aveugle** à ce défaut sémantique. Parse strict des
|
||
**114** fichiers JSON commités avec `object_pairs_hook` levant sur doublon → **0 clé dupliquée**,
|
||
0 erreur de parse. CLEAN.
|
||
|
||
**Axe 2 — re-dérivation des champs-compte MANIFEST depuis le payload réel (classe neuve).**
|
||
Distincte de « artifact internal set-semantics » (un dup ponctuel, 48276ee) et de « intégrité
|
||
référentielle slugs » (4bc9819, qui teste la *résolution* de chaque slug, **pas** la
|
||
*re-dérivation* d'un compte). Ici : chaque `nb_*`/`_total` d'un MANIFEST recomputé depuis la
|
||
liste réelle du **fichier-payload voisin**. Un bug générateur (comme le dup financement) serait
|
||
silencieux à la byte-repro mais tomberait ici. Résultats :
|
||
- **frontend/portails** — `nb_liens`/`nb_cartes`/`nb_roles` par workspace (5×3) + agrégats
|
||
(`liens_total`=53, `raccourcis_total`=20) recomputés de `workspace.json` → **0 écart**.
|
||
⚠️ Faux positif initial écarté : `nb_liens` ≠ `len(links)` car le tableau ERPNext `links`
|
||
mélange lignes `type=='Card Break'` (= cartes) **et** `type=='Link'` (= vrais liens) ;
|
||
`nb_liens`=Σ(type==Link), `nb_cartes`=Σ(type==Card Break) — **par design**, écart initial
|
||
(15−4=11…) = exactement le nb de cartes ; confirmé sur le champ `type`. `link_count` de
|
||
chaque Card Break = nb de Links sous la carte.
|
||
- **frontend/chat_otoia** — `nb_roles`/`nb_knowledge_doctypes` (5×2) vs `chat_mount.json`
|
||
(`roles_allowed`/`knowledge_scope`) → **0 écart**.
|
||
- **mobile/app_config** — `nb_roles` (5) vs `role_navigation.json` (`roles_allowed`) → **0 écart**.
|
||
- **rbac/roleprofile_gen** — `nb_roles` (6, dont Plateforme=6) vs `role_profile.json`
|
||
(`roles`, matché par `role_profile`) → **0 écart**.
|
||
- **qa/audit_5d** — `controls_total`=17 vs Σ(`dimensions[].controls_total`)=4+3+3+4+3 → **0 écart**
|
||
(les dimensions ne portent pas de liste de contrôles ; le sous-compte est l'autorité, gaté par
|
||
la suite du module).
|
||
|
||
**Verdict.** Repo **CLEAN** sur les deux axes neufs. **Aucun défaut de production.** Le seul
|
||
« mismatch » apparent (nb_liens) était une convention ERPNext Card-Break/Link que mon `len()`
|
||
naïf lisait mal — re-dérivé correctement = concordance totale.
|
||
|
||
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**,
|
||
**0 gate ajouté** (#5 — ces re-dérivations sont couvertes en substance par les suites de module ;
|
||
je ne fige pas un énième gate pour un axe qui sort CLEAN), **0 chiffre saisi à la main** (#6 —
|
||
tout recomputé depuis les payloads et `run_ci.sh`), **aucune commande VPS** (#8). Seule édition :
|
||
ce journal `05_activity_log/`.
|
||
|
||
---
|
||
|
||
## Session `20260806_041444` — VÉRIF indépendante · NOUVEL axe objectif « intégrité référentielle des slugs de rôles & portails inter-artefacts » → CLEAN · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée (8 gates statiques
|
||
+ 25 suites, 24 modules dans ≥1 fiche). Les commits récents (`48276ee` dup `roles_rbac_utilises`,
|
||
`b274958` currency) ayant épuisé les axes docstring↔code / numériques / currency, et l'anti-churn
|
||
proscrivant une énième couche de currency pour des commits sans changement d'état, j'ai chassé un
|
||
**vrai défaut ungaté sur un axe OBJECTIF encore jamais balayé** : la cohérence référentielle des
|
||
identifiants de rôle et de portail cités à travers **tous** les artefacts `out/*.json` vs
|
||
l'ensemble canonique `rbac/rbac_50_roles.json` (même famille que le fix `48276ee`, mais côté
|
||
*existence des slugs* et non *unicité*).
|
||
|
||
**Axe 0 — sanity docstring↔code (modules non couverts au dernier sweep).** `Explore` sceptique sur
|
||
commissions/dossier_vente/acceptance/audit_5d/regression/deploy_runbook/ecf/portails/faisabilite/
|
||
publiciste/rbac(apply,userperm,roleprofile) : **CLEAN**. Seul « défaut » remonté = le
|
||
`validate [-o OUT]` de deploy_runbook, **non-défaut connu** (bijection compat docstring↔argparse
|
||
self-consistante — mémoire `docstring-vs-code-drift`), écarté.
|
||
|
||
**Axe 1 — rôles.** Extraction de **980** valeurs-feuilles sous toute clé matchant `/role/i` dans
|
||
les **~50 artefacts** `05_deliverables_mvp/**/out/*.json`, filtrées aux tokens slug-like kebab
|
||
(le format des 50 ids canoniques, ex. `ventes-conseiller`). **0** slug non résolu vs les 50 ids.
|
||
→ intégrité totale des références de rôle.
|
||
|
||
**Axe 2 — portails.** **66** valeurs-feuilles sous toute clé matchant `/portail|portal/i`. Les 6
|
||
tokens hors `portails_business` (5) sont tous des **non-défauts vérifiés** :
|
||
- `sell·project·buying·accounting·organization` = valeurs du sous-champ **`icon`** des objets
|
||
portail de `mobile/app_config` (noms d'icônes ERPNext, pas le champ `portail` — lequel ne porte
|
||
que les 5 métier canoniques) ;
|
||
- `plateforme` = le **6ᵉ portail technique légitime** (`roleprofile_gen` reporte `portails_metier`
|
||
=5 / `portails_techniques`=1). `rbac_50_roles.json` distribue bien les 50 rôles sur **6** portails
|
||
(`ventes`12·`construction`10·`direction`9·`compta`8·`plateforme`6·`achat`5) ; `portails_business`
|
||
n'énumère **délibérément** que les 5 métier. Aucun `portail` réel hors des 6 attendus.
|
||
|
||
**Verdict.** Repo **CLEAN** sur le nouvel axe (rôles + portails référentiellement intègres) ; les
|
||
axes docstring↔code et numériques stakeholder restent concordants. **Aucun défaut de production.**
|
||
|
||
**Anti-gate (#5).** Pas de nouveau gate : beaucoup de ces slugs sont déjà transitivement
|
||
mono-sourcés (mémoire `roles-couverts-transitively-single-sourced`) et l'axe est une **vérification
|
||
rejouable** (à l'image de hash-seed / locale-TZ / forward-compat), pas un contrat à figer. Le
|
||
one-liner Python du sweep est consigné ici pour rejeu.
|
||
|
||
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**,
|
||
**0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6 — `980`/`66`/`50`/`6` recomputés des
|
||
artefacts + `rbac_50_roles.json`), **aucune commande VPS** (#8). `./run_ci.sh` = **33 PASS · 0 FAIL
|
||
· 0 SKIP** (inchangé, aucune édition de code). Seule édition : ce journal + une entrée mémoire.
|
||
|
||
## Session `20260806_034434` — CURRENCY canal stakeholder `a8342e9`→HEAD `48276ee` + re-vérif indépendante de la dernière prod (`48276ee`)
|
||
|
||
**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 (spec
|
||
`CHOISIR_MON_UNITE` = frontend VPS hors-périmètre #8). Aucune tâche fonctionnelle
|
||
in-repo. Constat : le daily report `2026-08-06.md` (rédigé session `011419`, attestait
|
||
HEAD `a8342e9`) ne consignait pas **deux** jalons de production 08-06 postérieurs —
|
||
`354a687` (fix help-text argparse `seo`) et surtout `48276ee` (fix générateur
|
||
`financement_bancaire` + MANIFEST reconstruit). Mémoire `two-logging-channels` : garder
|
||
le canal stakeholder courant, chaque chiffre sourcé d'artefact.
|
||
|
||
**Re-vérification indépendante de la dernière prod `48276ee` (avant de consigner).**
|
||
- MANIFEST courant `roles_rbac_utilises` = **3 objets distincts** (compta-tresorier,
|
||
ventes-conseiller, ventes-directeur), 0 doublon → fix effectif et correct.
|
||
- Balayage surfaces sœurs (README/finlib/tests) : **aucune** ne cite l'ancien compte
|
||
« 4 » ni une liste 4-entrées ; commentaire `builder.py:89-95` décrit correctement le
|
||
dédoublonnage → **0 dérive résiduelle** (motif « twin fix sweep ALL surfaces », propre).
|
||
- Champ appropriément ungaté (#5) : depuis l'état propre, `check_artifacts` MORD une
|
||
régression future (régénéré-avec-doublon ≠ committé-3-distinct → RED) → pas de gate N+1.
|
||
|
||
**Action.** Ajout d'une section de currency à `daily_reports/2026-08-06.md` : tableau
|
||
des 2 jalons de prod postérieurs (nature + opposabilité au merge), re-vérif de `48276ee`,
|
||
état courant re-dérivé au HEAD `48276ee` (8 statiques + 25 suites = 33 PASS · régression
|
||
624/607/17-skip = PASS). Chiffres recomputés de `git ls-files`/`run_ci.sh`/`ci.yml`/
|
||
`regression_run.json`, jamais saisis à la main.
|
||
|
||
**Verdict.** Dernière prod (`48276ee`) **correcte + complète**, 0 dérive résiduelle.
|
||
Canal stakeholder **à jour au HEAD**. **Aucun défaut de production.**
|
||
|
||
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**,
|
||
**0 gate ajouté** (#5), **0 chiffre inventé** (#6), **aucune commande VPS** (#8). Seules
|
||
éditions : `daily_reports/2026-08-06.md` + ce journal `05_activity_log/`.
|
||
|
||
## Session `20260806_031432` — FIX générateur (NOUVELLE sous-classe : liste per-slot vs ensemble distinct) · `crm/financement_bancaire` : `MANIFEST.roles_rbac_utilises` répétait `ventes-conseiller` (dup ungaté)
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée/gatée. Les 5 derniers commits étant FIX-help / currency / vérif-only,
|
||
chasse **adversariale à un vrai défaut ungaté** sur un **axe frais** (anti-churn) : la
|
||
**cohérence sémantique interne des artefacts commités** (un champ « ensemble » contenant un
|
||
doublon) — axe non balayé par les 7 axes de `024430`.
|
||
|
||
**Défaut trouvé (réel, haute confiance).**
|
||
`05_deliverables_mvp/crm/financement_bancaire/out/MANIFEST.json` · `roles_rbac_utilises` portait
|
||
**4 entrées pour 3 rôles distincts** : `ventes-conseiller` / `OTO Ventes Conseiller` **répété**
|
||
(positions 1 et 4). Reproductible depuis le générateur (donc **pas** un artefact stale — byte-repro
|
||
vert) : `finlib/builder.py:89` faisait `[roles_resolved[k] for k in sorted(roles_resolved)]`,
|
||
itérant les **4 slots logiques** de `spec["roles"]` — or **deux** slots (`conseiller_wag` ET
|
||
`validation_dossier`) pointent le même rôle `ventes-conseiller` → doublon.
|
||
|
||
**Preuve que c'est un bug et non un per-slot voulu.**
|
||
1. La sortie **drope la clé de slot** (`cle`) : chaque entrée ne porte que `role_id` +
|
||
`erpnext_role_name`. Un doublon ne transporte donc **aucune** information distinctive — si le
|
||
per-slot était voulu, la clé de slot serait sérialisée. Smoking gun.
|
||
2. Sémantique documentée : README `MANIFEST.json → … rôles RBAC **utilisés** » (README.md:54) +
|
||
`ci/README.md:1100` « l'**ensemble distinct** `(role_id, nom)` réellement payé ».
|
||
3. **Convention codebase** : les 3 modules frères produisent tous un ensemble **distinct**
|
||
(`confotur` 3/3 · `commissions` 4/4 · `workflow_vente` 7/7, `n == distinct`). `financement`
|
||
était **le seul outlier** (4/3).
|
||
|
||
**Fix (`finlib/builder.py:89`, aligné idiome `commissions`).** Ensemble **distinct** trié par
|
||
`role_id` : `[{"role_id": rid, "erpnext_role_name": resolver.erpnext_name(rid)} for rid in
|
||
sorted({rr["role_id"] for rr in roles_resolved.values()})]` + commentaire expliquant le
|
||
dédoublonnage multi-slots. Artefact régénéré (`build`) → `roles_rbac_utilises` = **3/3 distinct**
|
||
(`compta-tresorier`, `ventes-conseiller`, `ventes-directeur`).
|
||
|
||
**Pourquoi 0 gate ajouté (#5).** Le champ `roles_rbac_utilises` de `financement` n'est lu par
|
||
**aucun** gate (les blocs `check_readme_claims` qui le lisent visent confotur/commissions/
|
||
workflow_vente, en **SET** — donc dedup) ni aucun consommateur externe (`grep` = 0). Le champ
|
||
`counts` n'inclut pas de compte de rôles pour ce module (contrairement aux frères) → **aucune**
|
||
prose/oracle à réaligner. Le fix corrige la **source** ; un gate distinctness serait redondant
|
||
avec la convention déjà tenue par les frères et non-régressante ici (verify-before-gate).
|
||
|
||
**Non-régression.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** après (byte-repro
|
||
`check_artifacts` **vert avec le nouvel artefact** ; les **35** tests `crm-financement-bancaire`
|
||
verts — aucun ne figeait `roles_rbac_utilises`, l.204 teste `role_validation`, non affecté).
|
||
**2 fichiers édités** (`finlib/builder.py` + `out/MANIFEST.json` régénéré), **0 chiffre inventé**
|
||
(#6 — 4/3 recomputés), **aucune commande VPS** (#8).
|
||
|
||
## Session `20260806_024430` — VÉRIF indépendante multi-axes (7 axes) → **CLEAN · 0 édition de production**
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée/gatée côté dépôt (les restes roadmap = livrables VPS/live hors
|
||
périmètre worker · #8/instructions). Les 5 derniers commits étant FIX-help / currency / prose,
|
||
chasse **adversariale ciblée à un vrai défaut ungaté** sur des **axes frais** (anti-churn : ne PAS
|
||
réempiler une énième couche help-text/currency/prose déjà balayée par `021424`/`014423`/`011419`).
|
||
Chaque axe est soit corrigé, soit prouvé accurate/gaté — **aucune édition manufacturée** (#5/#6).
|
||
|
||
**Les 7 axes balayés (tous CLEAN) :**
|
||
|
||
1. **README « Entrée CLI » ↔ argparse** (23 modules) — sous-commandes / flags documentés dans les
|
||
README vs `add_parser(...)`/`add_argument(...)` réels. Aucun flag/sous-commande fantôme ni
|
||
divergence de nom (`--out` vs `--output`, etc.). Distinct de l'axe help-TEXT (déjà clos `021424`).
|
||
|
||
2. **Sémantique du CLI `validate`** — `cmd_validate` **re-construit en mémoire** (`_build`) puis
|
||
valide ; il ne relit **pas** l'artefact `out/` commité. **By-design, PAS un défaut de dents** :
|
||
la dérive byte d'un `out/` corrompu est couverte par `check_artifacts` (diff byte-à-byte).
|
||
Noté pour qu'une session future ne le « flag » pas comme teeth manquantes (verify-before-flag).
|
||
|
||
3. **Ledger 15 invariants SEO** — `seo_gen.py` numérote bien **1…15** (`# N ·`, l.77-215) ; les
|
||
3 surfaces prose (`validate` succès l.285, help `validate` l.297, README `## Garanties (15
|
||
invariants)`) disent **15**, self-consistent. Le « =9 » de la mémoire `invariant-ledger-count`
|
||
= **9 MODULES** en dialecte A, PAS 9 invariants/module (relecture — non-contradiction).
|
||
|
||
4. **Root `README.md` « 24/24 modules · 24 suites »** — correctement **sourcé** : `24 modules` =
|
||
périmètre `audit_4big/out/quality_report.json` ; `24 suites` = `regression_plan.json` qui
|
||
**s'auto-exclut** (`self_module: qa/regression`, ISA 315 · séparation des pouvoirs) → 24 =
|
||
25 gates-de-test `run_ci` − 1 (le harnais régression lui-même). **Piège de réconciliation**
|
||
24-vs-25 : NON-défaut. `totals.suites=24 · test_methods=624`, cohérent avec `regression_run.json`.
|
||
|
||
5. **Prose `notes[]` embarquée dans les artefacts JSON** (`regression_plan.json`, 5 notes) —
|
||
surface libre re-générée+byte-gatée ; contenu accurate (dérivation `.gitea/workflows/ci.yml`
|
||
via `q4lib/registry.parse_ci`, self-exclusion, anti-invention #6). CLEAN.
|
||
|
||
6. **Complétude de `gate.needs`** — le job d'agrégat `gate` (seul verrou de merge) liste bien les
|
||
**33** checks (8 statiques + 25 suites) ; `e2e-baseline` correctement exclu (manuel
|
||
`workflow_dispatch`). **Déjà GATÉ** par `ci/check_ci_integrity.sh` **INV-A**
|
||
(`gate.needs == {tous jobs} − {gate} − {manuels}`) → une dérive de câblage casserait le gate.
|
||
|
||
7. **Commentaires inline `#` cross-fait/compteur** (dans `*_gen.py` + `*lib/`, PAS docstrings/README
|
||
déjà audités) — 14 commentaires porteurs de compte vérifiés vs la réalité qu'ils décrivent
|
||
(50 rôles, 3 langues, 5 portails, 4 capacités OTOIA, 12 groupes Master Data PIE, 5 dimensions
|
||
audit_5d, ≥2 modules démo, axe5=20 pts, 4 conditions financement…). Tous synchronisés. CLEAN.
|
||
|
||
**Non-régression.** **0 fichier de production touché** (`git status` vide avant/après). `run_ci.sh`
|
||
**33 PASS · 0 FAIL · 0 SKIP** inchangé. 0 artefact reconstruit, 0 gate ajouté (#5 — tout défendable
|
||
est déjà gaté), 0 chiffre inventé (#6 — tout recomputé depuis artefacts/code), 0 VPS (#8).
|
||
|
||
## Session `20260806_021424` — FIX argparse-help↔code (classe `docstring-vs-code-drift`, sous-classe help-text du fix `a8342e9`) · `seo/seo_gen.py` : le help `build` nommait des fichiers de sortie INEXISTANTS
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Les 5 derniers commits étant currency/vérif-only, chasse **adversariale à un vrai défaut ungaté**,
|
||
en poursuivant la sous-classe ouverte par le fix `a8342e9` (session `004414`) : le **texte help
|
||
d'une sous-commande argparse énumérant ses fichiers de sortie**. Audit exhaustif des **22
|
||
générateurs** (`*_gen.py` avec sous-commande `build`/`generate`) : annoncé-dans-le-help ↔
|
||
réellement-écrit-par-le-code.
|
||
|
||
**Résultat de l'audit.** 21/22 CLEAN — mais **1 vrai défaut** trouvé, haute confiance :
|
||
`05_deliverables_mvp/seo/seo_gen.py:293`. Le help `build` disait
|
||
`"genere seo_keywords/schema_org/hreflang + MANIFEST"`, or les fichiers RÉELLEMENT écrits
|
||
(`seo_gen.py:259-262`) sont `seo_keywords.json`, **`seo_schema_org.json`**, **`seo_hreflang.json`**,
|
||
`MANIFEST.json`. Le help **droppait le préfixe `seo_`** sur 2 des 3 fichiers (`schema_org`,
|
||
`hreflang`) ET l'extension `.json` sur tous : il nommait donc des fichiers **qui n'existent pas**
|
||
(`schema_org` ≠ `seo_schema_org.json`). Ce n'est pas un simple raccourci toléré — exactement la
|
||
classe du fix `a8342e9` (le help ment sur la surface de sortie que l'agent lit pour lancer son
|
||
propre livrable).
|
||
|
||
**Preuve que c'était bien la SEULE surface fautive (fix en une passe).** Le docstring module
|
||
(`seo_gen.py:6-9`) ET le README (`README.md:15-18`) nomment déjà correctement les 4 fichiers
|
||
exacts (`out/seo_schema_org.json`, `out/seo_hreflang.json`, …) — c'est le help l'outlier, pas
|
||
l'inverse. Les modules frères (`commissions`, `audit_5d`, `app_config` post-`a8342e9`) énumèrent
|
||
des **noms de fichiers complets** ; `seo` était le seul en raccourci imprécis.
|
||
|
||
**Fix (`seo_gen.py:293`).** Help → `"genere seo_keywords.json / seo_schema_org.json /
|
||
seo_hreflang.json / MANIFEST.json"` — exact, aligné sur le docstring/README du module ET la
|
||
convention des frères. Style respecté : ASCII sans-accent (`genere`, comme le reste du fichier).
|
||
|
||
**Pourquoi 0 gate ajouté (#5).** Le help n'est ni sérialisé dans un artefact ni parsé par un gate
|
||
(le gate `check_readme_claims` « Entrée CLI » ne lit que le NOM `add_parser("build")` via AST, pas
|
||
le `help=`). Un gate parseur du help serait **fragile** : les 22 help strings n'ont PAS de
|
||
convention machine-parsable commune (`seo` en raccourci, `faisabilite` décrit un répertoire
|
||
`data_room/PXX/`, séparateurs `/` vs `+` mêlés). Mauvais compromis robustesse/valeur → la classe
|
||
reste couverte par l'audit périodique (ici 22/22 balayés), pas par un gate.
|
||
|
||
**Non-régression.** Sortie `build` **byte-identical** aux 4 artefacts `out/` commités (help = code
|
||
pur, non sérialisé → 0 rebuild). `python3 -S seo_gen.py build/validate` OK. `run_ci.sh` **33 PASS ·
|
||
0 FAIL · 0 SKIP**. 0 prod (#8), 0 artefact reconstruit, 0 chiffre inventé (#6 — tout recomputé).
|
||
|
||
## Session `20260806_014423` — FIX prose-numérique canal stakeholder · le compte « bijection README↔réel » de la session `011419` sous-comptait (14 → **16**) · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée/gatée. Les 5 derniers commits étant currency/vérif-only, chasse
|
||
**adversariale ciblée à un vrai défaut ungaté** — pas une énième couche de currency (anti-churn).
|
||
Premier axe (comment↔code des `ci/*.sh`, classe du fix `8903a4b`) → un candidat `check_regression.sh:17`
|
||
**écarté comme faux positif** : le commentaire « (ran/passed/failures) » décrit ce que l'**artefact**
|
||
*porte* (le JSON contient bien `failures:0`), pas la ligne d'affichage `l.79` ; le contrat réel du
|
||
gate est le `diff -q` byte-à-byte du fichier entier (`l.71`), qui couvre `failures`. Non-défaut.
|
||
|
||
**Défaut trouvé (réel, haute confiance) — classe `prose-facts-vs-numeric-drift`.** L'« axe de
|
||
vérification objectif » introduit par la session `011419` (bijection *compte de tests annoncé dans
|
||
chaque README* ↔ *nombre réel de `def test_*`*) affirmait **« concordance totale sur les 14 READMEs
|
||
annonceurs »** — figure reprise à l'**identique dans DEUX surfaces** : le canal stakeholder
|
||
`daily_reports/2026-08-06.md` (l.48-54) **et** ce journal (entrée `011419`). Or l'énumération de
|
||
`011419` liste effectivement 14 modules mais **en omet 2** qui annoncent pourtant un compte dans
|
||
leur README, tous deux concordants avec le réel : **`frontend/portails 19`** (19 `def test_`) et
|
||
**`demo/scenarios 39`** (39 `def test_`). Le vrai total est **16 annonceurs / 9 sans annonce**,
|
||
**corroboré par l'en-tête faisant autorité** de `ci/check_readme_claims.sh` (l.96 : « **27 claims
|
||
sur 16 modules** »). Le « 11 sans annonce » du canal était le complément erroné (25 − 14) → **9**.
|
||
|
||
**Fix (sweep des 2 surfaces en une passe, cf. `prose-facts-vs-numeric-drift`).**
|
||
- `daily_reports/2026-08-06.md` : `14 → 16`, ajout des 2 entrées manquantes à l'énumération,
|
||
`11 → 9` sans annonce, + ancrage explicite à l'en-tête « 16 modules » du gate.
|
||
- ce journal : `14 → 16` dans l'entrée `011419` (fait présent sur l'état courant du repo) avec
|
||
commentaire de traçabilité ; nouvelle entrée (celle-ci) documentant la correction.
|
||
Chiffres re-dérivés, non saisis : `grep -rlE '[0-9]+ tests' README.md` = **16** annonceurs · `def test_`
|
||
par suite = concordance **16/16** · `find -name tests` = **25** suites → complément **9** · en-tête gate = **16**.
|
||
|
||
**Non-régression.** Le compte est un fait de prose **ungaté** (canal stakeholder + journal, classe
|
||
`two-logging-channels` : chiffre à sourcer d'artefact, ici recomputé). Aucun oracle/gate ne fige
|
||
cette phrase (vérifié) : édition sûre. `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** avant/après.
|
||
|
||
**Portée.** **0 fichier de production édité** (2 docs : 1 deliverable stakeholder + ce journal),
|
||
**0 artefact reconstruit**, **0 gate ajouté** (#5 — correction de fait, pas un contrôle ; la surface
|
||
de compte-de-tests des READMEs est déjà gatée par `check_readme_claims.sh`), **0 chiffre inventé**
|
||
(#6 — `14→16`/`9`/`25` recomputés), **aucune commande VPS** (#8).
|
||
|
||
## Session `20260806_011419` — CURRENCY canal stakeholder porté au HEAD `a8342e9` + axe de vérif objectif ajouté (bijection compte-de-tests README↔réel) · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée+gatée. Le canal stakeholder `daily_reports/` s'arrêtait au
|
||
**2026-08-05** (HEAD `8903a4b`) alors que **deux** jalons du **2026-08-06** avaient depuis été
|
||
livrés — dont un **vrai fix de production** (`a8342e9`, help argparse `mobile/app_config` omettant
|
||
`store_listing.json`) **non encore consigné** côté stakeholder. Contrairement aux currency
|
||
purement vérification-only (motif anti-churn adopté en `234409`/`231404`), il y a ici une **vraie
|
||
évolution d'état** à reporter → currency légitime du canal lapsé (`two-logging-channels`).
|
||
|
||
**Ce qui a été fait.** Création de `05_deliverables_mvp/daily_reports/2026-08-06.md` :
|
||
- tableau des **2 jalons 08-06** (`fe61207` VÉRIF-only · `a8342e9` FIX 1-ligne help-text) avec
|
||
nature + opposabilité au merge ;
|
||
- état courant re-dérivé d'artefacts commités : **33 PASS** (8 statiques `git ls-files ci/*.sh`
|
||
hors `lib.sh` + 25 suites) · régression `624 exécutés / 607 passés / 17 skippés / 0 échec = PASS`
|
||
(`qa/regression/out/regression_run.json` `totals`, 17 skips par design) ;
|
||
- **axe de vérification objectif ajouté ce jour** : bijection `N tests` annoncé dans chaque
|
||
README ↔ nombre réel de `def test_*` → **concordance totale sur les 16 READMEs porteurs d'une
|
||
annonce** (seo 36 · ecf 39 · confotur 44 · dossier_vente 31 …), 0 dérive.
|
||
<!-- CORRIGÉ session 014423 : « 14 » était un sous-comptage — l'énumération de ce jour
|
||
omettait `frontend/portails 19` et `demo/scenarios 39` ; le vrai total est 16, concordant
|
||
avec l'en-tête faisant autorité « 27 claims sur 16 modules » de ci/check_readme_claims.sh. -->
|
||
|
||
**Vérif indépendante préalable (lecture-seule).** docstring↔code re-vérifié sur modules non
|
||
balayés la veille : `publiciste` (docstring/help/writes cohérents = `projets_master.json` +
|
||
`index.html`) · `fiscal/ecf_dgii` (« 12 invariants » = schéma(1)+2→12 numérotés, self-consistant,
|
||
**pas** un défaut). Couverture CI de `publiciste` confirmée dans `gate.needs`. Structure
|
||
`ci/*.sh`↔`gate.needs` intacte (8 statiques).
|
||
|
||
**Non-régression.** Le rapport est une doc stakeholder pure : `./run_ci.sh` = **33 PASS · 0 FAIL
|
||
· 0 SKIP** avant et après.
|
||
|
||
**Portée.** **0 fichier de production édité**, **0 artefact reconstruit**, **0 gate ajouté**
|
||
(#5 — currency documentaire, pas un contrôle), **0 chiffre inventé** (#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 : le rapport de currency + ce journal.
|
||
|
||
## Session `20260806_004414` — FIX docstring↔code (sous-classe help-text argparse) · `mobile/app_config_gen.py` : le help de la sous-commande `build` omettait `store_listing.json`
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, roadmap
|
||
intégralement livrée/gatée. Plutôt qu'une énième passe vérification-only (les 5 derniers
|
||
commits l'étaient), **chasse adversariale ciblée à un vrai défaut ungaté** sur la classe
|
||
RECURRING `docstring↔code`, scopée aux modules **non** balayés la veille (session `001412`
|
||
avait couvert seo/financement/demo/pie/rbac/audit_4big/chat/workspaces/workflow_vente/confotur).
|
||
|
||
**Défaut trouvé (réel, haute confiance).** `05_deliverables_mvp/mobile/app_config/app_config_gen.py:279` —
|
||
le `help=` de `sub.add_parser("build", …)` énumérait **4** sorties
|
||
(`app_config.json / eas_build.json / role_navigation.json / MANIFEST.json`) alors que
|
||
`cmd_build()` en écrit **5** (l.240-244) : `store_listing.json` (l.243) était **omis** du help.
|
||
La docstring (l.15, « écrit les 5 fichiers ci-dessus ») et le README (l.56/68) listent bien les 5.
|
||
Nouvelle **sous-classe help-text argparse** du motif `docstring↔code` — distincte des sorties
|
||
`open(...,'w')` vs docstring déjà balayées : le help CLI est une 2ᵉ surface prose dans le code.
|
||
|
||
**Fix.** Ajout de `store_listing.json` dans le `help=`, à sa position canonique
|
||
(…role_navigation → **store_listing** → MANIFEST), ordre identique docstring/README/code.
|
||
Aucun gate/test ne fige cette chaîne (`grep -rn` = 0 hit hors le fichier) → édition sûre,
|
||
pas d'oracle à réaligner.
|
||
|
||
**Non-régression.** Le help n'affecte aucune sortie : artefacts **byte-identiques**
|
||
(`ci/check_artifacts.sh` vert dans le merge). `--help` rend désormais les 5 fichiers.
|
||
`./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** avant et après.
|
||
|
||
**Portée.** **1 fichier de production édité** (1 ligne, help argparse), **0 artefact reconstruit**
|
||
(sortie inchangée), **0 gate ajouté** (#5 — la chaîne n'était figée par personne, on corrige
|
||
la source pas de nouveau gate), **0 chiffre inventé** (#6), **aucune commande VPS** (#8).
|
||
Reste de l'audit (audit_5d/acceptance/regression/deploy_runbook/commissions/dossier_vente/
|
||
ecf/portails/faisabilite) = **CLEAN**, comptes d'invariants et noms de sorties concordants.
|
||
|
||
## Session `20260806_001412` — VÉRIF indépendante multi-axes (docstring↔code · numériques du canal stakeholder · liens in-repo) → CLEAN · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
La roadmap `04_roadmap/ROADMAP_8_WEEKS_OR_LESS.md` est intégralement livrée/gatée (8 gates
|
||
statiques + 25 suites, 22 modules dans ≥1 fiche). Le canal de currency
|
||
`daily_reports/2026-08-05.md` attestait au HEAD `8903a4b` ; depuis, **deux** commits
|
||
**vérification-only** (`21f55a9` currency, `c196e41` VÉRIF adversariale, tous deux « 0 prod »).
|
||
Conformément à la décision anti-churn déjà prise en `234409` (« plutôt que répéter le motif de
|
||
currency »), **pas** de énième couche de currency pour deux commits sans changement d'état
|
||
stakeholder. À la place : **chasse indépendante à un vrai défaut ungaté** sur trois surfaces,
|
||
plus re-dérivation des chiffres du canal stakeholder pour prouver qu'aucun n'a dérivé.
|
||
|
||
**Axe 1 — docstring↔code (classe RECURRING).** Balayage `Explore` skeptique des générateurs de
|
||
production + helpers, sortie-par-sortie : noms de fichiers `open(...,'w')` vs docstring/README,
|
||
flags `argparse` vs docstring, comptes d'invariants du ledger numéroté vs docstring. **13 modules
|
||
audités CLEAN** (seo 4/4 fichiers · financement_bancaire 7/7 · demo_scenario 3/3 · pie 2/2 ·
|
||
rbac_fixtures 3/3 · audit_4big 2/2 · chat_otoia 3/3 · workspaces 2/2 · workflow_vente 4/4 ·
|
||
confotur 2/2 …). Comptes d'invariants concordants (seo 15 · audit_5d 15 · pie 10 · rbac_apply 7 ·
|
||
workflow_vente 9 · confotur 14 · dossier_vente 12 · commissions 10 · financement 12). Non-défaut
|
||
connu ré-écarté : `validate [-o OUT]` = bijection compat 8-vs-13 self-consistante, **pas** un défaut.
|
||
|
||
**Axe 2 — numériques du canal stakeholder re-dérivés au HEAD.** Aucune dérive :
|
||
- SEO **258** mots-clés recomputés de `seo/out/seo_keywords.json` → **fr=87 · en=87 · es=84** (concorde).
|
||
- Gates statiques : `git ls-files 'ci/*.sh'` hors `lib.sh` = **8** (concorde).
|
||
- Suite de merge : `run_ci.sh` = **33** PASS (= 8 statiques + 25 suites, concorde).
|
||
|
||
**Axe 3 — liens markdown in-repo (surface objective).** Extraction de tous les `[texte](cible)`
|
||
repo-wide non-`http`/`#`/`mailto` : **294** liens, **291 résolvent**. Les **3** « cassés »
|
||
sont des **faux positifs** — des exemples de *syntaxe* de lien cités en prose dans des journaux
|
||
**historiques**, non des liens réels : `2026-08-02.md:392` (`[texte](cible)` documentant le
|
||
comportement de `check_docs.sh`) et `2026-07-30.md:1432/1477/1479` (l'exemple pédagogique
|
||
`…/README.md` **à ellipse** que le journal lui-même décrit comme « déclaré cassé par la regex »).
|
||
Le vrai gate `check_docs.sh` **neutralise** les code-spans à backticks et ne les compte pas ;
|
||
ma regex ad-hoc, plus grossière, a simplement reproduit le faux positif que le journal explique.
|
||
Classe *pedagogical-hypothetical* = **KEEP** (motif prose-facts). **0 lien réel cassé.**
|
||
|
||
**Verdict.** Repo **CLEAN** sur les trois axes + numériques stakeholder intacts. **Aucun défaut de
|
||
production.** Session de vérification, à l'image de `d6a8d73`/`c196e41`.
|
||
|
||
**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`/`87`/`87`/`84`/`294`/`291`
|
||
recomputés de `git ls-files` · `run_ci.sh` · l'artefact · le sweep de liens), **aucune commande
|
||
VPS** (#8). Seule édition : ce journal `05_activity_log/`.
|
||
|
||
## Session `20260806_061455` — CURRENCY canal stakeholder porté `48276ee` → HEAD `e786c12` (prose-facts drift) · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée/gatée (Sprints 1→7 côté repo ; déploiement prod / builds EAS /
|
||
dépôts ONAPI = hors périmètre worker, VPS `153.75.250.214`, `CLAUDE.md` #8). Les **~10 derniers
|
||
commits** sont majoritairement des sweeps vérification-only à rendement décroissant. Objectif :
|
||
éviter le churn (re-sweep déjà couvert) et corriger un **fait de prose réellement dérivé**.
|
||
|
||
**Axes ré-audités CLEAN (non re-flaggés).** (1) liens md avec ancre `#…` → **1 seule**
|
||
occurrence (`README.md:20`), résout, déjà en mémoire. (2) Robustesse shell des gates : `set -e`
|
||
absent partout mais **intentionnel** (les gates accumulent les échecs puis `exit` en fin ;
|
||
`lib.sh::cd_repo_root` couvre le « vert trompeur » hors-git). (3) Mode git + shebang des 9
|
||
`ci/*.sh` : tous `100755 #!/usr/bin/env bash` sauf `lib.sh` `100644` (sourcé, correct) ; invoqués
|
||
`bash ci/…` dans `ci.yml`. → cohérents, **0 défaut**.
|
||
|
||
**Défaut réel trouvé (classe `prose-facts-vs-numeric-drift`).** Le canal stakeholder
|
||
`05_deliverables_mvp/daily_reports/2026-08-06.md` était ancré au HEAD `48276ee` et affirmait
|
||
« dernière prod = `48276ee`, tout le reste 0-édition ». Or **5 commits** ont atterri depuis, et
|
||
l'un — `e786c12` — **édite `README.md`** (3 href, fix label↔cible). La prose « dernière prod »
|
||
dérivait donc vs le graphe de commits réel : `git log 48276ee..HEAD` + filtrage des fichiers
|
||
hors `05_activity_log/` & `daily_reports/` → **4 commits journal-only** + **1 édition dépôt réelle**
|
||
(`e786c12` → `README.md`). → **FIX** = porter la currency à HEAD `e786c12`, tabuler l'opposabilité
|
||
au merge des 5 commits, ré-attester l'état courant.
|
||
|
||
**Chiffres re-dérivés (#6, aucun saisi à la main).** `8` gates statiques (`git ls-files 'ci/*.sh'`
|
||
hors `lib.sh`) · `25` suites (`*-tests` de `gate.needs`) · `25` modules testés (`find test_*.py`) ·
|
||
`624`/`607`/`17` (`regression_run.json::totals`) · `33 PASS` (`run_ci.sh`). **Tous inchangés** vs
|
||
`48276ee` — `e786c12` ne touche que des href → aucune sortie/compte modifié, `check_artifacts`
|
||
byte-identique.
|
||
|
||
**Vérif.** `ci/check_docs.sh` **PASS** · `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP**.
|
||
|
||
**Portée / anti-churn.** Édité : `daily_reports/2026-08-06.md` (section currency) + ce journal.
|
||
**0 artefact reconstruit**, **0 gate ajouté** (#5 — dérive prose isolée, pas une classe
|
||
récurrente à gater), **0 chiffre inventé** (#6), **0 commande VPS** (#8). Structure du gate
|
||
inchangée (33 checks).
|
||
|
||
## Session `20260806_064502` — Hypothèse « copie-constante à single-sourcer » RÉFUTÉE par le gate · +1 commentaire anti-footgun · 0 édition de production
|
||
|
||
**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre,
|
||
roadmap intégralement livrée/gatée. Les ~10 derniers commits sont des sweeps vérif-only à
|
||
rendement décroissant. Objectif : traquer une **vraie duplication de constante mandat** à
|
||
single-sourcer (classe `fix-vs-gate-transitively-protected-constant` : DELETE la copie, pas
|
||
gate N+1), pas re-sweeper du déjà-couvert.
|
||
|
||
**Piste investiguée (constantes canoniques #9/#10).** Les 6 marqueurs `3 % / 8.5 % / 52 % /
|
||
USD + DOP / Cardnet / Letter US` existent en **≥4 endroits** : (a) `CLAUDE.md` #9/#10 = source ·
|
||
(b) `genlib/model.py` CANONICAL (émis dans chaque rendu) · (c) `genlib/renderer.py`
|
||
`_CANONICAL_MARKERS` (oracle de `check_canonical`) · (d) `tests/test_generator.py` la liste
|
||
`for marker in [...]`. J'ai d'abord lu la 1ʳᵉ moitié du gate `check_readme_claims` qui n'ancrait
|
||
explicitement que (a→b) + la prose README → **hypothèse** : (c) et (d) sont des copies **non
|
||
gatées** → les dériver de `model.CANONICAL` (source unique auto-suivante).
|
||
|
||
**RÉFUTATION — le gate a mordu (bien joué la discipline `run_ci`).** Édité (c)+(d) →
|
||
`./run_ci.sh` = **32 PASS · 1 FAIL** (`check-readme-claims`). La **2ᵉ moitié** du même gate
|
||
(bloc ligne ~5475) `ast.literal_eval` **statiquement** les DEUX listes (regex
|
||
`_CANONICAL_MARKERS\s*=\s*(\[.*?\])` et `for marker in (\[...\])`) et les set-diffe vs les 6
|
||
valeurs re-dérivées de CLAUDE.md. Donc (c)/(d) étaient **déjà gatés**. Pire : la dérivation
|
||
casse la raison d'être même de l'oracle — `check_canonical()` **prouve** que le rendu (bâti
|
||
DEPUIS `model.CANONICAL`) émet bien chaque valeur ; le dériver de `CANONICAL` rend le contrôle
|
||
**tautologique** (« md-bâti-depuis-X contient X » = vert vacux). Le commentaire du gate le dit
|
||
noir sur blanc : « si cette liste DÉRIVE de CANONICAL … le contrôle NE VÉRIFIE PLUS RIEN ».
|
||
|
||
**Conclusion — EXCEPTION à `fix-vs-gate-transitively-protected-constant`.** Cette règle vise
|
||
les copies **passives** (prose, config). Un **oracle d'enforcement** est **actif** : sa
|
||
duplication EST le test ; l'ancrage correct = garder le littéral + gate statique vs la source
|
||
(exactement l'état existant). **Revert** intégral des 2 éditions (test byte-identique restauré).
|
||
|
||
**Livrable retenu.** Un seul changement survit : **+5 lignes de commentaire anti-footgun** à
|
||
`renderer.py:275`, remontant au **site de code** la raison (indépendance de l'oracle) autrement
|
||
enfouie dans le script CI — pour qu'un mainteneur (ou moi, prochaine session) ne refasse pas la
|
||
« DRY-ification » qui décapite l'oracle. Sortie **inchangée** (commentaire pur), `check_artifacts`
|
||
byte-identique. Mémoire `enforcement-oracle-must-stay-independent` créée.
|
||
|
||
**Vérif.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP**.
|
||
|
||
**Portée / anti-churn.** Édité : `renderer.py` (1 commentaire) + ce journal + mémoire. **0 artefact
|
||
reconstruit**, **0 gate ajouté** (#5), **0 chiffre inventé** (#6 — les 6 marqueurs déjà présents,
|
||
re-dérivés du gate), **0 commande VPS** (#8). Structure du gate inchangée (33 checks).
|
||
|
||
---
|
||
|
||
## Session `20260806_071503` — anti-footgun in-fiche : documenter l'omission MANIFEST volontaire de la colonne « Sortie » · 0 artefact reconstruit
|
||
|
||
**État au démarrage.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre, roadmap
|
||
intégralement livrée + gatée. HEAD `ddcafc5` (commentaire anti-footgun `renderer.py`, output
|
||
inchangé). Les ~15 derniers commits sont des sweeps vérif-only / currency à rendement décroissant
|
||
(la session précédente le notait). Objectif : **éviter d'ajouter un énième « CLEAN sweep »** et
|
||
trouver une amélioration *durable* réelle.
|
||
|
||
**Chasse au défaut (Explore adversarial).** Dispatché un agent lecture-seule sur 3 surfaces
|
||
(fiches `03_agents/*/AGENT.md` ↔ modules réels · READMEs ↔ `*_gen.py` · liens label↔cible).
|
||
Retour : **1 candidat** — `frontend_console/AGENT.md:29` « colonne Sortie du chat_otoia omet
|
||
`MANIFEST.json` » alors que `chat_otoia_gen.py:237` écrit bien les 3 fichiers.
|
||
|
||
**Réfutation via mémoire — FAUX POSITIF connu.** C'est exactement `fiche-sortie-cell-omits-
|
||
manifest-by-design` : la colonne « Sortie » liste le **payload métier** seul ; le MANIFEST est
|
||
omis **dans les DEUX rangs** (portails + chat) = convention éditoriale, PAS une dérive ; les
|
||
docstrings/READMEs énumèrent bien les 3 (byte-gatés). « Corriger » violerait #5/#6 et risquerait
|
||
de casser le gate (la cellule est regex-parsée par `check_readme_claims.sh`). **0 édition de ce
|
||
faux positif.**
|
||
|
||
**Signal actionnable.** Le fait qu'un Explore **re-flague la MÊME cellule cette session** (déjà
|
||
flaguée session 234409) = preuve que la convention est un **footgun non documenté** : elle brûle
|
||
des cycles d'audit et risque un « fix » erroné (ajout MANIFEST à la cellule gate-parsée → churn
|
||
#5, voire RED). Exactement le motif de la session précédente (commentaire anti-footgun remonté au
|
||
**site** dans `renderer.py`).
|
||
|
||
**Livrable — note anti-footgun in-fiche.** Ajouté au `frontend_console/AGENT.md` (juste après la
|
||
table + les puces Portails/Chat) un blockquote `> **Note de lecture — colonne « Sortie ».**`
|
||
expliquant que la cellule liste le payload seul, que chaque générateur écrit **en plus** un
|
||
`out/MANIFEST.json` **volontairement omis** par convention, que l'énumération exhaustive vit dans
|
||
docstrings/READMEs byte-gatés, et **« ne PAS l'ajouter »** (cellule regex-parsée). Rédigé pour
|
||
**éviter les regex ancrées** du gate (aucun motif `N cartes/M liens/K rôles`, aucun
|
||
`**N tests** · job CI`).
|
||
|
||
**Vérif.** `check_readme_claims.sh` exit 0 · `check_docs.sh` exit 0 · `./run_ci.sh` =
|
||
**33 PASS · 0 FAIL · 0 SKIP**. Mémoire `fiche-sortie-cell-omits-manifest-by-design` mise à jour
|
||
(récurrence + mitigation in-fiche consignées).
|
||
|
||
**Portée / anti-churn.** Édité : `frontend_console/AGENT.md` (1 blockquote de prose) + ce journal
|
||
+ mémoire. **0 artefact reconstruit**, **0 gate ajouté** (#5), **0 chiffre saisi à la main** (#6 —
|
||
la note ne contient aucun compteur), **0 commande VPS** (#8). Structure du gate inchangée (33 checks).
|
||
|
||
## Session `20260806_074504` — VÉRIF · NOUVEL axe méta « bijection de câblage CI » (fichiers `ci/*.sh` ↔ jobs `ci.yml` ↔ miroir `run_ci`) → CLEAN + auto-protégé · 0 édition de production
|
||
|
||
**État au démarrage.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP**, arbre propre, HEAD `4c741a7`,
|
||
roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée (Sprints 1→7 côté repo ; prod/EAS/
|
||
ONAPI hors périmètre worker, VPS `153.75.250.214` · `CLAUDE.md` #8). Les **~15 derniers commits**
|
||
sont des sweeps vérif-only / currency à rendement décroissant.
|
||
|
||
**Currency écartée (serait du churn).** Depuis la dernière currency `daily_reports` (`e786c12`),
|
||
**2 commits** seulement : `ddcafc5` (commentaire `renderer.py`) + `4c741a7` (blockquote
|
||
`frontend_console/AGENT.md`) — **0 changement de sortie/compte** (`check_artifacts` byte-identique).
|
||
Pas de vraie évolution d'état stakeholder → re-porter la currency serait du churn (`two-logging-channels`
|
||
= currency légitime **seulement** sur changement d'état réel). **0 édition du canal.**
|
||
|
||
**Axe NEUF chassé (absent de la mémoire) — bijection de câblage CI.** Distinct de
|
||
`gate-enumeration-completeness` (compte de gates dans la prose) et `ci-gate-verification-method`
|
||
(archive vs runner) : la cohérence des **trois couches** filesystem `ci/*.sh` ↔ jobs `.gitea/workflows/ci.yml`
|
||
↔ miroir local `run_ci.sh`.
|
||
- **8/8 gates statiques invoqués** par un job `ci.yml` (`check_artifacts / check_ci_integrity /
|
||
check_docs / check_mobile_workflow / check_readme_claims / check_regression / guard_constraints /
|
||
validate_json`) → **aucun gate orphelin/mort**.
|
||
- **`run_ci.sh` ne peut pas dériver de la CI par construction** — il **ne code en dur aucun nom de
|
||
script** (grep = 0 réf sur 7/8 ; l'unique hit `check_ci_integrity` est un commentaire). Il **dérive**
|
||
la liste de `gate.needs` dans `ci.yml` et rejoue chaque `run:`/`working-directory:` déclaré, en
|
||
**imprimant** le décompte jobs/gates/suites à l'exécution. Un gate ajouté/retiré s'y répercute
|
||
automatiquement ; un « vert local mais rouge au push » est **impossible**. L'en-tête `run_ci.sh`
|
||
le documente noir sur blanc, et `run_ci` lui-même n'est **pas** un gate (#5, `local-ci-runner`).
|
||
- Prose « 7/7 · 8 gates statiques verts » (`ci/README.md` · `check_mobile_workflow.sh:13` ·
|
||
`check_readme_claims.sh:9202`) = **descriptions pédagogiques de dents de mutation** (ce qu'un retrait
|
||
de ligne laisserait vert), **pas** des comptes d'état présent → **KEEP** (`prose-facts-vs-numeric-drift`).
|
||
|
||
**Une sous-classe réellement ungatée (occurrence-zéro ⇒ sweep, pas gate, #5).** `check_ci_integrity`
|
||
INV-A valide `gate.needs == jobs − gate − manuels` à partir de la **liste de jobs de ci.yml**, PAS de
|
||
l'ensemble **filesystem** `ci/*.sh`. Un script commité sur disque mais **jamais câblé** dans un job
|
||
serait un gate **mort silencieux** — non détecté. CLEAN aujourd'hui (8/8 câblés) ; verdict identique à
|
||
`runtime-encoding-integrity-sweep` (dents réelles, occurrence-zéro ⇒ rejouable, on ne fige **pas** un gate).
|
||
|
||
**Verdict.** Repo **CLEAN** + **auto-protégé** sur l'axe de câblage CI. **Aucun défaut de production.**
|
||
|
||
**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit**, **0 gate ajouté**
|
||
(#5), **0 chiffre saisi à la main** (#6 — `8`/8 recomputé par balayage), **0 commande VPS** (#8).
|
||
`./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** (inchangé). Seules éditions : ce journal + mémoire
|
||
`ci-wiring-bijection-sweep` (+ pointeur `MEMORY.md`).
|