{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Agent Baseline Manifest",
  "description": "Machine-readable baseline of capabilities every operator PA is expected to carry. Consumed by `pa agent audit` and by `pa-init` at scaffold time.",
  "type": "object",
  "required": ["schemaVersion", "manifestVersion", "capabilities"],
  "properties": {
    "$schema": { "type": "string" },
    "schemaVersion": { "type": "string", "const": "1.0" },
    "manifestVersion": {
      "type": "integer",
      "minimum": 1,
      "description": "Monotonic manifest version. Bump on every capability addition/removal so an audit can detect its own manifest is behind."
    },
    "description": { "type": "string" },
    "capabilities": {
      "type": "array",
      "items": { "$ref": "#/definitions/capability" }
    }
  },
  "definitions": {
    "capability": {
      "type": "object",
      "required": ["id", "label", "sinceVersion", "rationale", "probe"],
      "additionalProperties": false,
      "properties": {
        "id": {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9-]*[a-z0-9]$",
          "description": "Stable capability id — kebab-case, referenced in audit output. Never renamed once shipped."
        },
        "label": {
          "type": "string",
          "description": "Human-facing one-liner rendered in audit summaries."
        },
        "sinceVersion": {
          "type": "string",
          "pattern": "^\\d+\\.\\d+\\.\\d+$",
          "description": "@stravica-ai/engineering-pa-core version that introduced this capability."
        },
        "rationale": {
          "type": "string",
          "description": "Why this capability exists in the baseline. Renders in --verbose audit output."
        },
        "severity": {
          "type": "string",
          "enum": ["fail", "warn"],
          "default": "fail",
          "description": "How a missing/failing probe is reported. `warn` never contributes to a non-zero --strict exit."
        },
        "hostDependent": {
          "type": "boolean",
          "default": false,
          "description": "Declares the capability lives on a specific host or subset of hosts. The audit's fail-vs-unverified-here treatment is probe-specific: only `schedule-defined` currently reads host-shape (via each schedule's `host` field) and upgrades a matching-schedule-on-wrong-host outcome to `unverified-here`. For all other probe types, `hostDependent:true` is documentary metadata only — a mechanical fail (missing file, missing directory, missing field) is reported as `fail`, because a missing artefact is missing on every host, not just this one. The upgrade is deliberately kept probe-local: a generic 'hostDependent+fail → unverified-here' fold would silence genuine estate-wide gaps that no host has."
        },
        "probe": {
          "oneOf": [
            { "$ref": "#/definitions/probeFileExists" },
            { "$ref": "#/definitions/probeDirectoryExists" },
            { "$ref": "#/definitions/probeStagingRecentWrite" },
            { "$ref": "#/definitions/probeKnowledgeDocExists" },
            { "$ref": "#/definitions/probeScheduleDefined" },
            { "$ref": "#/definitions/probeJsonFieldIncludes" },
            { "$ref": "#/definitions/probeSettingsHookIncludes" },
            { "$ref": "#/definitions/probeFileIncludes" }
          ]
        }
      }
    },
    "probeFileExists": {
      "type": "object",
      "required": ["type", "path"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "file-exists" },
        "path": { "type": "string", "description": "Path relative to repo root. Tokens: {paName}." }
      }
    },
    "probeDirectoryExists": {
      "type": "object",
      "required": ["type", "path"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "directory-exists" },
        "path": { "type": "string" }
      }
    },
    "probeKnowledgeDocExists": {
      "type": "object",
      "required": ["type", "path"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "knowledge-doc-exists" },
        "path": { "type": "string" }
      }
    },
    "probeStagingRecentWrite": {
      "type": "object",
      "required": ["type", "path", "maxAgeDays"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "staging-recent-write" },
        "path": { "type": "string" },
        "maxAgeDays": { "type": "number", "minimum": 1 }
      }
    },
    "probeScheduleDefined": {
      "type": "object",
      "required": ["type", "path", "commandIncludes"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "schedule-defined" },
        "path": { "type": "string", "description": "Directory containing schedule JSON files (typically `schedules`)." },
        "commandIncludes": {
          "type": "array",
          "items": { "type": "string" },
          "minItems": 1,
          "description": "Substrings that MUST all appear (AND) in a schedule's `command` field."
        },
        "commandIncludesAny": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Substrings where AT LEAST ONE (OR) must appear in the same schedule's command."
        },
        "outputPathHints": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Optional path substrings that, if present in the estate, corroborate the schedule's declared output."
        }
      }
    },
    "probeJsonFieldIncludes": {
      "type": "object",
      "required": ["type", "path", "field", "expectedValue"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "json-field-includes" },
        "path": { "type": "string" },
        "field": { "type": "string", "description": "Top-level JSON field name (dot-path not supported in v1)." },
        "expectedValue": { "type": "string", "description": "Value expected in the field's array. Tokens: {paName}." },
        "requiredTool": {
          "type": "string",
          "description": "If set, the probe is skipped (unverified-here) when the named tool directory is absent under operator/extensions/tools/."
        }
      }
    },
    "probeSettingsHookIncludes": {
      "type": "object",
      "required": ["type", "path", "event", "commandIncludes"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "settings-hook-includes" },
        "path": { "type": "string", "description": "Claude Code settings file relative to repo root (the scaffold writes `.claude/settings.json`). Tokens: {paName}." },
        "altPaths": {
          "type": "array",
          "items": { "type": "string" },
          "description": "Further settings files read beside `path` (for example an agent-folder settings file); the probe passes when any file that exists holds the hook. Tokens: {paName}."
        },
        "event": { "type": "string", "description": "Hook event key under `hooks` (for example `SessionStart`)." },
        "matcherIncludes": { "type": "string", "description": "Substring the entry's matcher must contain." },
        "commandIncludes": {
          "type": "array",
          "items": { "type": "string" },
          "minItems": 1,
          "description": "Substrings that MUST all appear (AND) in one command hook of the matching entry."
        }
      }
    },
    "probeFileIncludes": {
      "type": "object",
      "required": ["type", "path", "includes"],
      "additionalProperties": false,
      "properties": {
        "type": { "const": "file-includes" },
        "path": { "type": "string", "description": "File relative to repo root. Tokens: {paName}." },
        "includes": {
          "type": "array",
          "items": { "type": "string" },
          "minItems": 1,
          "description": "Substrings that MUST all appear (AND) in the file."
        }
      }
    }
  }
}
