[DTP-Worker] hardening correctness · le critère CLI de l'audit 4Big (q4lib/criteria.py) détectait l'entrypoint __main__ par un littéral figé double-quoté → loupait silencieusement les gardes simple-quotées / « Yoda » / sans-espaces (toutes du Python valide) → sous-scorage CLI −20 pts d'un module sain (violation #6)
Même racine que le fix ASCII ac595d0 : une détection assume une graphie là où le langage admet plusieurs formes. Fix = regex de FORME (_MAIN_GUARD_RE : 2 styles de guillemets · ordre inversé · espacement libre) + teeth test_cli_detects_single_quoted_and_yoda_guards (3 fixtures, prouvé mordant : ancien littéral rend False sur les 3, nouvelle regex True). Robustesse pure : les 50 gardes du dépôt sont double-quotées et toujours matchées → aucun score ne bouge, quality_report.json byte-identique (audit_4big s'auto-exclut de son scoring). Cascade régression uniquement : 626/609 → 627/610 (nouveau test) + fiches qa/audit_4big 35→36 & agrégat & backend 626→627 re-dérivés (RED check_readme_claims). Sweep préalable : classe ASCII-vs-Unicode close au niveau CODE (générateurs+libs+gates shell tous ASCII-par-domaine sauf les 2 compteurs test déjà \w).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -217,3 +217,25 @@ Un lecteur (agent ou humain) du README — le doc le plus consulté — pouvait
|
||||
**Sûreté des gates (vérifiée AVANT édition).** `check_readme_claims` **exclut** `daily_reports/` de son scan (`:8239` `not f.startswith(f"{D}/daily_reports/")`) → chiffres non parsés. `check_docs` link-checke les `daily_reports/` mais la nouvelle section n'ajoute **aucun lien relatif** (uniquement des hashes de commit et chemins en code-spans, non link-checkés). `guard_constraints` : aucun URL/usage interdit (DCF/IRR/DSCR/LTV/LTC ≠ termes proscrits).
|
||||
|
||||
**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 reconstruit** (rapport actualisé depuis les artefacts, pas l'inverse), **0 gate ajouté** (#5). Aucune commande VPS (#8), aucune API externe. Fichiers : `05_deliverables_mvp/daily_reports/2026-08-11.md` (actualisation) + ce journal.
|
||||
|
||||
---
|
||||
|
||||
## Session `20260811_082825` — HARDENING correctness · le critère CLI de l'audit 4Big loupait les gardes `__main__` simple-quotées/Yoda (détection figée sur une graphie · même classe que le fix ASCII de `ac595d0`) — teeth ajoutée
|
||||
|
||||
**État au démarrage.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** (baseline verte). Séquence moteur V18 toujours **intégralement bloquée** en gouvernance (D-06 approbation de l'audit = gate d'entrée · D-07 formules DCF/IRR/VAN/DSCR/LTV/LTC absentes · D-08 Master Data Model · directive `:90-91` « NE PAS coder avant l'audit » · #6) — **aucun code moteur légitime**. Les bannières V18 des 4 modules-origine, le liage index et le fix `audit_4big` (session `072823`) sont clos. Les 2 nouvelles directives 08-10 (`OTO_3D_STUDIO`, `COMPTE_CLIENT_COURRIELS`) restent hors périmètre repo.
|
||||
|
||||
**Vérif d'abord : le fix ASCII (`ac595d0`) a-t-il un rayon de blast CODE complet ?** La session `072823` avait vérifié le rayon **données** (« un seul nom de test non-ASCII dans le dépôt → publiciste seul »), mais **pas** le rayon **code** (d'autres regex partagent-elles le même défaut char-class-ASCII-sur-contenu-accentué ?). Sweep mené : (a) toutes les regex Python génératrices/`*lib/` (hors `/out/`, `/tests/`) → **2 compteurs de test** seulement, **tous deux `\w`** (`criteria.py:18` + `reglib/discovery.py:23`), et `check_readme_claims` **réutilise** `discovery.count_tests` (mono-source, `:663`) ; (b) `registry.py:30` `_JOB_RE` `[A-Za-z0-9_-]` = **domaine ASCII** (noms de jobs YAML, jamais accentués) — non-défaut ; (c) toutes les char-class ASCII des **gates shell** (`ci/*.sh`) → **toutes sur tokens ASCII-par-domaine** (slugs de rôles/portails kebab-case · lettres e-NCF · abréviations critères en CAPS · IDs d'invariants) — **aucune** ne scanne de la prose accentée. **Classe ASCII-vs-Unicode CLOSE au niveau code** (extension du check données de `072823`). Figures de régression en prose également **à jour** (aucun `624`/`625`/`607`/`608` stale hors snapshots datés). Le candidat `crit_cli` quote-style (littéral `"__main__"` figé) : **all 50 gardes du dépôt sont double-quotées** → aucun mis-scorage courant.
|
||||
|
||||
**Défaut trouvé (classe #6 · robustesse de détection de l'outil d'audit lui-même · MÊME classe que le fix ASCII).** `q4lib/criteria.py:78` détectait l'entrypoint CLI par un **littéral figé** : `'__name__ == "__main__"' in src` — assume **une seule graphie**. Or `if __name__ == '__main__':` (**simple quote**), `if "__main__" == __name__:` (**« Yoda »**, opérandes inversés) et `if __name__=='__main__':` (**sans espaces**) sont tous du **Python valide** = un entrypoint réel. Le littéral les **loupe silencieusement** → le critère CLI échouerait sur un module sain (**−20 pts**, chute possible < 95), en violation du cœur anti-invention #6 de l'audit (« une note est recomputée à partir de faits vérifiables ») : le critère **sous-spécifie** ce qu'est un entrypoint valide. Exactement la même racine que le fix ASCII (`ac595d0`) : *une détection assume une forme syntaxique là où le langage en admet plusieurs.*
|
||||
|
||||
**Pourquoi c'est légitime et pas de la sur-défense (#5).** Distinction du « ne pas coder défensivement des cas non-occurrents » : ici ce n'est **pas un gate** ajouté pour un cas d'entrée improbable d'un module produit — c'est la **correction de la logique de détection d'un critère existant** de l'**outil d'enforcement #6** lui-même, dont le contrat est d'évaluer correctement **n'importe quel Python valide**. La robustesse aux deux styles de guillemets est **dans le contrat** de l'outil, pas de l'ornement. Précédent direct : le fix ASCII a été accepté sur des bases identiques (regex ne matchant pas des identifiants Python valides).
|
||||
|
||||
**Fix (chirurgical · regex de forme, pas de graphie · teeth).** `criteria.py` : nouveau `_MAIN_GUARD_RE = re.compile(r"__name__\s*==\s*['\"]__main__['\"]|['\"]__main__['\"]\s*==\s*__name__")` (deux styles de guillemets · ordre inversé · espacement libre) ; `crit_cli` passe de `'__name__ == "__main__"' in src` à `_MAIN_GUARD_RE.search(src)`. **+ teeth** : `test_cli_detects_single_quoted_and_yoda_guards` (3 fixtures : simple-quote · Yoda · sans-espaces) — **prouvé mordant** : sur l'ancien littéral les 3 rendent `False` (garde loupée) ; sur la regex les 3 rendent `True`. Aucun risque de faux positif nouveau (le motif exige la séquence complète `__name__ == "__main__"`, comme le littéral).
|
||||
|
||||
**Sortie inchangée (robustesse pure · #6 auto-vérifié).** Les 50 gardes du dépôt étant double-quotées et **toujours matchées** par la nouvelle regex, `crit_cli` rend un résultat **identique pour les 24 modules** → **`quality_report.json` byte-identique** (correctement NON régénéré : `audit_4big` **s'auto-exclut** de son propre scoring — les modules qa scorés sont `qa-audit-5d`/`qa-acceptance`/`qa-regression`, pas `audit_4big` ; même patron d'auto-exclusion que la régression). Le fix ne change **aucun score** — c'est une garantie de robustesse, pas une correction de note.
|
||||
|
||||
**Cascade d'artefacts (uniquement la matrice de régression · mémoire `artifact-reproducibility-gate`).** L'ajout du test augmente le décompte de la suite `audit_4big` : `regression_gen.py build` (plan) **puis** `run` (matrice) → `regression_run.json` **626 → 627 exécutés · 609 → 610 passés · 17 skippés · 0 échec** (le nouveau test). Surfaces de prose gatées re-dérivées (flaggées RED par `check_readme_claims`, corrigées) : fiche `03_agents/qa/AGENT.md` (colonne `audit_4big` **35 → 36** ← `count_tests` ; agrégat **626/609 → 627/610**) + `03_agents/erpnext_backend/AGENT.md:40` (claim live **626 → 627**). Le `daily_reports/2026-08-11` (snapshot signé) et les logs sont des instantanés datés → laissés (`two-logging-channels`).
|
||||
|
||||
**Pourquoi pas un nouveau gate (#5).** La divergence de compte est déjà **structurellement gatée** (`check_readme_claims` a immédiatement rougi la fiche QA + le compte `audit_4big`) et la teeth verrouille le comportement de `crit_cli`. Occurrence latente (0 garde simple-quotée aujourd'hui) mais correction de contrat de l'outil, pas un cas d'entrée produit → pas de gate additionnel.
|
||||
|
||||
**Vérif.** `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** rétabli après régénération. **0 code moteur V18** (bloqué #6), **0 commande VPS** (#8), **0 API externe**. Fichiers : `qa/audit_4big/q4lib/criteria.py` (regex) + `qa/audit_4big/tests/test_audit_4big.py` (teeth) + `qa/regression/out/{regression_plan,regression_run,MANIFEST}.json` + `03_agents/qa/AGENT.md` + `03_agents/erpnext_backend/AGENT.md` + ce journal. `quality_report.json` **non touché** (auto-exclusion prouvée).
|
||||
|
||||
Reference in New Issue
Block a user