# ============================================================================
# CI · OTO Enterprise OS DTP · Gitea Actions
# ----------------------------------------------------------------------------
# Gate qualité DevOps (roadmap Sprint 1 · GAP_ANALYSIS §7).
# Plateforme : Gitea Actions UNIQUEMENT (CLAUDE.md #2 · JAMAIS GitHub).
# Runner : act_runner enregistré sur le VPS avec le label « ubuntu-latest ».
#          Voir ci/README.md pour l'enregistrement du runner.
# Aucune dépendance réseau/marketplace externe hors actions/checkout.
# ============================================================================
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  workflow_dispatch:

jobs:
  constraints-guard:
    name: Contraintes NON-NÉGOCIABLES (CLAUDE.md)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: Guard des contraintes
        run: bash ci/guard_constraints.sh

  validate-json:
    name: Validation JSON (schémas Faisabilité)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Valider les JSON
        run: bash ci/validate_json.sh

  check-docs:
    name: Qualité documentaire (liens + 4Big)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Contrôle docs
        run: bash ci/check_docs.sh

  # --------------------------------------------------------------------------
  # Reproductibilité des artefacts (Sprint 8 · DevOps CI/CD). Prouve que chaque
  # `05_deliverables_mvp/**/out/*.json` versionné se régénère À L'IDENTIQUE
  # depuis son générateur `build`. Attrape la dérive silencieuse d'un artefact
  # qui auto-résout une valeur depuis un AUTRE module (ex. demo/scenarios lit
  # qa/audit_4big/coverage) et devient périmé quand la source grandit — dérive
  # qu'aucune suite `tests/` (qui teste des fonctions, pas le fichier commité)
  # n'attrape. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  check-artifacts:
    name: Reproductibilité des artefacts out/ (build == commité)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Contrôle reproductibilité artefacts
        run: bash ci/check_artifacts.sh

  # --------------------------------------------------------------------------
  # Fraîcheur de la matrice de régression (Sprint 8 · QA « Regression tests
  # exhaustifs »). Complète check-artifacts : ce dernier ne rejoue que `build`
  # et exclut les artefacts d'EXÉCUTION ; ce gate rejoue `run` et exige que le
  # `qa/regression/out/regression_run.json` commité (dont la doc dérive ses
  # totaux agrégés — suites · tests · verdict PASS — jamais figés en dur ici,
  # sous peine de se périmer) soit byte-identique au run frais. Rend
  # impossible la re-commission d'une matrice périmée (ex. dérive « demo 18→21 »)
  # ou rouge commitée verte. stdlib pur, zéro pip, ~5 s.
  # --------------------------------------------------------------------------
  check-regression:
    name: Fraîcheur matrice de régression (run == commité)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Contrôle fraîcheur matrice de régression
        run: bash ci/check_regression.sh

  # --------------------------------------------------------------------------
  # Intégrité du câblage CI (Sprint 8 buffer). Le job `gate` ci-dessous est le
  # SEUL verrou de merge : un check absent de son `needs:` ne bloque rien, même
  # rouge. Les couvertures existantes (audit_4big/registry · qa/regression/
  # discovery) ne prouvent l'appartenance au gate que des jobs de MODULE (ceux
  # portant un `working-directory:`). Ce gate ferme le trou côté gates STATIQUES
  # (les `ci/*.sh` sans working-directory) : il prouve, en lisant ci.yml, que
  # `gate.needs` == { tous les jobs } − { gate } − { jobs manuels workflow_dispatch }
  # (aucun oubli ni référence fantôme) et que chaque `ci/*.sh` du dépôt est lancé
  # par un job du gate. Même classe d'anti-dérive que INV4, appliquée au câblage.
  # stdlib pur (bash/awk/git), zéro réseau.
  # --------------------------------------------------------------------------
  check-ci-integrity:
    name: Intégrité du câblage CI (gate agrège tout · gates statiques verrouillés)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Contrôle intégrité du câblage CI
        run: bash ci/check_ci_integrity.sh

  # --------------------------------------------------------------------------
  # Intégrité des chiffres du README (Sprint 8 buffer · CLAUDE.md #6). Le README
  # est le point d'entrée du mandat et déclare que chaque chiffre de sa section
  # « État courant » est sourcé vers un artefact commité (« n'introduit aucune
  # donnée nouvelle »). Aucun gate ne l'enforçait : check-docs ne valide que les
  # LIENS, jamais la VALEUR des nombres. Ce gate RECOMPUTE chaque chiffre depuis
  # l'artefact cité (modules/verdict 4Big, suites régression, promesses/statuts/
  # verdict acceptance, nombre d'AGENT.md) et exige l'égalité avec ce qui est
  # écrit — un README qui se contredit avec sa propre source (ex. 21→22 modules
  # non répercuté) est un « vert trompeur ». stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  check-readme-claims:
    name: Intégrité des chiffres du README (valeur == artefact cité · #6)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Contrôle des chiffres du README
        run: bash ci/check_readme_claims.sh

  # --------------------------------------------------------------------------
  # Intégrité du SECOND workflow `mobile-build.yml` (Sprint 5 mobile · hors gate
  # de merge, mais AUCUN gate ne lintait sa structure : check-ci-integrity ne
  # verrouille que ci.yml, validate-json que le .json). Ce gate rend opposable le
  # correctif de portabilité 234104 (pas de `secrets.` en if: de job → SKIP
  # silencieux) + l'activation différée #6/#8 (builds gatés sur les outputs de
  # preflight). stdlib + awk pur, PyYAML best-effort. Détail : ci/README.md §2.
  # --------------------------------------------------------------------------
  check-mobile-workflow:
    name: Intégrité mobile-build.yml (gating portable · activation différée · #6/#8)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Contrôle structure mobile-build.yml
        run: bash ci/check_mobile_workflow.sh

  # --------------------------------------------------------------------------
  # Publiciste (Sprint 2) : parser faisabilité → projets_master.json + generator.
  # Tests unitaires stdlib pur (unittest) → aucune installation pip requise sur
  # le runner. L'oracle jsonschema est utilisé s'il est présent, sinon ignoré.
  # --------------------------------------------------------------------------
  publiciste-tests:
    name: Publiciste · parser + schéma + generator (unittest)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/publiciste
    steps:
      - uses: actions/checkout@v4
      - name: Tests unitaires Publiciste
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # RBAC 50 rôles (Sprint 2 · ERPNext Backend) : contrat rbac_50_roles.json vs
  # rbac.schema.json. Réutilise le validateur maison Publiciste (pas de pip).
  # --------------------------------------------------------------------------
  rbac-tests:
    name: RBAC · 50 rôles + schéma (unittest)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/rbac
    steps:
      - uses: actions/checkout@v4
      - name: Tests contrat RBAC
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur Faisabilité 4 volets (Sprint 2 · Faisabilité) : brief.json →
  # data_room/PXX/ (template v1.0). Le round-trip via le parser Publiciste est
  # testé ici (générateur → parser → schéma). stdlib pur, aucune install pip.
  # --------------------------------------------------------------------------
  faisabilite-gen-tests:
    name: Faisabilité · générateur 4 volets + round-trip (unittest)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/faisabilite/generator
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur Faisabilité
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur de fixtures ERPNext (Sprint 2 · ERPNext Backend) : le contrat
  # rbac_50_roles.json → fixtures Frappe `Role` + `Custom DocPerm`. Valide le
  # bundle contre fixtures.schema.json + invariants (50 rôles, séparation des
  # pouvoirs, round-trip fidèle au contrat). stdlib pur, aucune install pip.
  # --------------------------------------------------------------------------
  rbac-fixtures-tests:
    name: RBAC · fixtures ERPNext (Role + Custom DocPerm)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/rbac/fixtures_gen
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur de fixtures RBAC
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur de plan User Permission (Sprint 2 · ERPNext Backend) : le contrat
  # rbac_50_roles.json → plan row-level (scope_donnees → mécanisme Frappe natif +
  # template User Permission allow=Company pour la portée `entite`). Valide le
  # plan contre userperm.schema.json + invariants (couverture bijective des 50
  # rôles, template SSI `entite`, anti-invention utilisateur). stdlib pur.
  # --------------------------------------------------------------------------
  rbac-userperm-tests:
    name: RBAC · plan User Permission (row-level)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/rbac/userperm_gen
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur de plan User Permission
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur de Role Profile (Sprint 2 · ERPNext Backend) : le contrat
  # rbac_50_roles.json → un `Role Profile` ERPNext v15 natif par portail (bundle
  # de rôles assignable en un geste). Valide le bundle contre
  # roleprofile.schema.json + invariants (couverture bijective des 50 rôles, un
  # profil par portail, cohérence portail, anti-invention). stdlib pur.
  # --------------------------------------------------------------------------
  rbac-roleprofile-tests:
    name: RBAC · Role Profile (bundles par portail)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/rbac/roleprofile_gen
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur de Role Profile
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Agrégateur RBAC (Sprint 2 · ERPNext Backend) : recoud les 3 volets RBAC
  # (fixtures Role+DocPerm, plan User Permission, Role Profile) en un run-book
  # d'application VPS ordonné (SPEC §7) + un manifeste agrégé. Valide contre
  # apply_plan.schema.json + invariants (ordre + graphe de dépendances SPEC §7,
  # cohérence inter-volets, couverture bijective des 50 rôles). stdlib pur.
  # --------------------------------------------------------------------------
  rbac-applyplan-tests:
    name: RBAC · run-book d'application unifié (agrégat 3 volets)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/rbac/apply_plan
    steps:
      - uses: actions/checkout@v4
      - name: Tests agrégateur RBAC
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur de dossier bancable trilingue (Sprint 3 · Faisabilité) : le même
  # brief.json → data_room/PXX/50_financier_bancable/{fr,en,es}.md + manifest.json
  # (répertoire jusqu'ici vide qu'exige le Portail Bancables 4Big). Figures
  # sourcées verbatim + agrégats calculés de façon traçable (formule recoupée).
  # Valide le manifeste contre bancable.schema.json + invariants (3 langues,
  # bannière CONFIDENTIEL, anti-invention, recalcul des figures). stdlib pur.
  # --------------------------------------------------------------------------
  bancable-tests:
    name: Faisabilité · dossier bancable trilingue FR/EN/ES
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/faisabilite/bancable
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur bancable trilingue
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur de workflow vente ERPNext (Sprint 4 · CRM natif) : le contrat
  # pipeline workflow_vente_spec.json (lead → visite → devis → réservation →
  # contrat → CONFOTUR) → fixtures Frappe Workflow + Workflow State + Workflow
  # Action Master. Rôles résolus depuis rbac_50_roles.json (zéro duplication).
  # Valide le schéma de sortie + 9 invariants de graphe (monotonie doc_status,
  # atteignabilité, séparation des pouvoirs). stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  crm-workflow-vente-tests:
    name: CRM · workflow vente ERPNext (lead → CONFOTUR)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/crm/workflow_vente
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur workflow vente
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur du DocType porteur (Sprint 4 · CRM natif) : doctype_spec.json +
  # workflow_vente_spec.json → fixture Frappe `DocType` custom `OTO Dossier
  # Vente`, cible du Workflow `OTO Vente Pipeline`. Cross-cohérence workflow ↔
  # DocType : champ d'état + valeurs de statut + is_submittable + permissions
  # DÉDUITS du pipeline ; rôles résolus depuis rbac_50_roles.json (zéro
  # duplication). Valide le schéma de sortie + 12 invariants. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  crm-dossier-vente-tests:
    name: CRM · DocType porteur OTO Dossier Vente
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/crm/dossier_vente
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur DocType Dossier Vente
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Barème commissions vendeurs (Sprint 4 · ERPNext Backend « commissions
  # vendeurs auto »). Cross-cohérence barème ↔ workflow ↔ DocType ↔ RBAC : chaque
  # évènement paie sur un état SOUMIS, sur un champ Currency réel du Dossier
  # Vente, pour un rôle ventes résolu. Anti-invention (#6) : aucun taux fixé
  # (taux_pct null tant qu'à confirmer) ; calcul commission = base × taux
  # traçable. Valide le schéma de sortie + 10 invariants. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  crm-commissions-tests:
    name: CRM · barème commissions vendeurs
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/crm/commissions
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur barème commissions
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Financement Bancaire (Sprint 5 · CRM natif · roadmap L52 « workflow vente
  # end-to-end » · volet financement · DIRECTIVE_FINANCEMENT_BANCAIRE_COMPLET_
  # 20260803.md). Parcours hypothécaire immobilier RD : contrat banques/documents/
  # autorisations/sections + CŒUR MÉTIER du gate check 4 conditions (apport initial
  # 20/30 · documents validés WAG · autorisations signées · validation WAG). Anti-
  # invention (#6) : taux d'apport et rôles depuis le contrat + RBAC (jamais codés) ;
  # taux/LTV bancaires non énoncés = null a_confirmer. Exemple de gate CALCULÉ,
  # auditable. Schéma de sortie + 12 invariants. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  crm-financement-bancaire-tests:
    name: CRM · Financement Bancaire (gate hypothécaire RD)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/crm/financement_bancaire
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur Financement Bancaire
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Intégration e-CF DGII (Sprint 4 · ERPNext Backend « e-CF DGII intégration
  # (Compupar) »). Génère un plan de configuration de facturation électronique
  # dominicaine cross-cohérent : chaque émission se déclenche sur un état SOUMIS
  # du workflow, sur un champ Currency réel du Dossier Vente, par le rôle Compta
  # Fiscaliste eCF résolu. Anti-invention (#6) : RNC / ITBIS / TipoCambio /
  # endpoints Compupar restent null (a_confirmer) — jamais fabriqués ; composeur
  # d'e-NCF traçable (E+tipo(2)+seq(10)). Schéma de sortie + 12 invariants +
  # FormaPago Cardnet (#10). stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  fiscal-ecf-tests:
    name: Fiscal · e-CF DGII (Compupar)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/fiscal/ecf_dgii
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur e-CF DGII
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur de Workspaces ERPNext (Sprint 4 · Frontend Console « 5 portails
  # rôle »). Un `Workspace` natif v15 par portail métier (Ventes/Construction/
  # Achat/Compta/Direction) — le portail de landing par rôle du desk (#1 ERPNext
  # natif). Cross-cohérence Workspace ↔ RBAC : chaque lien/raccourci vise un
  # DocType présent dans les permissions_cibles du portail (anti-invention #6),
  # couverture exhaustive, rôles restreints dérivés du contrat, tokens de marque
  # repris de CLAUDE.md #4. Schéma de sortie + 12 invariants. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  frontend-portails-tests:
    name: Frontend · Workspaces 5 portails rôle
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/frontend/portails
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur de Workspaces
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Générateur du DocType `CONFOTUR Application` (Sprint 5 · ONAPI/Legal · roadmap
  # L55 « Refactor oto_module_confotur_application.py → dépôts automatiques »).
  # DocType custom porteur des dossiers d'incitation touristique CONFOTUR
  # (Ley 158-01, RD). Cross-cohérence DocType ↔ RBAC ↔ workflow : les permissions
  # SONT, mot pour mot, les permissions_cibles RBAC (rôles ventes-confotur /
  # legal-onapi / legal-directeur) ; le caractère soumissible en découle ;
  # `estado`/`dossier_vente` dérivent du workflow_vente ; aucun taux/loi/montant
  # CONFOTUR n'est fabriqué (#6). Schéma de sortie + 14 invariants. stdlib pur.
  # --------------------------------------------------------------------------
  legal-confotur-tests:
    name: Legal · DocType CONFOTUR Application
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/legal/confotur
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur CONFOTUR Application
        run: python3 -m unittest discover -s tests -v

  qa-audit-5d-tests:
    name: QA · Audit 5D conformité
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/qa/audit_5d
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur Audit 5D
        run: python3 -m unittest discover -s tests -v

  seo-tests:
    name: SEO · mots-clés trilingues + schema.org + hreflang
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/seo
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur SEO
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Chat OTOIA embarqué (Sprint 6 · ERPNext Backend · roadmap L63 « Chat OTOIA
  # embedded dans chaque portail »). Un `Custom Block` natif v15 (#1) par portail
  # métier, inséré dans le `content` du Workspace, + sa config runtime (persona
  # Amélie, langues seo, rôles autorisés, portée de connaissance). Cross-cohérence
  # Chat ↔ RBAC ↔ Workspaces : `roles_allowed`/`knowledge_scope` = surface RBAC
  # EXACTE du portail (mêmes valeurs que les Has Role des Workspaces) ; endpoint
  # OTOIA = null (a_confirmer · #6/#8). Schéma de sortie + 14 invariants. stdlib pur.
  # --------------------------------------------------------------------------
  chat-otoia-tests:
    name: Chat OTOIA · montage par portail (Custom Block)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/frontend/chat_otoia
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur Chat OTOIA
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Audit 4Big qualité (Sprint 7 · QA · roadmap L69 « Audit 4Big niveau 95+/100
  # sur 100% deliverables »). Audit de MÉTA-NIVEAU : note la qualité 4Big de TOUS
  # les livrables gated (documentation, contrat schema, couverture de tests, CLI
  # reproductible, intégrité du hand-off out/) et exige ≥ 95/100 sur chacun
  # (CLAUDE.md #5). Le périmètre « 100% » est PROUVÉ : le registre est recoupé
  # bijectivement avec les working-directory du CI (moins l'auditeur · SoD ISA
  # 315). Anti-invention (#6) : chaque note est RECALCULÉE depuis des faits du
  # dépôt, jamais saisie. Schéma de sortie + invariants. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  qa-audit-4big-tests:
    name: QA · Audit 4Big (95+/100 sur 100% deliverables)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/qa/audit_4big
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur Audit 4Big
        run: python3 -m unittest discover -s tests -v

  demo-scenario-tests:
    name: Démo · Scénarios (run-sheet P07 banquier / P05 client)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/demo/scenarios
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur Scénarios démo
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Matrice de régression exhaustive (Sprint 8 · QA · roadmap L74 « Regression
  # tests exhaustifs »). Harnais de MÉTA-NIVEAU : recense TOUTES les suites de
  # tests gated (dérivées du CI — zéro liste à la main · #5), prouve la
  # couverture (disque + gate), et fournit — via `run` — le compte agrégé
  # faisant autorité (« N tests verts »). Anti-invention (#6) : le plan ne
  # contient AUCUN compteur de résultat ; ceux-ci ne naissent qu'à l'exécution.
  # Ce job teste le harnais (parseur unittest, découverte, invariants) sans
  # ré-exécuter les suites (le gate le fait déjà, job par job). stdlib pur.
  # --------------------------------------------------------------------------
  qa-regression-tests:
    name: QA · Matrice de régression exhaustive (Sprint 8)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/qa/regression
    steps:
      - uses: actions/checkout@v4
      - name: Tests harnais de régression
        run: python3 -m unittest discover -s tests -v

  devops-deploy-runbook-tests:
    name: DevOps · Run-book de déploiement VPS unifié (Sprint 8)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/devops/deploy_runbook
    steps:
      - uses: actions/checkout@v4
      - name: Tests run-book de déploiement
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Matrice d'acceptation / traçabilité MVP (QA · Sprint 8 · buffer L75). Document
  # de RECETTE de méta-niveau : mappe chaque promesse roadmap (8 livrables de
  # sprint + 7 métriques succès MVP) vers sa preuve gated OU un hors-périmètre
  # sourcé. Périmètre PROUVÉ : modules-preuve dérivés du CI (parse_ci · #5) et
  # confrontés de façon BIJECTIVE à la réalité ; fenêtres de sprint lues dans le
  # registre 4Big (anti-dérive). Anti-invention (#6) : les nombres des énoncés
  # sont des citations verbatim de la roadmap. stdlib pur · zéro pip.
  # --------------------------------------------------------------------------
  qa-acceptance-tests:
    name: QA · Matrice d'acceptation / traçabilité MVP (Sprint 8)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/qa/acceptance
    steps:
      - uses: actions/checkout@v4
      - name: Tests matrice d'acceptation
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # Config app mobile (Sprint 5 · Mobile · roadmap L56-57 « Rebuild Expo 54 +
  # submit App Store #32 + Play Store »). Le worker ne BUILD ni ne SUBMIT
  # (VPS/stores · #8) : il génère la CONFIG versionnable de l'app compagnon,
  # surface mobile des 5 portails rôle. Cross-cohérence app ↔ RBAC : chaque
  # onglet est gated par la surface RBAC EXACTE du portail (mêmes rôles que les
  # Workspaces/Chat OTOIA) ; labels/icônes = portails_spec, langues = seo_spec,
  # thème = tokens #4, devises = #10. Anti-invention (#6) : bundleIdentifier /
  # package / projectId EAS / version / credentials restent null (a_confirmer).
  # Schéma de sortie + 12 invariants. stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  mobile-app-config-tests:
    name: Mobile · config app Expo/EAS (navigation par rôle)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/mobile/app_config
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur config app mobile
        run: python3 -m unittest discover -s tests -v

  # --------------------------------------------------------------------------
  # PIE · manifest de dépendances (Annexe 12 · V10.1 · directive Project Identity
  # Engine du 2026-08-03). La faisabilité = SSOT : ce module livre le P0 (schéma
  # Project Master Data + graphe faisabilité→livrables downstream, §88). Zéro
  # invention (#6) : contenu transcrit de la directive ; codes projets ancrés à
  # CLAUDE.md §Projets ; annexe/version verbatim dans la directive ; modules
  # downstream « gated » = répertoires de livrables réels (FS). Le worker n'écrit
  # PAS le storage VPS /opt/oto/data/pie/{code}/ (#8). Schéma + 10 invariants.
  # stdlib pur, zéro pip.
  # --------------------------------------------------------------------------
  pie-manifest-tests:
    name: PIE · manifest de dépendances (Annexe 12 · V10.1)
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: 05_deliverables_mvp/pie/manifest
    steps:
      - uses: actions/checkout@v4
      - name: Tests générateur manifest PIE
        run: python3 -m unittest discover -s tests -v

  gate:
    name: Gate qualité (agrégat)
    runs-on: ubuntu-latest
    needs: [constraints-guard, validate-json, check-docs, check-artifacts, check-regression, check-ci-integrity, check-readme-claims, check-mobile-workflow, publiciste-tests, rbac-tests, faisabilite-gen-tests, rbac-fixtures-tests, rbac-userperm-tests, rbac-roleprofile-tests, rbac-applyplan-tests, bancable-tests, crm-workflow-vente-tests, crm-dossier-vente-tests, crm-commissions-tests, crm-financement-bancaire-tests, fiscal-ecf-tests, frontend-portails-tests, legal-confotur-tests, qa-audit-5d-tests, seo-tests, chat-otoia-tests, qa-audit-4big-tests, demo-scenario-tests, qa-regression-tests, devops-deploy-runbook-tests, qa-acceptance-tests, mobile-app-config-tests, pie-manifest-tests]
    steps:
      - name: Résultat
        run: echo "✅ Gate qualité 4Big franchi — tous les checks verts."

  # --------------------------------------------------------------------------
  # E2E baseline (QA · Sprint 1). MANUEL uniquement (workflow_dispatch) : exige
  # un serveur live + navigateurs → hors du gate push/PR (checks statiques).
  # Cible via DTP_BASE_URL (variable/secret repo). Voir tests/README.md.
  # --------------------------------------------------------------------------
  e2e-baseline:
    name: E2E baseline Playwright (manuel)
    runs-on: ubuntu-latest
    if: github.event_name == 'workflow_dispatch'
    defaults:
      run:
        working-directory: tests
    env:
      CI: "true"
      DTP_BASE_URL: ${{ vars.DTP_BASE_URL }}
    steps:
      - uses: actions/checkout@v4
      - name: Installer dépendances + navigateurs
        run: |
          npm install
          npm run install:browsers
      - name: Lancer la baseline E2E
        run: npm test
      - name: Publier le rapport
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: tests/playwright-report/
