Files
Claude Code DTP Worker c06e15c058 [DTP-Worker] Sprint 5 · Générateur Audit 5D conformité (QA · roadmap L58)
Audit de second niveau : lit les hand-off out/ des livrables (workflow vente,
Dossier Vente, commissions, e-CF DGII, CONFOTUR) et vérifie 17 contrôles en
5 dimensions (D1 Traçabilité/ISA 500 · D2 AML-UAF/Ley 155-17 · D3 Fiscal
e-CF/Ley 32-23 · D4 Intégrité/IFRS · D5 Gouvernance-SoD/ISA 315).

Anti-invention #6 : paramètre réglementaire non confirmé → A_CONFIRMER (open
item assigné au métier), jamais fabriqué. Verdict PASS_WITH_OPEN_ITEMS (13 PASS,
0 FAIL, 4 à confirmer). Réutilise validateur Publiciste + RoleResolver CRM +
roles_targeting CONFOTUR (zéro duplication).

37 tests · 15 invariants · build déterministe · régression 341 tests verts.
Job CI qa-audit-5d-tests + gate.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-30 08:41:57 +00:00

54 lines
2.0 KiB
Python

"""Chargement des livrables audités (sortie `out/` des modules voisins).
L'audit 5D est un audit de SECOND NIVEAU : sa matière première est le hand-off
JSON déjà commité par chaque générateur. On ne relance pas les générateurs — on
lit leur produit tel qu'il sera importé côté VPS. Chaque artefact absent lève une
erreur explicite (un audit sur un livrable manquant serait mensonger).
"""
from __future__ import annotations
import json
import os
from typing import Any
_HERE = os.path.dirname(os.path.abspath(__file__))
_DELIVERABLES = os.path.normpath(os.path.join(_HERE, "..", "..", ".."))
# id logique → chemin relatif au dossier 05_deliverables_mvp
ARTIFACT_PATHS: dict[str, str] = {
"workflow": os.path.join("crm", "workflow_vente", "out", "workflow.json"),
"dossier": os.path.join("crm", "dossier_vente", "out",
"doctype_oto_dossier_vente.json"),
"commissions": os.path.join("crm", "commissions", "out",
"commission_plan.json"),
"ecf": os.path.join("fiscal", "ecf_dgii", "out", "ecf_plan.json"),
"confotur": os.path.join("legal", "confotur", "out",
"doctype_confotur_application.json"),
}
def _load(rel: str) -> Any:
path = os.path.join(_DELIVERABLES, rel)
if not os.path.exists(path):
raise FileNotFoundError(
f"Artefact audité introuvable : {rel} — le générateur amont doit "
f"avoir écrit son `out/` avant l'audit 5D (aucun audit à vide)."
)
with open(path, encoding="utf-8") as fh:
return json.load(fh)
def load_artifacts() -> dict[str, Any]:
"""Charge les 5 livrables. Le workflow est une liste ; on expose l'objet."""
raw = {aid: _load(rel) for aid, rel in ARTIFACT_PATHS.items()}
wf = raw["workflow"]
if not isinstance(wf, list) or not wf:
raise ValueError("workflow.json attendu = liste non vide de Workflow.")
raw["workflow"] = wf[0]
return raw
def known_ids() -> frozenset[str]:
return frozenset(ARTIFACT_PATHS)