Files
CASAN/packages/casan-harness/schemas/agentic-lifecycle.schema.json
T

222 lines
8.7 KiB
JSON

{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://casan.local/schemas/agentic-lifecycle.schema.json",
"title": "CASAN Agentic Lifecycle Contract",
"description": "Plan-20 client-agnostic lifecycle contract for the CASAN agentic bridge. Each request is a single JSON object read on stdin; each response is a single JSON object written on stdout. Client adapters (Claude Code, Codex, VS Code) translate their native hook payloads into these shapes and render bridge responses back into client-native JSON. The bridge NEVER calls a model — it only admits, gates, records evidence, and finalizes traces (single-model invariant, Plan-20 §3.1).",
"type": "object",
"required": ["op"],
"properties": {
"op": {
"type": "string",
"enum": ["begin", "pre-tool", "post-tool", "telemetry", "finalize", "abort"],
"description": "Lifecycle operation to perform."
}
},
"allOf": [
{
"if": { "properties": { "op": { "const": "begin" } } },
"then": { "$ref": "#/definitions/beginRequest" }
},
{
"if": { "properties": { "op": { "const": "pre-tool" } } },
"then": { "$ref": "#/definitions/preToolRequest" }
},
{
"if": { "properties": { "op": { "const": "post-tool" } } },
"then": { "$ref": "#/definitions/postToolRequest" }
},
{
"if": { "properties": { "op": { "const": "telemetry" } } },
"then": { "$ref": "#/definitions/telemetryRequest" }
},
{
"if": { "properties": { "op": { "const": "finalize" } } },
"then": { "$ref": "#/definitions/finalizeRequest" }
},
{
"if": { "properties": { "op": { "const": "abort" } } },
"then": { "$ref": "#/definitions/abortRequest" }
}
],
"definitions": {
"clientContext": {
"type": "object",
"required": ["client"],
"properties": {
"client": {
"type": "string",
"enum": ["claude-code", "codex", "vscode", "unknown"],
"description": "Agentic client family."
},
"client_version": { "type": ["string", "null"] },
"adapter_version": { "type": ["string", "null"] },
"project": {
"type": ["string", "null"],
"description": "Project root as the client sees it; canonicalized by the bridge."
},
"session": {
"type": ["string", "null"],
"description": "Client-native session id. Hashed by the bridge, never stored raw."
},
"actor": {
"type": ["string", "null"],
"description": "Stable actor identity asserted by the authenticated runtime boundary."
},
"integration_mode": {
"type": ["string", "null"],
"enum": ["casan_owned", "managed_hook", "project_hook", "observed_only", null],
"description": "Declared integration mode; the bridge may DOWNGRADE (never upgrade) it based on enforcement mode and coverage."
}
}
},
"beginRequest": {
"allOf": [{ "$ref": "#/definitions/clientContext" }],
"required": ["op", "client", "prompt"],
"properties": {
"op": { "const": "begin" },
"prompt": {
"type": "string",
"description": "Raw user prompt. Scanned by H4 then discarded — only a salted hash is persisted."
},
"turn": {
"type": ["string", "null"],
"description": "Optional client-native turn correlation id; hashed, not stored raw."
}
}
},
"preToolRequest": {
"required": ["op", "admission_id", "tool"],
"properties": {
"op": { "const": "pre-tool" },
"admission_id": { "type": "string" },
"tool": {
"type": "string",
"description": "Client-native tool name, e.g. Bash, Edit, Write, WebFetch."
},
"tool_input": {
"description": "Tool input payload. Scanned/redacted; only a hash + redacted summary are persisted."
},
"project": { "type": ["string", "null"] }
}
},
"postToolRequest": {
"required": ["op", "admission_id", "tool"],
"properties": {
"op": { "const": "post-tool" },
"admission_id": { "type": "string" },
"tool": { "type": "string" },
"status": {
"type": ["string", "null"],
"enum": ["success", "error", "denied", "timeout", null]
},
"duration_ms": { "type": ["integer", "null"], "minimum": 0 },
"result": { "description": "Tool result. Never stored raw — hashed + redacted." }
}
},
"telemetryRequest": {
"required": ["op", "admission_id"],
"properties": {
"op": { "const": "telemetry" },
"admission_id": { "type": "string" },
"model": { "type": ["string", "null"] },
"runtime_ms": { "type": ["integer", "null"], "minimum": 0 },
"input_tokens": { "type": ["integer", "null"], "minimum": 0 },
"output_tokens": { "type": ["integer", "null"], "minimum": 0 },
"cache_tokens": { "type": ["integer", "null"], "minimum": 0 },
"cost_amount": { "type": ["number", "null"], "minimum": 0 },
"cost_currency": { "type": ["string", "null"] },
"cost_source": {
"type": ["string", "null"],
"description": "Provenance of cost/token numbers, e.g. provider_reported, statusline_estimate, session_delta, unavailable. Numbers WITHOUT an accurate source MUST be null with a warning (Plan-20 §5).",
"enum": [
"provider_reported",
"sdk_result_message",
"statusline_estimate",
"session_delta",
"unavailable",
null
]
}
}
},
"finalizeRequest": {
"required": ["op", "admission_id"],
"properties": {
"op": { "const": "finalize" },
"admission_id": { "type": "string" },
"stop_reason": {
"type": ["string", "null"],
"enum": ["completed", "user_interrupt", "error", "max_turns", "timeout", null]
},
"assistant_summary": { "type": ["string", "null"] },
"changed_files": {
"type": ["array", "null"],
"items": { "type": "string" }
}
}
},
"abortRequest": {
"required": ["op"],
"properties": {
"op": { "const": "abort" },
"admission_id": { "type": ["string", "null"] },
"reason": { "type": ["string", "null"] }
}
},
"bridgeResponse": {
"type": "object",
"required": ["op", "decision", "schema_version"],
"properties": {
"op": { "type": "string" },
"schema_version": { "type": "string" },
"decision": {
"type": "string",
"enum": ["allow", "block", "deny", "require_approval", "halt", "quarantine", "recorded", "certified", "non_certified", "error"]
},
"admission_id": { "type": ["string", "null"] },
"trace_id": { "type": ["string", "null"] },
"integration_mode": { "type": ["string", "null"] },
"certification_strength": {
"type": ["string", "null"],
"enum": ["casan_owned", "managed_hook", "project_hook", "observed_only", null]
},
"telemetry_quality": {
"type": ["string", "null"],
"enum": ["complete", "partial", "insufficient", null]
},
"reason": { "type": ["string", "null"] },
"warnings": { "type": "array", "items": { "type": "string" } },
"report_url": { "type": ["string", "null"], "format": "uri" },
"receipt": {
"type": "object",
"description": "Non-sensitive materialized pointer for CLI and dashboard discovery.",
"properties": {
"schema_version": { "const": 1 },
"trace_id": { "type": ["string", "null"] },
"project_id": { "type": ["string", "null"] },
"decision": { "type": "string" },
"certified": { "type": "boolean" },
"certification_strength": { "type": ["string", "null"] },
"telemetry_quality": { "type": ["string", "null"] },
"telemetry_warnings": { "type": "array", "items": { "type": "string" } },
"duration_ms": { "type": ["number", "null"] },
"tool_calls": { "type": "integer" },
"failures": { "type": "integer" },
"finalized_at": { "type": ["string", "null"] },
"report_url": { "type": ["string", "null"] },
"trace_path": { "type": "string" },
"delivery": {
"type": "string",
"enum": ["local_spool", "async_delivery_started"]
}
}
},
"context": {
"type": ["string", "null"],
"description": "Optional additional context the adapter may inject into the turn (e.g. certification banner)."
}
}
}
}
}