diff --git a/05_activity_log/2026-08-05.md b/05_activity_log/2026-08-05.md index 08bc8bb..5e6d1bf 100644 --- a/05_activity_log/2026-08-05.md +++ b/05_activity_log/2026-08-05.md @@ -1,5 +1,57 @@ # Activity Log · 2026-08-05 · Claude Code DTP Worker +## Session 154314 · SWEEP neuf : indépendance LOCALE / TIMEZONE des artefacts `build` → **CLEAN** + +**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 in-repo (restes +S3/S5/S6 = refactor BIM / builds EAS / dépôts ONAPI / déploiement prod = **hors périmètre worker**, +#8). Un audit fan-out (Explore) docstring-vs-code + prose-vs-numérique sur les livrables → **CLEAN**, +0 drift présent. Le canal `daily_reports` est déjà courant (la ligne hash-seed `151312` a été ajoutée +par `a39c05a` lui-même). Choix d'un axe de **déterminisme absent de la mémoire et orthogonal** aux +deux précédents. + +**Constat — la fragilité ciblée.** Le sweep hash-seed (`151312`) a couvert `PYTHONHASHSEED` mais +**PAS** l'environnement **locale/timezone** du runner. `check_artifacts`/`check_regression` prouvent +la reproductibilité byte-à-byte, mais **une seule fois**, sous **le** `LANG`/`LC_ALL`/`TZ` que le +runner Gitea leur donne. Si un générateur formatait un nombre via `locale` (décimale-virgule sous +`de_DE`/`fr_FR`), triait des clés via `locale.strcoll`, ou embarquait un timestamp `localtime`, sa +sortie varierait d'un runner à l'autre : **VERT sur le poste dev, ROUGE sur un runner sous locale/TZ +différente** — faux-vert *forward-looking* orthogonal au hash-seed (ordre de hash) et au `-W error` +(API dépréciée). Même famille « le runner n'est pas ton poste », cause différente. + +**Méthode (lecture seule).** Réplique exacte de la boucle `check_artifacts` — pour chaque module +avec `out/`, le `.py` portant `add_parser("build")` est rejoué `build -o $tmp` puis `diff` vs commité +— mais sous **5 combos** `LANG`/`LC_ALL`/`TZ`/`LC_NUMERIC` : `C/UTC`, `en_US/America-New_York`, +`fr_FR/Europe-Paris`, `de_DE/Asia-Kolkata`, `POSIX/Pacific-Kiritimati`. **21 générateurs `build` +× 5 combos = 105 rejeux**. Tree resté propre (`git status --short` vide avant/après). + +**Résultat — CLEAN + preuve honnête à deux volets.** **0 dérive / 0 échec sur les 105 rejeux.** +Le volet **TZ est authentiquement exercé** (5 fuseaux, `zoneinfo` présent). Le volet **locale a une +limite empirique** — seules `C`/`C.utf8`/`POSIX` sont installées ici, donc `fr_FR`/`de_DE`/`en_US` +retombent en C locale par glibc : le cas décimale-virgule n'est pas *empiriquement* prouvé. Il l'est +en revanche **par audit du code**, qui est la preuve définitive : (a) **0 générateur** n'appelle +`locale.setlocale`/`import locale` → la sérialisation `json`/`float` reste `'.'` (locale-indépendante +par design Python, la source de risque décimale-virgule **n'existe pas dans le code**) ; (b) les +**2 seuls** lecteurs d'horloge murale du corpus — `publiciste/lib/parser.py:428` et +`faisabilite/generator/faisabilite_gen.py:51` — n'ont **aucun `out/` commité** (leur timestamp +`generated_at` n'est jamais un artefact gaté) **et** forcent tous deux `datetime.now(timezone.utc)` +(doublement TZ-safe) ; (c) `regression_run.json` ne porte **aucun champ horloge**. Conclusion : le +runner CI peut tourner sous **n'importe quelle locale/TZ**, `check_artifacts`/`check_regression` +restent VERTS. + +**Portée / anti-churn.** **0 fichier de production édité**, **0 artefact reconstruit** (aucun +`out/*.json` touché → pas de rebuild `quality_report`, cf. [[audit4big-rebuild-after-doc-edits]]), +**0 gate ajouté** (#5 — attester ≠ multiplier les gates ; propriété re-jouable via la commande, pas +une classe de dérive), **0 chiffre saisi à la main** (#6 — 21/105 dérivés de la boucle de découverte +`add_parser("build")`), **0 commande VPS** (#8 — 100 % local & lecture seule). Éditions : ce journal ++ 1 ligne dans la table « Veille d'intégrité » du canal stakeholder + 1 mémoire neuve +(*locale-tz-determinism-sweep*, sœur de [[hash-seed-determinism-sweep]] et +[[forward-compat-warnings-sweep]]). + +**Vérif.** `./run_ci.sh` après → **33 PASS · 0 FAIL · 0 SKIP** (aucun fichier gaté touché). + +--- + ## Session 151312 · SWEEP neuf : déterminisme sous hash-seed aléatoire des gates de reproductibilité → **CLEAN** **Contexte + choix de tâche.** `./run_ci.sh` au démarrage : **33 PASS · 0 FAIL · 0 SKIP**, arbre diff --git a/05_deliverables_mvp/daily_reports/2026-08-05.md b/05_deliverables_mvp/daily_reports/2026-08-05.md index ed900c0..7a7b36d 100644 --- a/05_deliverables_mvp/daily_reports/2026-08-05.md +++ b/05_deliverables_mvp/daily_reports/2026-08-05.md @@ -123,6 +123,7 @@ tables ci-dessus **recomputent à l'identique ce jour** (recompute `python3` ind | Docstring-vs-code | `48b19b9` (`134254`) | 26 modules (docstrings ↔ comportement réel du code) | **CLEAN** | | Forward-compat warnings | `f311a1b` (`141301`) | 25 suites de `gate.needs` rejouées sous `-W error` (Deprecation/Syntax/Pending/Resource) sous Python 3.10.12 | **CLEAN 25/25 · 624 tests · 0 warning latent** | | Déterminisme hash-seed | `151312` | Tous les générateurs `build` (57 artefacts) rejoués sous 5 `PYTHONHASHSEED` (`1/7/42/1000/random`) + `regression_run.json` sous 6 rejeux → `diff` vs commité | **CLEAN · 57 byte-identiques · 0 dépendance à l'ordre de hash** → gates `check_artifacts`/`check_regression` robustes au seed randomisé du runner | +| Indépendance locale / timezone | `154314` | 21 générateurs `build` × 5 combos `LANG`/`LC_ALL`/`TZ` (`C·UTC` → `de_DE·Kolkata` → `POSIX·Kiritimati`) = **105 rejeux** `diff` vs commité ; TZ empiriquement exercé (5 fuseaux) + audit code (0 `locale.setlocale` → `json` reste `'.'` ; 2 seuls lecteurs d'horloge sans `out/` commité et en `timezone.utc`) | **CLEAN · 0 dérive/105** → runner robuste sous toute locale/fuseau | ### Ré-attestation du point courant (recompute indépendant ce jour, HEAD `f311a1b`)