{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "peaks-loop/schemas/reviewer-envelope.schema.json",
  "title": "ReviewerEnvelope",
  "description": "Schema-validated JSON envelope emitted by peaks-reviewer (third-party reviewer). All LLM JSON output MUST validate against this shape; free-form LLM JSON is rejected. v2.14.0 G4 AC-4.2.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "reviewerId",
    "modelId",
    "modelFamily",
    "passed",
    "violations",
    "gateAction",
    "reason"
  ],
  "properties": {
    "reviewerId": {
      "type": "string",
      "minLength": 1,
      "description": "Stable reviewer identifier (e.g. 'third-party-reviewer-v2.14.0')."
    },
    "modelId": {
      "type": "string",
      "minLength": 1,
      "description": "Concrete model identifier the provider was called with (e.g. 'claude-haiku-4-5', 'gpt-4o-mini', 'llama3.2:8b')."
    },
    "modelFamily": {
      "type": "string",
      "minLength": 1,
      "description": "Provider family bucket derived from modelId. Used by A4.4 to enforce distinctness from karpathy-reviewer modelFamily. Examples: 'claude', 'gpt-4', 'gpt-3.5', 'llama', 'bedrock-claude', 'azure-openai'."
    },
    "passed": {
      "type": "boolean",
      "description": "True only when a review RAN and found no blocking violations. False when it found violations, and also false on every skip path (no config, provider error, non-conforming JSON) — a review that never produced a verdict is never a pass."
    },
    "violations": {
      "type": "array",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": ["kind", "file", "line", "hint"],
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["karpathy-violation", "code-smell", "security", "perf", "surgical-changes", "simplicity-first", "goal-driven-execution", "think-before-coding"],
            "description": "Violation category."
          },
          "file": {
            "type": "string",
            "minLength": 1,
            "description": "Repo-relative file path."
          },
          "line": {
            "type": "integer",
            "minimum": 0,
            "description": "1-based line number, or 0 when not file-anchored."
          },
          "hint": {
            "type": "string",
            "minLength": 1,
            "description": "Short hint describing the violation and fix direction."
          }
        }
      },
      "description": "List of structured violations. Empty array when no findings."
    },
    "gateAction": {
      "type": "string",
      "enum": ["block", "allow", "warn"],
      "description": "Recommended gate action for peaks request transition."
    },
    "reason": {
      "type": "string",
      "minLength": 1,
      "description": "One-sentence summary explaining the gateAction (e.g. 'no reviewer.providers configured; skipped via fallbackOnError=skip')."
    }
  }
}
