{ "openapi": "3.1.0", "info": { "title": "Bernstein Task Server", "description": "Bernstein REST API - deterministic orchestrator for CLI coding agents, one git worktree per task.\n\n## Authentication\n\nAuthentication is ENABLED by default. Include a Bearer token in all requests:\n\n```\nAuthorization: Bearer \n```\n\nTo run without auth (development only), set `BERNSTEIN_AUTH_DISABLED=1` - this logs a loud warning and passes every request through.\n\nPublic endpoints (no auth required): `/health`, `/health/ready`, `/health/live`, `/ready`, `/alive`, `/.well-known/agent.json`, `/docs`, `/openapi.json`, and the auth-flow endpoints (`/auth/login`, `/auth/oidc/callback`, etc.).\n\nWebhook and hook endpoints (`/webhook`, `/webhooks/*`, `/hooks/{session_id}`) authenticate via HMAC-SHA256 signatures - they do NOT accept Bearer tokens.\n\n## Base URL\n\nDefault: `http://127.0.0.1:8052`. Override with env vars `BERNSTEIN_HOST` and `BERNSTEIN_PORT`.\n\n## Error Format\n\nAll errors return JSON with a `detail` field:\n\n```json\n{\"detail\": \"Task not found: task-xyz\"}\n```\n\n| Status | Meaning |\n|--------|---------|\n| 400 | Bad request (validation error) |\n| 401 | Unauthorized (missing/invalid token) |\n| 403 | Forbidden (IP not in allowlist) |\n| 404 | Resource not found |\n| 409 | Conflict (task already in terminal state) |\n| 429 | Rate limited - respect the `Retry-After` header |\n| 500 | Internal server error |\n", "version": "1.0.0" }, "paths": { "/": { "get": { "summary": "Root", "operationId": "root__get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Response Root Get" } } } } } } }, "/tasks/search": { "get": { "summary": "Search Tasks", "description": "Search tasks with pagination, sorting, and filtering.\n\nQuery params:\n page: Page number (1-based, default 1).\n per_page: Items per page (1-100, default 20).\n sort: Sort field (created_at, priority, title, role, status).\n order: Sort order (asc, desc; default desc).\n status: Filter by task status.\n role: Filter by task role.\n assigned_agent: Filter by assigned agent.", "operationId": "search_tasks_tasks_search_get", "parameters": [ { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "default": 1, "title": "Page" } }, { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "default": 20, "title": "Per Page" } }, { "name": "sort", "in": "query", "required": false, "schema": { "type": "string", "default": "created_at", "title": "Sort" } }, { "name": "order", "in": "query", "required": false, "schema": { "type": "string", "default": "desc", "title": "Order" } }, { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } }, { "name": "role", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" } }, { "name": "assigned_agent", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Assigned Agent" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedSearchResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/agents": { "get": { "summary": "List Agents", "description": "Return a flat list of agent sessions for the web GUI grid.\n\nWhen ``TaskStore.agents`` is empty (e.g. only mock adapters spawned and\nthey never heartbeat) we fall back to synthesising one entry per\nclaimed/in-progress task, marked with ``\"synthetic\": true``. That keeps\nthe GUI grid populated during demos and avoids the dreaded \"0 sessions\"\nempty state when work is obviously in flight.", "operationId": "list_agents_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "additionalProperties": true, "type": "object" }, "type": "array", "title": "Response List Agents Agents Get" } } } } } } }, "/agents/comparison": { "get": { "tags": [ "agent-comparison" ], "summary": "Get Agent Comparison", "description": "Return per-(adapter, model) performance comparison metrics.\n\nAggregates data from all agent sessions in the current run:\nsuccess rate, average completion time, cost per task, and\nquality gate pass rate.\n\nReturns:\n JSON list of :class:`AgentMetrics` objects sorted by adapter\n then model.", "operationId": "get_agent_comparison_agents_comparison_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/AgentMetrics" }, "type": "array", "title": "Response Get Agent Comparison Agents Comparison Get" } } } } } } }, "/agents/{session_id}/logs": { "get": { "summary": "Agent Logs", "description": "Return log file content for a session.\n\nArgs:\n session_id: Agent session ID.\n tail_bytes: If > 0, return only the last N bytes of the log.", "operationId": "agent_logs_agents__session_id__logs_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } }, { "name": "tail_bytes", "in": "query", "required": false, "schema": { "type": "integer", "default": 0, "title": "Tail Bytes" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentLogsResponse" } } } }, "404": { "description": "No log file for session" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/agents/{session_id}/kill": { "post": { "summary": "Agent Kill", "description": "Request that an agent session be killed.\n\nWrites a ``.kill`` signal file that the orchestrator picks up on\nits next tick.", "operationId": "agent_kill_agents__session_id__kill_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentKillResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/agents/{session_id}/stream": { "get": { "summary": "Agent Stream", "description": "SSE stream of live log output for a session.", "operationId": "agent_stream_agents__session_id__stream_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/auth/providers": { "get": { "tags": [ "authentication" ], "summary": "Auth Providers", "description": "List available authentication providers.", "operationId": "auth_providers_auth_providers_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthProvidersResponse" } } } } } } }, "/auth/login": { "get": { "tags": [ "authentication" ], "summary": "Login", "description": "Initiate SSO login. Redirects to IdP.", "operationId": "login_auth_login_get", "parameters": [ { "name": "provider", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/LoginProvider", "default": "oidc" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Authentication provider not enabled" }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/auth/oidc/callback": { "get": { "tags": [ "authentication" ], "summary": "Oidc Callback", "description": "OIDC authorization code callback.", "operationId": "oidc_callback_auth_oidc_callback_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Missing or invalid authorization code or state" }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/auth/saml/acs": { "post": { "tags": [ "authentication" ], "summary": "Saml Acs", "description": "SAML Assertion Consumer Service (ACS) endpoint.\n\nReceives the SAML Response from the IdP via HTTP-POST binding.", "operationId": "saml_acs_auth_saml_acs_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Missing SAMLResponse" }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/auth/saml/metadata": { "get": { "tags": [ "authentication" ], "summary": "Saml Metadata", "description": "SAML SP metadata endpoint for IdP configuration.", "operationId": "saml_metadata_auth_saml_metadata_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/auth/cli/device": { "post": { "tags": [ "authentication" ], "summary": "Device Code Request", "description": "Initiate device authorization flow for CLI login.\n\nThe CLI calls this to get a device_code and user_code.\nThe user enters the user_code in the web dashboard after SSO login\nto authorize the CLI session.", "operationId": "device_code_request_auth_cli_device_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceCodeRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceCodeResponse" } } } }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/auth/cli/token": { "post": { "tags": [ "authentication" ], "summary": "Device Token Poll", "description": "Poll for device authorization status.\n\nReturns the access token once the user has authorized the device code.", "operationId": "device_token_poll_auth_cli_token_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DevicePollRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DevicePollResponse" } } } }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/auth/cli/authorize": { "post": { "tags": [ "authentication" ], "summary": "Device Authorize", "description": "Authorize a device code (called from web dashboard after SSO login).\n\nRequires an authenticated user session.", "operationId": "device_authorize_auth_cli_authorize_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceAuthorizeRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Invalid or expired user code" }, "401": { "description": "Authentication required" }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/auth/me": { "get": { "tags": [ "authentication" ], "summary": "Get Profile", "description": "Get the current authenticated user's profile.", "operationId": "get_profile_auth_me_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserProfileResponse" } } } }, "401": { "description": "Authentication required" } } } }, "/auth/logout": { "post": { "tags": [ "authentication" ], "summary": "Logout", "description": "Logout and revoke the current session.", "operationId": "logout_auth_logout_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/auth/group-mappings": { "get": { "tags": [ "authentication" ], "summary": "Get Group Mappings", "description": "Get current SSO group → role mappings.", "operationId": "get_group_mappings_auth_group_mappings_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GroupMappingsResponse" } } } }, "404": { "description": "SSO authentication is not configured on this server" } } }, "put": { "tags": [ "authentication" ], "summary": "Update Group Mappings", "description": "Update SSO group → role mappings (admin only).", "operationId": "update_group_mappings_auth_group_mappings_put", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GroupMappingsUpdateRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Invalid role value" }, "401": { "description": "Authentication required" }, "403": { "description": "Admin role required" }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/auth/users": { "get": { "tags": [ "authentication" ], "summary": "List Users", "description": "List all users (admin only).", "operationId": "list_users_auth_users_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "401": { "description": "Authentication required" }, "403": { "description": "Admin role required" }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/tasks": { "post": { "summary": "Create Task", "description": "Create a new task.", "operationId": "create_task_tasks_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCreate" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "400": { "description": "Blocked by pre-create hook" }, "403": { "description": "Tenant access denied" }, "404": { "description": "Tenant not found" }, "429": { "description": "Tenant task quota exceeded" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "List Tasks", "description": "List tasks, optionally filtered by status, cell_id, and/or claim owner.\n\nWhen ``limit`` or ``offset`` query params are provided the response is a\npaginated envelope (``{tasks, total, limit, offset}``). Without them,\nthe legacy flat list is returned for backward compatibility, capped at\n``_LIST_TASKS_HARD_CAP`` items and accompanied by a ``Deprecation``\nheader asking callers to pass explicit pagination.\n\nArgs:\n request: FastAPI request.\n status: If provided, only tasks with this status are returned.\n cell_id: If provided, only tasks in this cell are returned.\n tenant: Tenant scope override.\n claimed_by_session: If provided, only tasks claimed by this parent\n orchestrator session are returned.\n limit: Maximum number of tasks to return (max 500). Triggers\n paginated response when present.\n offset: Number of tasks to skip. Triggers paginated response\n when present.\n\nReturns:\n Paginated response **or** plain list of TaskResponse dicts (capped\n at ``_LIST_TASKS_HARD_CAP``).", "operationId": "list_tasks_tasks_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } }, { "name": "cell_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Cell Id" } }, { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } }, { "name": "claimed_by_session", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } }, { "name": "parent_session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Session Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Offset" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/batch": { "post": { "summary": "Create Tasks Batch", "description": "Create multiple tasks atomically with title dedup.", "operationId": "create_tasks_batch_tasks_batch_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchCreateRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchCreateResponse" } } } }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/self-create": { "post": { "summary": "Self Create Subtask", "description": "Create a subtask linked to a parent task.\n\nAgents call this to decompose work during execution. The parent\ntask is automatically transitioned to ``WAITING_FOR_SUBTASKS`` on\nthe first subtask creation (if it is not already in that state).", "operationId": "self_create_subtask_tasks_self_create_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSelfCreate" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Parent task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/next/{role}": { "get": { "summary": "Next Task", "description": "Claim the next available task for *role*.\n\nPass ``claimed_by_session`` as a query param to record which parent\norchestrator session owns the claim.\n\nPass ``parent_session_id`` to restrict claiming to tasks that were\ncreated under that coordinator session. Workers belonging to a\ncoordinator should always pass their coordinator's session ID here\nto avoid stealing tasks from other namespaces.", "operationId": "next_task_tasks_next__role__get", "parameters": [ { "name": "role", "in": "path", "required": true, "schema": { "type": "string", "title": "Role" } }, { "name": "claimed_by_session", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } }, { "name": "parent_session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/claim-batch": { "post": { "summary": "Claim Batch", "description": "Atomically claim multiple tasks by ID for an agent.", "operationId": "claim_batch_tasks_claim_batch_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchClaimRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchClaimResponse" } } } }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/claim": { "post": { "summary": "Claim Task", "description": "Claim a specific task by ID.\n\nPass ``expected_version`` as a query param for optimistic locking\n(CAS). If the task's version doesn't match, returns 409 Conflict.\n\nPass ``claimed_by_session`` to record which parent orchestrator\nsession owns this claim.", "operationId": "claim_task_tasks__task_id__claim_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } }, { "name": "expected_version", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Expected Version" } }, { "name": "claimed_by_session", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Version conflict or invalid state" }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/complete": { "post": { "summary": "Complete Task", "description": "Mark a task as done (or refused) from a worker terminal payload.\n\nStructured payloads (``body.payload`` or a JSON object embedded in\n``result_summary``) are validated against the worker completion\ncontract (#2244): an invalid payload is a typed ``contract_violation``\nfailure carrying the schema error path, and a validated refusal lands\nthe task in the terminal REFUSED state instead of DONE. Legacy prose\nsummaries are accepted unchanged.\n\nIf ``result_summary`` is empty the task is auto-transitioned to\n``FAILED`` with ``reason='completion missing summary'`` and\na 422 is returned with the failed task payload so the client knows the\nslot was released.", "operationId": "complete_task_tasks__task_id__complete_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCompleteRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Empty result_summary or contract violation - task auto-failed" } } } }, "/tasks/{task_id}/wait-for-subtasks": { "post": { "summary": "Wait For Subtasks", "description": "Mark a parent task as waiting until its generated subtasks complete.", "operationId": "wait_for_subtasks_tasks__task_id__wait_for_subtasks_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskWaitForSubtasksRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/fail": { "post": { "summary": "Fail Task", "description": "Mark a task as failed.", "operationId": "fail_task_tasks__task_id__fail_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskFailRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/release": { "post": { "summary": "Release Task", "description": "Release a claimed task back to the open pool without failing it.\n\nA cluster worker that claims a task but cannot start its agent (e.g. the\nworkspace is not a usable git checkout, or the adapter spawn fails) must\nreturn the task to the pool so another node can pick it up, rather than\nstranding it in ``claimed`` with no live agent (#3018). Distinct from\n``/fail`` (terminal FAILED) and ``/reopen`` (DONE -> OPEN): the task\ntransitions CLAIMED/IN_PROGRESS -> OPEN and is immediately claimable again.", "operationId": "release_task_tasks__task_id__release_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskReleaseRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/reopen": { "post": { "summary": "Reopen Task", "description": "Reopen a done task that failed janitor verification (same task id).\n\nTransitions DONE -> OPEN and increments\n``metadata['janitor_reopen_count']``. The orchestrator enforces the\nreopen budget; this endpoint only performs the state transition.", "operationId": "reopen_task_tasks__task_id__reopen_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskReopenRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/close": { "post": { "summary": "Close Task", "description": "Mark a verified task as closed (terminal success state).", "operationId": "close_task_tasks__task_id__close_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/cancel": { "post": { "summary": "Cancel Task", "description": "Cancel a task and cascade to all of its descendant subtasks.\n\nWalks the subtask tree (``parent_task_id`` references) via\n``TaskStore.cancel_cascade`` so that children are not left running\nafter the parent is aborted. Returns the root task.", "operationId": "cancel_task_tasks__task_id__cancel_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCancelRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/block": { "post": { "summary": "Block Task", "description": "Mark a task as blocked -- requires human intervention to unblock.", "operationId": "block_task_tasks__task_id__block_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskBlockRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/progress": { "post": { "summary": "Progress Task", "description": "Append an intermediate progress update to a task.\n\nAlso stores a progress snapshot for stall detection when snapshot\nfields (files_changed, tests_passing, errors) are provided.", "operationId": "progress_task_tasks__task_id__progress_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskProgressRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "Get Task Progress", "description": "Return the chain-computed progress vector for a task.\n\nThe ledger read is resolved from the task's own authoritative run id, never\nfrom a client-supplied parameter, so the vector cannot be steered by pairing\nthis task's journal with an arbitrary run's ledger.", "operationId": "get_task_progress_tasks__task_id__progress_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskProgressResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/partial-merge": { "post": { "summary": "Partial Merge Task", "description": "Incrementally merge specific committed files from the agent's branch into main.\n\nAllows a long-running agent to push a completed subset of its work (e.g.\nthe first 5 of 10 test files) while still writing the rest. Reduces\nwall-clock time by making partial results available downstream earlier.\n\nOnly files that are already **committed** in the agent's worktree branch\n(``agent/``) are merged. Uncommitted files are returned in\n``uncommitted_files`` so the caller knows to commit them in the worktree\nfirst. Files that were already merged by a prior call are skipped and\nreturned in ``skipped_already_merged``.\n\nRequires the task to be ``in_progress`` with a ``claimed_by_session`` set.", "operationId": "partial_merge_task_tasks__task_id__partial_merge_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartialMergeRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartialMergeResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Task not in progress or has no active session" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "Get Partial Merge State", "description": "Return the cumulative incremental-merge state for a task's active session.\n\nUseful for monitoring how much of an in-progress task's output has already\nbeen merged into the main branch.", "operationId": "get_partial_merge_state_tasks__task_id__partial_merge_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartialMergeResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/snapshots": { "get": { "summary": "Get Task Snapshots", "description": "Return stored progress snapshots for a task (oldest-first, up to 10).", "operationId": "get_task_snapshots_tasks__task_id__snapshots_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SnapshotEntry" }, "title": "Response Get Task Snapshots Tasks Task Id Snapshots Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/counts": { "get": { "summary": "Task Counts", "description": "Return task counts per status without serialising task bodies.\n\nThis is the lightweight alternative to GET /tasks for orchestrator\ntick summaries and dashboard polling.", "operationId": "task_counts_tasks_counts_get", "parameters": [ { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCountsResponse" } } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/archive": { "get": { "summary": "Get Archive", "description": "Return the last N archived (done/failed) task records.", "operationId": "get_archive_tasks_archive_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 50, "title": "Limit" } }, { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ArchiveRecord" }, "title": "Response Get Archive Tasks Archive Get" } } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/graph": { "get": { "summary": "Get Task Graph", "description": "Return the task dependency graph as JSON (nodes + edges + critical path).\n\nBuilds a DAG from all current tasks and returns:\n- ``nodes``: list of {id, role, status, estimated_minutes, title}\n- ``edges``: list of {from, to, type, semantic_type}\n- ``critical_path``: ordered list of task IDs on the longest chain\n- ``critical_path_minutes``: total estimated minutes on the critical path\n- ``parallel_width``: max tasks that can run concurrently\n- ``bottlenecks``: task IDs that block the most downstream work", "operationId": "get_task_graph_tasks_graph_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" } } } }, "/tasks/{task_id}": { "get": { "summary": "Get Task", "description": "Get a single task by ID.", "operationId": "get_task_tasks__task_id__get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "patch": { "summary": "Patch Task", "description": "Update mutable task fields (role, priority, model) - manager corrections.\n\nUsed by the manager agent or dashboard to correct mis-assigned tasks,\nadjust priority, or change model without interrupting the orchestrator.", "operationId": "patch_task_tasks__task_id__patch", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskPatchRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/graph-neighbors": { "get": { "summary": "Get Task Graph Neighbors", "description": "Return immediate dependency neighbours for a single task.\n\nPowers the dashboard Deps tab: upstream tasks the requested one waits\non (its ``depends_on`` list) and downstream tasks that declare it as a\ndependency. Depth is intentionally fixed at 1 - the panel renders two\nflat lists, not a transitive graph.", "operationId": "get_task_graph_neighbors_tasks__task_id__graph_neighbors_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Task Graph Neighbors Tasks Task Id Graph Neighbors Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/gates": { "get": { "summary": "Get Task Gates", "description": "Return the persisted quality-gate report for a task.", "operationId": "get_task_gates_tasks__task_id__gates_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Task or gate report not found" }, "500": { "description": "Gate report unreadable" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/prioritize": { "post": { "summary": "Prioritize Task", "description": "Bump a task to priority 0 so the orchestrator picks it up next.", "operationId": "prioritize_task_tasks__task_id__prioritize_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/force-claim": { "post": { "summary": "Force Claim Task", "description": "Force a task back to open with priority 0 for immediate pickup.\n\nResets claimed/in_progress tasks back to open so the orchestrator's\nnext tick will spawn a fresh agent for them. Terminal tasks\n(done/failed/cancelled) are rejected with 409.", "operationId": "force_claim_task_tasks__task_id__force_claim_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Cannot force-claim terminal task" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/agents/{agent_id}/heartbeat": { "post": { "summary": "Agent Heartbeat", "description": "Register an agent heartbeat.", "operationId": "agent_heartbeat_agents__agent_id__heartbeat_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HeartbeatRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HeartbeatResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/bulletin": { "post": { "summary": "Post Bulletin", "description": "Append a message to the bulletin board.\n\nReturns 201 when the message is stored and any registered signal action\nran. When a signal action hook fails (for example a ``blocker`` whose\nclearance gate did not materialize), the message is still on the\nappend-only board and queued in the board's retry outbox, but the action is\nnot complete: the response is 202 rather than 201 so the caller can tell\n\"stored and acted on\" from \"stored, action pending retry\" (#2648).", "operationId": "post_bulletin_bulletin_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulletinPostRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulletinMessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "Get Bulletin", "description": "Get bulletin messages since a given timestamp.", "operationId": "get_bulletin_bulletin_get", "parameters": [ { "name": "since", "in": "query", "required": false, "schema": { "type": "number", "default": 0.0, "title": "Since" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/BulletinMessageResponse" }, "title": "Response Get Bulletin Bulletin Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/channel/query": { "post": { "summary": "Post Channel Query", "description": "Post a coordination query targeted at an agent or role.", "operationId": "post_channel_query_channel_query_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelQueryRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelQueryResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/channel/{query_id}/respond": { "post": { "summary": "Post Channel Response", "description": "Respond to a channel query.", "operationId": "post_channel_response_channel__query_id__respond_post", "parameters": [ { "name": "query_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Query Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelResponseRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelResponseResponse" } } } }, "404": { "description": "Query not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/channel/queries": { "get": { "summary": "Get Channel Queries", "description": "Get pending queries, optionally filtered by agent_id or role.", "operationId": "get_channel_queries_channel_queries_get", "parameters": [ { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Agent Id" } }, { "name": "role", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ChannelQueryResponse" }, "title": "Response Get Channel Queries Channel Queries Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/channel/{query_id}/responses": { "get": { "summary": "Get Channel Responses", "description": "Get all responses for a channel query.", "operationId": "get_channel_responses_channel__query_id__responses_get", "parameters": [ { "name": "query_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Query Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ChannelResponseResponse" }, "title": "Response Get Channel Responses Channel Query Id Responses Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/claim-receipt": { "post": { "summary": "Claim Receipt", "description": "Claim the next eligible backlog row and return a signed claim receipt.\n\nThe dependency gate is enforced by :class:`ClaimFilter`: a row is offered\nonly when its ``depends_on`` are all in ``completed_ids``. The granted\nclaim is mirrored into the audit chain via the existing\n``record_task_claim_receipt`` (no new event type), and the returned\nreceipt embeds that event's chain head so the claim verifies offline. A\nfilter matching no eligible row returns a signed refusal receipt.", "operationId": "claim_receipt_tasks_claim_receipt_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClaimReceiptRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Claim Receipt Tasks Claim Receipt Post" } } } }, "503": { "description": "Server is draining -- no new claims accepted" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/messages": { "post": { "summary": "Post Task Message", "description": "Append one typed message to the recipient task's mailbox.\n\nThe message is DLP-redacted, HMAC-chained onto the mailbox journal,\nEd25519-signed, and mirrored into the audit chain before the response\nis returned - the response IS the signed journal entry.", "operationId": "post_task_message_tasks__task_id__messages_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskMessagePost" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskMessageResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Unknown message kind or body over the byte cap" }, "429": { "description": "Recipient task mailbox is full" } } }, "get": { "summary": "Get Task Messages", "description": "Deliver pending messages for a task, in chain append order.\n\n``since_seq`` is a deterministic cursor: pass the highest ``seq``\nalready processed to receive only newer messages. Replaying the same\njournal always reproduces the same delivery order.", "operationId": "get_task_messages_tasks__task_id__messages_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } }, { "name": "since_seq", "in": "query", "required": false, "schema": { "type": "integer", "default": -1, "title": "Since Seq" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/TaskMessageResponse" }, "title": "Response Get Task Messages Tasks Task Id Messages Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/artifacts": { "post": { "summary": "Post Task Artifact", "description": "Post one journal-anchored artifact against a task the caller holds.", "operationId": "post_task_artifact_tasks__task_id__artifacts_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskArtifactPost" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskArtifactContentResponse" } } } }, "403": { "description": "Caller does not hold the task's claim" }, "404": { "description": "Task not found" }, "413": { "description": "Artifact payload exceeds the per-blob cap" }, "422": { "description": "Invalid artifact payload" } } }, "get": { "summary": "List Task Artifacts", "description": "List every posted artifact version with its verification state.", "operationId": "list_task_artifacts_tasks__task_id__artifacts_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/TaskArtifactContentResponse" }, "title": "Response List Task Artifacts Tasks Task Id Artifacts Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/tasks/{task_id}/steer": { "post": { "summary": "Post Task Steer", "description": "Record a steering receipt for a running worker and apply its effect.\n\nThe receipt is bound into the audit chain before the effect executes; the\n``steer.*`` mailbox message and any process signal reference the receipt\nhash returned here. An effect can never precede its receipt.", "operationId": "post_task_steer_tasks__task_id__steer_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSteerPost" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSteerResponse" } } } }, "403": { "description": "Scope is not authorised to steer" }, "404": { "description": "Task not found" }, "409": { "description": "Confirmed payload differs from the executed command" }, "422": { "description": "Malformed steering command" }, "503": { "description": "Task mailbox is not configured" } } } }, "/cluster/nodes": { "post": { "summary": "Register Node", "description": "Register a new node in the cluster.", "operationId": "register_node_cluster_nodes_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeRegisterRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeResponse" } } } }, "401": { "description": "Cluster authentication failed" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "List Nodes", "description": "List all cluster nodes, optionally filtered by status.", "operationId": "list_nodes_cluster_nodes_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/NodeResponse" }, "title": "Response List Nodes Cluster Nodes Get" } } } }, "400": { "description": "Invalid node status" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/nodes/{node_id}/heartbeat": { "post": { "summary": "Node Heartbeat", "description": "Record a heartbeat from a cluster node.", "operationId": "node_heartbeat_cluster_nodes__node_id__heartbeat_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeHeartbeatRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeResponse" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not registered" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/nodes/{node_id}": { "delete": { "summary": "Unregister Node", "description": "Remove a node from the cluster.", "operationId": "unregister_node_cluster_nodes__node_id__delete", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "204": { "description": "Successful Response" }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/nodes/{node_id}/cordon": { "post": { "summary": "Cordon Node", "description": "Cordon a node -- exclude from scheduling.", "operationId": "cordon_node_cluster_nodes__node_id__cordon_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Cordon Node Cluster Nodes Node Id Cordon Post" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/nodes/{node_id}/uncordon": { "post": { "summary": "Uncordon Node", "description": "Uncordon a node -- resume accepting tasks.", "operationId": "uncordon_node_cluster_nodes__node_id__uncordon_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Uncordon Node Cluster Nodes Node Id Uncordon Post" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/nodes/{node_id}/drain": { "post": { "summary": "Drain Node", "description": "Start draining a node -- cordon + signal agents to finish.", "operationId": "drain_node_cluster_nodes__node_id__drain_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Drain Node Cluster Nodes Node Id Drain Post" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/status": { "get": { "summary": "Cluster Status", "description": "Get cluster status summary.", "operationId": "cluster_status_cluster_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClusterStatusResponse" } } } } } } }, "/cluster/claims/gossip": { "post": { "summary": "Gossip Claims", "description": "Fold peer claim receipts into this node's signed journal (#2558).\n\nThe leaderless counterpart to ``POST /cluster/steal``: no node decides who\ngets what here. Each receipt is folded only after its Ed25519 signature and\nits chain link both verify, so an unverifiable receipt is never written.\n\nA receipt that does not extend the local head is *not* merged. It produces\na signed ``fork`` receipt carrying the divergence entry index, which the\nresponse surfaces through ``forked``. Silent merge would be the one failure\nmode a leaderless design cannot recover from: two partitions would each\nhold a coherent-looking journal describing incompatible work.\n\nAuthorisation reuses the node-heartbeat scope: gossip is a peer-to-peer\nfleet-membership operation, not an administrative one.", "operationId": "gossip_claims_cluster_claims_gossip_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClaimGossipRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClaimGossipResponse" } } } }, "401": { "description": "Cluster authentication failed" }, "409": { "description": "Node is not running the MESH topology" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/cluster/steal": { "post": { "summary": "Steal Tasks", "description": "Evaluate task stealing policy and reassign claimed tasks between nodes.\n\nWorkers report their queue depths; the server runs the steal policy and\nreturns a list of task reassignments. Stolen tasks are reset to ``open``\nso the receiver node can claim them.", "operationId": "steal_tasks_cluster_steal_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskStealRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskStealResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/a2a/agent-card": { "get": { "summary": "Agent Card", "description": "Publish the Bernstein orchestrator Agent Card (legacy A2A path).\n\nThe richer service manifest at ``/.well-known/agent.json`` is served by\n``routes.well_known``; this endpoint is preserved for callers that\nhistorically pulled the orchestrator's own A2A card.", "operationId": "agent_card_a2a_agent_card_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AAgentCardResponse" } } } } } } }, "/a2a/agents": { "get": { "summary": "List A2A Agents", "description": "Return Bernstein's A2A agent card via the task API namespace.", "operationId": "list_a2a_agents_a2a_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AAgentCardResponse" } } } } } } }, "/a2a/message": { "post": { "summary": "A2A Message", "description": "Receive an inbound A2A message and inject it into the target task context.", "operationId": "a2a_message_a2a_message_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AMessageRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AMessageResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/a2a/tasks/send": { "post": { "summary": "A2A Send Task", "description": "Receive a task from an external A2A agent.\n\nCreates both an A2A task record and a corresponding Bernstein task,\nlinking them together for lifecycle synchronisation.", "operationId": "a2a_send_task_a2a_tasks_send_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2ATaskSendRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2ATaskResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/a2a/tasks/{a2a_task_id}": { "get": { "summary": "A2A Get Task", "description": "Get an A2A task by ID, syncing status from the Bernstein task.", "operationId": "a2a_get_task_a2a_tasks__a2a_task_id__get", "parameters": [ { "name": "a2a_task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "A2A Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2ATaskResponse" } } } }, "404": { "description": "A2A task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/a2a/tasks/{a2a_task_id}/artifacts": { "post": { "summary": "A2A Add Artifact", "description": "Attach an artifact to an A2A task.", "operationId": "a2a_add_artifact_a2a_tasks__a2a_task_id__artifacts_post", "parameters": [ { "name": "a2a_task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "A2A Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AArtifactRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AArtifactResponse" } } } }, "404": { "description": "A2A task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/a2a/v0/tasks": { "post": { "summary": "A2A V0 Accept Task", "description": "Accept a federated task delegated from a peer orchestrator.\n\nWire format::\n\n {\n \"sender\": { ...AgentCard... },\n \"task\": { \"id\": \"...\", \"message\": \"...\", \"role\": \"...\" }\n }\n\nReturns 202 with the local federated-task id and the remote task id\nthat was offered. Validation errors return HTTP 409 so that the\ncaller's retry policy treats them as terminal (the peer is reachable\nand authoritative, no point retrying with the same body).", "operationId": "a2a_v0_accept_task_a2a_v0_tasks_post", "responses": { "202": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response A2A V0 Accept Task A2A V0 Tasks Post" } } } }, "400": { "description": "Invalid sender Agent Card or task body" }, "409": { "description": "Task rejected (validation, capacity, etc.)" } } } }, "/status": { "get": { "summary": "Status Dashboard", "description": "Dashboard summary of task counts.", "operationId": "status_dashboard_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/status/duration-predictions": { "get": { "summary": "Duration Predictions", "description": "Return ML-predicted duration estimates for all open/claimed tasks.\n\nUses the local GradientBoosting duration predictor. Falls back to the\nstatic cold-start table when fewer than 50 completions are available.\n\nResponse shape::\n\n {\n \"predictor\": {\n \"trained\": true,\n \"training_samples\": 142,\n \"cold_start\": false\n },\n \"tasks\": [\n {\n \"task_id\": \"abc123\",\n \"title\": \"Refactor auth module\",\n \"role\": \"backend\",\n \"p50_seconds\": 720.0,\n \"p90_seconds\": 1440.0,\n \"confidence\": 0.62,\n \"is_cold_start\": false,\n \"eta_p50\": \"12m 0s\",\n \"eta_p90\": \"24m 0s\"\n }\n ]\n }", "operationId": "duration_predictions_status_duration_predictions_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/routing/bandit": { "get": { "summary": "Bandit Routing Stats", "description": "Return contextual bandit routing statistics.\n\nReads persisted state from ``.sdd/routing/``. Returns an empty dict\nwhen bandit routing has not been activated (``--routing bandit`` not passed).", "operationId": "bandit_routing_stats_routing_bandit_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/dashboard": { "get": { "summary": "Dashboard Page", "description": "Serve the single-page web dashboard.", "operationId": "dashboard_page_dashboard_get", "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } } } } }, "/dashboard/static/{asset_name}": { "get": { "summary": "Dashboard Static Asset", "description": "Serve allow-listed static assets used by the web dashboard.", "operationId": "dashboard_static_asset_dashboard_static__asset_name__get", "parameters": [ { "name": "asset_name", "in": "path", "required": true, "schema": { "type": "string", "title": "Asset Name" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/data": { "get": { "summary": "Dashboard Data", "description": "Return all mission control dashboard data as JSON.\n\nIncludes stats, tasks with timeline data, agent details with costs,\nfile ownership map, cost history, and alerts.", "operationId": "dashboard_data_dashboard_data_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/events": { "get": { "summary": "Sse Events", "description": "Server-Sent Events stream for real-time dashboard updates.\n\nIncludes disconnect detection via heartbeat pings and connection\ntimeout handling to prevent leaked subscriber queues.", "operationId": "sse_events_events_get", "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } } } } }, "/badge.json": { "get": { "summary": "Get Badge", "description": "Return dynamic badge data for GitHub shields.io integration.\n\nShows tasks completed, total cost, and quality score.\nUsage: https://img.shields.io/endpoint?url=/badge.json", "operationId": "get_badge_badge_json_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/memory/audit": { "get": { "summary": "Memory Audit", "description": "Audit the lesson memory provenance chain (OWASP ASI06 2026).\n\nReturns chain integrity status and a per-entry provenance trail.\nDetects tampering, insertion, deletion, and reordering attacks.", "operationId": "memory_audit_memory_audit_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/broadcast": { "post": { "summary": "Broadcast Command", "description": "Send a message to all running agents via fastest available channel.\n\nUses stdin pipe where available (sub-second delivery), falls back\nto file-based COMMAND signal for agents without pipe support.\n\nExpects JSON body: ``{\"message\": \"some instruction\"}``.", "operationId": "broadcast_command_broadcast_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BroadcastRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/health": { "get": { "summary": "Health Check", "description": "Liveness check with component-level status.", "operationId": "health_check_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } } } }, "/health/ready": { "get": { "summary": "Ready Check", "description": "Readiness check for load balancers.", "operationId": "ready_check_health_ready_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/ready": { "get": { "summary": "Ready Alias", "description": "Alias for /health/ready.", "operationId": "ready_alias_ready_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/health/live": { "get": { "summary": "Live Check", "description": "Liveness check for process monitoring.", "operationId": "live_check_health_live_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/alive": { "get": { "summary": "Live Alias", "description": "Alias for /health/live.", "operationId": "live_alias_alive_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/config": { "post": { "summary": "Update Config", "description": "Update mutable config fields at runtime.\n\nAccepts JSON body with ``{\"max_agents\": N}``. Writes the change to\n``bernstein.yaml`` so the orchestrator's hot-reload picks it up on\nthe next tick (~30s). Returns the new effective value.\n\nAgent identity JWTs (per-agent, task-scoped) are rejected with 403 -\nmutating process-wide config is an operator action. SSO admin users\nand legacy operator tokens may proceed. Bearer-level permission\nenforcement is handled by :class:`SSOAuthMiddleware` via the\n``admin:manage`` mapping; this check adds defense-in-depth against any\nagent JWT that slips through the middleware's prefix match.", "operationId": "update_config_config_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/shutdown": { "post": { "summary": "Shutdown Server", "description": "Initiate graceful server shutdown.\n\nAccepts an optional JSON body ``{\"reason\": \"...\"}``. Schedules a\nSIGTERM to the current process shortly after the response is sent so\nthat the Uvicorn server exits cleanly.", "operationId": "shutdown_server_shutdown_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/cache-stats": { "get": { "summary": "Cache Stats", "description": "Return prompt caching statistics from the manifest.\n\nReads `.sdd/caching/manifest.jsonl` and returns aggregated counts,\nestimated token savings, and estimated USD savings based on the\nAnthropic cached-input discount (90% off standard input price).\n\nReturns 200 with empty statistics if no cache manifest exists yet.", "operationId": "cache_stats_cache_stats_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/metrics": { "get": { "summary": "Metrics Endpoint", "description": "Prometheus metrics scrape endpoint.\n\nUpdates all gauges from the current task store state, then\nreturns the full metric exposition in Prometheus text format.", "operationId": "metrics_endpoint_metrics_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/workspace": { "get": { "tags": [ "workspace" ], "summary": "Workspace Status", "description": "Return repository status for the configured workspace.", "operationId": "workspace_status_workspace_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkspaceResponse" } } } }, "400": { "description": "Invalid seed file" } } } }, "/workspace/merge-order": { "post": { "tags": [ "workspace" ], "summary": "Workspace Merge Order", "description": "Return the repo merge order derived from current cross-repo task dependencies.", "operationId": "workspace_merge_order_workspace_merge_order_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MergeOrderResponse" } } } }, "400": { "description": "Invalid seed file" }, "404": { "description": "No workspace configured" } } } }, "/alerts": { "get": { "summary": "Get Alerts", "description": "Return current dashboard alerts as JSON.\n\nBuilds alerts from the live task/agent state - failed tasks, blocked\ntasks, stale agents, and budget thresholds. Intended for dashboard\npolling or external monitoring.\n\nReturns a JSON object with keys:\n- ``alerts``: list of alert dicts (``level``, ``message``, ``detail``)\n- ``count``: total number of alerts\n- ``ts``: server timestamp (Unix seconds)", "operationId": "get_alerts_alerts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhook": { "post": { "summary": "Generic Webhook", "description": "Create a task directly from a generic inbound webhook payload.\n\nThe endpoint is intentionally small and separate from the trigger-manager\nflow: callers POST a task-shaped payload and Bernstein creates one task.\n``BERNSTEIN_WEBHOOK_SECRET`` must be configured (fail-closed; )\nand each request must carry a fresh ``X-Bernstein-Timestamp`` header\nplus a matching ``X-Bernstein-Webhook-Signature-256`` HMAC over\n``f\"{timestamp}.\".encode() + body``. The plaintext\n``X-Bernstein-Webhook-Secret`` fallback has been removed; callers\nrelying on it must upgrade to the HMAC + timestamp flow.\n\nAutomation bridge (#2512): an admitted trigger returns a signed,\nchain-anchored trigger receipt in ``receipt`` so the calling platform holds\na proof of what it asked for rather than a bare task reference. A trigger\nthat fails authentication, or that replays a trigger id already admitted,\nis refused with its own signed refusal receipt (HTTP 401 and 409\nrespectively) -- the negative path leaves a record, never a silent drop.", "operationId": "generic_webhook_webhook_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookTaskCreate" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookTaskResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/webhooks/github": { "post": { "summary": "Github Webhook", "description": "Receive a GitHub App webhook, verify signature, and create tasks.\n\nHandles the following event types:\n- ``issues`` (opened / labeled)\n- ``pull_request_review_comment`` / ``issue_comment``\n- ``push``\n- ``workflow_run`` (completed + failure) - creates a ci-fix task, capped at\n ``MAX_CI_RETRIES`` active attempts per branch.\n\nReads ``GITHUB_WEBHOOK_SECRET`` from environment for HMAC verification.\nFail-closed: when the secret is not configured the\nendpoint is disabled and returns 503; unsigned GitHub webhooks are\nnever accepted.\nReplay protection: if the caller includes an\n``X-Bernstein-Timestamp`` header the request is additionally\nchecked for freshness - drift greater than five minutes returns\n401. Real GitHub deliveries omit this header and continue to\nwork; the check is there so bernstein-internal relays cannot be\nreplayed after capture.\nReturns 200 on success, 401 on bad/missing signature or stale\ntimestamp, 400 on parse error, 503 when the endpoint is not\nconfigured.", "operationId": "github_webhook_webhooks_github_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/gitlab": { "post": { "summary": "Gitlab Webhook", "description": "Receive a GitLab CI webhook, verify token, and create ci-fix tasks.\n\nHandles the following event types:\n- ``pipeline`` (failed) - creates a ci-fix task, capped at\n ``MAX_CI_RETRIES`` active attempts per branch.\n- ``job`` (failed) - creates a ci-fix task for the specific job.\n\nReads ``GITLAB_WEBHOOK_TOKEN`` from environment. GitLab sends a simple\nplaintext token in the ``x-gitlab-token`` header.\nReturns 200 on success, 401 on bad/missing token.", "operationId": "gitlab_webhook_webhooks_gitlab_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/telemetry/sentry/": { "post": { "summary": "Telemetry Sentry", "description": "Receive a Sentry-protocol issue-alert webhook.", "operationId": "telemetry_sentry_webhooks_telemetry_sentry__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/telemetry/gha_failure/": { "post": { "summary": "Telemetry Gha Failure", "description": "Receive a GitHub Actions ``workflow_run`` failure webhook.", "operationId": "telemetry_gha_failure_webhooks_telemetry_gha_failure__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/telemetry/datadog/": { "post": { "summary": "Telemetry Datadog", "description": "Receive a Datadog Logs webhook (stubbed in MVP).", "operationId": "telemetry_datadog_webhooks_telemetry_datadog__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/telemetry/loki/": { "post": { "summary": "Telemetry Loki", "description": "Receive a Loki / Alertmanager webhook (stubbed in MVP).", "operationId": "telemetry_loki_webhooks_telemetry_loki__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/telemetry/custom_jsonl/": { "post": { "summary": "Telemetry Custom Jsonl", "description": "Receive a custom JSONL tail webhook (stubbed in MVP).", "operationId": "telemetry_custom_jsonl_webhooks_telemetry_custom_jsonl__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/trackers/{adapter}": { "post": { "summary": "Tracker Webhook", "description": "Receive a tracker webhook, verify, dedupe, and enqueue.\n\nPath parameter:\n adapter: Short adapter name registered via\n :func:`bernstein.core.trackers.webhook_receiver.register_handler`.\n\nThe endpoint accepts any JSON object. All verification and replay\ndecisions are made before the body is enqueued. When verification\nsucceeds and the delivery is fresh the parsed\n:class:`~bernstein.core.trackers.webhook_receiver.TrackerEvent` is\nstashed on ``app.state.tracker_event_queue`` if present so the\norchestrator's normal task ingestion can drain it; if no queue is\nwired we simply log the event. Either way the tracker receives a\n200 so it does not retry.", "operationId": "tracker_webhook_webhooks_trackers__adapter__post", "parameters": [ { "name": "adapter", "in": "path", "required": true, "schema": { "type": "string", "title": "Adapter" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/webhooks/discord/interactions": { "post": { "summary": "Discord Interactions", "description": "Receive and route Discord Application Command interactions.\n\nVerifies the Ed25519 signature, handles PING handshakes, and dispatches\nslash commands to the appropriate handler. Returns an immediate response\n(Discord requires a reply within 3 seconds).\n\nReturns:\n 200 with a Discord interaction response object on success.\n 401 if the signature is invalid.\n 400 if the payload cannot be parsed.", "operationId": "discord_interactions_webhooks_discord_interactions_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/slack/commands": { "post": { "summary": "Slack Slash Command", "description": "Receive a Slack slash command, verify signature, and ack immediately.\n\nSlack requires a response within 3 seconds. This endpoint verifies the\nrequest signature, parses the URL-encoded form payload, and returns an\nimmediate acknowledgement. Any long-running work (task creation, etc.)\nshould be dispatched asynchronously using ``response_url``.\n\nReads ``SLACK_SIGNING_SECRET`` from environment for HMAC verification.\nReturns 200 on success, 401 on bad/missing signature, 400 on parse error.\n\nSlash command form fields parsed:\n - ``command`` - the slash command (e.g. ``/bernstein``)\n - ``text`` - text following the command\n - ``user_id`` - Slack user ID\n - ``channel_id`` - Slack channel ID\n - ``response_url`` - URL for delayed responses (up to 30 min)\n - ``trigger_id`` - trigger ID for opening modals", "operationId": "slack_slash_command_webhooks_slack_commands_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/webhooks/slack/events": { "post": { "summary": "Slack Events", "description": "Receive Slack Events API callbacks.\n\nHandles:\n- ``url_verification``: returns the challenge value for endpoint verification.\n- ``event_callback`` with ``message`` type: creates a task when the bot is\n mentioned. Bot messages and ``message_changed`` subtypes are ignored to\n prevent loops.\n\nReads ``SLACK_SIGNING_SECRET`` from environment for HMAC verification.\nReturns 200 on success, 401 on bad/missing signature, 400 on parse error.", "operationId": "slack_events_webhooks_slack_events_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/events/cost": { "get": { "summary": "Cost Events", "description": "SSE endpoint for real-time cost updates.\n\nListens to the global SSE bus for ``bulletin`` events that match\nthe ``live_cost_update`` status pattern and forwards them to clients.\nAlso provides periodic heartbeats.", "operationId": "cost_events_events_cost_get", "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } } } } }, "/costs": { "get": { "summary": "Get Costs", "description": "Aggregate cost data across all runs.\n\nScans every persisted cost file in ``.sdd/runtime/costs/``, aggregates\nper-agent and per-model totals, and computes cost attainment as\n``(total_spent / total_budget) * 100``. Budget of zero is treated as\nunlimited - attainment is reported as 0.0 in that case.", "operationId": "get_costs_costs_get", "parameters": [ { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant access denied" }, "404": { "description": "Tenant not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/live": { "get": { "summary": "Get Cost Live", "description": "Return live cost breakdown for the most recent run.\n\nFinds the most recently modified cost file in ``.sdd/runtime/costs/``,\nloads it, and returns budget status plus per-agent and per-model\ncost breakdowns.", "operationId": "get_cost_live_costs_live_get", "parameters": [ { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant access denied" }, "404": { "description": "Tenant not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/current": { "get": { "summary": "Get Cost Current", "description": "Return real-time cost snapshot for the active run + GUI rollups.\n\nUpdated after each agent completion. Designed for TUI sidebar polling\nand lightweight dashboard widgets. Returns per-model input/output/cache\ntoken breakdown alongside spend and budget status.\n\nWeb GUI (Costs.tsx §6.05) consumes the additive ``today_usd``,\n``week_usd``, ``projected_month_usd``, ``budget_usd``, ``used_pct``,\n``prior_week_usd``, ``delta_hour_usd``, ``resets_at`` and\n``last_sync_at`` fields. Existing TUI/CLI callers keep reading\n``spent_usd`` / ``percentage_used`` etc. unchanged.", "operationId": "get_cost_current_costs_current_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/alerts": { "get": { "summary": "Get Cost Alerts", "description": "Return active budget alerts and 30d/90d cost trends.\n\nReads the live cost data for the most recent run, checks whether spend\nhas reached the 80% or 95% alert threshold, and returns trend data\ncomputed from ``.sdd/metrics/cost_history.jsonl``.", "operationId": "get_cost_alerts_costs_alerts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/history": { "get": { "summary": "Get Cost History", "description": "Return cost history for chart visualization.\n\nTwo response modes share one endpoint:\n\n* ``GET /costs/history?hours=24&granularity=hour`` (web GUI sparkline) -\n returns a flat ``[{ts, usd}]`` array bucketed from cost-tracker\n usages over the last *hours* window.\n* ``GET /costs/history`` *or* ``?envelope=1`` (legacy/CLI) - returns the\n original ``{history, trend, burn_rate_*, history_days}`` envelope\n built from ``.sdd/metrics/cost_history.jsonl`` daily snapshots.\n\nThe sparkline branch lets the GUI feed `recharts` directly without\nunwrapping a ``.history`` field.", "operationId": "get_cost_history_costs_history_get", "parameters": [ { "name": "hours", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Hours" } }, { "name": "granularity", "in": "query", "required": false, "schema": { "type": "string", "default": "day", "title": "Granularity" } }, { "name": "envelope", "in": "query", "required": false, "schema": { "type": "integer", "default": 0, "title": "Envelope" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/export": { "get": { "summary": "Export Costs", "description": "Export cost data as CSV or JSON for finance analysis.\n\nArgs:\n request: FastAPI request.\n format: Export format ('csv' or 'json').\n\nReturns:\n File response with cost data in requested format.", "operationId": "export_costs_costs_export_get", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "json", "title": "Format" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/forecast": { "get": { "summary": "Forecast Costs", "description": "Forecast cost for next hour and project monthly spend.\n\nExtrapolates current spending rate to predict next hour's cost AND\nrolls the trailing 7-day spend out to a 30-day projection\n(``projected_month_usd``) for the web GUI's \"projected month\" KPI\ncard. The legacy fields (``forecast_next_hour_usd``,\n``burn_rate_*``, ``confidence``, ``data_points``) remain unchanged\nfor the TUI / CLI.", "operationId": "forecast_costs_costs_forecast_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/compare": { "get": { "summary": "Compare Model Costs", "description": "Return live model cost comparison during execution.\n\nShows current costs by model with token usage statistics.", "operationId": "compare_model_costs_costs_compare_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/cache-stats": { "get": { "summary": "Cache Stats", "description": "Return prompt cache hit rate statistics.\n\nShows cache hits/misses and savings by model.", "operationId": "cache_stats_costs_cache_stats_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/model-comparison": { "get": { "summary": "Model Cost Comparison", "description": "Return model cost comparison report.\n\nShows what the current run would have cost with different models.\nUseful for optimizing model routing decisions.", "operationId": "model_cost_comparison_costs_model_comparison_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/token-efficiency": { "get": { "summary": "Token Efficiency", "description": "Compare token efficiency across models and tasks.\n\nRanks models by tokens per useful line of code.", "operationId": "token_efficiency_costs_token_efficiency_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/by-tag": { "get": { "summary": "Get Costs By Tag", "description": "Aggregate cost data grouped by allocation tag *or* by adapter.\n\nThe endpoint serves three callers:\n\n* Web GUI (``Costs.tsx`` adapter table) - calls ``GET /costs/by-tag``\n and expects an array of ``{adapter, calls, tokens, cost_usd,\n share_pct, delta_7d_pct}`` rows. With ``shape=auto`` (default) and\n no ``tag_key``, this is what we return.\n* Legacy callers passing ``tag_key=…`` - receive the existing\n ``{by_tag: {key: {value: cost}}}`` envelope.\n* Legacy callers wanting the envelope explicitly - pass\n ``shape=tags`` and get the envelope without supplying a key.\n\nThe ``hours`` parameter controls the GUI window (default 24h).", "operationId": "get_costs_by_tag_costs_by_tag_get", "parameters": [ { "name": "tag_key", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tag Key" } }, { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "default": 24, "title": "Hours" } }, { "name": "shape", "in": "query", "required": false, "schema": { "type": "string", "default": "auto", "title": "Shape" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/by-adapter": { "get": { "summary": "Get Costs By Adapter", "description": "Per-adapter cost breakdown for the web GUI Costs tab.\n\nReturns the same array shape as ``GET /costs/by-tag`` (default mode);\nexists as a clearer alias so the frontend doesn't have to know about\nthe legacy \"by-tag\" naming.", "operationId": "get_costs_by_adapter_costs_by_adapter_get", "parameters": [ { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "default": 24, "title": "Hours" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/top-tasks": { "get": { "summary": "Get Costs Top Tasks", "description": "Top *limit* most-expensive tasks within the trailing *hours* window.\n\nWeb GUI Costs.tsx renders this as the \"Top 10 tasks\" card. Each item:\n``{id, title, agent, cost_usd}``. Empty list when no usage data is\npresent so the card can show its empty-state cleanly.", "operationId": "get_costs_top_tasks_costs_top_tasks_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 10, "title": "Limit" } }, { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "default": 24, "title": "Hours" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/token-breakdown": { "get": { "summary": "Get Token Breakdown", "description": "Per-agent session token consumption breakdown.\n\nFor each agent session shows where the context budget was spent:\nsystem prompt (Bernstein overhead), context files, task description,\ntool call results accumulated at runtime, and assistant output.\n\nIdentifies optimization opportunities - e.g. if 60% of tokens are\ncontext files the agent never used.\n\nArgs:\n request: FastAPI request.\n session_id: If provided, return breakdown for a single session only.\n\nReturns:\n JSON with ``sessions`` list and aggregate ``summary``.", "operationId": "get_token_breakdown_costs_token_breakdown_get", "parameters": [ { "name": "session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/costs/efficiency": { "get": { "summary": "Get Cost Efficiency", "description": "Real-time cost-per-line-of-code efficiency metric.\n\nShows cost efficiency as the run progresses:\n- **current**: efficiency of the most recently completed task\n- **run_average**: efficiency across all completed tasks in this run\n- **historical_average**: efficiency across all tracked runs\n\nHelps identify unusually expensive runs.\n\nReturns:\n JSON with ``current``, ``run_average``, ``historical_average``, and\n ``message`` fields.", "operationId": "get_cost_efficiency_costs_efficiency_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/costs/{run_id}": { "get": { "summary": "Get Cost Budget", "description": "Return budget status for a specific run.\n\nLoads the persisted cost tracker from ``.sdd/runtime/costs/{run_id}.json``\nand returns its ``BudgetStatus`` as JSON.", "operationId": "get_cost_budget_costs__run_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "No cost data for run" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/auth/status": { "get": { "summary": "Dashboard Auth Status", "description": "Report whether dashboard auth is required and who is logged in.", "operationId": "dashboard_auth_status_dashboard_auth_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/dashboard/auth/login": { "post": { "summary": "Dashboard Auth Login", "description": "Open a dashboard session from a password or a scoped token.\n\nThe session cookie wraps exactly the principal and scope the credential\ncarried; a viewer token can never log into an operator session. Every\nattempt -- success or failure -- is journaled as a signed governance\ndecision (``dashboard.login``).", "operationId": "dashboard_auth_login_dashboard_auth_login_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/dashboard/auth/logout": { "post": { "summary": "Dashboard Auth Logout", "description": "Close the current dashboard session (idempotent).", "operationId": "dashboard_auth_logout_dashboard_auth_logout_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/dashboard/file_locks": { "get": { "summary": "File Locks Endpoint", "description": "Return active file locks grouped by agent for the dashboard.\n\nReads the persisted lock state from ``.sdd/runtime/file_locks.json`` and\nreturns it in a dashboard-friendly format with both a flat list and an\nagent-grouped view.\n\nReturns:\n JSON with ``all_locks`` (flat list sorted by path), ``locks_by_agent``\n (dict keyed by agent_id with files list + task info + elapsed_s),\n ``count`` (total lock count), and ``ts`` (generation timestamp).", "operationId": "file_locks_endpoint_dashboard_file_locks_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/dashboard/team": { "get": { "summary": "Team Adoption Dashboard", "description": "Aggregate team usage metrics for engineering managers.\n\nReturns total runs, tasks completed, cost saved vs. budget,\ncode merge stats, and quality gate pass rate.", "operationId": "team_adoption_dashboard_dashboard_team_get", "responses": { "200": { "description": "Team adoption metrics", "content": { "application/json": { "schema": {} } } } } } }, "/graph/impact": { "get": { "tags": [ "graph" ], "summary": "Graph Impact", "description": "Return downstream files impacted by changing the given file.", "operationId": "graph_impact_graph_impact_get", "parameters": [ { "name": "file", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "title": "File" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImpactResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/observability/agents": { "get": { "summary": "Observability Agents", "description": "Return runtime heartbeat, stall-profile, and log-summary data per agent.", "operationId": "observability_agents_observability_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Agents Observability Agents Get" } } } } } } }, "/observability/effectiveness": { "get": { "summary": "Observability Effectiveness", "description": "Return recent effectiveness data, role trends, and best configs.", "operationId": "observability_effectiveness_observability_effectiveness_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Effectiveness Observability Effectiveness Get" } } } } } } }, "/observability/recommendations": { "get": { "summary": "Observability Recommendations", "description": "Return the current recommendation set and delivery hit counts.", "operationId": "observability_recommendations_observability_recommendations_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Recommendations Observability Recommendations Get" } } } } } } }, "/observability/budget": { "get": { "summary": "Observability Budget", "description": "Return completion-budget status per lineage.", "operationId": "observability_budget_observability_budget_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Budget Observability Budget Get" } } } } } } }, "/observability/deps": { "get": { "summary": "Observability Deps", "description": "Return dependency-graph validation status for current tasks.", "operationId": "observability_deps_observability_deps_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Deps Observability Deps Get" } } } } } } }, "/recap": { "get": { "summary": "Recap", "description": "Return post-run summary with diff stats, quality scores, and cost breakdown.\n\nReads completed tasks from the archive and computes:\n- Task completion statistics\n- Git diff statistics (files changed, additions, deletions)\n- Quality score distribution\n- Cost breakdown by model and role", "operationId": "recap_recap_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Recap Recap Get" } } } } } } }, "/observability/token-histogram": { "get": { "summary": "Token Histogram", "description": "Return histogram of token usage by task complexity.\n\nShows average tokens consumed for small, medium, large tasks.\nHelps understand token consumption patterns.", "operationId": "token_histogram_observability_token_histogram_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Token Histogram Observability Token Histogram Get" } } } } } } }, "/observability/queue-depth": { "get": { "summary": "Get Queue Depth", "description": "Return task queue depth over time.\n\nReturns last N records of queue depth snapshots.\n\nArgs:\n request: FastAPI request.\n limit: Maximum number of records to return (default 100).\n\nReturns:\n List of queue depth snapshots with timestamps.", "operationId": "get_queue_depth_observability_queue_depth_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 100, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Queue Depth Observability Queue Depth Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/observability/timeline": { "get": { "summary": "Get Timeline", "description": "Return task timing data for timeline visualization.\n\nReturns start and end times for all tasks tracked in metrics.", "operationId": "get_timeline_observability_timeline_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Get Timeline Observability Timeline Get" } } } } } } }, "/changelog": { "get": { "summary": "Get Changelog", "description": "Generate changelog from completed tasks.\n\nGroups completed tasks by type (Features, Fixes, etc.) and\nformats as markdown changelog.\n\nArgs:\n request: FastAPI request.\n days: Number of days to include (default 30).\n\nReturns:\n Dict with 'markdown' key containing changelog text.", "operationId": "get_changelog_changelog_get", "parameters": [ { "name": "days", "in": "query", "required": false, "schema": { "type": "integer", "default": 30, "title": "Days" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Changelog Changelog Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/observability/incidents": { "get": { "summary": "List Incidents", "description": "List all known incidents.\n\nReturns:\n Dict with 'incidents' list.", "operationId": "list_incidents_observability_incidents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response List Incidents Observability Incidents Get" } } } } } } }, "/observability/incident-timeline/{incident_id}": { "get": { "summary": "Get Incident Timeline", "description": "Build a correlated incident timeline from logs, metrics, and traces.\n\nArgs:\n request: FastAPI request.\n incident_id: The incident ID to build a timeline for.\n window_before: Seconds before incident to include (default 600).\n window_after: Seconds after incident to include (default 300).\n\nReturns:\n Dict with incident metadata and sorted timeline events.", "operationId": "get_incident_timeline_observability_incident_timeline__incident_id__get", "parameters": [ { "name": "incident_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Incident Id" } }, { "name": "window_before", "in": "query", "required": false, "schema": { "type": "integer", "default": 600, "title": "Window Before" } }, { "name": "window_after", "in": "query", "required": false, "schema": { "type": "integer", "default": 300, "title": "Window After" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Incident Timeline Observability Incident Timeline Incident Id Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/observability/token-breakdown": { "get": { "summary": "Token Breakdown", "description": "Return per-session token consumption breakdown.\n\nFor each agent session with a ``.tokens`` sidecar file, breaks down\ntoken usage into estimated categories:\n\n- ``system_prompt_estimated``: overhead from Bernstein role templates\n- ``task_description_estimated``: tokens for the task title + description\n- ``context_estimated``: remaining input tokens (context files, tool results,\n prior conversation history, etc.)\n- ``output_tokens``: actual assistant output tokens\n\nAlso reports ``optimization_opportunities`` - a list of human-readable\ninsights when a category accounts for an unusually large share of tokens\n(e.g. \"context files are 60% of input\").\n\nToken sidecar files live at ``.sdd/runtime/{session_id}.tokens``.\nBreakdown percentages use a 4-chars/token heuristic for size estimates.\n\nReturns:\n Dict with ``sessions`` list and aggregate ``summary``.", "operationId": "token_breakdown_observability_token_breakdown_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Token Breakdown Observability Token Breakdown Get" } } } } } } }, "/quality": { "get": { "summary": "Get Quality Metrics", "description": "Return aggregated internal quality metrics (last 7 days).\n\nReads from ``.sdd/metrics/`` JSONL files to compute:\n\n- ``per_model``: per-model success rate, avg tokens, and completion\n time distribution (p50/p90/p99).\n- ``overall``: aggregate across all models.\n- ``gate_stats``: per-gate pass/blocked/flagged counts (last 30 days).\n- ``guardrail_pass_rate``: fraction of gate checks that passed.\n- ``review_rejection_rate``: fraction of tasks that failed overall.\n\nReturns an empty structure when no metric data exists yet.", "operationId": "get_quality_metrics_quality_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/quality/budget-forecast": { "get": { "summary": "Get Budget Forecast", "description": "Return projected spend for the active planned backlog.", "operationId": "get_budget_forecast_quality_budget_forecast_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/quality/trend": { "get": { "summary": "Get Quality Trend", "description": "Return time-series quality metrics for trend visualization.\n\nBuckets quality data by day (default) or week and returns per-bucket\nsuccess rates, gate pass rates, and average quality scores. Covers the\nlast 90 days by default so dashboards can show weeks-to-months trends.\n\nQuery parameters:\n- ``days``: lookback window in days (default 90, max 365).\n- ``granularity``: ``\"day\"`` (default) or ``\"week\"``.\n\nReturns a ``series`` list ordered by date, each entry containing:\n- ``date``: ISO date string (bucket start).\n- ``ts``: Unix timestamp of the bucket start.\n- ``tasks_total``, ``tasks_success``: raw task counts.\n- ``success_rate``: fraction of tasks that succeeded (omitted if no tasks).\n- ``gate_pass_rates``: dict of gate name → pass rate for that bucket.\n- ``avg_quality_score``: mean quality score 0-100 (omitted if no scores).", "operationId": "get_quality_trend_quality_trend_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/quality/models": { "get": { "summary": "Get Quality By Model", "description": "Return per-model quality breakdown (last 30 days).\n\nExtended view of model performance for routing configuration and cost\nanalysis. Covers a longer window than the default ``/quality`` summary.", "operationId": "get_quality_by_model_quality_models_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/quality/file-health": { "get": { "summary": "List File Health", "description": "Return per-file code health scores, worst files first.\n\nQuery parameters:\n- ``limit``: max results (default 50, max 500).\n- ``min_score``: only return files at or below this score.\n- ``grade``: filter by grade (A/B/C/D/F).\n\nReturns a JSON object with ``files`` list and summary statistics.", "operationId": "list_file_health_quality_file_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/quality/file-health/flagged": { "get": { "summary": "List Flagged Files", "description": "Return files currently flagged for human review due to health degradation.\n\nA file is flagged when:\n- A task dropped its health score by ≥10 points, OR\n- Its total health score is below 60 (grade D or F).\n\nReturns ``files`` list with detailed health scores and degradation context.", "operationId": "list_flagged_files_quality_file_health_flagged_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/quality/file-health/{file_path}": { "get": { "summary": "Get File Health", "description": "Return the current health score for a single file.\n\nArgs:\n file_path: File path relative to repository root (URL-encoded).\n\nReturns 404 if the file has never been tracked.", "operationId": "get_file_health_quality_file_health__file_path__get", "parameters": [ { "name": "file_path", "in": "path", "required": true, "schema": { "type": "string", "title": "File Path" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "File not tracked yet" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/fleet/projects": { "get": { "summary": "Fleet Projects", "description": "Return aggregated per-project snapshots for the fleet overview.\n\nResponse shape mirrors :func:`bernstein.core.fleet.web.api_projects`:\n\n.. code-block:: json\n\n {\n \"projects\": [ProjectSnapshot, ...],\n \"errors\": [],\n \"stub\": true|false,\n \"hint\": \"Run `bernstein fleet --web` for the real aggregator.\"\n }\n\n``stub: true`` means the operator UI is talking to a single-project\nserver that has no fleet aggregator wired in; the ``projects`` list\nis empty in that case so the SPA can render the empty-state.", "operationId": "fleet_projects_fleet_projects_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Fleet Projects Fleet Projects Get" } } } } } } }, "/fleet/search": { "get": { "summary": "Fleet Search", "description": "Cross-project search stub for the topbar search bar.\n\nAccepts a free-text query plus the ``agent:/status:/across:`` operator\nsyntax used by the frontend search component; the stub does not yet\nexecute the search and instead returns the parsed filters so the SPA\ncan demonstrate the round-trip while the backend implementation is\nbeing built.\n\nReturns:\n ``{\"query\": str, \"filters\": {...}, \"matches\": [], \"stub\": bool}``.", "operationId": "fleet_search_fleet_search_get", "parameters": [ { "name": "q", "in": "query", "required": false, "schema": { "type": "string", "description": "Cross-project search query", "default": "", "title": "Q" }, "description": "Cross-project search query" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "default": 50, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Fleet Search Fleet Search Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/drain": { "get": { "summary": "Drain Status", "description": "Check drain status.", "operationId": "drain_status_drain_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } }, "post": { "summary": "Drain Start", "description": "Begin draining -- stop accepting new task claims.", "operationId": "drain_start_drain_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/drain/cancel": { "post": { "summary": "Drain Cancel", "description": "Cancel drain -- resume accepting claims.", "operationId": "drain_cancel_drain_cancel_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/identities": { "get": { "tags": [ "identities" ], "summary": "List Identities", "description": "List agent identities with optional status/role filters.\n\n``status`` is validated against the :class:`AgentIdentityStatus`\nenum by FastAPI, so an unknown value yields a ``422`` rather than\nreaching the handler and raising an unhandled ``ValueError``.", "operationId": "list_identities_identities_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "$ref": "#/components/schemas/AgentIdentityStatus" }, { "type": "null" } ], "title": "Status" } }, { "name": "role", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/identities/{identity_id}": { "get": { "tags": [ "identities" ], "summary": "Get Identity", "description": "Get details for a single agent identity.", "operationId": "get_identity_identities__identity_id__get", "parameters": [ { "name": "identity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Identity Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Identity not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/identities/{identity_id}/revoke": { "post": { "tags": [ "identities" ], "summary": "Revoke Identity", "description": "Revoke an agent identity.", "operationId": "revoke_identity_identities__identity_id__revoke_post", "parameters": [ { "name": "identity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Identity Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Identity not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/identities/{identity_id}/audit": { "get": { "tags": [ "identities" ], "summary": "Identity Audit", "description": "Return the audit trail for an agent identity.", "operationId": "identity_audit_identities__identity_id__audit_get", "parameters": [ { "name": "identity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Identity Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 100, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/.well-known/acp.json": { "get": { "summary": "Acp Discovery", "description": "ACP discovery document - editors poll this to find ACP-compatible agents.", "operationId": "acp_discovery__well_known_acp_json_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPDiscoveryResponse" } } } } } } }, "/acp/v0/agents": { "get": { "summary": "List Acp Agents", "description": "List all ACP-advertised agents.", "operationId": "list_acp_agents_acp_v0_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/ACPAgentListEntry" }, "type": "array", "title": "Response List Acp Agents Acp V0 Agents Get" } } } } } } }, "/acp/v0/agents/{agent_id}": { "get": { "summary": "Get Acp Agent", "description": "Get detailed metadata for a specific ACP agent.", "operationId": "get_acp_agent_acp_v0_agents__agent_id__get", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPAgentResponse" } } } }, "404": { "description": "ACP agent not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/acp/v0/runs": { "post": { "summary": "Create Acp Run", "description": "Create an ACP run - creates a Bernstein task and links it.\n\nEditors call this when the user submits a goal via the ACP sidebar.", "operationId": "create_acp_run_acp_v0_runs_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunCreateRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunResponse" } } } }, "400": { "description": "Unknown ACP agent" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/acp/v0/runs/{run_id}": { "get": { "summary": "Get Acp Run", "description": "Get ACP run status, syncing from the underlying Bernstein task.", "operationId": "get_acp_run_acp_v0_runs__run_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunResponse" } } } }, "404": { "description": "ACP run not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "delete": { "summary": "Cancel Acp Run", "description": "Cancel an ACP run and its underlying Bernstein task.", "operationId": "cancel_acp_run_acp_v0_runs__run_id__delete", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunResponse" } } } }, "404": { "description": "ACP run not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/approvals": { "get": { "tags": [ "approvals" ], "summary": "List Approvals", "description": "List all pending approval requests.", "operationId": "list_approvals_approvals_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListApprovalsResponse" } } } } } } }, "/approvals/{task_id}/approve": { "post": { "tags": [ "approvals" ], "summary": "Approve Task", "description": "Approve a pending approval request.\n\nWrites a .approved decision file so the orchestrator poll loop unblocks.\nThe pending file is then removed.\n\nArgs:\n task_id: Task ID to approve.\n body: Optional reason metadata.\n\nReturns:\n Success message.", "operationId": "approve_task_approvals__task_id__approve_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalDecisionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Approve Task Approvals Task Id Approve Post" } } } }, "400": { "description": "Invalid task_id format" }, "404": { "description": "No pending approval for task" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/approvals/{task_id}/reject": { "post": { "tags": [ "approvals" ], "summary": "Reject Task", "description": "Reject a pending approval request.\n\nWrites a .rejected decision file so the orchestrator poll loop unblocks.\nThe pending file is then removed.\n\nArgs:\n task_id: Task ID to reject.\n body: Optional reason metadata.\n\nReturns:\n Success message.", "operationId": "reject_task_approvals__task_id__reject_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalDecisionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Reject Task Approvals Task Id Reject Post" } } } }, "400": { "description": "Invalid task_id format" }, "404": { "description": "No pending approval for task" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/approvals/queue": { "get": { "tags": [ "approvals" ], "summary": "List Queued Approvals", "description": "List pending tool-call approvals (op-002).\n\nArgs:\n session_id: Optional filter; when given only approvals for that\n session are returned.", "operationId": "list_queued_approvals_approvals_queue_get", "parameters": [ { "name": "session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QueuedApprovalsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/approvals/{approval_id}/resolve": { "post": { "tags": [ "approvals" ], "summary": "Resolve Queued Approval", "description": "Resolve a queued approval with ``allow``, ``reject``, or ``always``.\n\nThe request body must echo the ``nonce`` the gate issued when the\napproval was queued. Mismatches return ``409 NONCE_MISMATCH``; a\nnonce replayed against an already-resolved or evicted approval\nreturns ``410 NONCE_EXPIRED``.", "operationId": "resolve_queued_approval_approvals__approval_id__resolve_post", "parameters": [ { "name": "approval_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Approval Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResolveRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Resolve Queued Approval Approvals Approval Id Resolve Post" } } } }, "400": { "description": "Invalid approval id or decision" }, "404": { "description": "No pending approval with that id" }, "409": { "description": "NONCE_MISMATCH" }, "410": { "description": "NONCE_EXPIRED" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/approvals/live-fragment": { "get": { "tags": [ "approvals" ], "summary": "Approvals Live Fragment", "description": "Return an HTML fragment the live-session page embeds.\n\nEach pending approval becomes a row with three buttons that POST the\nresolution back to ``/approvals/{id}/resolve``. The fragment is\nintentionally minimal so it can be inlined into the existing live\ndashboard without pulling a new framework.", "operationId": "approvals_live_fragment_approvals_live_fragment_get", "parameters": [ { "name": "session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/plans": { "get": { "tags": [ "plans" ], "summary": "List Plans", "description": "List all plans, optionally filtered by status.\n\nQuery params:\n status: Filter by plan status (pending, approved, rejected, expired).", "operationId": "list_plans_plans_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object", "additionalProperties": true }, "title": "Response List Plans Plans Get" } } } }, "400": { "description": "Invalid status filter" }, "404": { "description": "Plan mode is not enabled on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/plans/{plan_id}": { "get": { "tags": [ "plans" ], "summary": "Get Plan", "description": "Get a single plan by ID.", "operationId": "get_plan_plans__plan_id__get", "parameters": [ { "name": "plan_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Plan Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Plan Plans Plan Id Get" } } } }, "404": { "description": "Plan not found, or plan mode is not enabled on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/plans/{plan_id}/approve": { "post": { "tags": [ "plans" ], "summary": "Approve Plan", "description": "Approve a plan: promotes all its PLANNED tasks to OPEN.\n\nThis is the key operation: once approved, the orchestrator will\npick up the tasks and start spawning agents.", "operationId": "approve_plan_plans__plan_id__approve_post", "parameters": [ { "name": "plan_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Plan Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/PlanDecisionRequest" }, { "type": "null" } ], "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Approve Plan Plans Plan Id Approve Post" } } } }, "404": { "description": "Plan not found, or plan mode is not enabled on this server" }, "409": { "description": "Plan already decided" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/plans/{plan_id}/reject": { "post": { "tags": [ "plans" ], "summary": "Reject Plan", "description": "Reject a plan: cancels all its PLANNED tasks.\n\nRejected tasks are moved to CANCELLED status so they never execute.", "operationId": "reject_plan_plans__plan_id__reject_post", "parameters": [ { "name": "plan_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Plan Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/PlanDecisionRequest" }, { "type": "null" } ], "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Reject Plan Plans Plan Id Reject Post" } } } }, "404": { "description": "Plan not found, or plan mode is not enabled on this server" }, "409": { "description": "Plan already decided" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/gateway/metrics": { "get": { "summary": "Gateway Metrics", "description": "Return per-tool MCP call metrics from the active gateway session.\n\nReturns an empty ``metrics`` dict when no gateway is running.\nClients can use ``active`` to distinguish the two cases.", "operationId": "gateway_metrics_gateway_metrics_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/slo": { "get": { "summary": "Get Slo Status", "description": "Return current SLO dashboard data.", "operationId": "get_slo_status_slo_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/slo/budget": { "get": { "summary": "Get Error Budget", "description": "Return error budget details in focused format.", "operationId": "get_error_budget_slo_budget_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/slo/burndown": { "get": { "summary": "Get Slo Burndown", "description": "Return SLO burn-down rate visualization data .\n\nProvides:\n- Current SLO compliance and error budget fraction\n- Burn rate relative to the allowed failure rate (1.0 = on-target)\n- Linear projection of days until the SLO is breached\n- Sparkline data points for rendering a burn-down chart\n- Human-readable breach projection summary\n\nExample response::\n\n {\n \"slo_name\": \"task_success\",\n \"slo_target\": 0.9,\n \"slo_current\": 0.942,\n \"burn_rate\": 0.3,\n \"burn_rate_per_day\": 0.05,\n \"budget_fraction\": 0.72,\n \"budget_consumed_pct\": 28.0,\n \"days_to_breach\": 6.1,\n \"breach_projection\": \"SLO will breach in 6.1 days at current rate\",\n \"status\": \"green\",\n \"sparkline\": [...]\n }", "operationId": "get_slo_burndown_slo_burndown_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/slo/reset": { "post": { "summary": "Reset Slo State", "description": "Reset SLO tracker to initial state (no persisted data cleared).", "operationId": "reset_slo_state_slo_reset_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/sla": { "get": { "summary": "List Contracts", "description": "Return every registered SLA contract.", "operationId": "list_contracts_sla_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/sla/receipts": { "get": { "summary": "List Receipts", "description": "Return the operator projection of every persisted violation receipt.", "operationId": "list_receipts_sla_receipts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/sla/receipts/{receipt_id}/verify": { "get": { "summary": "Verify Receipt Endpoint", "description": "Verify a persisted violation receipt offline and return the verdict.", "operationId": "verify_receipt_endpoint_sla_receipts__receipt_id__verify_get", "parameters": [ { "name": "receipt_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Receipt Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/sla/{contract_id}": { "get": { "summary": "Show Contract", "description": "Return one SLA contract's full record.", "operationId": "show_contract_sla__contract_id__get", "parameters": [ { "name": "contract_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Contract Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/sla/{contract_id}/report": { "get": { "summary": "Contract Report", "description": "Return the deterministic error-budget report for a contract.", "operationId": "contract_report_sla__contract_id__report_get", "parameters": [ { "name": "contract_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Contract Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/metrics/custom": { "get": { "summary": "Get Custom Metrics", "description": "Evaluate all configured custom metrics and return current values.\n\nReturns an object with a ``metrics`` list. Each entry contains:\n- ``name``: metric name\n- ``value``: computed float value\n- ``unit``: display unit (e.g. ``\"lines/$\"``)\n- ``description``: optional human-readable description\n- ``error``: present only when evaluation failed\n\nReturns 200 with an empty list if no custom metrics are configured.", "operationId": "get_custom_metrics_metrics_custom_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/metrics/custom/schema": { "get": { "summary": "Get Custom Metrics Schema", "description": "Return the configured custom metric definitions (formulas and units).\n\nReturns the schema without evaluating - useful for documentation and\nformula validation checks.", "operationId": "get_custom_metrics_schema_metrics_custom_schema_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/sbom/generate": { "post": { "tags": [ "sbom" ], "summary": "Generate SBOM and optionally run vulnerability scan", "description": "Generate a CycloneDX or SPDX SBOM from installed packages.\n\nAfter generation, optionally run ``osv-scanner`` or ``grype`` for\nvulnerability scanning. When ``block_on_critical=true`` and critical\nfindings are detected, responds with HTTP 422 so CI/CD pipelines can\ngate merges on vulnerability status.\n\nSBOM artifacts are written to ``.sdd/artifacts/sbom/``.", "operationId": "generate_sbom_sbom_generate_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SBOMGenerateRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SBOMGenerateResponse" } } } }, "400": { "description": "Unknown SBOM format" }, "422": { "description": "Critical vulnerabilities found (gate blocked)" }, "503": { "description": "Server workdir not configured" } } } }, "/sbom/artifacts": { "get": { "tags": [ "sbom" ], "summary": "List generated SBOM artifact files", "description": "List previously generated SBOM artifact files from ``.sdd/artifacts/sbom/``.", "operationId": "list_sbom_artifacts_sbom_artifacts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SBOMListResponse" } } } }, "503": { "description": "Server workdir not configured" } } } }, "/hooks/{session_id}": { "post": { "summary": "Receive Hook", "description": "Receive a hook event from Claude Code.\n\nClaude Code sends structured JSON with at minimum a ``hook_event_name``\nfield. The event is parsed, persisted to a JSONL sidecar, and triggers\nside effects (heartbeat touch, completion markers, etc.).\n\nThe request body is verified against\n``X-Bernstein-Hook-Signature-256`` (HMAC-SHA256 over the raw body,\nkeyed with ``BERNSTEIN_HOOK_SECRET``) *before* any parsing or\nfilesystem work - this is the authentication boundary for the\nendpoint. The ``session_id`` is then validated against\na strict allowlist to prevent path traversal.\n\nArgs:\n session_id: Agent session identifier from the URL path.\n request: The incoming FastAPI request.\n\nReturns:\n JSON response with status and action taken, 401 if signature\n verification fails, or 400 if ``session_id`` is unsafe / body\n is not valid JSON.", "operationId": "receive_hook_hooks__session_id__post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/export/tasks": { "get": { "summary": "Export Tasks", "description": "Export tasks as CSV or JSON.\n\nQuery params:\n format: ``csv`` or ``json`` (default ``json``).\n limit: Optional max number of tasks to return. Pushed into\n ``TaskStore.list_tasks`` so large stores no longer materialise\n the whole table (issue #1728 finding 3).\n offset: Optional number of tasks to skip before returning rows.", "operationId": "export_tasks_export_tasks_get", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "json", "title": "Format" } }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Offset" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/export/agents": { "get": { "summary": "Export Agents", "description": "Export agent snapshots as CSV or JSON.\n\nQuery params:\n format: ``csv`` or ``json`` (default ``json``).", "operationId": "export_agents_export_agents_get", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "json", "title": "Format" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/grafana/dashboard": { "get": { "summary": "Grafana Dashboard Endpoint", "description": "Generate and return the Grafana dashboard JSON.\n\nQuery params:\n datasource: Prometheus datasource name (default ``Prometheus``).", "operationId": "grafana_dashboard_endpoint_grafana_dashboard_get", "parameters": [ { "name": "datasource", "in": "query", "required": false, "schema": { "type": "string", "default": "Prometheus", "title": "Datasource" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/tasks/{task_id}": { "get": { "summary": "Task Detail", "description": "Return detailed task view including log tail and progress.\n\nArgs:\n task_id: Task identifier.", "operationId": "task_detail_dashboard_tasks__task_id__get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskDetailResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/tasks/{task_id}/logs/stream": { "get": { "summary": "Task Log Stream", "description": "Stream agent logs for a task via Server-Sent Events.\n\nThe stream sends new log content as ``log`` events and closes\nafter the task completes or ``_MAX_IDLE_TICKS`` seconds of no new data.", "operationId": "task_log_stream_dashboard_tasks__task_id__logs_stream_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/tasks/{task_id}/diff": { "get": { "summary": "Task Diff", "description": "Return the diff for a task's working branch against the base ref.\n\nStrategy:\n 1. Resolve the working branch from the task's ``assigned_agent`` --\n ``agent/``. If no agent is assigned (or the branch\n does not exist yet), fall back to ``git diff HEAD`` so the user\n still sees uncommitted scratch work.\n 2. Run ``git diff ...`` (three-dot, symmetric\n difference relative to the merge base) and parse the output into\n a structured per-file representation.\n 3. Cap the unified diff at ``_DIFF_MAX_BYTES`` to keep payloads sane.\n\nThe sync ``_run_git`` helper is reused (it is also called from other\nsync helpers in this module). To keep the event loop responsive under\nload (issue #1723) every blocking ``_run_git`` invocation is offloaded\nto the default executor via ``asyncio.to_thread``. The helper itself\nstays sync so non-route callers keep working.", "operationId": "task_diff_dashboard_tasks__task_id__diff_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskDiffResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/tasks/{task_id}/trace": { "get": { "summary": "Task Trace", "description": "Return the timeline of trace events for *task_id*.\n\nThe endpoint is read-only and idempotent. A missing task returns 404; a\nvalid task with no trace returns 200 + an empty events list (the FE\nrenders an empty-state card in that case).", "operationId": "task_trace_dashboard_tasks__task_id__trace_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 1, "default": 500, "title": "Limit" } }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Cursor" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TraceTimelineResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/health/deps": { "get": { "summary": "Health Deps", "description": "Return health status with dependency checks.\n\nChecks: server, store, adapters, sse_bus.\nOverall status is ``healthy`` if all dependencies are ok,\n``degraded`` if any are degraded, ``unhealthy`` if any are down.", "operationId": "health_deps_health_deps_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthDepsResponse" } } } } } } }, "/tasks/batch-ops": { "post": { "tags": [ "batch-operations" ], "summary": "Batch Operations", "description": "Execute a batch operation on multiple tasks.\n\nSupported actions:\n- **cancel**: Cancel all specified tasks.\n- **retry**: Reset failed tasks back to open.\n- **reprioritize**: Update priority on all specified tasks (requires ``priority``).\n- **tag**: Add tags to all specified tasks (requires ``tags``).\n\nReturns a result with lists of succeeded and failed task IDs.", "operationId": "batch_operations_tasks_batch_ops_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchResult" } } } }, "422": { "description": "Invalid batch request" } } } }, "/audit": { "get": { "tags": [ "audit" ], "summary": "Query Audit Log", "description": "Query the audit log with filtering and pagination.\n\nReturns:\n Dict with items, total, page, page_size. Items are normalised\n through :func:`_normalise_audit_row` so the web GUI table can\n render every row without optional-chain dance.", "operationId": "query_audit_log_audit_get", "parameters": [ { "name": "event_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Event Type" } }, { "name": "search", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Search" } }, { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "default": 1, "title": "Page" } }, { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "default": 50, "title": "Page Size" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Query Audit Log Audit Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/audit/verify": { "get": { "tags": [ "audit" ], "summary": "Audit Verify", "description": "Lightweight HMAC chain integrity probe for the web GUI banner.\n\nWalks ``.sdd/audit/*.jsonl`` events and returns a fully-populated\npayload (no nulls in core scalar fields) so the GUI's\n``ChainStatusBanner`` has something to render even when the audit\ndirectory hasn't been initialised yet. Full Sigstore / Merkle\nreconciliation lives in the lineage-v1 verifier CLI.", "operationId": "audit_verify_audit_verify_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Audit Verify Audit Verify Get" } } } } } }, "post": { "tags": [ "audit" ], "summary": "Audit Reverify", "description": "Re-walk the audit chain.\n\nBehaviourally identical to ``GET /audit/verify`` for the lightweight\nprobe - the operator-visible \"Re-verify\" button in the GUI just wants\na fresh walk and an up-to-date payload. Accepts ``{from_chunk}`` so\nfuture implementations can scope the walk; today the field is read\nand echoed but not used to slice the chain.", "operationId": "audit_reverify_audit_verify_post", "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/VerifyChainRequest" }, { "type": "null" } ], "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Audit Reverify Audit Verify Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/audit/export": { "post": { "tags": [ "audit" ], "summary": "Audit Export", "description": "Stream the filtered audit log as CSV or JSONL.\n\nSame filter semantics as ``GET /audit`` (``event_type``, ``search``,\n``from``, ``to``); returns the entire matching set in one body, no\npagination - operators expect to download the whole filtered slice.\nUsed by the web GUI Export menu (CSV / JSONL buttons).", "operationId": "audit_export_audit_export_post", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "csv", "title": "Format" } }, { "name": "event_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Event Type" } }, { "name": "search", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Search" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/graphql": { "post": { "tags": [ "graphql" ], "summary": "Graphql Endpoint", "description": "Execute a GraphQL query.\n\nAccepts a standard GraphQL request body and resolves the query\nagainst the in-memory task store.\n\nArgs:\n req: GraphQL request body with query, optional variables and operationName.\n request: FastAPI request (provides access to app state).\n\nReturns:\n GraphQL response with ``data`` or ``errors``.", "operationId": "graphql_endpoint_graphql_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphQLRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Graphql Endpoint Graphql Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/graduation/status": { "get": { "tags": [ "graduation" ], "summary": "Graduation Status", "description": "Return graduation stage and metrics for all tracked sessions.\n\nReturns:\n JSON with ``sessions`` list and ``total`` count.", "operationId": "graduation_status_graduation_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/graduation/config/policies": { "get": { "tags": [ "graduation" ], "summary": "Get Policies", "description": "Return the current graduation stage policies.\n\nReturns:\n JSON mapping stage names to policy thresholds.", "operationId": "get_policies_graduation_config_policies_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/graduation/{session_id}": { "get": { "tags": [ "graduation" ], "summary": "Session Graduation", "description": "Return graduation state for a specific session.\n\nArgs:\n session_id: The session identifier to look up.\n\nReturns:\n JSON with stage, metrics, promotion log, and graduation readiness.\n\nRaises:\n HTTPException: 404 when no record exists for *session_id*.", "operationId": "session_graduation_graduation__session_id__get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "No graduation record for session" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/graduation/{session_id}/promote": { "post": { "tags": [ "graduation" ], "summary": "Promote Session", "description": "Manually promote a session to the next graduation stage.\n\nArgs:\n session_id: Session to promote.\n body: Promotion reason and who initiated it.\n\nReturns:\n JSON with ``from_stage``, ``to_stage``, and ``promoted: true``.\n\nRaises:\n HTTPException: 404 when no record exists.\n HTTPException: 409 when already at the terminal (autonomous) stage.", "operationId": "promote_session_graduation__session_id__promote_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PromoteRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "No graduation record for session" }, "409": { "description": "Already at terminal stage" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/graduation/{session_id}/record-event": { "post": { "tags": [ "graduation" ], "summary": "Record Task Event", "description": "Record a task completion or failure for graduation metric tracking.\n\nThe orchestrator or CLI calls this after each task completes/fails so\nthe graduation framework can accumulate per-stage metrics and determine\nwhen the session qualifies for the next stage.\n\nArgs:\n session_id: The session that executed the task.\n body: Task event details.\n\nReturns:\n JSON with updated stage, metrics, and graduation readiness.\n\nRaises:\n HTTPException: 422 when *initial_stage* is not a valid stage name.", "operationId": "record_task_event_graduation__session_id__record_event_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecordEventRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Invalid graduation stage" } } } }, "/handoff/{token}": { "get": { "summary": "Claim Handoff Token", "description": "Claim a handoff token and return the session identity + tail.\n\nArgs:\n token: Opaque urlsafe token presented by the dashboard.\n request: FastAPI request (used to resolve the workdir).\n\nReturns:\n JSON envelope with ``session_id``, ``task_id``,\n ``source_surface``, ``claimed_at``, ``note`` and ``tail`` (a\n list of recent stream entries).\n\nRaises:\n HTTPException: ``404`` for unknown tokens, ``410`` for expired\n or already-claimed tokens.", "operationId": "claim_handoff_token_handoff__token__get", "parameters": [ { "name": "token", "in": "path", "required": true, "schema": { "type": "string", "title": "Token" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/team": { "get": { "summary": "Team Summary", "description": "Return a summary of the current team state.\n\nIncludes total members, active/finished counts, role distribution,\nand full per-member metadata.", "operationId": "team_summary_team_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/team/active": { "get": { "summary": "Team Active", "description": "Return only active team members.", "operationId": "team_active_team_active_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/team/{agent_id}": { "get": { "summary": "Team Member", "description": "Return metadata for a single team member.\n\nReturns 404 if the agent is not in the team roster.", "operationId": "team_member_team__agent_id__get", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/metrics/provider-latency": { "get": { "summary": "Provider Latency Current", "description": "Return current p50/p95/p99 latency percentiles for all tracked providers.\n\nEach entry in the response includes a ``baseline_p99_ms`` derived from the\npast 7 days of data. When ``p99_ms`` exceeds ``baseline_p99_ms x 2``, the\nentry carries ``\"degraded\": true``.", "operationId": "provider_latency_current_metrics_provider_latency_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/metrics/provider-latency/history": { "get": { "summary": "Provider Latency History", "description": "Return raw latency samples for time-series charting.\n\nEach sample has: ``timestamp``, ``provider``, ``model``, ``latency_ms``.\nSamples are ordered chronologically. Use ``hours`` to control the lookback\nwindow (default 24h, max 7 days).", "operationId": "provider_latency_history_metrics_provider_latency_history_get", "parameters": [ { "name": "provider", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by provider name", "title": "Provider" }, "description": "Filter by provider name" }, { "name": "model", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by model identifier", "title": "Model" }, "description": "Filter by model identifier" }, { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 168, "minimum": 1, "description": "Hours of history to return (1-168)", "default": 24, "title": "Hours" }, "description": "Hours of history to return (1-168)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/metrics/predictions": { "get": { "summary": "Get Predictions", "description": "Evaluate all predictive forecasts and return active alerts.\n\nChecks three forecast dimensions:\n\n- **Budget exhaustion**: At current spend velocity, when will the\n budget cap be reached?\n- **Completion rate decline**: Is the task completion rate trending\n downward, indicating the run will take longer than expected?\n- **Run duration overrun**: Based on current throughput, will the run\n exceed the configured time window?\n\nUse ``budget_cap`` to enable the budget forecast. The run duration\nforecast requires at least one completed task.\n\nReturns a list of ``alerts`` ordered by severity (critical first).\nEach alert has: ``kind``, ``severity``, ``message``,\n``minutes_until_impact``, ``confidence``.", "operationId": "get_predictions_metrics_predictions_get", "parameters": [ { "name": "budget_cap", "in": "query", "required": false, "schema": { "type": "number", "minimum": 0.0, "description": "Budget ceiling in USD (0 = skip budget forecast)", "default": 0.0, "title": "Budget Cap" }, "description": "Budget ceiling in USD (0 = skip budget forecast)" }, { "name": "window_hours", "in": "query", "required": false, "schema": { "type": "number", "maximum": 72.0, "minimum": 0.1, "description": "Configured run window in hours (default 4)", "default": 4.0, "title": "Window Hours" }, "description": "Configured run window in hours (default 4)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/sessions/{session_id}/peek": { "get": { "summary": "Peek Session", "description": "Return the recent stream-tail entries for ``session_id``.\n\nArgs:\n session_id: Bernstein session whose tail to read.\n request: FastAPI request - used to resolve the workdir and the\n ``tail`` query argument.\n\nReturns:\n JSON envelope with ``session_id`` plus a ``tail`` list of\n ``{ts, surface, text}`` entries in chronological order. An\n empty list signals \"buffer not initialised yet\" rather than an\n error so the polling page renders a blank pane while it waits.", "operationId": "peek_session_sessions__session_id__peek_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/sessions/{session_id}/send": { "post": { "summary": "Send To Session", "description": "Pipe one line of operator input into ``session_id``'s stdin.\n\nThe send-bar tile on the dashboard POSTs ``{\"text\": \"...\"}`` here; we\nforward through :func:`bernstein.core.agents.agent_ipc.send_message`,\nwhich writes the line into the agent's registered stdin pipe.\n\nArgs:\n session_id: Slug-shaped session id; must pass the same validator\n as the peek endpoint.\n request: FastAPI request (unused beyond routing-level checks but\n present so the bearer-auth middleware sees the same shape as\n our other mutating routes).\n payload: JSON body with a single ``text`` field. Empty / missing\n text is rejected with ``400``; oversize payloads above\n :data:`MAX_SEND_BYTES` are rejected with ``413``.\n\nReturns:\n JSON envelope with ``session_id`` and ``delivered`` (``True`` if\n the line reached a registered stdin pipe, ``False`` if no pipe\n is registered for this session). The 200/404 split lets the\n front-end keep the input enabled but warn the operator when the\n agent has no live pipe yet.", "operationId": "send_to_session_sessions__session_id__send_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Payload" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/orchestrator/holds": { "get": { "tags": [ "orchestrator-holds" ], "summary": "Get Holds", "description": "List all currently active (non-expired) holds.", "operationId": "get_holds_orchestrator_holds_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldListResponse" } } } } } }, "post": { "tags": [ "orchestrator-holds" ], "summary": "Create Hold", "description": "Acquire a new hold, preventing orchestrator self-stop while active.", "operationId": "create_hold_orchestrator_holds_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldCreateRequest" } } }, "required": true }, "responses": { "200": { "description": "Hold acquired", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/orchestrator/holds/{hold_id}": { "delete": { "tags": [ "orchestrator-holds" ], "summary": "Delete Hold", "description": "Release a hold by id.", "operationId": "delete_hold_orchestrator_holds__hold_id__delete", "parameters": [ { "name": "hold_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Hold Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "boolean" }, "title": "Response Delete Hold Orchestrator Holds Hold Id Delete" } } } }, "404": { "description": "Hold not found (already released or expired)" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/orchestrator/holds/{hold_id}/renew": { "post": { "tags": [ "orchestrator-holds" ], "summary": "Renew Hold Endpoint", "description": "Heartbeat-renew a hold, extending its expiry by another grace window.", "operationId": "renew_hold_endpoint_orchestrator_holds__hold_id__renew_post", "parameters": [ { "name": "hold_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Hold Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldResponse" } } } }, "404": { "description": "Hold not found (never existed, released, or already expired)" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/review-board/runs": { "get": { "summary": "Review Board Runs", "description": "List run ids that have a journal to project, newest first.", "operationId": "review_board_runs_review_board_runs_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/review-board/runs/{run_id}": { "get": { "summary": "Review Board Projection", "description": "Serve the board projection receipt for ``run_id``.\n\nThe response is a deterministic function of the run's journal file:\nthe same journal bytes serve the same ``board`` and\n``projection_hash`` from any server, so a reviewer can cross-check two\noperators (or the API against a local ``project_run`` fold) byte for\nbyte. ``journal_verified=false`` marks a chain that no longer\nrecomputes - the board is still rendered but must not be trusted.", "operationId": "review_board_projection_review_board_runs__run_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/review-board/runs/{run_id}/evidence/{task_id}": { "get": { "summary": "Review Board Evidence", "description": "Serve the sealed evidence bundle for a board card.\n\nThe bundle is the #2362 proof-of-done artifact: content-addressed\nitems, the gate verdict, the producing signature, and the audit-chain\nentry hash. ``bundle_hash`` is recomputed from the canonical binding\nbytes on every read so the drawer always shows the bundle's current\nidentity.", "operationId": "review_board_evidence_review_board_runs__run_id__evidence__task_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/review-board/runs/{run_id}/diff/{task_id}": { "get": { "summary": "Review Board Diff", "description": "Serve the captured task diff for the card drawer's diff viewer.\n\nThe diff bytes were captured beside the run journal at completion time\n(``task_diff_captured``), so they are exactly what executed and are\navailable against a detached run - no live ``git`` at review time. The\nserved bytes are re-hashed and cross-checked against the journal-chained\ncapture hash: ``verified`` is ``true`` only when the diff a reviewer folds\nopen equals the diff that was captured and the chain still recomputes.", "operationId": "review_board_diff_review_board_runs__run_id__diff__task_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/review-board/runs/{run_id}/tasks/{task_id}/review": { "post": { "summary": "Review Board Action", "description": "Record an operator board decision as a chained, signed receipt.\n\nThe scope gate is enforced upstream by the dashboard-auth middleware\n(operator scope required for this write); the acting principal arrives on\n``request.state.dashboard_principal``. The decision row is appended via\n``EventJournal.resume`` so it chains onto the verified journal tail and\nfails closed on a poisoned chain (``409``).", "operationId": "review_board_action_dashboard_review_board_runs__run_id__tasks__task_id__review_post", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReviewActionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/dashboard/review-board": { "get": { "summary": "Review Board Page", "description": "Serve the review-board page.\n\nThe page is a pure consumer of the projection endpoints above plus the\nexisting ``/events`` SSE stream; it holds no state of its own, so\nreloading it (or opening it on a second machine against the same\njournal) renders the identical board.", "operationId": "review_board_page_dashboard_review_board_get", "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } } } } }, "/artifacts": { "get": { "summary": "List Artifacts", "description": "Return every artifact key the local lineage spines carry.", "operationId": "list_artifacts_artifacts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/artifacts/health": { "get": { "summary": "Artifact Health", "description": "Return the canonical health verdict for ``?uri=``.\n\nQuery parameters:\n\n* ``uri`` (required) - the artifact key.\n* ``at`` - evaluation instant; defaults to the wall clock. Pin it to\n reproduce a verdict byte-for-byte against the CLI.\n* ``cadence_seconds`` - declared refresh cadence; omitted means the cadence\n leg reports ``not_applicable``.\n\nThe body is the exact string the CLI prints for the same state and instant,\nbyte for byte. The status is always 200: the verdict is the payload, and a\nred artifact is a successfully computed answer, not a failed request.", "operationId": "artifact_health_artifacts_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/artifacts/log": { "get": { "summary": "Artifact Log Route", "description": "Return productions of ``?uri=``, newest first (the attribution log).\n\nRecorded attempts -- tasks that declared this artifact and did not deliver it\n-- travel in the same document under ``attempts`` (issue #2559), so a\nconsumer cannot see the productions without also seeing what tried and\nfailed. Byte-identical to what the CLI prints for the same state.", "operationId": "artifact_log_route_artifacts_log_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/missions": { "get": { "summary": "Missions List", "description": "List mission ids that have a ledger to project, newest first.", "operationId": "missions_list_missions_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/missions/{mission_id}": { "get": { "summary": "Mission Projection", "description": "Serve the mission projection receipt for ``mission_id``.\n\nThe response is a deterministic function of the mission's ledger file: the\nsame ledger bytes serve the same ``status`` and ``mission_status_hash`` from\nany server, so two operators cross-check byte for byte.\n``ledger_verified=false`` (with ``overall=unverified``) marks a chain that no\nlonger recomputes -- the timeline still renders, but the screen must show the\nunverified banner instead of trusting the state.", "operationId": "mission_projection_missions__mission_id__get", "parameters": [ { "name": "mission_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Mission Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/missions/{mission_id}/digest": { "get": { "summary": "Mission Digest", "description": "Serve the canonical daily progress digest for a fire instant.\n\nRead-only: the digest is recomputed from the ledger as a pure fold, so the\nendpoint never writes to the chain. The payload carries the ``digest_hash``,\nthe ``receipt_id`` (the per-fire delivery idempotency key), and the verbatim\n``message`` the digest projects to -- the exact bytes a chat delivery posts,\nso a caller can cross-check a posted message against this projection.", "operationId": "mission_digest_missions__mission_id__digest_get", "parameters": [ { "name": "mission_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Mission Id" } }, { "name": "fire_time", "in": "query", "required": true, "schema": { "type": "integer", "description": "Integer Unix epoch of the canonical fire instant.", "title": "Fire Time" }, "description": "Integer Unix epoch of the canonical fire instant." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/missions/{mission_id}/evidence/{task_id}": { "get": { "summary": "Mission Evidence", "description": "Serve the sealed evidence bundle behind a timeline element's provenance link.\n\n``bundle_hash`` is recomputed from the canonical binding bytes on every read,\nso the drawer always shows the bundle's current identity -- and a bundle that\nno longer matches the hash a phase receipt bound projects that phase as\nunverified in the mission projection above.", "operationId": "mission_evidence_missions__mission_id__evidence__task_id__get", "parameters": [ { "name": "mission_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Mission Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/search": { "get": { "summary": "Search Tasks", "description": "Search tasks with pagination, sorting, and filtering.\n\nQuery params:\n page: Page number (1-based, default 1).\n per_page: Items per page (1-100, default 20).\n sort: Sort field (created_at, priority, title, role, status).\n order: Sort order (asc, desc; default desc).\n status: Filter by task status.\n role: Filter by task role.\n assigned_agent: Filter by assigned agent.", "operationId": "search_tasks_api_v1_tasks_search_get", "parameters": [ { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "default": 1, "title": "Page" } }, { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "default": 20, "title": "Per Page" } }, { "name": "sort", "in": "query", "required": false, "schema": { "type": "string", "default": "created_at", "title": "Sort" } }, { "name": "order", "in": "query", "required": false, "schema": { "type": "string", "default": "desc", "title": "Order" } }, { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } }, { "name": "role", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" } }, { "name": "assigned_agent", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Assigned Agent" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PaginatedSearchResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/agents": { "get": { "summary": "List Agents", "description": "Return a flat list of agent sessions for the web GUI grid.\n\nWhen ``TaskStore.agents`` is empty (e.g. only mock adapters spawned and\nthey never heartbeat) we fall back to synthesising one entry per\nclaimed/in-progress task, marked with ``\"synthetic\": true``. That keeps\nthe GUI grid populated during demos and avoids the dreaded \"0 sessions\"\nempty state when work is obviously in flight.", "operationId": "list_agents_api_v1_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "additionalProperties": true, "type": "object" }, "type": "array", "title": "Response List Agents Api V1 Agents Get" } } } } } } }, "/api/v1/agents/comparison": { "get": { "tags": [ "agent-comparison" ], "summary": "Get Agent Comparison", "description": "Return per-(adapter, model) performance comparison metrics.\n\nAggregates data from all agent sessions in the current run:\nsuccess rate, average completion time, cost per task, and\nquality gate pass rate.\n\nReturns:\n JSON list of :class:`AgentMetrics` objects sorted by adapter\n then model.", "operationId": "get_agent_comparison_api_v1_agents_comparison_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/AgentMetrics" }, "type": "array", "title": "Response Get Agent Comparison Api V1 Agents Comparison Get" } } } } } } }, "/api/v1/agents/{session_id}/logs": { "get": { "summary": "Agent Logs", "description": "Return log file content for a session.\n\nArgs:\n session_id: Agent session ID.\n tail_bytes: If > 0, return only the last N bytes of the log.", "operationId": "agent_logs_api_v1_agents__session_id__logs_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } }, { "name": "tail_bytes", "in": "query", "required": false, "schema": { "type": "integer", "default": 0, "title": "Tail Bytes" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentLogsResponse" } } } }, "404": { "description": "No log file for session" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/agents/{session_id}/kill": { "post": { "summary": "Agent Kill", "description": "Request that an agent session be killed.\n\nWrites a ``.kill`` signal file that the orchestrator picks up on\nits next tick.", "operationId": "agent_kill_api_v1_agents__session_id__kill_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AgentKillResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/agents/{session_id}/stream": { "get": { "summary": "Agent Stream", "description": "SSE stream of live log output for a session.", "operationId": "agent_stream_api_v1_agents__session_id__stream_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/auth/providers": { "get": { "tags": [ "authentication" ], "summary": "Auth Providers", "description": "List available authentication providers.", "operationId": "auth_providers_api_v1_auth_providers_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/AuthProvidersResponse" } } } } } } }, "/api/v1/auth/login": { "get": { "tags": [ "authentication" ], "summary": "Login", "description": "Initiate SSO login. Redirects to IdP.", "operationId": "login_api_v1_auth_login_get", "parameters": [ { "name": "provider", "in": "query", "required": false, "schema": { "$ref": "#/components/schemas/LoginProvider", "default": "oidc" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Authentication provider not enabled" }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/auth/oidc/callback": { "get": { "tags": [ "authentication" ], "summary": "Oidc Callback", "description": "OIDC authorization code callback.", "operationId": "oidc_callback_api_v1_auth_oidc_callback_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Missing or invalid authorization code or state" }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/api/v1/auth/saml/acs": { "post": { "tags": [ "authentication" ], "summary": "Saml Acs", "description": "SAML Assertion Consumer Service (ACS) endpoint.\n\nReceives the SAML Response from the IdP via HTTP-POST binding.", "operationId": "saml_acs_api_v1_auth_saml_acs_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Missing SAMLResponse" }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/api/v1/auth/saml/metadata": { "get": { "tags": [ "authentication" ], "summary": "Saml Metadata", "description": "SAML SP metadata endpoint for IdP configuration.", "operationId": "saml_metadata_api_v1_auth_saml_metadata_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/api/v1/auth/cli/device": { "post": { "tags": [ "authentication" ], "summary": "Device Code Request", "description": "Initiate device authorization flow for CLI login.\n\nThe CLI calls this to get a device_code and user_code.\nThe user enters the user_code in the web dashboard after SSO login\nto authorize the CLI session.", "operationId": "device_code_request_api_v1_auth_cli_device_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceCodeRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceCodeResponse" } } } }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/auth/cli/token": { "post": { "tags": [ "authentication" ], "summary": "Device Token Poll", "description": "Poll for device authorization status.\n\nReturns the access token once the user has authorized the device code.", "operationId": "device_token_poll_api_v1_auth_cli_token_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DevicePollRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DevicePollResponse" } } } }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/auth/cli/authorize": { "post": { "tags": [ "authentication" ], "summary": "Device Authorize", "description": "Authorize a device code (called from web dashboard after SSO login).\n\nRequires an authenticated user session.", "operationId": "device_authorize_api_v1_auth_cli_authorize_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/DeviceAuthorizeRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Invalid or expired user code" }, "401": { "description": "Authentication required" }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/auth/me": { "get": { "tags": [ "authentication" ], "summary": "Get Profile", "description": "Get the current authenticated user's profile.", "operationId": "get_profile_api_v1_auth_me_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/UserProfileResponse" } } } }, "401": { "description": "Authentication required" } } } }, "/api/v1/auth/logout": { "post": { "tags": [ "authentication" ], "summary": "Logout", "description": "Logout and revoke the current session.", "operationId": "logout_api_v1_auth_logout_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/api/v1/auth/group-mappings": { "get": { "tags": [ "authentication" ], "summary": "Get Group Mappings", "description": "Get current SSO group → role mappings.", "operationId": "get_group_mappings_api_v1_auth_group_mappings_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GroupMappingsResponse" } } } }, "404": { "description": "SSO authentication is not configured on this server" } } }, "put": { "tags": [ "authentication" ], "summary": "Update Group Mappings", "description": "Update SSO group → role mappings (admin only).", "operationId": "update_group_mappings_api_v1_auth_group_mappings_put", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GroupMappingsUpdateRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "400": { "description": "Invalid role value" }, "401": { "description": "Authentication required" }, "403": { "description": "Admin role required" }, "404": { "description": "SSO authentication is not configured on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/auth/users": { "get": { "tags": [ "authentication" ], "summary": "List Users", "description": "List all users (admin only).", "operationId": "list_users_api_v1_auth_users_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "401": { "description": "Authentication required" }, "403": { "description": "Admin role required" }, "404": { "description": "SSO authentication is not configured on this server" } } } }, "/api/v1/tasks": { "post": { "summary": "Create Task", "description": "Create a new task.", "operationId": "create_task_api_v1_tasks_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCreate" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "400": { "description": "Blocked by pre-create hook" }, "403": { "description": "Tenant access denied" }, "404": { "description": "Tenant not found" }, "429": { "description": "Tenant task quota exceeded" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "List Tasks", "description": "List tasks, optionally filtered by status, cell_id, and/or claim owner.\n\nWhen ``limit`` or ``offset`` query params are provided the response is a\npaginated envelope (``{tasks, total, limit, offset}``). Without them,\nthe legacy flat list is returned for backward compatibility, capped at\n``_LIST_TASKS_HARD_CAP`` items and accompanied by a ``Deprecation``\nheader asking callers to pass explicit pagination.\n\nArgs:\n request: FastAPI request.\n status: If provided, only tasks with this status are returned.\n cell_id: If provided, only tasks in this cell are returned.\n tenant: Tenant scope override.\n claimed_by_session: If provided, only tasks claimed by this parent\n orchestrator session are returned.\n limit: Maximum number of tasks to return (max 500). Triggers\n paginated response when present.\n offset: Number of tasks to skip. Triggers paginated response\n when present.\n\nReturns:\n Paginated response **or** plain list of TaskResponse dicts (capped\n at ``_LIST_TASKS_HARD_CAP``).", "operationId": "list_tasks_api_v1_tasks_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } }, { "name": "cell_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Cell Id" } }, { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } }, { "name": "claimed_by_session", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } }, { "name": "parent_session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Session Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Offset" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/batch": { "post": { "summary": "Create Tasks Batch", "description": "Create multiple tasks atomically with title dedup.", "operationId": "create_tasks_batch_api_v1_tasks_batch_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchCreateRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchCreateResponse" } } } }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/self-create": { "post": { "summary": "Self Create Subtask", "description": "Create a subtask linked to a parent task.\n\nAgents call this to decompose work during execution. The parent\ntask is automatically transitioned to ``WAITING_FOR_SUBTASKS`` on\nthe first subtask creation (if it is not already in that state).", "operationId": "self_create_subtask_api_v1_tasks_self_create_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSelfCreate" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Parent task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/next/{role}": { "get": { "summary": "Next Task", "description": "Claim the next available task for *role*.\n\nPass ``claimed_by_session`` as a query param to record which parent\norchestrator session owns the claim.\n\nPass ``parent_session_id`` to restrict claiming to tasks that were\ncreated under that coordinator session. Workers belonging to a\ncoordinator should always pass their coordinator's session ID here\nto avoid stealing tasks from other namespaces.", "operationId": "next_task_api_v1_tasks_next__role__get", "parameters": [ { "name": "role", "in": "path", "required": true, "schema": { "type": "string", "title": "Role" } }, { "name": "claimed_by_session", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } }, { "name": "parent_session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/claim-batch": { "post": { "summary": "Claim Batch", "description": "Atomically claim multiple tasks by ID for an agent.", "operationId": "claim_batch_api_v1_tasks_claim_batch_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchClaimRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchClaimResponse" } } } }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/claim": { "post": { "summary": "Claim Task", "description": "Claim a specific task by ID.\n\nPass ``expected_version`` as a query param for optimistic locking\n(CAS). If the task's version doesn't match, returns 409 Conflict.\n\nPass ``claimed_by_session`` to record which parent orchestrator\nsession owns this claim.", "operationId": "claim_task_api_v1_tasks__task_id__claim_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } }, { "name": "expected_version", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Expected Version" } }, { "name": "claimed_by_session", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Version conflict or invalid state" }, "503": { "description": "Server is draining" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/complete": { "post": { "summary": "Complete Task", "description": "Mark a task as done (or refused) from a worker terminal payload.\n\nStructured payloads (``body.payload`` or a JSON object embedded in\n``result_summary``) are validated against the worker completion\ncontract (#2244): an invalid payload is a typed ``contract_violation``\nfailure carrying the schema error path, and a validated refusal lands\nthe task in the terminal REFUSED state instead of DONE. Legacy prose\nsummaries are accepted unchanged.\n\nIf ``result_summary`` is empty the task is auto-transitioned to\n``FAILED`` with ``reason='completion missing summary'`` and\na 422 is returned with the failed task payload so the client knows the\nslot was released.", "operationId": "complete_task_api_v1_tasks__task_id__complete_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCompleteRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Empty result_summary or contract violation - task auto-failed" } } } }, "/api/v1/tasks/{task_id}/wait-for-subtasks": { "post": { "summary": "Wait For Subtasks", "description": "Mark a parent task as waiting until its generated subtasks complete.", "operationId": "wait_for_subtasks_api_v1_tasks__task_id__wait_for_subtasks_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskWaitForSubtasksRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/fail": { "post": { "summary": "Fail Task", "description": "Mark a task as failed.", "operationId": "fail_task_api_v1_tasks__task_id__fail_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskFailRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/release": { "post": { "summary": "Release Task", "description": "Release a claimed task back to the open pool without failing it.\n\nA cluster worker that claims a task but cannot start its agent (e.g. the\nworkspace is not a usable git checkout, or the adapter spawn fails) must\nreturn the task to the pool so another node can pick it up, rather than\nstranding it in ``claimed`` with no live agent (#3018). Distinct from\n``/fail`` (terminal FAILED) and ``/reopen`` (DONE -> OPEN): the task\ntransitions CLAIMED/IN_PROGRESS -> OPEN and is immediately claimable again.", "operationId": "release_task_api_v1_tasks__task_id__release_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskReleaseRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/reopen": { "post": { "summary": "Reopen Task", "description": "Reopen a done task that failed janitor verification (same task id).\n\nTransitions DONE -> OPEN and increments\n``metadata['janitor_reopen_count']``. The orchestrator enforces the\nreopen budget; this endpoint only performs the state transition.", "operationId": "reopen_task_api_v1_tasks__task_id__reopen_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskReopenRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/close": { "post": { "summary": "Close Task", "description": "Mark a verified task as closed (terminal success state).", "operationId": "close_task_api_v1_tasks__task_id__close_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/cancel": { "post": { "summary": "Cancel Task", "description": "Cancel a task and cascade to all of its descendant subtasks.\n\nWalks the subtask tree (``parent_task_id`` references) via\n``TaskStore.cancel_cascade`` so that children are not left running\nafter the parent is aborted. Returns the root task.", "operationId": "cancel_task_api_v1_tasks__task_id__cancel_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCancelRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/block": { "post": { "summary": "Block Task", "description": "Mark a task as blocked -- requires human intervention to unblock.", "operationId": "block_task_api_v1_tasks__task_id__block_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskBlockRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Invalid state transition" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/progress": { "post": { "summary": "Progress Task", "description": "Append an intermediate progress update to a task.\n\nAlso stores a progress snapshot for stall detection when snapshot\nfields (files_changed, tests_passing, errors) are provided.", "operationId": "progress_task_api_v1_tasks__task_id__progress_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskProgressRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "Get Task Progress", "description": "Return the chain-computed progress vector for a task.\n\nThe ledger read is resolved from the task's own authoritative run id, never\nfrom a client-supplied parameter, so the vector cannot be steered by pairing\nthis task's journal with an arbitrary run's ledger.", "operationId": "get_task_progress_api_v1_tasks__task_id__progress_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskProgressResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/partial-merge": { "post": { "summary": "Partial Merge Task", "description": "Incrementally merge specific committed files from the agent's branch into main.\n\nAllows a long-running agent to push a completed subset of its work (e.g.\nthe first 5 of 10 test files) while still writing the rest. Reduces\nwall-clock time by making partial results available downstream earlier.\n\nOnly files that are already **committed** in the agent's worktree branch\n(``agent/``) are merged. Uncommitted files are returned in\n``uncommitted_files`` so the caller knows to commit them in the worktree\nfirst. Files that were already merged by a prior call are skipped and\nreturned in ``skipped_already_merged``.\n\nRequires the task to be ``in_progress`` with a ``claimed_by_session`` set.", "operationId": "partial_merge_task_api_v1_tasks__task_id__partial_merge_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartialMergeRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartialMergeResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Task not in progress or has no active session" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "Get Partial Merge State", "description": "Return the cumulative incremental-merge state for a task's active session.\n\nUseful for monitoring how much of an in-progress task's output has already\nbeen merged into the main branch.", "operationId": "get_partial_merge_state_api_v1_tasks__task_id__partial_merge_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartialMergeResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/snapshots": { "get": { "summary": "Get Task Snapshots", "description": "Return stored progress snapshots for a task (oldest-first, up to 10).", "operationId": "get_task_snapshots_api_v1_tasks__task_id__snapshots_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/SnapshotEntry" }, "title": "Response Get Task Snapshots Api V1 Tasks Task Id Snapshots Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/counts": { "get": { "summary": "Task Counts", "description": "Return task counts per status without serialising task bodies.\n\nThis is the lightweight alternative to GET /tasks for orchestrator\ntick summaries and dashboard polling.", "operationId": "task_counts_api_v1_tasks_counts_get", "parameters": [ { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskCountsResponse" } } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/archive": { "get": { "summary": "Get Archive", "description": "Return the last N archived (done/failed) task records.", "operationId": "get_archive_api_v1_tasks_archive_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 50, "title": "Limit" } }, { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ArchiveRecord" }, "title": "Response Get Archive Api V1 Tasks Archive Get" } } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/graph": { "get": { "summary": "Get Task Graph", "description": "Return the task dependency graph as JSON (nodes + edges + critical path).\n\nBuilds a DAG from all current tasks and returns:\n- ``nodes``: list of {id, role, status, estimated_minutes, title}\n- ``edges``: list of {from, to, type, semantic_type}\n- ``critical_path``: ordered list of task IDs on the longest chain\n- ``critical_path_minutes``: total estimated minutes on the critical path\n- ``parallel_width``: max tasks that can run concurrently\n- ``bottlenecks``: task IDs that block the most downstream work", "operationId": "get_task_graph_api_v1_tasks_graph_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant scope access denied" }, "404": { "description": "Resource not found or tenant mismatch" } } } }, "/api/v1/tasks/{task_id}": { "get": { "summary": "Get Task", "description": "Get a single task by ID.", "operationId": "get_task_api_v1_tasks__task_id__get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "patch": { "summary": "Patch Task", "description": "Update mutable task fields (role, priority, model) - manager corrections.\n\nUsed by the manager agent or dashboard to correct mis-assigned tasks,\nadjust priority, or change model without interrupting the orchestrator.", "operationId": "patch_task_api_v1_tasks__task_id__patch", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskPatchRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/graph-neighbors": { "get": { "summary": "Get Task Graph Neighbors", "description": "Return immediate dependency neighbours for a single task.\n\nPowers the dashboard Deps tab: upstream tasks the requested one waits\non (its ``depends_on`` list) and downstream tasks that declare it as a\ndependency. Depth is intentionally fixed at 1 - the panel renders two\nflat lists, not a transitive graph.", "operationId": "get_task_graph_neighbors_api_v1_tasks__task_id__graph_neighbors_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Task Graph Neighbors Api V1 Tasks Task Id Graph Neighbors Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/gates": { "get": { "summary": "Get Task Gates", "description": "Return the persisted quality-gate report for a task.", "operationId": "get_task_gates_api_v1_tasks__task_id__gates_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Task or gate report not found" }, "500": { "description": "Gate report unreadable" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/prioritize": { "post": { "summary": "Prioritize Task", "description": "Bump a task to priority 0 so the orchestrator picks it up next.", "operationId": "prioritize_task_api_v1_tasks__task_id__prioritize_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/force-claim": { "post": { "summary": "Force Claim Task", "description": "Force a task back to open with priority 0 for immediate pickup.\n\nResets claimed/in_progress tasks back to open so the orchestrator's\nnext tick will spawn a fresh agent for them. Terminal tasks\n(done/failed/cancelled) are rejected with 409.", "operationId": "force_claim_task_api_v1_tasks__task_id__force_claim_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskResponse" } } } }, "404": { "description": "Task not found" }, "409": { "description": "Cannot force-claim terminal task" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/agents/{agent_id}/heartbeat": { "post": { "summary": "Agent Heartbeat", "description": "Register an agent heartbeat.", "operationId": "agent_heartbeat_api_v1_agents__agent_id__heartbeat_post", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HeartbeatRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HeartbeatResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/bulletin": { "post": { "summary": "Post Bulletin", "description": "Append a message to the bulletin board.\n\nReturns 201 when the message is stored and any registered signal action\nran. When a signal action hook fails (for example a ``blocker`` whose\nclearance gate did not materialize), the message is still on the\nappend-only board and queued in the board's retry outbox, but the action is\nnot complete: the response is 202 rather than 201 so the caller can tell\n\"stored and acted on\" from \"stored, action pending retry\" (#2648).", "operationId": "post_bulletin_api_v1_bulletin_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulletinPostRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BulletinMessageResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "Get Bulletin", "description": "Get bulletin messages since a given timestamp.", "operationId": "get_bulletin_api_v1_bulletin_get", "parameters": [ { "name": "since", "in": "query", "required": false, "schema": { "type": "number", "default": 0.0, "title": "Since" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/BulletinMessageResponse" }, "title": "Response Get Bulletin Api V1 Bulletin Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/channel/query": { "post": { "summary": "Post Channel Query", "description": "Post a coordination query targeted at an agent or role.", "operationId": "post_channel_query_api_v1_channel_query_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelQueryRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelQueryResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/channel/{query_id}/respond": { "post": { "summary": "Post Channel Response", "description": "Respond to a channel query.", "operationId": "post_channel_response_api_v1_channel__query_id__respond_post", "parameters": [ { "name": "query_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Query Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelResponseRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ChannelResponseResponse" } } } }, "404": { "description": "Query not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/channel/queries": { "get": { "summary": "Get Channel Queries", "description": "Get pending queries, optionally filtered by agent_id or role.", "operationId": "get_channel_queries_api_v1_channel_queries_get", "parameters": [ { "name": "agent_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Agent Id" } }, { "name": "role", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ChannelQueryResponse" }, "title": "Response Get Channel Queries Api V1 Channel Queries Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/channel/{query_id}/responses": { "get": { "summary": "Get Channel Responses", "description": "Get all responses for a channel query.", "operationId": "get_channel_responses_api_v1_channel__query_id__responses_get", "parameters": [ { "name": "query_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Query Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/ChannelResponseResponse" }, "title": "Response Get Channel Responses Api V1 Channel Query Id Responses Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/claim-receipt": { "post": { "summary": "Claim Receipt", "description": "Claim the next eligible backlog row and return a signed claim receipt.\n\nThe dependency gate is enforced by :class:`ClaimFilter`: a row is offered\nonly when its ``depends_on`` are all in ``completed_ids``. The granted\nclaim is mirrored into the audit chain via the existing\n``record_task_claim_receipt`` (no new event type), and the returned\nreceipt embeds that event's chain head so the claim verifies offline. A\nfilter matching no eligible row returns a signed refusal receipt.", "operationId": "claim_receipt_api_v1_tasks_claim_receipt_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClaimReceiptRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Claim Receipt Api V1 Tasks Claim Receipt Post" } } } }, "503": { "description": "Server is draining -- no new claims accepted" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/messages": { "post": { "summary": "Post Task Message", "description": "Append one typed message to the recipient task's mailbox.\n\nThe message is DLP-redacted, HMAC-chained onto the mailbox journal,\nEd25519-signed, and mirrored into the audit chain before the response\nis returned - the response IS the signed journal entry.", "operationId": "post_task_message_api_v1_tasks__task_id__messages_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskMessagePost" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskMessageResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Unknown message kind or body over the byte cap" }, "429": { "description": "Recipient task mailbox is full" } } }, "get": { "summary": "Get Task Messages", "description": "Deliver pending messages for a task, in chain append order.\n\n``since_seq`` is a deterministic cursor: pass the highest ``seq``\nalready processed to receive only newer messages. Replaying the same\njournal always reproduces the same delivery order.", "operationId": "get_task_messages_api_v1_tasks__task_id__messages_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } }, { "name": "since_seq", "in": "query", "required": false, "schema": { "type": "integer", "default": -1, "title": "Since Seq" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/TaskMessageResponse" }, "title": "Response Get Task Messages Api V1 Tasks Task Id Messages Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/artifacts": { "post": { "summary": "Post Task Artifact", "description": "Post one journal-anchored artifact against a task the caller holds.", "operationId": "post_task_artifact_api_v1_tasks__task_id__artifacts_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskArtifactPost" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskArtifactContentResponse" } } } }, "403": { "description": "Caller does not hold the task's claim" }, "404": { "description": "Task not found" }, "413": { "description": "Artifact payload exceeds the per-blob cap" }, "422": { "description": "Invalid artifact payload" } } }, "get": { "summary": "List Task Artifacts", "description": "List every posted artifact version with its verification state.", "operationId": "list_task_artifacts_api_v1_tasks__task_id__artifacts_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/TaskArtifactContentResponse" }, "title": "Response List Task Artifacts Api V1 Tasks Task Id Artifacts Get" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/tasks/{task_id}/steer": { "post": { "summary": "Post Task Steer", "description": "Record a steering receipt for a running worker and apply its effect.\n\nThe receipt is bound into the audit chain before the effect executes; the\n``steer.*`` mailbox message and any process signal reference the receipt\nhash returned here. An effect can never precede its receipt.", "operationId": "post_task_steer_api_v1_tasks__task_id__steer_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSteerPost" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskSteerResponse" } } } }, "403": { "description": "Scope is not authorised to steer" }, "404": { "description": "Task not found" }, "409": { "description": "Confirmed payload differs from the executed command" }, "422": { "description": "Malformed steering command" }, "503": { "description": "Task mailbox is not configured" } } } }, "/api/v1/cluster/nodes": { "post": { "summary": "Register Node", "description": "Register a new node in the cluster.", "operationId": "register_node_api_v1_cluster_nodes_post", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeRegisterRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeResponse" } } } }, "401": { "description": "Cluster authentication failed" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "get": { "summary": "List Nodes", "description": "List all cluster nodes, optionally filtered by status.", "operationId": "list_nodes_api_v1_cluster_nodes_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/NodeResponse" }, "title": "Response List Nodes Api V1 Cluster Nodes Get" } } } }, "400": { "description": "Invalid node status" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/nodes/{node_id}/heartbeat": { "post": { "summary": "Node Heartbeat", "description": "Record a heartbeat from a cluster node.", "operationId": "node_heartbeat_api_v1_cluster_nodes__node_id__heartbeat_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeHeartbeatRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/NodeResponse" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not registered" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/nodes/{node_id}": { "delete": { "summary": "Unregister Node", "description": "Remove a node from the cluster.", "operationId": "unregister_node_api_v1_cluster_nodes__node_id__delete", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "204": { "description": "Successful Response" }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/nodes/{node_id}/cordon": { "post": { "summary": "Cordon Node", "description": "Cordon a node -- exclude from scheduling.", "operationId": "cordon_node_api_v1_cluster_nodes__node_id__cordon_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Cordon Node Api V1 Cluster Nodes Node Id Cordon Post" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/nodes/{node_id}/uncordon": { "post": { "summary": "Uncordon Node", "description": "Uncordon a node -- resume accepting tasks.", "operationId": "uncordon_node_api_v1_cluster_nodes__node_id__uncordon_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Uncordon Node Api V1 Cluster Nodes Node Id Uncordon Post" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/nodes/{node_id}/drain": { "post": { "summary": "Drain Node", "description": "Start draining a node -- cordon + signal agents to finish.", "operationId": "drain_node_api_v1_cluster_nodes__node_id__drain_post", "parameters": [ { "name": "node_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Node Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Drain Node Api V1 Cluster Nodes Node Id Drain Post" } } } }, "401": { "description": "Cluster authentication failed" }, "404": { "description": "Node not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/status": { "get": { "summary": "Cluster Status", "description": "Get cluster status summary.", "operationId": "cluster_status_api_v1_cluster_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClusterStatusResponse" } } } } } } }, "/api/v1/cluster/claims/gossip": { "post": { "summary": "Gossip Claims", "description": "Fold peer claim receipts into this node's signed journal (#2558).\n\nThe leaderless counterpart to ``POST /cluster/steal``: no node decides who\ngets what here. Each receipt is folded only after its Ed25519 signature and\nits chain link both verify, so an unverifiable receipt is never written.\n\nA receipt that does not extend the local head is *not* merged. It produces\na signed ``fork`` receipt carrying the divergence entry index, which the\nresponse surfaces through ``forked``. Silent merge would be the one failure\nmode a leaderless design cannot recover from: two partitions would each\nhold a coherent-looking journal describing incompatible work.\n\nAuthorisation reuses the node-heartbeat scope: gossip is a peer-to-peer\nfleet-membership operation, not an administrative one.", "operationId": "gossip_claims_api_v1_cluster_claims_gossip_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClaimGossipRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ClaimGossipResponse" } } } }, "401": { "description": "Cluster authentication failed" }, "409": { "description": "Node is not running the MESH topology" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/cluster/steal": { "post": { "summary": "Steal Tasks", "description": "Evaluate task stealing policy and reassign claimed tasks between nodes.\n\nWorkers report their queue depths; the server runs the steal policy and\nreturns a list of task reassignments. Stolen tasks are reset to ``open``\nso the receiver node can claim them.", "operationId": "steal_tasks_api_v1_cluster_steal_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskStealRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskStealResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/a2a/agent-card": { "get": { "summary": "Agent Card", "description": "Publish the Bernstein orchestrator Agent Card (legacy A2A path).\n\nThe richer service manifest at ``/.well-known/agent.json`` is served by\n``routes.well_known``; this endpoint is preserved for callers that\nhistorically pulled the orchestrator's own A2A card.", "operationId": "agent_card_api_v1_a2a_agent_card_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AAgentCardResponse" } } } } } } }, "/api/v1/a2a/agents": { "get": { "summary": "List A2A Agents", "description": "Return Bernstein's A2A agent card via the task API namespace.", "operationId": "list_a2a_agents_api_v1_a2a_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AAgentCardResponse" } } } } } } }, "/api/v1/a2a/message": { "post": { "summary": "A2A Message", "description": "Receive an inbound A2A message and inject it into the target task context.", "operationId": "a2a_message_api_v1_a2a_message_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AMessageRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AMessageResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/a2a/tasks/send": { "post": { "summary": "A2A Send Task", "description": "Receive a task from an external A2A agent.\n\nCreates both an A2A task record and a corresponding Bernstein task,\nlinking them together for lifecycle synchronisation.", "operationId": "a2a_send_task_api_v1_a2a_tasks_send_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2ATaskSendRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2ATaskResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/a2a/tasks/{a2a_task_id}": { "get": { "summary": "A2A Get Task", "description": "Get an A2A task by ID, syncing status from the Bernstein task.", "operationId": "a2a_get_task_api_v1_a2a_tasks__a2a_task_id__get", "parameters": [ { "name": "a2a_task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "A2A Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2ATaskResponse" } } } }, "404": { "description": "A2A task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/a2a/tasks/{a2a_task_id}/artifacts": { "post": { "summary": "A2A Add Artifact", "description": "Attach an artifact to an A2A task.", "operationId": "a2a_add_artifact_api_v1_a2a_tasks__a2a_task_id__artifacts_post", "parameters": [ { "name": "a2a_task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "A2A Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AArtifactRequest" } } } }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/A2AArtifactResponse" } } } }, "404": { "description": "A2A task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/a2a/v0/tasks": { "post": { "summary": "A2A V0 Accept Task", "description": "Accept a federated task delegated from a peer orchestrator.\n\nWire format::\n\n {\n \"sender\": { ...AgentCard... },\n \"task\": { \"id\": \"...\", \"message\": \"...\", \"role\": \"...\" }\n }\n\nReturns 202 with the local federated-task id and the remote task id\nthat was offered. Validation errors return HTTP 409 so that the\ncaller's retry policy treats them as terminal (the peer is reachable\nand authoritative, no point retrying with the same body).", "operationId": "a2a_v0_accept_task_api_v1_a2a_v0_tasks_post", "responses": { "202": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response A2A V0 Accept Task Api V1 A2A V0 Tasks Post" } } } }, "400": { "description": "Invalid sender Agent Card or task body" }, "409": { "description": "Task rejected (validation, capacity, etc.)" } } } }, "/api/v1/status": { "get": { "summary": "Status Dashboard", "description": "Dashboard summary of task counts.", "operationId": "status_dashboard_api_v1_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/status/duration-predictions": { "get": { "summary": "Duration Predictions", "description": "Return ML-predicted duration estimates for all open/claimed tasks.\n\nUses the local GradientBoosting duration predictor. Falls back to the\nstatic cold-start table when fewer than 50 completions are available.\n\nResponse shape::\n\n {\n \"predictor\": {\n \"trained\": true,\n \"training_samples\": 142,\n \"cold_start\": false\n },\n \"tasks\": [\n {\n \"task_id\": \"abc123\",\n \"title\": \"Refactor auth module\",\n \"role\": \"backend\",\n \"p50_seconds\": 720.0,\n \"p90_seconds\": 1440.0,\n \"confidence\": 0.62,\n \"is_cold_start\": false,\n \"eta_p50\": \"12m 0s\",\n \"eta_p90\": \"24m 0s\"\n }\n ]\n }", "operationId": "duration_predictions_api_v1_status_duration_predictions_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/routing/bandit": { "get": { "summary": "Bandit Routing Stats", "description": "Return contextual bandit routing statistics.\n\nReads persisted state from ``.sdd/routing/``. Returns an empty dict\nwhen bandit routing has not been activated (``--routing bandit`` not passed).", "operationId": "bandit_routing_stats_api_v1_routing_bandit_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/dashboard": { "get": { "summary": "Dashboard Page", "description": "Serve the single-page web dashboard.", "operationId": "dashboard_page_api_v1_dashboard_get", "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } } } } }, "/api/v1/dashboard/static/{asset_name}": { "get": { "summary": "Dashboard Static Asset", "description": "Serve allow-listed static assets used by the web dashboard.", "operationId": "dashboard_static_asset_api_v1_dashboard_static__asset_name__get", "parameters": [ { "name": "asset_name", "in": "path", "required": true, "schema": { "type": "string", "title": "Asset Name" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/data": { "get": { "summary": "Dashboard Data", "description": "Return all mission control dashboard data as JSON.\n\nIncludes stats, tasks with timeline data, agent details with costs,\nfile ownership map, cost history, and alerts.", "operationId": "dashboard_data_api_v1_dashboard_data_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/events": { "get": { "summary": "Sse Events", "description": "Server-Sent Events stream for real-time dashboard updates.\n\nIncludes disconnect detection via heartbeat pings and connection\ntimeout handling to prevent leaked subscriber queues.", "operationId": "sse_events_api_v1_events_get", "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } } } } }, "/api/v1/badge.json": { "get": { "summary": "Get Badge", "description": "Return dynamic badge data for GitHub shields.io integration.\n\nShows tasks completed, total cost, and quality score.\nUsage: https://img.shields.io/endpoint?url=/badge.json", "operationId": "get_badge_api_v1_badge_json_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/memory/audit": { "get": { "summary": "Memory Audit", "description": "Audit the lesson memory provenance chain (OWASP ASI06 2026).\n\nReturns chain integrity status and a per-entry provenance trail.\nDetects tampering, insertion, deletion, and reordering attacks.", "operationId": "memory_audit_api_v1_memory_audit_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/broadcast": { "post": { "summary": "Broadcast Command", "description": "Send a message to all running agents via fastest available channel.\n\nUses stdin pipe where available (sub-second delivery), falls back\nto file-based COMMAND signal for agents without pipe support.\n\nExpects JSON body: ``{\"message\": \"some instruction\"}``.", "operationId": "broadcast_command_api_v1_broadcast_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BroadcastRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/health": { "get": { "summary": "Health Check", "description": "Liveness check with component-level status.", "operationId": "health_check_api_v1_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthResponse" } } } } } } }, "/api/v1/health/ready": { "get": { "summary": "Ready Check", "description": "Readiness check for load balancers.", "operationId": "ready_check_api_v1_health_ready_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/ready": { "get": { "summary": "Ready Alias", "description": "Alias for /health/ready.", "operationId": "ready_alias_api_v1_ready_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/health/live": { "get": { "summary": "Live Check", "description": "Liveness check for process monitoring.", "operationId": "live_check_api_v1_health_live_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/alive": { "get": { "summary": "Live Alias", "description": "Alias for /health/live.", "operationId": "live_alias_api_v1_alive_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/config": { "post": { "summary": "Update Config", "description": "Update mutable config fields at runtime.\n\nAccepts JSON body with ``{\"max_agents\": N}``. Writes the change to\n``bernstein.yaml`` so the orchestrator's hot-reload picks it up on\nthe next tick (~30s). Returns the new effective value.\n\nAgent identity JWTs (per-agent, task-scoped) are rejected with 403 -\nmutating process-wide config is an operator action. SSO admin users\nand legacy operator tokens may proceed. Bearer-level permission\nenforcement is handled by :class:`SSOAuthMiddleware` via the\n``admin:manage`` mapping; this check adds defense-in-depth against any\nagent JWT that slips through the middleware's prefix match.", "operationId": "update_config_api_v1_config_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/shutdown": { "post": { "summary": "Shutdown Server", "description": "Initiate graceful server shutdown.\n\nAccepts an optional JSON body ``{\"reason\": \"...\"}``. Schedules a\nSIGTERM to the current process shortly after the response is sent so\nthat the Uvicorn server exits cleanly.", "operationId": "shutdown_server_api_v1_shutdown_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/cache-stats": { "get": { "summary": "Cache Stats", "description": "Return prompt caching statistics from the manifest.\n\nReads `.sdd/caching/manifest.jsonl` and returns aggregated counts,\nestimated token savings, and estimated USD savings based on the\nAnthropic cached-input discount (90% off standard input price).\n\nReturns 200 with empty statistics if no cache manifest exists yet.", "operationId": "cache_stats_api_v1_cache_stats_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/metrics": { "get": { "summary": "Metrics Endpoint", "description": "Prometheus metrics scrape endpoint.\n\nUpdates all gauges from the current task store state, then\nreturns the full metric exposition in Prometheus text format.", "operationId": "metrics_endpoint_api_v1_metrics_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/workspace": { "get": { "tags": [ "workspace" ], "summary": "Workspace Status", "description": "Return repository status for the configured workspace.", "operationId": "workspace_status_api_v1_workspace_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WorkspaceResponse" } } } }, "400": { "description": "Invalid seed file" } } } }, "/api/v1/workspace/merge-order": { "post": { "tags": [ "workspace" ], "summary": "Workspace Merge Order", "description": "Return the repo merge order derived from current cross-repo task dependencies.", "operationId": "workspace_merge_order_api_v1_workspace_merge_order_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/MergeOrderResponse" } } } }, "400": { "description": "Invalid seed file" }, "404": { "description": "No workspace configured" } } } }, "/api/v1/alerts": { "get": { "summary": "Get Alerts", "description": "Return current dashboard alerts as JSON.\n\nBuilds alerts from the live task/agent state - failed tasks, blocked\ntasks, stale agents, and budget thresholds. Intended for dashboard\npolling or external monitoring.\n\nReturns a JSON object with keys:\n- ``alerts``: list of alert dicts (``level``, ``message``, ``detail``)\n- ``count``: total number of alerts\n- ``ts``: server timestamp (Unix seconds)", "operationId": "get_alerts_api_v1_alerts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhook": { "post": { "summary": "Generic Webhook", "description": "Create a task directly from a generic inbound webhook payload.\n\nThe endpoint is intentionally small and separate from the trigger-manager\nflow: callers POST a task-shaped payload and Bernstein creates one task.\n``BERNSTEIN_WEBHOOK_SECRET`` must be configured (fail-closed; )\nand each request must carry a fresh ``X-Bernstein-Timestamp`` header\nplus a matching ``X-Bernstein-Webhook-Signature-256`` HMAC over\n``f\"{timestamp}.\".encode() + body``. The plaintext\n``X-Bernstein-Webhook-Secret`` fallback has been removed; callers\nrelying on it must upgrade to the HMAC + timestamp flow.\n\nAutomation bridge (#2512): an admitted trigger returns a signed,\nchain-anchored trigger receipt in ``receipt`` so the calling platform holds\na proof of what it asked for rather than a bare task reference. A trigger\nthat fails authentication, or that replays a trigger id already admitted,\nis refused with its own signed refusal receipt (HTTP 401 and 409\nrespectively) -- the negative path leaves a record, never a silent drop.", "operationId": "generic_webhook_api_v1_webhook_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookTaskCreate" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/WebhookTaskResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/webhooks/github": { "post": { "summary": "Github Webhook", "description": "Receive a GitHub App webhook, verify signature, and create tasks.\n\nHandles the following event types:\n- ``issues`` (opened / labeled)\n- ``pull_request_review_comment`` / ``issue_comment``\n- ``push``\n- ``workflow_run`` (completed + failure) - creates a ci-fix task, capped at\n ``MAX_CI_RETRIES`` active attempts per branch.\n\nReads ``GITHUB_WEBHOOK_SECRET`` from environment for HMAC verification.\nFail-closed: when the secret is not configured the\nendpoint is disabled and returns 503; unsigned GitHub webhooks are\nnever accepted.\nReplay protection: if the caller includes an\n``X-Bernstein-Timestamp`` header the request is additionally\nchecked for freshness - drift greater than five minutes returns\n401. Real GitHub deliveries omit this header and continue to\nwork; the check is there so bernstein-internal relays cannot be\nreplayed after capture.\nReturns 200 on success, 401 on bad/missing signature or stale\ntimestamp, 400 on parse error, 503 when the endpoint is not\nconfigured.", "operationId": "github_webhook_api_v1_webhooks_github_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/gitlab": { "post": { "summary": "Gitlab Webhook", "description": "Receive a GitLab CI webhook, verify token, and create ci-fix tasks.\n\nHandles the following event types:\n- ``pipeline`` (failed) - creates a ci-fix task, capped at\n ``MAX_CI_RETRIES`` active attempts per branch.\n- ``job`` (failed) - creates a ci-fix task for the specific job.\n\nReads ``GITLAB_WEBHOOK_TOKEN`` from environment. GitLab sends a simple\nplaintext token in the ``x-gitlab-token`` header.\nReturns 200 on success, 401 on bad/missing token.", "operationId": "gitlab_webhook_api_v1_webhooks_gitlab_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/telemetry/sentry/": { "post": { "summary": "Telemetry Sentry", "description": "Receive a Sentry-protocol issue-alert webhook.", "operationId": "telemetry_sentry_api_v1_webhooks_telemetry_sentry__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/telemetry/gha_failure/": { "post": { "summary": "Telemetry Gha Failure", "description": "Receive a GitHub Actions ``workflow_run`` failure webhook.", "operationId": "telemetry_gha_failure_api_v1_webhooks_telemetry_gha_failure__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/telemetry/datadog/": { "post": { "summary": "Telemetry Datadog", "description": "Receive a Datadog Logs webhook (stubbed in MVP).", "operationId": "telemetry_datadog_api_v1_webhooks_telemetry_datadog__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/telemetry/loki/": { "post": { "summary": "Telemetry Loki", "description": "Receive a Loki / Alertmanager webhook (stubbed in MVP).", "operationId": "telemetry_loki_api_v1_webhooks_telemetry_loki__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/telemetry/custom_jsonl/": { "post": { "summary": "Telemetry Custom Jsonl", "description": "Receive a custom JSONL tail webhook (stubbed in MVP).", "operationId": "telemetry_custom_jsonl_api_v1_webhooks_telemetry_custom_jsonl__post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/trackers/{adapter}": { "post": { "summary": "Tracker Webhook", "description": "Receive a tracker webhook, verify, dedupe, and enqueue.\n\nPath parameter:\n adapter: Short adapter name registered via\n :func:`bernstein.core.trackers.webhook_receiver.register_handler`.\n\nThe endpoint accepts any JSON object. All verification and replay\ndecisions are made before the body is enqueued. When verification\nsucceeds and the delivery is fresh the parsed\n:class:`~bernstein.core.trackers.webhook_receiver.TrackerEvent` is\nstashed on ``app.state.tracker_event_queue`` if present so the\norchestrator's normal task ingestion can drain it; if no queue is\nwired we simply log the event. Either way the tracker receives a\n200 so it does not retry.", "operationId": "tracker_webhook_api_v1_webhooks_trackers__adapter__post", "parameters": [ { "name": "adapter", "in": "path", "required": true, "schema": { "type": "string", "title": "Adapter" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/webhooks/discord/interactions": { "post": { "summary": "Discord Interactions", "description": "Receive and route Discord Application Command interactions.\n\nVerifies the Ed25519 signature, handles PING handshakes, and dispatches\nslash commands to the appropriate handler. Returns an immediate response\n(Discord requires a reply within 3 seconds).\n\nReturns:\n 200 with a Discord interaction response object on success.\n 401 if the signature is invalid.\n 400 if the payload cannot be parsed.", "operationId": "discord_interactions_api_v1_webhooks_discord_interactions_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/slack/commands": { "post": { "summary": "Slack Slash Command", "description": "Receive a Slack slash command, verify signature, and ack immediately.\n\nSlack requires a response within 3 seconds. This endpoint verifies the\nrequest signature, parses the URL-encoded form payload, and returns an\nimmediate acknowledgement. Any long-running work (task creation, etc.)\nshould be dispatched asynchronously using ``response_url``.\n\nReads ``SLACK_SIGNING_SECRET`` from environment for HMAC verification.\nReturns 200 on success, 401 on bad/missing signature, 400 on parse error.\n\nSlash command form fields parsed:\n - ``command`` - the slash command (e.g. ``/bernstein``)\n - ``text`` - text following the command\n - ``user_id`` - Slack user ID\n - ``channel_id`` - Slack channel ID\n - ``response_url`` - URL for delayed responses (up to 30 min)\n - ``trigger_id`` - trigger ID for opening modals", "operationId": "slack_slash_command_api_v1_webhooks_slack_commands_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/webhooks/slack/events": { "post": { "summary": "Slack Events", "description": "Receive Slack Events API callbacks.\n\nHandles:\n- ``url_verification``: returns the challenge value for endpoint verification.\n- ``event_callback`` with ``message`` type: creates a task when the bot is\n mentioned. Bot messages and ``message_changed`` subtypes are ignored to\n prevent loops.\n\nReads ``SLACK_SIGNING_SECRET`` from environment for HMAC verification.\nReturns 200 on success, 401 on bad/missing signature, 400 on parse error.", "operationId": "slack_events_api_v1_webhooks_slack_events_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/events/cost": { "get": { "summary": "Cost Events", "description": "SSE endpoint for real-time cost updates.\n\nListens to the global SSE bus for ``bulletin`` events that match\nthe ``live_cost_update`` status pattern and forwards them to clients.\nAlso provides periodic heartbeats.", "operationId": "cost_events_api_v1_events_cost_get", "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } } } } }, "/api/v1/costs": { "get": { "summary": "Get Costs", "description": "Aggregate cost data across all runs.\n\nScans every persisted cost file in ``.sdd/runtime/costs/``, aggregates\nper-agent and per-model totals, and computes cost attainment as\n``(total_spent / total_budget) * 100``. Budget of zero is treated as\nunlimited - attainment is reported as 0.0 in that case.", "operationId": "get_costs_api_v1_costs_get", "parameters": [ { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant access denied" }, "404": { "description": "Tenant not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/live": { "get": { "summary": "Get Cost Live", "description": "Return live cost breakdown for the most recent run.\n\nFinds the most recently modified cost file in ``.sdd/runtime/costs/``,\nloads it, and returns budget status plus per-agent and per-model\ncost breakdowns.", "operationId": "get_cost_live_api_v1_costs_live_get", "parameters": [ { "name": "tenant", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tenant" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "403": { "description": "Tenant access denied" }, "404": { "description": "Tenant not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/current": { "get": { "summary": "Get Cost Current", "description": "Return real-time cost snapshot for the active run + GUI rollups.\n\nUpdated after each agent completion. Designed for TUI sidebar polling\nand lightweight dashboard widgets. Returns per-model input/output/cache\ntoken breakdown alongside spend and budget status.\n\nWeb GUI (Costs.tsx §6.05) consumes the additive ``today_usd``,\n``week_usd``, ``projected_month_usd``, ``budget_usd``, ``used_pct``,\n``prior_week_usd``, ``delta_hour_usd``, ``resets_at`` and\n``last_sync_at`` fields. Existing TUI/CLI callers keep reading\n``spent_usd`` / ``percentage_used`` etc. unchanged.", "operationId": "get_cost_current_api_v1_costs_current_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/alerts": { "get": { "summary": "Get Cost Alerts", "description": "Return active budget alerts and 30d/90d cost trends.\n\nReads the live cost data for the most recent run, checks whether spend\nhas reached the 80% or 95% alert threshold, and returns trend data\ncomputed from ``.sdd/metrics/cost_history.jsonl``.", "operationId": "get_cost_alerts_api_v1_costs_alerts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/history": { "get": { "summary": "Get Cost History", "description": "Return cost history for chart visualization.\n\nTwo response modes share one endpoint:\n\n* ``GET /costs/history?hours=24&granularity=hour`` (web GUI sparkline) -\n returns a flat ``[{ts, usd}]`` array bucketed from cost-tracker\n usages over the last *hours* window.\n* ``GET /costs/history`` *or* ``?envelope=1`` (legacy/CLI) - returns the\n original ``{history, trend, burn_rate_*, history_days}`` envelope\n built from ``.sdd/metrics/cost_history.jsonl`` daily snapshots.\n\nThe sparkline branch lets the GUI feed `recharts` directly without\nunwrapping a ``.history`` field.", "operationId": "get_cost_history_api_v1_costs_history_get", "parameters": [ { "name": "hours", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Hours" } }, { "name": "granularity", "in": "query", "required": false, "schema": { "type": "string", "default": "day", "title": "Granularity" } }, { "name": "envelope", "in": "query", "required": false, "schema": { "type": "integer", "default": 0, "title": "Envelope" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/export": { "get": { "summary": "Export Costs", "description": "Export cost data as CSV or JSON for finance analysis.\n\nArgs:\n request: FastAPI request.\n format: Export format ('csv' or 'json').\n\nReturns:\n File response with cost data in requested format.", "operationId": "export_costs_api_v1_costs_export_get", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "json", "title": "Format" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/forecast": { "get": { "summary": "Forecast Costs", "description": "Forecast cost for next hour and project monthly spend.\n\nExtrapolates current spending rate to predict next hour's cost AND\nrolls the trailing 7-day spend out to a 30-day projection\n(``projected_month_usd``) for the web GUI's \"projected month\" KPI\ncard. The legacy fields (``forecast_next_hour_usd``,\n``burn_rate_*``, ``confidence``, ``data_points``) remain unchanged\nfor the TUI / CLI.", "operationId": "forecast_costs_api_v1_costs_forecast_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/compare": { "get": { "summary": "Compare Model Costs", "description": "Return live model cost comparison during execution.\n\nShows current costs by model with token usage statistics.", "operationId": "compare_model_costs_api_v1_costs_compare_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/cache-stats": { "get": { "summary": "Cache Stats", "description": "Return prompt cache hit rate statistics.\n\nShows cache hits/misses and savings by model.", "operationId": "cache_stats_api_v1_costs_cache_stats_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/model-comparison": { "get": { "summary": "Model Cost Comparison", "description": "Return model cost comparison report.\n\nShows what the current run would have cost with different models.\nUseful for optimizing model routing decisions.", "operationId": "model_cost_comparison_api_v1_costs_model_comparison_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/token-efficiency": { "get": { "summary": "Token Efficiency", "description": "Compare token efficiency across models and tasks.\n\nRanks models by tokens per useful line of code.", "operationId": "token_efficiency_api_v1_costs_token_efficiency_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/by-tag": { "get": { "summary": "Get Costs By Tag", "description": "Aggregate cost data grouped by allocation tag *or* by adapter.\n\nThe endpoint serves three callers:\n\n* Web GUI (``Costs.tsx`` adapter table) - calls ``GET /costs/by-tag``\n and expects an array of ``{adapter, calls, tokens, cost_usd,\n share_pct, delta_7d_pct}`` rows. With ``shape=auto`` (default) and\n no ``tag_key``, this is what we return.\n* Legacy callers passing ``tag_key=…`` - receive the existing\n ``{by_tag: {key: {value: cost}}}`` envelope.\n* Legacy callers wanting the envelope explicitly - pass\n ``shape=tags`` and get the envelope without supplying a key.\n\nThe ``hours`` parameter controls the GUI window (default 24h).", "operationId": "get_costs_by_tag_api_v1_costs_by_tag_get", "parameters": [ { "name": "tag_key", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Tag Key" } }, { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "default": 24, "title": "Hours" } }, { "name": "shape", "in": "query", "required": false, "schema": { "type": "string", "default": "auto", "title": "Shape" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/by-adapter": { "get": { "summary": "Get Costs By Adapter", "description": "Per-adapter cost breakdown for the web GUI Costs tab.\n\nReturns the same array shape as ``GET /costs/by-tag`` (default mode);\nexists as a clearer alias so the frontend doesn't have to know about\nthe legacy \"by-tag\" naming.", "operationId": "get_costs_by_adapter_api_v1_costs_by_adapter_get", "parameters": [ { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "default": 24, "title": "Hours" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/top-tasks": { "get": { "summary": "Get Costs Top Tasks", "description": "Top *limit* most-expensive tasks within the trailing *hours* window.\n\nWeb GUI Costs.tsx renders this as the \"Top 10 tasks\" card. Each item:\n``{id, title, agent, cost_usd}``. Empty list when no usage data is\npresent so the card can show its empty-state cleanly.", "operationId": "get_costs_top_tasks_api_v1_costs_top_tasks_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 10, "title": "Limit" } }, { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "default": 24, "title": "Hours" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/token-breakdown": { "get": { "summary": "Get Token Breakdown", "description": "Per-agent session token consumption breakdown.\n\nFor each agent session shows where the context budget was spent:\nsystem prompt (Bernstein overhead), context files, task description,\ntool call results accumulated at runtime, and assistant output.\n\nIdentifies optimization opportunities - e.g. if 60% of tokens are\ncontext files the agent never used.\n\nArgs:\n request: FastAPI request.\n session_id: If provided, return breakdown for a single session only.\n\nReturns:\n JSON with ``sessions`` list and aggregate ``summary``.", "operationId": "get_token_breakdown_api_v1_costs_token_breakdown_get", "parameters": [ { "name": "session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/costs/efficiency": { "get": { "summary": "Get Cost Efficiency", "description": "Real-time cost-per-line-of-code efficiency metric.\n\nShows cost efficiency as the run progresses:\n- **current**: efficiency of the most recently completed task\n- **run_average**: efficiency across all completed tasks in this run\n- **historical_average**: efficiency across all tracked runs\n\nHelps identify unusually expensive runs.\n\nReturns:\n JSON with ``current``, ``run_average``, ``historical_average``, and\n ``message`` fields.", "operationId": "get_cost_efficiency_api_v1_costs_efficiency_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/costs/{run_id}": { "get": { "summary": "Get Cost Budget", "description": "Return budget status for a specific run.\n\nLoads the persisted cost tracker from ``.sdd/runtime/costs/{run_id}.json``\nand returns its ``BudgetStatus`` as JSON.", "operationId": "get_cost_budget_api_v1_costs__run_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "No cost data for run" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/auth/status": { "get": { "summary": "Dashboard Auth Status", "description": "Report whether dashboard auth is required and who is logged in.", "operationId": "dashboard_auth_status_api_v1_dashboard_auth_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/dashboard/auth/login": { "post": { "summary": "Dashboard Auth Login", "description": "Open a dashboard session from a password or a scoped token.\n\nThe session cookie wraps exactly the principal and scope the credential\ncarried; a viewer token can never log into an operator session. Every\nattempt -- success or failure -- is journaled as a signed governance\ndecision (``dashboard.login``).", "operationId": "dashboard_auth_login_api_v1_dashboard_auth_login_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/dashboard/auth/logout": { "post": { "summary": "Dashboard Auth Logout", "description": "Close the current dashboard session (idempotent).", "operationId": "dashboard_auth_logout_api_v1_dashboard_auth_logout_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/dashboard/file_locks": { "get": { "summary": "File Locks Endpoint", "description": "Return active file locks grouped by agent for the dashboard.\n\nReads the persisted lock state from ``.sdd/runtime/file_locks.json`` and\nreturns it in a dashboard-friendly format with both a flat list and an\nagent-grouped view.\n\nReturns:\n JSON with ``all_locks`` (flat list sorted by path), ``locks_by_agent``\n (dict keyed by agent_id with files list + task info + elapsed_s),\n ``count`` (total lock count), and ``ts`` (generation timestamp).", "operationId": "file_locks_endpoint_api_v1_dashboard_file_locks_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/dashboard/team": { "get": { "summary": "Team Adoption Dashboard", "description": "Aggregate team usage metrics for engineering managers.\n\nReturns total runs, tasks completed, cost saved vs. budget,\ncode merge stats, and quality gate pass rate.", "operationId": "team_adoption_dashboard_api_v1_dashboard_team_get", "responses": { "200": { "description": "Team adoption metrics", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/graph/impact": { "get": { "tags": [ "graph" ], "summary": "Graph Impact", "description": "Return downstream files impacted by changing the given file.", "operationId": "graph_impact_api_v1_graph_impact_get", "parameters": [ { "name": "file", "in": "query", "required": true, "schema": { "type": "string", "minLength": 1, "title": "File" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ImpactResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/observability/agents": { "get": { "summary": "Observability Agents", "description": "Return runtime heartbeat, stall-profile, and log-summary data per agent.", "operationId": "observability_agents_api_v1_observability_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Agents Api V1 Observability Agents Get" } } } } } } }, "/api/v1/observability/effectiveness": { "get": { "summary": "Observability Effectiveness", "description": "Return recent effectiveness data, role trends, and best configs.", "operationId": "observability_effectiveness_api_v1_observability_effectiveness_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Effectiveness Api V1 Observability Effectiveness Get" } } } } } } }, "/api/v1/observability/recommendations": { "get": { "summary": "Observability Recommendations", "description": "Return the current recommendation set and delivery hit counts.", "operationId": "observability_recommendations_api_v1_observability_recommendations_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Recommendations Api V1 Observability Recommendations Get" } } } } } } }, "/api/v1/observability/budget": { "get": { "summary": "Observability Budget", "description": "Return completion-budget status per lineage.", "operationId": "observability_budget_api_v1_observability_budget_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Budget Api V1 Observability Budget Get" } } } } } } }, "/api/v1/observability/deps": { "get": { "summary": "Observability Deps", "description": "Return dependency-graph validation status for current tasks.", "operationId": "observability_deps_api_v1_observability_deps_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Observability Deps Api V1 Observability Deps Get" } } } } } } }, "/api/v1/recap": { "get": { "summary": "Recap", "description": "Return post-run summary with diff stats, quality scores, and cost breakdown.\n\nReads completed tasks from the archive and computes:\n- Task completion statistics\n- Git diff statistics (files changed, additions, deletions)\n- Quality score distribution\n- Cost breakdown by model and role", "operationId": "recap_api_v1_recap_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Recap Api V1 Recap Get" } } } } } } }, "/api/v1/observability/token-histogram": { "get": { "summary": "Token Histogram", "description": "Return histogram of token usage by task complexity.\n\nShows average tokens consumed for small, medium, large tasks.\nHelps understand token consumption patterns.", "operationId": "token_histogram_api_v1_observability_token_histogram_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Token Histogram Api V1 Observability Token Histogram Get" } } } } } } }, "/api/v1/observability/queue-depth": { "get": { "summary": "Get Queue Depth", "description": "Return task queue depth over time.\n\nReturns last N records of queue depth snapshots.\n\nArgs:\n request: FastAPI request.\n limit: Maximum number of records to return (default 100).\n\nReturns:\n List of queue depth snapshots with timestamps.", "operationId": "get_queue_depth_api_v1_observability_queue_depth_get", "parameters": [ { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 100, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Queue Depth Api V1 Observability Queue Depth Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/observability/timeline": { "get": { "summary": "Get Timeline", "description": "Return task timing data for timeline visualization.\n\nReturns start and end times for all tasks tracked in metrics.", "operationId": "get_timeline_api_v1_observability_timeline_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Get Timeline Api V1 Observability Timeline Get" } } } } } } }, "/api/v1/changelog": { "get": { "summary": "Get Changelog", "description": "Generate changelog from completed tasks.\n\nGroups completed tasks by type (Features, Fixes, etc.) and\nformats as markdown changelog.\n\nArgs:\n request: FastAPI request.\n days: Number of days to include (default 30).\n\nReturns:\n Dict with 'markdown' key containing changelog text.", "operationId": "get_changelog_api_v1_changelog_get", "parameters": [ { "name": "days", "in": "query", "required": false, "schema": { "type": "integer", "default": 30, "title": "Days" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Changelog Api V1 Changelog Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/observability/incidents": { "get": { "summary": "List Incidents", "description": "List all known incidents.\n\nReturns:\n Dict with 'incidents' list.", "operationId": "list_incidents_api_v1_observability_incidents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response List Incidents Api V1 Observability Incidents Get" } } } } } } }, "/api/v1/observability/incident-timeline/{incident_id}": { "get": { "summary": "Get Incident Timeline", "description": "Build a correlated incident timeline from logs, metrics, and traces.\n\nArgs:\n request: FastAPI request.\n incident_id: The incident ID to build a timeline for.\n window_before: Seconds before incident to include (default 600).\n window_after: Seconds after incident to include (default 300).\n\nReturns:\n Dict with incident metadata and sorted timeline events.", "operationId": "get_incident_timeline_api_v1_observability_incident_timeline__incident_id__get", "parameters": [ { "name": "incident_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Incident Id" } }, { "name": "window_before", "in": "query", "required": false, "schema": { "type": "integer", "default": 600, "title": "Window Before" } }, { "name": "window_after", "in": "query", "required": false, "schema": { "type": "integer", "default": 300, "title": "Window After" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Incident Timeline Api V1 Observability Incident Timeline Incident Id Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/observability/token-breakdown": { "get": { "summary": "Token Breakdown", "description": "Return per-session token consumption breakdown.\n\nFor each agent session with a ``.tokens`` sidecar file, breaks down\ntoken usage into estimated categories:\n\n- ``system_prompt_estimated``: overhead from Bernstein role templates\n- ``task_description_estimated``: tokens for the task title + description\n- ``context_estimated``: remaining input tokens (context files, tool results,\n prior conversation history, etc.)\n- ``output_tokens``: actual assistant output tokens\n\nAlso reports ``optimization_opportunities`` - a list of human-readable\ninsights when a category accounts for an unusually large share of tokens\n(e.g. \"context files are 60% of input\").\n\nToken sidecar files live at ``.sdd/runtime/{session_id}.tokens``.\nBreakdown percentages use a 4-chars/token heuristic for size estimates.\n\nReturns:\n Dict with ``sessions`` list and aggregate ``summary``.", "operationId": "token_breakdown_api_v1_observability_token_breakdown_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Token Breakdown Api V1 Observability Token Breakdown Get" } } } } } } }, "/api/v1/quality": { "get": { "summary": "Get Quality Metrics", "description": "Return aggregated internal quality metrics (last 7 days).\n\nReads from ``.sdd/metrics/`` JSONL files to compute:\n\n- ``per_model``: per-model success rate, avg tokens, and completion\n time distribution (p50/p90/p99).\n- ``overall``: aggregate across all models.\n- ``gate_stats``: per-gate pass/blocked/flagged counts (last 30 days).\n- ``guardrail_pass_rate``: fraction of gate checks that passed.\n- ``review_rejection_rate``: fraction of tasks that failed overall.\n\nReturns an empty structure when no metric data exists yet.", "operationId": "get_quality_metrics_api_v1_quality_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/quality/budget-forecast": { "get": { "summary": "Get Budget Forecast", "description": "Return projected spend for the active planned backlog.", "operationId": "get_budget_forecast_api_v1_quality_budget_forecast_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/quality/trend": { "get": { "summary": "Get Quality Trend", "description": "Return time-series quality metrics for trend visualization.\n\nBuckets quality data by day (default) or week and returns per-bucket\nsuccess rates, gate pass rates, and average quality scores. Covers the\nlast 90 days by default so dashboards can show weeks-to-months trends.\n\nQuery parameters:\n- ``days``: lookback window in days (default 90, max 365).\n- ``granularity``: ``\"day\"`` (default) or ``\"week\"``.\n\nReturns a ``series`` list ordered by date, each entry containing:\n- ``date``: ISO date string (bucket start).\n- ``ts``: Unix timestamp of the bucket start.\n- ``tasks_total``, ``tasks_success``: raw task counts.\n- ``success_rate``: fraction of tasks that succeeded (omitted if no tasks).\n- ``gate_pass_rates``: dict of gate name → pass rate for that bucket.\n- ``avg_quality_score``: mean quality score 0-100 (omitted if no scores).", "operationId": "get_quality_trend_api_v1_quality_trend_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/quality/models": { "get": { "summary": "Get Quality By Model", "description": "Return per-model quality breakdown (last 30 days).\n\nExtended view of model performance for routing configuration and cost\nanalysis. Covers a longer window than the default ``/quality`` summary.", "operationId": "get_quality_by_model_api_v1_quality_models_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/quality/file-health": { "get": { "summary": "List File Health", "description": "Return per-file code health scores, worst files first.\n\nQuery parameters:\n- ``limit``: max results (default 50, max 500).\n- ``min_score``: only return files at or below this score.\n- ``grade``: filter by grade (A/B/C/D/F).\n\nReturns a JSON object with ``files`` list and summary statistics.", "operationId": "list_file_health_api_v1_quality_file_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/quality/file-health/flagged": { "get": { "summary": "List Flagged Files", "description": "Return files currently flagged for human review due to health degradation.\n\nA file is flagged when:\n- A task dropped its health score by ≥10 points, OR\n- Its total health score is below 60 (grade D or F).\n\nReturns ``files`` list with detailed health scores and degradation context.", "operationId": "list_flagged_files_api_v1_quality_file_health_flagged_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/quality/file-health/{file_path}": { "get": { "summary": "Get File Health", "description": "Return the current health score for a single file.\n\nArgs:\n file_path: File path relative to repository root (URL-encoded).\n\nReturns 404 if the file has never been tracked.", "operationId": "get_file_health_api_v1_quality_file_health__file_path__get", "parameters": [ { "name": "file_path", "in": "path", "required": true, "schema": { "type": "string", "title": "File Path" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "File not tracked yet" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/fleet/projects": { "get": { "summary": "Fleet Projects", "description": "Return aggregated per-project snapshots for the fleet overview.\n\nResponse shape mirrors :func:`bernstein.core.fleet.web.api_projects`:\n\n.. code-block:: json\n\n {\n \"projects\": [ProjectSnapshot, ...],\n \"errors\": [],\n \"stub\": true|false,\n \"hint\": \"Run `bernstein fleet --web` for the real aggregator.\"\n }\n\n``stub: true`` means the operator UI is talking to a single-project\nserver that has no fleet aggregator wired in; the ``projects`` list\nis empty in that case so the SPA can render the empty-state.", "operationId": "fleet_projects_api_v1_fleet_projects_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Fleet Projects Api V1 Fleet Projects Get" } } } } } } }, "/api/v1/fleet/search": { "get": { "summary": "Fleet Search", "description": "Cross-project search stub for the topbar search bar.\n\nAccepts a free-text query plus the ``agent:/status:/across:`` operator\nsyntax used by the frontend search component; the stub does not yet\nexecute the search and instead returns the parsed filters so the SPA\ncan demonstrate the round-trip while the backend implementation is\nbeing built.\n\nReturns:\n ``{\"query\": str, \"filters\": {...}, \"matches\": [], \"stub\": bool}``.", "operationId": "fleet_search_api_v1_fleet_search_get", "parameters": [ { "name": "q", "in": "query", "required": false, "schema": { "type": "string", "description": "Cross-project search query", "default": "", "title": "Q" }, "description": "Cross-project search query" }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 500, "minimum": 1, "default": 50, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Fleet Search Api V1 Fleet Search Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/drain": { "get": { "summary": "Drain Status", "description": "Check drain status.", "operationId": "drain_status_api_v1_drain_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } }, "post": { "summary": "Drain Start", "description": "Begin draining -- stop accepting new task claims.", "operationId": "drain_start_api_v1_drain_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/drain/cancel": { "post": { "summary": "Drain Cancel", "description": "Cancel drain -- resume accepting claims.", "operationId": "drain_cancel_api_v1_drain_cancel_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/identities": { "get": { "tags": [ "identities" ], "summary": "List Identities", "description": "List agent identities with optional status/role filters.\n\n``status`` is validated against the :class:`AgentIdentityStatus`\nenum by FastAPI, so an unknown value yields a ``422`` rather than\nreaching the handler and raising an unhandled ``ValueError``.", "operationId": "list_identities_api_v1_identities_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "$ref": "#/components/schemas/AgentIdentityStatus" }, { "type": "null" } ], "title": "Status" } }, { "name": "role", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/identities/{identity_id}": { "get": { "tags": [ "identities" ], "summary": "Get Identity", "description": "Get details for a single agent identity.", "operationId": "get_identity_api_v1_identities__identity_id__get", "parameters": [ { "name": "identity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Identity Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Identity not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/identities/{identity_id}/revoke": { "post": { "tags": [ "identities" ], "summary": "Revoke Identity", "description": "Revoke an agent identity.", "operationId": "revoke_identity_api_v1_identities__identity_id__revoke_post", "parameters": [ { "name": "identity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Identity Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "Identity not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/identities/{identity_id}/audit": { "get": { "tags": [ "identities" ], "summary": "Identity Audit", "description": "Return the audit trail for an agent identity.", "operationId": "identity_audit_api_v1_identities__identity_id__audit_get", "parameters": [ { "name": "identity_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Identity Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "default": 100, "title": "Limit" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/.well-known/acp.json": { "get": { "summary": "Acp Discovery", "description": "ACP discovery document - editors poll this to find ACP-compatible agents.", "operationId": "acp_discovery_api_v1__well_known_acp_json_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPDiscoveryResponse" } } } } } } }, "/api/v1/acp/v0/agents": { "get": { "summary": "List Acp Agents", "description": "List all ACP-advertised agents.", "operationId": "list_acp_agents_api_v1_acp_v0_agents_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "items": { "$ref": "#/components/schemas/ACPAgentListEntry" }, "type": "array", "title": "Response List Acp Agents Api V1 Acp V0 Agents Get" } } } } } } }, "/api/v1/acp/v0/agents/{agent_id}": { "get": { "summary": "Get Acp Agent", "description": "Get detailed metadata for a specific ACP agent.", "operationId": "get_acp_agent_api_v1_acp_v0_agents__agent_id__get", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPAgentResponse" } } } }, "404": { "description": "ACP agent not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/acp/v0/runs": { "post": { "summary": "Create Acp Run", "description": "Create an ACP run - creates a Bernstein task and links it.\n\nEditors call this when the user submits a goal via the ACP sidebar.", "operationId": "create_acp_run_api_v1_acp_v0_runs_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunCreateRequest" } } }, "required": true }, "responses": { "201": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunResponse" } } } }, "400": { "description": "Unknown ACP agent" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/acp/v0/runs/{run_id}": { "get": { "summary": "Get Acp Run", "description": "Get ACP run status, syncing from the underlying Bernstein task.", "operationId": "get_acp_run_api_v1_acp_v0_runs__run_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunResponse" } } } }, "404": { "description": "ACP run not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } }, "delete": { "summary": "Cancel Acp Run", "description": "Cancel an ACP run and its underlying Bernstein task.", "operationId": "cancel_acp_run_api_v1_acp_v0_runs__run_id__delete", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ACPRunResponse" } } } }, "404": { "description": "ACP run not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/approvals": { "get": { "tags": [ "approvals" ], "summary": "List Approvals", "description": "List all pending approval requests.", "operationId": "list_approvals_api_v1_approvals_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ListApprovalsResponse" } } } } } } }, "/api/v1/approvals/{task_id}/approve": { "post": { "tags": [ "approvals" ], "summary": "Approve Task", "description": "Approve a pending approval request.\n\nWrites a .approved decision file so the orchestrator poll loop unblocks.\nThe pending file is then removed.\n\nArgs:\n task_id: Task ID to approve.\n body: Optional reason metadata.\n\nReturns:\n Success message.", "operationId": "approve_task_api_v1_approvals__task_id__approve_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalDecisionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Approve Task Api V1 Approvals Task Id Approve Post" } } } }, "400": { "description": "Invalid task_id format" }, "404": { "description": "No pending approval for task" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/approvals/{task_id}/reject": { "post": { "tags": [ "approvals" ], "summary": "Reject Task", "description": "Reject a pending approval request.\n\nWrites a .rejected decision file so the orchestrator poll loop unblocks.\nThe pending file is then removed.\n\nArgs:\n task_id: Task ID to reject.\n body: Optional reason metadata.\n\nReturns:\n Success message.", "operationId": "reject_task_api_v1_approvals__task_id__reject_post", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ApprovalDecisionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Reject Task Api V1 Approvals Task Id Reject Post" } } } }, "400": { "description": "Invalid task_id format" }, "404": { "description": "No pending approval for task" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/approvals/queue": { "get": { "tags": [ "approvals" ], "summary": "List Queued Approvals", "description": "List pending tool-call approvals (op-002).\n\nArgs:\n session_id: Optional filter; when given only approvals for that\n session are returned.", "operationId": "list_queued_approvals_api_v1_approvals_queue_get", "parameters": [ { "name": "session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/QueuedApprovalsResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/approvals/{approval_id}/resolve": { "post": { "tags": [ "approvals" ], "summary": "Resolve Queued Approval", "description": "Resolve a queued approval with ``allow``, ``reject``, or ``always``.\n\nThe request body must echo the ``nonce`` the gate issued when the\napproval was queued. Mismatches return ``409 NONCE_MISMATCH``; a\nnonce replayed against an already-resolved or evicted approval\nreturns ``410 NONCE_EXPIRED``.", "operationId": "resolve_queued_approval_api_v1_approvals__approval_id__resolve_post", "parameters": [ { "name": "approval_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Approval Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ResolveRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Response Resolve Queued Approval Api V1 Approvals Approval Id Resolve Post" } } } }, "400": { "description": "Invalid approval id or decision" }, "404": { "description": "No pending approval with that id" }, "409": { "description": "NONCE_MISMATCH" }, "410": { "description": "NONCE_EXPIRED" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/approvals/live-fragment": { "get": { "tags": [ "approvals" ], "summary": "Approvals Live Fragment", "description": "Return an HTML fragment the live-session page embeds.\n\nEach pending approval becomes a row with three buttons that POST the\nresolution back to ``/approvals/{id}/resolve``. The fragment is\nintentionally minimal so it can be inlined into the existing live\ndashboard without pulling a new framework.", "operationId": "approvals_live_fragment_api_v1_approvals_live_fragment_get", "parameters": [ { "name": "session_id", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/plans": { "get": { "tags": [ "plans" ], "summary": "List Plans", "description": "List all plans, optionally filtered by status.\n\nQuery params:\n status: Filter by plan status (pending, approved, rejected, expired).", "operationId": "list_plans_api_v1_plans_get", "parameters": [ { "name": "status", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Status" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "array", "items": { "type": "object", "additionalProperties": true }, "title": "Response List Plans Api V1 Plans Get" } } } }, "400": { "description": "Invalid status filter" }, "404": { "description": "Plan mode is not enabled on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/plans/{plan_id}": { "get": { "tags": [ "plans" ], "summary": "Get Plan", "description": "Get a single plan by ID.", "operationId": "get_plan_api_v1_plans__plan_id__get", "parameters": [ { "name": "plan_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Plan Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Get Plan Api V1 Plans Plan Id Get" } } } }, "404": { "description": "Plan not found, or plan mode is not enabled on this server" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/plans/{plan_id}/approve": { "post": { "tags": [ "plans" ], "summary": "Approve Plan", "description": "Approve a plan: promotes all its PLANNED tasks to OPEN.\n\nThis is the key operation: once approved, the orchestrator will\npick up the tasks and start spawning agents.", "operationId": "approve_plan_api_v1_plans__plan_id__approve_post", "parameters": [ { "name": "plan_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Plan Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/PlanDecisionRequest" }, { "type": "null" } ], "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Approve Plan Api V1 Plans Plan Id Approve Post" } } } }, "404": { "description": "Plan not found, or plan mode is not enabled on this server" }, "409": { "description": "Plan already decided" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/plans/{plan_id}/reject": { "post": { "tags": [ "plans" ], "summary": "Reject Plan", "description": "Reject a plan: cancels all its PLANNED tasks.\n\nRejected tasks are moved to CANCELLED status so they never execute.", "operationId": "reject_plan_api_v1_plans__plan_id__reject_post", "parameters": [ { "name": "plan_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Plan Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/PlanDecisionRequest" }, { "type": "null" } ], "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Reject Plan Api V1 Plans Plan Id Reject Post" } } } }, "404": { "description": "Plan not found, or plan mode is not enabled on this server" }, "409": { "description": "Plan already decided" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/gateway/metrics": { "get": { "summary": "Gateway Metrics", "description": "Return per-tool MCP call metrics from the active gateway session.\n\nReturns an empty ``metrics`` dict when no gateway is running.\nClients can use ``active`` to distinguish the two cases.", "operationId": "gateway_metrics_api_v1_gateway_metrics_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/slo": { "get": { "summary": "Get Slo Status", "description": "Return current SLO dashboard data.", "operationId": "get_slo_status_api_v1_slo_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/slo/budget": { "get": { "summary": "Get Error Budget", "description": "Return error budget details in focused format.", "operationId": "get_error_budget_api_v1_slo_budget_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/slo/burndown": { "get": { "summary": "Get Slo Burndown", "description": "Return SLO burn-down rate visualization data .\n\nProvides:\n- Current SLO compliance and error budget fraction\n- Burn rate relative to the allowed failure rate (1.0 = on-target)\n- Linear projection of days until the SLO is breached\n- Sparkline data points for rendering a burn-down chart\n- Human-readable breach projection summary\n\nExample response::\n\n {\n \"slo_name\": \"task_success\",\n \"slo_target\": 0.9,\n \"slo_current\": 0.942,\n \"burn_rate\": 0.3,\n \"burn_rate_per_day\": 0.05,\n \"budget_fraction\": 0.72,\n \"budget_consumed_pct\": 28.0,\n \"days_to_breach\": 6.1,\n \"breach_projection\": \"SLO will breach in 6.1 days at current rate\",\n \"status\": \"green\",\n \"sparkline\": [...]\n }", "operationId": "get_slo_burndown_api_v1_slo_burndown_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/slo/reset": { "post": { "summary": "Reset Slo State", "description": "Reset SLO tracker to initial state (no persisted data cleared).", "operationId": "reset_slo_state_api_v1_slo_reset_post", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/sla": { "get": { "summary": "List Contracts", "description": "Return every registered SLA contract.", "operationId": "list_contracts_api_v1_sla_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/sla/receipts": { "get": { "summary": "List Receipts", "description": "Return the operator projection of every persisted violation receipt.", "operationId": "list_receipts_api_v1_sla_receipts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/sla/receipts/{receipt_id}/verify": { "get": { "summary": "Verify Receipt Endpoint", "description": "Verify a persisted violation receipt offline and return the verdict.", "operationId": "verify_receipt_endpoint_api_v1_sla_receipts__receipt_id__verify_get", "parameters": [ { "name": "receipt_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Receipt Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/sla/{contract_id}": { "get": { "summary": "Show Contract", "description": "Return one SLA contract's full record.", "operationId": "show_contract_api_v1_sla__contract_id__get", "parameters": [ { "name": "contract_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Contract Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/sla/{contract_id}/report": { "get": { "summary": "Contract Report", "description": "Return the deterministic error-budget report for a contract.", "operationId": "contract_report_api_v1_sla__contract_id__report_get", "parameters": [ { "name": "contract_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Contract Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/metrics/custom": { "get": { "summary": "Get Custom Metrics", "description": "Evaluate all configured custom metrics and return current values.\n\nReturns an object with a ``metrics`` list. Each entry contains:\n- ``name``: metric name\n- ``value``: computed float value\n- ``unit``: display unit (e.g. ``\"lines/$\"``)\n- ``description``: optional human-readable description\n- ``error``: present only when evaluation failed\n\nReturns 200 with an empty list if no custom metrics are configured.", "operationId": "get_custom_metrics_api_v1_metrics_custom_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/metrics/custom/schema": { "get": { "summary": "Get Custom Metrics Schema", "description": "Return the configured custom metric definitions (formulas and units).\n\nReturns the schema without evaluating - useful for documentation and\nformula validation checks.", "operationId": "get_custom_metrics_schema_api_v1_metrics_custom_schema_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/sbom/generate": { "post": { "tags": [ "sbom" ], "summary": "Generate SBOM and optionally run vulnerability scan", "description": "Generate a CycloneDX or SPDX SBOM from installed packages.\n\nAfter generation, optionally run ``osv-scanner`` or ``grype`` for\nvulnerability scanning. When ``block_on_critical=true`` and critical\nfindings are detected, responds with HTTP 422 so CI/CD pipelines can\ngate merges on vulnerability status.\n\nSBOM artifacts are written to ``.sdd/artifacts/sbom/``.", "operationId": "generate_sbom_api_v1_sbom_generate_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SBOMGenerateRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SBOMGenerateResponse" } } } }, "400": { "description": "Unknown SBOM format" }, "422": { "description": "Critical vulnerabilities found (gate blocked)" }, "503": { "description": "Server workdir not configured" } } } }, "/api/v1/sbom/artifacts": { "get": { "tags": [ "sbom" ], "summary": "List generated SBOM artifact files", "description": "List previously generated SBOM artifact files from ``.sdd/artifacts/sbom/``.", "operationId": "list_sbom_artifacts_api_v1_sbom_artifacts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SBOMListResponse" } } } }, "503": { "description": "Server workdir not configured" } } } }, "/api/v1/hooks/{session_id}": { "post": { "summary": "Receive Hook", "description": "Receive a hook event from Claude Code.\n\nClaude Code sends structured JSON with at minimum a ``hook_event_name``\nfield. The event is parsed, persisted to a JSONL sidecar, and triggers\nside effects (heartbeat touch, completion markers, etc.).\n\nThe request body is verified against\n``X-Bernstein-Hook-Signature-256`` (HMAC-SHA256 over the raw body,\nkeyed with ``BERNSTEIN_HOOK_SECRET``) *before* any parsing or\nfilesystem work - this is the authentication boundary for the\nendpoint. The ``session_id`` is then validated against\na strict allowlist to prevent path traversal.\n\nArgs:\n session_id: Agent session identifier from the URL path.\n request: The incoming FastAPI request.\n\nReturns:\n JSON response with status and action taken, 401 if signature\n verification fails, or 400 if ``session_id`` is unsafe / body\n is not valid JSON.", "operationId": "receive_hook_api_v1_hooks__session_id__post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/export/tasks": { "get": { "summary": "Export Tasks", "description": "Export tasks as CSV or JSON.\n\nQuery params:\n format: ``csv`` or ``json`` (default ``json``).\n limit: Optional max number of tasks to return. Pushed into\n ``TaskStore.list_tasks`` so large stores no longer materialise\n the whole table (issue #1728 finding 3).\n offset: Optional number of tasks to skip before returning rows.", "operationId": "export_tasks_api_v1_export_tasks_get", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "json", "title": "Format" } }, { "name": "limit", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Limit" } }, { "name": "offset", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Offset" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/export/agents": { "get": { "summary": "Export Agents", "description": "Export agent snapshots as CSV or JSON.\n\nQuery params:\n format: ``csv`` or ``json`` (default ``json``).", "operationId": "export_agents_api_v1_export_agents_get", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "json", "title": "Format" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/grafana/dashboard": { "get": { "summary": "Grafana Dashboard Endpoint", "description": "Generate and return the Grafana dashboard JSON.\n\nQuery params:\n datasource: Prometheus datasource name (default ``Prometheus``).", "operationId": "grafana_dashboard_endpoint_api_v1_grafana_dashboard_get", "parameters": [ { "name": "datasource", "in": "query", "required": false, "schema": { "type": "string", "default": "Prometheus", "title": "Datasource" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/tasks/{task_id}": { "get": { "summary": "Task Detail", "description": "Return detailed task view including log tail and progress.\n\nArgs:\n task_id: Task identifier.", "operationId": "task_detail_api_v1_dashboard_tasks__task_id__get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskDetailResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/tasks/{task_id}/logs/stream": { "get": { "summary": "Task Log Stream", "description": "Stream agent logs for a task via Server-Sent Events.\n\nThe stream sends new log content as ``log`` events and closes\nafter the task completes or ``_MAX_IDLE_TICKS`` seconds of no new data.", "operationId": "task_log_stream_api_v1_dashboard_tasks__task_id__logs_stream_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Server-Sent Events stream. The response body does not terminate.", "content": { "text/event-stream": { "schema": { "type": "string" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/tasks/{task_id}/diff": { "get": { "summary": "Task Diff", "description": "Return the diff for a task's working branch against the base ref.\n\nStrategy:\n 1. Resolve the working branch from the task's ``assigned_agent`` --\n ``agent/``. If no agent is assigned (or the branch\n does not exist yet), fall back to ``git diff HEAD`` so the user\n still sees uncommitted scratch work.\n 2. Run ``git diff ...`` (three-dot, symmetric\n difference relative to the merge base) and parse the output into\n a structured per-file representation.\n 3. Cap the unified diff at ``_DIFF_MAX_BYTES`` to keep payloads sane.\n\nThe sync ``_run_git`` helper is reused (it is also called from other\nsync helpers in this module). To keep the event loop responsive under\nload (issue #1723) every blocking ``_run_git`` invocation is offloaded\nto the default executor via ``asyncio.to_thread``. The helper itself\nstays sync so non-route callers keep working.", "operationId": "task_diff_api_v1_dashboard_tasks__task_id__diff_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TaskDiffResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/tasks/{task_id}/trace": { "get": { "summary": "Task Trace", "description": "Return the timeline of trace events for *task_id*.\n\nThe endpoint is read-only and idempotent. A missing task returns 404; a\nvalid task with no trace returns 200 + an empty events list (the FE\nrenders an empty-state card in that case).", "operationId": "task_trace_api_v1_dashboard_tasks__task_id__trace_get", "parameters": [ { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } }, { "name": "limit", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 2000, "minimum": 1, "default": 500, "title": "Limit" } }, { "name": "cursor", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 0, "default": 0, "title": "Cursor" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/TraceTimelineResponse" } } } }, "404": { "description": "Task not found" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/health/deps": { "get": { "summary": "Health Deps", "description": "Return health status with dependency checks.\n\nChecks: server, store, adapters, sse_bus.\nOverall status is ``healthy`` if all dependencies are ok,\n``degraded`` if any are degraded, ``unhealthy`` if any are down.", "operationId": "health_deps_api_v1_health_deps_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HealthDepsResponse" } } } } } } }, "/api/v1/tasks/batch-ops": { "post": { "tags": [ "batch-operations" ], "summary": "Batch Operations", "description": "Execute a batch operation on multiple tasks.\n\nSupported actions:\n- **cancel**: Cancel all specified tasks.\n- **retry**: Reset failed tasks back to open.\n- **reprioritize**: Update priority on all specified tasks (requires ``priority``).\n- **tag**: Add tags to all specified tasks (requires ``tags``).\n\nReturns a result with lists of succeeded and failed task IDs.", "operationId": "batch_operations_api_v1_tasks_batch_ops_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/BatchResult" } } } }, "422": { "description": "Invalid batch request" } } } }, "/api/v1/audit": { "get": { "tags": [ "audit" ], "summary": "Query Audit Log", "description": "Query the audit log with filtering and pagination.\n\nReturns:\n Dict with items, total, page, page_size. Items are normalised\n through :func:`_normalise_audit_row` so the web GUI table can\n render every row without optional-chain dance.", "operationId": "query_audit_log_api_v1_audit_get", "parameters": [ { "name": "event_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Event Type" } }, { "name": "search", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Search" } }, { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "default": 1, "title": "Page" } }, { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "default": 50, "title": "Page Size" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true, "title": "Response Query Audit Log Api V1 Audit Get" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/audit/verify": { "get": { "tags": [ "audit" ], "summary": "Audit Verify", "description": "Lightweight HMAC chain integrity probe for the web GUI banner.\n\nWalks ``.sdd/audit/*.jsonl`` events and returns a fully-populated\npayload (no nulls in core scalar fields) so the GUI's\n``ChainStatusBanner`` has something to render even when the audit\ndirectory hasn't been initialised yet. Full Sigstore / Merkle\nreconciliation lives in the lineage-v1 verifier CLI.", "operationId": "audit_verify_api_v1_audit_verify_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Audit Verify Api V1 Audit Verify Get" } } } } } }, "post": { "tags": [ "audit" ], "summary": "Audit Reverify", "description": "Re-walk the audit chain.\n\nBehaviourally identical to ``GET /audit/verify`` for the lightweight\nprobe - the operator-visible \"Re-verify\" button in the GUI just wants\na fresh walk and an up-to-date payload. Accepts ``{from_chunk}`` so\nfuture implementations can scope the walk; today the field is read\nand echoed but not used to slice the chain.", "operationId": "audit_reverify_api_v1_audit_verify_post", "requestBody": { "content": { "application/json": { "schema": { "anyOf": [ { "$ref": "#/components/schemas/VerifyChainRequest" }, { "type": "null" } ], "title": "Body" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Audit Reverify Api V1 Audit Verify Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/audit/export": { "post": { "tags": [ "audit" ], "summary": "Audit Export", "description": "Stream the filtered audit log as CSV or JSONL.\n\nSame filter semantics as ``GET /audit`` (``event_type``, ``search``,\n``from``, ``to``); returns the entire matching set in one body, no\npagination - operators expect to download the whole filtered slice.\nUsed by the web GUI Export menu (CSV / JSONL buttons).", "operationId": "audit_export_api_v1_audit_export_post", "parameters": [ { "name": "format", "in": "query", "required": false, "schema": { "type": "string", "default": "csv", "title": "Format" } }, { "name": "event_type", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Event Type" } }, { "name": "search", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Search" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/graphql": { "post": { "tags": [ "graphql" ], "summary": "Graphql Endpoint", "description": "Execute a GraphQL query.\n\nAccepts a standard GraphQL request body and resolves the query\nagainst the in-memory task store.\n\nArgs:\n req: GraphQL request body with query, optional variables and operationName.\n request: FastAPI request (provides access to app state).\n\nReturns:\n GraphQL response with ``data`` or ``errors``.", "operationId": "graphql_endpoint_api_v1_graphql_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/GraphQLRequest" } } }, "required": true }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "additionalProperties": true, "type": "object", "title": "Response Graphql Endpoint Api V1 Graphql Post" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/graduation/status": { "get": { "tags": [ "graduation" ], "summary": "Graduation Status", "description": "Return graduation stage and metrics for all tracked sessions.\n\nReturns:\n JSON with ``sessions`` list and ``total`` count.", "operationId": "graduation_status_api_v1_graduation_status_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/graduation/config/policies": { "get": { "tags": [ "graduation" ], "summary": "Get Policies", "description": "Return the current graduation stage policies.\n\nReturns:\n JSON mapping stage names to policy thresholds.", "operationId": "get_policies_api_v1_graduation_config_policies_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/graduation/{session_id}": { "get": { "tags": [ "graduation" ], "summary": "Session Graduation", "description": "Return graduation state for a specific session.\n\nArgs:\n session_id: The session identifier to look up.\n\nReturns:\n JSON with stage, metrics, promotion log, and graduation readiness.\n\nRaises:\n HTTPException: 404 when no record exists for *session_id*.", "operationId": "session_graduation_api_v1_graduation__session_id__get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "No graduation record for session" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/graduation/{session_id}/promote": { "post": { "tags": [ "graduation" ], "summary": "Promote Session", "description": "Manually promote a session to the next graduation stage.\n\nArgs:\n session_id: Session to promote.\n body: Promotion reason and who initiated it.\n\nReturns:\n JSON with ``from_stage``, ``to_stage``, and ``promoted: true``.\n\nRaises:\n HTTPException: 404 when no record exists.\n HTTPException: 409 when already at the terminal (autonomous) stage.", "operationId": "promote_session_api_v1_graduation__session_id__promote_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PromoteRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "404": { "description": "No graduation record for session" }, "409": { "description": "Already at terminal stage" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/graduation/{session_id}/record-event": { "post": { "tags": [ "graduation" ], "summary": "Record Task Event", "description": "Record a task completion or failure for graduation metric tracking.\n\nThe orchestrator or CLI calls this after each task completes/fails so\nthe graduation framework can accumulate per-stage metrics and determine\nwhen the session qualifies for the next stage.\n\nArgs:\n session_id: The session that executed the task.\n body: Task event details.\n\nReturns:\n JSON with updated stage, metrics, and graduation readiness.\n\nRaises:\n HTTPException: 422 when *initial_stage* is not a valid stage name.", "operationId": "record_task_event_api_v1_graduation__session_id__record_event_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/RecordEventRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Invalid graduation stage" } } } }, "/api/v1/handoff/{token}": { "get": { "summary": "Claim Handoff Token", "description": "Claim a handoff token and return the session identity + tail.\n\nArgs:\n token: Opaque urlsafe token presented by the dashboard.\n request: FastAPI request (used to resolve the workdir).\n\nReturns:\n JSON envelope with ``session_id``, ``task_id``,\n ``source_surface``, ``claimed_at``, ``note`` and ``tail`` (a\n list of recent stream entries).\n\nRaises:\n HTTPException: ``404`` for unknown tokens, ``410`` for expired\n or already-claimed tokens.", "operationId": "claim_handoff_token_api_v1_handoff__token__get", "parameters": [ { "name": "token", "in": "path", "required": true, "schema": { "type": "string", "title": "Token" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/team": { "get": { "summary": "Team Summary", "description": "Return a summary of the current team state.\n\nIncludes total members, active/finished counts, role distribution,\nand full per-member metadata.", "operationId": "team_summary_api_v1_team_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/team/active": { "get": { "summary": "Team Active", "description": "Return only active team members.", "operationId": "team_active_api_v1_team_active_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/team/{agent_id}": { "get": { "summary": "Team Member", "description": "Return metadata for a single team member.\n\nReturns 404 if the agent is not in the team roster.", "operationId": "team_member_api_v1_team__agent_id__get", "parameters": [ { "name": "agent_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Agent Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/metrics/provider-latency": { "get": { "summary": "Provider Latency Current", "description": "Return current p50/p95/p99 latency percentiles for all tracked providers.\n\nEach entry in the response includes a ``baseline_p99_ms`` derived from the\npast 7 days of data. When ``p99_ms`` exceeds ``baseline_p99_ms x 2``, the\nentry carries ``\"degraded\": true``.", "operationId": "provider_latency_current_api_v1_metrics_provider_latency_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/metrics/provider-latency/history": { "get": { "summary": "Provider Latency History", "description": "Return raw latency samples for time-series charting.\n\nEach sample has: ``timestamp``, ``provider``, ``model``, ``latency_ms``.\nSamples are ordered chronologically. Use ``hours`` to control the lookback\nwindow (default 24h, max 7 days).", "operationId": "provider_latency_history_api_v1_metrics_provider_latency_history_get", "parameters": [ { "name": "provider", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by provider name", "title": "Provider" }, "description": "Filter by provider name" }, { "name": "model", "in": "query", "required": false, "schema": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "description": "Filter by model identifier", "title": "Model" }, "description": "Filter by model identifier" }, { "name": "hours", "in": "query", "required": false, "schema": { "type": "integer", "maximum": 168, "minimum": 1, "description": "Hours of history to return (1-168)", "default": 24, "title": "Hours" }, "description": "Hours of history to return (1-168)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/metrics/predictions": { "get": { "summary": "Get Predictions", "description": "Evaluate all predictive forecasts and return active alerts.\n\nChecks three forecast dimensions:\n\n- **Budget exhaustion**: At current spend velocity, when will the\n budget cap be reached?\n- **Completion rate decline**: Is the task completion rate trending\n downward, indicating the run will take longer than expected?\n- **Run duration overrun**: Based on current throughput, will the run\n exceed the configured time window?\n\nUse ``budget_cap`` to enable the budget forecast. The run duration\nforecast requires at least one completed task.\n\nReturns a list of ``alerts`` ordered by severity (critical first).\nEach alert has: ``kind``, ``severity``, ``message``,\n``minutes_until_impact``, ``confidence``.", "operationId": "get_predictions_api_v1_metrics_predictions_get", "parameters": [ { "name": "budget_cap", "in": "query", "required": false, "schema": { "type": "number", "minimum": 0.0, "description": "Budget ceiling in USD (0 = skip budget forecast)", "default": 0.0, "title": "Budget Cap" }, "description": "Budget ceiling in USD (0 = skip budget forecast)" }, { "name": "window_hours", "in": "query", "required": false, "schema": { "type": "number", "maximum": 72.0, "minimum": 0.1, "description": "Configured run window in hours (default 4)", "default": 4.0, "title": "Window Hours" }, "description": "Configured run window in hours (default 4)" } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/sessions/{session_id}/peek": { "get": { "summary": "Peek Session", "description": "Return the recent stream-tail entries for ``session_id``.\n\nArgs:\n session_id: Bernstein session whose tail to read.\n request: FastAPI request - used to resolve the workdir and the\n ``tail`` query argument.\n\nReturns:\n JSON envelope with ``session_id`` plus a ``tail`` list of\n ``{ts, surface, text}`` entries in chronological order. An\n empty list signals \"buffer not initialised yet\" rather than an\n error so the polling page renders a blank pane while it waits.", "operationId": "peek_session_api_v1_sessions__session_id__peek_get", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/sessions/{session_id}/send": { "post": { "summary": "Send To Session", "description": "Pipe one line of operator input into ``session_id``'s stdin.\n\nThe send-bar tile on the dashboard POSTs ``{\"text\": \"...\"}`` here; we\nforward through :func:`bernstein.core.agents.agent_ipc.send_message`,\nwhich writes the line into the agent's registered stdin pipe.\n\nArgs:\n session_id: Slug-shaped session id; must pass the same validator\n as the peek endpoint.\n request: FastAPI request (unused beyond routing-level checks but\n present so the bearer-auth middleware sees the same shape as\n our other mutating routes).\n payload: JSON body with a single ``text`` field. Empty / missing\n text is rejected with ``400``; oversize payloads above\n :data:`MAX_SEND_BYTES` are rejected with ``413``.\n\nReturns:\n JSON envelope with ``session_id`` and ``delivered`` (``True`` if\n the line reached a registered stdin pipe, ``False`` if no pipe\n is registered for this session). The 200/404 split lets the\n front-end keep the input enabled but warn the operator when the\n agent has no live pipe yet.", "operationId": "send_to_session_api_v1_sessions__session_id__send_post", "parameters": [ { "name": "session_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Session Id" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "string" }, "title": "Payload" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/orchestrator/holds": { "get": { "tags": [ "orchestrator-holds" ], "summary": "Get Holds", "description": "List all currently active (non-expired) holds.", "operationId": "get_holds_api_v1_orchestrator_holds_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldListResponse" } } } } } }, "post": { "tags": [ "orchestrator-holds" ], "summary": "Create Hold", "description": "Acquire a new hold, preventing orchestrator self-stop while active.", "operationId": "create_hold_api_v1_orchestrator_holds_post", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldCreateRequest" } } }, "required": true }, "responses": { "200": { "description": "Hold acquired", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldResponse" } } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/orchestrator/holds/{hold_id}": { "delete": { "tags": [ "orchestrator-holds" ], "summary": "Delete Hold", "description": "Release a hold by id.", "operationId": "delete_hold_api_v1_orchestrator_holds__hold_id__delete", "parameters": [ { "name": "hold_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Hold Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "type": "object", "additionalProperties": { "type": "boolean" }, "title": "Response Delete Hold Api V1 Orchestrator Holds Hold Id Delete" } } } }, "404": { "description": "Hold not found (already released or expired)" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/orchestrator/holds/{hold_id}/renew": { "post": { "tags": [ "orchestrator-holds" ], "summary": "Renew Hold Endpoint", "description": "Heartbeat-renew a hold, extending its expiry by another grace window.", "operationId": "renew_hold_endpoint_api_v1_orchestrator_holds__hold_id__renew_post", "parameters": [ { "name": "hold_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Hold Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HoldResponse" } } } }, "404": { "description": "Hold not found (never existed, released, or already expired)" }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/review-board/runs": { "get": { "summary": "Review Board Runs", "description": "List run ids that have a journal to project, newest first.", "operationId": "review_board_runs_api_v1_review_board_runs_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/review-board/runs/{run_id}": { "get": { "summary": "Review Board Projection", "description": "Serve the board projection receipt for ``run_id``.\n\nThe response is a deterministic function of the run's journal file:\nthe same journal bytes serve the same ``board`` and\n``projection_hash`` from any server, so a reviewer can cross-check two\noperators (or the API against a local ``project_run`` fold) byte for\nbyte. ``journal_verified=false`` marks a chain that no longer\nrecomputes - the board is still rendered but must not be trusted.", "operationId": "review_board_projection_api_v1_review_board_runs__run_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/review-board/runs/{run_id}/evidence/{task_id}": { "get": { "summary": "Review Board Evidence", "description": "Serve the sealed evidence bundle for a board card.\n\nThe bundle is the #2362 proof-of-done artifact: content-addressed\nitems, the gate verdict, the producing signature, and the audit-chain\nentry hash. ``bundle_hash`` is recomputed from the canonical binding\nbytes on every read so the drawer always shows the bundle's current\nidentity.", "operationId": "review_board_evidence_api_v1_review_board_runs__run_id__evidence__task_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/review-board/runs/{run_id}/diff/{task_id}": { "get": { "summary": "Review Board Diff", "description": "Serve the captured task diff for the card drawer's diff viewer.\n\nThe diff bytes were captured beside the run journal at completion time\n(``task_diff_captured``), so they are exactly what executed and are\navailable against a detached run - no live ``git`` at review time. The\nserved bytes are re-hashed and cross-checked against the journal-chained\ncapture hash: ``verified`` is ``true`` only when the diff a reviewer folds\nopen equals the diff that was captured and the chain still recomputes.", "operationId": "review_board_diff_api_v1_review_board_runs__run_id__diff__task_id__get", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/review-board/runs/{run_id}/tasks/{task_id}/review": { "post": { "summary": "Review Board Action", "description": "Record an operator board decision as a chained, signed receipt.\n\nThe scope gate is enforced upstream by the dashboard-auth middleware\n(operator scope required for this write); the acting principal arrives on\n``request.state.dashboard_principal``. The decision row is appended via\n``EventJournal.resume`` so it chains onto the verified journal tail and\nfails closed on a poisoned chain (``409``).", "operationId": "review_board_action_api_v1_dashboard_review_board_runs__run_id__tasks__task_id__review_post", "parameters": [ { "name": "run_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Run Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ReviewActionRequest" } } } }, "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/dashboard/review-board": { "get": { "summary": "Review Board Page", "description": "Serve the review-board page.\n\nThe page is a pure consumer of the projection endpoints above plus the\nexisting ``/events`` SSE stream; it holds no state of its own, so\nreloading it (or opening it on a second machine against the same\njournal) renders the identical board.", "operationId": "review_board_page_api_v1_dashboard_review_board_get", "responses": { "200": { "description": "Successful Response", "content": { "text/html": { "schema": { "type": "string" } } } } } } }, "/api/v1/artifacts": { "get": { "summary": "List Artifacts", "description": "Return every artifact key the local lineage spines carry.", "operationId": "list_artifacts_api_v1_artifacts_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/artifacts/health": { "get": { "summary": "Artifact Health", "description": "Return the canonical health verdict for ``?uri=``.\n\nQuery parameters:\n\n* ``uri`` (required) - the artifact key.\n* ``at`` - evaluation instant; defaults to the wall clock. Pin it to\n reproduce a verdict byte-for-byte against the CLI.\n* ``cadence_seconds`` - declared refresh cadence; omitted means the cadence\n leg reports ``not_applicable``.\n\nThe body is the exact string the CLI prints for the same state and instant,\nbyte for byte. The status is always 200: the verdict is the payload, and a\nred artifact is a successfully computed answer, not a failed request.", "operationId": "artifact_health_api_v1_artifacts_health_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/artifacts/log": { "get": { "summary": "Artifact Log Route", "description": "Return productions of ``?uri=``, newest first (the attribution log).\n\nRecorded attempts -- tasks that declared this artifact and did not deliver it\n-- travel in the same document under ``attempts`` (issue #2559), so a\nconsumer cannot see the productions without also seeing what tried and\nfailed. Byte-identical to what the CLI prints for the same state.", "operationId": "artifact_log_route_api_v1_artifacts_log_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/missions": { "get": { "summary": "Missions List", "description": "List mission ids that have a ledger to project, newest first.", "operationId": "missions_list_api_v1_missions_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/missions/{mission_id}": { "get": { "summary": "Mission Projection", "description": "Serve the mission projection receipt for ``mission_id``.\n\nThe response is a deterministic function of the mission's ledger file: the\nsame ledger bytes serve the same ``status`` and ``mission_status_hash`` from\nany server, so two operators cross-check byte for byte.\n``ledger_verified=false`` (with ``overall=unverified``) marks a chain that no\nlonger recomputes -- the timeline still renders, but the screen must show the\nunverified banner instead of trusting the state.", "operationId": "mission_projection_api_v1_missions__mission_id__get", "parameters": [ { "name": "mission_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Mission Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/missions/{mission_id}/digest": { "get": { "summary": "Mission Digest", "description": "Serve the canonical daily progress digest for a fire instant.\n\nRead-only: the digest is recomputed from the ledger as a pure fold, so the\nendpoint never writes to the chain. The payload carries the ``digest_hash``,\nthe ``receipt_id`` (the per-fire delivery idempotency key), and the verbatim\n``message`` the digest projects to -- the exact bytes a chat delivery posts,\nso a caller can cross-check a posted message against this projection.", "operationId": "mission_digest_api_v1_missions__mission_id__digest_get", "parameters": [ { "name": "mission_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Mission Id" } }, { "name": "fire_time", "in": "query", "required": true, "schema": { "type": "integer", "description": "Integer Unix epoch of the canonical fire instant.", "title": "Fire Time" }, "description": "Integer Unix epoch of the canonical fire instant." } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/api/v1/missions/{mission_id}/evidence/{task_id}": { "get": { "summary": "Mission Evidence", "description": "Serve the sealed evidence bundle behind a timeline element's provenance link.\n\n``bundle_hash`` is recomputed from the canonical binding bytes on every read,\nso the drawer always shows the bundle's current identity -- and a bundle that\nno longer matches the hash a phase receipt bound projects that phase as\nunverified in the mission projection above.", "operationId": "mission_evidence_api_v1_missions__mission_id__evidence__task_id__get", "parameters": [ { "name": "mission_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Mission Id" } }, { "name": "task_id", "in": "path", "required": true, "schema": { "type": "string", "title": "Task Id" } } ], "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } }, "422": { "description": "Validation Error", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/HTTPValidationError" } } } } } } }, "/gui-meta": { "get": { "tags": [ "gui" ], "summary": "Gui Meta", "operationId": "gui_meta_gui_meta_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } }, "/api/v1/gui-meta": { "get": { "tags": [ "gui" ], "summary": "Gui Meta", "operationId": "gui_meta_api_v1_gui_meta_get", "responses": { "200": { "description": "Successful Response", "content": { "application/json": { "schema": {} } } } } } } }, "components": { "schemas": { "A2AAgentCardResponse": { "properties": { "name": { "type": "string", "title": "Name" }, "description": { "type": "string", "title": "Description" }, "capabilities": { "items": { "type": "string" }, "type": "array", "title": "Capabilities" }, "protocol_version": { "type": "string", "title": "Protocol Version" }, "endpoint": { "type": "string", "title": "Endpoint" }, "provider": { "type": "string", "title": "Provider" } }, "type": "object", "required": [ "name", "description", "capabilities", "protocol_version", "endpoint", "provider" ], "title": "A2AAgentCardResponse", "description": "Agent Card response for the ``/a2a/agent-card`` discovery endpoint.\n\nThe A2A v1.0 card served at ``/.well-known/agent.json`` is built and\nsigned in :mod:`bernstein.core.routes.well_known` and does not use this\nmodel." }, "A2AArtifactRequest": { "properties": { "name": { "type": "string", "title": "Name" }, "data": { "type": "string", "title": "Data", "default": "" }, "content_type": { "type": "string", "title": "Content Type", "default": "text/plain" } }, "type": "object", "required": [ "name" ], "title": "A2AArtifactRequest", "description": "Body for POST /a2a/tasks/{id}/artifacts - attach an artifact." }, "A2AArtifactResponse": { "properties": { "name": { "type": "string", "title": "Name" }, "content_type": { "type": "string", "title": "Content Type" }, "data": { "type": "string", "title": "Data" }, "created_at": { "type": "number", "title": "Created At" } }, "type": "object", "required": [ "name", "content_type", "data", "created_at" ], "title": "A2AArtifactResponse", "description": "Single artifact in responses." }, "A2AMessageRequest": { "properties": { "sender": { "type": "string", "title": "Sender" }, "recipient": { "type": "string", "title": "Recipient" }, "content": { "type": "string", "title": "Content" }, "task_id": { "type": "string", "title": "Task Id" } }, "type": "object", "required": [ "sender", "recipient", "content", "task_id" ], "title": "A2AMessageRequest", "description": "Body for POST /a2a/message." }, "A2AMessageResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "sender": { "type": "string", "title": "Sender" }, "recipient": { "type": "string", "title": "Recipient" }, "content": { "type": "string", "title": "Content" }, "task_id": { "type": "string", "title": "Task Id" }, "direction": { "type": "string", "title": "Direction" }, "delivered": { "type": "boolean", "title": "Delivered" }, "external_endpoint": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "External Endpoint" }, "created_at": { "type": "number", "title": "Created At" } }, "type": "object", "required": [ "id", "sender", "recipient", "content", "task_id", "direction", "delivered", "external_endpoint", "created_at" ], "title": "A2AMessageResponse", "description": "Serialized A2A message returned by Bernstein endpoints." }, "A2ATaskResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "bernstein_task_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Bernstein Task Id" }, "sender": { "type": "string", "title": "Sender" }, "message": { "type": "string", "title": "Message" }, "status": { "type": "string", "title": "Status" }, "artifacts": { "items": { "$ref": "#/components/schemas/A2AArtifactResponse" }, "type": "array", "title": "Artifacts" }, "created_at": { "type": "number", "title": "Created At" }, "updated_at": { "type": "number", "title": "Updated At" }, "receipt": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Receipt" } }, "type": "object", "required": [ "id", "bernstein_task_id", "sender", "message", "status", "artifacts", "created_at", "updated_at" ], "title": "A2ATaskResponse", "description": "Serialised A2A task in responses.\n\n``receipt`` carries the lineage receipt for an inbound task (#2609): the\nexecution evidence a caller verifies offline with ``bernstein a2a verify\n--receipt``. It is ``None`` on read paths, and on write paths when the\nnode could not provision receipt key material - an absent receipt means\n\"unattested\", which a caller should treat as unverified rather than\ntrusted." }, "A2ATaskSendRequest": { "properties": { "sender": { "type": "string", "title": "Sender" }, "message": { "type": "string", "title": "Message" }, "role": { "type": "string", "title": "Role", "default": "backend" } }, "type": "object", "required": [ "sender", "message" ], "title": "A2ATaskSendRequest", "description": "Body for POST /a2a/tasks/send - receive a task from an external A2A agent." }, "ACPAgentCapabilityResponse": { "properties": { "name": { "type": "string", "title": "Name" }, "description": { "type": "string", "title": "Description" }, "input_schema": { "additionalProperties": true, "type": "object", "title": "Input Schema" } }, "type": "object", "required": [ "name", "description" ], "title": "ACPAgentCapabilityResponse", "description": "Single ACP capability entry." }, "ACPAgentListEntry": { "properties": { "name": { "type": "string", "title": "Name" }, "description": { "type": "string", "title": "Description" }, "endpoint": { "type": "string", "title": "Endpoint" } }, "type": "object", "required": [ "name", "description", "endpoint" ], "title": "ACPAgentListEntry", "description": "Entry in the agents list." }, "ACPAgentResponse": { "properties": { "name": { "type": "string", "title": "Name" }, "description": { "type": "string", "title": "Description" }, "protocol_version": { "type": "string", "title": "Protocol Version" }, "capabilities": { "items": { "$ref": "#/components/schemas/ACPAgentCapabilityResponse" }, "type": "array", "title": "Capabilities" }, "endpoint": { "type": "string", "title": "Endpoint" }, "provider": { "type": "string", "title": "Provider" } }, "type": "object", "required": [ "name", "description", "protocol_version", "capabilities", "endpoint", "provider" ], "title": "ACPAgentResponse", "description": "ACP agent metadata." }, "ACPDiscoveryResponse": { "properties": { "protocol": { "type": "string", "title": "Protocol" }, "version": { "type": "string", "title": "Version" }, "agents": { "items": { "$ref": "#/components/schemas/ACPAgentListEntry" }, "type": "array", "title": "Agents" } }, "type": "object", "required": [ "protocol", "version", "agents" ], "title": "ACPDiscoveryResponse", "description": "Response for GET /.well-known/acp.json." }, "ACPRunCreateRequest": { "properties": { "input": { "type": "string", "title": "Input" }, "agent_id": { "type": "string", "title": "Agent Id", "default": "bernstein" }, "role": { "type": "string", "title": "Role", "default": "backend" } }, "type": "object", "required": [ "input" ], "title": "ACPRunCreateRequest", "description": "Body for POST /acp/v0/runs." }, "ACPRunResponse": { "properties": { "run_id": { "type": "string", "title": "Run Id" }, "bernstein_task_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Bernstein Task Id" }, "input": { "type": "string", "title": "Input" }, "role": { "type": "string", "title": "Role" }, "status": { "type": "string", "title": "Status" }, "created_at": { "type": "number", "title": "Created At" }, "updated_at": { "type": "number", "title": "Updated At" } }, "type": "object", "required": [ "run_id", "input", "role", "status", "created_at", "updated_at" ], "title": "ACPRunResponse", "description": "ACP run in responses." }, "AgentIdentityStatus": { "type": "string", "enum": [ "active", "suspended", "revoked" ], "title": "AgentIdentityStatus", "description": "Lifecycle status of an agent identity." }, "AgentKillResponse": { "properties": { "session_id": { "type": "string", "title": "Session Id" }, "kill_requested": { "type": "boolean", "title": "Kill Requested" } }, "type": "object", "required": [ "session_id", "kill_requested" ], "title": "AgentKillResponse", "description": "Response for POST /agents/{session_id}/kill." }, "AgentLogsResponse": { "properties": { "session_id": { "type": "string", "title": "Session Id" }, "content": { "type": "string", "title": "Content" }, "size": { "type": "integer", "title": "Size" } }, "type": "object", "required": [ "session_id", "content", "size" ], "title": "AgentLogsResponse", "description": "Response for GET /agents/{session_id}/logs." }, "AgentMetrics": { "properties": { "adapter": { "type": "string", "title": "Adapter" }, "model": { "type": "string", "title": "Model" }, "total_tasks": { "type": "integer", "title": "Total Tasks", "default": 0 }, "succeeded": { "type": "integer", "title": "Succeeded", "default": 0 }, "failed": { "type": "integer", "title": "Failed", "default": 0 }, "avg_completion_secs": { "type": "number", "title": "Avg Completion Secs", "default": 0.0 }, "total_cost_usd": { "type": "number", "title": "Total Cost Usd", "default": 0.0 }, "quality_gate_pass_rate": { "type": "number", "title": "Quality Gate Pass Rate", "default": 1.0 }, "success_rate": { "type": "number", "title": "Success Rate", "description": "Fraction of tasks that succeeded (0.0-1.0).", "readOnly": true }, "cost_per_task": { "type": "number", "title": "Cost Per Task", "description": "Average cost per task in USD.", "readOnly": true } }, "type": "object", "required": [ "adapter", "model", "success_rate", "cost_per_task" ], "title": "AgentMetrics", "description": "Aggregated performance metrics for a single (adapter, model) pair." }, "ApprovalDecisionRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "ApprovalDecisionRequest", "description": "Body for POST /approvals/{task_id}/approve or /reject." }, "ArchiveRecord": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "title": { "type": "string", "title": "Title" }, "role": { "type": "string", "title": "Role" }, "tenant_id": { "type": "string", "title": "Tenant Id" }, "status": { "type": "string", "title": "Status" }, "created_at": { "type": "number", "title": "Created At" }, "completed_at": { "type": "number", "title": "Completed At" }, "duration_seconds": { "type": "number", "title": "Duration Seconds" }, "result_summary": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Result Summary" }, "cost_usd": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Cost Usd" }, "assigned_agent": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Assigned Agent" }, "owned_files": { "items": { "type": "string" }, "type": "array", "title": "Owned Files" }, "claimed_by_session": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } }, "type": "object", "required": [ "task_id", "title", "role", "tenant_id", "status", "created_at", "completed_at", "duration_seconds", "result_summary", "cost_usd", "assigned_agent", "owned_files", "claimed_by_session" ], "title": "ArchiveRecord", "description": "Archive JSONL entry written when a task reaches a terminal state." }, "AuthProvidersResponse": { "properties": { "oidc_enabled": { "type": "boolean", "title": "Oidc Enabled", "default": false }, "saml_enabled": { "type": "boolean", "title": "Saml Enabled", "default": false }, "legacy_token_enabled": { "type": "boolean", "title": "Legacy Token Enabled", "default": false }, "device_flow_enabled": { "type": "boolean", "title": "Device Flow Enabled", "default": true } }, "type": "object", "title": "AuthProvidersResponse", "description": "Available authentication providers." }, "BatchAction": { "type": "string", "enum": [ "cancel", "retry", "reprioritize", "tag" ], "title": "BatchAction", "description": "Supported batch operation types." }, "BatchClaimRequest": { "properties": { "task_ids": { "items": { "type": "string" }, "type": "array", "title": "Task Ids" }, "agent_id": { "type": "string", "title": "Agent Id" }, "claimed_by_session": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Claimed By Session" } }, "type": "object", "required": [ "task_ids", "agent_id" ], "title": "BatchClaimRequest", "description": "Body for POST /tasks/claim-batch." }, "BatchClaimResponse": { "properties": { "claimed": { "items": { "type": "string" }, "type": "array", "title": "Claimed" }, "failed": { "items": { "type": "string" }, "type": "array", "title": "Failed" } }, "type": "object", "required": [ "claimed", "failed" ], "title": "BatchClaimResponse", "description": "Response for POST /tasks/claim-batch." }, "BatchCreateRequest": { "properties": { "tasks": { "items": { "$ref": "#/components/schemas/TaskCreate" }, "type": "array", "title": "Tasks" } }, "type": "object", "required": [ "tasks" ], "title": "BatchCreateRequest", "description": "Body for POST /tasks/batch." }, "BatchCreateResponse": { "properties": { "created": { "items": { "$ref": "#/components/schemas/TaskResponse" }, "type": "array", "title": "Created" }, "skipped_titles": { "items": { "type": "string" }, "type": "array", "title": "Skipped Titles" } }, "type": "object", "required": [ "created", "skipped_titles" ], "title": "BatchCreateResponse", "description": "Response for POST /tasks/batch." }, "BatchRequest": { "properties": { "action": { "$ref": "#/components/schemas/BatchAction" }, "ids": { "items": { "type": "string" }, "type": "array", "title": "Ids" }, "priority": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Priority" }, "tags": { "anyOf": [ { "items": { "type": "string" }, "type": "array" }, { "type": "null" } ], "title": "Tags" } }, "type": "object", "required": [ "action", "ids" ], "title": "BatchRequest", "description": "Request body for POST /tasks/batch-ops." }, "BatchResult": { "properties": { "succeeded": { "items": { "type": "string" }, "type": "array", "title": "Succeeded" }, "failed": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Failed" } }, "type": "object", "title": "BatchResult", "description": "Response body for POST /tasks/batch-ops." }, "BroadcastRequest": { "properties": { "message": { "type": "string", "title": "Message", "default": "" } }, "type": "object", "title": "BroadcastRequest", "description": "Body for ``POST /broadcast``.\n\nTyping the body with a model lets FastAPI reject non-object or\nmalformed JSON with a ``422`` instead of letting ``dict.get`` (or a\n``JSONDecodeError``) raise an unhandled exception. ``message``\ndefaults to an empty string so a missing field still funnels into\nthe existing ``400 message is required`` path." }, "BulletinMessageResponse": { "properties": { "agent_id": { "type": "string", "title": "Agent Id" }, "type": { "type": "string", "title": "Type" }, "content": { "type": "string", "title": "Content" }, "timestamp": { "type": "number", "title": "Timestamp" }, "cell_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Cell Id" } }, "type": "object", "required": [ "agent_id", "type", "content", "timestamp", "cell_id" ], "title": "BulletinMessageResponse", "description": "Single bulletin message in responses." }, "BulletinPostRequest": { "properties": { "agent_id": { "type": "string", "title": "Agent Id" }, "type": { "type": "string", "enum": [ "alert", "blocker", "finding", "status", "dependency" ], "title": "Type", "default": "status" }, "content": { "type": "string", "title": "Content" }, "cell_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Cell Id" } }, "type": "object", "required": [ "agent_id", "content" ], "title": "BulletinPostRequest", "description": "Body for POST /bulletin." }, "ChannelQueryRequest": { "properties": { "sender_agent": { "type": "string", "title": "Sender Agent" }, "topic": { "type": "string", "title": "Topic" }, "content": { "type": "string", "title": "Content" }, "target_agent": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Target Agent" }, "target_role": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Target Role" }, "ttl_seconds": { "type": "number", "title": "Ttl Seconds", "default": 300 } }, "type": "object", "required": [ "sender_agent", "topic", "content" ], "title": "ChannelQueryRequest", "description": "Body for POST /channel/query." }, "ChannelQueryResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "sender_agent": { "type": "string", "title": "Sender Agent" }, "topic": { "type": "string", "title": "Topic" }, "content": { "type": "string", "title": "Content" }, "target_agent": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Target Agent" }, "target_role": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Target Role" }, "timestamp": { "type": "number", "title": "Timestamp" }, "expires_at": { "type": "number", "title": "Expires At" }, "resolved": { "type": "boolean", "title": "Resolved" } }, "type": "object", "required": [ "id", "sender_agent", "topic", "content", "target_agent", "target_role", "timestamp", "expires_at", "resolved" ], "title": "ChannelQueryResponse", "description": "Single channel query in API responses." }, "ChannelResponseRequest": { "properties": { "responder_agent": { "type": "string", "title": "Responder Agent" }, "content": { "type": "string", "title": "Content" } }, "type": "object", "required": [ "responder_agent", "content" ], "title": "ChannelResponseRequest", "description": "Body for POST /channel/{query_id}/respond." }, "ChannelResponseResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "query_id": { "type": "string", "title": "Query Id" }, "responder_agent": { "type": "string", "title": "Responder Agent" }, "content": { "type": "string", "title": "Content" }, "timestamp": { "type": "number", "title": "Timestamp" } }, "type": "object", "required": [ "id", "query_id", "responder_agent", "content", "timestamp" ], "title": "ChannelResponseResponse", "description": "Single channel response in API responses." }, "ClaimGossipRequest": { "properties": { "receipts": { "items": { "additionalProperties": true, "type": "object" }, "type": "array", "title": "Receipts" }, "head": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Head" }, "node_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Node Id" } }, "type": "object", "required": [ "receipts" ], "title": "ClaimGossipRequest", "description": "Body for POST /cluster/claims/gossip - push signed claim receipts to a peer.\n\n``receipts`` are the raw :class:`ClaimReceipt` wire dicts in journal order.\n``head`` is the sender's journal head, echoed back so the sender can tell\nconvergence from divergence without a second round trip." }, "ClaimGossipResponse": { "properties": { "head": { "type": "string", "title": "Head" }, "accepted": { "type": "integer", "title": "Accepted" }, "results": { "items": { "$ref": "#/components/schemas/ClaimGossipResult" }, "type": "array", "title": "Results" }, "forked": { "type": "boolean", "title": "Forked", "default": false } }, "type": "object", "required": [ "head", "accepted", "results" ], "title": "ClaimGossipResponse", "description": "Response for POST /cluster/claims/gossip.\n\n``forked`` is surfaced at the top level because a fork is the one outcome\nthat must not be lost in a per-receipt list an integrator might ignore." }, "ClaimGossipResult": { "properties": { "entry_hash": { "type": "string", "title": "Entry Hash" }, "status": { "type": "string", "title": "Status" }, "reason": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Reason" }, "divergence_index": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Divergence Index" } }, "type": "object", "required": [ "entry_hash", "status" ], "title": "ClaimGossipResult", "description": "Per-receipt outcome of a gossip push." }, "ClaimReceiptRequest": { "properties": { "claimer_id": { "type": "string", "maxLength": 1000, "minLength": 1, "title": "Claimer Id" }, "claimer_card_fingerprint": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Claimer Card Fingerprint" }, "role": { "anyOf": [ { "type": "string", "maxLength": 64 }, { "type": "null" } ], "title": "Role" }, "project": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Project" }, "capability": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Capability" }, "completed_ids": { "items": { "type": "string" }, "type": "array", "title": "Completed Ids" }, "max_attempts": { "anyOf": [ { "type": "integer", "minimum": 0.0 }, { "type": "null" } ], "title": "Max Attempts" } }, "type": "object", "required": [ "claimer_id" ], "title": "ClaimReceiptRequest", "description": "Body for POST /tasks/claim-receipt (#2555).\n\nDrives the dependency-gated claim path over MCP and returns a signed,\ncontent-addressed :class:`ClaimReceipt` instead of a mutable task\nprojection. The eligibility predicates mirror\n:class:`bernstein.core.tasks.claim.ClaimFilter`: a task is offered only\nwhen its ``depends_on`` are all present in ``completed_ids`` (the\ndependency gate), and a filter that matches no eligible row still returns\na signed refusal receipt (never a silent skip)." }, "ClusterStatusResponse": { "properties": { "topology": { "type": "string", "title": "Topology" }, "total_nodes": { "type": "integer", "title": "Total Nodes" }, "online_nodes": { "type": "integer", "title": "Online Nodes" }, "offline_nodes": { "type": "integer", "title": "Offline Nodes" }, "total_capacity": { "type": "integer", "title": "Total Capacity" }, "available_slots": { "type": "integer", "title": "Available Slots" }, "active_agents": { "type": "integer", "title": "Active Agents" }, "nodes": { "items": { "$ref": "#/components/schemas/NodeResponse" }, "type": "array", "title": "Nodes" } }, "type": "object", "required": [ "topology", "total_nodes", "online_nodes", "offline_nodes", "total_capacity", "available_slots", "active_agents", "nodes" ], "title": "ClusterStatusResponse", "description": "Response for GET /cluster/status." }, "CompletionSignalSchema": { "properties": { "type": { "type": "string", "enum": [ "path_exists", "glob_exists", "test_passes", "file_contains", "llm_review", "llm_judge" ], "title": "Type" }, "value": { "type": "string", "title": "Value" } }, "type": "object", "required": [ "type", "value" ], "title": "CompletionSignalSchema", "description": "Pydantic schema for a single completion signal in API requests." }, "DependencyStatus": { "properties": { "name": { "type": "string", "title": "Name" }, "status": { "type": "string", "title": "Status" }, "latency_ms": { "type": "number", "title": "Latency Ms", "default": 0.0 }, "detail": { "type": "string", "title": "Detail", "default": "" } }, "type": "object", "required": [ "name", "status" ], "title": "DependencyStatus", "description": "Status of a single dependency." }, "DeviceAuthorizeRequest": { "properties": { "user_code": { "type": "string", "title": "User Code" } }, "type": "object", "required": [ "user_code" ], "title": "DeviceAuthorizeRequest", "description": "Body for POST /auth/cli/authorize - authorize a device code." }, "DeviceCodeRequest": { "properties": { "client_name": { "type": "string", "title": "Client Name", "default": "bernstein-cli" } }, "type": "object", "title": "DeviceCodeRequest", "description": "Body for POST /auth/cli/device - initiate device auth flow." }, "DeviceCodeResponse": { "properties": { "device_code": { "type": "string", "title": "Device Code" }, "user_code": { "type": "string", "title": "User Code" }, "verification_uri": { "type": "string", "title": "Verification Uri" }, "expires_in": { "type": "integer", "title": "Expires In" }, "interval": { "type": "integer", "title": "Interval" } }, "type": "object", "required": [ "device_code", "user_code", "verification_uri", "expires_in", "interval" ], "title": "DeviceCodeResponse", "description": "Response for device code request." }, "DevicePollRequest": { "properties": { "device_code": { "type": "string", "title": "Device Code" }, "grant_type": { "type": "string", "title": "Grant Type", "default": "urn:ietf:params:oauth:grant-type:device_code" } }, "type": "object", "required": [ "device_code" ], "title": "DevicePollRequest", "description": "Body for POST /auth/cli/token - poll for device authorization." }, "DevicePollResponse": { "properties": { "access_token": { "type": "string", "title": "Access Token", "default": "" }, "expires_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Expires At" }, "refresh_token": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Refresh Token" }, "token_type": { "type": "string", "title": "Token Type", "default": "Bearer" }, "status": { "type": "string", "title": "Status", "default": "pending" } }, "type": "object", "title": "DevicePollResponse", "description": "Response for device token poll." }, "DiffFile": { "properties": { "path": { "type": "string", "title": "Path" }, "old_path": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Old Path" }, "status": { "type": "string", "title": "Status", "default": "modified" }, "additions": { "type": "integer", "title": "Additions", "default": 0 }, "deletions": { "type": "integer", "title": "Deletions", "default": 0 }, "binary": { "type": "boolean", "title": "Binary", "default": false }, "language": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Language" }, "hunks": { "items": { "$ref": "#/components/schemas/DiffHunk" }, "type": "array", "title": "Hunks" } }, "type": "object", "required": [ "path" ], "title": "DiffFile", "description": "Per-file diff entry." }, "DiffHunk": { "properties": { "header": { "type": "string", "title": "Header" }, "old_start": { "type": "integer", "title": "Old Start" }, "old_lines": { "type": "integer", "title": "Old Lines" }, "new_start": { "type": "integer", "title": "New Start" }, "new_lines": { "type": "integer", "title": "New Lines" }, "lines": { "items": { "type": "string" }, "type": "array", "title": "Lines" } }, "type": "object", "required": [ "header", "old_start", "old_lines", "new_start", "new_lines", "lines" ], "title": "DiffHunk", "description": "A single hunk in a file diff." }, "GraphQLRequest": { "properties": { "query": { "type": "string", "title": "Query" }, "variables": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Variables" }, "operationName": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Operationname" } }, "type": "object", "required": [ "query" ], "title": "GraphQLRequest", "description": "GraphQL request body." }, "GroupMappingEntry": { "properties": { "group": { "type": "string", "title": "Group" }, "role": { "type": "string", "title": "Role" } }, "type": "object", "required": [ "group", "role" ], "title": "GroupMappingEntry", "description": "A single group → role mapping." }, "GroupMappingsResponse": { "properties": { "mappings": { "items": { "$ref": "#/components/schemas/GroupMappingEntry" }, "type": "array", "title": "Mappings" } }, "type": "object", "required": [ "mappings" ], "title": "GroupMappingsResponse", "description": "Response for GET /auth/group-mappings." }, "GroupMappingsUpdateRequest": { "properties": { "mappings": { "items": { "$ref": "#/components/schemas/GroupMappingEntry" }, "type": "array", "title": "Mappings" } }, "type": "object", "required": [ "mappings" ], "title": "GroupMappingsUpdateRequest", "description": "Body for PUT /auth/group-mappings." }, "HTTPValidationError": { "properties": { "detail": { "items": { "$ref": "#/components/schemas/ValidationError" }, "type": "array", "title": "Detail" } }, "type": "object", "title": "HTTPValidationError" }, "HealthDepsResponse": { "properties": { "status": { "type": "string", "title": "Status" }, "uptime_s": { "type": "number", "title": "Uptime S" }, "timestamp": { "type": "number", "title": "Timestamp" }, "dependencies": { "items": { "$ref": "#/components/schemas/DependencyStatus" }, "type": "array", "title": "Dependencies" } }, "type": "object", "required": [ "status", "uptime_s", "timestamp" ], "title": "HealthDepsResponse", "description": "Full health response with dependency checks." }, "HealthResponse": { "properties": { "status": { "type": "string", "title": "Status" }, "uptime_s": { "type": "number", "title": "Uptime S" }, "task_count": { "type": "integer", "title": "Task Count" }, "agent_count": { "type": "integer", "title": "Agent Count" }, "task_queue_depth": { "type": "integer", "title": "Task Queue Depth", "default": 0 }, "memory_mb": { "type": "number", "title": "Memory Mb", "default": 0.0 }, "restart_count": { "type": "integer", "title": "Restart Count", "default": 0 }, "is_readonly": { "type": "boolean", "title": "Is Readonly", "default": false }, "components": { "additionalProperties": { "additionalProperties": true, "type": "object" }, "type": "object", "title": "Components" } }, "type": "object", "required": [ "status", "uptime_s", "task_count", "agent_count" ], "title": "HealthResponse", "description": "Response for GET /health." }, "HeartbeatRequest": { "properties": { "role": { "type": "string", "title": "Role", "default": "" }, "status": { "type": "string", "enum": [ "starting", "working", "idle", "dead" ], "title": "Status", "default": "working" } }, "type": "object", "title": "HeartbeatRequest", "description": "Body for POST /agents/{agent_id}/heartbeat." }, "HeartbeatResponse": { "properties": { "agent_id": { "type": "string", "title": "Agent Id" }, "acknowledged": { "type": "boolean", "title": "Acknowledged" }, "server_ts": { "type": "number", "title": "Server Ts" } }, "type": "object", "required": [ "agent_id", "acknowledged", "server_ts" ], "title": "HeartbeatResponse", "description": "Response for heartbeat." }, "HoldCreateRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "description": "Why the caller wants the orchestrator to stay up" }, "ttl_seconds": { "anyOf": [ { "type": "number", "exclusiveMinimum": 0.0 }, { "type": "null" } ], "title": "Ttl Seconds", "description": "Grace-window auto-expiry; server default if omitted" } }, "additionalProperties": false, "type": "object", "required": [ "reason" ], "title": "HoldCreateRequest", "description": "Body for POST /orchestrator/holds." }, "HoldListResponse": { "properties": { "holds": { "items": { "$ref": "#/components/schemas/HoldResponse" }, "type": "array", "title": "Holds" }, "count": { "type": "integer", "title": "Count" } }, "type": "object", "required": [ "holds", "count" ], "title": "HoldListResponse", "description": "Response for GET /orchestrator/holds." }, "HoldResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "reason": { "type": "string", "title": "Reason" }, "created_at": { "type": "number", "title": "Created At" }, "ttl_seconds": { "type": "number", "title": "Ttl Seconds" }, "expires_at": { "type": "number", "title": "Expires At" }, "last_renewed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Last Renewed At" } }, "type": "object", "required": [ "id", "reason", "created_at", "ttl_seconds", "expires_at" ], "title": "HoldResponse", "description": "Serialised hold in API responses." }, "ImpactResponse": { "properties": { "file_query": { "type": "string", "title": "File Query" }, "matched_files": { "items": { "type": "string" }, "type": "array", "title": "Matched Files" }, "impacted_files": { "items": { "type": "string" }, "type": "array", "title": "Impacted Files" }, "built_at": { "type": "string", "title": "Built At" } }, "type": "object", "required": [ "file_query", "matched_files", "impacted_files", "built_at" ], "title": "ImpactResponse", "description": "Response body for ``GET /graph/impact``." }, "ListApprovalsResponse": { "properties": { "pending": { "items": { "$ref": "#/components/schemas/PendingApproval" }, "type": "array", "title": "Pending" } }, "type": "object", "required": [ "pending" ], "title": "ListApprovalsResponse", "description": "Response for GET /approvals." }, "LoginProvider": { "type": "string", "enum": [ "oidc", "saml" ], "title": "LoginProvider", "description": "SSO providers accepted by ``GET /auth/login``.\n\nTyping the ``provider`` query param with this enum lets FastAPI\nreject unknown values with a ``422`` at the validation layer instead\nof the handler falling through to a generic error for an input it\nwas never going to support." }, "MergeOrderResponse": { "properties": { "repos": { "items": { "type": "string" }, "type": "array", "title": "Repos" } }, "type": "object", "required": [ "repos" ], "title": "MergeOrderResponse", "description": "Topological repository merge order." }, "NodeCapacitySchema": { "properties": { "max_agents": { "type": "integer", "title": "Max Agents", "default": 6 }, "available_slots": { "type": "integer", "title": "Available Slots", "default": 6 }, "active_agents": { "type": "integer", "title": "Active Agents", "default": 0 }, "gpu_available": { "type": "boolean", "title": "Gpu Available", "default": false }, "supported_models": { "items": { "type": "string" }, "type": "array", "title": "Supported Models" } }, "type": "object", "title": "NodeCapacitySchema", "description": "Advertised capacity of a cluster node." }, "NodeHeartbeatRequest": { "properties": { "capacity": { "anyOf": [ { "$ref": "#/components/schemas/NodeCapacitySchema" }, { "type": "null" } ] } }, "type": "object", "title": "NodeHeartbeatRequest", "description": "Body for POST /cluster/nodes/{node_id}/heartbeat." }, "NodeRegisterRequest": { "properties": { "name": { "type": "string", "title": "Name", "default": "" }, "url": { "type": "string", "title": "Url", "default": "" }, "capacity": { "$ref": "#/components/schemas/NodeCapacitySchema" }, "labels": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Labels" }, "cell_ids": { "items": { "type": "string" }, "type": "array", "title": "Cell Ids" } }, "type": "object", "title": "NodeRegisterRequest", "description": "Body for POST /cluster/nodes." }, "NodeResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "name": { "type": "string", "title": "Name" }, "url": { "type": "string", "title": "Url" }, "status": { "type": "string", "title": "Status" }, "capacity": { "$ref": "#/components/schemas/NodeCapacitySchema" }, "last_heartbeat": { "type": "number", "title": "Last Heartbeat" }, "registered_at": { "type": "number", "title": "Registered At" }, "labels": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Labels" }, "cell_ids": { "items": { "type": "string" }, "type": "array", "title": "Cell Ids" } }, "type": "object", "required": [ "id", "name", "url", "status", "capacity", "last_heartbeat", "registered_at", "labels", "cell_ids" ], "title": "NodeResponse", "description": "Serialised node in API responses." }, "PaginatedSearchResponse": { "properties": { "tasks": { "items": { "$ref": "#/components/schemas/TaskResponse" }, "type": "array", "title": "Tasks" }, "total": { "type": "integer", "title": "Total" }, "page": { "type": "integer", "title": "Page" }, "per_page": { "type": "integer", "title": "Per Page" }, "total_pages": { "type": "integer", "title": "Total Pages" }, "sort": { "type": "string", "title": "Sort" }, "order": { "type": "string", "title": "Order" }, "filters": { "additionalProperties": { "type": "string" }, "type": "object", "title": "Filters" } }, "type": "object", "required": [ "tasks", "total", "page", "per_page", "total_pages", "sort", "order" ], "title": "PaginatedSearchResponse", "description": "Paginated task search response with metadata." }, "PartialMergeRequest": { "properties": { "files": { "items": { "type": "string" }, "type": "array", "title": "Files" }, "message": { "type": "string", "title": "Message", "default": "" } }, "type": "object", "required": [ "files" ], "title": "PartialMergeRequest", "description": "Body for POST /tasks/{task_id}/partial-merge.\n\nRequests an incremental merge of specific files from the agent's branch\ninto the main branch before the task finishes. Only files already\ncommitted in the agent's worktree branch are processed." }, "PartialMergeResponse": { "properties": { "success": { "type": "boolean", "title": "Success" }, "merged_files": { "items": { "type": "string" }, "type": "array", "title": "Merged Files" }, "skipped_already_merged": { "items": { "type": "string" }, "type": "array", "title": "Skipped Already Merged" }, "uncommitted_files": { "items": { "type": "string" }, "type": "array", "title": "Uncommitted Files" }, "conflicting_files": { "items": { "type": "string" }, "type": "array", "title": "Conflicting Files" }, "commit_sha": { "type": "string", "title": "Commit Sha" }, "error": { "type": "string", "title": "Error" } }, "type": "object", "required": [ "success", "merged_files", "skipped_already_merged", "uncommitted_files", "conflicting_files", "commit_sha", "error" ], "title": "PartialMergeResponse", "description": "Response for POST /tasks/{task_id}/partial-merge." }, "PendingApproval": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "task_title": { "type": "string", "title": "Task Title" }, "session_id": { "type": "string", "title": "Session Id" }, "diff": { "type": "string", "title": "Diff", "default": "" }, "test_summary": { "type": "string", "title": "Test Summary", "default": "" } }, "type": "object", "required": [ "task_id", "task_title", "session_id" ], "title": "PendingApproval", "description": "A single pending approval request." }, "PlanDecisionRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "PlanDecisionRequest", "description": "Body for POST /plans/{plan_id}/approve or /reject." }, "ProgressEntry": { "properties": { "timestamp": { "type": "number", "title": "Timestamp" }, "message": { "type": "string", "title": "Message" }, "percent": { "type": "integer", "title": "Percent" } }, "type": "object", "required": [ "timestamp", "message", "percent" ], "title": "ProgressEntry", "description": "Single entry in a task's progress_log." }, "PromoteRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "manual" }, "promoted_by": { "type": "string", "title": "Promoted By", "default": "operator" } }, "type": "object", "title": "PromoteRequest", "description": "Request body for a manual promotion to the next stage.\n\nAttributes:\n reason: Human-readable reason for the promotion.\n promoted_by: Who triggered the promotion (operator name or ID)." }, "QueuedApprovalResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "session_id": { "type": "string", "title": "Session Id" }, "agent_role": { "type": "string", "title": "Agent Role" }, "tool_name": { "type": "string", "title": "Tool Name" }, "tool_args": { "additionalProperties": true, "type": "object", "title": "Tool Args" }, "created_at": { "type": "number", "title": "Created At" }, "ttl_seconds": { "type": "integer", "title": "Ttl Seconds" }, "nonce": { "type": "string", "title": "Nonce" } }, "type": "object", "required": [ "id", "session_id", "agent_role", "tool_name", "tool_args", "created_at", "ttl_seconds", "nonce" ], "title": "QueuedApprovalResponse", "description": "One queued tool-call approval from the op-002 approval queue.\n\nThe ``nonce`` field is the hex-encoded single-use token the reply\nmust echo. It travels only over the human-channel surface (TUI,\ndashboard, chat bridge) and never reaches agent stdin or any\nrendered prompt template." }, "QueuedApprovalsResponse": { "properties": { "pending": { "items": { "$ref": "#/components/schemas/QueuedApprovalResponse" }, "type": "array", "title": "Pending" } }, "type": "object", "required": [ "pending" ], "title": "QueuedApprovalsResponse", "description": "Response envelope for ``GET /approvals/queue``." }, "RecordEventRequest": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "success": { "type": "boolean", "title": "Success" }, "duration_s": { "type": "number", "title": "Duration S", "default": 0.0 }, "cost_usd": { "type": "number", "title": "Cost Usd", "default": 0.0 }, "initial_stage": { "type": "string", "title": "Initial Stage", "default": "sandbox" } }, "type": "object", "required": [ "task_id", "success" ], "title": "RecordEventRequest", "description": "Body for recording a task completion/failure event.\n\nAttributes:\n task_id: Task identifier.\n success: Whether the task succeeded.\n duration_s: Task wall-clock duration in seconds.\n cost_usd: Estimated cost of the task in USD.\n initial_stage: Stage to initialise the record at when no record exists yet." }, "ResolveRequest": { "properties": { "decision": { "type": "string", "enum": [ "allow", "reject", "always" ], "title": "Decision" }, "nonce": { "type": "string", "title": "Nonce", "default": "" }, "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "required": [ "decision" ], "title": "ResolveRequest", "description": "Body for ``POST /approvals/{id}/resolve``.\n\nThe reply must echo the exact ``nonce`` hex string issued when the\napproval was queued. ``nonce`` defaults to an empty string at the\nschema layer so a missing field flows through the handler as a\nnonce mismatch (``409 NONCE_MISMATCH``) rather than a Pydantic 422\nvalidation error, matching the documented contract." }, "ReviewActionRequest": { "properties": { "decision": { "type": "string", "title": "Decision" }, "note": { "type": "string", "title": "Note", "default": "" } }, "type": "object", "required": [ "decision" ], "title": "ReviewActionRequest", "description": "Body of a board review action (approve / request-changes / merge)." }, "SBOMArtifactEntry": { "properties": { "filename": { "type": "string", "title": "Filename" }, "path": { "type": "string", "title": "Path" }, "size_bytes": { "type": "integer", "title": "Size Bytes" } }, "type": "object", "required": [ "filename", "path", "size_bytes" ], "title": "SBOMArtifactEntry", "description": "A single SBOM artifact file entry." }, "SBOMGenerateRequest": { "properties": { "sbom_format": { "type": "string", "title": "Sbom Format", "description": "Output format: 'cyclonedx-json' or 'spdx-json'.", "default": "cyclonedx-json" }, "source": { "type": "string", "title": "Source", "description": "Package source label (pip, npm, requirements.txt, etc.).", "default": "pip" }, "run_scan": { "type": "boolean", "title": "Run Scan", "description": "Run vulnerability scanning (osv-scanner or grype) after generation.", "default": true }, "block_on_critical": { "type": "boolean", "title": "Block On Critical", "description": "Raise 422 when critical vulnerabilities are found.", "default": true } }, "type": "object", "title": "SBOMGenerateRequest", "description": "Body for POST /sbom/generate." }, "SBOMGenerateResponse": { "properties": { "serial_number": { "type": "string", "title": "Serial Number" }, "sbom_format": { "type": "string", "title": "Sbom Format" }, "component_count": { "type": "integer", "title": "Component Count" }, "artifact_path": { "type": "string", "title": "Artifact Path" }, "scan_result": { "anyOf": [ { "$ref": "#/components/schemas/SBOMScanResultResponse" }, { "type": "null" } ] } }, "type": "object", "required": [ "serial_number", "sbom_format", "component_count", "artifact_path" ], "title": "SBOMGenerateResponse", "description": "Response from POST /sbom/generate." }, "SBOMListResponse": { "properties": { "artifacts": { "items": { "$ref": "#/components/schemas/SBOMArtifactEntry" }, "type": "array", "title": "Artifacts" }, "artifact_dir": { "type": "string", "title": "Artifact Dir" } }, "type": "object", "required": [ "artifacts", "artifact_dir" ], "title": "SBOMListResponse", "description": "Response from GET /sbom/artifacts." }, "SBOMScanResultResponse": { "properties": { "scanner": { "type": "string", "title": "Scanner" }, "finding_count": { "type": "integer", "title": "Finding Count" }, "highest_severity": { "type": "string", "title": "Highest Severity" }, "findings": { "items": { "$ref": "#/components/schemas/SBOMVulnFindingResponse" }, "type": "array", "title": "Findings" }, "errors": { "items": { "type": "string" }, "type": "array", "title": "Errors" }, "passed_gate": { "type": "boolean", "title": "Passed Gate" } }, "type": "object", "required": [ "scanner", "finding_count", "highest_severity", "findings", "errors", "passed_gate" ], "title": "SBOMScanResultResponse", "description": "Serialised scan result." }, "SBOMVulnFindingResponse": { "properties": { "component_name": { "type": "string", "title": "Component Name" }, "component_version": { "type": "string", "title": "Component Version" }, "vuln_id": { "type": "string", "title": "Vuln Id" }, "severity": { "type": "string", "title": "Severity" }, "summary": { "type": "string", "title": "Summary" }, "fix_version": { "type": "string", "title": "Fix Version" }, "scanner": { "type": "string", "title": "Scanner" } }, "type": "object", "required": [ "component_name", "component_version", "vuln_id", "severity", "summary", "fix_version", "scanner" ], "title": "SBOMVulnFindingResponse", "description": "Serialised vulnerability finding." }, "SnapshotEntry": { "properties": { "timestamp": { "type": "number", "title": "Timestamp" }, "files_changed": { "type": "integer", "title": "Files Changed" }, "tests_passing": { "type": "integer", "title": "Tests Passing" }, "errors": { "type": "integer", "title": "Errors" }, "last_file": { "type": "string", "title": "Last File" } }, "type": "object", "required": [ "timestamp", "files_changed", "tests_passing", "errors", "last_file" ], "title": "SnapshotEntry", "description": "A single machine-readable progress snapshot for stall detection." }, "TaskArtifactContentResponse": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "key": { "type": "string", "title": "Key" }, "artifact_type": { "type": "string", "title": "Artifact Type" }, "content_hash": { "type": "string", "title": "Content Hash" }, "version": { "type": "integer", "title": "Version" }, "prev_version_hash": { "type": "string", "title": "Prev Version Hash" }, "spine_entry_hash": { "type": "string", "title": "Spine Entry Hash" }, "journal_index": { "type": "integer", "title": "Journal Index" }, "journal_event_hash": { "type": "string", "title": "Journal Event Hash" }, "link_kind": { "type": "string", "title": "Link Kind", "default": "" }, "size": { "type": "integer", "title": "Size", "default": 0 }, "verified": { "type": "boolean", "title": "Verified", "default": true }, "verify_reason": { "type": "string", "title": "Verify Reason", "default": "" }, "content": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Content" } }, "type": "object", "required": [ "task_id", "key", "artifact_type", "content_hash", "version", "prev_version_hash", "spine_entry_hash", "journal_index", "journal_event_hash" ], "title": "TaskArtifactContentResponse", "description": "A posted artifact version plus its decoded content (for rendering).\n\n``content`` carries the type-specific fields (``body`` for a report,\n``columns``/``rows`` for a table, ``url``/``kind`` for a link). When the\nstored blob fails its hash check ``verified`` is False and ``content`` is\nomitted -- the surface must render *tampered*, never the bytes." }, "TaskArtifactPost": { "properties": { "key": { "type": "string", "maxLength": 128, "minLength": 1, "pattern": "^[A-Za-z0-9][A-Za-z0-9_.\\-]{0,127}$", "title": "Key" }, "artifact_type": { "type": "string", "pattern": "^(report|table|link)$", "title": "Artifact Type" }, "poster": { "type": "string", "maxLength": 1000, "minLength": 1, "title": "Poster" }, "body": { "type": "string", "maxLength": 1048576, "title": "Body", "default": "" }, "columns": { "items": { "type": "string" }, "type": "array", "title": "Columns" }, "rows": { "items": { "items": { "type": "string" }, "type": "array" }, "type": "array", "title": "Rows" }, "url": { "type": "string", "maxLength": 4096, "title": "Url", "default": "" }, "link_kind": { "type": "string", "maxLength": 64, "title": "Link Kind", "default": "" } }, "type": "object", "required": [ "key", "artifact_type", "poster" ], "title": "TaskArtifactPost", "description": "Body for POST /tasks/{task_id}/artifacts (#2553).\n\nAn agent-posted, journal-anchored artifact. ``artifact_type`` selects the\npayload shape: ``report`` uses ``body`` (markdown); ``table`` uses\n``columns`` and ``rows``; ``link`` uses ``url`` and ``link_kind``\n(``preview`` / ``dashboard`` / ``document``). ``poster`` is the claim\nidentity: a caller may only post against a task whose claim it holds.\n\nThere is deliberately no progress field. Progress is a chain-computed\nprojection of journaled work, never postable." }, "TaskBlockRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "TaskBlockRequest", "description": "Body for POST /tasks/{task_id}/block." }, "TaskCancelRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "TaskCancelRequest", "description": "Body for POST /tasks/{task_id}/cancel." }, "TaskCompleteRequest": { "properties": { "result_summary": { "type": "string", "title": "Result Summary", "default": "" }, "payload": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Payload" } }, "type": "object", "title": "TaskCompleteRequest", "description": "Body for POST /tasks/{task_id}/complete.\n\n``result_summary`` is the legacy free-form summary and stays accepted\nunchanged. ``payload`` carries a structured terminal payload under the\nworker completion contract (#2244) - either a completion or a typed\nrefusal - and is schema-validated at the API boundary; an invalid\npayload is a typed ``contract_violation`` failure, never a silent\naccept. When ``payload`` is provided, ``result_summary`` is ignored." }, "TaskCountsResponse": { "properties": { "open": { "type": "integer", "title": "Open", "default": 0 }, "claimed": { "type": "integer", "title": "Claimed", "default": 0 }, "in_progress": { "type": "integer", "title": "In Progress", "default": 0 }, "done": { "type": "integer", "title": "Done", "default": 0 }, "closed": { "type": "integer", "title": "Closed", "default": 0 }, "failed": { "type": "integer", "title": "Failed", "default": 0 }, "blocked": { "type": "integer", "title": "Blocked", "default": 0 }, "cancelled": { "type": "integer", "title": "Cancelled", "default": 0 }, "planned": { "type": "integer", "title": "Planned", "default": 0 }, "pending_approval": { "type": "integer", "title": "Pending Approval", "default": 0 }, "waiting_for_subtasks": { "type": "integer", "title": "Waiting For Subtasks", "default": 0 }, "orphaned": { "type": "integer", "title": "Orphaned", "default": 0 }, "abandoned": { "type": "integer", "title": "Abandoned", "default": 0 }, "blocked_by_abandon": { "type": "integer", "title": "Blocked By Abandon", "default": 0 }, "refused": { "type": "integer", "title": "Refused", "default": 0 }, "suspended": { "type": "integer", "title": "Suspended", "default": 0 }, "total": { "type": "integer", "title": "Total", "default": 0 } }, "type": "object", "title": "TaskCountsResponse", "description": "Lightweight status counts - no task bodies.\n\nEvery value in :class:`bernstein.core.tasks.models.TaskStatus` is exposed\nas a field so the GUI's status-chip badges can render real numbers\ninstead of ``-``. Adding fields here is non-breaking - existing clients\nthat consume only ``open``/``claimed``/``done`` continue to work and the\nnew fields default to ``0``." }, "TaskCreate": { "properties": { "title": { "type": "string", "maxLength": 500, "title": "Title" }, "description": { "type": "string", "maxLength": 100000, "title": "Description" }, "role": { "type": "string", "maxLength": 1000, "title": "Role", "default": "auto" }, "tenant_id": { "type": "string", "maxLength": 1000, "title": "Tenant Id", "default": "default" }, "priority": { "type": "integer", "title": "Priority", "default": 2 }, "scope": { "type": "string", "maxLength": 1000, "title": "Scope", "default": "medium" }, "complexity": { "type": "string", "maxLength": 1000, "title": "Complexity", "default": "medium" }, "eu_ai_act_risk": { "type": "string", "maxLength": 1000, "title": "Eu Ai Act Risk", "default": "minimal" }, "approval_required": { "type": "boolean", "title": "Approval Required", "default": false }, "risk_level": { "type": "string", "maxLength": 1000, "title": "Risk Level", "default": "low" }, "estimated_minutes": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Estimated Minutes" }, "depends_on": { "items": { "type": "string" }, "type": "array", "maxItems": 100, "title": "Depends On" }, "parent_task_id": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Parent Task Id" }, "depends_on_repo": { "anyOf": [ { "type": "string", "maxLength": 4096 }, { "type": "null" } ], "title": "Depends On Repo" }, "owned_files": { "items": { "type": "string" }, "type": "array", "maxItems": 100, "title": "Owned Files" }, "cell_id": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Cell Id" }, "repo": { "anyOf": [ { "type": "string", "maxLength": 4096 }, { "type": "null" } ], "title": "Repo" }, "task_type": { "type": "string", "maxLength": 1000, "title": "Task Type", "default": "standard" }, "upgrade_details": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Upgrade Details" }, "model": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Model" }, "effort": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Effort" }, "cli": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Cli" }, "batch_eligible": { "type": "boolean", "title": "Batch Eligible", "default": false }, "completion_signals": { "items": { "$ref": "#/components/schemas/CompletionSignalSchema" }, "type": "array", "maxItems": 100, "title": "Completion Signals" }, "slack_context": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Slack Context" }, "metadata": { "additionalProperties": true, "type": "object", "title": "Metadata" }, "deadline": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Deadline" }, "parent_session_id": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Parent Session Id" }, "parent_context": { "anyOf": [ { "type": "string", "maxLength": 100000 }, { "type": "null" } ], "title": "Parent Context" }, "retry_count": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Retry Count" }, "max_retries": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Retries" }, "retry_delay_s": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Retry Delay S" }, "terminal_reason": { "anyOf": [ { "type": "string", "maxLength": 100000 }, { "type": "null" } ], "title": "Terminal Reason" }, "max_output_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Output Tokens" }, "meta_messages": { "anyOf": [ { "items": { "type": "string" }, "type": "array", "maxItems": 100 }, { "type": "null" } ], "title": "Meta Messages" }, "max_turns": { "anyOf": [ { "type": "integer", "maximum": 10000.0, "minimum": 1.0 }, { "type": "null" } ], "title": "Max Turns" } }, "type": "object", "required": [ "title", "description" ], "title": "TaskCreate", "description": "Body for POST /tasks." }, "TaskDetailResponse": { "properties": { "task": { "$ref": "#/components/schemas/TaskResponse" }, "log_tail": { "type": "string", "title": "Log Tail" }, "log_size": { "type": "integer", "title": "Log Size" }, "progress_entries": { "items": { "additionalProperties": true, "type": "object" }, "type": "array", "title": "Progress Entries" }, "agent_status": { "type": "string", "title": "Agent Status", "default": "" }, "artifacts": { "items": { "additionalProperties": true, "type": "object" }, "type": "array", "title": "Artifacts" }, "progress": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Progress" } }, "type": "object", "required": [ "task", "log_tail", "log_size" ], "title": "TaskDetailResponse", "description": "Detailed task view including log tail and progress." }, "TaskDiffResponse": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "branch": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Branch" }, "base_ref": { "type": "string", "title": "Base Ref" }, "head_ref": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Head Ref" }, "additions": { "type": "integer", "title": "Additions" }, "deletions": { "type": "integer", "title": "Deletions" }, "files": { "items": { "$ref": "#/components/schemas/DiffFile" }, "type": "array", "title": "Files" }, "unified": { "type": "string", "title": "Unified" }, "truncated": { "type": "boolean", "title": "Truncated", "default": false }, "generated_at": { "type": "number", "title": "Generated At" }, "note": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Note" } }, "type": "object", "required": [ "task_id", "branch", "base_ref", "head_ref", "additions", "deletions", "files", "unified", "generated_at" ], "title": "TaskDiffResponse", "description": "Diff payload for a task's working branch vs the base ref." }, "TaskFailRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "TaskFailRequest", "description": "Body for POST /tasks/{task_id}/fail." }, "TaskMessagePost": { "properties": { "sender": { "type": "string", "maxLength": 1000, "minLength": 1, "title": "Sender" }, "kind": { "type": "string", "maxLength": 64, "minLength": 1, "title": "Kind" }, "body": { "type": "string", "maxLength": 4096, "minLength": 1, "title": "Body" }, "sender_card_fingerprint": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Sender Card Fingerprint" } }, "type": "object", "required": [ "sender", "kind", "body" ], "title": "TaskMessagePost", "description": "Body for POST /tasks/{task_id}/messages (#2357).\n\nTyped, size-capped worker mailbox payload. ``kind`` must be one of the\nclosed vocabulary (``finding`` / ``artefact_ref`` / ``question``).\nThe message body is capped by the mailbox chain to 4096 UTF-8 bytes\n(see ``task_mailbox.MAX_MESSAGE_BODY_BYTES``); the API model mirrors\nthis limit so oversized bodies fail validation up front instead of\nbeing rejected downstream. The byte-strict cap remains authoritative\nin the mailbox for multibyte payloads." }, "TaskMessageResponse": { "properties": { "seq": { "type": "integer", "title": "Seq" }, "task_id": { "type": "string", "title": "Task Id" }, "sender": { "type": "string", "title": "Sender" }, "sender_card_fingerprint": { "type": "string", "title": "Sender Card Fingerprint" }, "kind": { "type": "string", "title": "Kind" }, "body": { "type": "string", "title": "Body" }, "body_hash": { "type": "string", "title": "Body Hash" }, "redaction_count": { "type": "integer", "title": "Redaction Count" }, "timestamp": { "type": "number", "title": "Timestamp" }, "prev_entry_hash": { "type": "string", "title": "Prev Entry Hash" }, "entry_hash": { "type": "string", "title": "Entry Hash" }, "signature": { "type": "string", "title": "Signature" }, "signer_public_key_pem": { "type": "string", "title": "Signer Public Key Pem" } }, "type": "object", "required": [ "seq", "task_id", "sender", "sender_card_fingerprint", "kind", "body", "body_hash", "redaction_count", "timestamp", "prev_entry_hash", "entry_hash", "signature", "signer_public_key_pem" ], "title": "TaskMessageResponse", "description": "One delivered mailbox message (chain order = delivery order)." }, "TaskPatchRequest": { "properties": { "role": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Role" }, "priority": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Priority" }, "model": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Model" } }, "type": "object", "title": "TaskPatchRequest", "description": "Body for PATCH /tasks/{task_id} - manager corrections." }, "TaskProgressRequest": { "properties": { "message": { "type": "string", "title": "Message", "default": "" }, "percent": { "type": "integer", "title": "Percent", "default": 0 }, "files_changed": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Files Changed" }, "lines_changed": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Lines Changed" }, "tests_passing": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Tests Passing" }, "errors": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Errors" }, "last_file": { "type": "string", "title": "Last File", "default": "" }, "last_command": { "type": "string", "title": "Last Command", "default": "" } }, "type": "object", "title": "TaskProgressRequest", "description": "Body for POST /tasks/{task_id}/progress." }, "TaskProgressResponse": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "schema_version": { "type": "integer", "title": "Schema Version" }, "checkpoints": { "type": "integer", "title": "Checkpoints" }, "diffs_captured": { "type": "integer", "title": "Diffs Captured" }, "gate_attempts": { "type": "integer", "title": "Gate Attempts" }, "evidence_declared": { "type": "integer", "title": "Evidence Declared" }, "evidence_passed": { "type": "integer", "title": "Evidence Passed" }, "ledger_phase": { "type": "string", "title": "Ledger Phase" }, "ledger_attempts": { "type": "integer", "title": "Ledger Attempts" }, "terminal": { "type": "boolean", "title": "Terminal" }, "earned_steps": { "type": "integer", "title": "Earned Steps" }, "phase_ordinal": { "type": "integer", "title": "Phase Ordinal" }, "vector_hash": { "type": "string", "title": "Vector Hash" } }, "type": "object", "required": [ "task_id", "schema_version", "checkpoints", "diffs_captured", "gate_attempts", "evidence_declared", "evidence_passed", "ledger_phase", "ledger_attempts", "terminal", "earned_steps", "phase_ordinal", "vector_hash" ], "title": "TaskProgressResponse", "description": "The chain-computed progress vector for a task (#2553).\n\nA pure projection of journaled work: checkpoints, diffs, gates, evidence\nproducers, and ledger transitions. ``vector_hash`` is the stable hash of the\ncanonical vector; two projections of the same run agree byte-for-byte." }, "TaskReleaseRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "TaskReleaseRequest", "description": "Body for POST /tasks/{task_id}/release." }, "TaskReopenRequest": { "properties": { "reason": { "type": "string", "title": "Reason", "default": "" } }, "type": "object", "title": "TaskReopenRequest", "description": "Body for POST /tasks/{task_id}/reopen." }, "TaskResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "title": { "type": "string", "title": "Title" }, "description": { "type": "string", "title": "Description" }, "role": { "type": "string", "title": "Role" }, "tenant_id": { "type": "string", "title": "Tenant Id" }, "priority": { "type": "integer", "title": "Priority" }, "scope": { "type": "string", "title": "Scope" }, "complexity": { "type": "string", "title": "Complexity" }, "eu_ai_act_risk": { "type": "string", "title": "Eu Ai Act Risk" }, "approval_required": { "type": "boolean", "title": "Approval Required" }, "risk_level": { "type": "string", "title": "Risk Level" }, "estimated_minutes": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Estimated Minutes" }, "status": { "type": "string", "title": "Status" }, "depends_on": { "items": { "type": "string" }, "type": "array", "title": "Depends On" }, "parent_task_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Task Id" }, "depends_on_repo": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Depends On Repo" }, "owned_files": { "items": { "type": "string" }, "type": "array", "title": "Owned Files" }, "assigned_agent": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Assigned Agent" }, "result_summary": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Result Summary" }, "cell_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Cell Id" }, "repo": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Repo" }, "task_type": { "type": "string", "title": "Task Type" }, "upgrade_details": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Upgrade Details" }, "model": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Model" }, "effort": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Effort" }, "cli": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Cli" }, "batch_eligible": { "type": "boolean", "title": "Batch Eligible", "default": false }, "completion_signals": { "items": { "additionalProperties": { "type": "string" }, "type": "object" }, "type": "array", "title": "Completion Signals" }, "slack_context": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Slack Context" }, "metadata": { "additionalProperties": true, "type": "object", "title": "Metadata" }, "created_at": { "type": "number", "title": "Created At" }, "claimed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Claimed At" }, "completed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Completed At" }, "closed_at": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Closed At" }, "deadline": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Deadline" }, "progress_log": { "items": { "$ref": "#/components/schemas/ProgressEntry" }, "type": "array", "title": "Progress Log" }, "version": { "type": "integer", "title": "Version", "default": 1 }, "parent_session_id": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Parent Session Id" }, "retry_count": { "type": "integer", "title": "Retry Count", "default": 0 }, "max_retries": { "type": "integer", "title": "Max Retries", "default": 3 }, "retry_delay_s": { "type": "number", "title": "Retry Delay S", "default": 0.0 }, "terminal_reason": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "title": "Terminal Reason" }, "max_output_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Output Tokens" }, "meta_messages": { "items": { "type": "string" }, "type": "array", "title": "Meta Messages" }, "max_turns": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Turns" } }, "type": "object", "required": [ "id", "title", "description", "role", "tenant_id", "priority", "scope", "complexity", "eu_ai_act_risk", "approval_required", "risk_level", "estimated_minutes", "status", "depends_on", "parent_task_id", "depends_on_repo", "owned_files", "assigned_agent", "result_summary", "cell_id", "repo", "task_type", "upgrade_details", "model", "effort", "created_at" ], "title": "TaskResponse", "description": "Serialised task returned by every task endpoint." }, "TaskSelfCreate": { "properties": { "parent_task_id": { "type": "string", "title": "Parent Task Id" }, "title": { "type": "string", "title": "Title" }, "description": { "type": "string", "title": "Description" }, "role": { "type": "string", "title": "Role", "default": "auto" }, "priority": { "type": "integer", "title": "Priority", "default": 2 }, "scope": { "type": "string", "title": "Scope", "default": "medium" }, "complexity": { "type": "string", "title": "Complexity", "default": "medium" }, "estimated_minutes": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Estimated Minutes" }, "depends_on": { "items": { "type": "string" }, "type": "array", "title": "Depends On" }, "owned_files": { "items": { "type": "string" }, "type": "array", "title": "Owned Files" } }, "type": "object", "required": [ "parent_task_id", "title", "description" ], "title": "TaskSelfCreate", "description": "Body for POST /tasks/self-create - agent-initiated subtask creation.\n\nAgents use this to decompose work into subtasks during execution.\nThe parent_task_id is required and links the new subtask to the calling\nagent's current task." }, "TaskStealAction": { "properties": { "donor_node_id": { "type": "string", "title": "Donor Node Id" }, "receiver_node_id": { "type": "string", "title": "Receiver Node Id" }, "task_ids": { "items": { "type": "string" }, "type": "array", "title": "Task Ids" } }, "type": "object", "required": [ "donor_node_id", "receiver_node_id", "task_ids" ], "title": "TaskStealAction", "description": "A single steal action: move tasks from donor to receiver." }, "TaskStealRequest": { "properties": { "queue_depths": { "additionalProperties": { "type": "integer" }, "type": "object", "title": "Queue Depths" } }, "type": "object", "title": "TaskStealRequest", "description": "Body for POST /cluster/steal - report queue depths and request rebalancing." }, "TaskStealResponse": { "properties": { "actions": { "items": { "$ref": "#/components/schemas/TaskStealAction" }, "type": "array", "title": "Actions" }, "total_stolen": { "type": "integer", "title": "Total Stolen" } }, "type": "object", "required": [ "actions", "total_stolen" ], "title": "TaskStealResponse", "description": "Response for POST /cluster/steal." }, "TaskSteerPost": { "properties": { "kind": { "type": "string", "maxLength": 64, "minLength": 1, "title": "Kind" }, "principal": { "type": "string", "maxLength": 1000, "title": "Principal", "default": "" }, "guidance": { "type": "string", "maxLength": 2048, "title": "Guidance", "default": "" }, "redirect_target": { "type": "string", "maxLength": 2048, "title": "Redirect Target", "default": "" }, "reason": { "type": "string", "maxLength": 2048, "title": "Reason", "default": "" }, "session_id": { "type": "string", "maxLength": 1000, "title": "Session Id", "default": "" }, "adapter": { "type": "string", "maxLength": 1000, "title": "Adapter", "default": "" }, "worktree": { "type": "string", "maxLength": 4096, "title": "Worktree", "default": "" }, "displayed_payload_hash": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Displayed Payload Hash" } }, "type": "object", "required": [ "kind" ], "title": "TaskSteerPost", "description": "Body for POST /tasks/{task_id}/steer (#2508).\n\nAn operator steering command: pause, resume, guidance, redirect, or\nabort. Free-text fields are capped so the mailbox delivery envelope\nalways fits the mailbox body cap. ``displayed_payload_hash`` is the hash\nthe confirmation UI computed over what it showed the operator; when\nsupplied the server rejects the action if it differs from the executed\ncommand, so the receipt binds exactly the confirmed payload." }, "TaskSteerResponse": { "properties": { "kind": { "type": "string", "title": "Kind" }, "task_id": { "type": "string", "title": "Task Id" }, "principal": { "type": "string", "title": "Principal" }, "scope": { "type": "string", "title": "Scope" }, "payload_hash": { "type": "string", "title": "Payload Hash" }, "receipt_hash": { "type": "string", "title": "Receipt Hash" }, "timestamp": { "type": "number", "title": "Timestamp" }, "mailbox_seq": { "type": "integer", "title": "Mailbox Seq" }, "mailbox_entry_hash": { "type": "string", "title": "Mailbox Entry Hash" }, "checkpoint_event_hash": { "type": "string", "title": "Checkpoint Event Hash", "default": "" }, "abort_signal_written": { "type": "boolean", "title": "Abort Signal Written", "default": false } }, "type": "object", "required": [ "kind", "task_id", "principal", "scope", "payload_hash", "receipt_hash", "timestamp", "mailbox_seq", "mailbox_entry_hash" ], "title": "TaskSteerResponse", "description": "The receipt a steering action produced (#2508).\n\nThe response IS the receipt: the chain-anchored ``receipt_hash`` the\ndelivered effect references, the ``payload_hash`` it binds, and the\nmailbox journal position the effect was delivered at." }, "TaskWaitForSubtasksRequest": { "properties": { "subtask_count": { "type": "integer", "title": "Subtask Count", "default": 0 } }, "type": "object", "title": "TaskWaitForSubtasksRequest", "description": "Body for POST /tasks/{task_id}/wait-for-subtasks." }, "TraceTimelineEvent": { "properties": { "id": { "type": "string", "title": "Id" }, "ts": { "type": "number", "title": "Ts" }, "kind": { "type": "string", "title": "Kind" }, "actor": { "type": "string", "title": "Actor", "default": "" }, "summary": { "type": "string", "title": "Summary", "default": "" }, "outcome": { "type": "string", "title": "Outcome", "default": "neutral" }, "trace_id": { "type": "string", "title": "Trace Id", "default": "" }, "session_id": { "type": "string", "title": "Session Id", "default": "" }, "payload": { "additionalProperties": true, "type": "object", "title": "Payload" } }, "type": "object", "required": [ "id", "ts", "kind" ], "title": "TraceTimelineEvent", "description": "One event card on the Trace tab timeline.\n\nAttributes:\n id: Stable per-task event identifier (``\"{trace_idx}:{step_idx}\"`` for\n steps; ``\"{trace_idx}:meta\"`` for the synthetic trace-level summary).\n ts: Unix timestamp (seconds, float). 0.0 means unknown.\n kind: Event kind - mirrors the TUI vocabulary\n (``spawn|orient|plan|edit|verify|complete|fail|compact|trace_meta``).\n actor: Best-effort attribution string - usually ``{role}/{model}`` or\n ``{session_id}``. Empty when unknown.\n summary: One-line human-readable description.\n outcome: ``success | failed | unknown | neutral`` - drives colour coding.\n trace_id: Owning trace id (so the FE can group events from the same spawn).\n session_id: Owning session id (mirrors the agent log filename).\n payload: Full event payload for the expandable JSON card." }, "TraceTimelineResponse": { "properties": { "task_id": { "type": "string", "title": "Task Id" }, "events": { "items": { "$ref": "#/components/schemas/TraceTimelineEvent" }, "type": "array", "title": "Events" }, "total": { "type": "integer", "title": "Total" }, "cursor": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Cursor" }, "first_ts": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "First Ts" }, "last_ts": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Last Ts" }, "has_open_trace": { "type": "boolean", "title": "Has Open Trace", "default": false } }, "type": "object", "required": [ "task_id", "events", "total" ], "title": "TraceTimelineResponse", "description": "Container returned by ``GET /dashboard/tasks/{task_id}/trace``." }, "UserProfileResponse": { "properties": { "id": { "type": "string", "title": "Id" }, "email": { "type": "string", "title": "Email" }, "display_name": { "type": "string", "title": "Display Name" }, "role": { "type": "string", "title": "Role" }, "sso_provider": { "type": "string", "title": "Sso Provider" }, "sso_groups": { "items": { "type": "string" }, "type": "array", "title": "Sso Groups" }, "permissions": { "items": { "type": "string" }, "type": "array", "title": "Permissions" } }, "type": "object", "required": [ "id", "email", "display_name", "role", "sso_provider", "sso_groups", "permissions" ], "title": "UserProfileResponse", "description": "Response for GET /auth/me." }, "ValidationError": { "properties": { "loc": { "items": { "anyOf": [ { "type": "string" }, { "type": "integer" } ] }, "type": "array", "title": "Location" }, "msg": { "type": "string", "title": "Message" }, "type": { "type": "string", "title": "Error Type" }, "input": { "title": "Input" }, "ctx": { "type": "object", "title": "Context" } }, "type": "object", "required": [ "loc", "msg", "type" ], "title": "ValidationError" }, "VerifyChainRequest": { "properties": { "from_chunk": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "From Chunk" } }, "type": "object", "title": "VerifyChainRequest", "description": "Body for ``POST /audit/verify`` (re-verify chain or chunk)." }, "WebhookTaskCreate": { "properties": { "title": { "type": "string", "maxLength": 500, "title": "Title" }, "description": { "type": "string", "maxLength": 100000, "title": "Description" }, "role": { "type": "string", "title": "Role", "default": "backend" }, "tenant_id": { "type": "string", "maxLength": 1000, "title": "Tenant Id", "default": "default" }, "priority": { "type": "integer", "title": "Priority", "default": 2 }, "scope": { "type": "string", "maxLength": 1000, "title": "Scope", "default": "medium" }, "complexity": { "type": "string", "maxLength": 1000, "title": "Complexity", "default": "medium" }, "eu_ai_act_risk": { "type": "string", "maxLength": 1000, "title": "Eu Ai Act Risk", "default": "minimal" }, "approval_required": { "type": "boolean", "title": "Approval Required", "default": false }, "risk_level": { "type": "string", "maxLength": 1000, "title": "Risk Level", "default": "low" }, "estimated_minutes": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Estimated Minutes" }, "depends_on": { "items": { "type": "string" }, "type": "array", "maxItems": 100, "title": "Depends On" }, "parent_task_id": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Parent Task Id" }, "depends_on_repo": { "anyOf": [ { "type": "string", "maxLength": 4096 }, { "type": "null" } ], "title": "Depends On Repo" }, "owned_files": { "items": { "type": "string" }, "type": "array", "maxItems": 100, "title": "Owned Files" }, "cell_id": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Cell Id" }, "repo": { "anyOf": [ { "type": "string", "maxLength": 4096 }, { "type": "null" } ], "title": "Repo" }, "task_type": { "type": "string", "maxLength": 1000, "title": "Task Type", "default": "standard" }, "upgrade_details": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Upgrade Details" }, "model": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Model" }, "effort": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Effort" }, "cli": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Cli" }, "batch_eligible": { "type": "boolean", "title": "Batch Eligible", "default": false }, "completion_signals": { "items": { "$ref": "#/components/schemas/CompletionSignalSchema" }, "type": "array", "maxItems": 100, "title": "Completion Signals" }, "slack_context": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Slack Context" }, "metadata": { "additionalProperties": true, "type": "object", "title": "Metadata" }, "deadline": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Deadline" }, "parent_session_id": { "anyOf": [ { "type": "string", "maxLength": 1000 }, { "type": "null" } ], "title": "Parent Session Id" }, "parent_context": { "anyOf": [ { "type": "string", "maxLength": 100000 }, { "type": "null" } ], "title": "Parent Context" }, "retry_count": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Retry Count" }, "max_retries": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Retries" }, "retry_delay_s": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "title": "Retry Delay S" }, "terminal_reason": { "anyOf": [ { "type": "string", "maxLength": 100000 }, { "type": "null" } ], "title": "Terminal Reason" }, "max_output_tokens": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "title": "Max Output Tokens" }, "meta_messages": { "anyOf": [ { "items": { "type": "string" }, "type": "array", "maxItems": 100 }, { "type": "null" } ], "title": "Meta Messages" }, "max_turns": { "anyOf": [ { "type": "integer", "maximum": 10000.0, "minimum": 1.0 }, { "type": "null" } ], "title": "Max Turns" } }, "type": "object", "required": [ "title", "description" ], "title": "WebhookTaskCreate", "description": "Body for POST /webhook." }, "WebhookTaskResponse": { "properties": { "task": { "$ref": "#/components/schemas/TaskResponse" }, "receipt": { "anyOf": [ { "additionalProperties": true, "type": "object" }, { "type": "null" } ], "title": "Receipt" } }, "type": "object", "required": [ "task" ], "title": "WebhookTaskResponse", "description": "Serialized task returned by POST /webhook.\n\n``receipt`` carries the signed, chain-anchored trigger receipt for the\nadmitted trigger (#2512) so the calling automation platform stores a proof\nof what it asked for, not just a task reference. It is optional: an install\nwhose bridge state is unavailable still creates the task and returns\n``None`` rather than failing the caller." }, "WorkspaceRepoResponse": { "properties": { "name": { "type": "string", "title": "Name" }, "path": { "type": "string", "title": "Path" }, "branch": { "type": "string", "title": "Branch" }, "clean": { "type": "boolean", "title": "Clean" }, "ahead": { "type": "integer", "title": "Ahead" }, "behind": { "type": "integer", "title": "Behind" } }, "type": "object", "required": [ "name", "path", "branch", "clean", "ahead", "behind" ], "title": "WorkspaceRepoResponse", "description": "Workspace repository status entry." }, "WorkspaceResponse": { "properties": { "repos": { "items": { "$ref": "#/components/schemas/WorkspaceRepoResponse" }, "type": "array", "title": "Repos" } }, "type": "object", "required": [ "repos" ], "title": "WorkspaceResponse", "description": "Workspace repository status payload." } } } }