From 731ff6b65d8498044670600ed7ed283776e428d3 Mon Sep 17 00:00:00 2001 From: Claude Code DTP Worker Date: Wed, 5 Aug 2026 15:55:28 +0000 Subject: [PATCH] =?UTF-8?q?[DTP-Worker=2020260805=5F154314]=20SWEEP=20neuf?= =?UTF-8?q?=20ind=C3=A9pendance=20LOCALE/TIMEZONE=20:=20les=2021=20g=C3=A9?= =?UTF-8?q?n=C3=A9rateurs=20`build`=20rejou=C3=A9s=20=C3=97=205=20combos?= =?UTF-8?q?=20LANG/LC=5FALL/TZ=20(C=C2=B7UTC=20=E2=86=92=20de=5FDE=C2=B7Ko?= =?UTF-8?q?lkata=20=E2=86=92=20POSIX=C2=B7Kiritimati)=20=3D=20105=20rejeux?= =?UTF-8?q?=20diff=20vs=20commit=C3=A9=20=E2=86=92=20CLEAN=200=20d=C3=A9ri?= =?UTF-8?q?ve.=203e=20axe=20d=C3=A9terminisme=20apr=C3=A8s=20hash-seed=20(?= =?UTF-8?q?PYTHONHASHSEED)=20et=20forward-compat=20(-W=20error),=20m=C3=AA?= =?UTF-8?q?me=20famille=20=C2=AB=20le=20runner=20n'est=20pas=20ton=20poste?= =?UTF-8?q?=20=C2=BB,=20cause=20diff=C3=A9rente=20(locale/fuseau).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Honnêteté à 2 volets : TZ empiriquement exercé (5 fuseaux, zoneinfo présent) ; locale NON testable ici (seules C/C.utf8/POSIX installées → fr_FR/de_DE retombent en C par glibc) mais prouvée par AUDIT CODE (preuve définitive) : (a) 0 générateur n'appelle locale.setlocale → json/float reste '.' locale-indépendant par design Python, la source décimale-virgule n'existe pas ; (b) les 2 seuls lecteurs d'horloge (publiciste/lib/parser.py, faisabilite/generator/faisabilite_gen.py) n'ont AUCUN out/ commité + forcent timezone.utc (doublement TZ-safe) ; (c) regression_run.json sans champ horloge. Runner robuste sous toute locale/fuseau. 0 prod édité, 0 artefact rebuild, 0 gate ajouté (#5 · propriété re-jouable, pas une classe de dérive), 0 chiffre saisi (#6 · 21/105 dérivés de la boucle add_parser build), 0 VPS (#8). Audit fan-out docstring-vs-code + prose-vs-numérique = CLEAN au passage. run_ci 33 PASS. Éditions : activity_log + daily_reports (ligne Veille d'intégrité) + memory neuve. Co-Authored-By: Claude Opus 4.8 (1M context) --- 05_activity_log/2026-08-05.md | 52 +++++++++++++++++++ .../daily_reports/2026-08-05.md | 1 + 2 files changed, 53 insertions(+) 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`)