{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://thossullivan.github.io/model-eol/schema/0.1/model-eol.bot-config.schema.json",
  "title": "model-eol repository configuration",
  "description": "Optional strict .model-eol.json configuration shared by the zero-dependency CLI, Action, and GitHub bot adapter.",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "days": {
      "type": "integer",
      "minimum": 0,
      "default": 90,
      "description": "Open migration work for models retiring within this many days."
    },
    "scope": {
      "enum": ["direct", "all"],
      "default": "direct",
      "description": "Use the direct-first scope (direct API plus generic model references, leaving cloud/gateway references as hints), or include all tracked references."
    },
    "via": {
      "type": ["string", "null"],
      "minLength": 1,
      "default": null,
      "description": "Optional distributor lifecycle clock, such as azure-ai-foundry."
    },
    "feeds": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "allow_vendored_fallback": {
          "type": "boolean",
          "default": false,
          "description": "Continue with vendored feeds after a remote feed failure in degraded report-only mode."
        }
      },
      "default": { "allow_vendored_fallback": false }
    },
    "ignore": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "models": {
          "type": "array",
          "items": { "type": "string", "minLength": 1 },
          "default": [],
          "description": "Canonical IDs or aliases to ignore across CLI, Action, and bot. Either form ignores every alias of the canonical feed entry."
        },
        "paths": {
          "type": "array",
          "items": { "type": "string", "minLength": 1 },
          "default": [],
          "description": "Repo-relative simple globs supporting *, **, and ?. Matching paths are excluded before file coverage checks where possible."
        }
      },
      "default": { "models": [], "paths": [] }
    },
    "overrides": {
      "type": "array",
      "items": { "$ref": "#/definitions/pathOverride" },
      "default": [],
      "description": "Path-scoped policy overrides. Matching entries apply in array order; later scalar values win and ignore lists are additive."
    },
    "routes": {
      "type": "array",
      "items": { "$ref": "#/definitions/referenceRoute" },
      "default": [],
      "description": "Path- and optionally reference-scoped distributor routes. The last matching route wins. Exact match/model pairs can resolve repository deployment aliases to canonical feed IDs."
    },
    "issues": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "Maintain GitHub issues for non-patchable actionable findings."
        }
      },
      "default": { "enabled": true }
    },
    "eval": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "command": {
          "type": ["string", "null"],
          "minLength": 1,
          "default": null,
          "description": "Opt-in repository-owned command run independently for each patchable migration only in the read-only evaluate phase. Write-capable publication consumes its commit-bound result manifest and never executes this command."
        },
        "timeout_ms": {
          "type": "integer",
          "minimum": 1000,
          "maximum": 3600000,
          "default": 600000
        },
        "max_report_bytes": {
          "type": "integer",
          "minimum": 1,
          "maximum": 8388608,
          "default": 65536
        },
        "pass_env": {
          "type": "array",
          "items": {
            "type": "string",
            "minLength": 1,
            "pattern": "^(?!(?:[Gg][Ii][Tt][Hh][Uu][Bb]_|[Gg][Hh]_|[Aa][Cc][Tt][Ii][Oo][Nn][Ss]_|[Ss][Ss][Hh]_|[Aa][Ww][Ss]_[Ss][Ee][Cc][Rr][Ee][Tt]|[\\s\\S]*(?:[Tt][Oo][Kk][Ee][Nn]|[Ss][Ee][Cc][Rr][Ee][Tt]|[Pp][Aa][Ss][Ss][Ww][Oo][Rr][Dd]|[Cc][Rr][Ee][Dd][Ee][Nn][Tt][Ii][Aa][Ll])))[\\s\\S]+$"
          },
          "default": [],
          "description": "Environment variable names explicitly forwarded to trusted eval code. GitHub, Actions, SSH, AWS secret, token, secret, password, and credential name patterns are refused. This controls normal subprocess forwarding and is not an OS sandbox or same-user secret-isolation boundary."
        }
      },
      "default": { "command": null, "timeout_ms": 600000, "max_report_bytes": 65536, "pass_env": [] }
    }
  },
  "default": {
    "days": 90,
    "scope": "direct",
    "via": null,
    "feeds": { "allow_vendored_fallback": false },
    "ignore": { "models": [], "paths": [] },
    "overrides": [],
    "routes": [],
    "issues": { "enabled": true },
    "eval": { "command": null, "timeout_ms": 600000, "max_report_bytes": 65536, "pass_env": [] }
  },
  "definitions": {
    "stringArray": {
      "type": "array",
      "items": { "type": "string", "minLength": 1 }
    },
    "nonEmptyStringArray": {
      "allOf": [
        { "$ref": "#/definitions/stringArray" },
        { "minItems": 1 }
      ]
    },
    "ignore": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "models": { "$ref": "#/definitions/stringArray" },
        "paths": { "$ref": "#/definitions/stringArray" }
      }
    },
    "pathOverride": {
      "type": "object",
      "additionalProperties": false,
      "required": ["paths"],
      "properties": {
        "paths": { "$ref": "#/definitions/nonEmptyStringArray" },
        "days": { "type": "integer", "minimum": 0 },
        "scope": { "enum": ["direct", "all"] },
        "via": { "type": ["string", "null"], "minLength": 1 },
        "ignore": { "$ref": "#/definitions/ignore" }
      }
    },
    "referenceRoute": {
      "type": "object",
      "additionalProperties": false,
      "required": ["paths", "via"],
      "properties": {
        "paths": { "$ref": "#/definitions/nonEmptyStringArray" },
        "via": { "type": "string", "minLength": 1 },
        "match": { "type": "string", "minLength": 1 },
        "model": { "type": "string", "minLength": 1 }
      },
      "dependencies": {
        "match": ["model"],
        "model": ["match"]
      }
    }
  }
}
