{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://mosaicstack.dev/schemas/reflection/reflection.v1.schema.json",
  "title": "Agent Reflection (v1)",
  "description": "End-of-run reflection sidecar. Mechanical fields are written by the Stop hook; self-reported fields are merged from an optional agent-supplied input and are null when absent (provenance.degraded=true).",
  "type": "object",
  "required": [
    "schema",
    "task_ref",
    "agent",
    "session_id",
    "timestamp",
    "repo",
    "risk",
    "files_changed",
    "provenance"
  ],
  "properties": {
    "schema": {
      "const": "reflection.v1"
    },
    "task_ref": {
      "type": "string",
      "description": "Canonical task ref; derived from REFLECTION_TASK_REF or repo+branch."
    },
    "agent": {
      "type": "string",
      "description": "Persona/runtime id (REFLECTION_AGENT or 'unknown')."
    },
    "session_id": {
      "type": "string",
      "description": "From the Stop payload session_id, else 'unknown'."
    },
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "description": "ISO-8601 UTC capture time."
    },
    "repo": {
      "type": "string",
      "description": "Repo root basename."
    },
    "confidence": {
      "type": ["number", "null"],
      "minimum": 0,
      "maximum": 1,
      "description": "SELF-REPORTED. Agent's overall confidence; null when not supplied."
    },
    "most_likely_wrong": {
      "type": ["object", "null"],
      "description": "SELF-REPORTED. The single most-likely way the work is wrong.",
      "required": ["surface", "description"],
      "properties": {
        "surface": { "$ref": "#/$defs/surface" },
        "description": { "type": "string" }
      },
      "additionalProperties": false
    },
    "known_not_in_diff": {
      "type": ["string", "null"],
      "description": "SELF-REPORTED. What the agent knows that isn't visible in the diff."
    },
    "risk": {
      "type": "object",
      "description": "MECHANICAL. Output of the diff risk-floor.",
      "required": ["needs_review", "score", "surface", "reason"],
      "properties": {
        "needs_review": { "type": "boolean" },
        "score": { "type": "number", "minimum": 0, "maximum": 1 },
        "surface": { "$ref": "#/$defs/surface" },
        "reason": { "type": "string" }
      },
      "additionalProperties": false
    },
    "files_changed": {
      "type": "array",
      "items": { "type": "string" },
      "description": "MECHANICAL. git diff name-only."
    },
    "provenance": {
      "type": "object",
      "required": ["source", "reflection_attempt", "degraded", "reflection_mode"],
      "properties": {
        "source": { "const": "stop-hook" },
        "reflection_attempt": { "type": "integer", "minimum": 1 },
        "degraded": {
          "type": "boolean",
          "description": "True when self-report inputs were missing/unreadable."
        },
        "reflection_mode": {
          "type": "string",
          "enum": ["off", "solo", "orchestrated"]
        }
      },
      "additionalProperties": false
    }
  },
  "additionalProperties": false,
  "$defs": {
    "surface": {
      "type": "string",
      "enum": ["auth", "data", "infra", "build", "ui", "test", "docs", "none"]
    }
  }
}
