"""Réutilisation des briques déjà livrées (workflow #5 · zéro duplication). La matrice d'acceptation ne redéfinit RIEN qui existe ailleurs : - `parse_ci` : parseur de `.gitea/workflows/ci.yml` de l'auditeur 4Big (`qa/audit_4big/q4lib/registry.py`) — la SEULE autorité sur les jobs de test réellement gated. On le réutilise pour DÉRIVER l'ensemble des modules-preuve (jamais une liste à la main) et prouver la couverture bijective. - `validate` : validateur JSON-Schema maison du Publiciste (draft-07, sous-ensemble) — la matrice est validée SANS pip, car le gate CI Gitea Actions tourne sans réseau (CLAUDE.md #2). - `audit_sprints` : la fenêtre de sprint de chaque module est LUE dans le registre de l'auditeur 4Big (`quality_spec.json`) — une seule source de vérité pour tout le mandat (anti-dérive). Import par manipulation de `sys.path` (idiome des modules voisins : `q4lib/deps.py`, `reglib/deps.py`) plutôt que duplication. """ from __future__ import annotations import json import os import sys _HERE = os.path.dirname(os.path.abspath(__file__)) # qa/acceptance/acclib → 05_deliverables_mvp _DELIVERABLES = os.path.normpath(os.path.join(_HERE, "..", "..", "..")) _PUB = os.path.join(_DELIVERABLES, "publiciste") _AUDIT = os.path.join(_DELIVERABLES, "qa", "audit_4big") for _p in (_PUB, _AUDIT): if _p not in sys.path: sys.path.insert(0, _p) from lib import validator # type: ignore # noqa: E402 from q4lib import registry # type: ignore # noqa: E402 validate = validator.validate parse_ci = registry.parse_ci # Racine des livrables, exposée aux autres modules acclib. DELIVERABLES_ROOT = _DELIVERABLES _AUDIT_SPEC = os.path.join(_AUDIT, "quality_spec.json") def audit_sprints() -> dict: """{chemin module -> sprint} tel que déclaré par le registre de l'auditeur 4Big. Une seule source de vérité (anti-dérive · #5) ; l'auditeur ne se référence pas lui-même — son sprint est complété par le spec (extra).""" with open(_AUDIT_SPEC, encoding="utf-8") as fh: spec = json.load(fh) return {m["path"]: m["sprint"] for m in spec["modules"]} def artifact_exists(rel_path: str) -> bool: """Vrai ssi l'artefact cité (chemin relatif à 05_deliverables_mvp) existe. Fait de disque pur — un artefact-preuve inexistant est un mensonge de couverture (#6).""" return os.path.exists(os.path.join(DELIVERABLES_ROOT, rel_path)) __all__ = [ "validate", "parse_ci", "audit_sprints", "artifact_exists", "DELIVERABLES_ROOT", ]