{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://orkestron.dev/schemas/contract/0.1.0/contract.schema.json",
  "title": "Orkestron Software Agent Contract",
  "description": "Canonical, transport-agnostic schema for a Contract authored/governed on orkestron.dev and instantiated as a Mission on orkestro.net. Chain: Contract -> Fulfillment Protocol -> Deliverable. The top-level field set is handoff-compatible with b2.203.api.contract_to_mission.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema_version",
    "contract_ref",
    "meta_model_ref",
    "work_mode",
    "acceptance_criteria",
    "deliverable_spec"
  ],
  "properties": {
    "schema_version": {
      "description": "Version of THIS schema the instance conforms to.",
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "const": "0.1.0"
    },
    "title": { "type": "string", "minLength": 1 },

    "contract_ref": {
      "description": "Stable identity of the Contract; the .net Mission references this, never duplicates it as source of truth.",
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "version"],
      "properties": {
        "id": { "type": "string", "pattern": "^contract\\.[a-z0-9_.-]+$" },
        "version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
        "governed_on": { "type": "string", "const": "orkestron.dev" },
        "supersedes": {
          "type": "array",
          "items": { "type": "string", "pattern": "^contract\\.[a-z0-9_.-]+@\\d+\\.\\d+\\.\\d+$" }
        }
      }
    },

    "meta_model_ref": {
      "description": "The AISMM model the contract is scoped to (the working context handed to agents). BR11: a contract is always bound to a concrete meta-model.",
      "type": "object",
      "additionalProperties": false,
      "required": ["product_id", "model_instance_id"],
      "properties": {
        "product_id": { "type": "string", "format": "uuid" },
        "model_instance_id": { "type": "string", "format": "uuid" },
        "spec_version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" },
        "includes_layers": {
          "description": "AISMM layer keys forming the context package, e.g. b4.402, b2.203.",
          "type": "array",
          "items": { "type": "string", "pattern": "^b\\d+\\.\\d{3}$" }
        },
        "retrieval_strategy": { "type": "string", "description": "Pointer to a retrieval strategy (e.g. b9.905)." },
        "redaction_policy": { "type": "string", "enum": ["standard", "strict", "none"], "default": "standard" }
      }
    },

    "work_mode": {
      "description": "BR11. contract-based = bound meta-model + atomic-task decomposition; process-based = agent runs its own routines (persona/position processes), no decomposition.",
      "type": "string",
      "enum": ["contract-based", "process-based"]
    },

    "fulfillment_protocol": {
      "description": "HOW the work is done: ordered phases, each with steps and an optional gate. Maps to orkestro.net Fulfillment Protocols (P1-P4).",
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "phases"],
      "properties": {
        "id": { "type": "string", "pattern": "^protocol\\.[a-z0-9_.-]+$" },
        "phases": {
          "type": "array",
          "minItems": 1,
          "items": { "$ref": "#/$defs/phase" }
        }
      }
    },

    "atomic_tasks": {
      "description": "Decomposed, delegatable unit list. BR11: each carries its own inputs/outputs/acceptance.",
      "type": "array",
      "items": { "$ref": "#/$defs/atomic_task" }
    },

    "acceptance_criteria": {
      "description": "The Mandatory Verification gate. Becomes the Review Engine rubric on .net. BR2/BR3/BR4/BR5, V1/V4/V5.",
      "$ref": "#/$defs/acceptance_criteria"
    },

    "constraints": {
      "description": "Budget/spend floor, control-policy hints, SLA, pricing. Becomes ControlPolicy + spend floor on .net (BR7/BR12).",
      "$ref": "#/$defs/constraints"
    },

    "deliverable_spec": {
      "description": "What 'done' produces: signed Artifact(s) with provenance + a Change Set. Closes the chain.",
      "$ref": "#/$defs/deliverable_spec"
    },

    "composition": {
      "description": "OPTIONAL. Parent contract orchestrating sub-contracts; each sub-contract instantiates as its own child Mission via the same handoff (no inlining → single source of truth per contract).",
      "$ref": "#/$defs/composition"
    },

    "process_ref": {
      "description": "Used only in process-based mode (required by the allOf branch): the persona/position process the agent runs by.",
      "$ref": "#/$defs/process_ref"
    },

    "transport_binding": {
      "description": "OPTIONAL and ORTHOGONAL to semantics. Pins a wire (A2A) and/or a context/tool channel (MCP). Omitting it does not change the contract's meaning; the same instance is valid over any transport or fetched by contract_ref.",
      "$ref": "#/$defs/transport_binding"
    }
  },

  "allOf": [
    {
      "description": "BR11: a contract-based contract MUST decompose into atomic tasks under a fulfillment protocol.",
      "if": { "properties": { "work_mode": { "const": "contract-based" } } },
      "then": {
        "required": ["fulfillment_protocol", "atomic_tasks"],
        "properties": { "atomic_tasks": { "minItems": 1 } }
      }
    },
    {
      "description": "process-based work declares the process/persona it runs by, in lieu of a decomposition.",
      "if": { "properties": { "work_mode": { "const": "process-based" } } },
      "then": { "required": ["process_ref"] }
    }
  ],

  "$defs": {
    "phase": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "name", "steps"],
      "properties": {
        "id": { "type": "string", "pattern": "^phase\\.[a-z0-9_.-]+$" },
        "name": { "type": "string", "minLength": 1 },
        "intent": { "type": "string" },
        "steps": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "do"],
            "properties": {
              "id": { "type": "string" },
              "do": { "type": "string", "description": "Human/agent-readable instruction for this step." },
              "produces": { "type": "array", "items": { "type": "string" } }
            }
          }
        },
        "gate": {
          "description": "Optional phase gate: acceptance criterion ids that must pass before the next phase.",
          "type": "array",
          "items": { "type": "string", "pattern": "^crit\\.[a-z0-9_.-]+$" }
        }
      }
    },

    "io_port": {
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "kind"],
      "properties": {
        "name": { "type": "string" },
        "kind": { "type": "string", "enum": ["artifact", "data", "decision", "reference", "access_grant"] },
        "ref": { "type": "string", "description": "Optional pointer (e.g. meta-model layer, prior task output, grant path)." },
        "required": { "type": "boolean", "default": true }
      }
    },

    "atomic_task": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "title", "outputs", "acceptance_refs"],
      "properties": {
        "id": { "type": "string", "pattern": "^task\\.[a-z0-9_.-]+$" },
        "title": { "type": "string", "minLength": 1 },
        "description": { "type": "string" },
        "phase_ref": { "type": "string", "pattern": "^phase\\.[a-z0-9_.-]+$" },
        "assignable_to": {
          "type": "string",
          "enum": ["specialist", "reviewer", "orchestrator", "human"],
          "description": "Role class permitted to take the task (orkestron.dev role-interaction rules)."
        },
        "inputs": { "type": "array", "items": { "$ref": "#/$defs/io_port" } },
        "outputs": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/io_port" } },
        "acceptance_refs": {
          "description": "Per-task acceptance: ids into acceptance_criteria.rubric that gate this task.",
          "type": "array",
          "minItems": 1,
          "items": { "type": "string", "pattern": "^crit\\.[a-z0-9_.-]+$" }
        },
        "depends_on": {
          "type": "array",
          "items": { "type": "string", "pattern": "^task\\.[a-z0-9_.-]+$" }
        }
      }
    },

    "acceptance_criteria": {
      "type": "object",
      "additionalProperties": false,
      "required": ["scale", "threshold", "rubric", "verification"],
      "properties": {
        "scale": {
          "description": "Scoring scale. Ecosystem default 1-5 (V4).",
          "type": "object",
          "additionalProperties": false,
          "required": ["min", "max"],
          "properties": {
            "min": { "type": "integer", "default": 1 },
            "max": { "type": "integer", "default": 5 }
          }
        },
        "threshold": {
          "description": "Verdict mapping (V5). >=4 accepted; ==3 accepted-with-notes (recorded in TrackRecord); <=2 rework. Any single failed critical criterion forces rework regardless of average (BR3).",
          "type": "object",
          "additionalProperties": false,
          "required": ["accept", "rework"],
          "properties": {
            "accept": { "type": "string", "default": ">=4" },
            "accept_with_notes": { "type": "string", "default": "==3" },
            "rework": { "type": "string", "default": "<=2" }
          }
        },
        "rubric": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "statement"],
            "properties": {
              "id": { "type": "string", "pattern": "^crit\\.[a-z0-9_.-]+$" },
              "statement": { "type": "string", "minLength": 1 },
              "weight": { "type": "number", "minimum": 0 },
              "critical": {
                "type": "boolean",
                "default": false,
                "description": "If true, a sub-threshold score on this criterion forces rework regardless of the average (BR3)."
              },
              "applies_to": {
                "description": "'contract' (whole deliverable) or specific task ids.",
                "oneOf": [
                  { "type": "string", "const": "contract" },
                  { "type": "array", "items": { "type": "string", "pattern": "^task\\.[a-z0-9_.-]+$" } }
                ]
              }
            }
          }
        },
        "verification": {
          "description": "Mandatory Verification policy. Cannot be dropped on instantiation.",
          "type": "object",
          "additionalProperties": false,
          "required": ["mandatory", "reviewer_independent", "rework_loop_max"],
          "properties": {
            "mandatory": { "type": "boolean", "const": true, "description": "BR-core: verification is mandatory and cannot be skipped." },
            "reviewer_independent": { "type": "boolean", "const": true, "description": "BR2: the reviewer is not among the executors." },
            "meta_review": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "enabled": { "type": "boolean", "default": false },
                "auditor_distinct_from_reviewer": { "type": "boolean", "const": true, "description": "Meta-review auditor != reviewer." }
              }
            },
            "rework_loop_max": { "type": "integer", "minimum": 1, "default": 3, "description": "BR4/V1: rework iterations before auto-escalation to owner." },
            "on_exhaustion": { "type": "string", "enum": ["escalate"], "default": "escalate" }
          }
        }
      }
    },

    "constraints": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "budget": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "spend_limit_usd": { "type": "number", "minimum": 0, "description": "Spend floor; BR7 platform minimum still applies (cannot be lowered below platform floor)." },
            "currency": { "type": "string", "default": "USD" },
            "value_floor_ae": { "type": "number", "minimum": 0, "description": "Minimum Æ value expected from the deliverable." }
          }
        },
        "sla": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "deadline": { "type": "string", "format": "date-time" },
            "response_time": { "type": "string", "description": "ISO 8601 duration, e.g. PT4H." }
          }
        },
        "pricing": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "scheme": { "type": "string", "enum": ["fixed", "hourly", "value_based", "bid"] },
            "amount": { "type": "number", "minimum": 0 },
            "currency": { "type": "string", "default": "USD" },
            "platform_commission_pct": { "type": "number", "minimum": 0, "maximum": 100, "default": 15 }
          }
        },
        "control_policy_hints": {
          "description": "Seeds the .net ControlPolicy (BR12). Customer-tunable and dynamic; the platform keeps change history and never lowers the BR7 floor.",
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "checkpoints": {
              "type": "array",
              "items": { "type": "string", "enum": ["plan", "squad", "acceptance", "spend_above_limit", "access_provisioning"] }
            },
            "pre_approval": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "actions": { "type": "array", "items": { "type": "string" } },
                "temporary": {
                  "type": "object",
                  "additionalProperties": false,
                  "properties": {
                    "first_n": { "type": "integer", "minimum": 0 },
                    "for_weeks": { "type": "integer", "minimum": 0 }
                  }
                }
              }
            },
            "reporting": { "type": "string", "description": "Cadence/form, e.g. weekly-performance." },
            "trust_ramp": { "type": "string", "enum": ["manual", "temporary", "rating_based"], "default": "manual", "description": "BR10/BR12: how control relaxes over time/rating." },
            "scope": { "type": "string", "enum": ["executor", "reviewer", "both"], "default": "both" }
          }
        }
      }
    },

    "deliverable_spec": {
      "type": "object",
      "additionalProperties": false,
      "required": ["artifacts"],
      "properties": {
        "artifacts": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "kind", "signed", "provenance_required"],
            "properties": {
              "id": { "type": "string", "pattern": "^artifact\\.[a-z0-9_.-]+$" },
              "kind": { "type": "string", "description": "e.g. document, code, model, report, deployment." },
              "format": { "type": "string", "description": "e.g. markdown, json, diff, container-image." },
              "signed": { "type": "boolean", "const": true, "description": "Artifacts are signed on return (.net response)." },
              "provenance_required": { "type": "boolean", "const": true },
              "maps_to_tasks": { "type": "array", "items": { "type": "string", "pattern": "^task\\.[a-z0-9_.-]+$" } }
            }
          }
        },
        "change_set": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "required": { "type": "boolean", "default": false },
            "format": { "type": "string", "enum": ["diff", "patch", "pull_request"], "default": "diff" },
            "targets": { "type": "array", "items": { "type": "string" }, "description": "Repos/paths/systems the change set applies to." }
          }
        }
      }
    },

    "transport_binding": {
      "type": "object",
      "additionalProperties": false,
      "required": ["semantic_layer"],
      "properties": {
        "semantic_layer": { "type": "string", "const": "software-agents-contracts" },
        "note": { "type": "string", "default": "Transport is orthogonal to semantics; bindings below do not alter any semantic field." },
        "bindings": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "a2a": { "$ref": "#/$defs/a2a_binding" },
            "mcp": { "$ref": "#/$defs/mcp_binding" }
          }
        }
      }
    },

    "a2a_binding": {
      "description": "Agent-to-Agent (A2A) wire binding for delegation/handoff between agents. Field names follow the A2A AgentCard spec (camelCase) so a card is portable to a real A2A runtime. Carries the Contract; never substitutes for it.",
      "type": "object",
      "additionalProperties": false,
      "required": ["protocol", "endpoint", "agentCard"],
      "properties": {
        "protocol": { "type": "string", "const": "A2A" },
        "protocolVersion": { "type": "string", "description": "A2A protocol version the endpoint speaks." },
        "endpoint": { "type": "string", "format": "uri", "description": "A2A service URL (JSON-RPC / message endpoint)." },
        "agentCard": { "$ref": "#/$defs/a2a_agent_card" }
      }
    },

    "a2a_agent_card": {
      "description": "A2A AgentCard: the executing/serving agent's advertised identity and capabilities. Mirrors the public A2A AgentCard shape.",
      "type": "object",
      "additionalProperties": false,
      "required": ["name", "url", "version", "capabilities", "skills"],
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "description": { "type": "string" },
        "url": { "type": "string", "format": "uri", "description": "Base URL the agent is reachable at." },
        "version": { "type": "string", "description": "Agent (not protocol) version." },
        "provider": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "organization": { "type": "string" },
            "url": { "type": "string", "format": "uri" }
          }
        },
        "capabilities": {
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "streaming": { "type": "boolean", "default": false },
            "pushNotifications": { "type": "boolean", "default": false },
            "stateTransitionHistory": { "type": "boolean", "default": false }
          }
        },
        "defaultInputModes": {
          "type": "array",
          "items": { "type": "string", "description": "Media types, e.g. text/plain, application/json." },
          "default": ["application/json", "text/plain"]
        },
        "defaultOutputModes": {
          "type": "array",
          "items": { "type": "string" },
          "default": ["application/json", "text/plain"]
        },
        "securitySchemes": {
          "description": "How a caller authenticates (names map to a securitySchemes registry, OpenAPI-style).",
          "type": "object",
          "additionalProperties": {
            "type": "object",
            "additionalProperties": false,
            "required": ["type"],
            "properties": {
              "type": { "type": "string", "enum": ["apiKey", "http", "oauth2", "openIdConnect", "mutualTLS"] },
              "scheme": { "type": "string", "description": "For http, e.g. bearer." },
              "description": { "type": "string" }
            }
          }
        },
        "security": {
          "description": "Which declared schemes apply, and required scopes per scheme.",
          "type": "array",
          "items": { "type": "object", "additionalProperties": { "type": "array", "items": { "type": "string" } } }
        },
        "skills": {
          "description": "Discrete capabilities the agent advertises. An atomic_task is dispatched to a matching skill, but the Contract's acceptance_criteria — not the skill — define 'done'.",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "name", "description"],
            "properties": {
              "id": { "type": "string" },
              "name": { "type": "string" },
              "description": { "type": "string" },
              "tags": { "type": "array", "items": { "type": "string" } },
              "examples": { "type": "array", "items": { "type": "string" } },
              "inputModes": { "type": "array", "items": { "type": "string" } },
              "outputModes": { "type": "array", "items": { "type": "string" } }
            }
          }
        }
      }
    },

    "mcp_binding": {
      "description": "Model Context Protocol (MCP) binding for context/tool access: how the agent receives the meta-model context package and grant-scoped tools. Field names follow the MCP spec. Servers expose ONLY what redaction_policy / grant scope permits.",
      "type": "object",
      "additionalProperties": false,
      "required": ["protocol", "servers"],
      "properties": {
        "protocol": { "type": "string", "const": "MCP" },
        "protocolVersion": { "type": "string", "description": "MCP version, e.g. 2025-06-18." },
        "clientCapabilities": {
          "description": "What the consuming agent (client) supports during capability negotiation.",
          "type": "object",
          "additionalProperties": false,
          "properties": {
            "roots": { "type": "object", "additionalProperties": false, "properties": { "listChanged": { "type": "boolean", "default": false } } },
            "sampling": { "type": "object", "additionalProperties": false, "properties": {} },
            "elicitation": { "type": "object", "additionalProperties": false, "properties": {} }
          }
        },
        "servers": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["name", "transport"],
            "properties": {
              "name": { "type": "string" },
              "transport": {
                "type": "object",
                "additionalProperties": false,
                "required": ["type"],
                "properties": {
                  "type": { "type": "string", "enum": ["stdio", "streamable-http"] },
                  "url": { "type": "string", "format": "uri", "description": "Required for streamable-http." },
                  "command": { "type": "string", "description": "Required for stdio." }
                }
              },
              "serverCapabilities": {
                "description": "What the server advertises (MCP capability negotiation).",
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "resources": {
                    "type": "object",
                    "additionalProperties": false,
                    "properties": {
                      "subscribe": { "type": "boolean", "default": false },
                      "listChanged": { "type": "boolean", "default": false }
                    }
                  },
                  "tools": { "type": "object", "additionalProperties": false, "properties": { "listChanged": { "type": "boolean", "default": false } } },
                  "prompts": { "type": "object", "additionalProperties": false, "properties": { "listChanged": { "type": "boolean", "default": false } } }
                }
              },
              "resources": {
                "description": "Declared resource exposure — typically the AISMM context package (meta_model_ref). Should respect redaction_policy.",
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": ["uri"],
                  "properties": {
                    "uri": { "type": "string", "description": "e.g. aismm://model/{model_instance_id}/layer/{layer_key}." },
                    "name": { "type": "string" },
                    "mimeType": { "type": "string" }
                  }
                }
              },
              "tools": {
                "description": "Tool names the server exposes to the agent. MUST be covered by an AccessGrant (BR6); secrets never enter the prompt (owner-constraint).",
                "type": "array",
                "items": { "type": "string" }
              },
              "scope": {
                "description": "Grant/redaction scope, e.g. model:{id}@layers:b2.203,b4.402 or grant:{mission}/{system}.",
                "type": "string"
              }
            }
          }
        }
      }
    },

    "process_ref": {
      "description": "Used only in process-based mode: the persona/position process the agent runs by.",
      "type": "object",
      "additionalProperties": false,
      "required": ["id"],
      "properties": {
        "id": { "type": "string" },
        "kind": { "type": "string", "enum": ["persona_process", "position_profile"] }
      }
    },

    "composition": {
      "description": "Parent->children orchestration. Sub-contracts are REFERENCED (not inlined): each is a full Contract with its own contract_ref and instantiates as a child Mission via the same handoff. The graph MUST be acyclic (a contract cannot transitively reference itself).",
      "type": "object",
      "additionalProperties": false,
      "required": ["sub_contracts", "rollup"],
      "properties": {
        "sub_contracts": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["alias", "contract_ref"],
            "properties": {
              "alias": { "type": "string", "description": "Local handle for wiring dependencies/outputs within this composition." },
              "contract_ref": {
                "type": "object",
                "additionalProperties": false,
                "required": ["id", "version"],
                "properties": {
                  "id": { "type": "string", "pattern": "^contract\\.[a-z0-9_.-]+$" },
                  "version": { "type": "string", "pattern": "^\\d+\\.\\d+\\.\\d+$" }
                }
              },
              "depends_on": { "type": "array", "items": { "type": "string" }, "description": "Aliases of sibling sub-contracts that must reach pass before this one instantiates." },
              "condition": { "type": "string", "description": "Optional guard; the child is instantiated only if it holds." },
              "binds": {
                "description": "Wire a finished sibling's deliverable artifact into this child's input port.",
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": ["from", "to"],
                  "properties": {
                    "from": { "type": "string", "description": "'<alias>.<artifact.id>' of a sibling's deliverable." },
                    "to": { "type": "string", "description": "Input port name in the child contract's atomic_tasks." }
                  }
                }
              }
            }
          }
        },
        "rollup": {
          "description": "How children gate the parent. The parent's own acceptance_criteria are evaluated ONLY after rollup is satisfied (verification is still mandatory at every level).",
          "type": "object",
          "additionalProperties": false,
          "required": ["require"],
          "properties": {
            "require": { "type": "string", "enum": ["all_children_pass", "quorum", "any_child_pass"], "default": "all_children_pass" },
            "quorum": { "type": "integer", "minimum": 1, "description": "Required count of passing children when require=quorum." }
          }
        },
        "settlement": {
          "type": "string",
          "enum": ["per_child", "parent_only"],
          "default": "per_child",
          "description": "per_child: each child Mission settles independently on its own pass; the parent settles on parent pass. parent_only: children roll value up and only the parent settles."
        }
      }
    }
  }
}