diff --git a/05_activity_log/2026-08-12.md b/05_activity_log/2026-08-12.md index c2fa482..ac7a0a8 100644 --- a/05_activity_log/2026-08-12.md +++ b/05_activity_log/2026-08-12.md @@ -1,5 +1,27 @@ # Activity Log · 2026-08-12 · Claude Code DTP Worker +## Session `20260812_140156` — VÉRIF · nouvel axe FRAIS « mode d'arrondi (banquier / round-half-to-even) » balayé repo-wide → CLEAN teeth-prouvé, 0 défaut · replayable · sans fix · sans gate + +**État au démarrage.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** (baseline verte). `regression_run.json totals` (lu de l'artefact commité · #6) = **635 exécutés · 618 passés · 17 skippés · 0 échec** (24 suites vertes · PASS). `quality_report.json` = **PASS · 24 modules · min 100/100 · all PASS**. Séquence moteur V18 toujours **intégralement bloquée** en gouvernance (D-06 approbation audit = gate d'entrée · « NE PAS coder avant l'audit » · #6) → **aucun code moteur légitime**. Arbitrages produit D-01→D-08 en attente Michel (`OPEN_DECISIONS_REGISTER.md`). Canal stakeholder `daily_reports/2026-08-12.md` **à jour au HEAD `e15129b`** (grep-count 5 hashes 4ᵉ-vague = 10 hits) → rien à ré-émettre. + +**Chasse au défaut d'abord (angle jamais balayé en ~45 sweeps : le MODE D'ARRONDI).** Aucun des sweeps antérieurs (arithmétique dérivée, date/time, parsing money/percent, déterminisme hash/locale/TZ/ordre) n'avait attaqué la question « Python `round()` est round-half-to-**even** (banquier) — un site s'appuie-t-il implicitement sur round-half-**up** ? ». Un `.5` exact y renverrait une valeur qui diffère de l'attente naïve (`round(2.5)==2`, pas 3), byte-repro-aveugle si l'échantillon figé ne tombe pas sur la bande. Recensement des `round()` de production (hors `test`, hors `_round1`) = **8 sites** sur 4 modules : `finlib/gate.py:54,64,72,96` · `genlib/scorer.py:57,81` · `lib/parser.py:101` · `audit_4big/scoring.py:8` (docstring). + +**Classement des 8 sites (tous NON-DÉFAUT, teeth-prouvé) :** +- **`scorer.py:57` `round(20*filled/total)`** (axe Complétude) — SEUL site `round()`-sur-ratio dont l'immunité au verdict est **non-locale**. Teeth : `total=16` champs 🔴 → la bande `.5` **EST atteignable** (filled∈{2,6,10,14} → 2.5/7.5/12.5/17.5, banquier diffère de half-up de ±1 pt). **Mais verdict-immune** : `_statut` n'émet « complete » que si `not champs_manquants` ⟹ `filled==total` ⟹ `pts1 == round(20) == 20` **exact** ; l'arrondi banquier ne s'engage donc **jamais** sur le chemin décisionnel. Reproduit end-to-end : brief complet → completude=20/statut=complete ; masterplan vidé → completude=11, 7 champs manquants, statut=en_developpement (**jamais** complete). Le seul effet de l'arrondi = ±1 pt sur le **score partiel affiché** d'un brief **incomplet** — cosmétique, aucun `spec` ne définit half-up, découplé du verdict, épinglé byte-repro. **Non-défaut.** +- **`scorer.py:81`** (axe Anti-gap prix) — même famille, immunité par **inclusion** : une cellule manquante ⟹ `champs2 ⊆ champs_manquants` non vide ⟹ verdict ≠ complete, indépendamment de l'arrondi de `pts2` (même si `pts2` pouvait remonter à 20 avec `filled/total ≥ 0.975`, la clause `not champs_manquants` bloque). **Non-défaut.** +- **`gate.py:64,72,96`** (montants USD, `round(...,2)`) — arrondi **au cent** = montant métier canonique (un USD ne se paie pas au sous-cent). L'arrondi banquier au sous-cent est immatériel : `ok = paid+1e-9 >= required` compare des valeurs déjà en cents. **Non-défaut.** +- **`gate.py:54` `_round1`** (percents user-facing) — la classe « affichage arrondi ⟺ gate booléen » est **déjà FERMÉE** ce cycle (gardes `:105`/agrégat des fixes `85cd625`/`1992ee6` + notes `113134`). **Non-défaut** (déjà couvert). +- **`parser.py:101` `int(round(n))`** — parse la **quantité** de typologies (entier métier : pas de demi-unité) → bande `.5` sans signification. **Non-défaut** (domaine entier). +- **`audit_4big/scoring.py:8`** — **docstring** (formule §), pas du code ; scoring réel prouvé immune par `ea8458d` (score-au-seuil = quantité UNIQUE). **Non-défaut.** + +**Teeth du détecteur (prouvé mordant).** Confirmé au runtime que `round()` EST banquier (`round(2.5)=2 · round(3.5)=4 · round(0.5)=0`) — l'axe n'est pas un homme de paille ; ET que la bande `.5` est réellement atteignable sur `scorer.py:57`. Le CLEAN n'est donc pas un faux-vert : la propriété testée existe, elle est simplement **découplée du verdict** partout. + +**Pourquoi PAS un fix ni un gate ni une note in-situ (#5/#6).** Aucun défaut (8/8 non-défauts). Passer à `Decimal(ROUND_HALF_UP)` serait de la sur-ingénierie sur un effet cosmétique ±1 pt inatteignable au verdict, + casserait le déterminisme byte-repro. **Pas de note in-situ non plus** (contrairement à `rate()`/`_cond_documents`) : le trigger de ces notes était un Explore ayant *mal-classé* le locus — ici **aucun mis-flag**, et sur-annoter violerait `verify-uncovered`/#5. Comme les axes de déterminisme (`run-order`/`hash-seed`/`locale-tz`), c'est une **commande replayable**, occurrence-zéro, pas une matière à gate. + +**Impact d'artefact : ZÉRO.** Sweep en lecture seule (repro dans le module, aucun fichier tracké touché hors ce journal). `regression_run.json`/`quality_report.json` inchangés (635/618/17 · 24×100). + +**Vérif.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** (inchangé). **0 code moteur V18** (bloqué #6), **0 module de production touché**, **0 artefact autoritaire modifié/reconstruit**, **0 chiffre inventé** (#6 — tous lus des artefacts commités), **0 gate ajouté** (#5), **0 commande VPS** (#8), **0 API externe**. Fichiers : ce journal (+ mémoire agent `rounding-mode-bankers-sweep`, hors repo). + ## Session `20260812_130149` — VÉRIF · chasse au défaut sur axe FRAIS (date/time + parsing chaîne money/percent) → 3 candidats RÉFUTÉS comme non-défauts + 1 note anti-récurrence in-situ sur `rate()` (commentaire pur · 0 impact artefact) **État au démarrage.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** (baseline verte). `regression_run.json totals` (lu de l'artefact commité · #6) = **635 exécutés · 618 passés · 17 skippés · 0 échec** (PASS). `quality_report.json` = **PASS · 24 modules · min 100/100**. Séquence moteur V18 toujours **intégralement bloquée** en gouvernance (D-06 approbation audit = gate d'entrée · « NE PAS coder avant l'audit » · #6) → **aucun code moteur légitime**. Arbitrages produit D-01→D-08 en attente Michel (`OPEN_DECISIONS_REGISTER.md`, citations réalignées au HEAD par `4eb615b`). Canal stakeholder `daily_reports/2026-08-12.md` **à jour** (matrice 635, 4ᵉ vague · les commits `626c39d`→`4eb615b` sont vérif/currency à 0 impact matrice) → rien à ré-émettre.