{
  "openapi": "3.1.0",
  "info": {
    "title": "turnstone Server API",
    "version": "1.5.0a4",
    "description": "Single-node workstream management, chat interaction, and real-time streaming."
  },
  "paths": {
    "/v1/api/workstreams": {
      "get": {
        "summary": "List active workstreams",
        "operationId": "v1_api_workstreams_get",
        "tags": [
          "Workstreams"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListWorkstreamsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/dashboard": {
      "get": {
        "summary": "Dashboard with workstream details and aggregates",
        "operationId": "v1_api_dashboard_get",
        "tags": [
          "Workstreams"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/new": {
      "post": {
        "summary": "Create a new workstream",
        "operationId": "v1_api_workstreams_new_post",
        "tags": [
          "Workstreams"
        ],
        "description": "Accepts two content types. Default is `application/json` with a `CreateWorkstreamRequest` body. Alternatively, `multipart/form-data` with one `meta` field (JSON-encoded `CreateWorkstreamRequest` shape) plus zero-or-more `file` parts saves each file as an attachment under the new workstream. When `initial_message` is also set, attachments are reserved onto that turn before the worker thread dispatches; otherwise they remain pending for a follow-up `POST /v1/api/workstreams/{ws_id}/send`.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWorkstreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateWorkstreamResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Error 409",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Error 413",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/close": {
      "post": {
        "summary": "Close a workstream",
        "operationId": "v1_api_workstreams_{ws_id}_close_post",
        "tags": [
          "Workstreams"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CloseWorkstreamRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/send": {
      "post": {
        "summary": "Send a user message",
        "operationId": "v1_api_workstreams_{ws_id}_send_post",
        "tags": [
          "Chat"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Cancel a queued message",
        "operationId": "v1_api_workstreams_{ws_id}_send_delete",
        "tags": [
          "Chat"
        ],
        "description": "Removes a previously-queued message from the workstream's pending queue. Returns ``status: removed`` when the queue had the entry, ``status: not_found`` otherwise.",
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DequeueRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/approve": {
      "post": {
        "summary": "Approve or deny a tool call",
        "operationId": "v1_api_workstreams_{ws_id}_approve_post",
        "tags": [
          "Chat"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApproveRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/plan": {
      "post": {
        "summary": "Respond to a plan review",
        "operationId": "v1_api_plan_post",
        "tags": [
          "Chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PlanFeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/command": {
      "post": {
        "summary": "Execute a slash command",
        "operationId": "v1_api_command_post",
        "tags": [
          "Chat"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/cancel": {
      "post": {
        "summary": "Cancel the active generation in a workstream",
        "operationId": "v1_api_workstreams_{ws_id}_cancel_post",
        "tags": [
          "Chat"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CancelRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/events": {
      "get": {
        "summary": "Per-workstream SSE event stream",
        "operationId": "v1_api_workstreams_{ws_id}_events_get",
        "tags": [
          "Streaming"
        ],
        "description": "Opens a Server-Sent Events stream scoped to a single workstream. Returns text/event-stream. See API reference for event types.",
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/events/global": {
      "get": {
        "summary": "Global SSE event stream",
        "operationId": "v1_api_events_global_get",
        "tags": [
          "Streaming"
        ],
        "description": "Server-Sent Events stream for node-level state broadcasts. Emits a node_snapshot event on connect (workstreams, health, aggregate), followed by real-time delta events (ws_state, ws_activity, ws_created, ws_closed, ws_rename, health_changed, aggregate). Pass ?expected_node_id=X for identity verification (returns 409 on mismatch).",
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/delete": {
      "post": {
        "summary": "Permanently delete a saved workstream",
        "operationId": "v1_api_workstreams_{ws_id}_delete_post",
        "tags": [
          "Workstreams"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Error 500",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/open": {
      "post": {
        "summary": "Load a saved workstream into memory",
        "operationId": "v1_api_workstreams_{ws_id}_open_post",
        "tags": [
          "Workstreams"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Error 500",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/title": {
      "post": {
        "summary": "Set workstream title manually",
        "operationId": "v1_api_workstreams_{ws_id}_title_post",
        "tags": [
          "Workstreams"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Error 409",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/refresh-title": {
      "post": {
        "summary": "Regenerate workstream title via LLM",
        "operationId": "v1_api_workstreams_{ws_id}_refresh-title_post",
        "tags": [
          "Workstreams"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}": {
      "get": {
        "summary": "Get workstream detail (rehydrates lazily on miss)",
        "operationId": "v1_api_workstreams_{ws_id}_get",
        "tags": [
          "Workstreams"
        ],
        "description": "Returns the persisted workstream's display fields. If the session isn't currently in memory the manager rehydrates it before responding; ``500`` on rehydrate failure carries a correlation id matching the server log line. Lifted from the coord-only surface in the Stage 2 history/detail verb lift \u2014 interactive previously had no detail endpoint.",
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkstreamDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Error 500",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Error 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/history": {
      "get": {
        "summary": "Read the workstream's reconstructed message history",
        "operationId": "v1_api_workstreams_{ws_id}_history_get",
        "tags": [
          "Workstreams"
        ],
        "description": "Returns the tail of the conversation in OpenAI-like message format. Persisted-but-not-loaded workstreams (closed / evicted) serve history without rehydrating. Lifted from the coord-only surface in the Stage 2 history/detail verb lift \u2014 interactive previously only exposed history through the SSE replay on ``/events``.",
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100
            },
            "description": "Max conversation rows to fetch from storage (default 100, max 500)."
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WorkstreamHistoryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "500": {
            "description": "Error 500",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Error 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/attachments": {
      "post": {
        "summary": "Upload a file (multipart/form-data, field 'file') and attach it to the caller's next user turn on this workstream.  Validates size, MIME, and UTF-8 for text; magic-byte sniff for images.  Ownership failures are masked as 404 so non-owners cannot enumerate workstream existence; a 403 indicates a scope/auth failure from the middleware layer.",
        "operationId": "v1_api_workstreams_{ws_id}_attachments_post",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UploadAttachmentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Error 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Error 409",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "Error 413",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List the caller's pending (unconsumed) attachments for this workstream.  Ownership failures are masked as 404.",
        "operationId": "v1_api_workstreams_{ws_id}_attachments_get",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAttachmentsResponse"
                }
              }
            }
          },
          "403": {
            "description": "Error 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/attachments/{attachment_id}/content": {
      "get": {
        "summary": "Return raw bytes of an attachment with its stored Content-Type.  Ownership failures are masked as 404.",
        "operationId": "v1_api_workstreams_{ws_id}_attachments_{attachment_id}_content_get",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "403": {
            "description": "Error 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/{ws_id}/attachments/{attachment_id}": {
      "delete": {
        "summary": "Remove a pending attachment (consumed attachments return 404).  Ownership failures are also masked as 404.",
        "operationId": "v1_api_workstreams_{ws_id}_attachments_{attachment_id}_delete",
        "tags": [
          "Attachments"
        ],
        "parameters": [
          {
            "name": "ws_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "attachment_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "403": {
            "description": "Error 403",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/workstreams/saved": {
      "get": {
        "summary": "List saved workstreams",
        "operationId": "v1_api_workstreams_saved_get",
        "tags": [
          "Workstreams"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSavedWorkstreamsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/skills": {
      "get": {
        "summary": "List available skills (summary)",
        "operationId": "v1_api_skills_get",
        "tags": [
          "Skills"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSkillSummaryResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/models": {
      "get": {
        "summary": "List available model aliases",
        "operationId": "v1_api_models_get",
        "tags": [
          "Models"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAvailableModelsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/auth/login": {
      "post": {
        "summary": "Authenticate with a token",
        "operationId": "v1_api_auth_login_post",
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthLoginRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthLoginResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/auth/setup": {
      "post": {
        "summary": "Create first admin user",
        "operationId": "v1_api_auth_setup_post",
        "tags": [
          "Auth"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthSetupRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthSetupResponse"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Error 409",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Error 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/auth/status": {
      "get": {
        "summary": "Return auth state",
        "operationId": "v1_api_auth_status_get",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthStatusResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/auth/logout": {
      "post": {
        "summary": "Clear auth cookie",
        "operationId": "v1_api_auth_logout_post",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/auth/oidc/authorize": {
      "get": {
        "summary": "Redirect to OIDC provider for SSO login",
        "operationId": "v1_api_auth_oidc_authorize_get",
        "tags": [
          "Auth"
        ],
        "responses": {
          "302": {
            "description": "Success"
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Error 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/auth/oidc/callback": {
      "get": {
        "summary": "OIDC callback \u2014 validates code, provisions user, sets JWT cookie, redirects to app",
        "operationId": "v1_api_auth_oidc_callback_get",
        "tags": [
          "Auth"
        ],
        "responses": {
          "302": {
            "description": "Success"
          }
        }
      }
    },
    "/v1/api/auth/whoami": {
      "get": {
        "summary": "Return authenticated user info and permissions",
        "operationId": "v1_api_auth_whoami_get",
        "tags": [
          "Auth"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthWhoamiResponse"
                }
              }
            }
          },
          "401": {
            "description": "Error 401",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/memories": {
      "get": {
        "summary": "List structured memories",
        "operationId": "v1_api_memories_get",
        "tags": [
          "Memories"
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter by memory type"
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter by scope"
          },
          {
            "name": "scope_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Filter by scope identifier"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 100
            },
            "description": "Max results (default 100, max 200)"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListMemoriesResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Save (upsert) a structured memory",
        "operationId": "v1_api_memories_post",
        "tags": [
          "Memories"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveMemoryRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryInfo"
                }
              }
            }
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/memories/search": {
      "post": {
        "summary": "Search structured memories by query",
        "operationId": "v1_api_memories_search_post",
        "tags": [
          "Memories"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SearchMemoriesRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListMemoriesResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/memories/{name}": {
      "delete": {
        "summary": "Delete a structured memory by name and scope",
        "operationId": "v1_api_memories_{name}_delete",
        "tags": [
          "Memories"
        ],
        "parameters": [
          {
            "name": "name",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Scope (default: global)"
          },
          {
            "name": "scope_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            },
            "description": "Scope identifier"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                }
              }
            }
          },
          "404": {
            "description": "Error 404",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/api/admin/settings": {
      "get": {
        "summary": "List interface.* settings with values and sources",
        "operationId": "v1_api_admin_settings_get",
        "tags": [
          "Admin"
        ],
        "responses": {
          "200": {
            "description": "Success"
          }
        }
      }
    },
    "/v1/api/admin/settings/{key}": {
      "put": {
        "summary": "Update an interface.* setting",
        "operationId": "v1_api_admin_settings_{key}_put",
        "tags": [
          "Admin"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Error 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Update an interface.* setting (alias for PUT)",
        "operationId": "v1_api_admin_settings_{key}_post",
        "tags": [
          "Admin"
        ],
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Success"
          },
          "400": {
            "description": "Error 400",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Error 503",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "summary": "Server health check",
        "operationId": "health_get",
        "tags": [
          "Observability"
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ErrorResponse": {
        "description": "Standard error response body.",
        "properties": {
          "error": {
            "description": "Error message",
            "title": "Error",
            "type": "string"
          }
        },
        "required": [
          "error"
        ],
        "title": "ErrorResponse",
        "type": "object"
      },
      "StatusResponse": {
        "description": "Generic success response.",
        "properties": {
          "status": {
            "default": "ok",
            "examples": [
              "ok"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "title": "StatusResponse",
        "type": "object"
      },
      "AuthLoginRequest": {
        "description": "POST /v1/api/auth/login request body.\n\nEither username+password or token must be provided.",
        "properties": {
          "username": {
            "default": "",
            "description": "Login username",
            "title": "Username",
            "type": "string"
          },
          "password": {
            "default": "",
            "description": "Login password",
            "title": "Password",
            "type": "string"
          },
          "token": {
            "default": "",
            "description": "Legacy: bearer token to authenticate",
            "title": "Token",
            "type": "string"
          }
        },
        "title": "AuthLoginRequest",
        "type": "object"
      },
      "AuthLoginResponse": {
        "description": "POST /v1/api/auth/login success response.",
        "properties": {
          "status": {
            "default": "ok",
            "title": "Status",
            "type": "string"
          },
          "user_id": {
            "default": "",
            "description": "Authenticated user ID",
            "title": "User Id",
            "type": "string"
          },
          "role": {
            "description": "Legacy role",
            "examples": [
              "full",
              "read"
            ],
            "title": "Role",
            "type": "string"
          },
          "scopes": {
            "default": "",
            "description": "Comma-separated scopes",
            "examples": [
              "read,write,approve"
            ],
            "title": "Scopes",
            "type": "string"
          },
          "jwt": {
            "default": "",
            "description": "JWT session token (if JWT auth is configured)",
            "title": "Jwt",
            "type": "string"
          }
        },
        "required": [
          "role"
        ],
        "title": "AuthLoginResponse",
        "type": "object"
      },
      "AuthSetupRequest": {
        "description": "POST /v1/api/auth/setup request body.",
        "properties": {
          "username": {
            "description": "Login username (1-64 ASCII characters)",
            "title": "Username",
            "type": "string"
          },
          "display_name": {
            "description": "Display name",
            "title": "Display Name",
            "type": "string"
          },
          "password": {
            "description": "Password (minimum 8 characters)",
            "title": "Password",
            "type": "string"
          }
        },
        "required": [
          "username",
          "display_name",
          "password"
        ],
        "title": "AuthSetupRequest",
        "type": "object"
      },
      "AuthSetupResponse": {
        "description": "POST /v1/api/auth/setup success response.",
        "properties": {
          "status": {
            "default": "ok",
            "title": "Status",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "string"
          },
          "username": {
            "title": "Username",
            "type": "string"
          },
          "role": {
            "default": "full",
            "title": "Role",
            "type": "string"
          },
          "scopes": {
            "default": "approve,read,write",
            "title": "Scopes",
            "type": "string"
          },
          "jwt": {
            "default": "",
            "description": "JWT session token",
            "title": "Jwt",
            "type": "string"
          }
        },
        "required": [
          "user_id",
          "username"
        ],
        "title": "AuthSetupResponse",
        "type": "object"
      },
      "AuthStatusResponse": {
        "description": "GET /v1/api/auth/status response.",
        "properties": {
          "auth_enabled": {
            "title": "Auth Enabled",
            "type": "boolean"
          },
          "has_users": {
            "title": "Has Users",
            "type": "boolean"
          },
          "setup_required": {
            "title": "Setup Required",
            "type": "boolean"
          },
          "oidc_enabled": {
            "default": false,
            "title": "Oidc Enabled",
            "type": "boolean"
          },
          "oidc_provider_name": {
            "default": "",
            "title": "Oidc Provider Name",
            "type": "string"
          },
          "password_enabled": {
            "default": true,
            "title": "Password Enabled",
            "type": "boolean"
          }
        },
        "required": [
          "auth_enabled",
          "has_users",
          "setup_required"
        ],
        "title": "AuthStatusResponse",
        "type": "object"
      },
      "SendRequest": {
        "properties": {
          "message": {
            "description": "User message text",
            "title": "Message",
            "type": "string"
          },
          "attachment_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Explicit list of attachment ids to inject into this turn. When omitted, any pending attachments for the caller on this workstream are auto-consumed. An empty list disables auto-consumption for this send.",
            "title": "Attachment Ids"
          }
        },
        "required": [
          "message"
        ],
        "title": "SendRequest",
        "type": "object"
      },
      "SendResponse": {
        "properties": {
          "status": {
            "description": "'ok', 'busy', 'queued', or 'queue_full'",
            "examples": [
              "ok",
              "busy",
              "queued",
              "queue_full"
            ],
            "title": "Status",
            "type": "string"
          },
          "attached_ids": {
            "description": "Attachment ids actually reserved onto this turn. Subset of the request's `attachment_ids` (or the auto-consumed pending set). Empty when the send carries no attachments.",
            "items": {
              "type": "string"
            },
            "title": "Attached Ids",
            "type": "array"
          },
          "dropped_attachment_ids": {
            "description": "Attachment ids the caller requested that the server could not reserve (lost a race, already consumed, or cross-scope). The request still proceeds with whatever was reserved; the client can retry uploads or surface a partial-attach warning.",
            "items": {
              "type": "string"
            },
            "title": "Dropped Attachment Ids",
            "type": "array"
          },
          "priority": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Set on `queued` responses: relative priority of the queued message.",
            "title": "Priority"
          },
          "msg_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Set on `queued` responses: id used to dequeue the message.",
            "title": "Msg Id"
          }
        },
        "required": [
          "status"
        ],
        "title": "SendResponse",
        "type": "object"
      },
      "DequeueRequest": {
        "description": "Body for ``DELETE /v1/api/workstreams/{ws_id}/send``.\n\nRemoves a previously-queued message from the workstream's pending\nqueue. ``msg_id`` is the id returned in a prior ``send`` response\nwhen the workstream was busy and the message was queued.",
        "properties": {
          "msg_id": {
            "description": "Id of the queued message to remove",
            "title": "Msg Id",
            "type": "string"
          }
        },
        "required": [
          "msg_id"
        ],
        "title": "DequeueRequest",
        "type": "object"
      },
      "ApproveRequest": {
        "properties": {
          "approved": {
            "description": "True to approve, false to deny",
            "title": "Approved",
            "type": "boolean"
          },
          "feedback": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional denial reason",
            "title": "Feedback"
          },
          "always": {
            "default": false,
            "description": "Auto-approve the tools in this batch going forward",
            "title": "Always",
            "type": "boolean"
          }
        },
        "required": [
          "approved"
        ],
        "title": "ApproveRequest",
        "type": "object"
      },
      "PlanFeedbackRequest": {
        "properties": {
          "feedback": {
            "description": "Feedback text; empty string means approval",
            "title": "Feedback",
            "type": "string"
          },
          "ws_id": {
            "description": "Target workstream ID",
            "title": "Ws Id",
            "type": "string"
          }
        },
        "required": [
          "feedback",
          "ws_id"
        ],
        "title": "PlanFeedbackRequest",
        "type": "object"
      },
      "CommandRequest": {
        "properties": {
          "command": {
            "description": "Slash command (e.g. /clear, /new, /resume)",
            "title": "Command",
            "type": "string"
          },
          "ws_id": {
            "description": "Target workstream ID",
            "title": "Ws Id",
            "type": "string"
          }
        },
        "required": [
          "command",
          "ws_id"
        ],
        "title": "CommandRequest",
        "type": "object"
      },
      "CancelRequest": {
        "properties": {
          "force": {
            "default": false,
            "description": "Force cancel: abandon the stuck worker thread immediately. Use when cooperative cancel has not resolved within a few seconds.",
            "title": "Force",
            "type": "boolean"
          }
        },
        "title": "CancelRequest",
        "type": "object"
      },
      "CreateWorkstreamRequest": {
        "properties": {
          "name": {
            "default": "",
            "description": "Workstream display name (auto-generated if empty)",
            "title": "Name",
            "type": "string"
          },
          "model": {
            "default": "",
            "description": "Model alias from registry",
            "title": "Model",
            "type": "string"
          },
          "auto_approve": {
            "default": false,
            "description": "Auto-approve all tool calls",
            "title": "Auto Approve",
            "type": "boolean"
          },
          "resume_ws": {
            "default": "",
            "description": "Workstream ID to resume atomically during creation (empty = fresh start)",
            "title": "Resume Ws",
            "type": "string"
          },
          "skill": {
            "default": "",
            "description": "Skill name (replaces default skills)",
            "title": "Skill",
            "type": "string"
          },
          "notify_targets": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "items": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object"
                },
                "type": "array"
              }
            ],
            "default": "[]",
            "description": "Notification targets, accepted as either a JSON string or a structured array of objects containing channel_type + channel_id/user_id",
            "title": "Notify Targets"
          },
          "client_type": {
            "default": "",
            "description": "Client surface type (web, cli, chat). Defaults to web for server-created sessions.",
            "title": "Client Type",
            "type": "string"
          },
          "initial_message": {
            "default": "",
            "description": "Optional first user message dispatched as a background turn after the workstream is created. When attachments are also provided (via the multipart variant), they are reserved onto this turn.",
            "title": "Initial Message",
            "type": "string"
          },
          "ws_id": {
            "default": "",
            "description": "Optional caller-supplied workstream id (32-hex). Required when creating with attachments via the cluster routing layer so the console can hash to the owning node before the multipart body lands. Auto-generated when omitted.",
            "title": "Ws Id",
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/WorkstreamKind",
            "default": "interactive",
            "description": "Workstream kind \u2014 'interactive' (default) or 'coordinator'. Coordinator workstreams are created by the console's own /v1/api/workstreams/new endpoint; clients hitting /v1/api/workstreams/new should leave this at the default."
          },
          "parent_ws_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional parent workstream id. Populated on children spawned by a coordinator so the parent/child relationship survives restart and appears in audit / list views.",
            "title": "Parent Ws Id"
          }
        },
        "title": "CreateWorkstreamRequest",
        "type": "object"
      },
      "WorkstreamKind": {
        "description": "Classifier for which manager hosts a workstream.\n\nStrEnum so members are drop-in ``str`` replacements for the DB column,\nJSON payloads, and existing ``==`` comparisons against raw strings.\nNarrow internal annotations to this type; wide boundaries (HTTP body,\nDB row) stay ``str`` and parse via ``WorkstreamKind(raw)`` / ``from_raw``\nat the edge.",
        "enum": [
          "interactive",
          "coordinator"
        ],
        "title": "WorkstreamKind",
        "type": "string"
      },
      "CreateWorkstreamResponse": {
        "properties": {
          "ws_id": {
            "description": "Unique ID of the new workstream",
            "title": "Ws Id",
            "type": "string"
          },
          "name": {
            "description": "Assigned workstream name",
            "title": "Name",
            "type": "string"
          },
          "resumed": {
            "default": false,
            "description": "Whether a previous workstream was resumed",
            "title": "Resumed",
            "type": "boolean"
          },
          "message_count": {
            "default": 0,
            "description": "Number of messages in the resumed workstream",
            "title": "Message Count",
            "type": "integer"
          },
          "attachment_ids": {
            "description": "Ids of attachments saved by this request (multipart variant only). Already reserved onto the initial_message turn when one was provided; otherwise left pending for a follow-up POST /v1/api/workstreams/{ws_id}/send.",
            "items": {
              "type": "string"
            },
            "title": "Attachment Ids",
            "type": "array"
          }
        },
        "required": [
          "ws_id",
          "name"
        ],
        "title": "CreateWorkstreamResponse",
        "type": "object"
      },
      "CloseWorkstreamRequest": {
        "description": "Body for ``POST /v1/api/workstreams/{ws_id}/close``.\n\nThe body must be valid JSON; send ``{}`` when omitting all\nfields. Pre-1.5 the model also carried a body-keyed ``ws_id``;\n1.5 moved that to the path so the body shrinks to the optional\n``reason``. Coord ignores the body entirely (its close handler\nis wired ``supports_close_reason=False``).",
        "properties": {
          "reason": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional close reason persisted to ``workstream_config`` for postmortem. Capped at 512 UTF-8 bytes server-side; credential-redaction is applied via the output guard.",
            "title": "Reason"
          }
        },
        "title": "CloseWorkstreamRequest",
        "type": "object"
      },
      "ListWorkstreamsResponse": {
        "description": "Response body for ``GET /v1/api/workstreams`` on either kind.\n\nTop-level key is ``workstreams`` regardless of the kind serving\nthe request \u2014 pre-lift coord returned ``{\"coordinators\": [...]}``;\nconvergence lifted both kinds onto the same shape. Coord SDK /\nfrontend consumers branching on ``data.coordinators`` swap to\n``data.workstreams``.",
        "properties": {
          "workstreams": {
            "items": {
              "$ref": "#/components/schemas/WorkstreamInfo"
            },
            "title": "Workstreams",
            "type": "array"
          }
        },
        "required": [
          "workstreams"
        ],
        "title": "ListWorkstreamsResponse",
        "type": "object"
      },
      "WorkstreamInfo": {
        "description": "Active-list row shape, shared across both kinds.\n\nRenamed ``id`` \u2192 ``ws_id`` and added ``user_id`` in the Stage 2\n``list``/``saved`` verb lift so the active-list response shape\nmatches the rest of the v1 surface (every other shared verb's\npayload uses ``ws_id``). ``user_id`` was previously coord-only;\ninteractive now populates it too. SDK consumers reading\n``row.id`` should swap to ``row.ws_id``.",
        "properties": {
          "ws_id": {
            "title": "Ws Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "state": {
            "title": "State",
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/WorkstreamKind",
            "default": "interactive"
          },
          "parent_ws_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Parent Ws Id"
          },
          "user_id": {
            "default": "",
            "title": "User Id",
            "type": "string"
          }
        },
        "required": [
          "ws_id",
          "name",
          "state"
        ],
        "title": "WorkstreamInfo",
        "type": "object"
      },
      "WorkstreamDetailResponse": {
        "description": "Response body for ``GET /v1/api/workstreams/{ws_id}``.\n\nRenamed and relocated from ``CoordinatorDetailResponse`` in the\nStage 2 history/detail verb lift. Both kinds populate every field;\nSDK consumers don't branch on kind to read them. The lift adds the\nendpoint to interactive as a feature gain (pre-lift only coord\nexposed it).",
        "properties": {
          "ws_id": {
            "title": "Ws Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "state": {
            "title": "State",
            "type": "string"
          },
          "user_id": {
            "title": "User Id",
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/WorkstreamKind",
            "default": "interactive"
          }
        },
        "required": [
          "ws_id",
          "name",
          "state",
          "user_id"
        ],
        "title": "WorkstreamDetailResponse",
        "type": "object"
      },
      "WorkstreamHistoryResponse": {
        "description": "Response body for ``GET /v1/api/workstreams/{ws_id}/history``.\n\nRenamed and relocated from ``CoordinatorHistoryResponse`` in the\nStage 2 history/detail verb lift. Same OpenAI-like message-row\nshape on both kinds; the lift adds the endpoint to interactive as\na feature gain (pre-lift interactive only exposed history through\nthe SSE replay on ``/events``).",
        "properties": {
          "ws_id": {
            "title": "Ws Id",
            "type": "string"
          },
          "messages": {
            "description": "Tail of the workstream's reconstructed message history (provider-fidelity OpenAI-like shape). Bounded by the ``limit`` query parameter (default 100, max 500).",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Messages",
            "type": "array"
          }
        },
        "required": [
          "ws_id"
        ],
        "title": "WorkstreamHistoryResponse",
        "type": "object"
      },
      "DashboardResponse": {
        "properties": {
          "workstreams": {
            "items": {
              "$ref": "#/components/schemas/DashboardWorkstream"
            },
            "title": "Workstreams",
            "type": "array"
          },
          "aggregate": {
            "$ref": "#/components/schemas/DashboardAggregate"
          }
        },
        "required": [
          "workstreams",
          "aggregate"
        ],
        "title": "DashboardResponse",
        "type": "object"
      },
      "DashboardAggregate": {
        "properties": {
          "total_tokens": {
            "default": 0,
            "title": "Total Tokens",
            "type": "integer"
          },
          "total_tool_calls": {
            "default": 0,
            "title": "Total Tool Calls",
            "type": "integer"
          },
          "active_count": {
            "default": 0,
            "title": "Active Count",
            "type": "integer"
          },
          "total_count": {
            "default": 0,
            "title": "Total Count",
            "type": "integer"
          },
          "uptime_seconds": {
            "default": 0,
            "title": "Uptime Seconds",
            "type": "integer"
          },
          "node": {
            "default": "local",
            "title": "Node",
            "type": "string"
          }
        },
        "title": "DashboardAggregate",
        "type": "object"
      },
      "DashboardWorkstream": {
        "description": "Dashboard row shape for ``GET /v1/api/dashboard``.\n\nRenamed ``id`` \u2192 ``ws_id`` for v1 row-shape consistency with\nthe rest of the workstream surface (active list, saved list,\nhistory, detail, etc.). Frontend consumers reading\n``dashboard.workstreams[].id`` swap to ``.ws_id``.",
        "properties": {
          "ws_id": {
            "title": "Ws Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "state": {
            "title": "State",
            "type": "string"
          },
          "title": {
            "default": "",
            "title": "Title",
            "type": "string"
          },
          "tokens": {
            "default": 0,
            "title": "Tokens",
            "type": "integer"
          },
          "context_ratio": {
            "default": 0.0,
            "title": "Context Ratio",
            "type": "number"
          },
          "activity": {
            "default": "",
            "title": "Activity",
            "type": "string"
          },
          "activity_state": {
            "default": "",
            "title": "Activity State",
            "type": "string"
          },
          "tool_calls": {
            "default": 0,
            "title": "Tool Calls",
            "type": "integer"
          },
          "node": {
            "default": "",
            "title": "Node",
            "type": "string"
          },
          "model": {
            "default": "",
            "title": "Model",
            "type": "string"
          },
          "model_alias": {
            "default": "",
            "title": "Model Alias",
            "type": "string"
          },
          "kind": {
            "$ref": "#/components/schemas/WorkstreamKind",
            "default": "interactive"
          },
          "parent_ws_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Parent Ws Id"
          },
          "user_id": {
            "default": "",
            "title": "User Id",
            "type": "string"
          },
          "pending_approval_detail": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PendingApprovalDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Inline approval payload for the coordinator children-tree UI. Carries the merged ``_pending_approval`` items list + per-call_id LLM verdict cache so a coord can render approve/deny buttons + judge pill without a separate per-child round-trip. ``None`` when no approval is pending. Also surfaced (verbatim) on ``GET /v1/api/cluster/ws/live`` via the ``_CLUSTER_WS_LIVE_KEYS`` projection."
          },
          "recent_auto_approvals": {
            "description": "Per-ws ring buffer (cap 10) of recent tool calls that bypassed the operator approval gate. Surfaces ``WebUI._recent_auto_approvals`` so the coord-tree row can render an 'auto-approved by ...' pill when the child's skill / blanket / admin-policy rules silently let a tool through. Also projected onto ``GET /v1/api/cluster/ws/live`` via ``_CLUSTER_WS_LIVE_KEYS``.",
            "items": {
              "$ref": "#/components/schemas/RecentAutoApproval"
            },
            "title": "Recent Auto Approvals",
            "type": "array"
          }
        },
        "required": [
          "ws_id",
          "name",
          "state"
        ],
        "title": "DashboardWorkstream",
        "type": "object"
      },
      "PendingApprovalDetail": {
        "description": "Inline approval payload merged into ``DashboardWorkstream``.\n\nSet when a workstream's ``approve_tools`` is parked on\n``_approval_event``; ``None`` (omitted) otherwise. Cross-tenant\nexposure here follows the same trusted-team posture as\n``activity`` / ``tokens`` \u2014 see ``server.py``'s ``dashboard``\nhandler comment.",
        "properties": {
          "call_id": {
            "default": "",
            "description": "Primary call_id \u2014 first non-empty call_id in items list order. Matches the 409 ``current_call_id`` response from ``POST /v1/api/workstreams/{ws_id}/approve`` so the UI can render the same identifier the server reports as current.",
            "title": "Call Id",
            "type": "string"
          },
          "judge_pending": {
            "default": false,
            "description": "LLM judge tier still running; heuristic verdicts may already be present on items.",
            "title": "Judge Pending",
            "type": "boolean"
          },
          "items": {
            "items": {
              "$ref": "#/components/schemas/PendingApprovalItem"
            },
            "title": "Items",
            "type": "array"
          }
        },
        "title": "PendingApprovalDetail",
        "type": "object"
      },
      "PendingApprovalItem": {
        "description": "One pending tool-call inside a ``PendingApprovalDetail`` envelope.\n\nMirrors the dict ``SessionUIBase.serialize_pending_approval_detail``\nemits per item. ``heuristic_verdict`` / ``judge_verdict`` are kept\nloosely-typed because the underlying verdict shape varies by tier;\nconsumers that want the full structure can decode against\n:class:`turnstone.sdk.events.IntentVerdictEvent`.",
        "properties": {
          "call_id": {
            "default": "",
            "title": "Call Id",
            "type": "string"
          },
          "header": {
            "default": "",
            "title": "Header",
            "type": "string"
          },
          "preview": {
            "default": "",
            "title": "Preview",
            "type": "string"
          },
          "func_name": {
            "default": "",
            "title": "Func Name",
            "type": "string"
          },
          "approval_label": {
            "default": "",
            "title": "Approval Label",
            "type": "string"
          },
          "needs_approval": {
            "default": false,
            "title": "Needs Approval",
            "type": "boolean"
          },
          "error": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Error"
          },
          "heuristic_verdict": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Heuristic Verdict"
          },
          "judge_verdict": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Judge Verdict"
          }
        },
        "title": "PendingApprovalItem",
        "type": "object"
      },
      "RecentAutoApproval": {
        "description": "One ring-buffer entry for ``DashboardWorkstream.recent_auto_approvals``.\n\nRecords a tool call that bypassed the operator approval gate\n(admin tool policy / skill ``allowed_tools`` allowlist / blanket\n``auto_approve`` / \"Approve + Always\" memory).  The coord-tree\npill reads this list to surface \"auto-approved by skill X\" so\nthe operator can see WHICH calls bypassed and WHY.",
        "properties": {
          "call_id": {
            "default": "",
            "title": "Call Id",
            "type": "string"
          },
          "func_name": {
            "default": "",
            "title": "Func Name",
            "type": "string"
          },
          "approval_label": {
            "default": "",
            "title": "Approval Label",
            "type": "string"
          },
          "auto_approve_reason": {
            "default": "",
            "description": "Source that fired the bypass.  ``skill`` (skill template's ``allowed_tools``), ``always`` (user 'Approve + Always' click), ``policy`` (admin tool-policy ``allow`` rule), ``blanket`` (workstream-level ``auto_approve=True``), or ``auto_approve_tools`` (legacy / unknown writer).",
            "title": "Auto Approve Reason",
            "type": "string"
          },
          "ts": {
            "default": 0.0,
            "description": "Unix epoch seconds when the auto-approve fired.",
            "title": "Ts",
            "type": "number"
          }
        },
        "title": "RecentAutoApproval",
        "type": "object"
      },
      "ListSavedWorkstreamsResponse": {
        "properties": {
          "workstreams": {
            "items": {
              "$ref": "#/components/schemas/SavedWorkstreamInfo"
            },
            "title": "Workstreams",
            "type": "array"
          }
        },
        "required": [
          "workstreams"
        ],
        "title": "ListSavedWorkstreamsResponse",
        "type": "object"
      },
      "SavedWorkstreamInfo": {
        "properties": {
          "ws_id": {
            "title": "Ws Id",
            "type": "string"
          },
          "alias": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Alias"
          },
          "title": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Title"
          },
          "created": {
            "title": "Created",
            "type": "string"
          },
          "updated": {
            "title": "Updated",
            "type": "string"
          },
          "message_count": {
            "title": "Message Count",
            "type": "integer"
          }
        },
        "required": [
          "ws_id",
          "created",
          "updated",
          "message_count"
        ],
        "title": "SavedWorkstreamInfo",
        "type": "object"
      },
      "UploadAttachmentResponse": {
        "description": "Returned after a successful upload.",
        "properties": {
          "attachment_id": {
            "description": "Opaque id for this attachment",
            "title": "Attachment Id",
            "type": "string"
          },
          "filename": {
            "description": "Original upload filename",
            "title": "Filename",
            "type": "string"
          },
          "mime_type": {
            "description": "Canonicalized MIME type",
            "title": "Mime Type",
            "type": "string"
          },
          "size_bytes": {
            "description": "Payload size in bytes",
            "title": "Size Bytes",
            "type": "integer"
          },
          "kind": {
            "description": "'image' or 'text'",
            "examples": [
              "image",
              "text"
            ],
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "attachment_id",
          "filename",
          "mime_type",
          "size_bytes",
          "kind"
        ],
        "title": "UploadAttachmentResponse",
        "type": "object"
      },
      "ListAttachmentsResponse": {
        "properties": {
          "attachments": {
            "description": "Pending (unconsumed) attachments for caller+workstream",
            "items": {
              "$ref": "#/components/schemas/AttachmentInfo"
            },
            "title": "Attachments",
            "type": "array"
          }
        },
        "required": [
          "attachments"
        ],
        "title": "ListAttachmentsResponse",
        "type": "object"
      },
      "AttachmentInfo": {
        "properties": {
          "attachment_id": {
            "description": "Opaque id for this attachment",
            "title": "Attachment Id",
            "type": "string"
          },
          "filename": {
            "description": "Original upload filename",
            "title": "Filename",
            "type": "string"
          },
          "mime_type": {
            "description": "Canonicalized MIME type",
            "title": "Mime Type",
            "type": "string"
          },
          "size_bytes": {
            "description": "Payload size in bytes",
            "title": "Size Bytes",
            "type": "integer"
          },
          "kind": {
            "description": "'image' or 'text'",
            "examples": [
              "image",
              "text"
            ],
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "attachment_id",
          "filename",
          "mime_type",
          "size_bytes",
          "kind"
        ],
        "title": "AttachmentInfo",
        "type": "object"
      },
      "HealthResponse": {
        "properties": {
          "status": {
            "examples": [
              "ok",
              "degraded"
            ],
            "title": "Status",
            "type": "string"
          },
          "version": {
            "default": "",
            "title": "Version",
            "type": "string"
          },
          "node_id": {
            "default": "",
            "title": "Node Id",
            "type": "string"
          },
          "uptime_seconds": {
            "default": 0.0,
            "title": "Uptime Seconds",
            "type": "number"
          },
          "model": {
            "default": "",
            "title": "Model",
            "type": "string"
          },
          "max_ws": {
            "default": 10,
            "description": "Maximum concurrent workstreams",
            "title": "Max Ws",
            "type": "integer"
          },
          "workstreams": {
            "$ref": "#/components/schemas/WorkstreamCounts",
            "default": {
              "total": 0,
              "idle": 0,
              "thinking": 0,
              "running": 0,
              "attention": 0,
              "error": 0
            }
          },
          "backend": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BackendStatus"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "mcp": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/McpStatus"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          }
        },
        "required": [
          "status"
        ],
        "title": "HealthResponse",
        "type": "object"
      },
      "BackendStatus": {
        "properties": {
          "status": {
            "examples": [
              "up",
              "down"
            ],
            "title": "Status",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "title": "BackendStatus",
        "type": "object"
      },
      "McpStatus": {
        "properties": {
          "servers": {
            "default": 0,
            "title": "Servers",
            "type": "integer"
          },
          "resources": {
            "default": 0,
            "title": "Resources",
            "type": "integer"
          },
          "prompts": {
            "default": 0,
            "title": "Prompts",
            "type": "integer"
          }
        },
        "title": "McpStatus",
        "type": "object"
      },
      "WorkstreamCounts": {
        "properties": {
          "total": {
            "default": 0,
            "title": "Total",
            "type": "integer"
          },
          "idle": {
            "default": 0,
            "title": "Idle",
            "type": "integer"
          },
          "thinking": {
            "default": 0,
            "title": "Thinking",
            "type": "integer"
          },
          "running": {
            "default": 0,
            "title": "Running",
            "type": "integer"
          },
          "attention": {
            "default": 0,
            "title": "Attention",
            "type": "integer"
          },
          "error": {
            "default": 0,
            "title": "Error",
            "type": "integer"
          }
        },
        "title": "WorkstreamCounts",
        "type": "object"
      },
      "SaveMemoryRequest": {
        "properties": {
          "name": {
            "description": "Memory identifier (normalized to snake_case)",
            "title": "Name",
            "type": "string"
          },
          "content": {
            "description": "Memory content",
            "maxLength": 65536,
            "title": "Content",
            "type": "string"
          },
          "description": {
            "default": "",
            "description": "Short description for relevance matching",
            "title": "Description",
            "type": "string"
          },
          "type": {
            "default": "project",
            "description": "Memory type",
            "enum": [
              "user",
              "project",
              "feedback",
              "reference"
            ],
            "title": "Type",
            "type": "string"
          },
          "scope": {
            "default": "global",
            "description": "Memory scope",
            "enum": [
              "global",
              "workstream",
              "user"
            ],
            "title": "Scope",
            "type": "string"
          },
          "scope_id": {
            "default": "",
            "description": "Scope identifier (ws_id for workstream, user_id for user scope)",
            "title": "Scope Id",
            "type": "string"
          }
        },
        "required": [
          "name",
          "content"
        ],
        "title": "SaveMemoryRequest",
        "type": "object"
      },
      "MemoryInfo": {
        "properties": {
          "memory_id": {
            "title": "Memory Id",
            "type": "string"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "description": {
            "default": "",
            "title": "Description",
            "type": "string"
          },
          "type": {
            "enum": [
              "user",
              "project",
              "feedback",
              "reference"
            ],
            "title": "Type",
            "type": "string"
          },
          "scope": {
            "enum": [
              "global",
              "workstream",
              "user"
            ],
            "title": "Scope",
            "type": "string"
          },
          "scope_id": {
            "default": "",
            "title": "Scope Id",
            "type": "string"
          },
          "content": {
            "title": "Content",
            "type": "string"
          },
          "created": {
            "title": "Created",
            "type": "string"
          },
          "updated": {
            "title": "Updated",
            "type": "string"
          }
        },
        "required": [
          "memory_id",
          "name",
          "type",
          "scope",
          "content",
          "created",
          "updated"
        ],
        "title": "MemoryInfo",
        "type": "object"
      },
      "ListMemoriesResponse": {
        "properties": {
          "memories": {
            "items": {
              "$ref": "#/components/schemas/MemoryInfo"
            },
            "title": "Memories",
            "type": "array"
          },
          "total": {
            "default": 0,
            "title": "Total",
            "type": "integer"
          }
        },
        "required": [
          "memories"
        ],
        "title": "ListMemoriesResponse",
        "type": "object"
      },
      "SearchMemoriesRequest": {
        "properties": {
          "query": {
            "description": "Search query text",
            "title": "Query",
            "type": "string"
          },
          "type": {
            "default": "",
            "description": "Filter by memory type",
            "enum": [
              "",
              "user",
              "project",
              "feedback",
              "reference"
            ],
            "title": "Type",
            "type": "string"
          },
          "scope": {
            "default": "",
            "description": "Filter by scope",
            "enum": [
              "",
              "global",
              "workstream",
              "user"
            ],
            "title": "Scope",
            "type": "string"
          },
          "scope_id": {
            "default": "",
            "description": "Filter by scope_id",
            "title": "Scope Id",
            "type": "string"
          },
          "limit": {
            "default": 20,
            "description": "Max results (1-50)",
            "maximum": 50,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          }
        },
        "required": [
          "query"
        ],
        "title": "SearchMemoriesRequest",
        "type": "object"
      },
      "SkillSummary": {
        "properties": {
          "name": {
            "description": "Skill name",
            "title": "Name",
            "type": "string"
          },
          "category": {
            "default": "",
            "description": "Skill category",
            "title": "Category",
            "type": "string"
          },
          "description": {
            "default": "",
            "description": "Skill description for discovery",
            "title": "Description",
            "type": "string"
          },
          "tags": {
            "description": "Semantic tags",
            "items": {
              "type": "string"
            },
            "title": "Tags",
            "type": "array"
          },
          "is_default": {
            "default": false,
            "description": "Whether auto-applied to all sessions",
            "title": "Is Default",
            "type": "boolean"
          },
          "activation": {
            "default": "named",
            "description": "Activation mode: default, named, search",
            "title": "Activation",
            "type": "string"
          },
          "origin": {
            "default": "manual",
            "description": "Source: manual, mcp, skills.sh, github",
            "title": "Origin",
            "type": "string"
          },
          "author": {
            "default": "",
            "description": "Skill author",
            "title": "Author",
            "type": "string"
          },
          "version": {
            "default": "1.0.0",
            "description": "Skill version",
            "title": "Version",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "SkillSummary",
        "type": "object"
      },
      "ListSkillSummaryResponse": {
        "properties": {
          "skills": {
            "items": {
              "$ref": "#/components/schemas/SkillSummary"
            },
            "title": "Skills",
            "type": "array"
          }
        },
        "required": [
          "skills"
        ],
        "title": "ListSkillSummaryResponse",
        "type": "object"
      },
      "AvailableModelInfo": {
        "properties": {
          "alias": {
            "title": "Alias",
            "type": "string"
          },
          "model": {
            "title": "Model",
            "type": "string"
          },
          "provider": {
            "title": "Provider",
            "type": "string"
          }
        },
        "required": [
          "alias",
          "model",
          "provider"
        ],
        "title": "AvailableModelInfo",
        "type": "object"
      },
      "ListAvailableModelsResponse": {
        "properties": {
          "models": {
            "items": {
              "$ref": "#/components/schemas/AvailableModelInfo"
            },
            "title": "Models",
            "type": "array"
          },
          "default_alias": {
            "default": "",
            "title": "Default Alias",
            "type": "string"
          },
          "channel_default_alias": {
            "default": "",
            "title": "Channel Default Alias",
            "type": "string"
          }
        },
        "title": "ListAvailableModelsResponse",
        "type": "object"
      }
    }
  }
}
