Files
oto-enterprise-os-dtp/05_activity_log/2026-08-05.md
T

172 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Activity Log · 2026-08-05 · Claude Code DTP Worker
## Session 001109 · Nouveau gate `check-mobile-workflow` — la structure de `mobile-build.yml` devient opposable au merge (surface mutation-testée UNGATED, 1er contrôle) → 1 gate ajouté + câblé · 32→33 jobs
**Contexte + choix de tâche.** `./run_ci.sh` au démarrage : **32 PASS · 0 FAIL · 0
SKIP**, arbre propre. Roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée
(8 sprints). Les 4 sessions du 08-04 (`221055`, `224101`, `231101`, `234104`) avaient
saturé les surfaces d'audit read-only (inter-artefacts, dérive non-gatée, attestation
stakeholder) puis **durci `mobile-build.yml`** (pattern preflight-output, portable
GitHub/Gitea). Cette dernière édition a laissé une **queue** : son propre log notait
« Aucun gate ne linte la structure de `mobile-build.yml` (`check-ci-integrity` ne
verrouille QUE `ci.yml`) ». Autrement dit le correctif de portabilité qu'elle venait
de poser **pouvait régresser en silence** — exactement la classe « marche dans ma
tête, casse le jour où on en a besoin » (mémoire [[mobile-build-secrets-if-gating]] :
« workflow HORS `gate.needs``run_ci` won't catch a regression »). La valeur honnête
du jour : **fermer cette queue** en rendant la structure de `mobile-build.yml`
opposable au merge. NON redondant (#5) : c'est le **premier** contrôle de ce fichier.
**Preuve d'absence de couverture AVANT d'ajouter le gate** (discipline
[[verify-uncovered-before-gating]]). Mutation : réintroduire l'exact anti-pattern
corrigé en `234104``secrets.EAS_TOKEN != ''` dans un `if:` au niveau job. Résultat :
**7/7 gates statiques restent VERTS**. Surface confirmée non gatée (ni
`check_ci_integrity` — scope `CI=ci.yml` — ni `validate_json` — scope `.json`). Fichier
byte-restauré aussitôt (`cp` depuis backup tmp · jamais `git clean`). <!-- ci-allow : mention de l'interdit, jamais exécuté -->
**Livrable : `ci/check_mobile_workflow.sh` (8ᵉ gate statique) + câblage.** Le gate lit
des **FAITS dans le fichier** (jamais une liste à la main · #6), 4 invariants :
- **MOB-1 · bien-formé** — existe · `name:`/`on:`/`jobs:` + 3 jobs (`preflight`,
`build-ios`, `build-android`) ; parse YAML strict **exigé si PyYAML dispo**, sinon
awk seul (runner sans pip → best-effort, jamais un faux vert : MOB-2/3/4 en sont
indépendants).
- **MOB-2 · portabilité** — **0** `secrets.` dans un `if:` de **job** (`^ if:`).
Le contexte `secrets` n'est pas exposé dans `jobs.<id>.if` (table d'availability
GitHub Actions) → sur `act`/Gitea il s'évaluerait vide → **SKIP silencieux**. C'est
la régression `234104` verrouillée.
- **MOB-3 · activation différée (#6/#8)** — chaque job de build (`run: eas build`) est
gaté sur `needs.preflight.outputs.has_token` → SKIP tant que le token absent, donc
le workflow ne rend jamais le CI rouge avant activation Michel.
- **MOB-4 · contrat d'outputs** — `preflight` déclare `has_token`/`has_repo`, chaque
`needs.preflight.outputs.<X>` référencé est **déclaré** (0 dangling) et chaque output
déclaré est **alimenté** par un `echo …>>$GITHUB_OUTPUT`.
**Bug corrigé pendant l'écriture (auto-vérification).** 1er jet : `preflight` était
classé « job de build » car un **commentaire** `# … eas build …` (l.108, entre deux
jobs) était attribué au job précédent par le parseur awk. Corrigé en exigeant
`run:[[:space:]]*eas build` (commande réelle, pas une mention). Après correctif : gate
**VERT** sur le fichier propre.
**Mutation-testing du gate lui-même (5 mutations · toutes ROUGES, fichier propre
re-VERT).** (1) YAML cassé (indent) · (2) `secrets.` en `if:` de job · (3) `if:` du
job `build-ios` supprimé · (4) output fantôme référencé (`has_tokenX`) · (5) output
`has_repo` non alimenté. Chaque mutation → `exit 1` ; `cp` backup → gate re-VERT.
**Câblage (garde `check-ci-integrity` INV-A/B vert).** Job `check-mobile-workflow`
ajouté à `ci.yml` (steps `bash ci/check_mobile_workflow.sh`) **et** à `gate.needs`.
`check_ci_integrity` reconnaît le nouveau `ci/*.sh` comme **câblé** (lancé par un job
du gate + il source `lib.sh`) → INV-A (gate.needs == tous jobs non-manuels) et INV-B
(tout `ci/*.sh` câblé) **restent verts**. `run_ci.sh` (dérivé de `gate.needs`, sans
liste en dur) l'inclut **automatiquement** → passage **32→33 jobs (8 gates statiques
+ 25 suites)**, zéro édition de `run_ci.sh` (#6, exactitude structurelle).
**Doc (traçabilité, pas de dérive).** `ci/README.md` : ligne §1 pour
`check-mobile-workflow`, sous-section §2 détaillée (4 invariants + les 5 mutations),
et nuance ajoutée à « Second workflow » (les **jobs** restent hors gate de merge, mais
la **structure du fichier** est désormais gatée). Convention [[ci-readme-table-detail-in-section2]]
respectée : ligne §1 courte, détail en §2. Les mentions historiques « 7 gates
re-verts » (§2, records de mutations passées) restent exactes en **passé** ; le nouveau
record dit **8ᵉ gate**.
**Vérifications.** `bash ci/check_mobile_workflow.sh` → VERT (4 invariants) ; 5
mutations → ROUGE ; `python3 yaml.safe_load` sur `ci.yml` → valide ; `check_ci_integrity`
→ VERT (câblage intègre) ; `./run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP**. **1 gate
ajouté (NON redondant : 1re couverture d'un fichier mutation-testé ungated · pas un
doublon #5) · 1 job CI câblé · 0 nouveau module · 0 chiffre inventé (#6) · 0 édition
de production hors CI · aucune commande VPS (#8) · aucun `git clean`.** <!-- ci-allow : mention de l'interdit, jamais exécuté -->
---
## Session 004112 · Currency du canal stakeholder `daily_reports` au jalon 33 jobs + réattestation indépendante → CLEAN · 0 édition de production
**Contexte + 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. La session `001109` (même
jour, plus tôt) a fait franchir au gate de merge le cap **32 → 33 jobs** (8ᵉ gate
statique `check-mobile-workflow`). Or le canal roadmap-facing `daily_reports/` s'arrêtait
au `2026-08-04` en affichant encore « **32 PASS** ». Les surfaces de dérive read-only
étant saturées (re-scan = redondant #5), la valeur honnête du jour est de **rendre le
canal stakeholder fidèle au point courant** — discipline [[two-logging-channels]] :
garder les deux canaux, chaque figure sourcée d'un artefact commité.
**Vérification préalable — pas de dérive présent-tense « 32 » résiduelle.** Balayage des
surfaces present-tense (`README.md`, `ci/README.md`) : **aucun** décompte de jobs figé en
dur (le nombre est **dérivé à l'exécution** par `run_ci.sh --list`, jamais retranscrit).
Les nombreux « 32 » des logs/daily_reports antérieurs sont des **snapshots datés** (vrais
à l'époque) → classe *historical-repro = KEEP* ([[prose-facts-vs-numeric-drift]]), on n'y
touche pas. Le « 7 gates statiques » de `ci/README.md` l.49 décrit l'état **avant** l'ajout
du 8ᵉ gate (narratif du mutation-test préalable) → exact en passé, KEEP.
**Livrable : `05_deliverables_mvp/daily_reports/2026-08-05.md`.** Snapshot stakeholder
consignant le jalon 33 jobs (= **8 gates statiques + 25 suites**) + réattestation. Chaque
chiffre **recomputé `python3` indépendamment** des artefacts commités (aucune valeur saisie
à la main · #6), tous concordants avec la table :
- `quality_report.json` : **24/24 modules == 100** · `coverage.ok=true` · ci==registry==24 · verdict `PASS`.
- `regression_run.json.totals` : **24 suites · 624 ran · 624 passed · 0/0/0** · verdict `PASS`.
- `acceptance_matrix.json` : **15/15 `status=in_repo`** · verdict `True` · **`ci_job` ×36** (niché `matrix[].modules[]`).
- Structure CI : `run_ci.sh --list` = **33 jobs = 8 statiques + 25 suites** · `ls ci/*.sh` (hors `lib.sh`) = **8**.
**Vérifications.** `./run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** (inchangé — livrable
prose, hors `check_artifacts`/`audit_4big`). Liens Markdown du rapport résolus depuis
`daily_reports/` : `../qa/…` (artefacts), `../../run_ci.sh`, `../../.gitea/…`, `../../ci/…`
`check_docs` VERT. **0 chiffre inventé (#6) · 0 édition de production · aucune commande
VPS (#8) · aucun `git clean`.** <!-- ci-allow : mention de l'interdit, jamais exécuté -->
---
## Session 011114 · Double sweep read-only sur les DEUX classes de dérive free-text ungated (docstring↔code des 22 générateurs · inventaire↔filesystem) → CLEAN · 0 édition de production · faux « nouveau finding » écarté (anti-invention #6)
**Contexte + 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
(8 sprints · 7 critères de succès ✅). Les deux sessions du jour ont déjà (a) ajouté le
8ᵉ gate statique `check-mobile-workflow` (`001109`, 32→33 jobs) et (b) mis le canal
stakeholder `daily_reports` au jalon 33 jobs avec réattestation des 4 chiffres (`004112`).
Les surfaces d'audit inter-artefacts / dérive gatée / attestation sont **saturées**
(re-scan = redondant #5). La valeur honnête restante : re-vérifier les **deux classes de
dérive free-text NON gatées** que la mémoire marque comme récurrentes/non-fermées, avant
d'envisager quoi que ce soit — discipline [[verify-uncovered-before-gating]] (prouver
l'état AVANT d'agir) + anti-invention #6.
**Sweep 1 — docstring↔code des 22 générateurs ([[docstring-vs-code-drift]], classe
RECURRING/not-closed).** Pour chacun des 22 `*_gen.py` de `05_deliverables_mvp/*` :
comparaison du **docstring/en-tête** (inputs annoncés · fichiers `out/` produits ·
fallbacks) au **code réel** (argparse · `open(...,"w")` / `json.dump` / `write_text` ·
branches de fallback). Résultat : **22/22 CLEAN** — chaque docstring décrit exactement les
sous-commandes, les inputs et les artefacts écrits. Spot-check manuel des deux générateurs
multi-sorties les plus risqués (au-delà de la lecture agent) :
- `demo/scenarios/demo_scenario_gen.py` — docstring l.20/l.32 annonce `run_sheet.json` +
`run_sheet.md` + `MANIFEST.json` → code écrit bien les 3 (l.197-199 JSON, l.203-204 `.md`). ✓
- `faisabilite/bancable/bancable_gen.py` — docstring `50_financier_bancable/{fr,en,es}.md`
→ écrits l.171-173. ✓
Aucune régression du type « fallback §5.3 fantôme » (publiciste) ni « output omis »
(demo run_sheet.md) qui avaient été corrigés antérieurement : la classe reste propre.
**Sweep 2 — inventaire `AGENTS_EXISTING_ASSETS.md` ↔ filesystem `/opt/oto`
([[inventory-vs-filesystem-drift]]).** Extraction de tous les chemins `/opt/oto/*` cités
(38 uniques), classification **SRC-OK / PYC-ONLY / MISS** (avec check `__pycache__`) :
- **8 PYC-ONLY** (`oto_agent_faisabilite`, `oto_orchestrateur_faisabilite`,
`oto_module_{etudes_faisabilite_real,execution_faisabilite,faisabilites_pages,faisabilites_viewer,mobile_api,plans_ifc}`)
**tous** déjà annotés « (compilé pyc) » dans le doc : convention interne **cohérente**,
0 dérive.
- **2 MISS** : `otoia/capabilities/chat.py` (absent vs CLAUDE.md §Architecture cible qui le
liste) et `config/projets_editor.py` (§13, « API GET/POST déjà en place » — sibling
`projets_config.json` présent, lui). **Vérification anti-invention #6 AVANT de flaguer :**
`grep -rn` interne → **les deux MISS sont DÉJÀ surfacés à Michel** par la session `133718`
du **2026-08-03** (log l.1245/1284/1289-1295 : claims VPS-externes / non-réfutables laissés
ouverts, chat.py ≠ le module chatbot-lead distinct). Donc **PAS un nouveau finding**
re-signaler serait redondant (#5). Le reste (containers Docker, Speckle, systemd, GSC) est
runtime, non réfutable depuis le dépôt → hors périmètre worker (#8). **SURFACE, don't
rewrite** respecté : 0 édition de l'inventaire (le fichier peut viser un runtime
container-side ; un « fix » unilatéral serait une invention).
**Conclusion honnête.** Les deux seules classes de dérive free-text ungated sont **stables
et propres** à ce jalon ; la dimension chiffres-README est densément gatée (`check_readme_claims`
= 27 claims / 16 modules + fiches). Rien à corriger, **aucun gate à ajouter** (ajouter serait
un doublon #5 ; par ailleurs un gate lisant `/opt/oto` serait non-portable — le runner Gitea
n'a pas ce filesystem, cf. [[ci-gate-verification-method]]). Session **read-only** volontaire,
dans la lignée des attestations `234104`/`004112`, mais sur un **axe distinct** (les 2 classes
free-text, pas les 4 chiffres stakeholder ni le cross-artefact).
**Vérifications.** `./run_ci.sh`**33 PASS · 0 FAIL · 0 SKIP** (inchangé — aucun fichier
gaté touché). **0 chiffre inventé (#6) · faux nouveau-finding écarté par grep interne · 0
édition de production · 0 gate ajouté (anti-redondance #5) · aucune commande VPS (#8) · aucun
`git clean`.** <!-- ci-allow : mention de l'interdit, jamais exécuté -->