{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://oto-enterprise-os-dtp/qa/regression.schema.json",
  "title": "Plan de regression exhaustive genere depuis regression_spec.json + les faits du depot",
  "description": "Contrat de sortie du generateur regression_gen.py (sous-commande build). Recensement deterministe des suites de tests gated, sans compteur de resultat. Valide par le validateur maison Publiciste (zero pip) dans le job CI qa-regression-tests.",
  "type": "object",
  "additionalProperties": false,
  "required": ["matrix", "version", "reference_cadre", "self_module", "thresholds", "discover_cmd", "coverage", "suites", "under_threshold", "totals", "verdict", "notes"],
  "properties": {
    "matrix": { "type": "string", "const": "OTO QA · Matrice de régression exhaustive" },
    "version": { "type": "string", "pattern": "^[0-9]+\\.[0-9]+$" },
    "reference_cadre": { "type": "string", "minLength": 1 },
    "self_module": { "type": "string", "minLength": 1 },
    "thresholds": {
      "type": "object",
      "additionalProperties": false,
      "required": ["min_test_files", "min_methods_per_suite"],
      "properties": {
        "min_test_files": { "type": "integer", "minimum": 1 },
        "min_methods_per_suite": { "type": "integer", "minimum": 1 }
      }
    },
    "discover_cmd": {
      "type": "array",
      "minItems": 1,
      "items": { "type": "string", "minLength": 1 }
    },
    "coverage": {
      "type": "object",
      "additionalProperties": false,
      "required": ["ok", "suites_count", "gated_in_ci", "self_module_excluded", "self_module_gated", "missing_tests_dir", "not_in_gate", "orphan_tests_dirs"],
      "properties": {
        "ok": { "type": "boolean" },
        "suites_count": { "type": "integer", "minimum": 0 },
        "gated_in_ci": { "type": "integer", "minimum": 0 },
        "self_module_excluded": { "type": "string", "minLength": 1 },
        "self_module_gated": { "type": "boolean" },
        "missing_tests_dir": { "type": "array", "items": { "type": "string", "minLength": 1 } },
        "not_in_gate": { "type": "array", "items": { "type": "string", "minLength": 1 } },
        "orphan_tests_dirs": { "type": "array", "items": { "type": "string", "minLength": 1 } }
      }
    },
    "suites": {
      "type": "array",
      "minItems": 1,
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["id", "path", "jobs", "in_gate", "has_tests_dir", "test_files", "test_methods"],
        "properties": {
          "id": { "type": "string", "minLength": 1 },
          "path": { "type": "string", "minLength": 1 },
          "jobs": { "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } },
          "in_gate": { "type": "boolean" },
          "has_tests_dir": { "type": "boolean" },
          "test_files": { "type": "integer", "minimum": 0 },
          "test_methods": { "type": "integer", "minimum": 0 }
        }
      }
    },
    "under_threshold": { "type": "array", "items": { "type": "string", "minLength": 1 } },
    "totals": {
      "type": "object",
      "additionalProperties": false,
      "required": ["suites", "test_files", "test_methods", "min_methods", "under_threshold"],
      "properties": {
        "suites": { "type": "integer", "minimum": 1 },
        "test_files": { "type": "integer", "minimum": 0 },
        "test_methods": { "type": "integer", "minimum": 0 },
        "min_methods": { "type": "integer", "minimum": 0 },
        "under_threshold": { "type": "integer", "minimum": 0 }
      }
    },
    "verdict": { "type": "string", "enum": ["PASS", "FAIL"] },
    "notes": {
      "type": "array",
      "items": { "type": "string", "minLength": 1 }
    }
  }
}
