1af5d01ccf
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
477 lines
33 KiB
Markdown
477 lines
33 KiB
Markdown
# Activity Log · 2026-08-03 · Claude Code DTP Worker
|
||
|
||
## Session 033642 · Sprint 5 P1 · Livrable FONCTIONNEL : workflow CI/CD Mobile `.gitea/workflows/mobile-build.yml` (build EAS iOS + Android)
|
||
|
||
**Contexte + choix de tâche.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**,
|
||
arbre propre. Michel : « commits fonctionnels, pas juste docs ». La roadmap est couverte
|
||
par des modules gatés+verts, mais `DIRECTIVE_MOBILE_STORES_20260803.md` (Sprint 5, actif)
|
||
liste explicitement en **P1 · CI/CD Mobile** la création de `.gitea/workflows/mobile-build.yml`
|
||
— classée **non-bloqueur** (« configurer sans token, activation quand Michel fournit »),
|
||
donc **in-périmètre worker** (fichier config versionné, aucune exécution VPS/stores #8).
|
||
Vérifié absent : `.gitea/workflows/` ne contenait que `ci.yml`. **Vraie tâche fonctionnelle
|
||
non faite** → exécutée.
|
||
|
||
**Livrable créé : `.gitea/workflows/mobile-build.yml`.**
|
||
- **Triggers** (conformes directive P1) : push `main` + tags `v*` (paths `mobile/**` +
|
||
le workflow) + `workflow_dispatch` (inputs `platform` all/ios/android, `profile`).
|
||
- **Jobs** : `preflight` (TOUJOURS vert · prouve la présence de la config EAS versionnée
|
||
`mobile/app_config/out/eas_build.json` + rapporte l'état des secrets, sans jamais les
|
||
logger) ; `build-ios` (App Store #32) + `build-android` (Play Store) → `eas build
|
||
--platform … --profile production --non-interactive` (directive P4).
|
||
- **Source de vérité** : les profils de build viennent de l'artefact versionné
|
||
`eas_build.json` (development/preview/production) — pas réinventés.
|
||
- **Code natif hors repo** : le code Expo vit dans un **autre dépôt Gitea**
|
||
(`/opt/oto/mobile/native/` · Expo 51→cible 54) ; cloné au run depuis la variable
|
||
`vars.MOBILE_NATIVE_REPO` — **jamais recopié ici**.
|
||
|
||
**Sûreté (activation différée · #6 zéro invention · #8).** Les jobs de build sont gardés
|
||
par `if: secrets.EAS_TOKEN != '' && vars.MOBILE_NATIVE_REPO != ''` → **SKIP** tant que
|
||
Michel n'a pas fourni token+repo (« Vrais bloqueurs » de la directive : EAS_TOKEN 2 min sur
|
||
expo.dev). Conséquence : ce workflow **ne rend JAMAIS le CI rouge** avant activation, et
|
||
`preflight` reste vert et informatif. Aucun credential fabriqué : token, repo natif,
|
||
appleId/ascAppId/serviceAccount restent des secrets/vars `a_confirmer` — cohérent avec les
|
||
champs `null · a_confirmer` du livrable mobile. Plateforme **Gitea Actions uniquement** (#2).
|
||
|
||
**Non-régression des gates (vérifié).** `check_ci_integrity.sh` n'inspecte QUE `ci.yml`
|
||
(chemin en dur `CI=".gitea/workflows/ci.yml"`) → le 2e workflow lui est invisible, aucun
|
||
job à ajouter à `gate.needs`. `guard_constraints.sh` vert (aucune URL/usage interdit ;
|
||
`actions/checkout@v4` déjà toléré via `ci.yml`). YAML valide (pyyaml).
|
||
|
||
**Consommateur régénéré (classe [[artifact-reproducibility-gate]]).** Ajout d'un pointeur
|
||
concis (paragraphe « CI/CD Mobile » + 1 ligne au tableau périmètre) dans
|
||
`mobile/app_config/README.md` → sa taille passe 4261→4917 octets, mesurée par le critère
|
||
**DOC** de l'audit 4Big. `check-artifacts` a viré ROUGE (dérive attendue) →
|
||
`audit_4big_gen.py build -o out` régénéré : **seule** la ligne `evidence "README.md (…octets)"`
|
||
change ; verdict inchangé **PASS · 22/22 modules ≥ 95**. Lien Markdown vérifié résolvant
|
||
(`../../../.gitea/workflows/mobile-build.yml`).
|
||
|
||
**Vérifications finales.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP**. **Zéro nouveau
|
||
module · zéro gate ajouté (#5)** · aucune commande VPS (#8).
|
||
Aucun `git clean` exécuté <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
|
||
## Session 020634 · Dérive ground-truth résiduelle : roadmap L18 (colonne « Existe déjà ») affirmait encore « Expo 54 » — corrigée → Expo 51 réel (#6)
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Focus mandat courant = Sprint 5 Mobile (`DIRECTIVE_MOBILE_STORES_20260803.md`). Le
|
||
module in-repo `mobile/app_config` est complet et vert (schéma + 12 invariants ·
|
||
comptes 5 onglets / 44 rôles / 3 langues / 13 `a_confirmer` vérifiés contre
|
||
`out/MANIFEST.json` · docstring/README cohérents). Les actions P1-P5 de la directive
|
||
visent l'app réelle `/opt/oto/mobile/native/` (**hors repo #8**, bloquées sur
|
||
EAS_TOKEN/credentials Michel). J'ai donc cherché une **dérive réelle in-repo** dans le
|
||
périmètre worker.
|
||
|
||
**Défaut RÉEL trouvé (prolonge la session 013634).** La session 013634 a corrigé la
|
||
fausse affirmation « Expo 54 **en place** » dans `AGENTS_EXISTING_ASSETS.md §8` + la
|
||
fiche `03_agents/mobile/AGENT.md`, en distinguant **runtime ACTUEL (51)** vs **cible de
|
||
rebuild S5 (54)**. Elle a **délibérément laissé la roadmap** — mais son raisonnement ne
|
||
visait que la **ligne 56** (Sprint 5 « **Rebuild Expo 54** » = la cible, décision P0 de
|
||
Michel, à ne pas trancher). Elle n'a **pas examiné la ligne 18** : la table « Gains
|
||
d'accélération identifiés », colonne « **Existe déjà** », qui disait
|
||
`modules RBAC + API + Expo 54`. Or « Existe déjà » = ce qui **existe déjà** (à
|
||
refactorer) : y écrire « Expo 54 » ré-affirme **exactement** la dérive « Expo 54 en
|
||
place » corrigée partout ailleurs — le runtime réel vérifié (`package.json`, session
|
||
013634 + directive audit 2026-08-03) est **Expo 51**, et 54 est la **cible de rebuild**
|
||
(colonne « Reste à faire » / Sprint 5 L56).
|
||
|
||
**Contradiction interne prouvée.** `03_agents/mobile/AGENT.md:88` **cite** cette ligne :
|
||
« État courant (**table roadmap L18**) : modules RBAC + API + **Expo 51** en place ». La
|
||
fiche affirmait donc que la L18 dit « Expo 51 » alors que la L18 disait « Expo 54 » — une
|
||
**citation en désaccord avec sa source**, introduite quand 013634 a corrigé la fiche sans
|
||
corriger la roadmap. Grep confirme : l'unique consommateur de la L18 est `AGENT.md:88` ;
|
||
le spec/MANIFEST mobile ancrent sur **l.56** (`roadmap_ref`/`expo_sdk_source`), jamais l.18.
|
||
|
||
**Correctif — chirurgical (1 ligne), fidèle, non-gaté vérifié AVANT édition.**
|
||
Roadmap L18 : `Existe déjà: … Expo 54` → `… Expo 51` (runtime réel), et
|
||
`Reste à faire: Builds + submit stores` → `Rebuild vers Expo 54 + builds + submit stores`
|
||
(rend la ligne honnête sur le travail restant, fidèle à Sprint 5 L56). Résout la
|
||
contradiction avec `AGENT.md:88` (qui devient exact). **Ligne 56 « Rebuild Expo 54 » NON
|
||
touchée** = la cible S5 / décision P0 de Michel, non tranchée.
|
||
|
||
**Sûreté (vérifiée AVANT édition).** Le gate Expo-SDK (`check_readme_claims.sh:7779-7794`,
|
||
ancrage roadmap INV-mobile) ancre via `re.search(r"Rebuild Expo (\d+)", roadmap)` → ne
|
||
lit **que** la ligne 56 ; le gate (d) ne scanne que `mobile/app_config/README.md`, jamais
|
||
la roadmap. La L18 était donc **ungated** pour ce « 54 ». Formulation « Rebuild **vers**
|
||
Expo 54 » choisie **exprès** pour ne PAS matcher le bigramme `Rebuild Expo` → l'ancre du
|
||
gate reste liée à la **L56** (pas de second littéral porteur, cf. `[[roadmap-anchor-gate]]`).
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (inchangé) ·
|
||
`grep 'Rebuild Expo' roadmap` = **1 seule occurrence, L56** (ancre intacte) ·
|
||
`git diff --stat` = 1 fichier, 1 insertion / 1 suppression. **Zéro nouveau module ·
|
||
zéro gate ajouté (#5) · aucune logique de prod ni de gate touchée** — pure correction de
|
||
dérive ground-truth sourcée, prolongeant [[mobile-runtime-actual-vs-rebuild-target]].
|
||
Aucune commande touchant au VPS (#8) · aucun `git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
## Session 013634 · Dérive ground-truth réelle : app mobile documentée « Expo 54 en place » alors que le runtime réel est **Expo 51** (upgrade 54 abandonné) — corrigée (#6)
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
La directive la plus récente (commit `85d2fa3`, aujourd'hui) —
|
||
`DIRECTIVE_MOBILE_STORES_20260803.md` — porte le Sprint 5 Mobile. J'ai cherché la
|
||
prochaine tâche prioritaire **non-complétée** qui soit **dans le périmètre worker**.
|
||
|
||
**Périmètre : l'essentiel de la directive Mobile est bloqué / hors-repo (#8).** Le
|
||
module de config mobile in-repo (`05_deliverables_mvp/mobile/app_config/`) est
|
||
**complet et vert** (schéma + 12 invariants · Expo SDK 54 = **cible de rebuild**
|
||
correctement ancrée à la roadmap S5). Les actions P1 (`mobile-build.yml` EAS), P2-P5
|
||
(features / assets binaires / submit stores) visent l'app réelle
|
||
`/opt/oto/mobile/native/` (**hors de ce dépôt**) et sont **bloquées** sur
|
||
EAS_TOKEN + credentials Apple/Google (attendus de Michel). Rien à construire ici.
|
||
|
||
**Défaut RÉEL trouvé (investigation read-only, aucune commande VPS).** La directive
|
||
elle-même (§« État actuel · audit 2026-08-03 ») déclare le runtime **Expo SDK 51.0.0**,
|
||
l'upgrade Expo 54 **abandonné le 2026-07-27**. Vérification indépendante du
|
||
`package.json` réel : `expo ~51.0.0` · `react 18.2.0` · `react-native 0.74.5` ·
|
||
`expo-router ~3.5.0` — et **même le backup `native.bak-upgrade54-*` est resté sur ~51**
|
||
(le bump 54 n'a jamais atterri). Or l'inventaire d'actifs
|
||
`AGENTS_EXISTING_ASSETS.md §8:63` affirmait « **Expo SDK 54 + React 19.1.0 + React
|
||
Native 0.81.5 (upgrade 2026-07)** » comme runtime **en place**, et la fiche
|
||
`03_agents/mobile/AGENT.md` recopiait ces versions (« Expo 54 en place »). C'est
|
||
**exactement la classe interdite** par CLAUDE.md (« Documenter code sans vérifier
|
||
existence courante ») + **#6** (« zéro invention · toujours vérifier sources ») :
|
||
un actif documenté comme existant qui ne correspond pas à l'existence réelle. Un
|
||
agent Mobile s'y fiant construirait sur une prémisse fausse (Expo 54 déjà en place).
|
||
|
||
**Correctif — chirurgical, sourcé, distinguant ACTUEL vs CIBLE-REBUILD.**
|
||
1. `AGENTS_EXISTING_ASSETS.md §8:63` : runtime **actuel** corrigé en Expo 51.0.0 /
|
||
React 18.2.0 / RN 0.74.5 / expo-router ~3.5.0 (vérifié `package.json`), avec note
|
||
« upgrade 54 abandonné 2026-07-27 · cible rebuild = 54 (roadmap S5) ».
|
||
2. `03_agents/mobile/AGENT.md` : 5 mentions de runtime-courant « Expo 54 / React
|
||
19.1.0 / RN 0.81.5 » corrigées en Expo 51 réel, **en préservant** la cible de
|
||
rebuild Sprint 5 = Expo 54 (titre, rôle, scope, table modules, état courant).
|
||
|
||
**Ce que je n'ai PAS touché (délibérément).** (a) La roadmap S5 « **Rebuild Expo 54** »
|
||
= la **cible** du rebuild, décision de Michel (directive P0 : « décision upgrade
|
||
51→54 » explicitement ouverte) — je ne tranche pas. (b) Le module `mobile/app_config`
|
||
(`expo_sdk_major: 54`) = la config **écrite pour ce rebuild-cible**, byte-gatée et
|
||
ancrée à la roadmap par `check_readme_claims.sh:7739` (artefact⇔MANIFEST⇔spec⇔roadmap⇔
|
||
README, gate (d) rejette tout « Expo N≠54 » dans son README) — **correcte telle
|
||
quelle**, non touchée. La distinction clé : **runtime ACTUEL (51)** ≠ **cible de
|
||
rebuild S5 (54)** ; l'inventaire d'actifs doit dire le réel, le module de config dit
|
||
la cible. Aucune contradiction — ils décrivent deux choses différentes.
|
||
|
||
**⚠️ SIGNAL À MICHEL (décision P0, non tranchée par moi).** La roadmap prescrit
|
||
« Rebuild Expo 54 » mais le runtime réel est Expo 51 et l'upgrade 54 a été abandonné
|
||
2026-07-27 sans atterrir (backup inclus). La directive P0 demande justement cette
|
||
décision (reprendre 54, ou rester sur 51 LTS). Tant que la roadmap n'est pas mise à
|
||
jour par Michel, le module de config reste — correctement — la cible 54. Signal
|
||
documenté ici (canal ungated), pas masqué, pas tranché unilatéralement.
|
||
|
||
**Sûreté (vérifiée AVANT édition).** Les littéraux de version `0.81.5`/`19.1.0`/
|
||
`18.2.0`/`0.74` n'apparaissent dans **aucun** gate (grep) ; `check_readme_claims.sh`
|
||
ne pinne ces fichiers que sur (l.239) un **compte d'agents** et (l.8071) l'**IP VPS +
|
||
noms Docker** — jamais la version Expo ; le gate Expo-SDK (l.7739) ne scanne que
|
||
`mobile/app_config/README.md`. Les mentions corrigées étaient donc **ungated** →
|
||
édition sûre, zéro gate affaibli.
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (inchangé). `git
|
||
status` = 2 fichiers (`AGENTS_EXISTING_ASSETS.md` + `03_agents/mobile/AGENT.md`).
|
||
**Zéro nouveau module · zéro gate ajouté (#5) · aucune logique de prod ni de gate
|
||
touchée** — pure correction de dérive ground-truth sourcée. Aucune commande touchant
|
||
au VPS (#8) · aucun `git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
## Session 010630 · Gate `constraints-guard` RED réparé (mandat signé Michel l.35) + contradiction inter-mandats signalée
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **29 PASS · 1 FAIL** — régression NEUVE du
|
||
gate depuis les commits de Michel de ce soir (`7e4456e`, `94ae143`, `9067313` ont
|
||
introduit 4 fichiers root-owned à la racine). Job en échec : `constraints-guard`.
|
||
|
||
**Cause racine.** `AUTORISATIONS_MICHEL_20260803.md:35`
|
||
« - Écriture dans `/var/www/html/static/` (assets publics) » <!-- ci-allow : citation du mandat, jamais un usage --> — une **autorisation
|
||
positive** (parmi 40 permissions filesystem) qui matche le terme interdit <!-- ci-allow -->
|
||
`/var/www/html/static/` **sans** marqueur de prohibition <!-- ci-allow --> (contrairement à la l.96
|
||
`❌ git clean` qui passe) ni `ci-allow`. Les 3 autres fichiers (`DIRECTIVE_*`) sont
|
||
propres. C'est **exactement la classe de faux-positif** que le garde prétend ignorer
|
||
(en-tête : « détecte l'USAGE… PAS sa simple mention ») — une mention en prose de
|
||
gouvernance, pas un usage dans du code exécutable.
|
||
|
||
**Pourquoi PAS d'édition du fichier fautif.** (1) Root-owned `root:root 644` — **non
|
||
éditable** par `otoclaude` (test `-w` négatif). (2) C'est un **document signé par
|
||
Michel que je n'ai pas créé** → principe « surface, don't overwrite ». La convention
|
||
`ci-allow` par ligne était donc inapplicable.
|
||
|
||
**Correctif — au niveau du garde (que je possède, `ci/`).** Ajout de
|
||
`AUTORISATIONS_*.md` et `DIRECTIVE_*.md` aux exclusions de `tracked_files()`, **même
|
||
catégorie** que les exclusions préexistantes (`ci/guard_constraints.sh` lui-même,
|
||
`.gitea/workflows/*.yml`) : documents contenant *nécessairement* les termes interdits
|
||
en tant que **texte de politique**. Robustesse durable : survit à un re-push du doc par
|
||
Michel (le fix vit dans MON `ci/`, pas dans le doc root).
|
||
|
||
**Détection vraie-positive PRÉSERVÉE (mutation-test).** Un `.sh` temporaire commité
|
||
avec les trois usages interdits littéraux (écriture chemin statique VPS, purge git,
|
||
URL GitHub) → le garde **mord les 3** (✗). L'usage réel vit dans `.sh`/`.py`/`.yml` (toujours scannés) ; seule
|
||
la prose de mandat est exclue. `CLAUDE.md` **reste scanné** (constitution ; sa prose
|
||
d'interdits passe via marqueurs). Aucun trou vers un usage forbidden dans du code.
|
||
|
||
**⚠️ CONTRADICTION INTER-MANDATS SIGNALÉE À MICHEL (à trancher par lui).**
|
||
`AUTORISATIONS l.35` autorise « Écriture dans `/var/www/html/static/` » <!-- ci-allow : citation, contradiction signalée --> alors que
|
||
**CLAUDE.md · Interdits absolus** l'interdit explicitement : « ❌ Écrire directement
|
||
dans `/var/www/html/static/` (use `/opt/oto/sites/static/`) » <!-- ci-allow : citation de l'interdit CLAUDE.md --> — car `/var/www/html/static`
|
||
est un **SYMLINK** dont la source à écrire est `/opt/oto/sites/static/` (cf. section VPS
|
||
de CLAUDE.md). La l.35 est donc vraisemblablement une **imprécision de rédaction** :
|
||
Michel veut autoriser le déploiement d'assets publics, qui passe correctement par
|
||
`/opt/oto/sites/static/`. **Recommandation** : corriger la l.35 en
|
||
`/opt/oto/sites/static/ (assets publics · source du symlink)`. Je ne masque pas ce
|
||
signal (documenté ici + `ci/README.md`) ; je ne le tranche pas non plus (décision
|
||
architecture → Michel).
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (rétabli).
|
||
`ci/README.md` §guard mis en cohérence (exclusions documentées + contradiction notée).
|
||
**Zéro nouveau module · zéro gate ajouté (#5)** — le garde n'est pas affaibli (mutation
|
||
7/7 RED sur usage code), il est corrigé d'un faux-positif conforme à sa propre
|
||
philosophie. Aucune commande touchant au VPS (#8) · aucun
|
||
`git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
|
||
|
||
## Session 000623 · Audit 2 surfaces d'intégrité inter-artefacts neuves + ouverture canal 2 du jour
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP** — gate vert,
|
||
arbre `git status` propre. Sprint 8 buffer en veille saturée : fiches 13/13 closes,
|
||
gates statiques 7/7 mordants (`7c79e43`), surface docstring-vs-CODE saturée hier sur
|
||
62 fichiers de production (`1c3bed3`) — **aucun code modifié depuis**, donc re-rejouer
|
||
ce sweep serait redondant (#5).
|
||
|
||
**Décision.** Ouvrir des **surfaces d'intégrité INTER-ARTEFACTS neuves** — jamais
|
||
couvertes par les sweeps antérieurs (docstrings, sorties générateurs, comptes README
|
||
gatés) — plutôt que re-scanner l'acquis. Deux surfaces auditées :
|
||
|
||
**1. Intégrité des chemins-preuve de la matrice de recette.** Confrontation des
|
||
`matrix[].artifacts[].path` de `acceptance_matrix.json` au système de fichiers réel.
|
||
Unique chemin : `GAP_ANALYSIS_SPRINT1.md` (S1).
|
||
- **Faux-positif de mauvaise base évité et documenté.** Un contrôle naïf depuis la
|
||
racine du repo rapporte un « MISMATCH » (artefact `exists=true`, introuvable). En
|
||
réalité les chemins sont **relatifs à `DELIVERABLES_ROOT`** (`05_deliverables_mvp/`),
|
||
où `05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md` **existe**. Vérifié via
|
||
`acclib/deps.py:109-114` (`artifact_exists` joint `DELIVERABLES_ROOT`).
|
||
- **Surface doublement protégée · ZÉRO gate ajouté (#5).** (a) `acceptance_gen.py:198`
|
||
**lève** au build si un artefact-preuve cité est absent sous `DELIVERABLES_ROOT` ;
|
||
(b) `acclib/builder.py:62` **recalcule `exists`** à chaque build → reproductibilité
|
||
byte-à-byte (`check_artifacts`) prouve **transitivement** la résolution du chemin.
|
||
- Garde-fou mémoire `acceptance-evidence-paths-deliverables-root` (classe de
|
||
faux-positif récurrent · lignée `otov7-platform-not-drift`).
|
||
|
||
**2. Résolution des `ci_job` recette → `gate.needs`.** Les **22** noms de jobs CI
|
||
cités dans `matrix[].modules[].ci_job` **résolvent tous** vers un job réel de
|
||
`gate.needs` (**30**) dans `.gitea/workflows/ci.yml` — **0 orphelin**. Transitivement
|
||
mono-sourcé (dérivé du manifeste) → pas de cross-gate (#5).
|
||
|
||
**Résultat.** **0 dérive** sur les 2 surfaces neuves. **Zéro fichier de production
|
||
modifié** (audit pur). Surfaces désormais connues comme transitivement gatées.
|
||
|
||
**Reporting canal 2.** Ouverture de `daily_reports/2026-08-03.md` (nouveau jour ; le
|
||
`2026-08-02` a été clos à 7 addenda). Chaque agrégat re-sourcé par recompute `python3`
|
||
indépendant contre l'artefact commité (anti-invention #6) : **22/22** qualité
|
||
(scores={100}, seuil 95) · **564/564** régression (22 suites, 0/0/0) · **15/15**
|
||
recette (`in_repo`, verdict `True`) · **13** fiches · `gate.needs` = **30**.
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (inchangé — audit +
|
||
reporting seuls, zéro logique). Recompute indépendant concordant sur les 4 dimensions.
|
||
Arbre propre avant édition. **Zéro nouveau module · zéro gate ajouté (#5) · aucune
|
||
logique de prod ni de gate touchée**. Aucune commande touchant au VPS (#8) · aucun
|
||
`git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
## Session 003624 · Dé-duplication doc : table §1 de `ci/README.md` (lisibilité 4Big + #5)
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Surfaces de dérive (docstrings, comptes README gatés, artefacts) saturées ; re-scanner
|
||
l'acquis serait redondant (#5). J'ai cherché un défaut de **qualité documentaire réel**
|
||
plutôt qu'une énième surface d'audit.
|
||
|
||
**Défaut trouvé.** La table récapitulative §1 de `ci/README.md` (« Ce que fait le
|
||
pipeline ») a 9 lignes. Huit sont des one-liners nets ; la ligne
|
||
`check-readme-claims` (l.23) était une **phrase-fleuve de 39 074 caractères
|
||
(~15 000 mots)** entassée dans une seule cellule de table — construite par accrétion
|
||
« **et** … **et** … » au fil de dizaines de sessions. Or le **§2 « Détail des
|
||
contrôles »** documente DÉJÀ chacune de ces surfaces, proprement et de façon
|
||
structurée, sur **1 410 lignes** (l.157-1567). La cellule géante était donc :
|
||
- **du doublon pur** de §2 → viole CLAUDE.md **#5** (« éliminer le vieux · JAMAIS
|
||
accumuler doublons ») ;
|
||
- un **défaut de lisibilité 4Big réel** : une table dont une cellule fait 400× la
|
||
taille des autres n'est plus une table.
|
||
|
||
**Correctif.** Ligne 23 remplacée par un one-liner de **914 caractères** cohérent avec
|
||
les 8 autres lignes : il résume l'intégrité chiffres+faits data-derived, énumère les
|
||
familles de surfaces couvertes, et **renvoie au §2** pour le détail exhaustif (qui
|
||
reste intact, mot pour mot). **Zéro perte d'information** — tout ce que la cellule
|
||
disait, §2 le dit déjà en mieux. Édition purement chirurgicale : `git diff --stat` =
|
||
`1 file changed, 1 insertion(+), 1 deletion(-)`.
|
||
|
||
**Sûreté du changement (vérifiée avant édition).** `check_readme_claims.sh` ne parse
|
||
**JAMAIS** `ci/README.md` comme source de claims gatés (unique occurrence l.8073 = un
|
||
commentaire) ; la cellule n'est donc **aucun** faux-négatif à protéger. La nouvelle
|
||
prose n'introduit **aucun lien Markdown** (rien à valider pour `check_docs`), **aucun
|
||
terme interdit** en usage (rien pour `guard_constraints`), **aucun JSON** ni artefact.
|
||
`ci/README.md` ∉ `05_deliverables_mvp/*.md` → hors du contrôle auto-score 4Big [SOFT].
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (inchangé). **Zéro
|
||
nouveau module · zéro gate ajouté (#5) · aucune logique de prod ni de gate touchée** —
|
||
pure amélioration doc. Aucune commande touchant au VPS (#8) · aucun
|
||
`git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
## Session 023638 · Dérive ground-truth Mobile résiduelle · `GAP_ANALYSIS_SPRINT1.md` (Expo 54 « Existe » → Expo 51 réel)
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Priorité recherchée : une tâche **fonctionnelle** (Michel · « commits fonctionnels, pas
|
||
juste docs ») dans le périmètre worker (repo seul · pas de VPS #8 · pas de nouveau
|
||
module). Constat : la roadmap est intégralement couverte par des modules gatés+verts ;
|
||
les DIRECTIVES fraîches (Mobile stores, PlanPoint) pointent surtout hors périmètre
|
||
(builds EAS, ERPNext prod, `/opt/oto/mobile/native/` = autre repo). La valeur restante
|
||
in-repo est l'**intégrité de la vérité-terrain** des livrables.
|
||
|
||
**Défaut trouvé (réel, anti-invention #6).** Le sweep Expo 51/54 des commits `94e9365`
|
||
(inventaire) et `642643f` (roadmap L18/L56) avait **manqué** `GAP_ANALYSIS_SPRINT1.md`,
|
||
qui affirmait encore l'upgrade **abandonné** comme le runtime **existant** :
|
||
- **L45** (tableau, colonne « Existe ») : `Moyenne (modules + Expo 54)` ;
|
||
- **L110** (§8 Mobile, « **Existe** ») : `Expo SDK 54 + RN 0.81.5`.
|
||
|
||
Or la vérité-terrain (fiche gatée `03_agents/mobile/AGENT.md` L59 « Expo SDK 51.0.0 ·
|
||
RN 0.74.5 · upgrade 54 tenté puis abandonné 2026-07-27 », vérifiée `package.json` ·
|
||
`DIRECTIVE_MOBILE_STORES` « Actif · Expo SDK 51.0.0 ») est **Expo 51 / RN 0.74.5
|
||
actuel**, l'Expo 54 étant la **cible de rebuild** (S5), pas l'existant. Classe
|
||
[[mobile-runtime-actual-vs-rebuild-target]] (« sweep EVERY 'en place' surface ») +
|
||
[[prose-facts-vs-numeric-drift]] (surface prose non gatée).
|
||
|
||
**Correctif (2 éditions chirurgicales, alignées sur roadmap L18).**
|
||
- L45 → `Moyenne (modules + Expo 51)` · colonne « À faire » → `Rebuild Expo 54 + builds
|
||
EAS + submit 2 stores` (existant=51, cible=54, comme roadmap L18) ;
|
||
- L110 → `Expo SDK 51 + RN 0.74.5 (runtime actuel · upgrade 54 tenté puis abandonné
|
||
2026-07-27)`.
|
||
- L112 « **À faire** : rebuild Expo 54 → submit 2 stores » déjà correct (54 = cible) —
|
||
intact.
|
||
|
||
**Sûreté du changement (vérifiée AVANT édition).** `check_readme_claims.sh` parse
|
||
`GAP_ANALYSIS_SPRINT1.md` UNIQUEMENT pour les **comptes d'agents** (l.237-244 :
|
||
« audit des N agents », « N des M agents », « Couverture N agents ») — **jamais** la
|
||
version Expo. La dérive corrigée est donc une **surface prose non gatée** ; l'édition
|
||
est **gate-neutre** (aucun claim gaté touché, aucun lien Markdown, aucun terme interdit,
|
||
aucun JSON). Les 4 mentions « Expo 54 » restantes du repo audit-vérifiées = toutes des
|
||
contextes **cible/futur** (`eas build (Expo 54)`, items acceptance `out_of_scope`), zéro
|
||
« Existe » résiduel.
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (inchangé). **Zéro
|
||
nouveau module · zéro gate ajouté (#5) · aucune logique de prod ni de gate touchée.**
|
||
Aucune commande touchant au VPS (#8) · aucun `git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
## Session 040643 · Dérive doc-vs-CODE Mobile · `app_config_gen.py` + README (« 4 fichiers » → 5, `store_listing.json` omis)
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Roadmap intégralement couverte par des modules gatés+verts ; priorité recherchée :
|
||
tâche **fonctionnelle** in-repo (Michel · « commits fonctionnels »), périmètre worker
|
||
(repo seul · pas de VPS #8 · pas de nouveau module #5). Le dernier livrable touché
|
||
(commit `af84b21`, workflow `mobile-build.yml`) a orienté l'audit vers le module Mobile
|
||
`05_deliverables_mvp/mobile/app_config`.
|
||
|
||
**Défaut trouvé (réel · classe [[docstring-vs-code-drift]], ungated).** Le générateur
|
||
`cmd_build` écrit **5** fichiers JSON (`app_config`, `eas_build`, `role_navigation`,
|
||
`store_listing`, `MANIFEST` — vérifié `app_config_gen.py:239-243`), mais **deux**
|
||
surfaces de doc décrivaient encore **4** — l'output `store_listing.json` (ajouté après
|
||
coup) y était omis :
|
||
- **`app_config_gen.py` l.20** (docstring, bloc « Sous-commandes ») : `build … -> écrit
|
||
les 4 fichiers ci-dessus` — alors que l'énumération **juste au-dessus** (l.11-17) liste
|
||
bien **5** fichiers, dont `store_listing.json` : incohérence **interne** au docstring,
|
||
off-by-one classique laissé par l'insertion tardive de la fiche store ;
|
||
- **`README.md` § Utilisation** : `# écrit out/{app_config,eas_build,role_navigation}.json
|
||
+ MANIFEST.json` — `store_listing.json` **absent** du glob, alors que la § « Sorties »
|
||
du même README le documente déjà comme sortie produite.
|
||
|
||
**Correctif (2 éditions chirurgicales, gate-neutres).**
|
||
- l.20 → `écrit les 5 fichiers ci-dessus` (aligné sur l'énumération l.11-17) ;
|
||
- README → `out/{app_config,eas_build,role_navigation,store_listing}.json + MANIFEST.json`.
|
||
- Sweep résiduel `grep « 4 fichiers » / « les 4 » / « role_navigation}.json » / « 3
|
||
fichiers »` sur `05_deliverables_mvp/mobile/` + `03_agents/mobile/` → **0** autre
|
||
occurrence stale. La § « Sorties » (5 items) et « Résultat courant » du README étaient
|
||
déjà correctes.
|
||
|
||
**Régénération du consommateur (obligatoire · [[artifact-reproducibility-gate]]).**
|
||
L'édition du README a fait dériver `qa/audit_4big/out/quality_report.json` (critère DOC :
|
||
évidence `README.md (4917 → 4931 octets)`). `python3 audit_4big_gen.py build` → verdict
|
||
**PASS · 22/22 modules ≥ 95 (min 100)** inchangé ; seul le byte-count évolue. `git diff`
|
||
du report = **1 insertion / 1 suppression** (l'octet-compte du README Mobile).
|
||
|
||
**Sûreté du changement.** Aucun claim numérique gaté touché (le « 5 » du docstring n'est
|
||
pas re-dérivé par un gate de compte ; le glob README n'est pas un lien Markdown → hors
|
||
`check_docs`) ; aucun terme interdit ; aucune logique de prod ni de gate modifiée.
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP**. **Zéro nouveau module ·
|
||
zéro gate ajouté (#5)** — pure correction de vérité-terrain doc-vs-CODE. Aucune commande
|
||
touchant au VPS (#8) · aucun `git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
## Session 043644 · Sprint 5/8 · Canal 2 `daily_reports/` remis à jour (2 livrables du jour manquants)
|
||
|
||
**Contexte.** `./run_ci.sh` au démarrage : **30 PASS · 0 FAIL · 0 SKIP**, arbre propre.
|
||
Roadmap 1→8 intégralement livrée côté repo + gatée verte (22/22 qualité · 569/569
|
||
régression · 15/15 recette). Pas de module à créer (#5 interdit l'invention). Périmètre
|
||
worker (repo seul · pas de VPS #8). Audit du canal stakeholder
|
||
`daily_reports/2026-08-03.md`.
|
||
|
||
**Constat (dérive de couverture, réelle).** Le canal 2 (instantané stakeholder du jour ·
|
||
contrat roadmap « Rapports quotidiens ») s'arrêtait à l'addendum session `030641` (fiche
|
||
store). Les **deux livrables du jour les plus significatifs manquaient** au snapshot :
|
||
- session `033642` — **Sprint 5 P1 · workflow CI/CD Mobile `mobile-build.yml`** (commit
|
||
`af84b21`) : un vrai livrable fonctionnel de la roadmap, absent du snapshot ;
|
||
- session `040643` — fix dérive doc-vs-CODE Mobile (`cmd_build` 5 fichiers · commit
|
||
`953e683`).
|
||
Classe [[two-logging-channels]] : le canal daily_reports (snapshot roadmap) doit rester
|
||
courant, distinct de l'activity_log per-session.
|
||
|
||
**Réalisé.** Deux addenda ajoutés à `daily_reports/2026-08-03.md`, 100 % sourcés :
|
||
- addendum `033642` : workflow `mobile-build.yml` (3 jobs `preflight`/`build-ios`/
|
||
`build-android` · gardes `if secrets.EAS_TOKEN != '' && vars.MOBILE_NATIVE_REPO != ''`
|
||
→ SKIP-safe, CI jamais rouge avant activation Michel · profils EAS de `eas_build.json`
|
||
source de vérité · Gitea-only #2) ;
|
||
- addendum `040643` : réalignement docstring/README 4→5 fichiers + consommateur
|
||
`quality_report.json` régénéré (README Mobile 4917→4931 o · verdict PASS 22/22 inchangé) ;
|
||
- table « État launch-readiness · fin de journée » (chiffres re-vérifiés d'artefacts).
|
||
|
||
**Chiffres re-dérivés (aucun saisi à la main).** `regression_run.json.totals` = 22 suites ·
|
||
**569 ran · 569 passed · 0/0/0** · `quality_report.json` verdict **PASS · 22 modules** ·
|
||
`acceptance_matrix.json` **15/15 in_repo** · README Mobile **4931 octets** (`wc -c`) ·
|
||
workflow **3 jobs** (`grep`). Tous concordants.
|
||
|
||
**Sûreté du changement.** `daily_reports/` n'est ni un artefact `out/` byte-gaté ni un
|
||
doc d'entrée de `check_readme_claims` (surfaces gatées = README/AGENT.md, pas les
|
||
rapports quotidiens) → édition **gate-neutre**. Aucun claim numérique gaté touché ·
|
||
aucun terme interdit · aucune logique de prod ni de gate modifiée · zéro nouveau module ·
|
||
zéro gate ajouté (#5).
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP**. Aucune commande touchant
|
||
au VPS (#8) · aucun `git clean` <!-- ci-allow : mention de l'interdit absolu, jamais exécuté -->.
|
||
|
||
---
|
||
|
||
## Session `20260803_050654` · doc DevOps — `ci/README.md` complété : second workflow `mobile-build.yml`
|
||
|
||
**Sweep de vérité d'abord (aucune dérive trouvée sur les axes usuels).** Balayage
|
||
docstring-vs-CODE / README-vs-CODE des **20** générateurs (`*_gen.py` + `lib/generator.py`)
|
||
→ **CLEAN** (chaque docstring/README concorde avec les fichiers réellement écrits ;
|
||
la dérive `4→5 cmd_build` de la veille était le dernier cas). Ancres roadmap de
|
||
`acceptance_matrix.json` (33/39/46/52/58/64/70/76 + 81-87) re-vérifiées contre le fichier
|
||
roadmap → exactes. Câblage `gate.needs` (30 entrées) == miroir `run_ci.sh` → concordant.
|
||
Chiffres du daily report re-dérivés d'artefacts : `regression_run.json.totals` **569/569 ·
|
||
0/0/0**, `quality_report.json` **PASS · 22 modules**, `acceptance_matrix.json` **15/15
|
||
in_repo** → tous exacts.
|
||
|
||
**Gap réel corrigé (complétude doc, classe `prose-facts-vs-numeric-drift`).** Depuis
|
||
l'ajout de `.gitea/workflows/mobile-build.yml` (commit `af84b21`), le dépôt possède
|
||
**deux** workflows Gitea Actions, mais le livrable CI/CD `ci/README.md` § 1 s'ouvrait sur
|
||
« Workflow : `ci.yml` » et ne mentionnait **jamais** le second — alors que `mobile-build.yml`
|
||
lui, pointe vers `ci/README.md` (« même runner · voir ci/README.md »). Référence à sens
|
||
unique → doc CI/CD incomplète pour un auditeur du dépôt.
|
||
|
||
**Correctif.** Nouvelle sous-section § 1 « Second workflow Gitea Actions — `mobile-build.yml`
|
||
(HORS gate de merge) » : explicite, **vérifié par construction**, que ce workflow
|
||
n'appartient pas au gate (`check-ci-integrity` ne verrouille que `ci.yml` via sa variable
|
||
`CI=` ; aucun job dans `gate.needs` ; `run_ci.sh` ne le rejoue pas), qu'il tourne sur le
|
||
**même runner**, et qu'il est **SKIP-safe** (jobs de build en SKIP tant que `EAS_TOKEN`
|
||
absent → CI jamais rouge). Liens relatifs ajoutés vers le workflow et le README du module
|
||
Mobile (résolus par `check_docs` relativement à `ci/`).
|
||
|
||
**Sûreté du changement.** Prose éditoriale **sans chiffre data-derived** (aucun compte de
|
||
jobs, aucune valeur gatée) → `check_readme_claims` neutre. Aucun terme interdit (#2 Gitea
|
||
only respecté) · aucun `out/*.json` touché → `check_artifacts` neutre · aucun nouveau
|
||
`ci/*.sh` ni assertion → `check_ci_integrity`/#5 neutres. Table § 1 inchangée (lignes
|
||
one-liner préservées ; détail placé en sous-section, cf. discipline `ci-readme` du dépôt).
|
||
|
||
**Vérifications.** `./run_ci.sh` → **30 PASS · 0 FAIL · 0 SKIP** (dont `check-docs` liens
|
||
OK · `check-readme-claims` vert). Aucune commande VPS (#8) · aucun `git clean` <!-- ci-allow : mention de l'interdit, jamais exécuté -->.
|