openapi: "3.1.0"
info:
  title: Fabro Run API
  version: "0.1.0"
  description: HTTP API for managing Fabro workflow run executions.

tags:
  - name: Discovery
    description: API discovery and health
  - name: Runs
    description: Run management operations
  - name: Human-in-the-Loop
    description: Questions, answers, and steering for runs
  - name: Run Outputs
    description: Files and verifications produced by runs
  - name: Run Internals
    description: Internal run details (stages, turns, context, configuration)
  - name: Workflows
    description: Workflow definitions and execution
  - name: Verification
    description: Verification criteria and controls
  - name: Usage
    description: Token and cost usage
  - name: Insights
    description: SQL query editor and history
  - name: Sessions
    description: Interactive chat sessions
  - name: Retros
    description: Run retrospectives
  - name: Models
    description: Available LLM models
  - name: Completions
    description: Single-turn LLM completions
  - name: Settings
    description: Platform configuration

security:
  - BearerAuth: []
  - mTLS: []

paths:
  # ── Discovery ────────────────────────────────────────────────────────

  /:
    get:
      operationId: getRoot
      tags: [Discovery]
      summary: API Discovery
      description: Returns discovery URLs for the API.
      security: []
      responses:
        "200":
          description: Discovery URLs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RootResponse"

  /health:
    get:
      operationId: getHealth
      tags: [Discovery]
      summary: Health Check
      description: Returns service health status. Used by load balancers and monitoring.
      security: []
      responses:
        "200":
          description: Service is healthy
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/HealthResponse"

  /openapi.json:
    get:
      operationId: getOpenApiSpec
      tags: [Discovery]
      summary: OpenAPI Specification
      description: Returns the OpenAPI spec as JSON.
      security: []
      responses:
        "200":
          description: OpenAPI specification
          content:
            application/json:
              schema:
                type: object

  /user:
    get:
      operationId: getUser
      tags: [Discovery]
      summary: Current User
      description: Returns info about the authenticated user.
      responses:
        "200":
          description: User info
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/UserResponse"
        "401":
          description: Not authenticated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Runs ──────────────────────────────────────────────────────────────

  /runs:
    get:
      operationId: listRuns
      tags: [Runs]
      summary: List Runs
      description: Returns a paginated list of runs for the board view, ordered by recency.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of runs for the board view
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedRunList"
    post:
      operationId: startRun
      tags: [Runs]
      summary: Start Run
      description: Queues a new workflow run from a Graphviz graph source. The run is created in `queued` status and will be picked up by the scheduler.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/StartRunRequest"
      responses:
        "201":
          description: Run created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunStatusResponse"
        "400":
          description: Invalid Graphviz source
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}:
    get:
      operationId: retrieveRun
      tags: [Runs]
      summary: Retrieve Run
      description: Returns the current status of a run, including error details and queue position if applicable.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Run status
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunStatusResponse"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/cancel:
    post:
      operationId: cancelRun
      tags: [Runs]
      summary: Cancel Run
      description: Cancels a running or queued run. Returns 409 if the run has already completed or been cancelled.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Run cancelled
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunStatusResponse"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Run is not running
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/pause:
    post:
      operationId: pauseRun
      tags: [Runs]
      summary: Pause Run
      description: Pauses a running run. Returns 409 if the run is not running.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Run paused
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunStatusResponse"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Run is not running
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/unpause:
    post:
      operationId: unpauseRun
      tags: [Runs]
      summary: Unpause Run
      description: Resumes a paused run. Returns 409 if the run is not paused.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Run unpaused
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunStatusResponse"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Run is not paused
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/graph:
    get:
      operationId: retrieveRunGraph
      tags: [Runs]
      summary: Render SVG
      description: Renders the workflow graph as an SVG image using Graphviz.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: SVG image of the workflow graph
          content:
            image/svg+xml:
              schema:
                type: string
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "502":
          description: Graphviz not available
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/checkpoint:
    get:
      operationId: retrieveRunCheckpoint
      tags: [Run Internals]
      summary: Retrieve Run Checkpoint
      description: Returns the latest checkpoint data for a run, or null if no checkpoint has been recorded yet.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Checkpoint data (null if not yet available)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/RunCheckpoint"
                  - type: "null"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/context:
    get:
      operationId: retrieveRunContext
      tags: [Run Internals]
      summary: Retrieve Run Context
      description: Returns the key-value context map accumulated during the run. Empty if the run has not started.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Context key-value map
          content:
            application/json:
              schema:
                type: object
                additionalProperties: true
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/events:
    get:
      operationId: streamRunEvents
      tags: [Runs]
      summary: Stream Run Events
      description: Opens a server-sent event (SSE) stream for real-time run updates. Returns 410 if the stream has been closed.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Server-sent event stream
          content:
            text/event-stream:
              schema:
                type: string
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "410":
          description: Event stream closed
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/questions:
    get:
      operationId: listRunQuestions
      tags: [Human-in-the-Loop]
      summary: List Run Questions
      description: Returns pending human-in-the-loop questions for a run. Questions are generated when the workflow needs user input to proceed.
      parameters:
        - $ref: "#/components/parameters/RunId"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Array of pending questions
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedApiQuestionList"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/questions/{qid}/answer:
    post:
      operationId: submitRunAnswer
      tags: [Human-in-the-Loop]
      summary: Submit Run Answer
      description: Submits an answer to a pending question. The answer can be freeform text or a selected option key, depending on the question type.
      parameters:
        - $ref: "#/components/parameters/RunId"
        - $ref: "#/components/parameters/QuestionId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SubmitAnswerRequest"
      responses:
        "204":
          description: Answer accepted
        "400":
          description: Invalid option key
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Question no longer exists or already answered
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/retro:
    get:
      operationId: retrieveRetro
      tags: [Retros]
      summary: Retrieve Retro
      description: Returns the retrospective analysis for a completed run, or null if the retro has not been generated yet.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Retro data (null if not yet available)
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: "#/components/schemas/RetroDetail"
                  - type: "null"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/stages:
    get:
      operationId: listRunStages
      tags: [Run Internals]
      summary: List Run Stages
      description: Returns the ordered list of stages in a run's workflow graph with their current status and timing. Stages are bounded by the workflow graph size, typically fewer than 20.
      parameters:
        - $ref: "#/components/parameters/RunId"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Array of run stages
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedRunStageList"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/stages/{stageId}/turns:
    get:
      operationId: listStageTurns
      tags: [Run Internals]
      summary: List Stage Turns
      description: Returns a paginated list of conversation turns within a specific stage, including system prompts, assistant responses, and tool invocations.
      parameters:
        - $ref: "#/components/parameters/RunId"
        - $ref: "#/components/parameters/StageId"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of conversation turns
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedStageTurnList"
        "404":
          description: Run or stage not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/files:
    get:
      operationId: retrieveRunFiles
      tags: [Run Outputs]
      summary: Retrieve Run Files
      description: Returns a paginated list of file-level diffs produced by the run, optionally filtered to a specific checkpoint.
      parameters:
        - $ref: "#/components/parameters/RunId"
        - $ref: "#/components/parameters/CheckpointFilter"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of file diffs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedRunFileList"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/usage:
    get:
      operationId: retrieveRunUsage
      tags: [Run Outputs]
      summary: Retrieve Run Usage
      description: Returns token and cost usage broken down by stage and model for a specific run.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Usage data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunUsage"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/verification:
    get:
      operationId: retrieveRunVerification
      tags: [Run Outputs]
      summary: Retrieve Run Verification
      description: Returns verification results for a run, organized by criterion with individual control statuses.
      parameters:
        - $ref: "#/components/parameters/RunId"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Array of verification criteria with controls
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedRunVerificationList"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/configuration:
    get:
      operationId: retrieveRunConfiguration
      tags: [Run Internals]
      summary: Retrieve Run Configuration
      description: Returns the structured configuration used to launch this run.
      parameters:
        - $ref: "#/components/parameters/RunId"
      responses:
        "200":
          description: Run configuration
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/RunConfiguration"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/steer:
    post:
      operationId: steerRun
      tags: [Human-in-the-Loop]
      summary: Steer Run
      description: Sends inline guidance to a running agent, targeting a specific file and line. The guidance is delivered asynchronously.
      parameters:
        - $ref: "#/components/parameters/RunId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SteerRequest"
      responses:
        "202":
          description: Steering accepted for processing
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Run is not in a steerable state
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /runs/{id}/preview:
    post:
      operationId: generatePreviewUrl
      tags: [Human-in-the-Loop]
      summary: Preview URL
      description: Generates a time-limited preview URL for a port exposed by the run's sandbox environment.
      parameters:
        - $ref: "#/components/parameters/RunId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/PreviewUrlRequest"
      responses:
        "201":
          description: Preview URL created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PreviewUrlResponse"
        "404":
          description: Run not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
        "409":
          description: Run has no active sandbox
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Workflows ─────────────────────────────────────────────────────────

  /workflows:
    get:
      operationId: listWorkflows
      tags: [Workflows]
      summary: List Workflows
      description: Returns a paginated list of workflow definitions available for execution.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of workflows
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedWorkflowList"

  /workflows/{name}:
    get:
      operationId: retrieveWorkflow
      tags: [Workflows]
      summary: Retrieve Workflow
      description: Returns the full detail of a workflow including its Graphviz graph, TOML config, and description.
      parameters:
        - $ref: "#/components/parameters/WorkflowName"
      responses:
        "200":
          description: Workflow detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/WorkflowDetail"
        "404":
          description: Workflow not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /workflows/{name}/runs:
    get:
      operationId: listWorkflowRuns
      tags: [Workflows]
      summary: List Workflow Runs
      description: Returns a paginated list of runs filtered to a specific workflow.
      parameters:
        - $ref: "#/components/parameters/WorkflowName"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of runs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedRunList"
        "404":
          description: Workflow not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Verification ──────────────────────────────────────────────────────

  /verification/criteria:
    get:
      operationId: listVerificationCriteria
      tags: [Verification]
      summary: List Verification Criteria
      description: Returns paginated verification criteria with their controls and performance metrics. Each criterion contains controls; retrieve a specific control via `/verification/controls/{id}`.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Array of verification criteria
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedVerificationCriterionList"

  /verification/criteria/{id}:
    get:
      operationId: retrieveVerificationCriterion
      tags: [Verification]
      summary: Retrieve Verification Criterion
      description: Returns a specific verification criterion with its controls and performance metrics.
      parameters:
        - $ref: "#/components/parameters/CriterionId"
      responses:
        "200":
          description: Verification criterion detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VerificationCriterionDetail"
        "404":
          description: Criterion not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /verification/controls:
    get:
      operationId: listVerificationControls
      tags: [Verification]
      summary: List Verification Controls
      description: Returns a flat paginated list of all verification controls across all criteria.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Array of verification controls
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedVerificationControlList"

  /verification/controls/{id}:
    get:
      operationId: retrieveVerificationControl
      tags: [Verification]
      summary: Retrieve Verification Control
      description: Returns detailed information about a specific verification control, including performance data, recent results, and sibling controls in the same criterion.
      parameters:
        - $ref: "#/components/parameters/ControlId"
      responses:
        "200":
          description: Verification control detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/VerificationDetailResponse"
        "404":
          description: Control not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /verification/signoffs:
    get:
      operationId: listSignoffs
      tags: [Verification]
      summary: List Signoffs
      description: Returns a paginated list of signoffs, optionally filtered by control, repository, and/or commit SHA.
      parameters:
        - $ref: "#/components/parameters/SignoffControlFilter"
        - $ref: "#/components/parameters/SignoffRepositoryFilter"
        - $ref: "#/components/parameters/SignoffCommitShaFilter"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of signoffs
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedSignoffList"
    post:
      operationId: createSignoff
      tags: [Verification]
      summary: Create Signoff
      description: Creates a new signoff for a (control, repository, commit SHA) tuple. Multiple signoffs are allowed per tuple; the latest one wins for display purposes.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSignoffRequest"
      responses:
        "201":
          description: Signoff created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Signoff"
        "400":
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /verification/signoffs/{id}:
    get:
      operationId: retrieveSignoff
      tags: [Verification]
      summary: Retrieve Signoff
      description: Returns a specific signoff by ID.
      parameters:
        - $ref: "#/components/parameters/SignoffId"
      responses:
        "200":
          description: Signoff detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Signoff"
        "404":
          description: Signoff not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Retros ────────────────────────────────────────────────────────────

  /retros:
    get:
      operationId: listRetros
      tags: [Retros]
      summary: List Retros
      description: Returns a paginated list of run retrospectives ordered by recency, with smoothness ratings and summary statistics.
      parameters:
        - $ref: "#/components/parameters/RetroWorkflowFilter"
        - $ref: "#/components/parameters/RetroSmoothnessFilter"
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of retros
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedRetroList"

  # ── Sessions ──────────────────────────────────────────────────────────

  /sessions:
    get:
      operationId: listSessions
      tags: [Sessions]
      summary: List Sessions
      description: Returns sessions ordered by recency (newest first).
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of sessions
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedSessionList"
    post:
      operationId: createSession
      tags: [Sessions]
      summary: Create Session
      description: Start a new interactive chat session. The initial user prompt is required; a model may optionally be specified.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateSessionRequest"
      responses:
        "201":
          description: Session created
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CreateSessionResponse"

  /sessions/{id}:
    get:
      operationId: retrieveSession
      tags: [Sessions]
      summary: Retrieve Session
      description: Returns the full session detail including all conversation turns.
      parameters:
        - $ref: "#/components/parameters/SessionId"
      responses:
        "200":
          description: Session detail
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SessionDetail"
        "404":
          description: Session not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /sessions/{id}/messages:
    post:
      operationId: sendSessionMessage
      tags: [Sessions]
      summary: Send Session Message
      description: Append a user message to an existing session. The server will process it and produce assistant and tool turns asynchronously via the event stream.
      parameters:
        - $ref: "#/components/parameters/SessionId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SendMessageRequest"
      responses:
        "202":
          description: Message accepted for processing
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SendMessageResponse"
        "404":
          description: Session not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /sessions/{id}/events:
    get:
      operationId: streamSessionEvents
      tags: [Sessions]
      summary: Stream Session Events
      description: |
        Opens a server-sent event (SSE) stream for real-time session updates.

        Each SSE frame includes a sequential numeric `id:` field that supports
        resumption via the `Last-Event-ID` request header.

        The stream emits the following SSE event types:

        - `event: content_delta` — data: `{"delta": "..."}` (incremental text chunk)
        - `event: assistant_turn` — data: `AssistantTurn` JSON object
        - `event: tool_turn` — data: `ToolTurn` JSON object
        - `event: done` — data: `{}` (stream complete)
        - `event: error` — data: `{"message": "..."}` (error occurred)

        Each SSE frame has an `id:` line (sequential integer), an `event:` line (the event type),
        and a `data:` line (the JSON payload).
      parameters:
        - $ref: "#/components/parameters/SessionId"
        - name: Last-Event-ID
          in: header
          required: false
          description: >
            SSE reconnection header. When provided, the server resumes the
            stream after the event with this ID. IDs are 0-based sequential
            integers assigned to each emitted SSE frame.
          schema:
            type: string
      responses:
        "200":
          description: Server-sent event stream
          content:
            text/event-stream:
              schema:
                type: string
        "404":
          description: Session not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Insights ──────────────────────────────────────────────────────────

  /insights/queries:
    get:
      operationId: listSavedQueries
      tags: [Insights]
      summary: List Saved Queries
      description: Returns a paginated list of saved SQL queries for the insights editor.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of saved queries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedSavedQueryList"
    post:
      operationId: createSavedQuery
      tags: [Insights]
      summary: Create Saved Query
      description: Saves a new named SQL query for later reuse.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SaveQueryRequest"
      responses:
        "201":
          description: Query saved
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SavedQuery"

  /insights/queries/{id}:
    get:
      operationId: retrieveSavedQuery
      tags: [Insights]
      summary: Retrieve Saved Query
      description: Returns a single saved query by ID.
      parameters:
        - $ref: "#/components/parameters/InsightQueryId"
      responses:
        "200":
          description: Saved query
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SavedQuery"
        "404":
          description: Query not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    put:
      operationId: updateSavedQuery
      tags: [Insights]
      summary: Update Saved Query
      description: Replaces the name and SQL of an existing saved query.
      parameters:
        - $ref: "#/components/parameters/InsightQueryId"
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/SaveQueryRequest"
      responses:
        "200":
          description: Query updated
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/SavedQuery"
        "404":
          description: Query not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"
    delete:
      operationId: deleteSavedQuery
      tags: [Insights]
      summary: Delete Saved Query
      description: Permanently removes a saved query.
      parameters:
        - $ref: "#/components/parameters/InsightQueryId"
      responses:
        "204":
          description: Query deleted
        "404":
          description: Query not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /insights/execute:
    post:
      operationId: executeQuery
      tags: [Insights]
      summary: Execute Query
      description: Executes an ad-hoc SQL query against the analytics database and returns columnar results.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/ExecuteQueryRequest"
      responses:
        "200":
          description: Query results
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ExecuteQueryResponse"
        "400":
          description: Bad SQL or query error
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  /insights/history:
    get:
      operationId: listQueryHistory
      tags: [Insights]
      summary: List Query History
      description: Returns a paginated history of recently executed queries with timing and row counts.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of history entries
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedHistoryEntryList"

  # ── Usage ────────────────────────────────────────────────────────────

  /usage:
    get:
      operationId: getAggregateUsage
      tags: [Usage]
      summary: Aggregate Usage
      description: Returns aggregate token/cost usage across all completed runs since server start.
      responses:
        "200":
          description: Aggregate usage data
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/AggregateUsage"

  # ── Models ───────────────────────────────────────────────────────────

  /models:
    get:
      operationId: listModels
      tags: [Models]
      summary: List Models
      description: Returns a paginated list of available LLM models from the built-in catalog.
      parameters:
        - $ref: "#/components/parameters/PageLimit"
        - $ref: "#/components/parameters/PageOffset"
      responses:
        "200":
          description: Paginated list of models
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/PaginatedModelList"

  /models/{id}/test:
    post:
      operationId: testModel
      tags: [Models]
      summary: Test Model
      description: Tests a model by sending a simple prompt and reporting pass/fail.
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: string
          description: The model identifier.
      responses:
        "200":
          description: Test result
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ModelTestResult"
        "404":
          description: Model not found
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Completions ───────────────────────────────────────────────────────

  /completions:
    post:
      operationId: createCompletion
      tags: [Completions]
      summary: Create Completion
      description: |
        Generate a text completion. Set `stream: true` for SSE streaming.

        All SSE frames use `event: stream_event` with a JSON-serialized StreamEvent
        payload. StreamEvent types: stream_start, text_start, text_delta, text_end,
        tool_call_start, tool_call_delta, tool_call_end, finish, error.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: "#/components/schemas/CreateCompletionRequest"
      responses:
        "200":
          description: Completion result (JSON when stream=false, SSE when stream=true)
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/CompletionResponse"
        "400":
          description: Invalid request
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ErrorResponse"

  # ── Settings ──────────────────────────────────────────────────────────

  /settings:
    get:
      operationId: retrieveServerConfiguration
      tags: [Settings]
      summary: Retrieve Server Configuration
      description: Returns the structured server configuration.
      responses:
        "200":
          description: Server configuration
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/ServerConfiguration"

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: >
        JWT bearer token issued by fabro-web. See the [Authentication](/api-reference/overview#authentication) guide for details.
    # OpenAPI 3.1 defines type: mutualTLS, but our parser (openapiv3) only
    # supports 3.0 scheme types. We use apiKey as a placeholder; actual mTLS
    # enforcement happens at the transport layer via client certificates.
    mTLS:
      type: apiKey
      in: header
      name: X-mTLS-Client-CN
      description: >
        Mutual TLS: client certificate signed by the configured CA. Identity
        is extracted from the certificate's Common Name (CN). This scheme is
        enforced at the transport layer, not via an HTTP header.

  parameters:
    RunId:
      name: id
      in: path
      required: true
      description: Unique run identifier (ULID).
      schema:
        type: string
      example: 01JNQVR7M0EJ5GKAT2SC4ERS1Z

    SessionId:
      name: id
      in: path
      required: true
      description: Unique session identifier.
      schema:
        type: string
        format: uuid
      example: a1b2c3d4-e5f6-7890-abcd-ef1234567890

    StageId:
      name: stageId
      in: path
      required: true
      description: Identifier of a stage within a run's workflow graph.
      schema:
        type: string
      example: propose-changes

    QuestionId:
      name: qid
      in: path
      required: true
      description: Unique identifier of a pending question.
      schema:
        type: string
      example: q-001

    WorkflowName:
      name: name
      in: path
      required: true
      description: URL-safe slug identifying a workflow definition.
      schema:
        type: string
      example: fix_build

    CriterionId:
      name: id
      in: path
      required: true
      description: URL-safe slug identifying a verification criterion.
      schema:
        type: string
      example: traceability

    ControlId:
      name: id
      in: path
      required: true
      description: URL-safe slug identifying a verification control.
      schema:
        type: string
      example: motivation

    SignoffId:
      name: id
      in: path
      required: true
      description: Unique identifier of a signoff (ULID).
      schema:
        type: string
      example: 01JQVKX0001SIGNOFF00001

    SignoffControlFilter:
      name: control
      in: query
      required: false
      description: Filter signoffs by control slug.
      schema:
        type: string
      example: motivation

    SignoffRepositoryFilter:
      name: repository
      in: query
      required: false
      description: Filter signoffs by repository name.
      schema:
        type: string
      example: api-server

    SignoffCommitShaFilter:
      name: commit_sha
      in: query
      required: false
      description: Filter signoffs by commit SHA.
      schema:
        type: string
      example: a1b2c3d4e5f6

    InsightQueryId:
      name: id
      in: path
      required: true
      description: Unique identifier of a saved query.
      schema:
        type: string
      example: "1"

    CheckpointFilter:
      name: checkpoint
      in: query
      required: false
      description: Filter to a specific checkpoint ID. Omit to include all changes.
      schema:
        type: string
      example: cp-3

    RetroWorkflowFilter:
      name: workflow
      in: query
      required: false
      description: Filter retros by workflow slug.
      schema:
        type: string
      example: implement

    RetroSmoothnessFilter:
      name: smoothness
      in: query
      required: false
      description: Filter retros by smoothness rating.
      schema:
        $ref: "#/components/schemas/SmoothnessRating"
      example: bumpy

    PageLimit:
      name: page[limit]
      in: query
      required: false
      description: Maximum number of items to return per page.
      schema:
        type: integer
        minimum: 1
        maximum: 100
        default: 20
      example: 20

    PageOffset:
      name: page[offset]
      in: query
      required: false
      description: Number of items to skip before returning results.
      schema:
        type: integer
        minimum: 0
        default: 0
      example: 0

  schemas:
    # ── Pagination ───────────────────────────────────────────────────────

    PaginationMeta:
      description: Pagination metadata included in every paginated response.
      type: object
      required:
        - has_more
      properties:
        has_more:
          type: boolean
          description: Whether additional pages of results are available.
          example: true

    PaginatedRunList:
      description: Paginated list of runs.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/RunListItem"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedWorkflowList:
      description: Paginated list of workflows.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/WorkflowListItem"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedRetroList:
      description: Paginated list of run retrospectives.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/RetroListItem"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedSessionList:
      description: Paginated list of sessions.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/SessionListItem"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedModelList:
      description: Paginated list of models.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/Model"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    ModelLimits:
      description: Token limits for a model.
      type: object
      required:
        - context_window
      properties:
        context_window:
          type: integer
          format: int64
          description: Maximum context window size in tokens.
          example: 1000000
        max_output:
          type: integer
          format: int64
          nullable: true
          description: Maximum output tokens, if known.
          example: 128000

    ModelFeatures:
      description: Capability flags for a model.
      type: object
      required:
        - tools
        - vision
        - reasoning
      properties:
        tools:
          type: boolean
          description: Whether the model supports tool use.
        vision:
          type: boolean
          description: Whether the model supports vision/image inputs.
        reasoning:
          type: boolean
          description: Whether the model supports extended reasoning.

    ModelCosts:
      description: Pricing per million tokens in USD.
      type: object
      properties:
        input_cost_per_mtok:
          type: number
          format: double
          nullable: true
          description: Cost per million input tokens in USD.
          example: 15.0
        output_cost_per_mtok:
          type: number
          format: double
          nullable: true
          description: Cost per million output tokens in USD.
          example: 75.0
        cache_input_cost_per_mtok:
          type: number
          format: double
          nullable: true
          description: Cost per million cached input tokens in USD.
          example: 1.50

    Model:
      description: An available LLM model from the built-in catalog.
      type: object
      required:
        - id
        - provider
        - family
        - display_name
        - limits
        - features
        - costs
        - aliases
        - default
      properties:
        id:
          type: string
          description: Unique model identifier.
          example: "claude-opus-4-6"
        provider:
          type: string
          description: Provider that serves this model.
          example: "anthropic"
        family:
          type: string
          description: Model family grouping.
          example: "claude-4"
        display_name:
          type: string
          description: Human-readable model name.
          example: "Claude Opus 4.6"
        limits:
          $ref: "#/components/schemas/ModelLimits"
        training:
          type: string
          nullable: true
          description: Training data cutoff date (YYYY-MM-DD).
          example: "2025-08-01"
        features:
          $ref: "#/components/schemas/ModelFeatures"
        costs:
          $ref: "#/components/schemas/ModelCosts"
        estimated_output_tps:
          type: number
          format: double
          nullable: true
          description: Estimated output tokens per second.
        aliases:
          type: array
          items:
            type: string
          description: Alternative names that resolve to this model.
          example: ["opus"]
        default:
          type: boolean
          description: Whether this is the default model for its provider.

    ModelTestResult:
      description: Result of testing a model with a simple prompt.
      type: object
      required:
        - model_id
        - status
      properties:
        model_id:
          type: string
          description: The model identifier that was tested.
          example: "claude-opus-4-6"
        status:
          type: string
          enum:
            - ok
            - error
          description: Whether the model responded successfully.
        error_message:
          type: string
          nullable: true
          description: Error details when status is "error".

    # ── Completion Schemas ─────────────────────────────────────────────

    CompletionMessage:
      description: A message in the conversation.
      type: object
      required: [role, content]
      properties:
        role:
          type: string
          enum: [system, user, assistant, tool, developer]
          description: The role of the message author.
        content:
          type: array
          description: Content parts of the message.
          items:
            $ref: "#/components/schemas/CompletionContentPart"
        name:
          type: string
          description: Optional name for the message author.
        tool_call_id:
          type: string
          description: Tool call ID for tool result messages.

    CompletionContentPart:
      description: A content part within a message, discriminated by `kind`.
      type: object
      required: [kind]
      properties:
        kind:
          type: string
          description: "Content part type: text, image, tool_call, tool_result, thinking, etc."
        data:
          description: Content data, structure depends on kind.

    CompletionToolDefinition:
      description: A tool available for the model to call.
      type: object
      required: [name, description, parameters]
      properties:
        name:
          type: string
          description: Tool name.
        description:
          type: string
          description: Human-readable tool description.
        parameters:
          description: JSON Schema for the tool's parameters.

    CompletionToolChoice:
      description: Controls how the model selects tools.
      type: object
      required: [mode]
      properties:
        mode:
          type: string
          enum: [auto, none, required, named]
          description: Tool selection mode.
        tool_name:
          type: string
          description: Required when mode is "named".

    CreateCompletionRequest:
      type: object
      required: [messages]
      properties:
        messages:
          type: array
          description: The conversation messages.
          items:
            $ref: "#/components/schemas/CompletionMessage"
        model:
          type: string
          description: Model ID or alias. Server picks default if omitted.
        system:
          type: string
          description: System prompt (convenience; prepended as a system message).
        stream:
          type: boolean
          default: true
          description: Stream response via SSE.
        tools:
          type: array
          description: Tool definitions available to the model.
          items:
            $ref: "#/components/schemas/CompletionToolDefinition"
        tool_choice:
          $ref: "#/components/schemas/CompletionToolChoice"
        schema:
          description: JSON Schema for structured output.
        temperature:
          type: number
          format: double
        max_tokens:
          type: integer
          format: int64
        top_p:
          type: number
          format: double
        stop_sequences:
          type: array
          items:
            type: string
          description: Stop sequences.
        reasoning_effort:
          type: string
          description: Reasoning effort level.
        provider:
          type: string
          description: Provider to route to.
        provider_options:
          description: Provider-specific options.

    CompletionUsage:
      type: object
      required: [input_tokens, output_tokens]
      properties:
        input_tokens:
          type: integer
          format: int64
        output_tokens:
          type: integer
          format: int64

    CompletionResponse:
      type: object
      required: [id, model, message, stop_reason, usage]
      properties:
        id:
          type: string
        model:
          type: string
        message:
          $ref: "#/components/schemas/CompletionMessage"
        stop_reason:
          type: string
          description: Why generation stopped (end_turn, max_tokens, tool_calls).
        usage:
          $ref: "#/components/schemas/CompletionUsage"
        output:
          description: Parsed structured output when schema was provided.

    PaginatedSavedQueryList:
      description: Paginated list of saved queries.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/SavedQuery"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedHistoryEntryList:
      description: Paginated list of query history entries.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/HistoryEntry"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedStageTurnList:
      description: Paginated list of stage turns.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/StageTurn"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedApiQuestionList:
      description: Paginated list of pending questions.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/ApiQuestion"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedRunStageList:
      description: Paginated list of run stages.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/RunStage"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedRunVerificationList:
      description: Paginated list of run verification categories.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/RunVerification"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    PaginatedVerificationCriterionList:
      description: Paginated list of verification criteria.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/VerificationCriterion"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    # ── Run Schemas ──────────────────────────────────────────────────────

    RunStatus:
      description: Lifecycle status of a run.
      type: string
      enum:
        - queued
        - starting
        - running
        - completed
        - failed
        - cancelled
        - paused

    StartRunRequest:
      description: Request body for starting a new run from a Graphviz graph source.
      type: object
      required:
        - dot_source
      properties:
        dot_source:
          type: string
          description: Graphviz DOT language source defining the workflow graph.
          example: 'digraph { start [shape=Mdiamond]; exit [shape=Msquare]; start -> exit }'

    RunStatusResponse:
      description: Current status of a run with optional error and queue position.
      type: object
      required:
        - id
        - status
        - created_at
      properties:
        id:
          type: string
          description: Unique run identifier (ULID).
          example: 01JNQVR7M0EJ5GKAT2SC4ERS1Z
        status:
          $ref: "#/components/schemas/RunStatus"
        error:
          $ref: "#/components/schemas/RunError"
        queue_position:
          type: integer
          description: Position in the queue (1-based). Only present when status is `queued`.
          example: 3
        created_at:
          type: string
          format: date-time
          description: Timestamp when the run was created.
          example: "2026-03-06T14:30:00Z"

    ApiQuestionOption:
      description: A selectable option for a multiple-choice or multi-select question.
      type: object
      required:
        - key
        - label
      properties:
        key:
          type: string
          description: Machine-readable option key used when submitting an answer.
          example: option_a
        label:
          type: string
          description: Human-readable label displayed to the user.
          example: Accept changes

    ApiQuestion:
      description: A pending human-in-the-loop question generated by a workflow stage.
      type: object
      required:
        - id
        - text
        - question_type
        - options
        - allow_freeform
      properties:
        id:
          type: string
          description: Unique question identifier.
          example: q-001
        text:
          type: string
          description: The question text displayed to the user.
          example: Should we proceed with the proposed changes?
        question_type:
          $ref: "#/components/schemas/QuestionType"
        options:
          type: array
          description: Available options for selection-based questions. Empty for freeform questions.
          items:
            $ref: "#/components/schemas/ApiQuestionOption"
        allow_freeform:
          type: boolean
          description: Whether the user may provide freeform text in addition to selecting options.
          example: true

    QuestionType:
      description: The interaction type of a human-in-the-loop question.
      type: string
      enum:
        - yes_no
        - multiple_choice
        - multi_select
        - freeform
        - confirmation

    SubmitAnswerRequest:
      description: >
        Request body for submitting an answer to a pending question.
        At least one of `value`, `selected_option_key`, or `selected_option_keys` must be provided.
      type: object
      properties:
        value:
          type: string
          description: Freeform answer text.
          example: "Yes, proceed with the changes."
        selected_option_key:
          type: string
          description: Key of the selected option (for single-select multiple-choice questions).
          example: option_a
        selected_option_keys:
          type: array
          items:
            type: string
          description: Keys of selected options (for multi-select questions).
          example: ["option_a", "option_b"]

    ErrorResponseEntry:
      description: A single error entry in an error response.
      type: object
      required:
        - status
        - title
        - detail
      properties:
        status:
          type: string
          description: HTTP status code as a string.
          example: "404"
        title:
          type: string
          description: Short error classification.
          example: Not Found
        detail:
          type: string
          description: Human-readable error description.
          example: Run not found.

    ErrorResponse:
      description: Standard error response containing one or more error entries.
      type: object
      required:
        - errors
      properties:
        errors:
          type: array
          description: List of error entries.
          items:
            $ref: "#/components/schemas/ErrorResponseEntry"

    # ── Run Board Schemas ────────────────────────────────────────────────

    BoardColumn:
      description: Board column status for a run in the list view.
      type: string
      enum:
        - working
        - pending
        - review
        - merge

    CheckRunStatus:
      description: Status of a CI check run.
      type: string
      enum:
        - success
        - failure
        - skipped
        - pending
        - queued

    CheckRun:
      description: A CI check run result associated with a run's pull request.
      type: object
      required:
        - name
        - status
      properties:
        name:
          type: string
          description: Name of the CI check.
          example: unit-tests
        status:
          $ref: "#/components/schemas/CheckRunStatus"
        duration_secs:
          type: number
          description: Duration of the check run in seconds.
          example: 154.0

    # ── Reusable Sub-Schemas ───────────────────────────────────────────

    ModelReference:
      description: Reference to a model by its identifier.
      type: object
      required:
        - id
      properties:
        id:
          type: string
          description: Model identifier.
          example: claude-opus-4-6

    WorkflowReference:
      description: Reference to a workflow by its slug.
      type: object
      required:
        - slug
      properties:
        slug:
          type: string
          description: URL-safe workflow slug.
          example: implement

    RunReference:
      description: Reference to a run with its title.
      type: object
      required:
        - id
        - title
      properties:
        id:
          type: string
          description: Unique run identifier.
          example: run-047
        title:
          type: string
          description: Human-readable run title.
          example: "PR #312 — Add OAuth2 PKCE flow"

    RepositoryReference:
      description: Reference to a repository by name.
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Repository name.
          example: api-server

    CriterionReference:
      description: Reference to a verification criterion by name.
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Criterion name.
          example: Traceability

    TokenUsage:
      description: Token and cost usage totals.
      type: object
      required:
        - input_tokens
        - output_tokens
        - cost
      properties:
        input_tokens:
          type: integer
          description: Number of input tokens consumed.
          example: 28640
        output_tokens:
          type: integer
          description: Number of output tokens generated.
          example: 8750
        cost:
          type: number
          description: Cost in USD.
          example: 0.72

    CodeLocation:
      description: A file and line location in the codebase.
      type: object
      required:
        - file
      properties:
        file:
          type: string
          description: File path.
          example: src/middleware/rate-limit.ts
        line:
          type: integer
          description: Line number in the file.
          example: 42

    RunError:
      description: Error information for a failed run.
      type: object
      required:
        - message
      properties:
        message:
          type: string
          description: Error message.
          example: "Stage 'apply-changes' exceeded maximum retries."

    RunPullRequest:
      description: Pull request information for a run.
      type: object
      required:
        - number
      properties:
        number:
          type: integer
          description: Pull request number.
          example: 889
        additions:
          type: integer
          description: Lines added.
          example: 234
        deletions:
          type: integer
          description: Lines deleted.
          example: 67
        comments:
          type: integer
          description: Number of review comments.
          example: 4
        checks:
          type: array
          description: CI check run results.
          items:
            $ref: "#/components/schemas/CheckRun"

    RunTimings:
      description: Timing information for a run.
      type: object
      required:
        - elapsed_secs
      properties:
        elapsed_secs:
          type: number
          description: Wall-clock time elapsed in seconds.
          example: 420.0
        elapsed_warning:
          type: boolean
          description: Whether the elapsed time exceeds the expected threshold.
          example: false

    SandboxResources:
      description: Compute resources allocated to a sandbox.
      type: object
      required:
        - cpu
        - memory
      properties:
        cpu:
          type: integer
          description: Number of CPU cores.
          example: 4
        memory:
          type: integer
          description: Memory in GB.
          example: 8

    RunSandbox:
      description: Sandbox environment for a run.
      type: object
      required:
        - id
      properties:
        id:
          type: string
          description: Sandbox identifier.
          example: sb-a1b2c3d4
        resources:
          $ref: "#/components/schemas/SandboxResources"

    RunQuestion:
      description: A pending human-in-the-loop question summary.
      type: object
      required:
        - text
      properties:
        text:
          type: string
          description: Question text.
          example: Accept or push for another round?

    AggregateUsageTotals:
      description: Aggregate usage totals across all runs.
      type: object
      required:
        - runs
        - input_tokens
        - output_tokens
        - cost
        - runtime_secs
      properties:
        runs:
          type: integer
          description: Total number of completed runs.
          example: 9
        input_tokens:
          type: integer
          description: Total input tokens.
          example: 643860
        output_tokens:
          type: integer
          description: Total output tokens.
          example: 189720
        cost:
          type: number
          description: Total cost in USD.
          example: 20.34
        runtime_secs:
          type: number
          description: Total runtime in seconds.
          example: 3501.0

    WorkflowSchedule:
      description: Schedule configuration for a workflow.
      type: object
      required:
        - expression
      properties:
        expression:
          type: string
          description: Cron-like schedule expression.
          example: "0 */6 * * *"
        next_run:
          type: string
          format: date-time
          description: ISO 8601 timestamp of the next scheduled run.
          example: "2025-09-15T18:00:00Z"

    WorkflowLastRun:
      description: Information about a workflow's most recent run.
      type: object
      required:
        - ran_at
      properties:
        ran_at:
          type: string
          format: date-time
          description: ISO 8601 timestamp of the most recent run.
          example: "2025-09-15T12:00:00Z"

    UsageStageRef:
      description: Reference to a usage stage.
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: string
          description: Stage identifier (slug).
          example: propose-changes
        name:
          type: string
          description: Human-readable stage name.
          example: Propose Changes

    # ── Run Board Schemas (updated) ─────────────────────────────────────

    RunListItem:
      description: Summary of a run shown in the board view.
      type: object
      required:
        - id
        - repository
        - title
        - workflow
        - status
        - created_at
      properties:
        id:
          type: string
          description: Unique run identifier (ULID).
          example: 01JNQVR7M0EJ5GKAT2SC4ERS1Z
        repository:
          $ref: "#/components/schemas/RepositoryReference"
        title:
          type: string
          description: Human-readable title describing the run's goal.
          example: Add rate limiting to auth endpoints
        workflow:
          $ref: "#/components/schemas/WorkflowReference"
        status:
          $ref: "#/components/schemas/BoardColumn"
        pull_request:
          $ref: "#/components/schemas/RunPullRequest"
        timings:
          $ref: "#/components/schemas/RunTimings"
        sandbox:
          $ref: "#/components/schemas/RunSandbox"
        question:
          $ref: "#/components/schemas/RunQuestion"
        created_at:
          type: string
          format: date-time
          description: Timestamp when the run was created.
          example: "2026-03-06T14:30:00Z"

    RunCheckpoint:
      description: Serializable snapshot of execution state for crash recovery and resume.
      type: object
      required:
        - timestamp
        - current_node
        - completed_nodes
        - node_retries
        - context_values
        - logs
      properties:
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the checkpoint was created.
        current_node:
          type: string
          description: Identifier of the node being executed at checkpoint time.
        completed_nodes:
          type: array
          items:
            type: string
          description: Identifiers of nodes that have completed execution.
        node_retries:
          type: object
          additionalProperties:
            type: integer
          description: Map of node identifier to retry count.
        context_values:
          type: object
          additionalProperties: true
          description: Key-value context map accumulated during execution.
        logs:
          type: array
          items:
            type: string
          description: Log entries recorded during execution.
        node_outcomes:
          type: object
          additionalProperties: true
          description: Map of node identifier to outcome data for goal gate checks after resume.
        next_node_id:
          type: string
          description: The node to resume execution at after this checkpoint.
        git_commit_sha:
          type: string
          description: SHA of the git commit created at this checkpoint.
        loop_failure_signatures:
          type: object
          additionalProperties: true
          description: Failure signature counts within the main loop.
        restart_failure_signatures:
          type: object
          additionalProperties: true
          description: Failure signature counts across loop_restart edges.

    # ── Stage / Turn Schemas ─────────────────────────────────────────────

    StageStatus:
      description: Execution status of a workflow stage.
      type: string
      enum:
        - completed
        - running
        - pending
        - failed
        - cancelled

    RunStage:
      description: A single stage in a run's workflow graph.
      type: object
      required:
        - id
        - name
        - status
      properties:
        id:
          type: string
          description: Unique stage identifier within the run.
          example: propose-changes
        name:
          type: string
          description: Human-readable stage name.
          example: Propose Changes
        status:
          $ref: "#/components/schemas/StageStatus"
        duration_secs:
          type: number
          description: Time spent in this stage, in seconds.
          example: 154.0
        dot_id:
          type: string
          description: Node identifier in the Graphviz graph source.
          example: propose

    ToolUse:
      description: A single tool invocation with its input, result, and execution metadata.
      type: object
      required:
        - id
        - tool_name
        - input
        - result
        - is_error
      properties:
        id:
          type: string
          description: Unique identifier for this tool invocation. Enables correlation in parallel tool use.
          example: toolu_01A09q90qw90lq917835lq9
        tool_name:
          type: string
          description: Name of the tool that was invoked.
          example: read_file
        input:
          type: string
          description: JSON-encoded input passed to the tool.
          example: '{ "path": "src/routes/auth.ts" }'
        result:
          type: string
          description: Output returned by the tool. Contains the error message when is_error is true.
          example: 'import { Router } from "express";'
        is_error:
          type: boolean
          description: Whether the tool invocation failed. When true, the result field contains the error message.
          example: false
        duration_ms:
          type: integer
          description: Wall-clock execution time of the tool invocation in milliseconds.
          example: 142

    StageTurn:
      description: A single turn in a stage conversation — a system prompt, assistant response, or tool invocation block.
      discriminator:
        propertyName: kind
        mapping:
          system: "#/components/schemas/SystemStageTurn"
          assistant: "#/components/schemas/AssistantStageTurn"
          tool: "#/components/schemas/ToolStageTurn"
      oneOf:
        - $ref: "#/components/schemas/SystemStageTurn"
        - $ref: "#/components/schemas/AssistantStageTurn"
        - $ref: "#/components/schemas/ToolStageTurn"

    SystemStageTurn:
      description: A system prompt turn that sets the stage's instructions.
      type: object
      required:
        - kind
        - content
      properties:
        kind:
          type: string
          enum: [system]
        content:
          type: string
          description: System prompt text.
          example: You are a drift detection agent. Compare the production and staging environments.

    AssistantStageTurn:
      description: An assistant response turn within a stage.
      type: object
      required:
        - kind
        - content
      properties:
        kind:
          type: string
          enum: [assistant]
        content:
          type: string
          description: Assistant response text.
          example: I'll start by loading the environment configurations for both production and staging.

    ToolStageTurn:
      description: A tool invocation turn containing one or more tool calls.
      type: object
      required:
        - kind
        - tools
      properties:
        kind:
          type: string
          enum: [tool]
        content:
          type: string
          description: Text accompanying the tool invocations, or null when the turn contains only tool calls.
        tools:
          type: array
          description: Tool invocations executed in this turn.
          items:
            $ref: "#/components/schemas/ToolUse"

    # ── File Diff Schemas ──────────────────────────────────────────────

    FileCheckpoint:
      description: A named checkpoint within a run, used to filter file diffs.
      type: object
      required:
        - id
        - label
      properties:
        id:
          type: string
          description: Checkpoint identifier.
          example: cp-3
        label:
          type: string
          description: Human-readable label for the checkpoint.
          example: "Checkpoint 3 — Review Changes"

    DiffFile:
      description: A file's contents at one side of a diff.
      type: object
      required:
        - name
        - contents
      properties:
        name:
          type: string
          description: File path relative to the repository root.
          example: src/commands/run.ts
        contents:
          type: string
          description: Full file contents. Empty string for newly created or deleted files.
          example: 'import { parseArgs } from "node:util";'

    FileDiff:
      description: A before/after pair showing changes to a single file.
      type: object
      required:
        - old_file
        - new_file
      properties:
        old_file:
          $ref: "#/components/schemas/DiffFile"
        new_file:
          $ref: "#/components/schemas/DiffFile"

    DiffStats:
      description: Aggregate line-change statistics for a diff.
      type: object
      required:
        - additions
        - deletions
      properties:
        additions:
          type: integer
          description: Total lines added.
          example: 567
        deletions:
          type: integer
          description: Total lines deleted.
          example: 234

    PaginatedRunFileList:
      description: Paginated list of file diffs produced by a run.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/FileDiff"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    # ── Usage Schemas ────────────────────────────────────────────────────

    UsageStage:
      description: Token and cost usage for a single stage within a run.
      type: object
      required:
        - stage
        - model
        - usage
        - runtime_secs
      properties:
        stage:
          $ref: "#/components/schemas/UsageStageRef"
        model:
          $ref: "#/components/schemas/ModelReference"
        usage:
          $ref: "#/components/schemas/TokenUsage"
        runtime_secs:
          type: number
          description: Wall-clock runtime in seconds.
          example: 154.0

    UsageTotals:
      description: Aggregate usage totals across all stages of a run.
      type: object
      required:
        - runtime_secs
        - input_tokens
        - output_tokens
        - cost
      properties:
        runtime_secs:
          type: number
          description: Total wall-clock runtime in seconds.
          example: 389.0
        input_tokens:
          type: integer
          description: Total input tokens consumed.
          example: 71540
        output_tokens:
          type: integer
          description: Total output tokens generated.
          example: 21080
        cost:
          type: number
          description: Total cost in USD.
          example: 2.26

    UsageByModel:
      description: Usage statistics grouped by model.
      type: object
      required:
        - model
        - stages
        - usage
      properties:
        model:
          $ref: "#/components/schemas/ModelReference"
        stages:
          type: integer
          description: Number of stages that used this model.
          example: 2
        usage:
          $ref: "#/components/schemas/TokenUsage"

    RunUsage:
      description: Complete usage breakdown for a single run.
      type: object
      required:
        - stages
        - totals
        - by_model
      properties:
        stages:
          type: array
          description: Per-stage usage breakdown.
          items:
            $ref: "#/components/schemas/UsageStage"
        totals:
          $ref: "#/components/schemas/UsageTotals"
        by_model:
          type: array
          description: Usage grouped by model.
          items:
            $ref: "#/components/schemas/UsageByModel"

    AggregateUsage:
      description: Aggregate token and cost usage across all runs since server start.
      type: object
      required:
        - totals
        - by_model
      properties:
        totals:
          $ref: "#/components/schemas/AggregateUsageTotals"
        by_model:
          type: array
          description: Usage grouped by model.
          items:
            $ref: "#/components/schemas/UsageByModel"

    # ── Verification Schemas ─────────────────────────────────────────────

    VerificationResult:
      description: >
        Outcome of a verification control evaluation.
        `skip`: evaluation was intentionally skipped (e.g., control is disabled).
        `na`: control does not apply to this run (e.g., Python lint on a Rust-only change).
      type: string
      enum:
        - pass
        - fail
        - skip
        - na

    VerificationType:
      description: The evaluation method used by a verification control.
      type: string
      enum:
        - ai
        - automated
        - analysis
        - ai-analysis

    RunVerificationControl:
      description: A verification control result within a run.
      type: object
      required:
        - name
        - slug
        - description
        - type
        - status
      properties:
        name:
          type: string
          description: Human-readable control name.
          example: Motivation
        slug:
          type: string
          description: URL-safe slug for linking to verification detail page.
          example: motivation
        description:
          type: string
          description: Short description of what the control verifies.
          example: Origin of proposal identified
        type:
          $ref: "#/components/schemas/VerificationType"
        status:
          $ref: "#/components/schemas/VerificationResult"

    RunVerification:
      description: Verification results for a category within a run.
      type: object
      required:
        - name
        - question
        - status
        - controls
      properties:
        name:
          type: string
          description: Category name.
          example: Traceability
        question:
          type: string
          description: The guiding question for this verification category.
          example: Do we understand what this change is and why we're making it?
        status:
          $ref: "#/components/schemas/VerificationResult"
        controls:
          type: array
          description: Individual control results within this category.
          items:
            $ref: "#/components/schemas/RunVerificationControl"

    SteerRequest:
      description: Request body for sending inline steering guidance to a running agent.
      type: object
      required:
        - guidance
      properties:
        location:
          $ref: "#/components/schemas/CodeLocation"
        guidance:
          type: string
          description: Guidance text for the agent.
          example: Use a sliding window algorithm instead of fixed window.

    PreviewUrlRequest:
      description: Request body for generating a preview URL from a sandbox port.
      type: object
      required:
        - port
        - expires_in_secs
      properties:
        port:
          type: integer
          description: Port number exposed by the sandbox.
          example: 3000
        expires_in_secs:
          type: integer
          description: Time-to-live for the preview URL in seconds.
          minimum: 1
          maximum: 86400
          example: 3600

    PreviewUrlResponse:
      description: Response containing the generated preview URL.
      type: object
      required:
        - url
      properties:
        url:
          type: string
          description: Time-limited preview URL.
          example: "https://preview.example.com/sb-a1b2c3d4/3000"

    # ── Workflow Schemas ─────────────────────────────────────────────────

    WorkflowListItem:
      description: Summary of a workflow shown in list views.
      type: object
      required:
        - name
        - slug
        - filename
      properties:
        name:
          type: string
          description: Human-readable workflow name.
          example: Fix Build
        slug:
          type: string
          description: URL-safe slug used in API paths.
          example: fix_build
        filename:
          type: string
          description: Graphviz graph filename.
          example: fix_build.fabro
        last_run:
          $ref: "#/components/schemas/WorkflowLastRun"
        schedule:
          $ref: "#/components/schemas/WorkflowSchedule"

    WorkflowDetail:
      description: Full detail of a workflow definition including graph and configuration.
      type: object
      required:
        - name
        - slug
        - filename
        - description
        - config
        - graph
      properties:
        name:
          type: string
          description: Human-readable workflow name.
          example: Fix Build
        slug:
          type: string
          description: URL-safe slug used in API paths.
          example: fix_build
        filename:
          type: string
          description: Graphviz graph filename.
          example: fix_build.fabro
        description:
          type: string
          description: Prose description of what the workflow does.
          example: Automatically diagnoses and fixes CI build failures.
        config:
          $ref: "#/components/schemas/RunConfiguration"
        graph:
          type: string
          description: Graphviz DOT language source defining the workflow graph.
          example: "digraph fix_build { rankdir=LR; start -> diagnose -> fix -> validate }"

    # ── Verification Detail Schemas ──────────────────────────────────────

    VerificationMode:
      description: Operational mode of a verification control.
      type: string
      enum:
        - active
        - evaluate
        - disabled

    VerificationControl:
      description: A verification control within a category, with performance metrics.
      type: object
      required:
        - name
        - slug
        - description
        - type
      properties:
        name:
          type: string
          description: Human-readable control name.
          example: Motivation
        slug:
          type: string
          description: URL-safe slug for API lookups.
          example: motivation
        description:
          type: string
          description: Short description of what the control verifies.
          example: Origin of proposal identified
        type:
          $ref: "#/components/schemas/VerificationType"
        mode:
          $ref: "#/components/schemas/VerificationMode"
        f1:
          type: number
          description: F1 score of the control's AI evaluator.
          example: 0.87
        pass_at_1:
          type: number
          description: Pass@1 rate — probability of passing on the first evaluation.
          example: 0.82
        evaluations:
          type: array
          description: Recent evaluation results (newest first).
          items:
            $ref: "#/components/schemas/VerificationResult"

    VerificationCriterion:
      description: A group of related verification controls.
      type: object
      required:
        - name
        - question
        - controls
      properties:
        name:
          type: string
          description: Criterion name.
          example: Traceability
        question:
          type: string
          description: Guiding question for the criterion.
          example: Do we understand what this change is and why we're making it?
        controls:
          type: array
          description: Verification controls in this criterion.
          items:
            $ref: "#/components/schemas/VerificationControl"

    VerificationControlListItem:
      description: A verification control in a flat list view with criterion reference.
      type: object
      required:
        - name
        - slug
        - description
        - type
        - criterion
      properties:
        name:
          type: string
          description: Human-readable control name.
          example: Motivation
        slug:
          type: string
          description: URL-safe slug for API lookups.
          example: motivation
        description:
          type: string
          description: Short description of what the control verifies.
          example: Origin of proposal identified
        type:
          $ref: "#/components/schemas/VerificationType"
        mode:
          $ref: "#/components/schemas/VerificationMode"
        f1:
          type: number
          description: F1 score of the control's AI evaluator.
          example: 0.87
        pass_at_1:
          type: number
          description: Pass@1 rate.
          example: 0.82
        criterion:
          $ref: "#/components/schemas/CriterionReference"

    PaginatedVerificationControlList:
      description: Paginated list of verification controls.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/VerificationControlListItem"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    SignoffStatus:
      description: Status of a signoff.
      type: string
      enum:
        - pass
        - fail
        - pending

    ControlReference:
      description: Reference to a verification control by slug.
      type: object
      required:
        - slug
      properties:
        slug:
          type: string
          description: Control slug.
          example: motivation

    Signoff:
      description: A stamp of approval for a (control, repository, commit SHA) tuple.
      type: object
      required:
        - id
        - control
        - repository
        - commit_sha
        - status
        - created_at
      properties:
        id:
          type: string
          description: Unique identifier (ULID).
          example: 01JQVKX0001SIGNOFF00001
        control:
          $ref: "#/components/schemas/ControlReference"
        repository:
          $ref: "#/components/schemas/RepositoryReference"
        commit_sha:
          type: string
          description: Git commit SHA this signoff applies to.
          example: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
        status:
          $ref: "#/components/schemas/SignoffStatus"
        url:
          type: string
          nullable: true
          description: Optional URL with more details about the signoff.
          example: https://github.com/acme/api-server/actions/runs/12345
        description:
          type: string
          nullable: true
          description: Optional human-readable description.
          example: All tests passed on CI
        source:
          type: string
          nullable: true
          description: Freeform string identifying the logical origin of the signoff.
          example: github-actions
        created_at:
          type: string
          format: date-time
          description: When the signoff was created.
          example: "2025-09-15T12:00:00Z"

    CreateSignoffRequest:
      description: Request body to create a new signoff.
      type: object
      required:
        - control
        - repository
        - commit_sha
        - status
      properties:
        control:
          type: string
          description: Control slug or ID.
          example: motivation
        repository:
          type: string
          description: Repository name.
          example: api-server
        commit_sha:
          type: string
          description: Git commit SHA.
          example: a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2
        status:
          $ref: "#/components/schemas/SignoffStatus"
        url:
          type: string
          description: Optional URL with more details.
          example: https://github.com/acme/api-server/actions/runs/12345
        description:
          type: string
          description: Optional human-readable description.
          example: All tests passed on CI
        source:
          type: string
          description: Freeform string identifying the logical origin.
          example: github-actions

    PaginatedSignoffList:
      description: Paginated list of signoffs.
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            $ref: "#/components/schemas/Signoff"
        meta:
          $ref: "#/components/schemas/PaginationMeta"

    VerificationCriterionDetail:
      description: Detail view of a verification criterion with inline controls and performance metrics.
      type: object
      required:
        - name
        - question
        - controls
      properties:
        name:
          type: string
          description: Criterion name.
          example: Traceability
        question:
          type: string
          description: Guiding question for the criterion.
          example: Do we understand what this change is and why we're making it?
        controls:
          type: array
          description: Verification controls in this criterion with performance metrics.
          items:
            $ref: "#/components/schemas/VerificationControl"

    ControlInfo:
      description: Core metadata about a verification control.
      type: object
      required:
        - name
        - slug
        - description
        - criterion
      properties:
        name:
          type: string
          description: Human-readable control name.
          example: Motivation
        slug:
          type: string
          description: URL-safe slug.
          example: motivation
        description:
          type: string
          description: Short description of what the control verifies.
          example: Origin of proposal identified
        type:
          $ref: "#/components/schemas/VerificationType"
        criterion:
          $ref: "#/components/schemas/CriterionReference"

    ControlPerformance:
      description: Performance metrics for a verification control.
      type: object
      required:
        - mode
        - evaluations
      properties:
        mode:
          $ref: "#/components/schemas/VerificationMode"
        f1:
          type: number
          description: F1 score of the control's AI evaluator.
          example: 0.87
        pass_at_1:
          type: number
          description: Pass@1 rate.
          example: 0.82
        evaluations:
          type: array
          description: Recent evaluation results (newest first).
          items:
            $ref: "#/components/schemas/VerificationResult"

    ControlDetail:
      description: Detailed information about a verification control including checks and examples.
      type: object
      required:
        - rationale
        - checks
        - pass_example
        - fail_example
      properties:
        rationale:
          type: string
          description: Detailed prose description of the control's purpose and rationale.
          example: Verifies that every change traces back to a clear origin.
        checks:
          type: array
          description: Specific checks performed by this control.
          items:
            type: string
          example: ["PR body explains why the change is needed", "Commit messages reference a ticket"]
        pass_example:
          type: string
          description: Example scenario where the control passes.
          example: PR links to JIRA-1234 and explains the user-facing pain point.
        fail_example:
          type: string
          description: Example scenario where the control fails.
          example: PR description is empty or says only 'fix stuff'.

    RecentControlResult:
      description: Result of a recent verification control evaluation for a specific run.
      type: object
      required:
        - run
        - workflow
        - result
        - timestamp
      properties:
        run:
          $ref: "#/components/schemas/RunReference"
        workflow:
          $ref: "#/components/schemas/WorkflowReference"
        result:
          $ref: "#/components/schemas/VerificationResult"
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp of the evaluation.
          example: "2025-09-15T12:00:00Z"

    SiblingControl:
      description: Summary of a sibling verification control in the same category.
      type: object
      required:
        - name
        - slug
      properties:
        name:
          type: string
          description: Human-readable control name.
          example: Specifications
        slug:
          type: string
          description: URL-safe slug.
          example: specifications
        type:
          $ref: "#/components/schemas/VerificationType"
        mode:
          $ref: "#/components/schemas/VerificationMode"

    VerificationDetailResponse:
      description: Complete detail view of a verification control with performance, examples, and recent results.
      type: object
      required:
        - control
        - performance
        - control_detail
        - recent_results
        - siblings
      properties:
        control:
          $ref: "#/components/schemas/ControlInfo"
        performance:
          $ref: "#/components/schemas/ControlPerformance"
        control_detail:
          $ref: "#/components/schemas/ControlDetail"
        recent_results:
          type: array
          description: Recent evaluation results across runs.
          items:
            $ref: "#/components/schemas/RecentControlResult"
        siblings:
          type: array
          description: Other controls in the same category.
          items:
            $ref: "#/components/schemas/SiblingControl"

    # ── Retro Schemas ────────────────────────────────────────────────────

    SmoothnessRating:
      description: Qualitative assessment of how smoothly a run executed.
      type: string
      enum:
        - effortless
        - smooth
        - bumpy
        - struggled
        - failed

    RetroStats:
      description: Summary statistics for a run retrospective.
      type: object
      required:
        - total_duration_ms
        - total_retries
        - files_touched
        - stages_completed
        - stages_failed
      properties:
        total_duration_ms:
          type: integer
          description: Total run duration in milliseconds.
          example: 389000
        total_cost:
          type: number
          description: Total cost in USD. Absent when cost data is unavailable from the model provider.
          example: 2.78
        total_retries:
          type: integer
          description: Total number of retries across all stages.
          example: 0
        files_touched:
          type: array
          description: List of files modified during the run.
          items:
            type: string
          example: ["src/middleware/rate-limit.ts", "src/routes/auth.ts"]
        stages_completed:
          type: integer
          description: Number of stages that completed successfully.
          example: 4
        stages_failed:
          type: integer
          description: Number of stages that failed.
          example: 0

    RetroListItem:
      description: Summary of a run retrospective shown in list views.
      type: object
      required:
        - run
        - workflow
        - timestamp
        - stats
        - friction_point_count
      properties:
        run:
          $ref: "#/components/schemas/RunReference"
        workflow:
          $ref: "#/components/schemas/WorkflowReference"
        timestamp:
          type: string
          format: date-time
          description: Timestamp when the retro was generated.
          example: "2026-02-28T14:32:00Z"
        smoothness:
          description: Absent when the retro has been generated from quantitative data but not yet enriched by the retro agent.
          $ref: "#/components/schemas/SmoothnessRating"
        stats:
          $ref: "#/components/schemas/RetroStats"
        friction_point_count:
          type: integer
          description: Number of friction points identified in the retro.
          example: 0

    RetroDetail:
      description: Full retrospective analysis for a completed run.
      type: object
      required:
        - run_id
        - workflow_name
        - goal
        - timestamp
        - stages
        - stats
      properties:
        run_id:
          type: string
          description: Unique run identifier.
          example: run-1
        workflow_name:
          type: string
          description: Workflow slug that produced this run.
          example: implement
        goal:
          type: string
          description: The goal that was set for the run.
          example: Add rate limiting to auth endpoints
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp when the retro was generated.
          example: "2026-02-28T14:32:00Z"
        smoothness:
          description: Absent when the retro has been generated from quantitative data but not yet enriched by the retro agent.
          $ref: "#/components/schemas/SmoothnessRating"
        stages:
          type: array
          description: Per-stage retrospective data.
          items:
            $ref: "#/components/schemas/StageRetro"
        stats:
          $ref: "#/components/schemas/RetroStats"
        intent:
          type: string
          description: What the agent intended to accomplish.
          example: Implement token-bucket rate limiting on /auth/login and /auth/register.
        outcome:
          type: string
          description: What actually happened during the run.
          example: Rate limiter deployed with configurable per-IP limits.
        learnings:
          type: array
          description: Insights discovered during the run.
          items:
            $ref: "#/components/schemas/Learning"
        friction_points:
          type: array
          description: Points where the run encountered difficulty.
          items:
            $ref: "#/components/schemas/FrictionPoint"
        open_items:
          type: array
          description: Follow-up items identified during the run.
          items:
            $ref: "#/components/schemas/OpenItem"

    StageRetro:
      description: Retrospective data for a single stage in the workflow.
      type: object
      required:
        - stage_id
        - stage_label
        - status
        - duration_ms
        - retries
        - files_touched
      properties:
        stage_id:
          type: string
          description: Identifier of the stage in the workflow graph.
          example: propose-changes
        stage_label:
          type: string
          description: Human-readable label for the stage.
          example: Propose Changes
        status:
          type: string
          description: Final status of the stage.
          example: completed
        duration_ms:
          type: integer
          description: Stage duration in milliseconds.
          example: 154000
        retries:
          type: integer
          description: Number of retries for this stage.
          example: 0
        cost:
          type: number
          description: Cost in USD for this stage. Absent when cost data is unavailable.
          example: 1.12
        notes:
          type: string
          description: Optional notes about this stage's execution.
        failure_reason:
          type: string
          description: Reason the stage failed, if applicable.
        files_touched:
          type: array
          description: Files modified during this stage.
          items:
            type: string
          example: ["src/middleware/rate-limit.ts", "src/routes/auth.ts"]

    LearningCategory:
      description: Category of a learning insight.
      type: string
      enum:
        - repo
        - code
        - workflow
        - tool

    Learning:
      description: An insight discovered during the run.
      type: object
      required:
        - category
        - text
      properties:
        category:
          $ref: "#/components/schemas/LearningCategory"
        text:
          type: string
          description: Description of the learning.
          example: Auth middleware chain order matters.

    FrictionKind:
      description: Type of friction encountered during a run.
      type: string
      enum:
        - retry
        - timeout
        - wrong_approach
        - tool_failure
        - ambiguity

    FrictionPoint:
      description: A point where the run encountered difficulty.
      type: object
      required:
        - kind
        - description
      properties:
        kind:
          $ref: "#/components/schemas/FrictionKind"
        description:
          type: string
          description: Description of the friction encountered.
          example: Nested route outlet types were incorrect on first 3 attempts.
        stage_id:
          type: string
          description: Stage where the friction occurred, if applicable.
          example: apply-changes

    OpenItemKind:
      description: Type of open item identified during a run.
      type: string
      enum:
        - tech_debt
        - follow_up
        - investigation
        - test_gap

    OpenItem:
      description: A follow-up item identified during the run.
      type: object
      required:
        - kind
        - description
      properties:
        kind:
          $ref: "#/components/schemas/OpenItemKind"
        description:
          type: string
          description: Description of the open item.
          example: Add rate-limit headers (X-RateLimit-Remaining) to response.

    # ── Session Schemas ──────────────────────────────────────────────────

    SessionListItem:
      description: Summary of a session shown in list views.
      type: object
      required:
        - id
        - title
        - model
        - last_message_preview
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
          description: Unique session identifier.
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        title:
          type: string
          description: Short title summarizing the session topic.
          example: Add rate limiting to auth endpoints
        model:
          $ref: "#/components/schemas/ModelReference"
        last_message_preview:
          type: string
          description: Truncated snippet of the most recent turn's content.
          example: "Done. I've created the rate limiter and wired it up..."
        created_at:
          type: string
          format: date-time
          description: Timestamp when the session was created.
          example: "2026-03-06T14:30:00Z"
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the session was last updated (e.g. new turn added).
          example: "2026-03-06T15:45:00Z"


    SessionTurn:
      description: A single turn in a session conversation — a user message, assistant response, or tool invocation block.
      discriminator:
        propertyName: kind
        mapping:
          user: "#/components/schemas/UserTurn"
          assistant: "#/components/schemas/AssistantTurn"
          tool: "#/components/schemas/ToolTurn"
      oneOf:
        - $ref: "#/components/schemas/UserTurn"
        - $ref: "#/components/schemas/AssistantTurn"
        - $ref: "#/components/schemas/ToolTurn"

    UserTurn:
      description: A user message turn.
      type: object
      required:
        - kind
        - content
        - created_at
      properties:
        kind:
          type: string
          enum: [user]
        content:
          type: string
          description: Text content of the user message.
          example: Add rate limiting to the auth endpoints using a sliding window approach with Redis.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the turn was created.
          example: "2026-02-28T10:00:00Z"

    AssistantTurn:
      description: An assistant response turn.
      type: object
      required:
        - kind
        - content
        - created_at
      properties:
        kind:
          type: string
          enum: [assistant]
        content:
          type: string
          description: Text content of the assistant response.
          example: I'll implement sliding window rate limiting using Redis.
        created_at:
          type: string
          format: date-time
          description: Timestamp when the turn was created.
          example: "2026-02-28T10:01:00Z"

    ToolTurn:
      description: A tool invocation turn.
      type: object
      required:
        - kind
        - tools
        - created_at
      properties:
        kind:
          type: string
          enum: [tool]
        tools:
          type: array
          description: Tool invocations for this turn.
          items:
            $ref: "#/components/schemas/ToolUse"
        created_at:
          type: string
          format: date-time
          description: Timestamp when the turn was created.
          example: "2026-02-28T10:01:05Z"

    SessionDetail:
      description: Full session record including metadata and the complete conversation history.
      type: object
      required:
        - id
        - title
        - model
        - created_at
        - updated_at
        - turns
      properties:
        id:
          type: string
          format: uuid
          description: Unique session identifier.
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        title:
          type: string
          description: Short title summarizing the session topic.
          example: Add rate limiting to auth endpoints
        model:
          $ref: "#/components/schemas/ModelReference"
        created_at:
          type: string
          format: date-time
          description: Timestamp when the session was created.
          example: "2026-03-06T14:30:00Z"
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the session was last updated (e.g. new turn added).
          example: "2026-03-06T15:45:00Z"
        turns:
          type: array
          description: Ordered list of conversation turns.
          items:
            $ref: "#/components/schemas/SessionTurn"

    CreateSessionRequest:
      description: Request body for starting a new session.
      type: object
      required:
        - content
      properties:
        content:
          type: string
          description: The initial user message to start the session.
          example: Add rate limiting to the auth endpoints using a sliding window approach with Redis, 10 requests per minute per IP.
        model:
          type: string
          description: LLM model to use. If omitted, the server default is used.
          example: claude-opus-4-6
        system:
          type: string
          description: System prompt for the session.
          example: You are a helpful coding assistant.

    CreateSessionResponse:
      description: Response returned after successfully creating a session.
      type: object
      required:
        - id
        - title
        - model
        - created_at
        - updated_at
      properties:
        id:
          type: string
          format: uuid
          description: Unique identifier for the newly created session.
          example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
        title:
          type: string
          description: Server-generated title for the session.
          example: Add rate limiting to auth endpoints
        model:
          $ref: "#/components/schemas/ModelReference"
        created_at:
          type: string
          format: date-time
          description: Timestamp when the session was created.
          example: "2026-03-06T16:00:00Z"
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the session was last updated (equal to created_at at creation time).
          example: "2026-03-06T16:00:00Z"

    SendMessageRequest:
      description: Request body for sending a follow-up message in an existing session.
      type: object
      required:
        - content
      properties:
        content:
          type: string
          description: The user message text.
          example: Can you also add a bypass for internal health-check IPs?

    SendMessageResponse:
      description: Acknowledgement that the message was accepted for asynchronous processing.
      type: object
      required:
        - accepted
      properties:
        accepted:
          type: boolean
          description: Whether the message was accepted for processing.
          example: true

    # ── Insights Schemas ─────────────────────────────────────────────────

    SavedQuery:
      description: A saved SQL query for the insights editor.
      type: object
      required:
        - id
        - name
        - sql
        - created_at
        - updated_at
      properties:
        id:
          type: string
          description: Unique query identifier.
          example: "1"
        name:
          type: string
          description: Human-readable query name.
          example: Run duration by workflow
        sql:
          type: string
          description: SQL query text.
          example: "SELECT workflow_name, AVG(duration_seconds) FROM runs GROUP BY 1"
        created_at:
          type: string
          format: date-time
          description: Timestamp when the query was saved.
          example: "2026-03-01T10:00:00Z"
        updated_at:
          type: string
          format: date-time
          description: Timestamp when the query was last modified.
          example: "2026-03-05T14:30:00Z"

    SaveQueryRequest:
      description: Request body for creating or updating a saved query.
      type: object
      required:
        - name
        - sql
      properties:
        name:
          type: string
          description: Human-readable query name.
          example: Run duration by workflow
        sql:
          type: string
          description: SQL query text.
          example: "SELECT workflow_name, AVG(duration_seconds) FROM runs GROUP BY 1"

    ExecuteQueryRequest:
      description: Request body for executing an ad-hoc SQL query.
      type: object
      required:
        - sql
      properties:
        sql:
          type: string
          description: SQL query to execute.
          example: "SELECT workflow_name, COUNT(*) FROM runs GROUP BY 1"

    ExecuteQueryResponse:
      description: Columnar result set from an executed query.
      type: object
      required:
        - columns
        - rows
        - elapsed
        - row_count
      properties:
        columns:
          type: array
          description: Column names in the result set.
          items:
            type: string
          example: ["workflow_name", "count"]
        rows:
          type: array
          description: Result rows, each an array of values matching the column order.
          items:
            type: array
            items:
              oneOf:
                - type: string
                - type: number
                - type: boolean
                - type: "null"
        elapsed:
          type: number
          description: Query execution time in seconds.
          example: 0.342
        row_count:
          type: integer
          description: Number of rows returned.
          example: 3

    HistoryEntry:
      description: A previously executed query in the history log.
      type: object
      required:
        - id
        - sql
        - timestamp
        - elapsed
        - row_count
      properties:
        id:
          type: string
          description: Unique history entry identifier.
          example: h1
        sql:
          type: string
          description: SQL query that was executed.
          example: "SELECT workflow_name, COUNT(*) FROM runs GROUP BY 1"
        timestamp:
          type: string
          format: date-time
          description: ISO 8601 timestamp of execution.
          example: "2025-09-15T14:00:00Z"
        elapsed:
          type: number
          description: Query execution time in seconds.
          example: 0.342
        row_count:
          type: integer
          description: Number of rows returned.
          example: 6

    # ── Configuration Schemas ────────────────────────────────────────────

    RunConfiguration:
      description: Structured run configuration mirroring WorkflowRunConfig.
      type: object
      required:
        - version
        - graph
      properties:
        version:
          type: integer
          description: Configuration schema version.
          example: 1
        goal:
          type: string
          description: Goal description for the run.
          example: Diagnose and fix CI build failures
        graph:
          type: string
          description: Graphviz graph filename.
          example: fix_build.fabro
        work_dir:
          type: string
          description: Working directory for the run.
        llm:
          $ref: "#/components/schemas/LlmConfiguration"
        setup:
          $ref: "#/components/schemas/SetupConfiguration"
        sandbox:
          $ref: "#/components/schemas/SandboxConfiguration"
        vars:
          type: object
          additionalProperties:
            type: string
          description: Variable map for template expansion.
        hooks:
          type: array
          items:
            $ref: "#/components/schemas/HookDefinition"

    LlmConfiguration:
      description: LLM provider and model settings.
      type: object
      properties:
        model:
          type: string
          description: Model identifier.
          example: claude-sonnet
        provider:
          type: string
          description: Provider name.
          example: anthropic
        fallbacks:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
          description: Provider fallback chains.

    SetupConfiguration:
      description: Setup commands run before the workflow.
      type: object
      required:
        - commands
      properties:
        commands:
          type: array
          items:
            type: string
          description: Shell commands to execute.
        timeout_ms:
          type: integer
          description: Timeout per command in milliseconds.

    SandboxConfiguration:
      description: Sandbox execution environment settings.
      type: object
      properties:
        provider:
          type: string
          description: Sandbox provider name.
          example: daytona
        preserve:
          type: boolean
          description: Whether to preserve the sandbox after the run.
        devcontainer:
          type: boolean
          description: Whether to use a devcontainer for the sandbox.
        daytona:
          $ref: "#/components/schemas/DaytonaConfiguration"
        exe:
          $ref: "#/components/schemas/ExeConfiguration"
        ssh:
          $ref: "#/components/schemas/SshConfiguration"
        local:
          $ref: "#/components/schemas/LocalSandboxConfiguration"
        env:
          type: object
          additionalProperties:
            type: string
          description: Environment variables injected into the sandbox.

    LocalSandboxConfiguration:
      description: Local sandbox settings.
      type: object
      properties:
        worktree_mode:
          type: string
          description: Git worktree mode for local sandbox.
          enum: [always, clean, dirty, never]
          default: clean

    ExeConfiguration:
      description: exe.dev sandbox configuration.
      type: object
      properties:
        image:
          type: string
          description: VM image to use for the exe.dev sandbox.

    SshConfiguration:
      description: SSH sandbox configuration for user-provided hosts.
      type: object
      required:
        - destination
        - working_directory
      properties:
        destination:
          type: string
          description: SSH destination (e.g. user@host or an SSH alias).
        working_directory:
          type: string
          description: Remote working directory.
        config_file:
          type: string
          description: Optional path to a custom SSH config file.

    DaytonaConfiguration:
      description: Daytona-specific sandbox settings.
      type: object
      properties:
        auto_stop_interval:
          type: integer
          description: Auto-stop interval in seconds.
        labels:
          type: object
          additionalProperties:
            type: string
          description: Labels applied to the sandbox.
        snapshot:
          $ref: "#/components/schemas/DaytonaSnapshotConfiguration"
        network:
          description: "Network access mode: \"block\", \"allow_all\", or {\"allow_list\": [...]}."
          oneOf:
            - type: string
              enum:
                - block
                - allow_all
            - type: object
              required:
                - allow_list
              properties:
                allow_list:
                  type: array
                  items:
                    type: string
                  description: CIDR allowlist for network access.

    DaytonaSnapshotConfiguration:
      description: Snapshot configuration for Daytona sandboxes.
      type: object
      required:
        - name
      properties:
        name:
          type: string
          description: Snapshot name.
        cpu:
          type: integer
          description: CPU cores.
        memory:
          type: integer
          description: Memory in GB.
        disk:
          type: integer
          description: Disk in GB.
        dockerfile:
          type: string
          description: Dockerfile content for snapshot creation.

    HookDefinition:
      description: |
        A single hook definition. The type discriminator and variant fields are flattened into this object.

        Field-to-type mapping:
        - `command`: requires `command`
        - `http`: requires `url`; optional `headers`, `allowed_env_vars`, `tls`
        - `prompt`: requires `prompt`; optional `model`
        - `agent`: requires `prompt`; optional `model`, `max_tool_rounds`

        Top-level `command` without `type` is shorthand for type=command.
      type: object
      required:
        - event
      properties:
        name:
          type: string
          description: Human-readable hook name.
        event:
          type: string
          description: Event that triggers this hook.
          enum:
            - run_start
            - run_complete
            - stage_start
            - stage_complete
        command:
          type: string
          description: Shell command (shorthand for type=command).
        type:
          type: string
          description: Hook execution type.
          enum:
            - command
            - http
            - prompt
            - agent
        url:
          type: string
          description: URL for HTTP hooks.
        headers:
          type: object
          additionalProperties:
            type: string
          description: Headers for HTTP hooks.
        allowed_env_vars:
          type: array
          items:
            type: string
          description: Environment variables allowed in HTTP hook headers.
        tls:
          type: string
          description: TLS verification mode for HTTP hooks.
          enum:
            - verify
            - no_verify
            - "off"
        prompt:
          type: string
          description: Prompt text for prompt/agent hooks.
        model:
          type: string
          description: Model for prompt/agent hooks.
        max_tool_rounds:
          type: integer
          description: Max tool rounds for agent hooks.
        matcher:
          type: string
          description: Regex matched against node_id or handler_type.
        blocking:
          type: boolean
          description: Whether this hook blocks execution.
        timeout_ms:
          type: integer
          description: Timeout in milliseconds.
        sandbox:
          type: boolean
          description: Whether hook runs in sandbox.

    ServerConfiguration:
      description: Structured server configuration mirroring ServerConfig.
      type: object
      properties:
        data_dir:
          type: string
          description: Data directory path.
        max_concurrent_runs:
          type: integer
          description: Maximum concurrent runs.
        web:
          $ref: "#/components/schemas/WebConfiguration"
        api:
          $ref: "#/components/schemas/ApiConfiguration"
        git:
          $ref: "#/components/schemas/GitConfiguration"
        features:
          $ref: "#/components/schemas/Features"
        log:
          $ref: "#/components/schemas/LogConfiguration"
        work_dir:
          type: string
          description: Default working directory.
        llm:
          $ref: "#/components/schemas/LlmConfiguration"
        setup:
          $ref: "#/components/schemas/SetupConfiguration"
        sandbox:
          $ref: "#/components/schemas/SandboxConfiguration"
        vars:
          type: object
          additionalProperties:
            type: string
          description: Default variable map.
        checkpoint:
          $ref: "#/components/schemas/CheckpointConfiguration"
        pull_request:
          $ref: "#/components/schemas/PullRequestConfiguration"
        hooks:
          type: array
          items:
            $ref: "#/components/schemas/HookDefinition"
        assets:
          $ref: "#/components/schemas/AssetsConfiguration"
        mcp_servers:
          type: object
          additionalProperties:
            $ref: "#/components/schemas/McpServerEntry"
          description: Default MCP server configurations.
        github:
          $ref: "#/components/schemas/GitHubConfiguration"

    GitHubConfiguration:
      description: GitHub App token injection configuration.
      type: object
      properties:
        permissions:
          type: object
          additionalProperties:
            type: string
          description: GitHub API permissions to request (e.g. contents = write).

    McpServerEntry:
      description: MCP server connection entry.
      type: object
      properties:
        type:
          type: string
          description: Transport type (stdio or http).
        command:
          type: array
          items:
            type: string
          description: Command and arguments for stdio transport.
        env:
          type: object
          additionalProperties:
            type: string
          description: Environment variables for stdio transport.
        url:
          type: string
          description: URL for http transport.
        headers:
          type: object
          additionalProperties:
            type: string
          description: HTTP headers for http transport.
        startup_timeout_secs:
          type: integer
          description: Startup timeout in seconds.
        tool_timeout_secs:
          type: integer
          description: Tool call timeout in seconds.

    AssetsConfiguration:
      description: Asset collection configuration.
      type: object
      properties:
        include:
          type: array
          items:
            type: string
          description: Glob patterns for files to collect as run assets.

    LogConfiguration:
      description: Logging configuration.
      type: object
      properties:
        level:
          type: string
          description: Log level (e.g. trace, debug, info).

    CheckpointConfiguration:
      description: Checkpoint configuration for file exclusion.
      type: object
      properties:
        exclude_globs:
          type: array
          items:
            type: string
          description: Glob patterns to exclude from checkpoints.

    PullRequestConfiguration:
      description: Pull request creation configuration.
      type: object
      properties:
        enabled:
          type: boolean
          description: Whether to create a pull request after a successful run.
        draft:
          type: boolean
          description: Whether to create the pull request as a draft.
        auto_merge:
          type: boolean
          description: Whether to enable GitHub auto-merge on the created PR. Implies draft = false.
        merge_strategy:
          type: string
          enum: [squash, merge, rebase]
          description: Merge strategy for auto-merge.

    WebConfiguration:
      description: Web UI configuration.
      type: object
      properties:
        url:
          type: string
          description: Web UI URL.
        auth:
          $ref: "#/components/schemas/AuthConfiguration"

    AuthConfiguration:
      description: Authentication configuration.
      type: object
      properties:
        provider:
          type: string
          description: Auth provider.
          enum:
            - github
            - insecure_disabled
        allowed_usernames:
          type: array
          items:
            type: string
          description: Allowed usernames.

    ApiConfiguration:
      description: API server configuration.
      type: object
      properties:
        base_url:
          type: string
          description: API base URL.
        authentication_strategies:
          type: array
          items:
            type: string
            enum:
              - jwt
              - mtls
          description: Authentication strategies.
        tls:
          $ref: "#/components/schemas/TlsConfiguration"

    TlsConfiguration:
      description: TLS certificate configuration.
      type: object
      required:
        - cert
        - key
        - ca
      properties:
        cert:
          type: string
          description: Certificate file path.
        key:
          type: string
          description: Key file path.
        ca:
          type: string
          description: CA certificate file path.

    GitConfiguration:
      description: Git provider configuration.
      type: object
      properties:
        provider:
          type: string
          description: Git provider.
          enum:
            - github
        app_id:
          type: string
          description: GitHub App ID.
        client_id:
          type: string
          description: GitHub App Client ID.
        slug:
          type: string
          description: GitHub App slug.
        author:
          $ref: "#/components/schemas/GitAuthorConfiguration"
        webhooks:
          $ref: "#/components/schemas/WebhookConfiguration"

    GitAuthorConfiguration:
      description: Git commit author configuration.
      type: object
      properties:
        name:
          type: string
          description: Author name for commits.
        email:
          type: string
          description: Author email for commits.

    WebhookConfiguration:
      description: Webhook delivery configuration.
      type: object
      required:
        - strategy
      properties:
        strategy:
          type: string
          description: Webhook delivery strategy.
          enum:
            - tailscale_funnel

    Features:
      description: Feature flags.
      type: object
      properties:
        session_sandboxes:
          type: boolean
          description: Enable session sandboxes.
        retros:
          type: boolean
          description: "Experimental: enable automatic retro generation after workflow runs."

    # ── Discovery Schemas ────────────────────────────────────────────────

    RootResponseUrls:
      description: Collection of API discovery URLs.
      type: object
      required:
        - openapi_url
        - current_user_url
        - health_url
      properties:
        openapi_url:
          type: string
          description: URL of the OpenAPI JSON specification.
          example: /openapi.json
        current_user_url:
          type: string
          description: URL of the current user endpoint.
          example: /user
        health_url:
          type: string
          description: URL of the health check endpoint.
          example: /health

    RootResponse:
      description: API discovery response with navigation URLs.
      type: object
      required:
        - urls
      properties:
        urls:
          $ref: "#/components/schemas/RootResponseUrls"

    HealthResponse:
      description: Service health check response.
      type: object
      required:
        - status
      properties:
        status:
          type: string
          description: Health status indicator.
          example: ok

    UserResponse:
      description: Information about the authenticated user.
      type: object
      required:
        - login
      properties:
        login:
          type: string
          description: User's login identifier (e.g. GitHub username).
          example: octocat