[DTP-Worker 20260805_154314] SWEEP neuf indépendance LOCALE/TIMEZONE : les 21 générateurs build rejoués × 5 combos LANG/LC_ALL/TZ (C·UTC → de_DE·Kolkata → POSIX·Kiritimati) = 105 rejeux diff vs commité → CLEAN 0 dérive. 3e axe déterminisme après hash-seed (PYTHONHASHSEED) et forward-compat (-W error), même famille « le runner n'est pas ton poste », cause différente (locale/fuseau).

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) <noreply@anthropic.com>
This commit is contained in:
Claude Code DTP Worker
2026-08-05 15:55:28 +00:00
parent a39c05aeda
commit 731ff6b65d
2 changed files with 53 additions and 0 deletions
+52
View File
@@ -1,5 +1,57 @@
# Activity Log · 2026-08-05 · Claude Code DTP Worker # 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** ## 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 **Contexte + choix de tâche.** `./run_ci.sh` au démarrage : **33 PASS · 0 FAIL · 0 SKIP**, arbre
@@ -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** | | 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** | | 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 | | 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`) ### Ré-attestation du point courant (recompute indépendant ce jour, HEAD `f311a1b`)