Files
Claude Code DTP Worker 9d30939db9
CI / Contraintes NON-NÉGOCIABLES (CLAUDE.md) (push) Has been cancelled
CI / Validation JSON (schémas Faisabilité) (push) Has been cancelled
CI / Qualité documentaire (liens + 4Big) (push) Has been cancelled
CI / Reproductibilité des artefacts out/ (build == commité) (push) Has been cancelled
CI / Fraîcheur matrice de régression (run == commité) (push) Has been cancelled
CI / Intégrité du câblage CI (gate agrège tout · gates statiques verrouillés) (push) Has been cancelled
CI / Intégrité des chiffres du README (valeur == artefact cité · (push) Has been cancelled
CI / Intégrité mobile-build.yml (gating portable · activation différée · (push) Has been cancelled
CI / Publiciste · parser + schéma + generator (unittest) (push) Has been cancelled
CI / RBAC · 50 rôles + schéma (unittest) (push) Has been cancelled
CI / Faisabilité · générateur 4 volets + round-trip (unittest) (push) Has been cancelled
CI / RBAC · fixtures ERPNext (Role + Custom DocPerm) (push) Has been cancelled
CI / RBAC · plan User Permission (row-level) (push) Has been cancelled
CI / RBAC · Role Profile (bundles par portail) (push) Has been cancelled
CI / RBAC · run-book d'application unifié (agrégat 3 volets) (push) Has been cancelled
CI / Faisabilité · dossier bancable trilingue FR/EN/ES (push) Has been cancelled
CI / CRM · workflow vente ERPNext (lead → CONFOTUR) (push) Has been cancelled
CI / CRM · DocType porteur OTO Dossier Vente (push) Has been cancelled
CI / CRM · barème commissions vendeurs (push) Has been cancelled
CI / CRM · Financement Bancaire (gate hypothécaire RD) (push) Has been cancelled
CI / Fiscal · e-CF DGII (Compupar) (push) Has been cancelled
CI / Frontend · Workspaces 5 portails rôle (push) Has been cancelled
CI / Legal · DocType CONFOTUR Application (push) Has been cancelled
CI / QA · Audit 5D conformité (push) Has been cancelled
CI / SEO · mots-clés trilingues + schema.org + hreflang (push) Has been cancelled
CI / Chat OTOIA · montage par portail (Custom Block) (push) Has been cancelled
CI / QA · Audit 4Big (95+/100 sur 100% deliverables) (push) Has been cancelled
CI / Démo · Scénarios (run-sheet P07 banquier / P05 client) (push) Has been cancelled
CI / QA · Matrice de régression exhaustive (Sprint 8) (push) Has been cancelled
CI / DevOps · Run-book de déploiement VPS unifié (Sprint 8) (push) Has been cancelled
CI / QA · Matrice d'acceptation / traçabilité MVP (Sprint 8) (push) Has been cancelled
CI / Mobile · config app Expo/EAS (navigation par rôle) (push) Has been cancelled
CI / PIE · manifest de dépendances (Annexe 12 · V10.1) (push) Has been cancelled
CI / E2E baseline Playwright (manuel) (push) Has been cancelled
Mobile Build (EAS) / Préflight config EAS + état secrets (push) Has been cancelled
CI / Gate qualité (agrégat) (push) Has been cancelled
Mobile Build (EAS) / EAS build iOS (App Store (push) Has been cancelled
Mobile Build (EAS) / EAS build Android (Play Store) (push) Has been cancelled
[DTP-Worker 20260805_161319] Auto exec · session 20260805_161319
2026-08-05 16:28:19 +00:00

113 lines
4.2 KiB
Python

"""Assemblage : plan déterministe (`build`) et matrice live (`run`).
Deux artefacts, deux natures :
build → PLAN (out/regression_plan.json) : recensement EXHAUSTIF et
DÉTERMINISTE des suites gated (chemin, jobs, gate, fichiers/méthodes
test_*). Aucun compteur de résultat → diffable, re-générable, commité.
Verdict PASS ssi couverture prouvée + chaque suite ≥ planchers.
run → MATRICE live : exécute réellement chaque suite et agrège les compteurs
(ran/passed/failures/errors/skipped) + verdict global. Aucun horodatage /
hôte / chemin absolu → deux `run` sont byte-identiques : l'artefact
`regression_run.json` EST commité et byte-gaté par `ci/check_regression.sh`
(voir .gitignore), c'est la sortie qui fait autorité sur « N tests verts ».
Aucune date/horodatage → build reproductible (gate CI stable)."""
from __future__ import annotations
import os
from typing import Any
from . import discovery, runner
from .deps import DELIVERABLES_ROOT
MATRIX_NAME = "OTO QA · Matrice de régression exhaustive"
def build_plan(spec: dict[str, Any]) -> dict[str, Any]:
"""Plan déterministe des suites gated (sans exécution)."""
suites = discovery.discover_suites(spec)
coverage = discovery.coverage_report(spec, suites)
th = spec["thresholds"]
min_files = th["min_test_files"]
min_methods = th["min_methods_per_suite"]
under = [
s["path"] for s in suites
if s["test_files"] < min_files or s["test_methods"] < min_methods
]
totals = {
"suites": len(suites),
"test_files": sum(s["test_files"] for s in suites),
"test_methods": sum(s["test_methods"] for s in suites),
"min_methods": min((s["test_methods"] for s in suites), default=0),
"under_threshold": len(under),
}
verdict = "PASS" if (coverage["ok"] and not under) else "FAIL"
return {
"matrix": MATRIX_NAME,
"version": spec["version"],
"reference_cadre": spec["reference_cadre"],
"self_module": spec["self_module"],
"thresholds": {
"min_test_files": min_files,
"min_methods_per_suite": min_methods,
},
"discover_cmd": list(spec["discover_cmd"]),
"coverage": coverage,
"suites": suites,
"under_threshold": under,
"totals": totals,
"verdict": verdict,
"notes": spec.get("notes", []),
}
def run_matrix(spec: dict[str, Any], *, python: str | None = None) -> dict[str, Any]:
"""Exécute réellement toutes les suites du plan et agrège les compteurs.
Byte-déterministe (aucun horodatage/hôte/chemin absolu ; suites lancées sous
`python -S` → oracle tiers optionnel `jsonschema` neutralisé, cf.
`runner.run_suite`) → l'artefact `regression_run.json` EST commité et
byte-gaté par `ci/check_regression.sh`, identique en local et sur le runner
Gitea pip-less."""
suites = discovery.discover_suites(spec)
discover_cmd = list(spec["discover_cmd"])
# `python3 -m unittest ...` → on retire le binaire, on garde les args.
cmd_args = discover_cmd[1:] if discover_cmd and discover_cmd[0].startswith("python") \
else discover_cmd
results: list[dict] = []
for s in suites:
abs_path = os.path.join(DELIVERABLES_ROOT, s["path"])
res = runner.run_suite(abs_path, python=python, discover_cmd=cmd_args)
results.append({
"id": s["id"],
"path": s["path"],
"expected_methods": s["test_methods"],
**res,
})
totals = {
"suites": len(results),
"green": sum(1 for r in results if r["ok"]),
"red": sum(1 for r in results if not r["ok"]),
"ran": sum(r["ran"] for r in results),
"passed": sum(r["passed"] for r in results),
"failures": sum(r["failures"] for r in results),
"errors": sum(r["errors"] for r in results),
"skipped": sum(r["skipped"] for r in results),
}
verdict = "PASS" if totals["red"] == 0 and totals["suites"] > 0 else "FAIL"
return {
"matrix": MATRIX_NAME,
"version": spec["version"],
"self_module": spec["self_module"],
"suites": results,
"totals": totals,
"verdict": verdict,
}