From 3710253c02c4efd5ad8a36707e4db84ce03b9999 Mon Sep 17 00:00:00 2001 From: Claude Code DTP Worker Date: Thu, 6 Aug 2026 10:56:35 +0000 Subject: [PATCH] =?UTF-8?q?[DTP-Worker=2020260806=5F104533]=20FIX=20couver?= =?UTF-8?q?ture=20=C2=B7=20oracle=20orphelin=20brief.schema.json=20c=C3=A2?= =?UTF-8?q?bl=C3=A9=20=C3=A0=20un=20test=20=E2=86=92=20le=20SEUL=20des=202?= =?UTF-8?q?6=20*.schema.json=20non=20enforced?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constat: faisabilite/generator/brief.schema.json, documenté « Contrat d'entrée » et sibling de version/projets_master (tous deux test-enforced), n'était validé par AUCUN test — _validate_brief() ne garde que le code projet, jamais la forme complète du brief; un brief drifté hors contrat passait inaperçu. Fix (teeth): test_input_briefs_validate_against_brief_schema valide les 2 fixtures contre brief.schema.json via le validateur maison Publiciste (zéro-pip, toujours exécuté, pas de skip sous python -S). Conformité pré-vérifiée sous validateur maison ET oracle jsonschema. L'« incomplet » est conforme au sens schéma (null admis) — incomplet seulement au sens sémantique (prix→placeholders #6). Cascade régénérée (générateurs, jamais à la main #6): regression_plan/run/MANIFEST 16→17 · totaux 624→625 exécutés / 607→608 passés / 17 skippés · quality_report evidence 16→17. Prose gatée réalignée (le gate check-readme-claims a mordu): README module + fiches faisabilite/qa/erpnext_backend. Prose ungatée: GAP_ANALYSIS 16→17 + nouveau bloc daily_report (blocs currency antérieurs = snapshots datés, non réécrits). 0 gate ajouté (#5) · 0 chiffre à la main (#6) · 0 commande VPS (#8). run_ci.sh = 33 PASS · 0 FAIL · 0 SKIP. Co-Authored-By: Claude Opus 4.8 (1M context) --- 03_agents/erpnext_backend/AGENT.md | 2 +- 03_agents/faisabilite/AGENT.md | 2 +- 03_agents/qa/AGENT.md | 2 +- 05_activity_log/2026-08-06.md | 52 +++++++++++++++++++ 05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md | 2 +- .../daily_reports/2026-08-06.md | 31 +++++++++++ .../faisabilite/generator/README.md | 5 +- .../generator/tests/test_generator.py | 14 +++++ .../qa/audit_4big/out/quality_report.json | 4 +- .../qa/regression/out/MANIFEST.json | 2 +- .../qa/regression/out/regression_plan.json | 4 +- .../qa/regression/out/regression_run.json | 10 ++-- 12 files changed, 114 insertions(+), 16 deletions(-) diff --git a/03_agents/erpnext_backend/AGENT.md b/03_agents/erpnext_backend/AGENT.md index 8601ddf..de8a637 100644 --- a/03_agents/erpnext_backend/AGENT.md +++ b/03_agents/erpnext_backend/AGENT.md @@ -37,7 +37,7 @@ le VPS reçoit — jamais l'inverse. vente, le barème commissions, le DocType Dossier Vente et le plan e-CF **résolvent** leurs rôles depuis ce fichier, jamais un nom Frappe en dur. Total backend **RBAC 60 tests** (10 + 11 + 12 + 11 + 16) + **e-CF 39 tests**, tous gated dans le CI (matrice -de régression du repo : **624 tests · 24 suites** · verdict `PASS`, source +de régression du repo : **625 tests · 24 suites** · verdict `PASS`, source `qa/regression/out/regression_run.json` — jamais compté à la main · #6). ## Hand-off reçus (à appliquer sur le VPS, dans l'ordre) diff --git a/03_agents/faisabilite/AGENT.md b/03_agents/faisabilite/AGENT.md index 450d5b0..51905d5 100644 --- a/03_agents/faisabilite/AGENT.md +++ b/03_agents/faisabilite/AGENT.md @@ -19,7 +19,7 @@ les composants runtime OTOIA/VPS listés plus bas (`otoia/capabilities/…`, sys | Module | Sprint | Rôle | Entrée CLI | Job CI | Tests | |---|---|---|---|---|---| | [`TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md`](../../05_deliverables_mvp/faisabilite/TEMPLATE_FAISABILITE_CANONIQUE_v1.0.md) | 1 (roadmap L41-46) | **Template canonique v1.0** — contrat des 4 volets + champs obligatoires (§Livrable S1 ci-dessous) | — (doc contrat) | `check-docs` | — | -| [`generator/`](../../05_deliverables_mvp/faisabilite/generator/README.md) | 2 (roadmap L44) | **Générateur 4 volets** : `brief.json` → `data_room/PXX/` (template v1.0), round-trip via le parser Publiciste | `faisabilite_gen.py score\|scaffold\|generate\|batch` | `faisabilite-gen-tests` | 16 | +| [`generator/`](../../05_deliverables_mvp/faisabilite/generator/README.md) | 2 (roadmap L44) | **Générateur 4 volets** : `brief.json` → `data_room/PXX/` (template v1.0), round-trip via le parser Publiciste | `faisabilite_gen.py score\|scaffold\|generate\|batch` | `faisabilite-gen-tests` | 17 | | [`bancable/`](../../05_deliverables_mvp/faisabilite/bancable/README.md) | 3 (roadmap L46) | **Dossier bancable trilingue** : `brief.json` → `50_financier_bancable/{fr,en,es}.md` + manifest, figures sourcées verbatim + agrégats recalculés | `bancable_gen.py build\|validate` | `bancable-tests` | 22 | **Anti-invention (#6)** : `generator` et `bancable` ne **fabriquent aucun chiffre** — les figures diff --git a/03_agents/qa/AGENT.md b/03_agents/qa/AGENT.md index d49df62..6076719 100644 --- a/03_agents/qa/AGENT.md +++ b/03_agents/qa/AGENT.md @@ -32,7 +32,7 @@ périmètre — un auditeur ne s'audite jamais. **conformité** normative des hand-off. ## Verdict agrégé courant (source `qa/regression/out/regression_run.json`) -**24 suites gated · 624 tests · 607 passés · 0 échec · 0 erreur → verdict `PASS`.** +**24 suites gated · 625 tests · 608 passés · 0 échec · 0 erreur → verdict `PASS`.** Ce compte est **découvert automatiquement depuis le CI** (`q4lib.registry.parse_ci`, réutilisé sans duplication) — jamais compté à la main. Les **17 tests restants sont ignorés** (`skipped`) : ce sont les *oracles optionnels* diff --git a/05_activity_log/2026-08-06.md b/05_activity_log/2026-08-06.md index 435e35b..db06737 100644 --- a/05_activity_log/2026-08-06.md +++ b/05_activity_log/2026-08-06.md @@ -882,3 +882,55 @@ lecture-seule, occurrence-zéro, rejouable → **pas un gate** (#5), sibling de (#5), **0 chiffre saisi à la main** (#6 — `26`/`57` recomputés par balayage), **0 commande VPS** (#8). `./run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** (inchangé). Seules éditions : ce journal + mémoire `schema-oracle-teeth-audit` (+ pointeur `MEMORY.md`). + +--- + +## Session `20260806_104533` — FIX couverture · oracle orphelin `brief.schema.json` câblé à un test (le seul des 26 schémas non enforced) · +1 test · 4 artefacts régénérés · CI verte + +**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` livrée/gatée, `OPEN_DECISIONS_REGISTER.md` = 3 arbitrages +produit appartenant à Michel (non éditables worker). Plutôt qu'un énième sweep zéro-trouvaille, +recherche d'une **lacune de couverture réelle et corrigeable**. + +**Axe.** Câblage des 26 oracles `*.schema.json` aux tests (distinct du *teeth-audit* qui prouvait +la non-vacuité des schémas, et de la *closedness* : ici « le schéma valide-t-il réellement +quelque chose ? »). Balayage `grep -rl .schema.json --include='*.py'` sur tout le dépôt : +**25/26 schémas référencés par au moins un `.py`** ; **1 orphelin** → +`faisabilite/generator/brief.schema.json` (**0 référence** dans aucun `.py`). + +**Constat — orphelin authentique, pas by-design.** +- Le README du module documente `brief.schema.json` comme **« Contrat d'entrée »** (avec lien) et + ses deux siblings (`version.schema.json`, `projets_master.schema.json`) SONT test-enforced + (`test_version_json_validates_against_schema`, `test_full_pipeline_master_validates`). +- Le garde-fou runtime `faisabilite_gen.py::_validate_brief()` ne vérifie QUE le code `projet` + (`P01..P09`), **jamais** la forme complète du brief (masterplan/architecture/typologies…). +- Donc un brief drifté hors contrat (type erroné, clé renommée/droppée) passait **inaperçu** : + l'asymétrie vs les 2 siblings est le tell. + +**Correction (teeth, pas churn).** Ajout de `test_input_briefs_validate_against_brief_schema` +dans `tests/test_generator.py` : valide `brief_complete.json` **et** `brief_incomplete.json` contre +`brief.schema.json` via le **validateur maison Publiciste** (zéro-pip → toujours exécuté, **pas** de +skip sous `python -S`, donc `skipped` reste 17). Vérifié empiriquement AVANT d'écrire le test : les +deux fixtures conforment sous le validateur maison **ET** l'oracle `jsonschema` (`errs=[]` / OK). +L'« incomplet » est conforme au **sens schéma** (null/champ absent admis, seul `projet` requis) ; il +n'est « incomplet » qu'au **sens sémantique** (prix→placeholders/rétrogradation · anti-invention #6). + +**Cascade gatée régénérée** (générateurs, jamais à la main · #6) : +- `count_tests` (faits disque) → `regression_plan.json` : `faisabilite/generator` 16→**17**. +- `regression_gen.py build` + `run` → `regression_run.json` + `MANIFEST.json` : totaux + **624→625** exécutés · **607→608** passés · **17** skippés inchangés · 24/24 vertes · PASS byte-repro. +- `audit_4big_gen.py build` → `quality_report.json` : evidence « 16 méthodes test_* » → **17** (24/24 ≥95). + +**Prose gatée réalignée** (le gate `check-readme-claims` a mordu, comme prévu, sur 4 surfaces) : +README module (`16 tests`→`17`, + mention du contrat d'entrée), fiches +`03_agents/faisabilite/AGENT.md:22` (col Tests 16→17), `03_agents/qa/AGENT.md` (624/607→625/608), +`03_agents/erpnext_backend/AGENT.md` (624→625). **Prose ungatée present-tense réalignée** : +`GAP_ANALYSIS_SPRINT1.md` (16→17 tests). **Canal stakeholder** : nouveau bloc de session appendé à +`daily_reports/2026-08-06.md` (les 3 blocs de currency antérieurs = snapshots datés à leur HEAD, +**non réécrits** — leur 624/607 était juste à leur instant). + +**Portée / anti-churn.** **0 gate ajouté** (#5 — le gate `check-readme-claims` existant a suffi à +prouver la cohérence, il a mordu sur les 4 fiches/README stales) · **0 chiffre saisi à la main** +(#6 — tous recomputés par les générateurs) · **0 commande VPS** (#8). `./run_ci.sh` = +**33 PASS · 0 FAIL · 0 SKIP**. Fichiers touchés : 1 test (+1 méthode) · 4 artefacts régénérés · +5 surfaces prose · ce journal. diff --git a/05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md b/05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md index 4dc6a4e..53edb18 100644 --- a/05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md +++ b/05_deliverables_mvp/GAP_ANALYSIS_SPRINT1.md @@ -71,7 +71,7 @@ et la cible plancher **4-5 semaines**. - ✅ P01, P08, P09 : prix documentés dans `commercial.md`. - ⚠ **P02, P03, P05, P07 : « prix non défini » / « typologie non fournie »** — faisabilités hétérogènes, templates différents. - **Cause** : générations avec templates non versionnés / anciens. -- **À faire** : ~~template canonique v1.0~~ ✅ **livré S1** → ~~générateur 4 volets~~ ✅ **livré S2** (`faisabilite/generator/` : brief JSON → `data_room/PXX/` template v1.0 + scoring §7 + `version.json` ; **round-trip prouvé** vers le parser Publiciste ; 16 tests · job CI `faisabilite-gen-tests`) → régénération des 7 faisabilités réelles au même standard (S4 · VPS) → archives auto (S3) → trigger sur update template (S6 · VPS). +- **À faire** : ~~template canonique v1.0~~ ✅ **livré S1** → ~~générateur 4 volets~~ ✅ **livré S2** (`faisabilite/generator/` : brief JSON → `data_room/PXX/` template v1.0 + scoring §7 + `version.json` ; **round-trip prouvé** vers le parser Publiciste ; 17 tests · job CI `faisabilite-gen-tests`) → régénération des 7 faisabilités réelles au même standard (S4 · VPS) → archives auto (S3) → trigger sur update template (S6 · VPS). - **Sprint** : ✅ S1 (template + scaffold) · ✅ S2 (générateur 4 volets) → S4 (régénération batch données réelles) → S5 (validation 4Big). ### 3 · Rendu Agent — 🟡 Refactor (gain ~40 %) diff --git a/05_deliverables_mvp/daily_reports/2026-08-06.md b/05_deliverables_mvp/daily_reports/2026-08-06.md index d188efb..b8495d6 100644 --- a/05_deliverables_mvp/daily_reports/2026-08-06.md +++ b/05_deliverables_mvp/daily_reports/2026-08-06.md @@ -166,3 +166,34 @@ re-sweep de vérification. **0 artefact reconstruit**, **0 gate ajouté** (#5), saisi à la main** (#6 — `8`/`25`/`33`/`624`/`607`/`17` recomputés de `git ls-files` · `run_ci.sh` · `ci.yml` · `regression_run.json`), **aucune commande VPS** (#8). Seules éditions : cette section de currency + le journal `05_activity_log/`. + +--- + +## FIX couverture — oracle orphelin `brief.schema.json` câblé au test (session `104533`) + +**Édition de dépôt cette session : OUI (générateur de tests + 4 artefacts régénérés).** +Contrairement aux sessions de currency ci-dessus, cette session livre une **amélioration de +couverture réelle**, pas un sweep lecture-seule. + +**Constat.** `faisabilite/generator/brief.schema.json` — documenté comme **« Contrat d'entrée »** +dans le README du module et sibling des deux autres schémas faisabilité — était le **seul des 26 +oracles `*.schema.json` non câblé à un test** : `_validate_brief()` ne garde que le code `projet` +(`^P0[1-9]$`), jamais la forme complète du brief ; aucun test ne validait les fixtures contre le +schéma. Un brief drifté hors contrat (type erroné, clé renommée) passait donc inaperçu. + +**Correction.** Ajout de `test_input_briefs_validate_against_brief_schema` : valide +`brief_complete.json` **et** `brief_incomplete.json` contre `brief.schema.json` via le **validateur +maison Publiciste** (zéro-pip, toujours exécuté — pas de skip sous `python -S`). L'« incomplet » +est conforme au sens schéma (null/champ absent admis) ; il n'est « incomplet » qu'au sens +sémantique (prix→placeholders). Confirmé par les **deux** validateurs (maison + oracle `jsonschema`). + +| Chiffre | Avant | Après | Source régénérée | +|---|---|---|---| +| Tests `faisabilite/generator` | 16 | **17** | `count_tests` (disque) → `regression_plan.json` | +| Matrice de régression (exécutés) | 624 | **625** | `qa/regression/out/regression_run.json` (`totals`) | +| Matrice de régression (passés) | 607 | **608** | idem (17 skippés inchangés) | + +**Artefacts régénérés** (jamais édités à la main · #6) : `regression_plan.json`, +`regression_run.json`, `regression/out/MANIFEST.json`, `audit_4big/out/quality_report.json`. +**Prose gatée réalignée** : README module (`17 tests`), fiches `03_agents/{faisabilite,qa,erpnext_backend}`. +`run_ci.sh` = **33 PASS · 0 FAIL · 0 SKIP** · **0 gate ajouté** (#5) · **aucune commande VPS** (#8). diff --git a/05_deliverables_mvp/faisabilite/generator/README.md b/05_deliverables_mvp/faisabilite/generator/README.md index 0e19b4e..26107cc 100644 --- a/05_deliverables_mvp/faisabilite/generator/README.md +++ b/05_deliverables_mvp/faisabilite/generator/README.md @@ -93,8 +93,9 @@ Voir [`brief.schema.json`](./brief.schema.json). Les fixtures sont **synthétiqu python3 -m unittest discover -s tests -v ``` -16 tests `unittest` (stdlib pur, **zéro pip**) : scoring, rétrogradation, -paramètres canoniques, et **round-trip end-to-end** generator → parser Publiciste +17 tests `unittest` (stdlib pur, **zéro pip**) : scoring, rétrogradation, +paramètres canoniques, conformité des fixtures au **contrat d'entrée** +(`brief.schema.json`), et **round-trip end-to-end** generator → parser Publiciste → `projets_master.json` validé contre le schéma. Réutilise le parser + le validateur du Publiciste (aucune duplication · workflow #5). Un oracle `jsonschema` est activé en plus s'il est installé. diff --git a/05_deliverables_mvp/faisabilite/generator/tests/test_generator.py b/05_deliverables_mvp/faisabilite/generator/tests/test_generator.py index 5f5bedf..a1476d8 100644 --- a/05_deliverables_mvp/faisabilite/generator/tests/test_generator.py +++ b/05_deliverables_mvp/faisabilite/generator/tests/test_generator.py @@ -175,6 +175,20 @@ class RoundTripTest(unittest.TestCase): errs = pub_validator.validate(version, _schema("version.schema.json")) self.assertEqual(errs, [], f"version.json non conforme : {errs}") + def test_input_briefs_validate_against_brief_schema(self): + # `brief.schema.json` est le « Contrat d'entrée » documenté (README §Contrat + # d'entrée) : les deux fixtures DOIVENT s'y conformer. Le brief « incomplet » + # l'est au sens SÉMANTIQUE (prix absents → placeholders/rétrogradation), pas au + # sens SCHÉMA (le schéma admet null/champ absent, seul `projet` est requis). + # Sans ce test, le contrat d'entrée resterait un oracle orphelin : `_validate_brief` + # ne garde que le code `projet`, jamais la forme complète du brief. + with open(os.path.join(_GEN, "brief.schema.json"), encoding="utf-8") as fh: + brief_schema = json.load(fh) + _, pub_validator = _pub() + for name in ("brief_complete.json", "brief_incomplete.json"): + errs = pub_validator.validate(_brief(name), brief_schema) + self.assertEqual(errs, [], f"{name} viole brief.schema.json : {errs}") + def test_full_pipeline_master_validates(self): # Génère 2 projets → parcours build_master → projets_master.json conforme. for name in ("brief_complete.json", "brief_incomplete.json"): diff --git a/05_deliverables_mvp/qa/audit_4big/out/quality_report.json b/05_deliverables_mvp/qa/audit_4big/out/quality_report.json index 358d267..fc7e5ea 100644 --- a/05_deliverables_mvp/qa/audit_4big/out/quality_report.json +++ b/05_deliverables_mvp/qa/audit_4big/out/quality_report.json @@ -318,7 +318,7 @@ "criterion": "DOC", "weight": 20, "passed": true, - "evidence": "README.md (4797 octets)" + "evidence": "README.md (4870 octets)" }, { "criterion": "CONTRAT", @@ -330,7 +330,7 @@ "criterion": "TESTS", "weight": 25, "passed": true, - "evidence": "16 méthodes test_* dans 1 fichier(s) (seuil 8)" + "evidence": "17 méthodes test_* dans 1 fichier(s) (seuil 8)" }, { "criterion": "CLI", diff --git a/05_deliverables_mvp/qa/regression/out/MANIFEST.json b/05_deliverables_mvp/qa/regression/out/MANIFEST.json index dad96d8..5116fff 100644 --- a/05_deliverables_mvp/qa/regression/out/MANIFEST.json +++ b/05_deliverables_mvp/qa/regression/out/MANIFEST.json @@ -5,7 +5,7 @@ "version": "1.0", "verdict": "PASS", "suites": 24, - "test_methods": 624, + "test_methods": 625, "coverage_ok": true, "artifacts": [ "regression_plan.json" diff --git a/05_deliverables_mvp/qa/regression/out/regression_plan.json b/05_deliverables_mvp/qa/regression/out/regression_plan.json index f059e64..8931d91 100644 --- a/05_deliverables_mvp/qa/regression/out/regression_plan.json +++ b/05_deliverables_mvp/qa/regression/out/regression_plan.json @@ -112,7 +112,7 @@ "in_gate": true, "has_tests_dir": true, "test_files": 1, - "test_methods": 16 + "test_methods": 17 }, { "id": "fiscal.ecf_dgii", @@ -295,7 +295,7 @@ "totals": { "suites": 24, "test_files": 24, - "test_methods": 624, + "test_methods": 625, "min_methods": 10, "under_threshold": 0 }, diff --git a/05_deliverables_mvp/qa/regression/out/regression_run.json b/05_deliverables_mvp/qa/regression/out/regression_run.json index d0cb8b3..c59a823 100644 --- a/05_deliverables_mvp/qa/regression/out/regression_run.json +++ b/05_deliverables_mvp/qa/regression/out/regression_run.json @@ -90,9 +90,9 @@ { "id": "faisabilite.generator", "path": "faisabilite/generator", - "expected_methods": 16, - "ran": 16, - "passed": 15, + "expected_methods": 17, + "ran": 17, + "passed": 16, "failures": 0, "errors": 0, "skipped": 1, @@ -296,8 +296,8 @@ "suites": 24, "green": 24, "red": 0, - "ran": 624, - "passed": 607, + "ran": 625, + "passed": 608, "failures": 0, "errors": 0, "skipped": 17