{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://aisa.ablera.com/contracts/message-envelope.schema.json",
  "title": "Inter-agent message envelope (platform seam 1 of 5)",
  "description": "Agent Runtime § 4 (D66): every message between tasks is a versioned record whose payload is a hash plus an artefact reference. Transcripts never cross a task boundary. A receiver that meets an unknown type or version answers DeadEnd {capability gap}, never a guess. This schema is a PLATFORM seam: closed (additionalProperties false); adding a kind is a governed runtime version.",
  "type": "object",
  "additionalProperties": false,
  "required": ["type", "version", "message_id", "case_id", "task_path", "sender", "occurred_on", "trust_class", "payload"],
  "properties": {
    "type": { "type": "string", "enum": ["Spawn", "Plan", "PlanConfirmation", "Question", "Answer", "Result", "Verdict", "Finding", "Consult", "ConsultReply", "DeadEnd", "Cancel"] },
    "version": { "type": "integer", "minimum": 1, "description": "schema version of this message kind; the v1 set is version 1" },
    "message_id": { "$ref": "#/$defs/id" },
    "case_id": { "$ref": "#/$defs/id" },
    "task_path": { "type": "string", "pattern": "^[A-Za-z0-9_\\-]+(/[A-Za-z0-9_\\-]+)*$", "description": "materialised ancestry root/stage/sub-agent (TASKS.TASK_PATH)" },
    "recipient_task_id": { "$ref": "#/$defs/id" },
    "sender": {
      "type": "object", "additionalProperties": false,
      "required": ["task_id", "profile_key", "profile_version"],
      "properties": {
        "task_id": { "$ref": "#/$defs/id" },
        "profile_key": { "type": "string", "pattern": "^[a-z][a-z0-9_.\\-]+$" },
        "profile_version": { "type": "integer", "minimum": 1 },
        "runtime_version": { "type": "string" }
      }
    },
    "occurred_on": { "type": "string", "format": "date-time" },
    "deadline": { "type": "string", "format": "date-time", "description": "Consult only: never past the requester's remaining budget" },
    "priority": { "type": "integer", "minimum": 0, "maximum": 9 },
    "trust_class": { "type": "string", "enum": ["trusted", "derived", "untrusted", "absent"], "description": "Trust and Data § 1; 'absent' is what the runtime writes on a ConsultReply no_answer" },
    "artefact": {
      "type": "object", "additionalProperties": false,
      "required": ["hash", "paper_ref"],
      "properties": {
        "hash": { "$ref": "#/$defs/sha256" },
        "paper_ref": { "type": "string", "description": "PAPERS.ID or case-relative path; the body never travels in the message" },
        "media_type": { "type": "string" },
        "byte_length": { "type": "integer", "minimum": 0 },
        "truncated": { "type": "boolean" }
      }
    },
    "payload": {
      "description": "the small typed payload per kind; anything larger is the artefact",
      "oneOf": [
        { "$ref": "#/$defs/Spawn" }, { "$ref": "#/$defs/Plan" }, { "$ref": "#/$defs/PlanConfirmation" }, { "$ref": "#/$defs/Question" },
        { "$ref": "#/$defs/Answer" }, { "$ref": "#/$defs/Result" }, { "$ref": "#/$defs/Verdict" }, { "$ref": "#/$defs/Finding" },
        { "$ref": "#/$defs/Consult" }, { "$ref": "#/$defs/ConsultReply" }, { "$ref": "#/$defs/DeadEnd" }, { "$ref": "#/$defs/Cancel" }
      ]
    }
  },
  "allOf": [
    { "if": { "properties": { "type": { "const": "Spawn" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/Spawn" } } } },
    { "if": { "properties": { "type": { "const": "Plan" } } }, "then": { "required": ["artefact"], "properties": { "payload": { "$ref": "#/$defs/Plan" } } } },
    { "if": { "properties": { "type": { "const": "PlanConfirmation" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/PlanConfirmation" } } } },
    { "if": { "properties": { "type": { "const": "Question" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/Question" } } } },
    { "if": { "properties": { "type": { "const": "Answer" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/Answer" } } } },
    { "if": { "properties": { "type": { "const": "Result" } } }, "then": { "required": ["artefact"], "properties": { "payload": { "$ref": "#/$defs/Result" } } } },
    { "if": { "properties": { "type": { "const": "Verdict" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/Verdict" } } } },
    { "if": { "properties": { "type": { "const": "Finding" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/Finding" } } } },
    { "if": { "properties": { "type": { "const": "Consult" } } }, "then": { "required": ["deadline"], "properties": { "payload": { "$ref": "#/$defs/Consult" } } } },
    { "if": { "properties": { "type": { "const": "ConsultReply" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/ConsultReply" } } } },
    { "if": { "properties": { "type": { "const": "DeadEnd" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/DeadEnd" } } } },
    { "if": { "properties": { "type": { "const": "Cancel" } } }, "then": { "properties": { "payload": { "$ref": "#/$defs/Cancel" } } } }
  ],
  "$defs": {
    "id": { "type": "string", "minLength": 8, "maxLength": 64, "pattern": "^[A-Za-z0-9_\\-:.]+$" },
    "sha256": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
    "Spawn": {
      "type": "object", "additionalProperties": false,
      "required": ["kind", "profile_key", "profile_version", "task_text", "budget_minutes", "grant_subset", "memory_node", "denied_context"],
      "properties": {
        "kind": { "type": "string", "enum": ["stage", "sub_agent", "consult", "write_executor", "connector", "handover"] },
        "profile_key": { "type": "string" }, "profile_version": { "type": "integer", "minimum": 1 },
        "task_text": { "type": "string", "minLength": 1 },
        "budget_minutes": { "type": "number", "minimum": 0, "description": "the slice of the case's predicted delivery time (D135)" },
        "grant_subset": { "type": "array", "items": { "$ref": "#/$defs/id" }, "description": "GRANTS.ID values the child may use — a subset of the parent's" },
        "memory_node": { "type": "string" },
        "denied_context": { "type": "array", "items": { "type": "string" }, "description": "service names not registered in the child scope (Agents § 0.2)" },
        "stage_id": { "type": "string" }
      }
    },
    "Plan": {
      "type": "object", "additionalProperties": false,
      "required": ["plan_id", "revision_no", "step_count", "open_questions"],
      "properties": {
        "plan_id": { "$ref": "#/$defs/id" }, "revision_no": { "type": "integer", "minimum": 1 },
        "step_count": { "type": "integer", "minimum": 1 },
        "effect_classes": { "type": "array", "items": { "type": "string", "enum": ["none", "transactional", "compensable", "irreversible", "ddl"] }, "uniqueItems": true },
        "write_classes": { "type": "array", "items": { "type": "string", "enum": ["W1", "W2", "W3", "W4", "W5", "W6", "W7"] }, "uniqueItems": true },
        "open_questions": { "type": "integer", "minimum": 0 }
      }
    },
    "PlanConfirmation": {
      "type": "object", "additionalProperties": false,
      "required": ["plan_id", "revision_no", "decision"],
      "properties": {
        "plan_id": { "$ref": "#/$defs/id" }, "revision_no": { "type": "integer", "minimum": 1 },
        "decision": { "type": "string", "enum": ["confirmed", "amended", "gate_raised"] },
        "gate_id": { "$ref": "#/$defs/id" },
        "scope_confirmed": { "type": "array", "items": { "type": "string" }, "description": "step ids confirmed; absent = all" }
      }
    },
    "Question": {
      "type": "object", "additionalProperties": false,
      "required": ["gap", "checked", "depends", "alternatives", "decision_needed"],
      "properties": {
        "gap": { "type": "string" }, "checked": { "type": "array", "items": { "type": "string" } },
        "depends": { "type": "array", "items": { "type": "string" }, "description": "step ids that wait on the answer" },
        "alternatives": { "type": "array", "minItems": 1, "items": { "type": "object", "required": ["option", "consequence"], "properties": { "option": { "type": "string" }, "consequence": { "type": "string" } } } },
        "decision_needed": { "type": "string" },
        "park_reason": {"type": "string", "enum": ["question", "gate", "sub_case", "connector_down", "provider_down", "budget", "capability_gap", "external_job", "effect_unknown"]}
      }
    },
    "Answer": {
      "type": "object", "additionalProperties": false,
      "required": ["in_reply_to", "decision", "source"],
      "properties": {
        "in_reply_to": { "$ref": "#/$defs/id" }, "decision": { "type": "string" },
        "source": { "type": "string", "enum": ["parent", "human_gate", "policy"] },
        "gate_decision_id": { "$ref": "#/$defs/id" }
      }
    },
    "Result": {
      "type": "object", "additionalProperties": false,
      "required": ["proof_level", "reconciliation"],
      "properties": {
        "proof_level": { "type": "string", "enum": ["structural", "priced", "reachable", "quoted", "issued", "verified", "none"], "description": "the rung actually reached — never an implied higher one (CR-3)" },
        "reconciliation": { "type": "object", "required": ["steps_planned", "steps_done", "assertions_passed", "assertions_failed"], "properties": { "steps_planned": { "type": "integer" }, "steps_done": { "type": "integer" }, "assertions_passed": { "type": "integer" }, "assertions_failed": { "type": "integer" } } },
        "missing_open": { "type": "integer", "minimum": 0 }
      }
    },
    "Verdict": {
      "type": "object", "additionalProperties": false,
      "required": ["verdict", "checks"],
      "properties": {
        "verdict": { "type": "string", "enum": ["pass", "refuse", "agree", "disagree"] },
        "checks": { "type": "array", "items": { "type": "object", "required": ["check", "result"], "properties": { "check": { "type": "string", "enum": ["exactness", "boundedness", "reversibility", "scope", "mechanism"] }, "result": { "type": "string", "enum": ["pass", "refuse", "agree", "disagree", "unknown"] }, "failing_item": { "type": "string" }, "evidence_ref": { "type": "string" } } } },
        "separating_evidence_ref": { "type": "string", "description": "verifier: the evidence that separates the two mechanisms when it disagrees" }
      }
    },
    "Finding": {
      "type": "object", "additionalProperties": false,
      "required": ["domain", "statement", "evidence_refs"],
      "properties": { "domain": { "type": "string" }, "statement": { "type": "string" }, "evidence_refs": { "type": "array", "minItems": 1, "items": { "type": "string" } }, "proposed_article_key": { "type": "string" } }
    },
    "Consult": {
      "type": "object", "additionalProperties": false,
      "required": ["domain", "question", "question_hash"],
      "properties": { "domain": { "type": "string", "description": "a knowledge domain, never an agent (Agents § 5 rule 1)" }, "question": { "type": "string" }, "question_hash": { "$ref": "#/$defs/sha256" }, "depth": { "type": "integer", "const": 1 } }
    },
    "ConsultReply": {
      "type": "object", "additionalProperties": false,
      "required": ["in_reply_to", "outcome"],
      "properties": {
        "in_reply_to": { "$ref": "#/$defs/id" },
        "outcome": { "type": "string", "enum": ["answered", "no_answer", "needs_change"] },
        "answer_paper_ref": { "type": "string" },
        "no_answer": { "type": "object", "required": ["reason", "waited_s"], "properties": { "reason": { "type": "string" }, "waited_s": { "type": "integer" }, "queue_depth": { "type": "integer" } } },
        "needs_change_in_module": { "type": "string", "enum": ["configuration", "support", "source"], "description": "'this needs a change in my module' → the asking root raises Hd" }
      }
    },
    "DeadEnd": {
      "type": "object", "additionalProperties": false,
      "required": ["reason", "checked", "minutes_used", "would_need"],
      "properties": { "reason": { "type": "string", "enum": ["capability_gap", "no_mechanism_holds", "budget", "unknown_message_type", "unknown_message_version", "rejected_handover", "unreachable_target"] }, "checked": { "type": "array", "items": { "type": "string" } }, "minutes_used": { "type": "number" }, "would_need": { "type": "string" } }
    },
    "Cancel": {
      "type": "object", "additionalProperties": false,
      "required": ["reason", "fence_epoch"],
      "properties": { "reason": { "type": "string" }, "fence_epoch": { "type": "integer", "minimum": 0 } }
    }
  }
}
