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

16 KiB
Raw Blame History

Activity Log · 2026-08-05 · Claude Code DTP Worker

Session 014119 · Registre des décisions ouvertes — consolidation sourcée des arbitrages produit surfacés au fil de l'eau (Sprint 8 launch-readiness) → 1 livrable-doc neuf · 0 édition d'autorité

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. Les 6 dernières sessions (200738 08-03 → 011114 08-05) ont saturé l'audit read-only (inter-artefacts, dérive free-text, attestation stakeholder, 8ᵉ gate mobile). Reproduire une 7ᵉ passe read-only aurait été à faible valeur / redondant (#5). Valeur honnête distincte du jour : les items réellement ouverts (arbitrages de périmètre produit + dépendances runtime hors dépôt) sont éparpillés dans les journaux de session et n'existaient nulle part de façon consolidée et découvrable pour Michel — un vrai trou de launch-readiness Sprint 8. J'ai créé 05_deliverables_mvp/OPEN_DECISIONS_REGISTER.md : une punch-list unique, 100 % sourcée, qui regroupe (ne tranche pas, ne réécrit aucune source d'autorité).

Vérification indépendante de CHAQUE signal AVANT consolidation (anti-invention #6 · deux Explore parallèles + spot-check manuel). Aucun item repris de mémoire sans re-preuve :

  • D-01 PIE contratslegal/confotur : REAL. pie/manifest/pie_spec.json:24 attribue contrats (Promesa · Fideicomiso · HOA) à legal/confotur ; or ce module ne produit que le DocType demande CONFOTUR (legal/confotur/README.md:8-17). Incohérence interne confirmée : tous les autres downstreams sans générateur portent "module": null (pie_spec.json:22,27-30), contrats est le seul attribué à un module qui ne le génère pas. Arbitrage de périmètre.
  • D-02 Financement condition #4 WAG→audit IA : REAL. Directive ## PRÉCISION (DIRECTIVE_FINANCEMENT_..._20260803.md:275-279) supersede wag_validated_by par audit.decision=='APPROVED' signé ; le module ship encore l'ancienne couche (finlib/gate.py:142-145 + financement_spec.json:157). Dépend d'un agent auditeur hors dépôt.
  • D-03 chat.py absent / D-04 projets_editor.py absent : REAL, filesystem confirmé (ni .py ni .pyc sous /opt/oto), déjà surfacés session 20260803_133718 (2026-08-03.md:1245-1253) → registre = pointeur anti-doublon (#5), pas re-surfaçage.
  • D-05 bundle id mobile : soupçon INVALIDÉ → 🟢 VÉRIFIÉ-SANS-SUITE. Le renommage OTOV7→« OTO Enterprise OS » ne touche pas le bundle : bundleIdentifier/package quarantinés null · a_confirmer, découplés du nom d'app (mobile_spec.json, out/app_config.json). Consigné pour ne pas ré-ouvrir. Faux-positif écarté (#6).

Discipline. SURFACE, don't rewrite respecté : 0 édition de CLAUDE.md, d'une directive datée, ou d'un pie_spec.json/gate.py (les toucher serait invention de périmètre ou réécriture d'autorité). Le registre est un doc-pointeur volontairement non-gaté (chaque ligne cite sa source file:line, contenu 100 % dérivé — faible surface de dérive), au même titre que daily_reports.

Vérifications. ./run_ci.sh33 PASS · 0 FAIL · 0 SKIP (inchangé — aucun fichier gaté touché). 0 chiffre inventé (#6) · 1 faux-positif écarté (bundle id) · 4 signaux re-prouvés indépendamment avant consolidation · 0 édition d'autorité · aucune commande VPS (#8) · aucun git clean.

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.needsrun_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 234104secrets.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 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'outputspreflight 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.sh33 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 · 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.sh33 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 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.sh33 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.