13 KiB
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).
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 unif:de job (^ if:). Le contextesecretsn'est pas exposé dansjobs.<id>.if(table d'availability GitHub Actions) → suract/Gitea il s'évaluerait vide → SKIP silencieux. C'est la régression234104verrouillée. - MOB-3 · activation différée (#6/#8) — chaque job de build (
run: eas build) est gaté surneeds.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 —
preflightdéclarehas_token/has_repo, chaqueneeds.preflight.outputs.<X>référencé est déclaré (0 dangling) et chaque output déclaré est alimenté par unecho …>>$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.
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 · verdictPASS.regression_run.json.totals: 24 suites · 624 ran · 624 passed · 0/0/0 · verdictPASS.acceptance_matrix.json: 15/15status=in_repo· verdictTrue·ci_job×36 (nichématrix[].modules[]).- Structure CI :
run_ci.sh --list= 33 jobs = 8 statiques + 25 suites ·ls ci/*.sh(horslib.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.
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 annoncerun_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— docstring50_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) etconfig/projets_editor.py(§13, « API GET/POST déjà en place » — siblingprojets_config.jsonprésent, lui). Vérification anti-invention #6 AVANT de flaguer :grep -rninterne → les deux MISS sont DÉJÀ surfacés à Michel par la session133718du 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.