{
  "schema_version": "1.0",
  "contract_version": 1,
  "policy": {
    "canonical_source": "templates/tool-surface.json",
    "manual_coverage": "complete",
    "mutation_path": "validated_handlers",
    "description": "One capability contract accounts for every PRD Plugin tool, and the generated UTCP manual covers every capability on every transport (PRD-REQ-076, ARCH-DEC-049): read tools call the cli surface natively; mutations are exposed through mcp call templates targeting the validated state server so locking, duplicate-safe allocation, validation, and worker boundaries hold. MCP metadata is generated from mcp/tool-metadata.json, never hand-authored; per-capability transport_rationale explains why a tool's native execution lives server-side."
  },
  "capabilities": [
    {
      "id": "state.read",
      "access": "read",
      "transports": {
        "utcp": [
          "status",
          "tracking",
          "decisions",
          "evidence"
        ],
        "mcp": [
          "prd_status",
          "prd_check_messages",
          "prd_find",
          "prd_get"
        ]
      }
    },
    {
      "id": "state.mutate",
      "access": "write",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_create",
          "prd_update",
          "prd_link",
          "prd_open_tracking_branch",
          "prd_update_tracking_branch",
          "prd_promote_tracking_branch",
          "prd_next_id",
          "prd_open_goal",
          "prd_update_goal",
          "prd_close_goal",
          "prd_file_request",
          "prd_import_request",
          "prd_record_evidence",
          "prd_record_decision",
          "prd_log_change",
          "prd_close_thread"
        ]
      },
      "transport_rationale": "Canonical state mutation stays MCP-only so locking, duplicate-safe allocation, validation, worker boundaries, and atomic writes cannot be bypassed by the read-only UTCP CLI surface."
    },
    {
      "id": "reflection.read",
      "access": "read",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_reflection_list"
        ]
      },
      "transport_rationale": "Reflection-bank inspection remains beside its guarded CRUD authority; the UTCP observe surface exposes configuration inventory rather than a second question-bank API."
    },
    {
      "id": "reflection.mutate",
      "access": "write",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_reflection_create",
          "prd_reflection_update",
          "prd_reflection_delete"
        ]
      },
      "transport_rationale": "Reflection CRUD allocates IDs and rewrites canonical configuration under the MCP state lock, so it is intentionally unavailable through read-only UTCP."
    },
    {
      "id": "services.read",
      "access": "read",
      "transports": {
        "utcp": [
          "services"
        ],
        "mcp": [
          "prd_service_list",
          "prd_service_get",
          "prd_service_audit"
        ]
      }
    },
    {
      "id": "services.mutate",
      "access": "write",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_service_upsert",
          "prd_service_remove"
        ]
      },
      "transport_rationale": "Repository service declarations are canonical project state and mutate only through the locked MCP authority."
    },
    {
      "id": "substrate.read",
      "access": "read",
      "transports": {
        "utcp": [
          "substrate"
        ],
        "mcp": [
          "prd_substrate_catalog",
          "prd_substrate_links"
        ]
      }
    },
    {
      "id": "substrate.coordinate",
      "access": "coordinate",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_substrate_call",
          "prd_substrate_runtime"
        ]
      },
      "transport_rationale": "Live calls and runtime dispatch require allowlists, source references, receipts, and idempotency enforcement at the MCP coordination boundary."
    },
    {
      "id": "reporting",
      "access": "read",
      "transports": {
        "utcp": [
          "reporting"
        ],
        "mcp": [
          "prd_reporting_validate"
        ]
      }
    },
    {
      "id": "config.read",
      "access": "read",
      "transports": {
        "utcp": [
          "config_inventory"
        ],
        "mcp": [
          "prd_config_list",
          "prd_config_get"
        ]
      }
    },
    {
      "id": "config.mutate",
      "access": "write",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_config_set",
          "prd_config_profile"
        ]
      },
      "transport_rationale": "Validated configuration writes and profile application remain MCP-only to preserve schema checks, formatting, and worker-session write guards."
    },
    {
      "id": "workflow.read",
      "access": "read",
      "transports": {
        "utcp": [
          "workflow"
        ],
        "mcp": [
          "prd_workflow_list",
          "prd_workflow_actions",
          "prd_workflow_audit",
          "prd_workflow_plan",
          "prd_workflow_status"
        ]
      }
    },
    {
      "id": "workflow.mutate",
      "access": "write",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_workflow_run",
          "prd_workflow_resume",
          "prd_workflow_cancel",
          "prd_workflow_retry"
        ]
      },
      "transport_rationale": "Persistent workflow transitions and judgment resumption mutate WFR state and therefore stay behind MCP locking and hash validation."
    },
    {
      "id": "verification",
      "access": "read",
      "transports": {
        "utcp": [
          "gate"
        ],
        "mcp": [
          "prd_validate"
        ]
      }
    },
    {
      "id": "knowledge_and_drift",
      "access": "read",
      "transports": {
        "utcp": [
          "wiki",
          "drift"
        ],
        "mcp": []
      },
      "transport_rationale": "These CLI-backed observe helpers are mounted through the UTCP-to-MCP bridge; duplicating them in the canonical mutation server would create two registrations for the same read-only capability."
    },
    {
      "id": "fabric.resolve",
      "summary": "Resolve the evidence-bound fabric prediction profile for a model (fail-safe raw default for unmapped models).",
      "transports": {
        "utcp": [
          "fabric"
        ],
        "mcp": []
      },
      "transport_rationale": "Read-only CLI-backed resolver on the UTCP surface; binding writes go through the validated config contract (set-fabric-binding / structured-key validation), never a bespoke transport.",
      "access": "read"
    },
    {
      "id": "requests.route.read",
      "access": "read",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_list_destinations"
        ]
      },
      "transport_rationale": "Reads the peer declarations that authorize cross-repo delivery. Kept on the same transport as the writes it gates so an agent cannot discover destinations through a surface that the delivery tools themselves do not share."
    },
    {
      "id": "requests.route.mutate",
      "access": "write",
      "transports": {
        "utcp": [],
        "mcp": [
          "prd_send_request",
          "prd_flush_addressed_requests"
        ]
      },
      "transport_rationale": "Peer delivery writes a package INTO ANOTHER REPOSITORY, the widest blast radius any tool here has. It stays MCP-only so the declared-peer check, the self/imported/terminal guards, and the read-back verification cannot be bypassed by the read-only UTCP CLI surface."
    }
  ]
}
