{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/kitepon/Lattice/blob/main/docs/schemas/lattice.plan_create_input.v2.schema.json",
  "title": "lattice.plan_create_input.v2",
  "description": "Canonical initial authoring input for a phase-controlled Lattice plan.",
  "$comment": "Runtime validation additionally enforces canonical JSON+LF bytes, sorted identifiers, unique ids, acyclic task/phase graphs, byte bounds, and input_digest.",
  "type": "object",
  "additionalProperties": false,
  "required": ["schema", "project_id", "plan_key", "plan_version", "actor", "recorded_at", "tasks", "phases", "hard_dependencies", "joins", "input_digest"],
  "properties": {
    "schema": { "const": "lattice.plan_create_input.v2" },
    "project_id": { "$ref": "#/$defs/identifier" },
    "plan_key": { "$ref": "#/$defs/identifier" },
    "plan_version": { "$ref": "#/$defs/identifier" },
    "actor": { "$ref": "#/$defs/actor" },
    "recorded_at": { "$ref": "#/$defs/strictTimestamp" },
    "tasks": { "type": "array", "minItems": 1, "maxItems": 512, "items": { "$ref": "#/$defs/task" } },
    "phases": { "type": "array", "minItems": 1, "maxItems": 512, "items": { "$ref": "#/$defs/phase" } },
    "hard_dependencies": { "type": "array", "maxItems": 2048, "items": { "$ref": "#/$defs/edge" } },
    "joins": { "type": "array", "maxItems": 128, "items": { "$ref": "#/$defs/join" } },
    "input_digest": { "$ref": "#/$defs/digest" }
  },
  "$defs": {
    "identifier": { "type": "string", "pattern": "^[0-9A-Za-z](?:[0-9A-Za-z._-]{0,127})$" },
    "digest": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
    "repoRef": { "type": "string", "minLength": 1, "maxLength": 1024 },
    "strictTimestamp": { "type": "string", "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}Z$" },
    "nullableRepoRef": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/repoRef" }] },
    "nullableIdentifier": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/identifier" }] },
    "actor": {
      "type": "object", "additionalProperties": false, "required": ["host", "session", "agent"],
      "properties": { "host": { "$ref": "#/$defs/identifier" }, "session": { "$ref": "#/$defs/identifier" }, "agent": { "$ref": "#/$defs/identifier" } }
    },
    "task": {
      "type": "object", "additionalProperties": false,
      "required": ["task_id", "title", "lane", "narrative_ref", "narrative_anchor", "compile_binding", "parent_task_id", "phase_id"],
      "properties": {
        "task_id": { "$ref": "#/$defs/identifier" },
        "title": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "maxLength": 16384 }] },
        "lane": { "$ref": "#/$defs/identifier" },
        "narrative_ref": { "$ref": "#/$defs/nullableRepoRef" },
        "narrative_anchor": { "type": "null" },
        "compile_binding": { "type": "null" },
        "parent_task_id": { "$ref": "#/$defs/nullableIdentifier" },
        "phase_id": { "$ref": "#/$defs/identifier" }
      }
    },
    "phase": {
      "type": "object", "additionalProperties": false,
      "required": ["phase_id", "title", "gate_policy", "predecessor_phase_ids", "required_evidence_slots"],
      "properties": {
        "phase_id": { "$ref": "#/$defs/identifier" },
        "title": { "oneOf": [{ "type": "null" }, { "type": "string", "minLength": 1, "maxLength": 16384 }] },
        "gate_policy": { "$ref": "#/$defs/identifier" },
        "predecessor_phase_ids": { "type": "array", "items": { "$ref": "#/$defs/identifier" }, "uniqueItems": true },
        "required_evidence_slots": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/identifier" }, "uniqueItems": true }
      }
    },
    "nodeRef": {
      "type": "object", "additionalProperties": false, "required": ["project_id", "plan_key", "task_id"],
      "properties": { "project_id": { "$ref": "#/$defs/identifier" }, "plan_key": { "$ref": "#/$defs/identifier" }, "task_id": { "$ref": "#/$defs/identifier" }, "expected_topology_digest": { "$ref": "#/$defs/digest" } }
    },
    "edge": {
      "type": "object", "additionalProperties": false, "required": ["from", "to"],
      "properties": { "from": { "$ref": "#/$defs/nodeRef" }, "to": { "$ref": "#/$defs/nodeRef" } }
    },
    "join": {
      "type": "object", "additionalProperties": false, "required": ["id", "after", "before"],
      "properties": { "id": { "$ref": "#/$defs/identifier" }, "after": { "type": "array", "minItems": 1, "maxItems": 512, "items": { "$ref": "#/$defs/nodeRef" } }, "before": { "$ref": "#/$defs/nodeRef" } }
    }
  }
}
