{"openapi":"3.0.3","info":{"title":"ultrarouter API","version":"0.0.0","description":"OpenAI/OpenRouter-compatible AI gateway: proxy + compression + continuous evals + auto-routing. This spec is generated from the API route schemas (never hand-edited) and checked in CI against the served API."},"servers":[{"url":"http://localhost:8080","description":"A self-hosted ultrarouter gateway (the local dev stack listens here); use your deployment's URL."}],"tags":[{"name":"Adaptive optimization"},{"name":"API keys","description":"API-key provisioning."},{"name":"Audit","description":"Zero-configuration Audit Autopilot — the passive readiness report."},{"name":"Bench","description":"ultrarouter Bench — dev/test capture suites + readiness."},{"name":"Billing"},{"name":"Call types","description":"Programmatic call-type config (the objects the dashboard edits)."},{"name":"Chat","description":"OpenAI-compatible chat completions (streaming + non-streaming)."},{"name":"Custom providers","description":"Workspace-owned OpenAI-compatible providers."},{"name":"Embeddings","description":"Multi-provider embeddings."},{"name":"Feedback","description":"Human feedback that feeds evals."},{"name":"Flywheel","description":"The outcome ledger — artifacts, typed outcome events, finals, pending claims."},{"name":"Generation","description":"Post-hoc per-request stats (OpenRouter parity)."},{"name":"Invitations","description":"Workspace invitations."},{"name":"Keys","description":"API-key introspection."},{"name":"Knowledge"},{"name":"Learning","description":"Per-call-type learning controls — status, self-serve enable, pause / resume / disable, versions, evaluations, rollback and manual promote / reject."},{"name":"Members","description":"Workspace membership management."},{"name":"Models","description":"The model catalog and per-provider offers."},{"name":"Ops","description":"Operational probes and smoke endpoints."},{"name":"Passthrough"},{"name":"Preflight","description":"Ask what the gateway would decide before a non-proxied call — model, fallbacks, learned knowledge, placement."},{"name":"Provider keys","description":"BYOK provider keys (write-only secrets)."},{"name":"Workspaces","description":"Workspace tenancy management."}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"ur_sk","description":"ultrarouter API key: `Authorization: Bearer ur_sk_live_…` / `ur_sk_test_…`."},"sessionCookie":{"type":"apiKey","in":"cookie","name":"better-auth.session_token","description":"Dashboard session cookie (Better Auth). Prefixed `__Secure-` over HTTPS; management routes also enforce workspace RBAC + 2FA for owner/admin actions."}},"schemas":{"GatewayError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable error code (e.g. `invalid_request`, `authentication`, `rate_limited`, `spend_cap_exceeded`, `provider_unavailable`); the HTTP status and retryability follow from it."},"message":{"type":"string","description":"Human-readable, secret-free explanation."},"provider_code":{"type":"string","description":"Raw upstream provider error code, when a provider produced the failure."},"request_id":{"type":"string","description":"Correlation id (`req_…`) echoed on `x-ur-request-id`."},"retryable":{"type":"boolean","description":"Whether a client may safely retry this request as-is."}},"required":["code","message","request_id","retryable"]}},"required":["error"],"description":"Normalized gateway error."},"ApiError":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","description":"Stable, machine-readable error code (e.g. `unauthorized`, `forbidden`, `2fa_required`, `not_found`, `validation_error`, `conflict`, `rate_limited`); the HTTP status follows from it."},"message":{"type":"string","description":"Human-readable, secret-free explanation."},"request_id":{"type":"string","description":"Correlation id (`req_…`)."}},"required":["code","message"]}},"required":["error"],"description":"Normalized management-plane error envelope."},"ChatCompletionsRequest":{"type":"object","properties":{"model":{"type":"string","description":"Provider-prefixed model id, e.g. \"openai/gpt-5.2-mini\"."},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["system","developer","user","assistant","tool"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"The content part type (\"text\" | \"image_url\" | …)."},"text":{"type":"string","description":"The text of a text part."},"cache_control":{"type":"object","properties":{"type":{"type":"string","enum":["ephemeral"],"description":"The only supported cache type."},"ttl":{"type":"string","description":"Cache lifetime hint, e.g. \"5m\" (default) or \"1h\"."}},"required":["type"],"description":"Mark this content part as a prompt-cache breakpoint. Translated to Anthropic `cache_control` on the block; stripped + ignored (structured log) for non-Anthropic providers."}},"description":"One OpenAI-shaped message content part; may carry a `cache_control` breakpoint."}}],"nullable":true},"name":{"type":"string"},"tool_calls":{"type":"array","items":{"nullable":true}},"tool_call_id":{"type":"string"}},"required":["role"],"description":"An OpenAI-shaped chat message."},"minItems":1,"description":"Conversation messages (required)."},"tools":{"type":"array","items":{"nullable":true},"description":"Tool/function definitions."},"tool_choice":{"anyOf":[{"type":"string"},{"type":"object","additionalProperties":{"nullable":true}}],"description":"Tool selection strategy."},"response_format":{"anyOf":[{"type":"object","properties":{"type":{"type":"string","enum":["text"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["json_object"]}},"required":["type"]},{"type":"object","properties":{"type":{"type":"string","enum":["json_schema"]},"json_schema":{"type":"object","additionalProperties":{"nullable":true}}},"required":["type","json_schema"]}],"description":"Structured-output format (incl. json_schema)."},"temperature":{"type":"number","minimum":0,"maximum":2},"top_p":{"type":"number","minimum":0,"maximum":1},"max_tokens":{"type":"integer","minimum":0,"exclusiveMinimum":true},"max_completion_tokens":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The modern OpenAI max-output-token budget (visible + reasoning tokens). Carried to every adapter (OpenAI reasoning models require it in place of `max_tokens`; other providers map it to their own max-output field). When BOTH `max_completion_tokens` and `max_tokens` are sent, `max_completion_tokens` wins — the metered ceiling equals the cap actually sent."},"reasoning_effort":{"type":"string","enum":["none","minimal","low","medium","high"],"description":"The OpenAI reasoning-effort control, carried to every adapter. Forwarded verbatim to OpenAI-compatible providers (OpenAI reasoning models honour it; it also decides whether sampling parameters such as `temperature` are forwarded to those models); MAPPED to a thinking-token budget for budget-based providers (Anthropic / Gemini / Bedrock-Anthropic per the OpenRouter reference); refused with a NAMED `capability_unsupported` error where a provider has no reasoning knob — never silently dropped. The structured `reasoning` object takes precedence when both are sent."},"reasoning":{"type":"object","properties":{"effort":{"type":"string","enum":["none","minimal","low","medium","high"],"description":"Reasoning effort: none | minimal | low | medium | high (OpenAI / OpenRouter reference)."},"max_tokens":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Direct thinking-token budget (budget-based providers; min 1024)."},"exclude":{"type":"boolean","description":"Drop reasoning tokens from the response — unsupported, refused NAMED when true."}},"description":"OpenRouter-native reasoning control (`{ effort, max_tokens, exclude }`)."},"stop":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}]},"stream":{"type":"boolean","description":"Stream the response as server-sent events (OpenAI `chat.completion.chunk` format)."},"stream_options":{"type":"object","additionalProperties":{"nullable":true}},"seed":{"type":"integer"},"logprobs":{"type":"boolean"},"top_logprobs":{"type":"integer","minimum":0,"maximum":20},"n":{"type":"integer","minimum":0,"exclusiveMinimum":true},"frequency_penalty":{"type":"number","minimum":-2,"maximum":2},"presence_penalty":{"type":"number","minimum":-2,"maximum":2},"user":{"type":"string"},"models":{"type":"array","items":{"type":"string"},"description":"Ordered fallback model ids (OpenRouter)."},"router":{"type":"string","enum":["off","auto","candidates"],"description":"Routing mode; when no config layer sets one, the system default is \"off\"."},"call_type":{"type":"string","description":"Stable call-type slug."},"compression":{"anyOf":[{"type":"string","enum":["off","semantic_safe","adaptive","lossless","auto"]},{"type":"object","properties":{"mode":{"type":"string","enum":["off","semantic_safe","adaptive","lossless","auto"]},"no_compress_fields":{"type":"array","items":{"type":"string"}},"max_quality_risk":{"type":"string","enum":["low","medium","high"]}}}]},"provider":{"type":"object","properties":{"order":{"type":"array","items":{"type":"string"}},"allow_fallbacks":{"type":"boolean"},"ignore":{"type":"array","items":{"type":"string"}},"require_parameters":{"type":"boolean"},"data_collection":{"type":"string","enum":["allow","deny"]},"quantizations":{"type":"array","items":{"type":"string"}},"sort":{"type":"string","enum":["price","throughput","latency"]}},"description":"OpenRouter-parity provider preferences."},"ur":{"type":"object","properties":{"trace_id":{"type":"string"},"artifact":{"type":"string","description":"The DECLARED artifact key this request contributes to (pre-dispatch assembly). Binds the served request to the artifact (`assembly_source=declared_request`) and is the standing-holdout cluster key; the response `ur.artifact_id` echoes the bound id. Equivalent to the `X-UR-Artifact` header; the body wins on conflict."},"tags":{"type":"object","additionalProperties":{"type":"string"}},"max_cost_usd":{"type":"number","minimum":0},"timeout_ms":{"type":"integer","minimum":0,"exclusiveMinimum":true},"segments":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0,"description":"Index into the `messages` array."},"kind":{"type":"string","enum":["system_instructions","user_question","reference_context","few_shot_examples","tool_results","history"],"description":"The segment kind the SDK asserts for that message."},"start":{"type":"integer","minimum":0,"description":"Optional span start (char offset) within the message content."},"end":{"type":"integer","minimum":0,"description":"Optional span end (char offset, exclusive) within the message content."}},"required":["index","kind"],"description":"An SDK-provided segment label for one message or span."},"description":"SDK segment-part labels to refine compression segmentation."},"manifest":{"type":"object","properties":{"scaffold_hash":{"type":"string","minLength":1,"description":"The call-type identity (kinds/slots/ids only, stable across executions)."},"manifest_hash":{"type":"string","minLength":1,"description":"The declared per-execution manifest hash."},"envelope_hash":{"type":"string","minLength":1,"description":"The declared execution-envelope hash."},"entries":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","minLength":1,"description":"The context module kind (opaque label; drives no branching)."},"slot":{"type":"string","minLength":1,"description":"The rendering slot ('instruction' | 'reference' | 'exemplar' | …)."},"trust_class":{"type":"string","minLength":1,"description":"Trust class ('authoritative' | 'approved_derived' | 'untrusted')."},"memory_class":{"type":"string","minLength":1,"description":"The memory class (opaque label)."},"content_hash":{"type":"string","minLength":1,"description":"sha256 hex over the declared slice (or canonical JSON of an opaque part)."},"mandatory":{"type":"boolean","description":"Whether the module was mandatory in the compiled manifest."},"order":{"type":"integer","minimum":0,"description":"Position in the compiled manifest order."},"range":{"type":"object","properties":{"message_index":{"type":"integer","minimum":0,"description":"Index into the `messages` array."},"part_index":{"type":"integer","minimum":0,"description":"Index into a multi-part message content array (omit for string content)."},"start":{"type":"integer","minimum":0,"description":"Span start (UTF-16 code-unit offset)."},"end":{"type":"integer","minimum":0,"description":"Span end (UTF-16 code-unit offset, exclusive)."}},"required":["message_index","start","end"],"description":"The exact declared range; absent for an opaque part hashed over canonical JSON."}},"required":["kind","slot","trust_class","memory_class","content_hash","mandatory","order"],"description":"One declared context-manifest entry."},"description":"The ordered declared entries."}},"required":["scaffold_hash","manifest_hash","envelope_hash","entries"],"description":"Declared context manifest (`toWire(manifest)`); the gateway witnesses it (verifies every hash against the received bytes before any transform) and drives compression eligibility from the declared kinds."},"bench":{"anyOf":[{"type":"string","minLength":1,"description":"The bench suite slug (auto-created on first use)."},{"type":"object","properties":{"suite":{"type":"string","minLength":1,"description":"The bench suite slug (auto-created on first use)."},"run":{"type":"string","description":"Capture-window label (commit SHA/branch/agent)."},"trace":{"type":"string","description":"Multi-call task grouping id."}},"required":["suite"]}],"description":"ultrarouter Bench capture activation."},"context_modules":{"type":"array","items":{"type":"object","properties":{"module_id":{"type":"string","minLength":1,"description":"The learned-context module id (`lcm_…`)."},"module_version":{"type":"string","minLength":1,"description":"The PINNED module version — the recipe hash (`lcm1_…`)."}},"required":["module_id","module_version"],"description":"A pinned learned-context module reference."},"maxItems":8,"description":"The ordered `profile.contextModules[]` this call opts into — the `learned_context` lever surface. Each entry pins a module id AND its exact version (a retrieval-backed version IS its recipe hash), so a pack change or a ranker refit can never be served under an old pin. The gateway rebuilds the pack from the pinned recipe, refuses fail-closed on any mismatch, and SKIPS injection entirely for a holdout request."},"prompt_vars":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"The values for the ACTIVE hosted prompt’s `{{name}}` variables, when the gateway applies a hosted prompt for this call type (`gateway_apply`). A missing REQUIRED variable is a named `prompt_variables_missing` refusal (never a silent blank). Ignored when no hosted prompt is applied."}},"description":"ultrarouter per-request controls."},"metadata":{"type":"object","additionalProperties":{"nullable":true},"description":"Opaque JSON stored with the request."}},"required":["messages"],"description":"OpenAI-compatible chat-completions request with ultrarouter extensions."},"ChatCompletionsResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["chat.completion"]},"created":{"type":"integer"},"model":{"type":"string"},"choices":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0},"message":{"type":"object","properties":{"role":{"type":"string"},"content":{"type":"string","nullable":true},"tool_calls":{"type":"array","items":{"nullable":true}}},"required":["role"]},"finish_reason":{"type":"string","nullable":true},"logprobs":{"nullable":true}},"required":["index","message","finish_reason"]}},"usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer","minimum":0},"completion_tokens":{"type":"integer","minimum":0},"total_tokens":{"type":"integer","minimum":0},"prompt_tokens_details":{"type":"object","properties":{"cached_tokens":{"type":"integer","minimum":0}}}},"required":["prompt_tokens","completion_tokens","total_tokens"],"description":"OpenAI usage accounting."},"system_fingerprint":{"type":"string"},"ur":{"type":"object","properties":{"request_id":{"type":"string","description":"Correlation id (`req_…`)."},"call_type":{"type":"string","nullable":true,"description":"Resolved call type, or null when none was resolved."},"model_served":{"type":"string","description":"The model actually served."},"provider":{"type":"string","description":"The provider that served it."},"routing":{"type":"object","properties":{"mode":{"type":"string","enum":["off","auto","candidates"]},"fallback_used":{"type":"boolean"},"engine":{"type":"string","description":"\"policy\" when the auto-routing policy engine ran (auto/candidates); \"verified_memory\" when the request was answered from the workspace’s verified memory (no provider was called)."}},"required":["mode","fallback_used"],"description":"Routing decision summary."},"compression":{"type":"object","properties":{"applied":{"type":"string","enum":["off","semantic_safe","adaptive"],"description":"The compression safety tier actually applied."},"source":{"type":"string","enum":["off","qualified","unqualified-legacy"],"description":"Provenance of the applied tier (unqualified-legacy = no shadow evidence yet)."},"deprecated_alias":{"type":"string","enum":["lossless","auto"],"description":"Set when the request used a deprecated legacy compression alias."},"tokens_saved":{"type":"integer"},"est_saved_usd":{"type":"number","description":"Estimated saved USD — a diagnostic (chars/4)."},"savings_basis":{"type":"string","enum":["provider_reported","estimated_diagnostic"],"description":"Whether a savings ledger line was recorded (provider-reported usage) or the figure is a diagnostic only."},"verify":{"type":"string"}},"required":["applied"],"description":"Compression summary — the applied compression safety tier + honest savings provenance."},"cost_usd":{"type":"number","minimum":0,"description":"Total request cost in USD."},"byok":{"type":"boolean","description":"Whether a workspace BYOK key served the request."},"artifact_id":{"type":"string","description":"The flywheel artifact id this request was bound to — present only when the request DECLARED an artifact (`ur.artifact` / `X-UR-Artifact`). Absent otherwise."},"bench":{"type":"object","properties":{"suite":{"type":"string","description":"The bench suite slug this call was captured into."},"run":{"type":"string","nullable":true,"description":"The capture-window run tag, or null."},"capture_status":{"type":"string","enum":["queued"],"description":"Honest capture status: an API response may only ever say \"queued\" — the capture is enqueued durably (same-tx outbox); only a persisted envelope is \"confirmed\" (read it via the bench suite readiness meter)."}},"required":["suite","run","capture_status"],"description":"ultrarouter Bench capture echo — present only on a bench-tagged call."},"verified_memory":{"type":"object","properties":{"lever_version":{"type":"string"},"rule_version":{"type":"string"},"pool_fact_id":{"type":"string"},"pool_hash":{"type":"string"},"case_ids":{"type":"array","items":{"type":"string"},"description":"The `cex1_…` ids of the verified cases that decided the answer (nearest first)."},"agreeing_items":{"type":"integer","minimum":0},"similarity":{"type":"number","minimum":0,"maximum":1},"agreement":{"type":"number","minimum":0,"maximum":1},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"tau_s":{"type":"number","minimum":0,"maximum":1},"tau_a":{"type":"number","minimum":0,"maximum":1}},"required":["lever_version","rule_version","pool_fact_id","pool_hash","case_ids","agreeing_items","similarity","agreement","k","tau_s","tau_a"],"description":"Verified-memory answer details: present ONLY when the request was answered from the workspace’s verified memory (no provider was called; `ur.routing.engine` = `verified_memory`, `cost_usd` = 0)."}},"required":["request_id","call_type","model_served","provider","routing","compression","cost_usd","byok"],"description":"ultrarouter response extension block."}},"required":["id","object","created","model","choices","usage","ur"],"description":"OpenAI-compatible chat-completions response with the ultrarouter `ur` block."},"UrResponseBlock":{"type":"object","properties":{"request_id":{"type":"string","description":"Correlation id (`req_…`)."},"call_type":{"type":"string","nullable":true,"description":"Resolved call type, or null when none was resolved."},"model_served":{"type":"string","description":"The model actually served."},"provider":{"type":"string","description":"The provider that served it."},"routing":{"type":"object","properties":{"mode":{"type":"string","enum":["off","auto","candidates"]},"fallback_used":{"type":"boolean"},"engine":{"type":"string","description":"\"policy\" when the auto-routing policy engine ran (auto/candidates); \"verified_memory\" when the request was answered from the workspace’s verified memory (no provider was called)."}},"required":["mode","fallback_used"],"description":"Routing decision summary."},"compression":{"type":"object","properties":{"applied":{"type":"string","enum":["off","semantic_safe","adaptive"],"description":"The compression safety tier actually applied."},"source":{"type":"string","enum":["off","qualified","unqualified-legacy"],"description":"Provenance of the applied tier (unqualified-legacy = no shadow evidence yet)."},"deprecated_alias":{"type":"string","enum":["lossless","auto"],"description":"Set when the request used a deprecated legacy compression alias."},"tokens_saved":{"type":"integer"},"est_saved_usd":{"type":"number","description":"Estimated saved USD — a diagnostic (chars/4)."},"savings_basis":{"type":"string","enum":["provider_reported","estimated_diagnostic"],"description":"Whether a savings ledger line was recorded (provider-reported usage) or the figure is a diagnostic only."},"verify":{"type":"string"}},"required":["applied"],"description":"Compression summary — the applied compression safety tier + honest savings provenance."},"cost_usd":{"type":"number","minimum":0,"description":"Total request cost in USD."},"byok":{"type":"boolean","description":"Whether a workspace BYOK key served the request."},"artifact_id":{"type":"string","description":"The flywheel artifact id this request was bound to — present only when the request DECLARED an artifact (`ur.artifact` / `X-UR-Artifact`). Absent otherwise."},"bench":{"type":"object","properties":{"suite":{"type":"string","description":"The bench suite slug this call was captured into."},"run":{"type":"string","nullable":true,"description":"The capture-window run tag, or null."},"capture_status":{"type":"string","enum":["queued"],"description":"Honest capture status: an API response may only ever say \"queued\" — the capture is enqueued durably (same-tx outbox); only a persisted envelope is \"confirmed\" (read it via the bench suite readiness meter)."}},"required":["suite","run","capture_status"],"description":"ultrarouter Bench capture echo — present only on a bench-tagged call."},"verified_memory":{"type":"object","properties":{"lever_version":{"type":"string"},"rule_version":{"type":"string"},"pool_fact_id":{"type":"string"},"pool_hash":{"type":"string"},"case_ids":{"type":"array","items":{"type":"string"},"description":"The `cex1_…` ids of the verified cases that decided the answer (nearest first)."},"agreeing_items":{"type":"integer","minimum":0},"similarity":{"type":"number","minimum":0,"maximum":1},"agreement":{"type":"number","minimum":0,"maximum":1},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"tau_s":{"type":"number","minimum":0,"maximum":1},"tau_a":{"type":"number","minimum":0,"maximum":1}},"required":["lever_version","rule_version","pool_fact_id","pool_hash","case_ids","agreeing_items","similarity","agreement","k","tau_s","tau_a"],"description":"Verified-memory answer details: present ONLY when the request was answered from the workspace’s verified memory (no provider was called; `ur.routing.engine` = `verified_memory`, `cost_usd` = 0)."}},"required":["request_id","call_type","model_served","provider","routing","compression","cost_usd","byok"],"description":"ultrarouter response extension block."},"EmbeddingsRequest":{"type":"object","properties":{"model":{"type":"string","description":"Provider-prefixed embeddings model id, e.g. \"openai/text-embedding-4-small\"."},"input":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"string"},"minItems":1}],"description":"A string or array of strings to embed."},"dimensions":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Optional output dimensionality (provider-supported models only)."},"encoding_format":{"type":"string","enum":["float","base64"],"description":"Output encoding, passed through to the provider. The official OpenAI SDK defaults to `base64` (it decodes client-side), so both are accepted for OpenAI-client compatibility."},"user":{"type":"string","description":"Opaque end-user id (OpenAI parity)."},"call_type":{"type":"string","description":"Stable call-type slug (selects the call type whose config applies)."},"ur":{"type":"object","properties":{"trace_id":{"type":"string"},"artifact":{"type":"string","description":"The DECLARED artifact key this request contributes to (pre-dispatch assembly). Binds the served request to the artifact (`assembly_source=declared_request`) and is the standing-holdout cluster key; the response `ur.artifact_id` echoes the bound id. Equivalent to the `X-UR-Artifact` header; the body wins on conflict."},"tags":{"type":"object","additionalProperties":{"type":"string"}},"max_cost_usd":{"type":"number","minimum":0},"timeout_ms":{"type":"integer","minimum":0,"exclusiveMinimum":true},"segments":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0,"description":"Index into the `messages` array."},"kind":{"type":"string","enum":["system_instructions","user_question","reference_context","few_shot_examples","tool_results","history"],"description":"The segment kind the SDK asserts for that message."},"start":{"type":"integer","minimum":0,"description":"Optional span start (char offset) within the message content."},"end":{"type":"integer","minimum":0,"description":"Optional span end (char offset, exclusive) within the message content."}},"required":["index","kind"],"description":"An SDK-provided segment label for one message or span."},"description":"SDK segment-part labels to refine compression segmentation."},"manifest":{"type":"object","properties":{"scaffold_hash":{"type":"string","minLength":1,"description":"The call-type identity (kinds/slots/ids only, stable across executions)."},"manifest_hash":{"type":"string","minLength":1,"description":"The declared per-execution manifest hash."},"envelope_hash":{"type":"string","minLength":1,"description":"The declared execution-envelope hash."},"entries":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","minLength":1,"description":"The context module kind (opaque label; drives no branching)."},"slot":{"type":"string","minLength":1,"description":"The rendering slot ('instruction' | 'reference' | 'exemplar' | …)."},"trust_class":{"type":"string","minLength":1,"description":"Trust class ('authoritative' | 'approved_derived' | 'untrusted')."},"memory_class":{"type":"string","minLength":1,"description":"The memory class (opaque label)."},"content_hash":{"type":"string","minLength":1,"description":"sha256 hex over the declared slice (or canonical JSON of an opaque part)."},"mandatory":{"type":"boolean","description":"Whether the module was mandatory in the compiled manifest."},"order":{"type":"integer","minimum":0,"description":"Position in the compiled manifest order."},"range":{"type":"object","properties":{"message_index":{"type":"integer","minimum":0,"description":"Index into the `messages` array."},"part_index":{"type":"integer","minimum":0,"description":"Index into a multi-part message content array (omit for string content)."},"start":{"type":"integer","minimum":0,"description":"Span start (UTF-16 code-unit offset)."},"end":{"type":"integer","minimum":0,"description":"Span end (UTF-16 code-unit offset, exclusive)."}},"required":["message_index","start","end"],"description":"The exact declared range; absent for an opaque part hashed over canonical JSON."}},"required":["kind","slot","trust_class","memory_class","content_hash","mandatory","order"],"description":"One declared context-manifest entry."},"description":"The ordered declared entries."}},"required":["scaffold_hash","manifest_hash","envelope_hash","entries"],"description":"Declared context manifest (`toWire(manifest)`); the gateway witnesses it (verifies every hash against the received bytes before any transform) and drives compression eligibility from the declared kinds."},"bench":{"anyOf":[{"type":"string","minLength":1,"description":"The bench suite slug (auto-created on first use)."},{"type":"object","properties":{"suite":{"type":"string","minLength":1,"description":"The bench suite slug (auto-created on first use)."},"run":{"type":"string","description":"Capture-window label (commit SHA/branch/agent)."},"trace":{"type":"string","description":"Multi-call task grouping id."}},"required":["suite"]}],"description":"ultrarouter Bench capture activation."},"context_modules":{"type":"array","items":{"type":"object","properties":{"module_id":{"type":"string","minLength":1,"description":"The learned-context module id (`lcm_…`)."},"module_version":{"type":"string","minLength":1,"description":"The PINNED module version — the recipe hash (`lcm1_…`)."}},"required":["module_id","module_version"],"description":"A pinned learned-context module reference."},"maxItems":8,"description":"The ordered `profile.contextModules[]` this call opts into — the `learned_context` lever surface. Each entry pins a module id AND its exact version (a retrieval-backed version IS its recipe hash), so a pack change or a ranker refit can never be served under an old pin. The gateway rebuilds the pack from the pinned recipe, refuses fail-closed on any mismatch, and SKIPS injection entirely for a holdout request."},"prompt_vars":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"}]},"description":"The values for the ACTIVE hosted prompt’s `{{name}}` variables, when the gateway applies a hosted prompt for this call type (`gateway_apply`). A missing REQUIRED variable is a named `prompt_variables_missing` refusal (never a silent blank). Ignored when no hosted prompt is applied."}},"description":"ultrarouter per-request controls."},"metadata":{"type":"object","additionalProperties":{"nullable":true},"description":"Opaque JSON stored with the request."}},"required":["model","input"],"description":"OpenAI-compatible embeddings request with ultrarouter extensions."},"EmbeddingsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["embedding"]},"index":{"type":"integer","minimum":0},"embedding":{"anyOf":[{"type":"array","items":{"type":"number"}},{"type":"string"}]}},"required":["object","index","embedding"]}},"model":{"type":"string"},"usage":{"type":"object","properties":{"prompt_tokens":{"type":"integer","minimum":0},"total_tokens":{"type":"integer","minimum":0}},"required":["prompt_tokens","total_tokens"]},"ur":{"type":"object","properties":{"request_id":{"type":"string"},"call_type":{"type":"string","nullable":true},"model_served":{"type":"string"},"provider":{"type":"string"},"routing":{"type":"object","properties":{"mode":{"type":"string"},"fallback_used":{"type":"boolean"},"engine":{"type":"string"}},"required":["mode","fallback_used"]},"cost_usd":{"type":"number","minimum":0},"byok":{"type":"boolean"}},"required":["request_id","call_type","model_served","provider","routing","cost_usd","byok"],"description":"ultrarouter response extension block."}},"required":["object","data","model","usage","ur"],"description":"OpenAI-compatible embeddings response with the ultrarouter `ur` block."},"ModelsListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["model"]},"name":{"type":"string"},"provider":{"type":"string"},"context_length":{"type":"integer","nullable":true},"capabilities":{"type":"object","additionalProperties":{"nullable":true}},"pricing":{"type":"object","properties":{"input_micro_usd_per_1m":{"type":"integer","minimum":0},"output_micro_usd_per_1m":{"type":"integer","minimum":0},"cached_input_micro_usd_per_1m":{"type":"integer","nullable":true,"minimum":0},"input_usd_per_1m":{"type":"number","minimum":0},"output_usd_per_1m":{"type":"number","minimum":0}},"required":["input_micro_usd_per_1m","output_micro_usd_per_1m","cached_input_micro_usd_per_1m","input_usd_per_1m","output_usd_per_1m"],"description":"List pricing in integer micro-USD per 1M tokens (money is integer micro-USD)."},"active":{"type":"boolean"},"origin_jurisdiction":{"type":"string","description":"PROVENANCE — the developing lab's ISO 3166-1 alpha-2 jurisdiction (e.g. US/CN/FR/CA), RESOLVED for this row (an offer inherits it from the logical model it serves), or \"unknown\"."},"weights":{"type":"string","enum":["open","closed","unknown"],"description":"Whether the LOGICAL model weights are downloadable — open | closed | unknown (fail-closed)."},"hosting_jurisdiction":{"type":"string","description":"HOSTING — where THIS offer RUNS (ISO 3166-1 alpha-2), or \"unknown\". A CN-origin open-weight model HOSTED in the US shows origin_jurisdiction \"CN\" + hosting_jurisdiction \"US\"."},"hosting_region":{"type":"string","nullable":true,"description":"HOSTING — the provider-published serving region (e.g. us-east-1), or null."},"workspace_custom":{"type":"boolean","description":"True on a WORKSPACE custom-provider model — tenant-scoped, visible only to the owning workspace's keys; absent on global catalog rows."}},"required":["id","object","name","provider","context_length","capabilities","pricing","active","origin_jurisdiction","weights","hosting_jurisdiction","hosting_region"],"description":"A catalog model with pricing + capabilities + provenance (of the logical model) and hosting (of this offer)."}}},"required":["object","data"],"description":"Active model catalog."},"ModelDetailResponse":{"type":"object","properties":{"id":{"type":"string"},"object":{"type":"string","enum":["model"]},"name":{"type":"string"},"context_length":{"type":"integer","nullable":true},"capabilities":{"type":"object","additionalProperties":{"nullable":true}},"origin_jurisdiction":{"type":"string","description":"PROVENANCE — the LOGICAL model's origin jurisdiction (ISO alpha-2), or \"unknown\"."},"weights":{"type":"string","enum":["open","closed","unknown"],"description":"Whether the LOGICAL model weights are downloadable — open | closed | unknown (fail-closed)."},"workspace_custom":{"type":"boolean","description":"True when the id resolves ONLY via the workspace custom providers."},"offers":{"type":"array","items":{"type":"object","properties":{"provider":{"type":"string","description":"Provider slug serving this offer."},"model_id":{"type":"string","description":"The offer's own catalog id (may mirror the logical id)."},"context_length":{"type":"integer","nullable":true},"quantization":{"type":"string","nullable":true,"description":"Offer quantization (e.g. fp8), or null."},"data_policy":{"type":"string","nullable":true,"description":"Provider data policy ('strict' = ZDR), or null."},"throughput_rank":{"type":"integer","nullable":true,"description":"Static throughput rank (lower = faster)."},"pricing":{"type":"object","properties":{"input_micro_usd_per_1m":{"type":"integer","minimum":0},"output_micro_usd_per_1m":{"type":"integer","minimum":0},"cached_input_micro_usd_per_1m":{"type":"integer","nullable":true,"minimum":0},"input_usd_per_1m":{"type":"number","minimum":0},"output_usd_per_1m":{"type":"number","minimum":0}},"required":["input_micro_usd_per_1m","output_micro_usd_per_1m","cached_input_micro_usd_per_1m","input_usd_per_1m","output_usd_per_1m"],"description":"List pricing in integer micro-USD per 1M tokens (money is integer micro-USD)."},"hosting_jurisdiction":{"type":"string","description":"HOSTING — where THIS offer RUNS (ISO 3166-1 alpha-2), or \"unknown\"."},"hosting_region":{"type":"string","nullable":true,"description":"HOSTING — the provider-published serving region (e.g. us-east-1), or null."}},"required":["provider","model_id","context_length","quantization","data_policy","throughput_rank","pricing","hosting_jurisdiction","hosting_region"],"description":"One provider offer of a logical model, incl. its per-offer hosting."},"description":"Every active provider offer, INCLUDING the workspace custom-provider offers routing merges in. Each offer carries its OWN hosting."}},"required":["id","object","name","context_length","capabilities","origin_jurisdiction","weights","offers"],"description":"A catalog model with its per-provider offers. Provenance (origin/weights) is a top-level LOGICAL-model fact; hosting is per-offer."},"GenerationStats":{"type":"object","properties":{"id":{"type":"string","description":"The `req_…` id these stats describe."},"call_type":{"type":"string","nullable":true,"description":"Resolved call type (`ct_…`), or null."},"model_requested":{"type":"string","description":"The logical model the caller asked for."},"model_served":{"type":"string","nullable":true,"description":"The model actually served, or null on failure."},"provider":{"type":"string","nullable":true,"description":"The provider that served it, or null."},"status":{"type":"string","enum":["ok","error","cancelled"],"description":"Terminal request status."},"error_class":{"type":"string","nullable":true,"description":"The gateway error code (see `GatewayError.error.code`) when status != ok, else null."},"tokens":{"type":"object","properties":{"input":{"type":"integer","minimum":0},"output":{"type":"integer","minimum":0},"cached":{"type":"integer","minimum":0,"description":"Cached prompt tokens (subset of input)."},"total":{"type":"integer","minimum":0}},"required":["input","output","cached","total"],"description":"Token accounting (incl. cached-prompt tokens)."},"cost":{"type":"object","properties":{"total_micro_usd":{"type":"integer","minimum":0,"description":"Total cost in integer micro-USD."},"total_usd":{"type":"number","minimum":0,"description":"Total cost in USD (float, for readability)."},"cost_basis":{"type":"string","nullable":true,"enum":["priced","derived","unpriced","verified_memory"],"description":"Provenance of the cost: `priced` (the offer’s own catalog price), `derived` (a price derived from the logical model it serves), `verified_memory` (answered from verified memory at $0), or `unpriced` (served with no usable price — metered at $0 only where the unpriced-model override is enabled; null on a non-ok row)."}},"required":["total_micro_usd","total_usd","cost_basis"],"description":"Cost accounting (money is integer micro-USD)."},"timing":{"type":"object","properties":{"ttfb_ms":{"type":"integer","nullable":true,"description":"Time-to-first-byte in ms (null when N/A)."},"latency_ms":{"type":"integer","nullable":true,"description":"Total request latency in ms."}},"required":["ttfb_ms","latency_ms"],"description":"Timing."},"routing_decision":{"type":"object","additionalProperties":{"nullable":true},"description":"The full routing trail (mode/sort/attempts/skipped/config_sources) — why this request used the model it did."},"compression":{"type":"object","additionalProperties":{"nullable":true},"description":"Compression summary — the applied compression safety tier + savings provenance."},"byok":{"type":"boolean","description":"Whether a workspace BYOK key served the request."},"contract_digest":{"type":"string","nullable":true,"description":"The request's declared-contract digest (json_schema / tools / tool_choice / response_format); the distinguished empty-contract digest for a plain-text request, null on a request recorded before contract digests existed."},"outcomes":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string","description":"The outcome channel (e.g. `mechanical`)."},"kind":{"type":"string","description":"The closed-vocab kind (e.g. `schema_valid`, `tool_error`)."},"source":{"type":"string","description":"Server-assigned provenance (`gateway` for gateway-native events)."},"value":{"type":"object","additionalProperties":{"nullable":true},"description":"Typed value payload — reasons / indices / counts only (never a body)."},"latency_class":{"type":"string","description":"`instant` | `delayed` (server-derived)."},"learning_use":{"type":"array","items":{"type":"string"},"description":"Server-derived learning-use set (`train`/`calibrate`/`rank`/`audit`)."},"observed_at":{"type":"string","description":"ISO-8601 effective time of the outcome."},"artifact_id":{"type":"string","description":"The artifact the outcome landed on."}},"required":["channel","kind","source","value","latency_class","learning_use","observed_at","artifact_id"],"description":"One request-bound outcome event."},"description":"Outcome events bound to this request — gateway-native (`source:gateway`) mechanical events plus any declared request-shortcut outcomes. Empty when none recorded."},"exposure":{"type":"object","properties":{"arm":{"type":"string","nullable":true,"description":"Standing-holdout arm assigned at dispatch (null when unstamped)."},"epoch":{"type":"integer","nullable":true,"description":"The assignment epoch the arm was assigned under."}},"required":["arm","epoch"],"description":"The immutable pre-dispatch exposure stamp (read-back; never a decision input)."},"lever":{"type":"object","properties":{"lever_id":{"type":"string","nullable":true,"description":"The lever family injected (`learned_context`), or null when none was."},"module_version":{"type":"string","nullable":true,"description":"The injected module’s PINNED version — its recipe hash."},"epoch":{"type":"integer","nullable":true,"description":"The measurement epoch the injection was bound to."},"pack_hash":{"type":"string","nullable":true,"description":"The content address of the ORDERED item set actually served."},"injection":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"The serve-time retrieval provenance (`module_id`, `item_ids[]`, `served_rank[]`, `propensity[]`) when injected, or the NAMED refusal that withheld the lever (`holdout`, `candidate_unknown`, `pack_hash_mismatch`, …). Propensity is computable only at serve time and is never backfilled. Ids and numbers only — never a body."}},"required":["lever_id","module_version","epoch","pack_hash","injection"],"description":"The learned-context lever stamp for this request."},"created_at":{"type":"string","description":"ISO-8601 timestamp the request was recorded."}},"required":["id","call_type","model_requested","model_served","provider","status","error_class","tokens","cost","timing","routing_decision","compression","byok","contract_digest","outcomes","exposure","lever","created_at"],"description":"Post-hoc stats for one request (GET /v1/generation)."},"KeyIntrospection":{"type":"object","properties":{"object":{"type":"string","enum":["api_key"]},"name":{"type":"string","description":"Human-readable key name."},"prefix":{"type":"string","description":"Display prefix (`ur_sk_<mode>_` + 8 chars) — safe to show."},"mode":{"type":"string","enum":["live","test"],"description":"Key mode."},"scopes":{"type":"array","items":{"type":"string"},"description":"The key's closed-vocabulary scopes."},"workspace_id":{"type":"string"},"limits":{"type":"object","properties":{"spend_cap_micro_usd":{"type":"integer","nullable":true,"minimum":0,"description":"Per-key monthly hard cap in micro-USD; null = uncapped."},"rps_limit":{"type":"integer","nullable":true,"minimum":0,"exclusiveMinimum":true,"description":"Per-key requests-per-second cap; null = the gateway-key default."}},"required":["spend_cap_micro_usd","rps_limit"],"description":"Enforced limits on this key."},"usage":{"type":"object","properties":{"period":{"type":"string","description":"The current spend period (UTC calendar month, YYYY-MM-DD)."},"key_spent_micro_usd":{"type":"integer","minimum":0,"description":"This key's spend this period (from the live spend counters)."},"workspace_spent_micro_usd":{"type":"integer","minimum":0,"description":"The workspace's total spend this period."},"workspace_spend_cap_micro_usd":{"type":"integer","nullable":true,"minimum":0,"description":"The per-workspace monthly hard cap; null = uncapped."}},"required":["period","key_spent_micro_usd","workspace_spent_micro_usd","workspace_spend_cap_micro_usd"],"description":"Usage this period (from the live spend counters — never a scan of requests)."},"flywheel":{"type":"object","nullable":true,"properties":{"period":{"type":"string","description":"The current UTC month bucket (YYYY-MM-DD)."},"tracked_artifacts":{"type":"integer","minimum":0,"description":"OPERATIONAL — new artifacts captured this period (not an invoice line)."},"accepted_outcomes":{"type":"integer","minimum":0,"description":"OPERATIONAL — accepted outcome events this period (not an invoice line)."},"analysis_units":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0,"description":"Open analysis-unit holds this period."},"settled":{"type":"integer","minimum":0,"description":"Billed analysis units this period."},"monthly_cap":{"type":"integer","nullable":true,"description":"Monthly analysis-unit cap; null = lifetime governs."},"lifetime_used":{"type":"integer","minimum":0,"description":"Committed analysis units across the account lifetime."},"lifetime_cap":{"type":"integer","nullable":true,"description":"Lifetime analysis-unit cap; null = unlimited."}},"required":["reserved","settled","monthly_cap","lifetime_used","lifetime_cap"],"description":"PAID — bounded analysis units (billed by unique artifact version × recipe)."},"evaluation_compute_usd":{"type":"object","properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer","minimum":0},"cap_micro_usd":{"type":"integer","minimum":0,"description":"The approved monthly evaluation-compute cap."}},"required":["reserved_micro_usd","settled_micro_usd","cap_micro_usd"],"description":"PAID — approved evaluation compute (the platform-spend evaluation counters; one money source)."},"actual_cogs":{"type":"object","properties":{"analysis_micro_usd":{"type":"integer","minimum":0},"failed_attempt_micro_usd":{"type":"integer","minimum":0}},"required":["analysis_micro_usd","failed_attempt_micro_usd"],"description":"OUR actual COGS for margin (settled analysis + failed attempts); never billed to the customer."},"storage":{"type":"object","properties":{"retained_payload_bytes":{"type":"integer","minimum":0},"retained_payload_bytes_cap":{"type":"integer","nullable":true},"ledger_index_bytes":{"type":"integer","minimum":0},"ledger_index_bytes_cap":{"type":"integer","nullable":true},"paused":{"type":"boolean","description":"True when the storage quota is exhausted (new storage paused; export/deletion preserved)."}},"required":["retained_payload_bytes","retained_payload_bytes_cap","ledger_index_bytes","ledger_index_bytes_cap","paused"],"description":"The finite storage quotas + lifetime byte counters."},"metadata_artifacts_monthly_cap":{"type":"integer","nullable":true},"overage_paused":{"type":"boolean","description":"Default overage is paused — no unpriced automatic overage."}},"required":["period","tracked_artifacts","accepted_outcomes","analysis_units","evaluation_compute_usd","actual_cogs","storage","metadata_artifacts_monthly_cap","overage_paused"],"description":"The four SEPARATED Flywheel usage quantities for this workspace this period — operational capture counters vs the PAID analysis units + evaluation compute — plus caps, storage quota and our actual COGS. Never merged. Null/absent when the workspace has no Flywheel usage."},"expires_at":{"type":"string","nullable":true,"description":"ISO-8601 expiry, or null when non-expiring."},"created_at":{"type":"string","description":"ISO-8601 creation timestamp."}},"required":["object","name","prefix","mode","scopes","workspace_id","limits","usage","expires_at","created_at"],"description":"Current-key introspection (GET /v1/key)."},"PreflightBudget":{"type":"object","properties":{"max_usd":{"type":"number","minimum":0,"description":"Ceiling on the recommended offer NET-EFFECTIVE input price per 1M tokens, in USD. Preflight has NO request tokens to price a per-request budget against, so it filters on the rate-card input already in the policy decision (never a token estimator); an unpriceable offer is budget-excluded fail-closed. An excluded pin ⇒ `provisional:true, reason:\"budget\"`."},"max_latency_ms":{"type":"integer","minimum":0,"description":"Ceiling on the recommended offer p95 latency (the live health input already resolved for candidates/auto). An excluded pin ⇒ `provisional:true, reason:\"budget\"`. Not evaluated in off/pinned mode (no health is resolved there)."}},"description":"Optional pre-call budget hints."},"PreflightRequest":{"type":"object","properties":{"call_type":{"type":"string","minLength":1,"description":"The call type (slug or `ct_*` id) whose profile to preflight."},"artifact_key":{"type":"string","minLength":1,"description":"The declared artifact cluster key the exposure grant is minted on (supply it to receive a grant)."},"trace_id":{"type":"string","minLength":1,"description":"The trace-id cluster key (alternative to `artifact_key`; supply it to receive a grant)."},"budget":{"type":"object","properties":{"max_usd":{"type":"number","minimum":0,"description":"Ceiling on the recommended offer NET-EFFECTIVE input price per 1M tokens, in USD. Preflight has NO request tokens to price a per-request budget against, so it filters on the rate-card input already in the policy decision (never a token estimator); an unpriceable offer is budget-excluded fail-closed. An excluded pin ⇒ `provisional:true, reason:\"budget\"`."},"max_latency_ms":{"type":"integer","minimum":0,"description":"Ceiling on the recommended offer p95 latency (the live health input already resolved for candidates/auto). An excluded pin ⇒ `provisional:true, reason:\"budget\"`. Not evaluated in off/pinned mode (no health is resolved there)."}},"description":"Optional pre-call budget hints."},"messages":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["system","developer","user","assistant","tool"]},"content":{"anyOf":[{"type":"string"},{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","description":"The content part type (\"text\" | \"image_url\" | …)."},"text":{"type":"string","description":"The text of a text part."},"cache_control":{"type":"object","properties":{"type":{"type":"string","enum":["ephemeral"],"description":"The only supported cache type."},"ttl":{"type":"string","description":"Cache lifetime hint, e.g. \"5m\" (default) or \"1h\"."}},"required":["type"],"description":"Mark this content part as a prompt-cache breakpoint. Translated to Anthropic `cache_control` on the block; stripped + ignored (structured log) for non-Anthropic providers."}},"description":"One OpenAI-shaped message content part; may carry a `cache_control` breakpoint."}}],"nullable":true},"name":{"type":"string"},"tool_calls":{"type":"array","items":{"nullable":true}},"tool_call_id":{"type":"string"}},"required":["role"],"description":"An OpenAI-shaped chat message."},"description":"The messages the non-proxied call is about to send. Used ONLY when the learned module is a per-request CASE module (a classification call type learns verified cases, not a static list): the gateway renders the verified cases nearest THIS input (the last user message) — exactly what the chat path would inject for the same messages. Never stored, never logged. Omitted for a case module ⇒ `knowledge: null` with `knowledge_reason: \"case_query_missing\"`; a static module ignores it."}},"required":["call_type"],"additionalProperties":false,"description":"Preflight request — a call type + an OPTIONAL cluster key (artifact_key | trace_id) + budget + the OPTIONAL messages a per-request case module is rendered for."},"PreflightOfferScore":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."},"PreflightModel":{"type":"object","properties":{"id":{"type":"string","description":"The recommended logical model id."},"evidence":{"type":"string","enum":["none","qualified"],"description":"Whether qualified evals back this choice. `qualified` ONLY when the policy input already carries qualified evidence for the pin (a rec-backed migration baseline); else `none`. No $/task or quality-bar language is implied."},"score":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"The chosen offer policy score (candidates/auto), or null in off/pinned mode."}},"required":["id","evidence","score"],"description":"The recommended model — honest: the pin in off/pinned, the ranked offer in candidates/auto."},"PreflightFallback":{"type":"object","properties":{"id":{"type":"string","description":"The fallback logical model id."},"score":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."},"skipped_reason":{"type":"string","description":"Why this candidate was skipped (`capability:*`, `pref:*`, `not_in_list`, `model:unknown`)."}},"required":["id","score"],"description":"A fallback offer (live, health-ordered; max_age_s 30)."},"PreflightWhy":{"type":"object","properties":{"lever_suppressed":{"type":"string"},"mode":{"type":"string"},"config_mode":{"type":"string"},"downgraded":{"type":"boolean"},"upgrade_ignored":{"type":"boolean"},"kill_switch":{"type":"boolean"},"chain":{"type":"array","items":{"type":"string"}},"chosen":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"}},"required":["model","provider","offer_id"]},"scores":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."}},"canary_bucket":{"type":"number"}},"required":["mode","config_mode","downgraded","upgrade_ignored","kill_switch","chain","chosen","scores"],"description":"The serialised routing-policy decision (byte-compatible with `routing_decision.policy` in the generation stats)."},"PreflightLineage":{"type":"object","properties":{"pack_hash":{"type":"string"},"epoch":{"type":"integer"},"item_ids":{"type":"array","items":{"type":"string"}},"ranker_version":{"type":"string"},"k":{"type":"integer"},"key_spec":{"type":"string"},"source_snapshot":{"type":"string"}},"required":["pack_hash","epoch","item_ids","ranker_version","k","key_spec","source_snapshot"],"description":"The learned-module lineage (the pinned recipe the pack was frozen over)."},"PreflightKnowledgeModule":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string","description":"The recipe-hash module version."},"kind":{"type":"string","enum":["ur:learned"]},"slot":{"type":"string","enum":["learned"]},"state":{"type":"string","description":"The SERVING lifecycle state of the module the gateway would inject — `screened` (passed offline screening), `confirming` (a live confirmation is running; served to the treated arm) or `adopted` (a leased, adopted module). So a non-proxied customer can see WHAT the platform adopted and is serving."},"content_hash":{"type":"string","description":"sha256 of the rendered body — the byte identity of what is injected."},"tokens":{"type":"integer"},"content":{"type":"string","description":"The rendered module body (derived statistics only — never a body/PII)."},"lineage":{"type":"object","properties":{"pack_hash":{"type":"string"},"epoch":{"type":"integer"},"item_ids":{"type":"array","items":{"type":"string"}},"ranker_version":{"type":"string"},"k":{"type":"integer"},"key_spec":{"type":"string"},"source_snapshot":{"type":"string"}},"required":["pack_hash","epoch","item_ids","ranker_version","k","key_spec","source_snapshot"],"description":"The learned-module lineage (the pinned recipe the pack was frozen over)."}},"required":["id","version","kind","slot","state","content_hash","tokens","content","lineage"],"description":"The learned-context module preflight would inject (config-versioned; max_age_s 5 + ETag)."},"PreflightKnowledge":{"type":"object","properties":{"module":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string","description":"The recipe-hash module version."},"kind":{"type":"string","enum":["ur:learned"]},"slot":{"type":"string","enum":["learned"]},"state":{"type":"string","description":"The SERVING lifecycle state of the module the gateway would inject — `screened` (passed offline screening), `confirming` (a live confirmation is running; served to the treated arm) or `adopted` (a leased, adopted module). So a non-proxied customer can see WHAT the platform adopted and is serving."},"content_hash":{"type":"string","description":"sha256 of the rendered body — the byte identity of what is injected."},"tokens":{"type":"integer"},"content":{"type":"string","description":"The rendered module body (derived statistics only — never a body/PII)."},"lineage":{"type":"object","properties":{"pack_hash":{"type":"string"},"epoch":{"type":"integer"},"item_ids":{"type":"array","items":{"type":"string"}},"ranker_version":{"type":"string"},"k":{"type":"integer"},"key_spec":{"type":"string"},"source_snapshot":{"type":"string"}},"required":["pack_hash","epoch","item_ids","ranker_version","k","key_spec","source_snapshot"],"description":"The learned-module lineage (the pinned recipe the pack was frozen over)."}},"required":["id","version","kind","slot","state","content_hash","tokens","content","lineage"],"description":"The learned-context module preflight would inject (config-versioned; max_age_s 5 + ETag)."},"placement":{"type":"string","enum":["after_stable_prefix"]},"delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"HOW this module reaches the call for the call type. `gateway_inject_after_stable_prefix` — a PROXIED request has the gateway inject it (this advisory is informational). `off` — the gateway does NOT inject; a NON-proxied SDK/preflight consumer MUST inject the returned module itself (at `placement`). Either way preflight returns the module so the SDK knows exactly what to inject; a flip to `off` starts a new learned_context epoch."}},"required":["module","placement","delivery"],"description":"The learned knowledge preflight would inject + where + how it is delivered."},"PreflightRouting":{"type":"object","properties":{"mode":{"type":"string","enum":["off","pinned","candidates","auto"],"description":"The EFFECTIVE router mode the gateway would run."},"model":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The recommended logical model id."},"evidence":{"type":"string","enum":["none","qualified"],"description":"Whether qualified evals back this choice. `qualified` ONLY when the policy input already carries qualified evidence for the pin (a rec-backed migration baseline); else `none`. No $/task or quality-bar language is implied."},"score":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"The chosen offer policy score (candidates/auto), or null in off/pinned mode."}},"required":["id","evidence","score"],"description":"The recommended model, or null when none resolves."},"fallbacks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The fallback logical model id."},"score":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."},"skipped_reason":{"type":"string","description":"Why this candidate was skipped (`capability:*`, `pref:*`, `not_in_list`, `model:unknown`)."}},"required":["id","score"],"description":"A fallback offer (live, health-ordered; max_age_s 30)."},"description":"Health-ordered fallbacks (the 30 s live part)."},"why":{"type":"object","nullable":true,"properties":{"lever_suppressed":{"type":"string"},"mode":{"type":"string"},"config_mode":{"type":"string"},"downgraded":{"type":"boolean"},"upgrade_ignored":{"type":"boolean"},"kill_switch":{"type":"boolean"},"chain":{"type":"array","items":{"type":"string"}},"chosen":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"}},"required":["model","provider","offer_id"]},"scores":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."}},"canary_bucket":{"type":"number"}},"required":["mode","config_mode","downgraded","upgrade_ignored","kill_switch","chain","chosen","scores"],"description":"The serialised policy decision (null in off/pinned)."},"max_age_s":{"type":"number","enum":[30],"description":"The LIVE (health-ordered fallbacks) part max age in seconds — the 30 s regime."}},"required":["mode","model","fallbacks","why","max_age_s"],"description":"The routing decision preflight would have made."},"PreflightResponse":{"type":"object","properties":{"object":{"type":"string","enum":["preflight"]},"config_version":{"type":"integer","description":"The config version this decision was resolved on."},"routing":{"type":"object","properties":{"mode":{"type":"string","enum":["off","pinned","candidates","auto"],"description":"The EFFECTIVE router mode the gateway would run."},"model":{"type":"object","nullable":true,"properties":{"id":{"type":"string","description":"The recommended logical model id."},"evidence":{"type":"string","enum":["none","qualified"],"description":"Whether qualified evals back this choice. `qualified` ONLY when the policy input already carries qualified evidence for the pin (a rec-backed migration baseline); else `none`. No $/task or quality-bar language is implied."},"score":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"The chosen offer policy score (candidates/auto), or null in off/pinned mode."}},"required":["id","evidence","score"],"description":"The recommended model, or null when none resolves."},"fallbacks":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The fallback logical model id."},"score":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."},"skipped_reason":{"type":"string","description":"Why this candidate was skipped (`capability:*`, `pref:*`, `not_in_list`, `model:unknown`)."}},"required":["id","score"],"description":"A fallback offer (live, health-ordered; max_age_s 30)."},"description":"Health-ordered fallbacks (the 30 s live part)."},"why":{"type":"object","nullable":true,"properties":{"lever_suppressed":{"type":"string"},"mode":{"type":"string"},"config_mode":{"type":"string"},"downgraded":{"type":"boolean"},"upgrade_ignored":{"type":"boolean"},"kill_switch":{"type":"boolean"},"chain":{"type":"array","items":{"type":"string"}},"chosen":{"type":"object","nullable":true,"properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"}},"required":["model","provider","offer_id"]},"scores":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"offer_id":{"type":"string"},"net_effective_micro_usd_per_1m":{"type":"number","nullable":true},"marginal_micro_usd_per_1m":{"type":"number","nullable":true},"commit_mode":{"type":"string","enum":["sunk","discounted","list"]},"health_score":{"type":"number"},"policy_score":{"type":"number","nullable":true},"eligible":{"type":"boolean"},"reason":{"type":"string"}},"required":["model","provider","offer_id","net_effective_micro_usd_per_1m","marginal_micro_usd_per_1m","health_score","policy_score","eligible"],"description":"One offer policy score (the routing-policy decision evidence; ranking prices only)."}},"canary_bucket":{"type":"number"}},"required":["mode","config_mode","downgraded","upgrade_ignored","kill_switch","chain","chosen","scores"],"description":"The serialised policy decision (null in off/pinned)."},"max_age_s":{"type":"number","enum":[30],"description":"The LIVE (health-ordered fallbacks) part max age in seconds — the 30 s regime."}},"required":["mode","model","fallbacks","why","max_age_s"],"description":"The routing decision preflight would have made."},"prompt":{"type":"object","nullable":true,"properties":{"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The active hosted prompt version number."},"template":{"type":"string","description":"The prompt template (`{{name}}` variables the caller fills)."},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"required":{"type":"boolean"}},"required":["name","required"]},"description":"The declared template variables (name + required flag)."},"sha256":{"type":"string","description":"sha256 of the template — the byte identity of the active version."}},"required":["version","template","variables","sha256"],"description":"The ACTIVE hosted prompt version, or null when code-owned. Config-versioned (part of the ETag)."},"knowledge":{"type":"object","nullable":true,"properties":{"module":{"type":"object","properties":{"id":{"type":"string"},"version":{"type":"string","description":"The recipe-hash module version."},"kind":{"type":"string","enum":["ur:learned"]},"slot":{"type":"string","enum":["learned"]},"state":{"type":"string","description":"The SERVING lifecycle state of the module the gateway would inject — `screened` (passed offline screening), `confirming` (a live confirmation is running; served to the treated arm) or `adopted` (a leased, adopted module). So a non-proxied customer can see WHAT the platform adopted and is serving."},"content_hash":{"type":"string","description":"sha256 of the rendered body — the byte identity of what is injected."},"tokens":{"type":"integer"},"content":{"type":"string","description":"The rendered module body (derived statistics only — never a body/PII)."},"lineage":{"type":"object","properties":{"pack_hash":{"type":"string"},"epoch":{"type":"integer"},"item_ids":{"type":"array","items":{"type":"string"}},"ranker_version":{"type":"string"},"k":{"type":"integer"},"key_spec":{"type":"string"},"source_snapshot":{"type":"string"}},"required":["pack_hash","epoch","item_ids","ranker_version","k","key_spec","source_snapshot"],"description":"The learned-module lineage (the pinned recipe the pack was frozen over)."}},"required":["id","version","kind","slot","state","content_hash","tokens","content","lineage"],"description":"The learned-context module preflight would inject (config-versioned; max_age_s 5 + ETag)."},"placement":{"type":"string","enum":["after_stable_prefix"]},"delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"HOW this module reaches the call for the call type. `gateway_inject_after_stable_prefix` — a PROXIED request has the gateway inject it (this advisory is informational). `off` — the gateway does NOT inject; a NON-proxied SDK/preflight consumer MUST inject the returned module itself (at `placement`). Either way preflight returns the module so the SDK knows exactly what to inject; a flip to `off` starts a new learned_context epoch."}},"required":["module","placement","delivery"],"description":"The learned knowledge preflight would inject + where + how it is delivered."},"knowledge_reason":{"type":"string","nullable":true,"description":"The NAMED refusal when `knowledge` is null (the inject seam refusal, e.g. `holdout` / `candidate_unknown` / `module_version_mismatch`; `fell_back` when the learned module could not be resolved within the hot-path `learned`-slot budget; or `no_learned_module` when none is configured). Null only when a module WAS injected."},"grant":{"type":"object","nullable":true,"properties":{"grant_id":{"type":"string","description":"Deterministic: hash of workspace + cluster key + epoch (idempotent; never cached)."},"arm":{"type":"string","enum":["treated","holdout","lever_holdout","pre_lever"],"description":"The exposure arm the grant assigns (the SAME assignment the gateway stamps at dispatch)."},"lever_id":{"type":"string","nullable":true,"description":"The lever family when the arm is lever-derived, else null."},"epoch":{"type":"integer","description":"The assignment epoch (lift is never pooled across epochs)."},"valid_until_epoch_close":{"type":"string","description":"A conservative ISO validity horizon; re-mint on a newer epoch (never cached)."},"request_id":{"type":"string","description":"The zero-cost `status=preflight` served-record id (the served proof)."}},"required":["grant_id","arm","lever_id","epoch","valid_until_epoch_close","request_id"],"description":"The exposure grant (present when a cluster key was given; null otherwise). NEVER cached — also served on the `X-UR-Grant` header, which a 304 revalidation still carries."},"grant_reason":{"type":"string","nullable":true,"description":"The NAMED reason `grant` is null (`no_cluster_key` when neither artifact_key nor trace_id was given). Null when a grant WAS minted."},"provisional":{"type":"boolean","description":"Whether this advice is provisional (a confirmed plan / benchmarkable / budget caveat)."},"reason":{"type":"string","enum":["plan_unconfirmed","not_benchmarkable","budget"],"description":"Why the advice is provisional (present only when `provisional` is true)."}},"required":["object","config_version","routing","prompt","knowledge","knowledge_reason","grant","grant_reason","provisional"],"description":"Preflight response — the routing decision + the learned knowledge + placement + the exposure grant."},"BenchSuiteStatusResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_suite_status"]},"suite":{"type":"string","description":"The bench suite slug."},"suite_id":{"type":"string","description":"The bench suite id (`bs_…`)."},"ttl_days":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Capture TTL in days (1–90)."},"total_captured":{"type":"integer","minimum":0,"description":"Total CONFIRMED (durable, replayable) items in the suite."},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type":{"type":"string","nullable":true,"description":"The resolved call type id, or null (unattributed)."},"captured":{"type":"integer","minimum":0,"description":"Current confirmed captures (PROVENANCE, never a verdict — the verdict is the power plan)."},"qualified":{"type":"object","nullable":true,"properties":{"dataset_hash":{"type":"string","description":"The latest frozen dataset content address."},"card":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The call type this dataset is compiled for."},"dataset_hash":{"type":"string","description":"Content address — identical captures ⇒ identical hash."},"captured_count":{"type":"integer","minimum":0,"description":"n confirmed envelopes fed in."},"admitted_count":{"type":"integer","minimum":0,"description":"n admitted (captured − PII/empty)."},"unique_count":{"type":"integer","minimum":0,"description":"n exact-dedup uniques (before the cap)."},"item_count":{"type":"integer","minimum":0,"description":"n items in the frozen dataset (post ≤500 cap)."},"cluster_count":{"type":"integer","minimum":0,"description":"The VERDICT-LEVEL inferential-cluster n — one cluster per independent task/trace, else per item identity: the SAME unit the deciding interval-based verdict uses. Powers the power plan; the SimHash near-duplicate group count is reported separately as near_dup_cluster_count."},"near_dup_cluster_count":{"type":"integer","minimum":0,"description":"The SimHash near-DUPLICATE group count (masked-template redundancy) — a SEPARATE disclosure, NOT the plan n. Absent on legacy cards frozen before this field existed."},"task_count":{"type":"integer","minimum":0,"description":"Distinct task/trace ids present."},"shape":{"type":"string","enum":["request","task"],"description":"Request- or task-shaped overall."},"strata":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The stratum key (length/lang/tools/feedback tuple)."},"unique_count":{"type":"integer","minimum":0,"description":"Unique items in this stratum."},"frequency_weight":{"type":"integer","minimum":0,"description":"Frequency-weighted population share of the stratum (the shared population weight)."},"thin":{"type":"boolean","description":"True when the stratum is under-powered (below the thin threshold)."}},"required":["key","unique_count","frequency_weight","thin"],"description":"A dataset-card stratum summary."},"description":"Per-stratum summaries + thin warnings."},"exclusions":{"type":"array","items":{"type":"object","properties":{"envelope_ids":{"type":"array","items":{"type":"string"},"description":"The confirmed envelope ids excluded together."},"reason":{"type":"string","enum":["pii_low_confidence","empty_content","over_cap"],"description":"Why the item(s) were excluded (visible per-item on the card)."}},"required":["envelope_ids","reason"],"description":"A dataset-card exclusion."},"description":"Visible per-item exclusions."},"power_plan":{"type":"object","properties":{"cluster_n":{"type":"integer","minimum":0,"description":"The VERDICT-LEVEL inferential-cluster n — the SAME unit the deciding interval-based verdict bootstraps (one cluster per task/trace, else per item identity), NOT the SimHash near-duplicate group count."},"prior_quality_sd":{"type":"number","description":"The conservative-prior (or A/A) composite-quality SD."},"alpha":{"type":"number","description":"The significance level the plan assumed."},"power":{"type":"number","description":"The target power (e.g. 0.8)."},"margin_pp":{"type":"number","description":"The preregistered non-inferiority margin Δ (pp)."},"mde_pp":{"type":"number","description":"The minimum detectable effect (pp) — a PLANNING number, not a verdict."},"required_clusters":{"type":"integer","minimum":0,"description":"The minimum verdict-level clusters this margin needs at the plan alpha/power (so \"cap < required\" is visible AT FREEZE) — a PLANNING number, never a gate (the margin is never loosened). Absent on legacy cards frozen before this field existed."},"adequately_powered":{"type":"boolean","description":"Power adequacy HINT (mde_pp ≤ margin_pp) — still never a verdict."},"summary":{"type":"string","description":"Planning-language readout (\"can detect ~Xpp at 80% power\")."}},"required":["cluster_n","prior_quality_sd","alpha","power","margin_pp","mde_pp","adequately_powered","summary"],"description":"The preregistered power plan — planning language, never a verdict."},"staleness":{"type":"object","properties":{"prior_run_count":{"type":"integer","minimum":0,"description":"Runs referencing this dataset_hash."},"stale":{"type":"boolean","description":"Whether the run count trips the staleness flag."}},"required":["prior_run_count","stale"],"description":"Prior-run staleness disclosure."},"attestation":{"type":"boolean","description":"Whether the audited low-confidence-PII attestation admitted otherwise-excluded items."}},"required":["call_type_id","dataset_hash","captured_count","admitted_count","unique_count","item_count","cluster_count","task_count","shape","strata","exclusions","power_plan","staleness","attestation"],"description":"The immutable dataset card (qualified-evidence readiness — replaces raw counts)."},"captured_at_freeze":{"type":"integer","minimum":0,"description":"Confirmed captures at the moment of the freeze."},"frozen_at":{"type":"string","description":"When the dataset was frozen (ISO timestamp)."}},"required":["dataset_hash","card","captured_at_freeze","frozen_at"],"description":"The qualified-evidence readiness (latest frozen card), or null until frozen."},"new_since_freeze":{"type":"integer","nullable":true,"minimum":0,"description":"Confirmed captures accrued since the last freeze (re-freeze to qualify), or null."},"trace_covered":{"type":"integer","minimum":0,"description":"Confirmed captures carrying a task/trace id."},"trace_coverage":{"type":"number","minimum":0,"maximum":1,"description":"Fraction of confirmed captures with a task/trace id (0 blocks task claims)."},"task_claim_blocked":{"type":"boolean","description":"True when no trace coverage exists — `$/task` claims are blocked."},"trace_source_mix":{"type":"object","additionalProperties":{"type":"integer","minimum":0},"description":"Confirmed captures per resolved trace source (explicit_trace/traceparent/… → count)."},"trace_mean_confidence":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"Mean stored [0,1] confidence over covered captures, or null when none."}},"required":["call_type","captured","qualified","new_since_freeze","trace_covered","trace_coverage","task_claim_blocked","trace_source_mix","trace_mean_confidence"],"description":"Per-call-type bench readiness."},"description":"Per-call-type readiness rows."},"capture":{"type":"object","properties":{"confirmed":{"type":"integer","minimum":0,"description":"Durable, replayable envelopes (persisted only — never over-claimed)."},"queued":{"type":"integer","minimum":0,"description":"Captures awaiting background persistence (not yet confirmed)."},"failed":{"type":"integer","minimum":0,"description":"Captures that failed (DB/blob outage after retries, or stream-tee overflow)."},"non_replayable":{"type":"integer","minimum":0,"description":"Refused captures (no consent / size ceiling) — shape metadata only, no body."}},"required":["confirmed","queued","failed","non_replayable"],"description":"Workspace-wide capture health (confirmed/queued/failed/non_replayable)."}},"required":["object","suite","suite_id","ttl_days","total_captured","call_types","capture"],"description":"ultrarouter Bench suite readiness meter."},"BenchFreezeRequest":{"type":"object","properties":{"max_items":{"type":"integer","minimum":1,"maximum":5000,"description":"Optional per-call-type frozen-item cap (default 500; ≤ the hard ceiling of 5000 items, which bounds the O(n²) compile). Over-cap uniques are dropped keeping the highest frequency, recorded as `over_cap` exclusions. NO entitlement gate applies at freeze — the run-time free-tier shape cap remains the enforcement point."}},"description":"ultrarouter Bench dataset freeze request."},"BenchDatasetFreezeResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_dataset_freeze"]},"suite":{"type":"string","description":"The bench suite slug."},"suite_id":{"type":"string","description":"The bench suite id (`bs_…`)."},"datasets":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The call type this dataset was frozen for."},"dataset_id":{"type":"string","description":"The immutable dataset id (`bd_…`)."},"dataset_hash":{"type":"string","description":"Content address — identical captures ⇒ identical hash."},"card":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The call type this dataset is compiled for."},"dataset_hash":{"type":"string","description":"Content address — identical captures ⇒ identical hash."},"captured_count":{"type":"integer","minimum":0,"description":"n confirmed envelopes fed in."},"admitted_count":{"type":"integer","minimum":0,"description":"n admitted (captured − PII/empty)."},"unique_count":{"type":"integer","minimum":0,"description":"n exact-dedup uniques (before the cap)."},"item_count":{"type":"integer","minimum":0,"description":"n items in the frozen dataset (post ≤500 cap)."},"cluster_count":{"type":"integer","minimum":0,"description":"The VERDICT-LEVEL inferential-cluster n — one cluster per independent task/trace, else per item identity: the SAME unit the deciding interval-based verdict uses. Powers the power plan; the SimHash near-duplicate group count is reported separately as near_dup_cluster_count."},"near_dup_cluster_count":{"type":"integer","minimum":0,"description":"The SimHash near-DUPLICATE group count (masked-template redundancy) — a SEPARATE disclosure, NOT the plan n. Absent on legacy cards frozen before this field existed."},"task_count":{"type":"integer","minimum":0,"description":"Distinct task/trace ids present."},"shape":{"type":"string","enum":["request","task"],"description":"Request- or task-shaped overall."},"strata":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The stratum key (length/lang/tools/feedback tuple)."},"unique_count":{"type":"integer","minimum":0,"description":"Unique items in this stratum."},"frequency_weight":{"type":"integer","minimum":0,"description":"Frequency-weighted population share of the stratum (the shared population weight)."},"thin":{"type":"boolean","description":"True when the stratum is under-powered (below the thin threshold)."}},"required":["key","unique_count","frequency_weight","thin"],"description":"A dataset-card stratum summary."},"description":"Per-stratum summaries + thin warnings."},"exclusions":{"type":"array","items":{"type":"object","properties":{"envelope_ids":{"type":"array","items":{"type":"string"},"description":"The confirmed envelope ids excluded together."},"reason":{"type":"string","enum":["pii_low_confidence","empty_content","over_cap"],"description":"Why the item(s) were excluded (visible per-item on the card)."}},"required":["envelope_ids","reason"],"description":"A dataset-card exclusion."},"description":"Visible per-item exclusions."},"power_plan":{"type":"object","properties":{"cluster_n":{"type":"integer","minimum":0,"description":"The VERDICT-LEVEL inferential-cluster n — the SAME unit the deciding interval-based verdict bootstraps (one cluster per task/trace, else per item identity), NOT the SimHash near-duplicate group count."},"prior_quality_sd":{"type":"number","description":"The conservative-prior (or A/A) composite-quality SD."},"alpha":{"type":"number","description":"The significance level the plan assumed."},"power":{"type":"number","description":"The target power (e.g. 0.8)."},"margin_pp":{"type":"number","description":"The preregistered non-inferiority margin Δ (pp)."},"mde_pp":{"type":"number","description":"The minimum detectable effect (pp) — a PLANNING number, not a verdict."},"required_clusters":{"type":"integer","minimum":0,"description":"The minimum verdict-level clusters this margin needs at the plan alpha/power (so \"cap < required\" is visible AT FREEZE) — a PLANNING number, never a gate (the margin is never loosened). Absent on legacy cards frozen before this field existed."},"adequately_powered":{"type":"boolean","description":"Power adequacy HINT (mde_pp ≤ margin_pp) — still never a verdict."},"summary":{"type":"string","description":"Planning-language readout (\"can detect ~Xpp at 80% power\")."}},"required":["cluster_n","prior_quality_sd","alpha","power","margin_pp","mde_pp","adequately_powered","summary"],"description":"The preregistered power plan — planning language, never a verdict."},"staleness":{"type":"object","properties":{"prior_run_count":{"type":"integer","minimum":0,"description":"Runs referencing this dataset_hash."},"stale":{"type":"boolean","description":"Whether the run count trips the staleness flag."}},"required":["prior_run_count","stale"],"description":"Prior-run staleness disclosure."},"attestation":{"type":"boolean","description":"Whether the audited low-confidence-PII attestation admitted otherwise-excluded items."}},"required":["call_type_id","dataset_hash","captured_count","admitted_count","unique_count","item_count","cluster_count","task_count","shape","strata","exclusions","power_plan","staleness","attestation"],"description":"The immutable dataset card (qualified-evidence readiness — replaces raw counts)."},"evaluator":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The call type the evaluator was merged for."},"suite_hash":{"type":"string","nullable":true,"description":"The merged evaluator suite content address."},"assertions":{"type":"array","items":{"type":"object","properties":{"index":{"type":"integer","minimum":0,"description":"The assertion position (a stable per-item handle)."},"kind":{"type":"string","enum":["json_schema","exact_field","regex_match","citation_substring"],"description":"The closed programmatic assertion kind."},"hash":{"type":"string","description":"The content address of (kind + config)."},"scorer_id":{"type":"string","description":"The programmatic scorer id it compiles to."},"accepted":{"type":"boolean","description":"Whether the assertion passed qualification and was merged."},"reason":{"type":"string","nullable":true,"description":"The visible rejection reason (vacuous/contradicts_reference/…), or null."}},"required":["index","kind","hash","scorer_id","accepted","reason"],"description":"A freeze-time customer-assertion disposition."},"description":"Per-assertion accept/reject dispositions (never silent)."},"accepted_count":{"type":"integer","minimum":0},"rejected_count":{"type":"integer","minimum":0},"requalified":{"type":"boolean","description":"The MANDATORY merged-suite mutation re-qualification (apply only when true)."},"applied":{"type":"boolean","description":"Whether the merged suite was applied to the call type."},"judge_disabled":{"type":"boolean","description":"Whether the merged suite retired the judge residue (the zero-judge path)."},"trust_class":{"type":"string","enum":["A","B","C"],"description":"The composite trust class (A/B/C)."},"programmatic_outcome_share":{"type":"number","minimum":0,"maximum":1},"judge_share":{"type":"number","minimum":0,"maximum":1},"not_applied_reason":{"type":"string","nullable":true,"description":"Why the merged suite was not applied, else null."}},"required":["call_type_id","suite_hash","assertions","accepted_count","rejected_count","requalified","applied","judge_disabled","trust_class","programmatic_outcome_share","judge_share","not_applied_reason"],"description":"The freeze-time evaluator merge result for a call type."}},"required":["call_type_id","dataset_id","dataset_hash","card","evaluator"],"description":"A frozen per-call-type Bench dataset + its card + evaluator merge."},"description":"One immutable, content-addressed dataset + card per call type frozen."},"warnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["no_call_type_attribution"],"description":"The machine-readable warning code."},"message":{"type":"string","description":"A human-readable explanation of the condition + the fix."},"confirmed_captures":{"type":"integer","minimum":0,"description":"How many confirmed captures the warning concerns (e.g. unattributed captures)."}},"required":["code","message","confirmed_captures"],"description":"A bench-freeze warning."},"description":"Non-fatal freeze warnings — e.g. confirmed captures exist but 0 datasets froze because none carry an explicit call_type. Absent/empty when the freeze was clean."}},"required":["object","suite","suite_id","datasets"],"description":"ultrarouter Bench dataset freeze result."},"BenchRunTriggerRequest":{"type":"object","properties":{"mode":{"type":"string","enum":["request","task"],"description":"Paired-runner mode: `request` (default) or `task` (whole-trace, only evidence that may claim $/task)."},"selection_mode":{"type":"string","enum":["selection","noninferiority"],"description":"Selection mode: `selection` (default; ranked exploratory evidence, NEVER a recommendation) or `noninferiority` (incumbent-paired, migrate-eligible)."},"max_cost_usd":{"type":"number","minimum":0.000001,"maximum":9007199254,"description":"MANDATORY global umbrella reservation ceiling in USD across all accepted child runs. Live paid dispatch is gated by the platform paid-dispatch kill switch (default ON): when ON, omitting dry_run dispatches a real paired run within this ceiling; when OFF (or unseeded ⇒ fail-closed) live dispatch is refused with atomic_spend_guard_unavailable. dry_run always works."},"max_output_tokens":{"type":"integer","minimum":0,"exclusiveMinimum":true,"maximum":4096,"description":"Finite per-attempt output-token ceiling, pinned into the immutable RunSpec and used as the output component of reservation math (default 256; changing it is a new measurement epoch). It does not by itself bound provider input accounting or replace the atomic attempt guard."},"dry_run":{"type":"boolean","description":"When true: return the estimate + dispositions + allowance with NO reservation/dispatch. When false (default) and the paid-dispatch kill switch is ON, a real paired run is dispatched; when that kill switch is OFF (or unseeded ⇒ fail-closed), otherwise-valid paid shapes are labeled not_runnable/atomic_spend_guard_unavailable instead."},"force":{"type":"boolean","description":"Bench-only: skip the <14 d RunSpec-hash dedupe and always run fresh (audited)."},"require_power":{"type":"boolean","description":"Opt-in pre-spend power gate (default false): when true, an UNDERPOWERED call type (its power advisory `underpowered`) becomes `not_runnable(underpowered)` and is excluded from the estimate/reservation BEFORE any budget reserve. Advisory-only by default — the run proceeds."},"call_types":{"type":"array","items":{"type":"string"},"description":"Restrict the fan-out to these frozen call-type ids (default: every runnable one)."},"candidates":{"type":"array","items":{"type":"string"},"description":"Explicit challenger model ids (default: auto-selected from the catalog)."},"compare":{"type":"boolean","description":"COMPARE mode: run the CURRENT effective config as the single arm (the \"candidate\": the new prompt/pin/config) and gate it against a pinned baseline run — `candidates` are ignored."},"baseline_run_id":{"type":"string","description":"The baseline run (`br_*`) to compare against; defaults to the suite’s pinned baseline."},"cost_ceiling_usd":{"type":"number","minimum":0.000001,"maximum":9007199254,"description":"Absolute per-unit measured-cost ceiling (USD) — a breach FAILS the gate independent of quality. Omit for no ceiling."}},"required":["max_cost_usd"],"description":"ultrarouter Bench on-demand run trigger request."},"BenchRunTriggerResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_run_trigger"]},"bench_run_id":{"type":"string","nullable":true,"description":"The umbrella `br_*` id (null on a dry_run)."},"suite":{"type":"string","description":"The bench suite slug."},"dry_run":{"type":"boolean","description":"True when no reservation/dispatch happened (estimate only)."},"mode":{"type":"string","enum":["request","task"]},"selection_mode":{"type":"string","enum":["selection","noninferiority"]},"estimate_usd":{"type":"number","description":"Total pre-run estimate across runnable call types (USD)."},"judge_worst_case_usd":{"type":"number","description":"The run-total CONSERVATIVE worst-case JUDGE-phase cost (USD) across judge-enabled call types — surfaced additively alongside estimate_usd (the two are never summed into one figure). 0 when every runnable call type is zero-judge / has no priced judge."},"allowance":{"type":"object","properties":{"grant_usd":{"type":"number","nullable":true,"description":"The prepaid Bench allowance in USD, or null when the workspace has none."},"reserved_usd":{"type":"number","description":"Open reservations for in-flight runs (USD)."},"spent_usd":{"type":"number","description":"Settled Bench spend to date (USD)."},"available_usd":{"type":"number","description":"grant − reserved − spent (USD; 0 when there is no grant)."}},"required":["grant_usd","reserved_usd","spent_usd","available_usd"],"description":"The workspace Bench allowance state."},"entitlement":{"type":"object","properties":{"plan":{"type":"string","enum":["free","team"],"description":"The bench packaging plan."},"gate_entitled":{"type":"boolean","description":"Whether the workspace is entitled to the full CI gate (Team); free keeps read access."},"run_count_limit":{"type":"integer","nullable":true,"description":"Free monthly bench-run limit, or null when not run-count-limited (Team / prepaid grant)."},"run_count_used":{"type":"integer","nullable":true,"description":"Bench runs consumed this UTC calendar month, or null when not run-count-limited."},"max_candidates":{"type":"integer","nullable":true,"description":"Max challenger candidates per run, or null (Team)."},"max_items_per_call_type":{"type":"integer","nullable":true,"description":"Max frozen items per call-type run, or null (Team)."},"notice":{"type":"string","nullable":true,"description":"A legible entitlement notice (e.g. the CI-gate-is-Team notice), or null."}},"required":["plan","gate_entitled","run_count_limit","run_count_used","max_candidates","max_items_per_call_type","notice"],"description":"The bench packaging entitlement (plan + free-tier caps + run-count usage)."},"dispositions":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The frozen call type."},"disposition":{"type":"string","enum":["runnable","not_runnable","deduped","budget_queued"],"description":"runnable | not_runnable | deduped | budget_queued."},"reason":{"type":"string","nullable":true,"description":"Why not_runnable (insufficient_items/not_frozen/no_incumbent/no_candidates/underpowered), else null."},"tier":{"type":"string","enum":["insufficient_items","exploratory","standard"],"description":"The PLANNING verdict tier from the frozen card (<10/10–29/≥30 unique) — never a verdict."},"tier_summary":{"type":"string","description":"Planning-language readout of the tier."},"unique_count":{"type":"integer","minimum":0,"description":"The PINNED item count driving the tier + runnability: card.item_count (post-cap) — exactly the items the run executes. Equals the frozen unique count when uncapped; a max_items cap makes it the smaller pinned count so the tier reflects what actually runs."},"dataset_hash":{"type":"string","nullable":true,"description":"The frozen dataset content address, or null."},"estimate_usd":{"type":"number","description":"This child run's bounded planning estimate in USD (before global admission)."},"reserved_usd":{"type":"number","description":"The atomically-reserved allowance held for this run (USD)."},"eval_run_id":{"type":"string","nullable":true,"description":"The fanned child eval run id (runnable), else null."},"prior_run_id":{"type":"string","nullable":true,"description":"The prior run linked when deduped, else null."},"judge_worst_case_usd":{"type":"number","description":"The CONSERVATIVE worst-case JUDGE-phase cost (USD) this call type could incur — the SAME arithmetic the phase-time guard uses (pairs × positions × tiers × pinned maxTokens at judge rates + a re-invoke allowance), surfaced additively (NOT folded into estimate_usd). 0 for a judge_disabled (all-asserted / zero-judge) call type or an unpriced/stub judge. The umbrella admission checks arms + this bound against max_cost, so an unaffordable judge phase is refused at the trigger (judge_phase_unaffordable) before any arm spend."},"power":{"type":"object","properties":{"margin_pp":{"type":"number","description":"The registered non-inferiority margin Δ (pp) the advisory sizes power against."},"mde_pp":{"type":"number","description":"The planning MDE (pp) recomputed from the card prior SD + cluster n vs THIS margin — a power diagnostic, never a verdict."},"cluster_n":{"type":"integer","minimum":0,"description":"The frozen card independent-cluster n (the inferential unit)."},"required_clusters":{"type":"integer","minimum":0,"description":"The minimum clusters THIS margin needs at the plan alpha/power (never loosened)."},"underpowered":{"type":"boolean","description":"True when cluster_n < required_clusters (mde_pp > margin_pp) — advisory, never a blocking gate."}},"required":["margin_pp","mde_pp","cluster_n","required_clusters","underpowered"],"description":"Pre-spend power advisory — attached to runnable/deduped/budget_queued and the underpowered park (a not_runnable without a frozen card carries none)."},"unmatched_candidates":{"type":"array","items":{"type":"string"},"description":"EXPLICIT candidate ids that matched an offer globally but were NOT challengers for THIS call type (e.g. they resolve to the incumbent here) — a partial match is legal but VISIBLE. A fully-unmatched id is a 400 at the trigger, never a silent drop."}},"required":["call_type_id","disposition","reason","tier","tier_summary","unique_count","dataset_hash","estimate_usd","reserved_usd","eval_run_id","prior_run_id"],"description":"A per-call-type bench run disposition."},"description":"Per-call-type dispositions + estimate breakdown."}},"required":["object","bench_run_id","suite","dry_run","mode","selection_mode","estimate_usd","judge_worst_case_usd","allowance","entitlement","dispositions"],"description":"ultrarouter Bench on-demand run trigger result."},"BenchRunResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_run"]},"id":{"type":"string","description":"The umbrella `br_*` id."},"suite":{"type":"string","description":"The bench suite slug."},"mode":{"type":"string","enum":["request","task"]},"selection_mode":{"type":"string","enum":["selection","noninferiority"]},"status":{"type":"string","enum":["queued","running","complete","failed"],"description":"The umbrella status."},"estimate_usd":{"type":"number","description":"The aggregate pre-run estimate (USD)."},"allowance":{"type":"object","properties":{"grant_usd":{"type":"number","nullable":true,"description":"The prepaid Bench allowance in USD, or null when the workspace has none."},"reserved_usd":{"type":"number","description":"Open reservations for in-flight runs (USD)."},"spent_usd":{"type":"number","description":"Settled Bench spend to date (USD)."},"available_usd":{"type":"number","description":"grant − reserved − spent (USD; 0 when there is no grant)."}},"required":["grant_usd","reserved_usd","spent_usd","available_usd"],"description":"The workspace Bench allowance state."},"dispositions":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The frozen call type."},"disposition":{"type":"string","enum":["runnable","not_runnable","deduped","budget_queued"],"description":"runnable | not_runnable | deduped | budget_queued."},"reason":{"type":"string","nullable":true,"description":"Why not_runnable (insufficient_items/not_frozen/no_incumbent/no_candidates/underpowered), else null."},"tier":{"type":"string","enum":["insufficient_items","exploratory","standard"],"description":"The PLANNING verdict tier from the frozen card (<10/10–29/≥30 unique) — never a verdict."},"tier_summary":{"type":"string","description":"Planning-language readout of the tier."},"unique_count":{"type":"integer","minimum":0,"description":"The PINNED item count driving the tier + runnability: card.item_count (post-cap) — exactly the items the run executes. Equals the frozen unique count when uncapped; a max_items cap makes it the smaller pinned count so the tier reflects what actually runs."},"dataset_hash":{"type":"string","nullable":true,"description":"The frozen dataset content address, or null."},"estimate_usd":{"type":"number","description":"This child run's bounded planning estimate in USD (before global admission)."},"reserved_usd":{"type":"number","description":"The atomically-reserved allowance held for this run (USD)."},"eval_run_id":{"type":"string","nullable":true,"description":"The fanned child eval run id (runnable), else null."},"prior_run_id":{"type":"string","nullable":true,"description":"The prior run linked when deduped, else null."},"judge_worst_case_usd":{"type":"number","description":"The CONSERVATIVE worst-case JUDGE-phase cost (USD) this call type could incur — the SAME arithmetic the phase-time guard uses (pairs × positions × tiers × pinned maxTokens at judge rates + a re-invoke allowance), surfaced additively (NOT folded into estimate_usd). 0 for a judge_disabled (all-asserted / zero-judge) call type or an unpriced/stub judge. The umbrella admission checks arms + this bound against max_cost, so an unaffordable judge phase is refused at the trigger (judge_phase_unaffordable) before any arm spend."},"power":{"type":"object","properties":{"margin_pp":{"type":"number","description":"The registered non-inferiority margin Δ (pp) the advisory sizes power against."},"mde_pp":{"type":"number","description":"The planning MDE (pp) recomputed from the card prior SD + cluster n vs THIS margin — a power diagnostic, never a verdict."},"cluster_n":{"type":"integer","minimum":0,"description":"The frozen card independent-cluster n (the inferential unit)."},"required_clusters":{"type":"integer","minimum":0,"description":"The minimum clusters THIS margin needs at the plan alpha/power (never loosened)."},"underpowered":{"type":"boolean","description":"True when cluster_n < required_clusters (mde_pp > margin_pp) — advisory, never a blocking gate."}},"required":["margin_pp","mde_pp","cluster_n","required_clusters","underpowered"],"description":"Pre-spend power advisory — attached to runnable/deduped/budget_queued and the underpowered park (a not_runnable without a frozen card carries none)."},"unmatched_candidates":{"type":"array","items":{"type":"string"},"description":"EXPLICIT candidate ids that matched an offer globally but were NOT challengers for THIS call type (e.g. they resolve to the incumbent here) — a partial match is legal but VISIBLE. A fully-unmatched id is a 400 at the trigger, never a silent drop."}},"required":["call_type_id","disposition","reason","tier","tier_summary","unique_count","dataset_hash","estimate_usd","reserved_usd","eval_run_id","prior_run_id"],"description":"A per-call-type bench run disposition."},"description":"The per-call-type dispositions."},"runs":{"type":"array","items":{"type":"object","properties":{"eval_run_id":{"type":"string","description":"The child eval run id."},"call_type_id":{"type":"string","description":"The call type this child ran."},"status":{"type":"string","description":"The eval-run status (queued/running/scored/judge_pending/judge_running/complete/failed)."},"tier":{"type":"string","description":"The PLANNING verdict tier (planning language, never a verdict)."},"dataset_hash":{"type":"string","nullable":true,"description":"The frozen dataset content address."},"judged_pairs":{"type":"integer","description":"The LIVE count of fully-judged pairs. On a `judge_running` child it advances during the judge phase (diagnosable at a glance); at terminal it is the final judged count; 0 before judging."},"budget_spent_usd":{"type":"number","description":"The settled bench spend for this child (USD)."},"arms":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string","description":"The arm model id."},"provider":{"type":"string","description":"The serving provider slug."},"is_incumbent":{"type":"boolean","description":"Whether this is the re-invoked incumbent arm."},"composite_score":{"type":"number","nullable":true,"description":"The composite quality score, or null when skipped."},"passed":{"type":"boolean","nullable":true,"description":"The non-inferiority pass flag, or null."},"skipped":{"type":"boolean","description":"Whether the arm was skipped (keyless / no offer / envelope_mismatch)."},"skip_reason":{"type":"string","nullable":true,"description":"Why the arm was skipped, else null."},"total_cost_usd":{"type":"number","description":"The arm total cost (USD)."}},"required":["model","provider","is_incumbent","composite_score","passed","skipped","skip_reason","total_cost_usd"],"description":"One arm of a child bench eval run."},"description":"The per-arm evidence (incumbent + challengers)."},"trust_class":{"type":"string","nullable":true,"enum":["A","B","C"],"description":"The composite trust class (A/B/C), or null."},"evidence_classes":{"type":"array","items":{"type":"object","properties":{"scorer_id":{"type":"string","description":"The composite scorer id (or `outcome`)."},"evidence_class":{"type":"string","enum":["programmatic","outcome","reference","judge"],"description":"The evidence class the metric belongs to."},"weight":{"type":"number","description":"The absolute composite weight."},"share":{"type":"number","minimum":0,"maximum":1,"description":"The composite weight share (0–1)."}},"required":["scorer_id","evidence_class","weight","share"],"description":"An evidence-class-tagged composite metric row."},"description":"Per-metric evidence-class tags (empty until merged)."},"judge_disabled":{"type":"boolean","description":"Whether the ruler retired the judge residue (an all-asserted zero-judge run)."}},"required":["eval_run_id","call_type_id","status","tier","dataset_hash","judged_pairs","budget_spent_usd","arms","trust_class","evidence_classes","judge_disabled"],"description":"A child eval run of a bench run."},"description":"The child eval runs (tier + per-arm evidence)."}},"required":["object","id","suite","mode","selection_mode","status","estimate_usd","allowance","dispositions","runs"],"description":"ultrarouter Bench on-demand run."},"BenchExpectationsRequest":{"type":"object","properties":{"expectations":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The assertion kind (json_schema/exact_field/regex_match/citation_substring)."},"config":{"type":"object","additionalProperties":{"nullable":true},"default":{},"description":"The scorer config (required_fields / field / pattern+flags; a json_schema assertion may set closed:true to reject any leaf outside the pinned set); validated per kind."},"call_type":{"type":"string","description":"Scope the assertion to a call type id, or omit for the whole suite."},"item_content_hash":{"type":"string","description":"Narrow the assertion to a specific dataset item content hash."},"request_id":{"type":"string","description":"Narrow the assertion to a specific captured request id."}},"required":["kind"],"description":"A customer Bench assertion input."},"minItems":1,"maxItems":200,"description":"The customer assertions to attach (validated against the closed vocabulary)."}},"required":["expectations"],"description":"ultrarouter Bench assertions attach request."},"BenchExpectationsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_expectations"]},"suite":{"type":"string","description":"The bench suite slug."},"suite_id":{"type":"string","description":"The bench suite id (`bs_…`)."},"attached":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The assertion id (`bx_…`), or empty when rejected."},"kind":{"type":"string","description":"The echoed assertion kind (may be an unknown kind when rejected)."},"hash":{"type":"string","description":"The content address of (kind + config)."},"version":{"type":"integer","minimum":0,"description":"The per-suite monotonic version stamp (0 when rejected)."},"created":{"type":"boolean","description":"False when the identical assertion already existed (idempotent)."},"call_type":{"type":"string","nullable":true,"description":"The scoped call type id, or null (suite-wide)."},"valid":{"type":"boolean","description":"Whether the assertion passed closed-vocabulary validation."},"reason":{"type":"string","nullable":true,"description":"The validation rejection reason, or null when valid."}},"required":["id","kind","hash","version","created","call_type","valid","reason"],"description":"An attached (or rejected) Bench assertion."},"description":"One row per input assertion (attached or rejected with a reason)."},"accepted":{"type":"integer","minimum":0,"description":"How many assertions validated + attached."},"rejected":{"type":"integer","minimum":0,"description":"How many were rejected (invalid config/kind)."}},"required":["object","suite","suite_id","attached","accepted","rejected"],"description":"ultrarouter Bench assertions attach result."},"BenchOutcomesRequest":{"type":"object","properties":{"outcomes":{"type":"array","items":{"type":"object","properties":{"trace":{"type":"string","description":"The task/trace id the outcome grades (the stats cluster id)."},"passed":{"type":"boolean","description":"The binary ground-truth verdict for the whole trace."},"call_type":{"type":"string","description":"The call type the trace belongs to (optional)."},"labels":{"type":"object","additionalProperties":{"nullable":true},"description":"Optional free-form labels (no PII)."}},"required":["trace","passed"],"description":"A first-party per-trace outcome input."},"minItems":1,"maxItems":500,"description":"The per-trace binary outcomes to record (append-forward, latest wins)."}},"required":["outcomes"],"description":"ultrarouter Bench outcomes record request."},"BenchOutcomesResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_outcomes"]},"suite":{"type":"string","description":"The bench suite slug."},"suite_id":{"type":"string","description":"The bench suite id (`bs_…`)."},"bench_run_id":{"type":"string","nullable":true,"description":"The run scope, or null (suite-scoped)."},"recorded":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The outcome id (`bo_…`)."},"trace":{"type":"string","description":"The graded trace id."},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The per-suite monotonic version stamp."},"created":{"type":"boolean","description":"False when the identical outcome already existed (idempotent)."}},"required":["id","trace","version","created"],"description":"A recorded Bench outcome."},"description":"One row per recorded outcome."},"total":{"type":"integer","minimum":0,"description":"How many outcomes were recorded."}},"required":["object","suite","suite_id","bench_run_id","recorded","total"],"description":"ultrarouter Bench outcomes record result."},"BenchReportResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_report"]},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"bench_run_id":{"type":"string"},"suite":{"type":"string"},"mode":{"type":"string","enum":["request","task"]},"selection_mode":{"type":"string","enum":["selection","noninferiority"]},"status":{"type":"string"},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"eval_run_id":{"type":"string"},"status":{"type":"string"},"tier":{"type":"string","description":"The PLANNING verdict tier (planning language, never a verdict)."},"dataset_card":{"type":"object","nullable":true,"properties":{"call_type_id":{"type":"string","description":"The call type this dataset is compiled for."},"dataset_hash":{"type":"string","description":"Content address — identical captures ⇒ identical hash."},"captured_count":{"type":"integer","minimum":0,"description":"n confirmed envelopes fed in."},"admitted_count":{"type":"integer","minimum":0,"description":"n admitted (captured − PII/empty)."},"unique_count":{"type":"integer","minimum":0,"description":"n exact-dedup uniques (before the cap)."},"item_count":{"type":"integer","minimum":0,"description":"n items in the frozen dataset (post ≤500 cap)."},"cluster_count":{"type":"integer","minimum":0,"description":"The VERDICT-LEVEL inferential-cluster n — one cluster per independent task/trace, else per item identity: the SAME unit the deciding interval-based verdict uses. Powers the power plan; the SimHash near-duplicate group count is reported separately as near_dup_cluster_count."},"near_dup_cluster_count":{"type":"integer","minimum":0,"description":"The SimHash near-DUPLICATE group count (masked-template redundancy) — a SEPARATE disclosure, NOT the plan n. Absent on legacy cards frozen before this field existed."},"task_count":{"type":"integer","minimum":0,"description":"Distinct task/trace ids present."},"shape":{"type":"string","enum":["request","task"],"description":"Request- or task-shaped overall."},"strata":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","description":"The stratum key (length/lang/tools/feedback tuple)."},"unique_count":{"type":"integer","minimum":0,"description":"Unique items in this stratum."},"frequency_weight":{"type":"integer","minimum":0,"description":"Frequency-weighted population share of the stratum (the shared population weight)."},"thin":{"type":"boolean","description":"True when the stratum is under-powered (below the thin threshold)."}},"required":["key","unique_count","frequency_weight","thin"],"description":"A dataset-card stratum summary."},"description":"Per-stratum summaries + thin warnings."},"exclusions":{"type":"array","items":{"type":"object","properties":{"envelope_ids":{"type":"array","items":{"type":"string"},"description":"The confirmed envelope ids excluded together."},"reason":{"type":"string","enum":["pii_low_confidence","empty_content","over_cap"],"description":"Why the item(s) were excluded (visible per-item on the card)."}},"required":["envelope_ids","reason"],"description":"A dataset-card exclusion."},"description":"Visible per-item exclusions."},"power_plan":{"type":"object","properties":{"cluster_n":{"type":"integer","minimum":0,"description":"The VERDICT-LEVEL inferential-cluster n — the SAME unit the deciding interval-based verdict bootstraps (one cluster per task/trace, else per item identity), NOT the SimHash near-duplicate group count."},"prior_quality_sd":{"type":"number","description":"The conservative-prior (or A/A) composite-quality SD."},"alpha":{"type":"number","description":"The significance level the plan assumed."},"power":{"type":"number","description":"The target power (e.g. 0.8)."},"margin_pp":{"type":"number","description":"The preregistered non-inferiority margin Δ (pp)."},"mde_pp":{"type":"number","description":"The minimum detectable effect (pp) — a PLANNING number, not a verdict."},"required_clusters":{"type":"integer","minimum":0,"description":"The minimum verdict-level clusters this margin needs at the plan alpha/power (so \"cap < required\" is visible AT FREEZE) — a PLANNING number, never a gate (the margin is never loosened). Absent on legacy cards frozen before this field existed."},"adequately_powered":{"type":"boolean","description":"Power adequacy HINT (mde_pp ≤ margin_pp) — still never a verdict."},"summary":{"type":"string","description":"Planning-language readout (\"can detect ~Xpp at 80% power\")."}},"required":["cluster_n","prior_quality_sd","alpha","power","margin_pp","mde_pp","adequately_powered","summary"],"description":"The preregistered power plan — planning language, never a verdict."},"staleness":{"type":"object","properties":{"prior_run_count":{"type":"integer","minimum":0,"description":"Runs referencing this dataset_hash."},"stale":{"type":"boolean","description":"Whether the run count trips the staleness flag."}},"required":["prior_run_count","stale"],"description":"Prior-run staleness disclosure."},"attestation":{"type":"boolean","description":"Whether the audited low-confidence-PII attestation admitted otherwise-excluded items."}},"required":["call_type_id","dataset_hash","captured_count","admitted_count","unique_count","item_count","cluster_count","task_count","shape","strata","exclusions","power_plan","staleness","attestation"],"description":"Section 1: the frozen dataset card."},"power":{"type":"object","properties":{"unique_n":{"type":"integer","minimum":0},"cluster_n":{"type":"integer","minimum":0},"mde_pp":{"type":"number"},"margin_pp":{"type":"number"},"margin_source":{"type":"string","description":"WHERE the margin came from (`run_spec` = pinned at enqueue)."},"cost_min_savings":{"type":"number"},"alpha":{"type":"number"},"power":{"type":"number"},"adequately_powered":{"type":"boolean"}},"required":["unique_n","cluster_n","mde_pp","margin_pp","margin_source","cost_min_savings","alpha","power","adequately_powered"],"description":"Section 2: the power statement (unique n, planning MDE, pre-registered margins)."},"arms":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"is_incumbent":{"type":"boolean","description":"The re-invoked incumbent arm — never a fictitious $0 row."},"cost_evidence_id":{"type":"string","nullable":true,"description":"The immutable CostEvidenceV2 id (source unity)."},"usage_basis":{"type":"string","nullable":true},"cost_basis_label":{"type":"string","nullable":true,"enum":["measured","estimated"],"description":"`measured` only for the measured family; `estimated` otherwise."},"unit":{"type":"string","enum":["$/request","$/task"],"description":"The honest cost unit: $/task only with task proof."},"denominator":{"type":"integer","minimum":0},"observed_per_request_micro_usd":{"type":"number","nullable":true},"observed_per_task_micro_usd":{"type":"number","nullable":true},"cost_views":{"type":"array","items":{"type":"object","properties":{"view":{"type":"string","enum":["observed_eval_charge","constant_rate_technical","modeled_online_net","marginal_cash","invoice_reconciled"],"description":"The CostEvidenceV2 view."},"total_micro_usd":{"type":"number","nullable":true,"description":"The all-arm total for the view (µUSD), or null."},"per_unit_micro_usd":{"type":"number","nullable":true,"description":"total ÷ denominator — the per-UNIT figure (µUSD)."}},"required":["view","total_micro_usd","per_unit_micro_usd"],"description":"A CostEvidenceV2 cost view, by basis."}},"token_components":{"type":"object","nullable":true,"additionalProperties":{"type":"integer","minimum":0},"description":"Billed unit components (input/output/cached/reasoning/…) — never a universal efficiency unit."},"completeness":{"type":"number","nullable":true},"uncertainty_micro_usd":{"type":"number","nullable":true},"p95_latency_ms":{"type":"number","nullable":true},"composite_score":{"type":"number","nullable":true},"quality_interval":{"type":"object","nullable":true,"properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"},"n":{"type":"integer","minimum":0},"clusters":{"type":"integer","minimum":0},"bar":{"type":"number","description":"The registered bar the interval is judged against (−Δ or min-savings)."}},"required":["low","high","point","n","clusters","bar"],"description":"A decision interval, verbatim."},"skipped":{"type":"boolean"},"skip_reason":{"type":"string","nullable":true}},"required":["model","provider","is_incumbent","cost_evidence_id","usage_basis","cost_basis_label","unit","denominator","observed_per_request_micro_usd","observed_per_task_micro_usd","cost_views","token_components","completeness","uncertainty_micro_usd","p95_latency_ms","composite_score","quality_interval","skipped","skip_reason"],"description":"One arm headline row (report section 3)."},"description":"Section 3: per-arm headline rows."},"inversions":{"type":"array","items":{"type":"object","properties":{"candidate_model":{"type":"string"},"incumbent_model":{"type":"string"},"candidate_per_request_micro_usd":{"type":"number"},"incumbent_per_request_micro_usd":{"type":"number"},"candidate_per_task_micro_usd":{"type":"number"},"incumbent_per_task_micro_usd":{"type":"number"},"note":{"type":"string"}},"required":["candidate_model","incumbent_model","candidate_per_request_micro_usd","incumbent_per_request_micro_usd","candidate_per_task_micro_usd","incumbent_per_task_micro_usd","note"]},"description":"Cost inversion callouts (per-request-cheaper but per-task-costlier)."},"verdicts":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"quality":{"type":"string","enum":["pass","fail","inconclusive"]},"cost":{"type":"string","enum":["pass","fail","inconclusive"]},"overall":{"type":"string","enum":["pass","fail","inconclusive"]},"quality_interval":{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"},"n":{"type":"integer","minimum":0},"clusters":{"type":"integer","minimum":0},"bar":{"type":"number","description":"The registered bar the interval is judged against (−Δ or min-savings)."}},"required":["low","high","point","n","clusters","bar"],"description":"A decision interval, verbatim."},"cost_interval":{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"},"n":{"type":"integer","minimum":0},"clusters":{"type":"integer","minimum":0},"bar":{"type":"number","description":"The registered bar the interval is judged against (−Δ or min-savings)."}},"required":["low","high","point","n","clusters","bar"],"description":"A decision interval, verbatim."},"outcome_interval":{"type":"object","nullable":true,"properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"},"n":{"type":"integer","minimum":0},"clusters":{"type":"integer","minimum":0},"bar":{"type":"number","description":"The registered bar the interval is judged against (−Δ or min-savings)."}},"required":["low","high","point","n","clusters","bar"],"description":"The folded first-party outcome interval."},"mde_pp":{"type":"number","description":"The MDE (pp) — a POWER DIAGNOSTIC, never the verdict."},"reasons":{"type":"array","items":{"type":"string"}},"remediation":{"type":"string","nullable":true,"description":"The named remediation for a keep/inconclusive verdict."}},"required":["model","quality","cost","overall","quality_interval","cost_interval","outcome_interval","mde_pp","reasons","remediation"],"description":"A candidate verdict, verbatim (report section 4)."},"description":"Section 4: interval-based verdicts, verbatim."},"trust_class":{"type":"string","nullable":true,"enum":["A","B","C"],"description":"The PINNED composite trust class, never a live read."},"trust_statement":{"type":"string","nullable":true},"evidence_classes":{"type":"array","items":{"type":"object","properties":{"scorer_id":{"type":"string","description":"The composite scorer id (or `outcome`)."},"evidence_class":{"type":"string","enum":["programmatic","outcome","reference","judge"],"description":"The evidence class the metric belongs to."},"weight":{"type":"number","description":"The absolute composite weight."},"share":{"type":"number","minimum":0,"maximum":1,"description":"The composite weight share (0–1)."}},"required":["scorer_id","evidence_class","weight","share"],"description":"An evidence-class-tagged composite metric row."}},"judge_disabled":{"type":"boolean"},"projection":{"type":"object","properties":{"available":{"type":"boolean"},"estimate_micro_usd_month":{"type":"number","nullable":true},"basis":{"type":"object","properties":{"calls":{"type":"integer","minimum":0},"input_tokens":{"type":"integer","minimum":0},"output_tokens":{"type":"integer","minimum":0}},"required":["calls","input_tokens","output_tokens"]},"candidate_model":{"type":"string","nullable":true},"per_unit_saving_micro_usd":{"type":"number","nullable":true},"unit":{"type":"string","enum":["$/request","$/task"]},"reason":{"type":"string","nullable":true}},"required":["available","estimate_micro_usd_month","basis","candidate_model","per_unit_saving_micro_usd","unit","reason"],"description":"Section 5: the honest projection (ESTIMATE only where trailing volume exists)."},"task_view":{"type":"array","items":{"type":"object","properties":{"trace_id":{"type":"string"},"incumbent_passed":{"type":"boolean","nullable":true},"candidate_passed":{"type":"boolean","nullable":true},"outcome_delta":{"type":"number","nullable":true},"items_in_trace":{"type":"integer","minimum":0}},"required":["trace_id","incumbent_passed","candidate_passed","outcome_delta","items_in_trace"],"description":"A per-trace task-view row (report section 6)."},"description":"Section 6: per-trace task view."},"limitations":{"type":"array","items":{"type":"string"},"description":"Section 7: auto-generated limitations."},"partial":{"type":"boolean"}},"required":["call_type_id","eval_run_id","status","tier","dataset_card","power","arms","inversions","verdicts","trust_class","trust_statement","evidence_classes","judge_disabled","projection","task_view","limitations","partial"],"description":"One call type report block."},"description":"One block per call type (sections 1–7)."},"limitations":{"type":"array","items":{"type":"string"},"description":"The report-level limitations union."},"reproducibility":{"type":"object","properties":{"run_spec_ids":{"type":"array","items":{"type":"string"}},"execution_profile_hashes":{"type":"array","items":{"type":"string"}},"cost_evidence_ids":{"type":"array","items":{"type":"string"}},"decision_ids":{"type":"array","items":{"type":"string"}},"dataset_hashes":{"type":"array","items":{"type":"string"}},"seeds":{"type":"array","items":{"type":"number"}},"versions":{"type":"object","additionalProperties":{"type":"string"}}},"required":["run_spec_ids","execution_profile_hashes","cost_evidence_ids","decision_ids","dataset_hashes","seeds","versions"],"description":"Section 8: the reproducibility appendix (spec/profile/evidence/decision ids, seeds, versions)."},"content_hash":{"type":"string","description":"The content address — a re-read is byte-stable."},"export":{"type":"object","properties":{"json_url":{"type":"string","description":"The JSON report export path (`?format=json`)."},"markdown_url":{"type":"string","description":"The Markdown export path (`?format=md`)."},"bundle_url":{"type":"string","description":"The independently verifiable evidence-bundle export path (`?format=bundle`)."}},"required":["json_url","markdown_url","bundle_url"],"description":"The audited export links (JSON / Markdown / verifiable bundle)."}},"required":["object","version","bench_run_id","suite","mode","selection_mode","status","call_types","limitations","reproducibility","content_hash","export"],"description":"The immutable ultrarouter Bench evidence report."},"BenchBaselineResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_baseline"]},"suite":{"type":"string","description":"The bench suite slug."},"suite_id":{"type":"string","description":"The bench suite id (`bs_…`)."},"baseline_run_id":{"type":"string","description":"The newly-pinned baseline run (`br_…`)."},"previous_baseline_run_id":{"type":"string","nullable":true,"description":"The baseline run this pin replaced, or null (first pin)."}},"required":["object","suite","suite_id","baseline_run_id","previous_baseline_run_id"],"description":"ultrarouter Bench baseline pin result."},"BenchCompareGateResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_compare_gate"]},"bench_run_id":{"type":"string"},"baseline_run_id":{"type":"string","nullable":true},"verdict":{"type":"string","enum":["pass","fail","inconclusive"],"description":"The CI verdict = the STRICTEST across call types (fail > inconclusive > pass) — fails closed."},"cost_ceiling_micro_usd":{"type":"number","nullable":true},"entitlement":{"type":"object","properties":{"plan":{"type":"string","enum":["free","team"],"description":"The bench packaging plan."},"gate_entitled":{"type":"boolean","description":"Whether the workspace is entitled to the full CI gate (Team); free keeps read access."},"run_count_limit":{"type":"integer","nullable":true,"description":"Free monthly bench-run limit, or null when not run-count-limited (Team / prepaid grant)."},"run_count_used":{"type":"integer","nullable":true,"description":"Bench runs consumed this UTC calendar month, or null when not run-count-limited."},"max_candidates":{"type":"integer","nullable":true,"description":"Max challenger candidates per run, or null (Team)."},"max_items_per_call_type":{"type":"integer","nullable":true,"description":"Max frozen items per call-type run, or null (Team)."},"notice":{"type":"string","nullable":true,"description":"A legible entitlement notice (e.g. the CI-gate-is-Team notice), or null."}},"required":["plan","gate_entitled","run_count_limit","run_count_used","max_candidates","max_items_per_call_type","notice"],"description":"The bench packaging entitlement — a free workspace gets the verdict WITH a Team-gate notice, never a silent denial."},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"eval_run_id":{"type":"string","description":"The candidate (current-config) child eval run."},"baseline_eval_run_id":{"type":"string","nullable":true,"description":"The paired baseline child eval run, or null (no baseline for this call type)."},"verdict":{"type":"string","enum":["pass","fail","inconclusive"]},"quality":{"type":"string","enum":["pass","fail","inconclusive"]},"cost":{"type":"string","enum":["pass","fail","inconclusive"]},"quality_interval":{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"},"n":{"type":"integer","minimum":0},"clusters":{"type":"integer","minimum":0},"bar":{"type":"number","description":"The registered bar the interval is judged against (−Δ or min-savings)."}},"required":["low","high","point","n","clusters","bar"],"description":"A decision interval, verbatim."},"cost_interval":{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"},"n":{"type":"integer","minimum":0},"clusters":{"type":"integer","minimum":0},"bar":{"type":"number","description":"The registered bar the interval is judged against (−Δ or min-savings)."}},"required":["low","high","point","n","clusters","bar"],"description":"A decision interval, verbatim."},"quality_margin_pp":{"type":"number","description":"The registered non-inferiority margin Δ (pp)."},"cost_min_savings":{"type":"number","description":"The registered minimum cost-savings bar (fraction)."},"mde_pp":{"type":"number","description":"The MDE (pp) — a POWER DIAGNOSTIC, never the verdict."},"cost_ceiling":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Whether an absolute cost ceiling is enforced."},"ceiling_micro_usd":{"type":"number","nullable":true,"description":"The absolute per-unit ceiling (µUSD), or null."},"observed_mean_micro_usd":{"type":"number","nullable":true,"description":"The candidate mean per-unit cost over eligible pairs (µUSD), or null."},"breached":{"type":"boolean","description":"True when the observed mean exceeds the ceiling (a hard cost fail)."}},"required":["enabled","ceiling_micro_usd","observed_mean_micro_usd","breached"],"description":"The compare-gate absolute cost ceiling."},"pairing":{"type":"object","properties":{"candidate_items":{"type":"integer","minimum":0},"eligible_pairs":{"type":"integer","minimum":0,"description":"Pairs with a retained baseline artifact."},"ineligible_missing_artifact":{"type":"integer","minimum":0,"description":"Pairs whose baseline artifact was missing/expired (excluded, degrades)."},"unpaired":{"type":"integer","minimum":0,"description":"Candidate items with no baseline counterpart (excluded, stated)."},"eligible_clusters":{"type":"integer","minimum":0,"description":"Independent eligible clusters (the true inferential n)."}},"required":["candidate_items","eligible_pairs","ineligible_missing_artifact","unpaired","eligible_clusters"],"description":"The compare-gate pairing census."},"reasons":{"type":"array","items":{"type":"string"},"description":"Machine-readable reasons the verdict is not a full pass."}},"required":["call_type_id","eval_run_id","baseline_eval_run_id","verdict","quality","cost","quality_interval","cost_interval","quality_margin_pp","cost_min_savings","mde_pp","cost_ceiling","pairing","reasons"],"description":"One call type compare gate."}},"reasons":{"type":"array","items":{"type":"string"},"description":"The union of every call type’s reasons."}},"required":["object","bench_run_id","baseline_run_id","verdict","cost_ceiling_micro_usd","entitlement","call_types","reasons"],"description":"The ultrarouter Bench baseline-compare gate (interval-based tri-state)."},"BenchShareMintRequest":{"type":"object","properties":{"display_name":{"type":"string","minLength":1,"maxLength":120,"description":"The ONLY identity surfaced on the public page (never workspace/suite/run identity)."},"include_previews":{"type":"boolean","description":"Opt in to REDACTED example previews — honored ONLY when the suite carries the audited attestation; every preview is re-redacted regardless (opt-in never bypasses redaction)."},"remove_footer":{"type":"boolean","description":"Remove the \"Benchmarked with ultrarouter\" footer — honored ONLY on the Team plan (free always shows the footer)."}},"required":["display_name"],"description":"ultrarouter Bench public-share mint request."},"BenchShareMintResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_share"]},"share_id":{"type":"string","description":"The share id (`bsh_…`)."},"token":{"type":"string","description":"The raw bearer token — shown EXACTLY once, never stored (only its SHA-256 hash is)."},"url":{"type":"string","description":"The full public URL (gateway origin + `/share/bench/<token>`)."},"path":{"type":"string","description":"The public path (`/share/bench/<token>`)."},"display_name":{"type":"string","description":"The chosen display name (the only identity on the page)."},"plan":{"type":"string","enum":["free","team"],"description":"The plan pinned at mint (resolves the footer entitlement)."},"footer_removed":{"type":"boolean","description":"Whether the footer was removed (only possible on Team)."},"include_previews":{"type":"boolean","description":"Whether redacted previews were included."},"previews_gated":{"type":"boolean","description":"Whether the suite attestation gated previews on (previews require it + the opt-in)."}},"required":["object","share_id","token","url","path","display_name","plan","footer_removed","include_previews","previews_gated"],"description":"ultrarouter Bench public-share mint result."},"BenchSharesListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["bench_share_list"]},"bench_run_id":{"type":"string"},"shares":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The share id (`bsh_…`)."},"display_name":{"type":"string"},"include_previews":{"type":"boolean"},"footer_removed":{"type":"boolean"},"plan":{"type":"string","enum":["free","team"]},"view_count":{"type":"integer","minimum":0,"description":"Coarse view counter (no viewer PII)."},"last_viewed_at":{"type":"string","nullable":true},"revoked_at":{"type":"string","nullable":true,"description":"When the share was revoked, or null (active)."},"created_at":{"type":"string"}},"required":["id","display_name","include_previews","footer_removed","plan","view_count","last_viewed_at","revoked_at","created_at"],"description":"A bench public-share summary — never the token."}}},"required":["object","bench_run_id","shares"],"description":"ultrarouter Bench public-share list."},"AuditReadinessResponse":{"type":"object","properties":{"object":{"type":"string","enum":["audit_readiness"]},"state":{"type":"string","enum":["observing"],"description":"Workspace audit state — passive observation only."},"generated":{"type":"boolean","description":"False when the analyze worker has not produced a rollup yet (honest empty)."},"config_version":{"type":"integer","minimum":0,"description":"The config_version the rollup used."},"window_start":{"type":"string","description":"Rollup window start (ISO 8601)."},"window_end":{"type":"string","description":"Rollup window end (ISO 8601)."},"computed_at":{"type":"string","nullable":true,"description":"When the rollup was computed (ISO 8601), or null."},"total_requests":{"type":"integer","minimum":0},"total_spend_micro_usd":{"type":"integer","minimum":0},"observing_call_types":{"type":"integer","minimum":0},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string","description":"The call type id (`ct_…`)."},"slug":{"type":"string","description":"The call type slug."},"display_name":{"type":"string","description":"The human display name."},"source":{"type":"string","description":"`explicit` (caller slug) or `fingerprint` (automatically inferred from request shape)."},"lifecycle_state":{"type":"string","description":"Audit lifecycle state — `observing` in this passive subset."},"confidence":{"type":"string","enum":["high","medium","low"],"description":"Confidence this is a real, stable task shape."},"requests":{"type":"integer","minimum":0,"description":"Observed request volume in the window."},"spend_micro_usd":{"type":"integer","minimum":0,"description":"Observed spend (integer µUSD)."},"error_rate":{"type":"number","description":"Fraction of requests that errored, in [0,1]."},"cache_hit_rate":{"type":"number","description":"Fraction of requests that read a provider cache."},"fallback_rate":{"type":"number","description":"Fraction of requests that fell back to a non-primary offer."},"models_seen":{"type":"array","items":{"type":"string"},"description":"Distinct served models observed."},"providers_seen":{"type":"array","items":{"type":"string"},"description":"Distinct providers observed."},"cost_provenance":{"type":"object","properties":{"measured_replayable":{"type":"integer","minimum":0,"description":"Requests with a confirmed, replayable envelope → provider-reported usage."},"estimate_only":{"type":"integer","minimum":0,"description":"Requests whose cost is estimate-only (no replayable evidence)."}},"required":["measured_replayable","estimate_only"],"description":"Cost-provenance mix (an estimate is never labeled as provider-reported usage)."},"capture":{"type":"object","properties":{"confirmed":{"type":"integer","minimum":0},"non_replayable":{"type":"integer","minimum":0},"queued":{"type":"integer","minimum":0}},"required":["confirmed","non_replayable","queued"],"description":"Capture coverage for this call type."},"evidence_gaps":{"type":"array","items":{"type":"string"},"description":"Machine-readable evidence gaps — WHAT is unavailable and WHY (honesty)."}},"required":["call_type_id","slug","display_name","source","lifecycle_state","confidence","requests","spend_micro_usd","error_rate","cache_hit_rate","fallback_rate","models_seen","providers_seen","cost_provenance","capture","evidence_gaps"],"description":"Per-call-type passive readiness."}},"emerging_shapes":{"type":"array","items":{"type":"object","properties":{"hash8":{"type":"string","description":"The 8-hex-char template label."},"request_count":{"type":"integer","minimum":0,"description":"Observed similar requests so far."},"sample_prompt_masked":{"type":"string","description":"MASKED template preview (never raw content)."},"requests_to_surface":{"type":"integer","minimum":0,"description":"Requests remaining until the shape crosses the noise gate and surfaces as a call type."}},"required":["hash8","request_count","sample_prompt_masked","requests_to_surface"],"description":"An inferred request shape not yet surfaced as a call type."}},"inventory":{"type":"object","properties":{"providers":{"type":"array","items":{"type":"string"}},"models":{"type":"array","items":{"type":"string"}},"key_modes":{"type":"array","items":{"type":"string"}}},"required":["providers","models","key_modes"],"description":"Workspace inventory observed in the window."},"opportunities":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"slug":{"type":"string"},"spend_micro_usd":{"type":"integer","minimum":0},"current_model":{"type":"string","description":"The dominant (highest-priced) model observed."},"candidate_model":{"type":"string","description":"A cheaper catalog candidate (blended-price shortlist)."},"candidate_provider":{"type":"string"},"est_window_savings_micro_usd":{"type":"integer","description":"Estimated window savings (DISCOVERY — never realized cash)."},"est_monthly_savings_micro_usd":{"type":"integer","description":"Estimated monthly savings (DISCOVERY — never realized cash)."},"basis":{"type":"string","enum":["blended_price_discovery"],"description":"Blended per-token price shortlist basis."},"label":{"type":"string","enum":["discovery"],"description":"Always discovery — never a realized/claimed figure."}},"required":["call_type_id","slug","spend_micro_usd","current_model","candidate_model","candidate_provider","est_window_savings_micro_usd","est_monthly_savings_micro_usd","basis","label"],"description":"A DISCOVERY savings opportunity (blended-price shortlist, never a migration claim)."}},"coverage":{"type":"object","properties":{"retention_mode":{"type":"string","description":"Payload retention (`none`|`metadata`|`full`)."},"payload_consented":{"type":"boolean","description":"True only when retention is `full` (replay consent)."},"confirmed_envelopes":{"type":"integer","minimum":0},"non_replayable_envelopes":{"type":"integer","minimum":0},"queued_envelopes":{"type":"integer","minimum":0},"unconsented_capture_sampled":{"type":"boolean","description":"True when no-consent shape metadata is sampled (metadata retention)."},"unconsented_sample_rate":{"type":"number","description":"The deterministic sample rate bounding no-consent metadata-envelope volume."},"notes":{"type":"array","items":{"type":"string"},"description":"Human-readable coverage/honesty notes."}},"required":["retention_mode","payload_consented","confirmed_envelopes","non_replayable_envelopes","queued_envelopes","unconsented_capture_sampled","unconsented_sample_rate","notes"],"description":"Evidence-coverage summary — visibly surfaces the no-consent metadata sampling."}},"required":["object","state","generated","config_version","window_start","window_end","computed_at","total_requests","total_spend_micro_usd","observing_call_types","call_types","emerging_shapes","inventory","opportunities","coverage"],"description":"Audit Autopilot passive readiness report (zero-config, zero authority)."},"FeedbackRequest":{"type":"object","properties":{"rating":{"anyOf":[{"type":"number","enum":[1]},{"type":"number","enum":[-1]}],"description":"Thumbs up (1) or thumbs down (-1) — the human feedback signal evals consume."},"tags":{"type":"array","items":{"type":"string"},"maxItems":32,"description":"Optional free-form tags (e.g. \"hallucination\", \"great\")."},"comment":{"type":"string","maxLength":4000,"description":"Optional free-text comment."}},"required":["rating"],"description":"Human feedback on a prior request."},"FeedbackResponse":{"type":"object","properties":{"object":{"type":"string","enum":["request_feedback"]},"id":{"type":"string"},"request_id":{"type":"string"},"rating":{"anyOf":[{"type":"number","enum":[1]},{"type":"number","enum":[-1]}]},"tags":{"type":"array","items":{"type":"string"}},"comment":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["object","id","request_id","rating","tags","comment","created_at"],"description":"A stored feedback row."},"FeedbackEnvelope":{"type":"object","properties":{"feedback":{"type":"object","properties":{"object":{"type":"string","enum":["request_feedback"]},"id":{"type":"string"},"request_id":{"type":"string"},"rating":{"anyOf":[{"type":"number","enum":[1]},{"type":"number","enum":[-1]}]},"tags":{"type":"array","items":{"type":"string"}},"comment":{"type":"string","nullable":true},"created_at":{"type":"string"}},"required":["object","id","request_id","rating","tags","comment","created_at"],"description":"A stored feedback row."}},"required":["feedback"],"description":"A stored feedback row, wrapped in the `feedback` envelope."},"ArtifactObjective":{"type":"object","properties":{"metric":{"type":"string","enum":["claim_resolution","oracle_delta","correction_rate","acceptance_rate","engagement_rate","task_success"],"description":"The objective metric (closed vocabulary)."},"unit":{"type":"string","minLength":1,"maxLength":64,"description":"The unit the metric is measured in (e.g. `boolean`, `ratio`, `usd`)."},"direction":{"type":"string","minLength":1,"maxLength":64,"description":"Which direction is good (e.g. `true_is_good`, `higher_is_better`)."},"resolution_criteria":{"type":"string","minLength":1,"maxLength":2000,"description":"How the objective resolves — REDACTED free text, never a body."},"predicate_id":{"type":"string","enum":["equals","within_tolerance","ge","le","resolved_by_source"],"description":"An optional machine predicate over the resolution (closed set)."},"source":{"type":"string","minLength":1,"maxLength":256,"description":"Where the resolving signal comes from (e.g. `analyst`, `filing`, an oracle name)."},"window":{"type":"string","pattern":"^P(?!$)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+(?:\\.\\d+)?S)?)?$","description":"The resolution window as an ISO-8601 DURATION (e.g. `P12M`), never an instant."},"alternatives":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":64,"description":"Named alternatives for computable comparisons (`alternative_id`)."}},"required":["metric","unit","direction","resolution_criteria","source","window"],"additionalProperties":false,"description":"What “it worked” means for this artifact type — the ONE thing never inferred."},"UpsertArtifactTypeRequest":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":256,"description":"The customer-named type (`thesis`, `tax_plan`, `article`) — unique per workspace."},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The archetype every artifact of this type declares."},"objective":{"type":"object","properties":{"metric":{"type":"string","enum":["claim_resolution","oracle_delta","correction_rate","acceptance_rate","engagement_rate","task_success"],"description":"The objective metric (closed vocabulary)."},"unit":{"type":"string","minLength":1,"maxLength":64,"description":"The unit the metric is measured in (e.g. `boolean`, `ratio`, `usd`)."},"direction":{"type":"string","minLength":1,"maxLength":64,"description":"Which direction is good (e.g. `true_is_good`, `higher_is_better`)."},"resolution_criteria":{"type":"string","minLength":1,"maxLength":2000,"description":"How the objective resolves — REDACTED free text, never a body."},"predicate_id":{"type":"string","enum":["equals","within_tolerance","ge","le","resolved_by_source"],"description":"An optional machine predicate over the resolution (closed set)."},"source":{"type":"string","minLength":1,"maxLength":256,"description":"Where the resolving signal comes from (e.g. `analyst`, `filing`, an oracle name)."},"window":{"type":"string","pattern":"^P(?!$)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+(?:\\.\\d+)?S)?)?$","description":"The resolution window as an ISO-8601 DURATION (e.g. `P12M`), never an instant."},"alternatives":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":64,"description":"Named alternatives for computable comparisons (`alternative_id`)."}},"required":["metric","unit","direction","resolution_criteria","source","window"],"additionalProperties":false,"description":"What “it worked” means for this artifact type — the ONE thing never inferred."}},"required":["name","archetype","objective"],"additionalProperties":false,"description":"Register an artifact type / append an objective version."},"ArtifactType":{"type":"object","properties":{"object":{"type":"string","enum":["artifact_type"]},"id":{"type":"string"},"name":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The append-only objective version (max+1 per name; never rewritten)."},"objective":{"type":"object","properties":{"metric":{"type":"string","enum":["claim_resolution","oracle_delta","correction_rate","acceptance_rate","engagement_rate","task_success"],"description":"The objective metric (closed vocabulary)."},"unit":{"type":"string","minLength":1,"maxLength":64,"description":"The unit the metric is measured in (e.g. `boolean`, `ratio`, `usd`)."},"direction":{"type":"string","minLength":1,"maxLength":64,"description":"Which direction is good (e.g. `true_is_good`, `higher_is_better`)."},"resolution_criteria":{"type":"string","minLength":1,"maxLength":2000,"description":"How the objective resolves — REDACTED free text, never a body."},"predicate_id":{"type":"string","enum":["equals","within_tolerance","ge","le","resolved_by_source"],"description":"An optional machine predicate over the resolution (closed set)."},"source":{"type":"string","minLength":1,"maxLength":256,"description":"Where the resolving signal comes from (e.g. `analyst`, `filing`, an oracle name)."},"window":{"type":"string","pattern":"^P(?!$)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+(?:\\.\\d+)?S)?)?$","description":"The resolution window as an ISO-8601 DURATION (e.g. `P12M`), never an instant."},"alternatives":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":64,"description":"Named alternatives for computable comparisons (`alternative_id`)."}},"required":["metric","unit","direction","resolution_criteria","source","window"],"additionalProperties":false,"description":"What “it worked” means for this artifact type — the ONE thing never inferred."},"created_at":{"type":"string"}},"required":["object","id","name","archetype","version","objective","created_at"],"description":"An artifact-type objective version (append-only)."},"ArtifactTypeEnvelope":{"type":"object","properties":{"artifact_type":{"type":"object","properties":{"object":{"type":"string","enum":["artifact_type"]},"id":{"type":"string"},"name":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The append-only objective version (max+1 per name; never rewritten)."},"objective":{"type":"object","properties":{"metric":{"type":"string","enum":["claim_resolution","oracle_delta","correction_rate","acceptance_rate","engagement_rate","task_success"],"description":"The objective metric (closed vocabulary)."},"unit":{"type":"string","minLength":1,"maxLength":64,"description":"The unit the metric is measured in (e.g. `boolean`, `ratio`, `usd`)."},"direction":{"type":"string","minLength":1,"maxLength":64,"description":"Which direction is good (e.g. `true_is_good`, `higher_is_better`)."},"resolution_criteria":{"type":"string","minLength":1,"maxLength":2000,"description":"How the objective resolves — REDACTED free text, never a body."},"predicate_id":{"type":"string","enum":["equals","within_tolerance","ge","le","resolved_by_source"],"description":"An optional machine predicate over the resolution (closed set)."},"source":{"type":"string","minLength":1,"maxLength":256,"description":"Where the resolving signal comes from (e.g. `analyst`, `filing`, an oracle name)."},"window":{"type":"string","pattern":"^P(?!$)(\\d+Y)?(\\d+M)?(\\d+W)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+(?:\\.\\d+)?S)?)?$","description":"The resolution window as an ISO-8601 DURATION (e.g. `P12M`), never an instant."},"alternatives":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":64,"description":"Named alternatives for computable comparisons (`alternative_id`)."}},"required":["metric","unit","direction","resolution_criteria","source","window"],"additionalProperties":false,"description":"What “it worked” means for this artifact type — the ONE thing never inferred."},"created_at":{"type":"string"}},"required":["object","id","name","archetype","version","objective","created_at"],"description":"An artifact-type objective version (append-only)."}},"required":["artifact_type"],"description":"The current artifact-type objective version, wrapped in the `artifact_type` envelope."},"ClaimInput":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":256,"description":"The customer claim key (one active claim per key per artifact; a declared claim supersedes a platform-extracted claim on the same key)."},"claim_type":{"type":"string","minLength":1,"maxLength":256,"description":"The namespaced claim type (e.g. earnings_direction)."},"statement":{"type":"string","maxLength":4000,"description":"A REDACTED claim statement (never a raw body — redact upstream)."},"stated_confidence":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true,"description":"The customer stated confidence ∈ (0,1)."},"resolves_by":{"type":"string","description":"ISO-8601 resolution deadline (passing ⇒ overdue)."}},"required":["key","claim_type"],"additionalProperties":false,"description":"A customer-declared claim."},"CreateArtifactRequest":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":512,"description":"The canonical artifact alias (unique per workspace)."},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"Defaults to `answer` when omitted."},"artifact_type":{"type":"string","maxLength":256,"description":"A registered artifact-type name — its current objective version is pinned."},"occurred_at":{"type":"string","description":"When the artifact was created in the customer world (ISO-8601; defaults to now)."},"request_ids":{"type":"array","items":{"type":"string"},"maxItems":1000,"description":"The requests this artifact is assembled from (declared, post-hoc; assembly_source=api)."},"claims":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string","minLength":1,"maxLength":256,"description":"The customer claim key (one active claim per key per artifact; a declared claim supersedes a platform-extracted claim on the same key)."},"claim_type":{"type":"string","minLength":1,"maxLength":256,"description":"The namespaced claim type (e.g. earnings_direction)."},"statement":{"type":"string","maxLength":4000,"description":"A REDACTED claim statement (never a raw body — redact upstream)."},"stated_confidence":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true,"description":"The customer stated confidence ∈ (0,1)."},"resolves_by":{"type":"string","description":"ISO-8601 resolution deadline (passing ⇒ overdue)."}},"required":["key","claim_type"],"additionalProperties":false,"description":"A customer-declared claim."},"maxItems":256,"description":"Declared claims."},"situation_facets":{"type":"object","additionalProperties":{"nullable":true},"description":"Declared situation facets (customer-declared; hashed into the situation key)."},"grant_id":{"type":"string","minLength":1,"maxLength":128,"description":"An exposure GRANT from `POST /v1/flywheel/grants`. When present + VALID, the artifact is stamped with the GRANT’s arm (a non-proxied call becomes armed — for granted artifacts only). Absent ⇒ `unarmed_observation`. An unknown grant is a 400 (fail closed)."},"attestation":{"type":"string","enum":["served","applied"],"description":"CUSTOMER attestation (`served` = the grant was issued; `applied` = the recommended module/model was actually used). Defaults to `served`. Shown beside lift, NEVER provenance."}},"required":["key"],"additionalProperties":false,"description":"Create or upsert an artifact by key."},"ArtifactClaim":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"ArtifactSummary":{"type":"object","properties":{"object":{"type":"string","enum":["artifact"]},"id":{"type":"string"},"key":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"artifact_type_version_id":{"type":"string","nullable":true},"call_type_id":{"type":"string","nullable":true},"situation_key":{"type":"string","nullable":true},"occurred_at":{"type":"string"},"exposure_arm":{"type":"string","nullable":true},"exposure_epoch":{"type":"integer","nullable":true},"grant_id":{"type":"string","nullable":true,"description":"The exposure grant this artifact carries (null when unarmed/observation-only)."},"grant_attestation":{"type":"string","nullable":true,"description":"The customer attestation `served` | `applied` (null when no grant)."},"lifecycle":{"type":"string"},"current_version":{"type":"integer","description":"The artifact’s current (max) version."},"request_ids":{"type":"array","items":{"type":"string"},"description":"The ACTIVE request memberships (assembly lineage)."},"claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"The artifact’s ACTIVE claims (one per claim_key) + their current claim state. `claim_key` on an outcome resolves to these."},"superseded_claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"History: platform-extracted claims a later declared claim superseded for the same claim_key — kept (state `superseded`) and linked through `superseded_by_claim_id`, never deleted; their outcome events stay on them. Usually empty."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","key","archetype","artifact_type_version_id","call_type_id","situation_key","occurred_at","exposure_arm","exposure_epoch","grant_id","grant_attestation","lifecycle","current_version","request_ids","claims","superseded_claims","created_at","updated_at"],"description":"An artifact (metadata only — bodies are stored separately, never here)."},"ArtifactEnvelope":{"type":"object","properties":{"artifact":{"type":"object","properties":{"object":{"type":"string","enum":["artifact"]},"id":{"type":"string"},"key":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"artifact_type_version_id":{"type":"string","nullable":true},"call_type_id":{"type":"string","nullable":true},"situation_key":{"type":"string","nullable":true},"occurred_at":{"type":"string"},"exposure_arm":{"type":"string","nullable":true},"exposure_epoch":{"type":"integer","nullable":true},"grant_id":{"type":"string","nullable":true,"description":"The exposure grant this artifact carries (null when unarmed/observation-only)."},"grant_attestation":{"type":"string","nullable":true,"description":"The customer attestation `served` | `applied` (null when no grant)."},"lifecycle":{"type":"string"},"current_version":{"type":"integer","description":"The artifact’s current (max) version."},"request_ids":{"type":"array","items":{"type":"string"},"description":"The ACTIVE request memberships (assembly lineage)."},"claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"The artifact’s ACTIVE claims (one per claim_key) + their current claim state. `claim_key` on an outcome resolves to these."},"superseded_claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"History: platform-extracted claims a later declared claim superseded for the same claim_key — kept (state `superseded`) and linked through `superseded_by_claim_id`, never deleted; their outcome events stay on them. Usually empty."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","key","archetype","artifact_type_version_id","call_type_id","situation_key","occurred_at","exposure_arm","exposure_epoch","grant_id","grant_attestation","lifecycle","current_version","request_ids","claims","superseded_claims","created_at","updated_at"],"description":"An artifact (metadata only — bodies are stored separately, never here)."}},"required":["artifact"],"description":"A single artifact, wrapped in the `artifact` envelope."},"ArtifactListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["artifact"]},"id":{"type":"string"},"key":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"artifact_type_version_id":{"type":"string","nullable":true},"call_type_id":{"type":"string","nullable":true},"situation_key":{"type":"string","nullable":true},"occurred_at":{"type":"string"},"exposure_arm":{"type":"string","nullable":true},"exposure_epoch":{"type":"integer","nullable":true},"grant_id":{"type":"string","nullable":true,"description":"The exposure grant this artifact carries (null when unarmed/observation-only)."},"grant_attestation":{"type":"string","nullable":true,"description":"The customer attestation `served` | `applied` (null when no grant)."},"lifecycle":{"type":"string"},"current_version":{"type":"integer","description":"The artifact’s current (max) version."},"request_ids":{"type":"array","items":{"type":"string"},"description":"The ACTIVE request memberships (assembly lineage)."},"claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"The artifact’s ACTIVE claims (one per claim_key) + their current claim state. `claim_key` on an outcome resolves to these."},"superseded_claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"History: platform-extracted claims a later declared claim superseded for the same claim_key — kept (state `superseded`) and linked through `superseded_by_claim_id`, never deleted; their outcome events stay on them. Usually empty."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","key","archetype","artifact_type_version_id","call_type_id","situation_key","occurred_at","exposure_arm","exposure_epoch","grant_id","grant_attestation","lifecycle","current_version","request_ids","claims","superseded_claims","created_at","updated_at"],"description":"An artifact (metadata only — bodies are stored separately, never here)."}},"next_cursor":{"type":"string","nullable":true,"description":"Opaque keyset cursor for the next page (null = end)."}},"required":["object","data","next_cursor"],"description":"A keyset-paginated page of artifacts (cursor-based; never offset)."},"OutcomeInput":{"type":"object","properties":{"claim_id":{"type":"string","description":"Target a specific claim by id (else the artifact)."},"claim_key":{"type":"string","description":"Target a claim by its customer key — the key’s ACTIVE claim (else the artifact)."},"channel":{"type":"string","enum":["mechanical","correction","behavioral","resolution","computable","proxy"],"description":"The outcome channel (closed vocabulary)."},"kind":{"type":"string","minLength":1,"maxLength":64,"description":"The channel `kind` (a closed vocabulary per channel)."},"value":{"type":"object","additionalProperties":{"nullable":true},"description":"The typed numeric/diff-stats payload — never a body."},"observed_at":{"type":"string","description":"The effective time (ISO-8601; must be ≥ the artifact occurred_at). Defaults to now."},"source_event_id":{"type":"string","maxLength":256,"description":"The caller idempotency discriminator (ULID at enqueue). Defaults to a server ULID."},"supersedes_event_id":{"type":"string","description":"The event this one supersedes."},"alternative_id":{"type":"string","description":"A computable-comparison alternative id."},"confidence":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true,"description":"An optional confidence ∈ (0,1)."},"evidence_hash":{"type":"string","description":"A content hash of supporting evidence (never a body)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The pinned artifact version (defaults to the artifact’s current version)."},"tool_error_class":{"type":"string","enum":["model","infra","unclassified"],"description":"For mechanical:tool_error — refines learning_use (only model-class teaches)."}},"required":["channel","kind"],"additionalProperties":false,"description":"A single outcome event to record (the server assigns provenance + learning_use)."},"RecordOutcomesRequest":{"type":"object","properties":{"outcomes":{"type":"array","items":{"type":"object","properties":{"claim_id":{"type":"string","description":"Target a specific claim by id (else the artifact)."},"claim_key":{"type":"string","description":"Target a claim by its customer key — the key’s ACTIVE claim (else the artifact)."},"channel":{"type":"string","enum":["mechanical","correction","behavioral","resolution","computable","proxy"],"description":"The outcome channel (closed vocabulary)."},"kind":{"type":"string","minLength":1,"maxLength":64,"description":"The channel `kind` (a closed vocabulary per channel)."},"value":{"type":"object","additionalProperties":{"nullable":true},"description":"The typed numeric/diff-stats payload — never a body."},"observed_at":{"type":"string","description":"The effective time (ISO-8601; must be ≥ the artifact occurred_at). Defaults to now."},"source_event_id":{"type":"string","maxLength":256,"description":"The caller idempotency discriminator (ULID at enqueue). Defaults to a server ULID."},"supersedes_event_id":{"type":"string","description":"The event this one supersedes."},"alternative_id":{"type":"string","description":"A computable-comparison alternative id."},"confidence":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true,"description":"An optional confidence ∈ (0,1)."},"evidence_hash":{"type":"string","description":"A content hash of supporting evidence (never a body)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The pinned artifact version (defaults to the artifact’s current version)."},"tool_error_class":{"type":"string","enum":["model","infra","unclassified"],"description":"For mechanical:tool_error — refines learning_use (only model-class teaches)."}},"required":["channel","kind"],"additionalProperties":false,"description":"A single outcome event to record (the server assigns provenance + learning_use)."},"minItems":1,"maxItems":1000,"description":"1..N outcome events."}},"required":["outcomes"],"additionalProperties":false,"description":"Record 1..N outcome events on an artifact or its claims."},"OutcomeResult":{"type":"object","properties":{"status":{"type":"string","enum":["accepted","duplicate","conflict","rejected"],"description":"Per-event acceptance: accepted | duplicate (no-op) | conflict (409) | rejected."},"id":{"type":"string","nullable":true,"description":"The outcome-event id when accepted/duplicate; else null."},"source_event_id":{"type":"string","nullable":true},"canonical_target_id":{"type":"string","nullable":true},"target_kind":{"type":"string","nullable":true,"enum":["artifact","claim"]},"artifact_version":{"type":"integer","nullable":true},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"source":{"type":"string","nullable":true,"enum":["declared","inferred","gateway","imported"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string","enum":["train","calibrate","rank","audit"]}},"reason":{"type":"string","nullable":true,"description":"The rejection/conflict reason when not accepted."}},"required":["status","id","source_event_id","canonical_target_id","target_kind","artifact_version","latency_class","source","learning_use","reason"],"description":"One outcome event’s server-assigned result."},"RecordOutcomesResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","enum":["accepted","duplicate","conflict","rejected"],"description":"Per-event acceptance: accepted | duplicate (no-op) | conflict (409) | rejected."},"id":{"type":"string","nullable":true,"description":"The outcome-event id when accepted/duplicate; else null."},"source_event_id":{"type":"string","nullable":true},"canonical_target_id":{"type":"string","nullable":true},"target_kind":{"type":"string","nullable":true,"enum":["artifact","claim"]},"artifact_version":{"type":"integer","nullable":true},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"source":{"type":"string","nullable":true,"enum":["declared","inferred","gateway","imported"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string","enum":["train","calibrate","rank","audit"]}},"reason":{"type":"string","nullable":true,"description":"The rejection/conflict reason when not accepted."}},"required":["status","id","source_event_id","canonical_target_id","target_kind","artifact_version","latency_class","source","learning_use","reason"],"description":"One outcome event’s server-assigned result."}}},"required":["object","data"],"description":"The per-event results (202 only after the durable insert)."},"FinalRequest":{"type":"object","properties":{"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The draft version this final approves (defaults to the current version)."},"final":{"type":"string","description":"The final body — stored ONLY under corrections_consent."},"draft":{"type":"string","description":"The draft body — used ONLY to compute server-side diff_stats under consent."},"final_hash":{"type":"string","description":"The final content hash (required on the no-consent metadata-only path)."},"diff_stats":{"type":"object","properties":{"edit_ratio":{"type":"number"},"changed_spans":{"type":"integer"},"lengths":{"type":"object","properties":{"draft":{"type":"integer"},"final":{"type":"integer"}},"required":["draft","final"]},"final_hash":{"type":"string"}},"description":"CLIENT-computed diff stats (the no-consent path; the SDK `diffStats` helper)."}},"description":"Record the human-approved final output version (the correction channel)."},"FinalResponse":{"type":"object","properties":{"object":{"type":"string","enum":["artifact_version"]},"id":{"type":"string"},"artifact_id":{"type":"string"},"version":{"type":"integer"},"final_hash":{"type":"string","nullable":true},"diff_stats":{"type":"object","additionalProperties":{"nullable":true}},"client_computed":{"type":"boolean"},"stored":{"type":"string","enum":["blob","metadata_only"],"description":"`blob` (body stored under consent) | `metadata_only` (no consent)."},"created_at":{"type":"string"}},"required":["object","id","artifact_id","version","final_hash","diff_stats","client_computed","stored","created_at"],"description":"The appended final artifact version."},"BatchOutcomeInput":{"type":"object","properties":{"claim_id":{"type":"string","description":"Target a specific claim by id (else the artifact)."},"claim_key":{"type":"string","description":"Target a claim by its customer key — the key’s ACTIVE claim (else the artifact)."},"channel":{"type":"string","enum":["mechanical","correction","behavioral","resolution","computable","proxy"],"description":"The outcome channel (closed vocabulary)."},"kind":{"type":"string","minLength":1,"maxLength":64,"description":"The channel `kind` (a closed vocabulary per channel)."},"value":{"type":"object","additionalProperties":{"nullable":true},"description":"The typed numeric/diff-stats payload — never a body."},"observed_at":{"type":"string","description":"The effective time (ISO-8601; must be ≥ the artifact occurred_at). Defaults to now."},"source_event_id":{"type":"string","maxLength":256,"description":"The caller idempotency discriminator (ULID at enqueue). Defaults to a server ULID."},"supersedes_event_id":{"type":"string","description":"The event this one supersedes."},"alternative_id":{"type":"string","description":"A computable-comparison alternative id."},"confidence":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true,"description":"An optional confidence ∈ (0,1)."},"evidence_hash":{"type":"string","description":"A content hash of supporting evidence (never a body)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The pinned artifact version (defaults to the artifact’s current version)."},"tool_error_class":{"type":"string","enum":["model","infra","unclassified"],"description":"For mechanical:tool_error — refines learning_use (only model-class teaches)."},"request_id":{"type":"string","description":"Target via the request shortcut (one-request artifact)."},"artifact_id":{"type":"string","description":"Target an artifact by id."},"artifact_key":{"type":"string","description":"Target an artifact by its canonical key."}},"required":["channel","kind"],"additionalProperties":false,"description":"A batch outcome keyed by request_id | artifact_id | artifact_key."},"BatchOutcomesRequest":{"type":"object","properties":{"outcomes":{"type":"array","items":{"type":"object","properties":{"claim_id":{"type":"string","description":"Target a specific claim by id (else the artifact)."},"claim_key":{"type":"string","description":"Target a claim by its customer key — the key’s ACTIVE claim (else the artifact)."},"channel":{"type":"string","enum":["mechanical","correction","behavioral","resolution","computable","proxy"],"description":"The outcome channel (closed vocabulary)."},"kind":{"type":"string","minLength":1,"maxLength":64,"description":"The channel `kind` (a closed vocabulary per channel)."},"value":{"type":"object","additionalProperties":{"nullable":true},"description":"The typed numeric/diff-stats payload — never a body."},"observed_at":{"type":"string","description":"The effective time (ISO-8601; must be ≥ the artifact occurred_at). Defaults to now."},"source_event_id":{"type":"string","maxLength":256,"description":"The caller idempotency discriminator (ULID at enqueue). Defaults to a server ULID."},"supersedes_event_id":{"type":"string","description":"The event this one supersedes."},"alternative_id":{"type":"string","description":"A computable-comparison alternative id."},"confidence":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"exclusiveMaximum":true,"description":"An optional confidence ∈ (0,1)."},"evidence_hash":{"type":"string","description":"A content hash of supporting evidence (never a body)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The pinned artifact version (defaults to the artifact’s current version)."},"tool_error_class":{"type":"string","enum":["model","infra","unclassified"],"description":"For mechanical:tool_error — refines learning_use (only model-class teaches)."},"request_id":{"type":"string","description":"Target via the request shortcut (one-request artifact)."},"artifact_id":{"type":"string","description":"Target an artifact by id."},"artifact_key":{"type":"string","description":"Target an artifact by its canonical key."}},"required":["channel","kind"],"additionalProperties":false,"description":"A batch outcome keyed by request_id | artifact_id | artifact_key."},"minItems":1,"maxItems":1000}},"required":["outcomes"],"additionalProperties":false,"description":"Record ≤ 1,000 outcome events keyed by target."},"BatchOutcomeResult":{"type":"object","properties":{"status":{"type":"string","enum":["accepted","duplicate","conflict","rejected","pending"],"description":"Per-row acceptance: accepted | duplicate (no-op) | conflict | rejected | pending — a `request_id` row whose request has not been recorded yet: stored durably and applied when it is (see `receipt`)."},"id":{"type":"string","nullable":true,"description":"The outcome-event id when accepted/duplicate; else null."},"source_event_id":{"type":"string","nullable":true},"canonical_target_id":{"type":"string","nullable":true},"target_kind":{"type":"string","nullable":true,"enum":["artifact","claim"]},"artifact_version":{"type":"integer","nullable":true},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"source":{"type":"string","nullable":true,"enum":["declared","inferred","gateway","imported"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string","enum":["train","calibrate","rank","audit"]}},"reason":{"type":"string","nullable":true,"description":"The rejection/conflict reason when not accepted."},"key":{"type":"string","nullable":true,"description":"The input target key echoed (request_id/artifact_id/artifact_key)."},"receipt":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["outcome_receipt"]},"id":{"type":"string","description":"The receipt id (`ocr_…`)."},"request_id":{"type":"string","description":"The request the outcome names."},"status":{"type":"string","enum":["pending","applied","rejected","failed","expired"],"description":"`pending` — the request has not been recorded yet; `applied` — the outcome is recorded; `rejected` — it failed validation once the request was known (see `reason`); `failed` — recording kept hitting an internal error; `expired` — no request with this id appeared in your workspace within 15 minutes (`reason: request_not_found`)."},"reason":{"type":"string","nullable":true,"description":"A stable machine reason when not applied: `request_not_found`, `idempotency_conflict`, `apply_failed`, or the validation reason."},"channel":{"type":"string","description":"The outcome channel as sent."},"kind":{"type":"string","description":"The outcome kind as sent."},"source_event_id":{"type":"string","description":"Your idempotency discriminator, or a server-minted one when none was sent (then a retry is a new outcome)."},"outcome_event_id":{"type":"string","nullable":true,"description":"The recorded outcome event (`oev_…`) once applied."},"outcome_status":{"type":"string","nullable":true,"enum":["accepted","duplicate"],"description":"Whether applying recorded the event for the first time (`accepted`) or found it (`duplicate`)."},"artifact_id":{"type":"string","nullable":true,"description":"The artifact the outcome landed on, once applied."},"episode":{"type":"object","properties":{"status":{"type":"string","enum":["associated","pending","not_recorded","not_applicable"],"description":"`associated` — the episode holding this request carries a verdict; `pending` — a teaching outcome waiting for its episode to be recorded; `not_recorded` — the persisted request was held out and recording was intentionally suppressed, or no episode held the request within 15 minutes (episode memory or recording off, no consent); `not_applicable` — the outcome does not teach (a proxy, behavioral or mechanical signal) or was not applied."},"trace_id":{"type":"string","nullable":true,"description":"The episode (`ept_…`) the outcome was associated with, once associated."},"verdict":{"type":"string","nullable":true,"enum":["recorded","kept_earlier","revised","revised_after_incorporation"],"description":"What the outcome did to the episode: `recorded` — it is the episode verdict; `kept_earlier` — the episode already had a verdict (the first verdict wins); `revised` — it superseded the verdict (`supersedes_event_id`) before any learned version used the episode, so the verdict was replaced; `revised_after_incorporation` — the superseded verdict was already used by a learned version: the revision is recorded and counted, the episode is not silently unlearned."}},"required":["status","trace_id","verdict"],"description":"The episode association of an applied teaching outcome."},"attempts":{"type":"integer","description":"Recording attempts that hit an internal error (bounded; then `failed`)."},"created_at":{"type":"string","description":"When the outcome was accepted."},"updated_at":{"type":"string"},"applied_at":{"type":"string","nullable":true,"description":"When the outcome was recorded."},"expires_at":{"type":"string","description":"The receipt’s next deadline: while `pending`, when it expires; while its episode association is `pending`, when that becomes `not_recorded`; once settled, when the receipt itself is deleted (30 days)."}},"required":["object","id","request_id","status","reason","channel","kind","source_event_id","outcome_event_id","outcome_status","artifact_id","episode","attempts","created_at","updated_at","applied_at","expires_at"],"description":"The durable receipt of a `request_id` row (the same receipt the request-outcome route returns for the same `source_event_id`); null for an `artifact_id` / `artifact_key` row or a row refused before one."}},"required":["status","id","source_event_id","canonical_target_id","target_kind","artifact_version","latency_class","source","learning_use","reason","key","receipt"],"description":"One batch outcome’s result."},"BatchOutcomesResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"status":{"type":"string","enum":["accepted","duplicate","conflict","rejected","pending"],"description":"Per-row acceptance: accepted | duplicate (no-op) | conflict | rejected | pending — a `request_id` row whose request has not been recorded yet: stored durably and applied when it is (see `receipt`)."},"id":{"type":"string","nullable":true,"description":"The outcome-event id when accepted/duplicate; else null."},"source_event_id":{"type":"string","nullable":true},"canonical_target_id":{"type":"string","nullable":true},"target_kind":{"type":"string","nullable":true,"enum":["artifact","claim"]},"artifact_version":{"type":"integer","nullable":true},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"source":{"type":"string","nullable":true,"enum":["declared","inferred","gateway","imported"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string","enum":["train","calibrate","rank","audit"]}},"reason":{"type":"string","nullable":true,"description":"The rejection/conflict reason when not accepted."},"key":{"type":"string","nullable":true,"description":"The input target key echoed (request_id/artifact_id/artifact_key)."},"receipt":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["outcome_receipt"]},"id":{"type":"string","description":"The receipt id (`ocr_…`)."},"request_id":{"type":"string","description":"The request the outcome names."},"status":{"type":"string","enum":["pending","applied","rejected","failed","expired"],"description":"`pending` — the request has not been recorded yet; `applied` — the outcome is recorded; `rejected` — it failed validation once the request was known (see `reason`); `failed` — recording kept hitting an internal error; `expired` — no request with this id appeared in your workspace within 15 minutes (`reason: request_not_found`)."},"reason":{"type":"string","nullable":true,"description":"A stable machine reason when not applied: `request_not_found`, `idempotency_conflict`, `apply_failed`, or the validation reason."},"channel":{"type":"string","description":"The outcome channel as sent."},"kind":{"type":"string","description":"The outcome kind as sent."},"source_event_id":{"type":"string","description":"Your idempotency discriminator, or a server-minted one when none was sent (then a retry is a new outcome)."},"outcome_event_id":{"type":"string","nullable":true,"description":"The recorded outcome event (`oev_…`) once applied."},"outcome_status":{"type":"string","nullable":true,"enum":["accepted","duplicate"],"description":"Whether applying recorded the event for the first time (`accepted`) or found it (`duplicate`)."},"artifact_id":{"type":"string","nullable":true,"description":"The artifact the outcome landed on, once applied."},"episode":{"type":"object","properties":{"status":{"type":"string","enum":["associated","pending","not_recorded","not_applicable"],"description":"`associated` — the episode holding this request carries a verdict; `pending` — a teaching outcome waiting for its episode to be recorded; `not_recorded` — the persisted request was held out and recording was intentionally suppressed, or no episode held the request within 15 minutes (episode memory or recording off, no consent); `not_applicable` — the outcome does not teach (a proxy, behavioral or mechanical signal) or was not applied."},"trace_id":{"type":"string","nullable":true,"description":"The episode (`ept_…`) the outcome was associated with, once associated."},"verdict":{"type":"string","nullable":true,"enum":["recorded","kept_earlier","revised","revised_after_incorporation"],"description":"What the outcome did to the episode: `recorded` — it is the episode verdict; `kept_earlier` — the episode already had a verdict (the first verdict wins); `revised` — it superseded the verdict (`supersedes_event_id`) before any learned version used the episode, so the verdict was replaced; `revised_after_incorporation` — the superseded verdict was already used by a learned version: the revision is recorded and counted, the episode is not silently unlearned."}},"required":["status","trace_id","verdict"],"description":"The episode association of an applied teaching outcome."},"attempts":{"type":"integer","description":"Recording attempts that hit an internal error (bounded; then `failed`)."},"created_at":{"type":"string","description":"When the outcome was accepted."},"updated_at":{"type":"string"},"applied_at":{"type":"string","nullable":true,"description":"When the outcome was recorded."},"expires_at":{"type":"string","description":"The receipt’s next deadline: while `pending`, when it expires; while its episode association is `pending`, when that becomes `not_recorded`; once settled, when the receipt itself is deleted (30 days)."}},"required":["object","id","request_id","status","reason","channel","kind","source_event_id","outcome_event_id","outcome_status","artifact_id","episode","attempts","created_at","updated_at","applied_at","expires_at"],"description":"The durable receipt of a `request_id` row (the same receipt the request-outcome route returns for the same `source_event_id`); null for an `artifact_id` / `artifact_key` row or a row refused before one."}},"required":["status","id","source_event_id","canonical_target_id","target_kind","artifact_version","latency_class","source","learning_use","reason","key","receipt"],"description":"One batch outcome’s result."}},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"conflict":{"type":"integer"},"rejected":{"type":"integer"},"pending":{"type":"integer","description":"Rows whose request has not been recorded yet (durable pending receipts)."}},"required":["object","data","accepted","duplicate","conflict","rejected","pending"],"description":"The per-row batch results + a verdict rollup."},"PendingClaim":{"type":"object","properties":{"id":{"type":"string"},"artifact_id":{"type":"string"},"artifact_key":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"occurred_at":{"type":"string"},"created_at":{"type":"string"}},"required":["id","artifact_id","artifact_key","archetype","claim_key","claim_type","state","stated_confidence","resolves_by","occurred_at","created_at"],"description":"A claim awaiting resolution."},"PendingClaimsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"artifact_id":{"type":"string"},"artifact_key":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"occurred_at":{"type":"string"},"created_at":{"type":"string"}},"required":["id","artifact_id","artifact_key","archetype","claim_key","claim_type","state","stated_confidence","resolves_by","occurred_at","created_at"],"description":"A claim awaiting resolution."}},"next_cursor":{"type":"string","nullable":true}},"required":["object","data","next_cursor"],"description":"A keyset-paginated page of claims awaiting resolution (cursor-based; never offset)."},"PatchFlywheelConsentsRequest":{"type":"object","properties":{"corrections_consent":{"type":"boolean","description":"Store human-approved finals (default off — no silent retention upgrade)."},"training_export_consent":{"type":"boolean","description":"Allow the training-READY export to be produced (default off; produced FOR the customer)."},"corrections_retention_days":{"type":"integer","minimum":1,"maximum":3650,"description":"Finals/bodies retention window in days (default 90)."}},"additionalProperties":false,"description":"Update the workspace Flywheel consents (owner-only, audited, bumps config_version)."},"FlywheelConsentsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_consents"]},"corrections_consent":{"type":"boolean"},"training_export_consent":{"type":"boolean"},"corrections_retention_days":{"type":"integer"},"config_version":{"type":"integer"}},"required":["object","corrections_consent","training_export_consent","corrections_retention_days","config_version"],"description":"The workspace Flywheel consents."},"PutSiteBriefRequest":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri","description":"The public website/docs URL to fetch. Omit to infer it from the signup email domain."}},"additionalProperties":false,"description":"Request a site-brief fetch — explicit URL or inferred from the signup domain."},"SiteBriefResponse":{"type":"object","properties":{"object":{"type":"string","enum":["site_brief"]},"status":{"type":"string","enum":["pending","fetched","failed"]},"source":{"type":"string","enum":["given","inferred_from_domain"]},"source_url":{"type":"string"},"hash":{"type":"string","description":"The content hash of the stored REDACTED text (\"\" until fetched)."},"retrieved_at":{"type":"string","nullable":true,"description":"When the fetch completed (null until fetched)."},"text_length":{"type":"integer","minimum":0},"redaction_counts":{"type":"object","additionalProperties":{"type":"integer"},"description":"Per-category redaction COUNTS ({secret, email, …}) — never the raw values."},"failure_class":{"type":"string","nullable":true,"description":"The fetch failure reason CLASS on status=failed (never the body/message)."},"analysis":{"type":"object","properties":{"budget":{"type":"object","properties":{"micro_usd":{"type":"integer","minimum":0,"description":"The STATED one-time signup-analysis budget (micro-USD) — separate from the run-time spend cap and the $5/month analyzer discovery cap."},"used_micro_usd":{"type":"integer","minimum":0,"description":"Reserved+spent on the signup-analysis rail so far (micro-USD)."},"max_calls":{"type":"integer","minimum":0,"description":"Max model calls the one-time analysis may make — the injection SCREEN runs plus the categorise runs, per page (the count governor; it covers screening as well)."},"calls_made":{"type":"integer","minimum":0,"description":"Model calls made so far — screen + categorise (failed attempts count)."},"exhausted":{"type":"boolean","description":"True once the one-time signup-analysis budget (money OR calls) is exhausted."}},"required":["micro_usd","used_micro_usd","max_calls","calls_made","exhausted"],"description":"The one-time signup-analysis budget."},"pages":{"type":"array","items":{"type":"object","properties":{"url_host":{"type":"string","description":"The page URL host (never the path)."},"status":{"type":"string","enum":["fetched","analysed","skipped_cap","fetch_refused","budget_exhausted","insufficient_runs","flagged_injection","screen_failed"],"description":"The per-page lifecycle status."},"hash":{"type":"string","description":"The content hash of the REDACTED page text (\"\" when not fetched)."},"byte_count":{"type":"integer","minimum":0},"failure_class":{"type":"string","nullable":true},"screen_verdict":{"type":"string","enum":["unscreened","clean","suspected_injection"],"description":"The injection-screen verdict for this page."},"screen_reasons":{"type":"array","items":{"type":"string"},"description":"The CLOSED reason codes behind a flagged / screen-failed page (ids only, never a body)."}},"required":["url_host","status","hash","byte_count","failure_class","screen_verdict","screen_reasons"]},"description":"Per-page status of the MULTI-PAGE signup analysis (never the page text)."},"flagged_injection_pages":{"type":"integer","minimum":0,"description":"How many pages the injection screen FLAGGED and excluded from categorisation."},"workflows_inferred":{"type":"integer","minimum":0,"description":"How many inferred workflow proposals the merge produced (0 until analysed)."}},"required":["budget","pages","flagged_injection_pages","workflows_inferred"],"description":"The multi-page signup analysis: the one-time budget + per-page status + the injection-screen verdict per page (a flagged page is excluded and named; never the page text)."}},"required":["object","status","source","source_url","hash","retrieved_at","text_length","redaction_counts","failure_class","analysis"],"description":"The workspace site-brief status — never the page text."},"FlywheelUsageBlock":{"type":"object","properties":{"period":{"type":"string","description":"The current UTC month bucket (YYYY-MM-DD)."},"tracked_artifacts":{"type":"integer","minimum":0,"description":"OPERATIONAL — new artifacts captured this period (not an invoice line)."},"accepted_outcomes":{"type":"integer","minimum":0,"description":"OPERATIONAL — accepted outcome events this period (not an invoice line)."},"analysis_units":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0,"description":"Open analysis-unit holds this period."},"settled":{"type":"integer","minimum":0,"description":"Billed analysis units this period."},"monthly_cap":{"type":"integer","nullable":true,"description":"Monthly analysis-unit cap; null = lifetime governs."},"lifetime_used":{"type":"integer","minimum":0,"description":"Committed analysis units across the account lifetime."},"lifetime_cap":{"type":"integer","nullable":true,"description":"Lifetime analysis-unit cap; null = unlimited."}},"required":["reserved","settled","monthly_cap","lifetime_used","lifetime_cap"],"description":"PAID — bounded analysis units (billed by unique artifact version × recipe)."},"evaluation_compute_usd":{"type":"object","properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer","minimum":0},"cap_micro_usd":{"type":"integer","minimum":0,"description":"The approved monthly evaluation-compute cap."}},"required":["reserved_micro_usd","settled_micro_usd","cap_micro_usd"],"description":"PAID — approved evaluation compute (the platform-spend evaluation counters; one money source)."},"actual_cogs":{"type":"object","properties":{"analysis_micro_usd":{"type":"integer","minimum":0},"failed_attempt_micro_usd":{"type":"integer","minimum":0}},"required":["analysis_micro_usd","failed_attempt_micro_usd"],"description":"OUR actual COGS for margin (settled analysis + failed attempts); never billed to the customer."},"storage":{"type":"object","properties":{"retained_payload_bytes":{"type":"integer","minimum":0},"retained_payload_bytes_cap":{"type":"integer","nullable":true},"ledger_index_bytes":{"type":"integer","minimum":0},"ledger_index_bytes_cap":{"type":"integer","nullable":true},"paused":{"type":"boolean","description":"True when the storage quota is exhausted (new storage paused; export/deletion preserved)."}},"required":["retained_payload_bytes","retained_payload_bytes_cap","ledger_index_bytes","ledger_index_bytes_cap","paused"],"description":"The finite storage quotas + lifetime byte counters."},"metadata_artifacts_monthly_cap":{"type":"integer","nullable":true},"overage_paused":{"type":"boolean","description":"Default overage is paused — no unpriced automatic overage."}},"required":["period","tracked_artifacts","accepted_outcomes","analysis_units","evaluation_compute_usd","actual_cogs","storage","metadata_artifacts_monthly_cap","overage_paused"],"description":"The four SEPARATED Flywheel usage quantities + caps + storage + COGS."},"FlywheelChannelHealth":{"type":"object","properties":{"channel":{"type":"string"},"accepted_outcomes":{"type":"integer","minimum":0},"last_observed_at":{"type":"string","nullable":true}},"required":["channel","accepted_outcomes","last_observed_at"],"description":"One channel detected (integration health)."},"FlywheelStatusResponse":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_status"]},"workspace_id":{"type":"string"},"usage":{"type":"object","properties":{"period":{"type":"string","description":"The current UTC month bucket (YYYY-MM-DD)."},"tracked_artifacts":{"type":"integer","minimum":0,"description":"OPERATIONAL — new artifacts captured this period (not an invoice line)."},"accepted_outcomes":{"type":"integer","minimum":0,"description":"OPERATIONAL — accepted outcome events this period (not an invoice line)."},"analysis_units":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0,"description":"Open analysis-unit holds this period."},"settled":{"type":"integer","minimum":0,"description":"Billed analysis units this period."},"monthly_cap":{"type":"integer","nullable":true,"description":"Monthly analysis-unit cap; null = lifetime governs."},"lifetime_used":{"type":"integer","minimum":0,"description":"Committed analysis units across the account lifetime."},"lifetime_cap":{"type":"integer","nullable":true,"description":"Lifetime analysis-unit cap; null = unlimited."}},"required":["reserved","settled","monthly_cap","lifetime_used","lifetime_cap"],"description":"PAID — bounded analysis units (billed by unique artifact version × recipe)."},"evaluation_compute_usd":{"type":"object","properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer","minimum":0},"cap_micro_usd":{"type":"integer","minimum":0,"description":"The approved monthly evaluation-compute cap."}},"required":["reserved_micro_usd","settled_micro_usd","cap_micro_usd"],"description":"PAID — approved evaluation compute (the platform-spend evaluation counters; one money source)."},"actual_cogs":{"type":"object","properties":{"analysis_micro_usd":{"type":"integer","minimum":0},"failed_attempt_micro_usd":{"type":"integer","minimum":0}},"required":["analysis_micro_usd","failed_attempt_micro_usd"],"description":"OUR actual COGS for margin (settled analysis + failed attempts); never billed to the customer."},"storage":{"type":"object","properties":{"retained_payload_bytes":{"type":"integer","minimum":0},"retained_payload_bytes_cap":{"type":"integer","nullable":true},"ledger_index_bytes":{"type":"integer","minimum":0},"ledger_index_bytes_cap":{"type":"integer","nullable":true},"paused":{"type":"boolean","description":"True when the storage quota is exhausted (new storage paused; export/deletion preserved)."}},"required":["retained_payload_bytes","retained_payload_bytes_cap","ledger_index_bytes","ledger_index_bytes_cap","paused"],"description":"The finite storage quotas + lifetime byte counters."},"metadata_artifacts_monthly_cap":{"type":"integer","nullable":true},"overage_paused":{"type":"boolean","description":"Default overage is paused — no unpriced automatic overage."}},"required":["period","tracked_artifacts","accepted_outcomes","analysis_units","evaluation_compute_usd","actual_cogs","storage","metadata_artifacts_monthly_cap","overage_paused"],"description":"The four SEPARATED Flywheel usage quantities + caps + storage + COGS."},"channels":{"type":"array","items":{"type":"object","properties":{"channel":{"type":"string"},"accepted_outcomes":{"type":"integer","minimum":0},"last_observed_at":{"type":"string","nullable":true}},"required":["channel","accepted_outcomes","last_observed_at"],"description":"One channel detected (integration health)."},"description":"Channels detected (integration health)."},"imports":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"completed":{"type":"integer","minimum":0},"running":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"last_import_at":{"type":"string","nullable":true}},"required":["total","completed","running","failed","last_import_at"],"description":"History-import integration health."},"learning":{"type":"object","properties":{"flywheel_class":{"type":"string","enum":["unavailable"],"description":"Explicitly UNAVAILABLE on this status surface (the class is not computed here)."},"flywheel_class_reason":{"type":"string","enum":["collecting"]},"active_levers":{"type":"array","items":{"type":"string"},"description":"Empty on this status surface — no lift is claimed while collecting."},"calibration_available":{"type":"boolean","enum":[false]}},"required":["flywheel_class","flywheel_class_reason","active_levers","calibration_available"],"description":"Learning fields — explicitly unavailable; a collecting state never implies observed lift."},"experiment":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable"],"description":"The current bounded experiment, or null — benchmarkable is always false."}},"required":["object","workspace_id","usage","channels","imports","learning","experiment"],"description":"Flywheel status: capture counts + integration health + unavailable learning fields."},"MoatNextPrecondition":{"type":"object","properties":{"precondition":{"type":"string","description":"The closed readiness-precondition code."},"reason":{"type":"string","description":"The machine reason code (stable)."},"message":{"type":"string","description":"The customer sentence naming exactly what is missing. For the `below_benchmarkable` lifecycle blocker it reports resolved CLAIMS and resolved TASK OUTCOMES as separate counts (a task-only unit reads \"needs N more resolved task outcomes (n/200). Failure location may still be unknown.\"). A claim-less artifact contributes at most one resolved task outcome."}},"required":["precondition","reason","message"],"description":"An unmet readiness precondition — the code + the customer sentence."},"MoatNextItem":{"type":"object","properties":{"call_type_id":{"type":"string","nullable":true},"lever_family":{"type":"string"},"situation_class":{"type":"string"},"ready":{"type":"boolean"},"scheduled":{"type":"boolean","description":"True when the unit was actually scheduled to run."},"verdict":{"type":"string","enum":["run","below_hurdle","cost_exceeds_budget","not_ready"]},"primary_missing":{"type":"object","nullable":true,"properties":{"precondition":{"type":"string","description":"The closed readiness-precondition code."},"reason":{"type":"string","description":"The machine reason code (stable)."},"message":{"type":"string","description":"The customer sentence naming exactly what is missing. For the `below_benchmarkable` lifecycle blocker it reports resolved CLAIMS and resolved TASK OUTCOMES as separate counts (a task-only unit reads \"needs N more resolved task outcomes (n/200). Failure location may still be unknown.\"). A claim-less artifact contributes at most one resolved task outcome."}},"required":["precondition","reason","message"],"description":"The primary missing precondition (the first blocker), or null when ready."},"missing":{"type":"array","items":{"type":"object","properties":{"precondition":{"type":"string","description":"The closed readiness-precondition code."},"reason":{"type":"string","description":"The machine reason code (stable)."},"message":{"type":"string","description":"The customer sentence naming exactly what is missing. For the `below_benchmarkable` lifecycle blocker it reports resolved CLAIMS and resolved TASK OUTCOMES as separate counts (a task-only unit reads \"needs N more resolved task outcomes (n/200). Failure location may still be unknown.\"). A claim-less artifact contributes at most one resolved task outcome."}},"required":["precondition","reason","message"],"description":"An unmet readiness precondition — the code + the customer sentence."},"description":"Every unmet precondition; empty when ready."},"next_action":{"type":"string","description":"The customer next-action SENTENCE — always present (never a bare boolean)."}},"required":["call_type_id","lever_family","situation_class","ready","scheduled","verdict","primary_missing","missing","next_action"],"description":"What one unit of the moat needs next: ready + verdict, or the named missing precondition."},"MoatNextResponse":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_moat_next"]},"workspace_id":{"type":"string"},"items":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string","nullable":true},"lever_family":{"type":"string"},"situation_class":{"type":"string"},"ready":{"type":"boolean"},"scheduled":{"type":"boolean","description":"True when the unit was actually scheduled to run."},"verdict":{"type":"string","enum":["run","below_hurdle","cost_exceeds_budget","not_ready"]},"primary_missing":{"type":"object","nullable":true,"properties":{"precondition":{"type":"string","description":"The closed readiness-precondition code."},"reason":{"type":"string","description":"The machine reason code (stable)."},"message":{"type":"string","description":"The customer sentence naming exactly what is missing. For the `below_benchmarkable` lifecycle blocker it reports resolved CLAIMS and resolved TASK OUTCOMES as separate counts (a task-only unit reads \"needs N more resolved task outcomes (n/200). Failure location may still be unknown.\"). A claim-less artifact contributes at most one resolved task outcome."}},"required":["precondition","reason","message"],"description":"The primary missing precondition (the first blocker), or null when ready."},"missing":{"type":"array","items":{"type":"object","properties":{"precondition":{"type":"string","description":"The closed readiness-precondition code."},"reason":{"type":"string","description":"The machine reason code (stable)."},"message":{"type":"string","description":"The customer sentence naming exactly what is missing. For the `below_benchmarkable` lifecycle blocker it reports resolved CLAIMS and resolved TASK OUTCOMES as separate counts (a task-only unit reads \"needs N more resolved task outcomes (n/200). Failure location may still be unknown.\"). A claim-less artifact contributes at most one resolved task outcome."}},"required":["precondition","reason","message"],"description":"An unmet readiness precondition — the code + the customer sentence."},"description":"Every unmet precondition; empty when ready."},"next_action":{"type":"string","description":"The customer next-action SENTENCE — always present (never a bare boolean)."}},"required":["call_type_id","lever_family","situation_class","ready","scheduled","verdict","primary_missing","missing","next_action"],"description":"What one unit of the moat needs next: ready + verdict, or the named missing precondition."}},"experiment":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable"],"description":"The current bounded experiment, or null — benchmarkable is always false."}},"required":["object","workspace_id","items","experiment"],"description":"What your moat needs next — per-unit readiness + the missing-precondition sentence."},"ReviewAssistRequest":{"type":"object","properties":{"item_id":{"type":"string","minLength":1,"maxLength":512,"description":"The review item id from the queue listing (`exec:…` | `rec:…` | `req:…`)."},"note":{"type":"string","maxLength":2000,"description":"Optional reviewer feedback — \"what should change\" (drives the revision). ≤ 2,000 chars."},"reject_reason":{"type":"string","enum":["off_topic","inaccurate","tone","incomplete","formatting","policy","other"],"description":"Optional closed reject-reason code that steers the revision."}},"required":["item_id"],"additionalProperties":false,"description":"Ask the customer’s own model to revise a review-queue draft (billed as `ur_review_assist`)."},"ReviewAssistResponse":{"type":"object","properties":{"object":{"type":"string","enum":["review_assist"]},"revision":{"type":"string","description":"The revised draft text (the human accepts / edits / discards it)."},"request_id":{"type":"string","description":"The `req_…` id of the metered `ur_review_assist` call (appears in the workspace log)."},"cost_micro_usd":{"type":"integer","description":"The cost of this call in integer micro-USD — the customer’s own usage spend."}},"required":["object","revision","request_id","cost_micro_usd"],"description":"The \"Fix with AI\" revision + the metered request id + cost."},"ImprovementCollecting":{"type":"object","properties":{"n":{"type":"integer","nullable":true,"minimum":0,"description":"The count toward the floor, or null when the owning engine exposes no per-call-type count."},"floor":{"type":"integer","minimum":0,"description":"The floor value the owning engine sets (never a new floor)."},"floor_name":{"type":"string","description":"The NAME of the engine that owns the floor (e.g. golden_set.min_activate)."}},"required":["n","floor","floor_name"],"description":"Progress toward a NAMED engine floor (the collecting state)."},"ImprovementRead":{"type":"object","properties":{"goal":{"type":"string","enum":["spend_less","get_better"],"description":"Which goal this read is for."},"state":{"type":"string","enum":["evidence","collecting","needs_confirmation","keep_incumbent","unavailable"],"description":"The closed state this half resolved to."},"intent":{"type":"string","enum":["cost_optimization","required_migration","product_improvement"],"description":"The decision intent this half reports — cost_optimization for spend-less; the get-better default is product_improvement, a customer-stated intent is reported and never overridden."},"source_id":{"type":"string","nullable":true,"description":"The source row id for evidence / keep_incumbent / needs_confirmation (a rec / run / plan id), else null."},"tier":{"type":"string","nullable":true,"description":"The evidence tier in the engine’s own vocabulary (evidence state only; else null)."},"estimate":{"type":"boolean","description":"True ONLY when the surfaced figure is an ESTIMATE (a projected saving), never realized."},"deciding":{"type":"array","items":{"type":"string","enum":["quality","cost","guardrail","evidence"]},"description":"The deciding axes for a get-better screen (empty for a spend-less recommendation)."},"collecting":{"type":"object","nullable":true,"properties":{"n":{"type":"integer","nullable":true,"minimum":0,"description":"The count toward the floor, or null when the owning engine exposes no per-call-type count."},"floor":{"type":"integer","minimum":0,"description":"The floor value the owning engine sets (never a new floor)."},"floor_name":{"type":"string","description":"The NAME of the engine that owns the floor (e.g. golden_set.min_activate)."}},"required":["n","floor","floor_name"],"description":"The collecting progress (collecting state only; else null)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason (unavailable state only; else null)."},"next_action":{"type":"string","description":"The customer’s next action — always a sentence, never a bare state."}},"required":["goal","state","intent","source_id","tier","estimate","deciding","collecting","reason","next_action"],"description":"One improvement read (spend-less OR get-better) for one call type."},"CallTypeImprovementReads":{"type":"object","properties":{"call_type_id":{"type":"string"},"slug":{"type":"string","nullable":true},"spend_less":{"type":"object","properties":{"goal":{"type":"string","enum":["spend_less","get_better"],"description":"Which goal this read is for."},"state":{"type":"string","enum":["evidence","collecting","needs_confirmation","keep_incumbent","unavailable"],"description":"The closed state this half resolved to."},"intent":{"type":"string","enum":["cost_optimization","required_migration","product_improvement"],"description":"The decision intent this half reports — cost_optimization for spend-less; the get-better default is product_improvement, a customer-stated intent is reported and never overridden."},"source_id":{"type":"string","nullable":true,"description":"The source row id for evidence / keep_incumbent / needs_confirmation (a rec / run / plan id), else null."},"tier":{"type":"string","nullable":true,"description":"The evidence tier in the engine’s own vocabulary (evidence state only; else null)."},"estimate":{"type":"boolean","description":"True ONLY when the surfaced figure is an ESTIMATE (a projected saving), never realized."},"deciding":{"type":"array","items":{"type":"string","enum":["quality","cost","guardrail","evidence"]},"description":"The deciding axes for a get-better screen (empty for a spend-less recommendation)."},"collecting":{"type":"object","nullable":true,"properties":{"n":{"type":"integer","nullable":true,"minimum":0,"description":"The count toward the floor, or null when the owning engine exposes no per-call-type count."},"floor":{"type":"integer","minimum":0,"description":"The floor value the owning engine sets (never a new floor)."},"floor_name":{"type":"string","description":"The NAME of the engine that owns the floor (e.g. golden_set.min_activate)."}},"required":["n","floor","floor_name"],"description":"The collecting progress (collecting state only; else null)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason (unavailable state only; else null)."},"next_action":{"type":"string","description":"The customer’s next action — always a sentence, never a bare state."}},"required":["goal","state","intent","source_id","tier","estimate","deciding","collecting","reason","next_action"],"description":"The \"a cheaper model is enough here\" read (from the eval recommendations)."},"get_better":{"type":"object","properties":{"goal":{"type":"string","enum":["spend_less","get_better"],"description":"Which goal this read is for."},"state":{"type":"string","enum":["evidence","collecting","needs_confirmation","keep_incumbent","unavailable"],"description":"The closed state this half resolved to."},"intent":{"type":"string","enum":["cost_optimization","required_migration","product_improvement"],"description":"The decision intent this half reports — cost_optimization for spend-less; the get-better default is product_improvement, a customer-stated intent is reported and never overridden."},"source_id":{"type":"string","nullable":true,"description":"The source row id for evidence / keep_incumbent / needs_confirmation (a rec / run / plan id), else null."},"tier":{"type":"string","nullable":true,"description":"The evidence tier in the engine’s own vocabulary (evidence state only; else null)."},"estimate":{"type":"boolean","description":"True ONLY when the surfaced figure is an ESTIMATE (a projected saving), never realized."},"deciding":{"type":"array","items":{"type":"string","enum":["quality","cost","guardrail","evidence"]},"description":"The deciding axes for a get-better screen (empty for a spend-less recommendation)."},"collecting":{"type":"object","nullable":true,"properties":{"n":{"type":"integer","nullable":true,"minimum":0,"description":"The count toward the floor, or null when the owning engine exposes no per-call-type count."},"floor":{"type":"integer","minimum":0,"description":"The floor value the owning engine sets (never a new floor)."},"floor_name":{"type":"string","description":"The NAME of the engine that owns the floor (e.g. golden_set.min_activate)."}},"required":["n","floor","floor_name"],"description":"The collecting progress (collecting state only; else null)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason (unavailable state only; else null)."},"next_action":{"type":"string","description":"The customer’s next action — always a sentence, never a bare state."}},"required":["goal","state","intent","source_id","tier","estimate","deciding","collecting","reason","next_action"],"description":"The \"quality can improve here\" read (Flywheel candidate + plan)."},"holdout_gap":{"type":"object","properties":{"tier":{"type":"string","enum":["measured","inconclusive","unavailable"],"description":"The evidence tier the holdout gap resolved to."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason when the tier is not measured (no_measurement / no_confirmed_lever / under_powered / aa_parked / cost_ratio_inconclusive), else null."},"gap_per_1000":{"type":"number","nullable":true,"description":"The holdout gap per 1,000 tasks (null when no measurement)."},"gap_ci_low":{"type":"number","nullable":true,"description":"The gap two-sided CI lower bound (per 1,000)."},"gap_ci_high":{"type":"number","nullable":true,"description":"The gap two-sided CI upper bound (per 1,000)."},"cost_ratio":{"type":"number","nullable":true,"description":"The live $ per successful task ratio (treated ÷ holdout), null when inconclusive."},"cost_ratio_ci_low":{"type":"number","nullable":true,"description":"The cost-ratio CI lower bound."},"cost_ratio_ci_high":{"type":"number","nullable":true,"description":"The cost-ratio CI upper bound."}},"required":["tier","reason","gap_per_1000","gap_ci_low","gap_ci_high","cost_ratio","cost_ratio_ci_low","cost_ratio_ci_high"],"description":"The north-star holdout gap for this call type (unavailable until a lever earns live confirmation)."}},"required":["call_type_id","slug","spend_less","get_better","holdout_gap"],"description":"The multi-goal improvement reads for one call type + the north-star holdout gap."},"ImprovementReadsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["improvement_reads"]},"workspace_id":{"type":"string"},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"slug":{"type":"string","nullable":true},"spend_less":{"type":"object","properties":{"goal":{"type":"string","enum":["spend_less","get_better"],"description":"Which goal this read is for."},"state":{"type":"string","enum":["evidence","collecting","needs_confirmation","keep_incumbent","unavailable"],"description":"The closed state this half resolved to."},"intent":{"type":"string","enum":["cost_optimization","required_migration","product_improvement"],"description":"The decision intent this half reports — cost_optimization for spend-less; the get-better default is product_improvement, a customer-stated intent is reported and never overridden."},"source_id":{"type":"string","nullable":true,"description":"The source row id for evidence / keep_incumbent / needs_confirmation (a rec / run / plan id), else null."},"tier":{"type":"string","nullable":true,"description":"The evidence tier in the engine’s own vocabulary (evidence state only; else null)."},"estimate":{"type":"boolean","description":"True ONLY when the surfaced figure is an ESTIMATE (a projected saving), never realized."},"deciding":{"type":"array","items":{"type":"string","enum":["quality","cost","guardrail","evidence"]},"description":"The deciding axes for a get-better screen (empty for a spend-less recommendation)."},"collecting":{"type":"object","nullable":true,"properties":{"n":{"type":"integer","nullable":true,"minimum":0,"description":"The count toward the floor, or null when the owning engine exposes no per-call-type count."},"floor":{"type":"integer","minimum":0,"description":"The floor value the owning engine sets (never a new floor)."},"floor_name":{"type":"string","description":"The NAME of the engine that owns the floor (e.g. golden_set.min_activate)."}},"required":["n","floor","floor_name"],"description":"The collecting progress (collecting state only; else null)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason (unavailable state only; else null)."},"next_action":{"type":"string","description":"The customer’s next action — always a sentence, never a bare state."}},"required":["goal","state","intent","source_id","tier","estimate","deciding","collecting","reason","next_action"],"description":"The \"a cheaper model is enough here\" read (from the eval recommendations)."},"get_better":{"type":"object","properties":{"goal":{"type":"string","enum":["spend_less","get_better"],"description":"Which goal this read is for."},"state":{"type":"string","enum":["evidence","collecting","needs_confirmation","keep_incumbent","unavailable"],"description":"The closed state this half resolved to."},"intent":{"type":"string","enum":["cost_optimization","required_migration","product_improvement"],"description":"The decision intent this half reports — cost_optimization for spend-less; the get-better default is product_improvement, a customer-stated intent is reported and never overridden."},"source_id":{"type":"string","nullable":true,"description":"The source row id for evidence / keep_incumbent / needs_confirmation (a rec / run / plan id), else null."},"tier":{"type":"string","nullable":true,"description":"The evidence tier in the engine’s own vocabulary (evidence state only; else null)."},"estimate":{"type":"boolean","description":"True ONLY when the surfaced figure is an ESTIMATE (a projected saving), never realized."},"deciding":{"type":"array","items":{"type":"string","enum":["quality","cost","guardrail","evidence"]},"description":"The deciding axes for a get-better screen (empty for a spend-less recommendation)."},"collecting":{"type":"object","nullable":true,"properties":{"n":{"type":"integer","nullable":true,"minimum":0,"description":"The count toward the floor, or null when the owning engine exposes no per-call-type count."},"floor":{"type":"integer","minimum":0,"description":"The floor value the owning engine sets (never a new floor)."},"floor_name":{"type":"string","description":"The NAME of the engine that owns the floor (e.g. golden_set.min_activate)."}},"required":["n","floor","floor_name"],"description":"The collecting progress (collecting state only; else null)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason (unavailable state only; else null)."},"next_action":{"type":"string","description":"The customer’s next action — always a sentence, never a bare state."}},"required":["goal","state","intent","source_id","tier","estimate","deciding","collecting","reason","next_action"],"description":"The \"quality can improve here\" read (Flywheel candidate + plan)."},"holdout_gap":{"type":"object","properties":{"tier":{"type":"string","enum":["measured","inconclusive","unavailable"],"description":"The evidence tier the holdout gap resolved to."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason when the tier is not measured (no_measurement / no_confirmed_lever / under_powered / aa_parked / cost_ratio_inconclusive), else null."},"gap_per_1000":{"type":"number","nullable":true,"description":"The holdout gap per 1,000 tasks (null when no measurement)."},"gap_ci_low":{"type":"number","nullable":true,"description":"The gap two-sided CI lower bound (per 1,000)."},"gap_ci_high":{"type":"number","nullable":true,"description":"The gap two-sided CI upper bound (per 1,000)."},"cost_ratio":{"type":"number","nullable":true,"description":"The live $ per successful task ratio (treated ÷ holdout), null when inconclusive."},"cost_ratio_ci_low":{"type":"number","nullable":true,"description":"The cost-ratio CI lower bound."},"cost_ratio_ci_high":{"type":"number","nullable":true,"description":"The cost-ratio CI upper bound."}},"required":["tier","reason","gap_per_1000","gap_ci_low","gap_ci_high","cost_ratio","cost_ratio_ci_low","cost_ratio_ci_high"],"description":"The north-star holdout gap for this call type (unavailable until a lever earns live confirmation)."}},"required":["call_type_id","slug","spend_less","get_better","holdout_gap"],"description":"The multi-goal improvement reads for one call type + the north-star holdout gap."}}},"required":["object","workspace_id","call_types"],"description":"The multi-goal improvement reads for every call type the workspace has."},"ConfirmationLift":{"type":"object","properties":{"interval":{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"}},"required":["low","high","point"],"description":"The treated − lever_holdout contrast interval (fractions)."},"n_treated":{"type":"integer"},"n_lever_holdout":{"type":"integer"},"aa_status":{"type":"string","description":"The A/A instrument status: unknown | passing | parked."},"cost_per_success_micro_usd":{"type":"integer","nullable":true,"description":"OUR treated-arm cost per successful artifact (micro-USD), or null (no successes)."}},"required":["interval","n_treated","n_lever_holdout","aa_status","cost_per_success_micro_usd"],"description":"The live lift — the contrast interval + n per arm + cost per successful artifact."},"ConfirmationStatusResponse":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_confirmation_status"]},"candidate_ref":{"type":"string"},"present":{"type":"boolean","description":"Whether a confirmation exists for this candidate reference."},"module_id":{"type":"string","nullable":true,"description":"The servable learned-context module id (`candidate_id`) of this confirmation, or null. A non-proxied customer reads this + `module_version` to inject exactly what the platform is confirming/adopted."},"module_version":{"type":"string","nullable":true,"description":"The recipe-hash module version of the confirmation candidate, or null."},"status":{"type":"string","nullable":true,"description":"The lifecycle (open | adopted | rolled_back | invalidated | closed), or null."},"result_outcome":{"type":"string","nullable":true,"description":"The one-look live result: pending | confirmed | refuted | inconclusive, or null."},"epoch":{"type":"integer","nullable":true},"adoptable":{"type":"boolean","description":"True ONLY when the confirmation is open AND its live result is confirmed."},"adopt_refusal":{"type":"string","nullable":true,"description":"The NAMED reason adoption is unavailable (e.g. not_yet_confirmed_live), or null."},"self_improve_mode":{"type":"string","description":"The call type's self-improve mode (off | assist | autopilot)."},"adopted_by":{"type":"string","nullable":true,"description":"Who adopted this confirmation — `system:autopilot` for the platform auto path, `human:<userId>` for a dashboard press — or null when not adopted."},"auto_adopt":{"type":"object","properties":{"eligible":{"type":"boolean","description":"Whether autopilot WOULD auto-adopt this confirmed confirmation under the current mode + guardrails (recomputed at read time)."},"refusals":{"type":"array","items":{"type":"string"},"description":"The NAMED failed guard(s) when not eligible (e.g. mode_not_autopilot, cost_over_budget, surface_disabled) — so a customer can see WHY autopilot did not fire."}},"required":["eligible","refusals"],"description":"The autopilot decision for this confirmation (read-time, from the current config)."},"lift":{"type":"object","nullable":true,"properties":{"interval":{"type":"object","properties":{"low":{"type":"number"},"high":{"type":"number"},"point":{"type":"number"}},"required":["low","high","point"],"description":"The treated − lever_holdout contrast interval (fractions)."},"n_treated":{"type":"integer"},"n_lever_holdout":{"type":"integer"},"aa_status":{"type":"string","description":"The A/A instrument status: unknown | passing | parked."},"cost_per_success_micro_usd":{"type":"integer","nullable":true,"description":"OUR treated-arm cost per successful artifact (micro-USD), or null (no successes)."}},"required":["interval","n_treated","n_lever_holdout","aa_status","cost_per_success_micro_usd"],"description":"The recorded live lift (interval + n), or null before a result is recorded."}},"required":["object","candidate_ref","present","module_id","module_version","status","result_outcome","epoch","adoptable","adopt_refusal","self_improve_mode","adopted_by","auto_adopt","lift"],"description":"The live-confirmation state for a candidate — status, the one-look result, adoptability, and the recorded interval + n."},"ReviewerFinal":{"type":"object","properties":{"text":{"type":"string","maxLength":1000000,"description":"The approved final body — stored ONLY under corrections_consent."},"draft":{"type":"string","maxLength":1000000,"description":"The draft the reviewer edited — used ONLY to compute server-side diff stats."},"hash":{"type":"string","maxLength":256,"description":"The final content hash (never a body)."},"diff_stats":{"type":"object","properties":{"edit_ratio":{"type":"number"},"changed_spans":{"type":"integer"},"lengths":{"type":"object","properties":{"draft":{"type":"integer"},"final":{"type":"integer"}},"required":["draft","final"]},"final_hash":{"type":"string"}},"description":"CLIENT-computed diff stats (the no-consent path)."}},"additionalProperties":false,"description":"The optional, consented final the reviewer approved."},"ReviewerEventInput":{"type":"object","properties":{"event_id":{"type":"string","minLength":1,"maxLength":256,"description":"The reviewer system’s own stable event id — the idempotency key. A replay is a no-op."},"artifact_key":{"type":"string","minLength":1,"maxLength":512,"description":"The stable artifact key this review is about (or send `artifact_id`)."},"artifact_id":{"type":"string","minLength":1,"maxLength":256,"description":"The artifact id this review is about (or send `artifact_key`)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The EXACT draft version the human reviewed. A mismatch is HELD for repair, never guessed."},"decision":{"type":"string","enum":["approved","approved_with_edits","rejected","regenerated"],"description":"The reviewer’s verdict (closed vocabulary)."},"effective_at":{"type":"string","minLength":1,"description":"When the decision happened in the customer’s world (ISO-8601)."},"reviewer_id":{"type":"string","maxLength":256,"description":"An opaque reviewer identifier — an id, never a name or email."},"final":{"type":"object","properties":{"text":{"type":"string","maxLength":1000000,"description":"The approved final body — stored ONLY under corrections_consent."},"draft":{"type":"string","maxLength":1000000,"description":"The draft the reviewer edited — used ONLY to compute server-side diff stats."},"hash":{"type":"string","maxLength":256,"description":"The final content hash (never a body)."},"diff_stats":{"type":"object","properties":{"edit_ratio":{"type":"number"},"changed_spans":{"type":"integer"},"lengths":{"type":"object","properties":{"draft":{"type":"integer"},"final":{"type":"integer"}},"required":["draft","final"]},"final_hash":{"type":"string"}},"description":"CLIENT-computed diff stats (the no-consent path)."}},"additionalProperties":false,"description":"The optional, consented final the reviewer approved."}},"required":["event_id","artifact_version","decision","effective_at"],"additionalProperties":false,"description":"One reviewer decision. Provenance + learning use are the server’s."},"ReviewerBackfill":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":256,"description":"The customer’s id for this backfill run."},"total":{"type":"integer","minimum":0,"description":"The total the client expects to send (progress denominator; optional)."},"complete":{"type":"boolean","description":"Mark the backfill finished. We NEVER infer completion from counts."}},"required":["id"],"additionalProperties":false,"description":"A declared backfill window."},"ReviewerEventsRequest":{"type":"object","properties":{"reviewer_system":{"type":"string","maxLength":256,"description":"A label for the reviewer system (metadata only; shown in health)."},"backfill":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":256,"description":"The customer’s id for this backfill run."},"total":{"type":"integer","minimum":0,"description":"The total the client expects to send (progress denominator; optional)."},"complete":{"type":"boolean","description":"Mark the backfill finished. We NEVER infer completion from counts."}},"required":["id"],"additionalProperties":false,"description":"A declared backfill window."},"events":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"string","minLength":1,"maxLength":256,"description":"The reviewer system’s own stable event id — the idempotency key. A replay is a no-op."},"artifact_key":{"type":"string","minLength":1,"maxLength":512,"description":"The stable artifact key this review is about (or send `artifact_id`)."},"artifact_id":{"type":"string","minLength":1,"maxLength":256,"description":"The artifact id this review is about (or send `artifact_key`)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The EXACT draft version the human reviewed. A mismatch is HELD for repair, never guessed."},"decision":{"type":"string","enum":["approved","approved_with_edits","rejected","regenerated"],"description":"The reviewer’s verdict (closed vocabulary)."},"effective_at":{"type":"string","minLength":1,"description":"When the decision happened in the customer’s world (ISO-8601)."},"reviewer_id":{"type":"string","maxLength":256,"description":"An opaque reviewer identifier — an id, never a name or email."},"final":{"type":"object","properties":{"text":{"type":"string","maxLength":1000000,"description":"The approved final body — stored ONLY under corrections_consent."},"draft":{"type":"string","maxLength":1000000,"description":"The draft the reviewer edited — used ONLY to compute server-side diff stats."},"hash":{"type":"string","maxLength":256,"description":"The final content hash (never a body)."},"diff_stats":{"type":"object","properties":{"edit_ratio":{"type":"number"},"changed_spans":{"type":"integer"},"lengths":{"type":"object","properties":{"draft":{"type":"integer"},"final":{"type":"integer"}},"required":["draft","final"]},"final_hash":{"type":"string"}},"description":"CLIENT-computed diff stats (the no-consent path)."}},"additionalProperties":false,"description":"The optional, consented final the reviewer approved."}},"required":["event_id","artifact_version","decision","effective_at"],"additionalProperties":false,"description":"One reviewer decision. Provenance + learning use are the server’s."},"minItems":1,"maxItems":500,"description":"1..500 reviewer decisions."}},"required":["events"],"additionalProperties":false,"description":"A signed batch of reviewer decisions."},"ReviewerEventResult":{"type":"object","properties":{"event_id":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate","rejected","unsupported"],"description":"accepted | duplicate (a replay — a visible no-op) | rejected | unsupported."},"reason":{"type":"string","description":"The NAMED refusal, or the accepted marker set (`delayed`, `final_absent`, …)."},"artifact_id":{"type":"string","nullable":true},"artifact_version":{"type":"integer","nullable":true},"channel":{"type":"string","nullable":true,"description":"The mapped outcome channel (always `correction`)."},"kind":{"type":"string","nullable":true,"description":"The mapped outcome kind."},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string"},"description":"The SERVER-derived learning use — echoed so it is visibly not the caller’s to set."},"outcome_event_id":{"type":"string","nullable":true},"final_version":{"type":"integer","nullable":true,"description":"The appended final version, when one was sent."},"repairable":{"type":"boolean","description":"Whether re-driving this same event id can fix it."}},"required":["event_id","status","reason","artifact_id","artifact_version","channel","kind","latency_class","learning_use","outcome_event_id","final_version","repairable"],"description":"One reviewer event’s verdict."},"ReviewerEventsResponse":{"type":"object","properties":{"object":{"type":"string","enum":["reviewer_events"]},"adapter":{"type":"string","description":"The pinned adapter contract version (e.g. `reviewer.v1`)."},"data":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate","rejected","unsupported"],"description":"accepted | duplicate (a replay — a visible no-op) | rejected | unsupported."},"reason":{"type":"string","description":"The NAMED refusal, or the accepted marker set (`delayed`, `final_absent`, …)."},"artifact_id":{"type":"string","nullable":true},"artifact_version":{"type":"integer","nullable":true},"channel":{"type":"string","nullable":true,"description":"The mapped outcome channel (always `correction`)."},"kind":{"type":"string","nullable":true,"description":"The mapped outcome kind."},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string"},"description":"The SERVER-derived learning use — echoed so it is visibly not the caller’s to set."},"outcome_event_id":{"type":"string","nullable":true},"final_version":{"type":"integer","nullable":true,"description":"The appended final version, when one was sent."},"repairable":{"type":"boolean","description":"Whether re-driving this same event id can fix it."}},"required":["event_id","status","reason","artifact_id","artifact_version","channel","kind","latency_class","learning_use","outcome_event_id","final_version","repairable"],"description":"One reviewer event’s verdict."}},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"rejected":{"type":"integer"},"unsupported":{"type":"integer"}},"required":["object","adapter","data","accepted","duplicate","rejected","unsupported"],"description":"The per-event reviewer verdicts + a rollup."},"ReviewerRepairRequest":{"type":"object","properties":{"event":{"type":"object","properties":{"event_id":{"type":"string","minLength":1,"maxLength":256,"description":"The reviewer system’s own stable event id — the idempotency key. A replay is a no-op."},"artifact_key":{"type":"string","minLength":1,"maxLength":512,"description":"The stable artifact key this review is about (or send `artifact_id`)."},"artifact_id":{"type":"string","minLength":1,"maxLength":256,"description":"The artifact id this review is about (or send `artifact_key`)."},"artifact_version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The EXACT draft version the human reviewed. A mismatch is HELD for repair, never guessed."},"decision":{"type":"string","enum":["approved","approved_with_edits","rejected","regenerated"],"description":"The reviewer’s verdict (closed vocabulary)."},"effective_at":{"type":"string","minLength":1,"description":"When the decision happened in the customer’s world (ISO-8601)."},"reviewer_id":{"type":"string","maxLength":256,"description":"An opaque reviewer identifier — an id, never a name or email."},"final":{"type":"object","properties":{"text":{"type":"string","maxLength":1000000,"description":"The approved final body — stored ONLY under corrections_consent."},"draft":{"type":"string","maxLength":1000000,"description":"The draft the reviewer edited — used ONLY to compute server-side diff stats."},"hash":{"type":"string","maxLength":256,"description":"The final content hash (never a body)."},"diff_stats":{"type":"object","properties":{"edit_ratio":{"type":"number"},"changed_spans":{"type":"integer"},"lengths":{"type":"object","properties":{"draft":{"type":"integer"},"final":{"type":"integer"}},"required":["draft","final"]},"final_hash":{"type":"string"}},"description":"CLIENT-computed diff stats (the no-consent path)."}},"additionalProperties":false,"description":"The optional, consented final the reviewer approved."}},"required":["event_id","artifact_version","decision","effective_at"],"additionalProperties":false,"description":"The FULL original event (your durable queue still holds it — we keep receipts, not payloads)."},"repin_to_current_version":{"type":"boolean","description":"Re-pin to the artifact’s CURRENT version. OPT-IN: a stale pin is never silently corrected."},"reviewer_system":{"type":"string","maxLength":256}},"required":["event"],"additionalProperties":false,"description":"Repair ONE dead-lettered reviewer event."},"ReviewerRepairResponse":{"type":"object","properties":{"object":{"type":"string","enum":["reviewer_repair"]},"event_id":{"type":"string"},"before":{"type":"object","properties":{"status":{"type":"string"},"reason":{"type":"string"}},"required":["status","reason"],"description":"The receipt’s status + named refusal before the repair."},"result":{"type":"object","nullable":true,"properties":{"event_id":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate","rejected","unsupported"],"description":"accepted | duplicate (a replay — a visible no-op) | rejected | unsupported."},"reason":{"type":"string","description":"The NAMED refusal, or the accepted marker set (`delayed`, `final_absent`, …)."},"artifact_id":{"type":"string","nullable":true},"artifact_version":{"type":"integer","nullable":true},"channel":{"type":"string","nullable":true,"description":"The mapped outcome channel (always `correction`)."},"kind":{"type":"string","nullable":true,"description":"The mapped outcome kind."},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string"},"description":"The SERVER-derived learning use — echoed so it is visibly not the caller’s to set."},"outcome_event_id":{"type":"string","nullable":true},"final_version":{"type":"integer","nullable":true,"description":"The appended final version, when one was sent."},"repairable":{"type":"boolean","description":"Whether re-driving this same event id can fix it."}},"required":["event_id","status","reason","artifact_id","artifact_version","channel","kind","latency_class","learning_use","outcome_event_id","final_version","repairable"],"description":"The verdict after re-driving; null when the receipt was already accepted (never rewritten)."}},"required":["object","event_id","before","result"],"description":"The dead-letter repair result."},"ReviewerMappingRow":{"type":"object","properties":{"decision":{"type":"string","enum":["approved","approved_with_edits","rejected","regenerated"],"description":"The reviewer’s verdict (closed vocabulary)."},"channel":{"type":"string"},"kind":{"type":"string"},"accepts_final":{"type":"boolean"},"note":{"type":"string"}},"required":["decision","channel","kind","accepts_final","note"],"description":"What one reviewer decision becomes in the ledger (a mapping preview)."},"ReviewerSetupResponse":{"type":"object","properties":{"object":{"type":"string","enum":["reviewer_setup"]},"adapter":{"type":"string"},"endpoint":{"type":"string","description":"The path to POST signed reviewer events to."},"signature":{"type":"object","properties":{"header":{"type":"string"},"timestamp_header":{"type":"string"},"algorithm":{"type":"string","description":"`HMAC-SHA256 over \"<unix-seconds>.<raw body>\"`."},"key":{"type":"string","description":"WHICH secret signs: your ultrarouter API key. Never returned here — you already hold it."},"tolerance_seconds":{"type":"integer"}},"required":["header","timestamp_header","algorithm","key","tolerance_seconds"],"description":"The signed-webhook recipe. The secret itself is never echoed."},"required_scope":{"type":"string"},"mapping":{"type":"array","items":{"type":"object","properties":{"decision":{"type":"string","enum":["approved","approved_with_edits","rejected","regenerated"],"description":"The reviewer’s verdict (closed vocabulary)."},"channel":{"type":"string"},"kind":{"type":"string"},"accepts_final":{"type":"boolean"},"note":{"type":"string"}},"required":["decision","channel","kind","accepts_final","note"],"description":"What one reviewer decision becomes in the ledger (a mapping preview)."}},"corrections_consent":{"type":"boolean","description":"Whether a final BODY may be stored. Off ⇒ send diff_stats/final_hash only."},"test_artifact_key":{"type":"string","description":"The reserved key the guided-setup test event uses."},"events_received":{"type":"integer","description":"Reviewer events this producer has delivered so far."}},"required":["object","adapter","endpoint","signature","required_scope","mapping","corrections_consent","test_artifact_key","events_received"],"description":"The guided-setup payload for the reviewer adapter."},"ReviewerTestRequest":{"type":"object","properties":{"scenario":{"type":"string","enum":["happy","replay","version_mismatch"],"description":"`happy` (default) sends the pair; `replay` re-sends it; `version_mismatch` dead-letters."}},"additionalProperties":false,"description":"Run one guided-setup reviewer scenario."},"ReviewerTestResponse":{"type":"object","properties":{"object":{"type":"string","enum":["reviewer_test"]},"scenario":{"type":"string","enum":["happy","replay","version_mismatch"]},"artifact":{"type":"object","properties":{"object":{"type":"string","enum":["artifact"]},"id":{"type":"string"},"key":{"type":"string"},"archetype":{"type":"string","enum":["forecast","recommendation","draft","extraction","answer","action"],"description":"The artifact archetype (closed vocabulary)."},"artifact_type_version_id":{"type":"string","nullable":true},"call_type_id":{"type":"string","nullable":true},"situation_key":{"type":"string","nullable":true},"occurred_at":{"type":"string"},"exposure_arm":{"type":"string","nullable":true},"exposure_epoch":{"type":"integer","nullable":true},"grant_id":{"type":"string","nullable":true,"description":"The exposure grant this artifact carries (null when unarmed/observation-only)."},"grant_attestation":{"type":"string","nullable":true,"description":"The customer attestation `served` | `applied` (null when no grant)."},"lifecycle":{"type":"string"},"current_version":{"type":"integer","description":"The artifact’s current (max) version."},"request_ids":{"type":"array","items":{"type":"string"},"description":"The ACTIVE request memberships (assembly lineage)."},"claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"The artifact’s ACTIVE claims (one per claim_key) + their current claim state. `claim_key` on an outcome resolves to these."},"superseded_claims":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"claim_key":{"type":"string"},"claim_type":{"type":"string"},"state":{"type":"string","enum":["pending","overdue","resolved","censored","voided","disputed","superseded"],"description":"The current claim state (derived from the claim’s outcome events). `superseded` is terminal: a later customer-declared claim took this claim’s claim_key (only ever listed under `superseded_claims`)."},"state_version":{"type":"integer"},"stated_confidence":{"type":"number","nullable":true},"resolves_by":{"type":"string","nullable":true},"artifact_version":{"type":"integer"},"provenance":{"type":"string","enum":["declared","extracted"],"description":"Who asserted the claim: `declared` = yours (declared claims always win their claim_key); `extracted` = the platform’s claim extractor."},"qualification":{"type":"string","enum":["declared","qualified","unqualified"],"description":"The trust label: `declared` for a declared claim; for an extracted claim, the extractor’s verdict at extraction (`unqualified` never feeds learning)."},"superseded_at":{"type":"string","nullable":true,"description":"When a later declared claim superseded this one (null for an active claim)."},"superseded_by_claim_id":{"type":"string","nullable":true,"description":"The declared claim that superseded this one (null for an active claim)."},"created_at":{"type":"string"}},"required":["id","claim_key","claim_type","state","state_version","stated_confidence","resolves_by","artifact_version","provenance","qualification","superseded_at","superseded_by_claim_id","created_at"],"description":"A claim on an artifact (metadata only)."},"description":"History: platform-extracted claims a later declared claim superseded for the same claim_key — kept (state `superseded`) and linked through `superseded_by_claim_id`, never deleted; their outcome events stay on them. Usually empty."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","key","archetype","artifact_type_version_id","call_type_id","situation_key","occurred_at","exposure_arm","exposure_epoch","grant_id","grant_attestation","lifecycle","current_version","request_ids","claims","superseded_claims","created_at","updated_at"],"description":"The reserved test artifact (lifecycle `test`)."},"result":{"type":"object","properties":{"event_id":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate","rejected","unsupported"],"description":"accepted | duplicate (a replay — a visible no-op) | rejected | unsupported."},"reason":{"type":"string","description":"The NAMED refusal, or the accepted marker set (`delayed`, `final_absent`, …)."},"artifact_id":{"type":"string","nullable":true},"artifact_version":{"type":"integer","nullable":true},"channel":{"type":"string","nullable":true,"description":"The mapped outcome channel (always `correction`)."},"kind":{"type":"string","nullable":true,"description":"The mapped outcome kind."},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string"},"description":"The SERVER-derived learning use — echoed so it is visibly not the caller’s to set."},"outcome_event_id":{"type":"string","nullable":true},"final_version":{"type":"integer","nullable":true,"description":"The appended final version, when one was sent."},"repairable":{"type":"boolean","description":"Whether re-driving this same event id can fix it."}},"required":["event_id","status","reason","artifact_id","artifact_version","channel","kind","latency_class","learning_use","outcome_event_id","final_version","repairable"],"description":"The review event that landed on it — the joined pair."},"excluded_from_learning":{"type":"boolean","description":"Test data never enters learning: no exposure arm ⇒ excluded from the attribution and calibration rollups."},"excluded_from_invoicing":{"type":"boolean","description":"Test data never enters invoicing: the setup path is unmetered."}},"required":["object","scenario","artifact","result","excluded_from_learning","excluded_from_invoicing"],"description":"The guided-setup test result."},"ReviewerDeadLetter":{"type":"object","properties":{"event_id":{"type":"string"},"reason":{"type":"string","description":"The NAMED refusal (e.g. `version_mismatch:claimed=2,current=3`)."},"created_at":{"type":"string"}},"required":["event_id","reason","created_at"],"description":"A dead-lettered reviewer event awaiting repair."},"ReviewerBackfillProgress":{"type":"object","properties":{"id":{"type":"string"},"declared_total":{"type":"integer","nullable":true},"received":{"type":"integer"},"accepted":{"type":"integer"},"rejected":{"type":"integer"},"complete":{"type":"boolean","description":"Declared by the client — never inferred from counts."}},"required":["id","declared_total","received","accepted","rejected","complete"],"description":"One backfill’s progress."},"ReviewerHealthResponse":{"type":"object","properties":{"object":{"type":"string","enum":["reviewer_health"]},"adapter":{"type":"string"},"last_success_at":{"type":"string","nullable":true,"description":"(1) The last successful event — null until one lands."},"last_success_event_id":{"type":"string","nullable":true},"events":{"type":"object","properties":{"accepted":{"type":"integer"},"duplicate":{"type":"integer","description":"(2) Replays absorbed as visible no-ops."},"unmatched":{"type":"integer","description":"(3) Events whose artifact link did not resolve here."},"delayed":{"type":"integer","description":"(4) Accepted events the ledger classed `delayed`."},"rejected":{"type":"integer","description":"(5) Events refused for another named reason."},"unsupported":{"type":"integer","description":"Events this deployment cannot act on at all."}},"required":["accepted","duplicate","unmatched","delayed","rejected","unsupported"],"description":"The named integration states (counts only — NEVER a body)."},"dead_letters":{"type":"array","items":{"type":"object","properties":{"event_id":{"type":"string"},"reason":{"type":"string","description":"The NAMED refusal (e.g. `version_mismatch:claimed=2,current=3`)."},"created_at":{"type":"string"}},"required":["event_id","reason","created_at"],"description":"A dead-lettered reviewer event awaiting repair."}},"dead_letter_total":{"type":"integer"},"backfills":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"declared_total":{"type":"integer","nullable":true},"received":{"type":"integer"},"accepted":{"type":"integer"},"rejected":{"type":"integer"},"complete":{"type":"boolean","description":"Declared by the client — never inferred from counts."}},"required":["id","declared_total","received","accepted","rejected","complete"],"description":"One backfill’s progress."},"description":"(6) Backfill progress, per declared id."},"next_repair":{"type":"object","properties":{"action":{"type":"string","enum":["none","send_test_event","repair_version","create_artifact","grant_consent","contact_support"]},"detail":{"type":"string"},"event_id":{"type":"string","nullable":true}},"required":["action","detail","event_id"],"description":"The ONE next repair action. An unnameable dead letter is never `none`."}},"required":["object","adapter","last_success_at","last_success_event_id","events","dead_letters","dead_letter_total","backfills","next_repair"],"description":"Reviewer-integration health: the six named states + the next repair action."},"ImportRequest":{"type":"object","properties":{"format":{"type":"string","minLength":1,"maxLength":128,"description":"The pinned adapter format id (e.g. `usage_summary`, `openai_chat_jsonl`)."},"format_version":{"type":"string","maxLength":16,"description":"The pinned adapter version (defaults to the latest for the format)."},"mode":{"type":"string","enum":["preview","commit"],"description":"preview = capability report only (nothing stored); commit = ingest. Defaults to commit."},"import_id":{"type":"string","maxLength":128,"description":"Resume an existing import (idempotent per record content hash)."},"call_type_id":{"type":"string","minLength":1,"maxLength":128,"description":"The call type (a `ct_*` id from `GET /v1/call-types`) this history belongs to, and so its CONFIRMED objective. Intact traces only. Every accepted record’s artifact is stamped with the call type, its confirmed objective version and its situation at assembly (insert-only), so the batch’s task verdicts count toward that call type’s readiness once a blind ADMISSION audit of the batch passes. Refused by name: an unknown call type (404 `call_type_not_found`), one without a confirmed objective (409 `call_type_unconfirmed`), a usage-only file (400 `binding_requires_intact_trace`), a resume naming another call type or binding an unbound batch (409 `binding_conflict`), a resume after the confirmed objective changed (409 `binding_stale`). Omitted on a resume ⇒ the batch keeps the binding it was created with; omitted on a new import ⇒ an UNBOUND batch whose verdicts never count toward readiness."},"reason_vocabulary":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128},"codes":{"type":"array","items":{"type":"string","minLength":1,"maxLength":256},"maxItems":256}},"required":["id","codes"],"description":"workflow_execution_jsonl only: the typed hold-reason codes this batch’s executions may use (`{ id, codes[] }`). Registered ONCE at the batch creation (insert-only; a resume inherits it). An execution whose terminal names an unregistered code is refused `reason_code_unregistered`. Required for a workflow import (409 `workflow_requires_reason_vocabulary` otherwise)."},"records":{"type":"array","items":{"nullable":true},"maxItems":5000,"description":"The uploaded records (array form). Intact-trace records may carry request/response bodies — the ONLY import field that does; stored ONLY under corrections_consent, redacted on ingest. A workflow_execution_jsonl record groups the EXISTING gateway request rows its `calls` name into one artifact with one terminal outcome."},"jsonl":{"type":"string","description":"The uploaded records as JSONL (newline-delimited JSON). Alternative to `records`."}},"required":["format"],"additionalProperties":false,"description":"Create or resume a history import (consent-gated; owner/admin or outcomes:write)."},"UsageExposureRow":{"type":"object","properties":{"model":{"type":"string"},"requests":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cost_micro_usd":{"type":"integer"}},"required":["model","requests","input_tokens","output_tokens","cost_micro_usd"],"description":"A per-model exposure/spend summary row (usage-only import)."},"ImportParseError":{"type":"object","properties":{"line":{"type":"integer"},"message":{"type":"string"}},"required":["line","message"],"description":"A malformed JSONL line."},"ImportCapabilityReport":{"type":"object","properties":{"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"class_truth":{"type":"string","description":"The honest one-sentence class truth (usage-only vs consented/unconsented intact)."},"record_count":{"type":"integer"},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"rejected":{"type":"integer"},"unsupported":{"type":"integer"},"redacted":{"type":"integer","description":"How many stored records had PII redacted on ingest."},"missing_lineage":{"type":"integer"},"bodies_stored":{"type":"integer","description":"Replayable request/response bodies stored (consented intact only)."},"reasons":{"type":"object","additionalProperties":{"type":"integer"},"description":"Rejection/unsupported reason → count."},"unsupported_fields":{"type":"array","items":{"type":"string"}},"parse_errors":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"message":{"type":"string"}},"required":["line","message"],"description":"A malformed JSONL line."}},"replayable":{"type":"boolean","description":"Whether any record supports replay (consented intact + a body)."},"binding_truth":{"type":"string","description":"Intact traces only: the honest binding sentence — the call type + confirmed objective the batch is bound to and what still gates its verdicts (a blind admission audit of THIS batch), or that an unbound batch’s verdicts can never count toward readiness."},"usage_exposure":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"requests":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cost_micro_usd":{"type":"integer"}},"required":["model","requests","input_tokens","output_tokens","cost_micro_usd"],"description":"A per-model exposure/spend summary row (usage-only import)."},"description":"Usage-only: per-model exposure rows."},"spend_micro_usd":{"type":"integer","description":"Usage-only: total spend (micro-USD)."},"workflow":{"type":"object","properties":{"executions":{"type":"integer"},"delivered":{"type":"integer"},"held":{"type":"integer"},"orphan_calls":{"type":"integer","description":"Calls not members of a terminal execution (orphan/interrupted) — kept apart, never dropped."},"cost_reconciliation":{"type":"array","items":{"type":"object","properties":{"execution_key":{"type":"string"},"gateway_cost_micro_usd":{"type":"integer"},"client_cost_micro_usd":{"type":"integer","nullable":true},"cost_diff_micro_usd":{"type":"integer","nullable":true},"pending_charges":{"type":"integer"}},"required":["execution_key","gateway_cost_micro_usd","client_cost_micro_usd","cost_diff_micro_usd","pending_charges"],"description":"One execution’s cost reconciliation (gateway summed vs the client figure vs the difference)."}}},"required":["executions","delivered","held","orphan_calls","cost_reconciliation"],"description":"Workflow (workflow_execution_jsonl) only: the execution counts (delivered / held), the orphan/interrupted calls kept apart, and the per-execution cost reconciliation."}},"required":["format","format_version","import_class","class_truth","record_count","accepted","duplicate","rejected","unsupported","redacted","missing_lineage","bodies_stored","reasons","unsupported_fields","parse_errors","replayable"],"description":"The history-import capability report (NEVER a body)."},"ImportSummary":{"type":"object","properties":{"object":{"type":"string","enum":["import"]},"id":{"type":"string"},"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"status":{"type":"string","enum":["preview","running","completed","cancelled","failed"]},"key_mode":{"type":"string","enum":["test","live"]},"corrections_consent":{"type":"boolean"},"record_count":{"type":"integer"},"accepted_count":{"type":"integer"},"duplicate_count":{"type":"integer"},"rejected_count":{"type":"integer"},"unsupported_count":{"type":"integer"},"call_type_id":{"type":"string","nullable":true,"description":"The call type this batch is bound to (insert-only); null = an unbound batch whose verdicts never count toward readiness."},"artifact_type_version_id":{"type":"string","nullable":true,"description":"The call type’s CONFIRMED objective version the batch was bound to (insert-only); null = unbound."},"report":{"type":"object","properties":{"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"class_truth":{"type":"string","description":"The honest one-sentence class truth (usage-only vs consented/unconsented intact)."},"record_count":{"type":"integer"},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"rejected":{"type":"integer"},"unsupported":{"type":"integer"},"redacted":{"type":"integer","description":"How many stored records had PII redacted on ingest."},"missing_lineage":{"type":"integer"},"bodies_stored":{"type":"integer","description":"Replayable request/response bodies stored (consented intact only)."},"reasons":{"type":"object","additionalProperties":{"type":"integer"},"description":"Rejection/unsupported reason → count."},"unsupported_fields":{"type":"array","items":{"type":"string"}},"parse_errors":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"message":{"type":"string"}},"required":["line","message"],"description":"A malformed JSONL line."}},"replayable":{"type":"boolean","description":"Whether any record supports replay (consented intact + a body)."},"binding_truth":{"type":"string","description":"Intact traces only: the honest binding sentence — the call type + confirmed objective the batch is bound to and what still gates its verdicts (a blind admission audit of THIS batch), or that an unbound batch’s verdicts can never count toward readiness."},"usage_exposure":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"requests":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cost_micro_usd":{"type":"integer"}},"required":["model","requests","input_tokens","output_tokens","cost_micro_usd"],"description":"A per-model exposure/spend summary row (usage-only import)."},"description":"Usage-only: per-model exposure rows."},"spend_micro_usd":{"type":"integer","description":"Usage-only: total spend (micro-USD)."},"workflow":{"type":"object","properties":{"executions":{"type":"integer"},"delivered":{"type":"integer"},"held":{"type":"integer"},"orphan_calls":{"type":"integer","description":"Calls not members of a terminal execution (orphan/interrupted) — kept apart, never dropped."},"cost_reconciliation":{"type":"array","items":{"type":"object","properties":{"execution_key":{"type":"string"},"gateway_cost_micro_usd":{"type":"integer"},"client_cost_micro_usd":{"type":"integer","nullable":true},"cost_diff_micro_usd":{"type":"integer","nullable":true},"pending_charges":{"type":"integer"}},"required":["execution_key","gateway_cost_micro_usd","client_cost_micro_usd","cost_diff_micro_usd","pending_charges"],"description":"One execution’s cost reconciliation (gateway summed vs the client figure vs the difference)."}}},"required":["executions","delivered","held","orphan_calls","cost_reconciliation"],"description":"Workflow (workflow_execution_jsonl) only: the execution counts (delivered / held), the orphan/interrupted calls kept apart, and the per-execution cost reconciliation."}},"description":"The capability report (may be `{}` while running)."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","format","format_version","import_class","status","key_mode","corrections_consent","record_count","accepted_count","duplicate_count","rejected_count","unsupported_count","call_type_id","artifact_type_version_id","report","created_at","updated_at"],"description":"A history import (metadata + capability report; NEVER a body)."},"ImportEnvelope":{"type":"object","properties":{"import":{"type":"object","properties":{"object":{"type":"string","enum":["import"]},"id":{"type":"string"},"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"status":{"type":"string","enum":["preview","running","completed","cancelled","failed"]},"key_mode":{"type":"string","enum":["test","live"]},"corrections_consent":{"type":"boolean"},"record_count":{"type":"integer"},"accepted_count":{"type":"integer"},"duplicate_count":{"type":"integer"},"rejected_count":{"type":"integer"},"unsupported_count":{"type":"integer"},"call_type_id":{"type":"string","nullable":true,"description":"The call type this batch is bound to (insert-only); null = an unbound batch whose verdicts never count toward readiness."},"artifact_type_version_id":{"type":"string","nullable":true,"description":"The call type’s CONFIRMED objective version the batch was bound to (insert-only); null = unbound."},"report":{"type":"object","properties":{"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"class_truth":{"type":"string","description":"The honest one-sentence class truth (usage-only vs consented/unconsented intact)."},"record_count":{"type":"integer"},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"rejected":{"type":"integer"},"unsupported":{"type":"integer"},"redacted":{"type":"integer","description":"How many stored records had PII redacted on ingest."},"missing_lineage":{"type":"integer"},"bodies_stored":{"type":"integer","description":"Replayable request/response bodies stored (consented intact only)."},"reasons":{"type":"object","additionalProperties":{"type":"integer"},"description":"Rejection/unsupported reason → count."},"unsupported_fields":{"type":"array","items":{"type":"string"}},"parse_errors":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"message":{"type":"string"}},"required":["line","message"],"description":"A malformed JSONL line."}},"replayable":{"type":"boolean","description":"Whether any record supports replay (consented intact + a body)."},"binding_truth":{"type":"string","description":"Intact traces only: the honest binding sentence — the call type + confirmed objective the batch is bound to and what still gates its verdicts (a blind admission audit of THIS batch), or that an unbound batch’s verdicts can never count toward readiness."},"usage_exposure":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"requests":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cost_micro_usd":{"type":"integer"}},"required":["model","requests","input_tokens","output_tokens","cost_micro_usd"],"description":"A per-model exposure/spend summary row (usage-only import)."},"description":"Usage-only: per-model exposure rows."},"spend_micro_usd":{"type":"integer","description":"Usage-only: total spend (micro-USD)."},"workflow":{"type":"object","properties":{"executions":{"type":"integer"},"delivered":{"type":"integer"},"held":{"type":"integer"},"orphan_calls":{"type":"integer","description":"Calls not members of a terminal execution (orphan/interrupted) — kept apart, never dropped."},"cost_reconciliation":{"type":"array","items":{"type":"object","properties":{"execution_key":{"type":"string"},"gateway_cost_micro_usd":{"type":"integer"},"client_cost_micro_usd":{"type":"integer","nullable":true},"cost_diff_micro_usd":{"type":"integer","nullable":true},"pending_charges":{"type":"integer"}},"required":["execution_key","gateway_cost_micro_usd","client_cost_micro_usd","cost_diff_micro_usd","pending_charges"],"description":"One execution’s cost reconciliation (gateway summed vs the client figure vs the difference)."}}},"required":["executions","delivered","held","orphan_calls","cost_reconciliation"],"description":"Workflow (workflow_execution_jsonl) only: the execution counts (delivered / held), the orphan/interrupted calls kept apart, and the per-execution cost reconciliation."}},"description":"The capability report (may be `{}` while running)."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","format","format_version","import_class","status","key_mode","corrections_consent","record_count","accepted_count","duplicate_count","rejected_count","unsupported_count","call_type_id","artifact_type_version_id","report","created_at","updated_at"],"description":"A history import (metadata + capability report; NEVER a body)."}},"required":["import"],"description":"A single import, wrapped in the `import` envelope."},"ImportListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["import"]},"id":{"type":"string"},"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"status":{"type":"string","enum":["preview","running","completed","cancelled","failed"]},"key_mode":{"type":"string","enum":["test","live"]},"corrections_consent":{"type":"boolean"},"record_count":{"type":"integer"},"accepted_count":{"type":"integer"},"duplicate_count":{"type":"integer"},"rejected_count":{"type":"integer"},"unsupported_count":{"type":"integer"},"call_type_id":{"type":"string","nullable":true,"description":"The call type this batch is bound to (insert-only); null = an unbound batch whose verdicts never count toward readiness."},"artifact_type_version_id":{"type":"string","nullable":true,"description":"The call type’s CONFIRMED objective version the batch was bound to (insert-only); null = unbound."},"report":{"type":"object","properties":{"format":{"type":"string"},"format_version":{"type":"string"},"import_class":{"type":"string","enum":["usage_only","intact_trace"],"description":"The import class (pinned by the adapter): usage_only (summaries) | intact_trace (bodies)."},"class_truth":{"type":"string","description":"The honest one-sentence class truth (usage-only vs consented/unconsented intact)."},"record_count":{"type":"integer"},"accepted":{"type":"integer"},"duplicate":{"type":"integer"},"rejected":{"type":"integer"},"unsupported":{"type":"integer"},"redacted":{"type":"integer","description":"How many stored records had PII redacted on ingest."},"missing_lineage":{"type":"integer"},"bodies_stored":{"type":"integer","description":"Replayable request/response bodies stored (consented intact only)."},"reasons":{"type":"object","additionalProperties":{"type":"integer"},"description":"Rejection/unsupported reason → count."},"unsupported_fields":{"type":"array","items":{"type":"string"}},"parse_errors":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"message":{"type":"string"}},"required":["line","message"],"description":"A malformed JSONL line."}},"replayable":{"type":"boolean","description":"Whether any record supports replay (consented intact + a body)."},"binding_truth":{"type":"string","description":"Intact traces only: the honest binding sentence — the call type + confirmed objective the batch is bound to and what still gates its verdicts (a blind admission audit of THIS batch), or that an unbound batch’s verdicts can never count toward readiness."},"usage_exposure":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"requests":{"type":"integer"},"input_tokens":{"type":"integer"},"output_tokens":{"type":"integer"},"cost_micro_usd":{"type":"integer"}},"required":["model","requests","input_tokens","output_tokens","cost_micro_usd"],"description":"A per-model exposure/spend summary row (usage-only import)."},"description":"Usage-only: per-model exposure rows."},"spend_micro_usd":{"type":"integer","description":"Usage-only: total spend (micro-USD)."},"workflow":{"type":"object","properties":{"executions":{"type":"integer"},"delivered":{"type":"integer"},"held":{"type":"integer"},"orphan_calls":{"type":"integer","description":"Calls not members of a terminal execution (orphan/interrupted) — kept apart, never dropped."},"cost_reconciliation":{"type":"array","items":{"type":"object","properties":{"execution_key":{"type":"string"},"gateway_cost_micro_usd":{"type":"integer"},"client_cost_micro_usd":{"type":"integer","nullable":true},"cost_diff_micro_usd":{"type":"integer","nullable":true},"pending_charges":{"type":"integer"}},"required":["execution_key","gateway_cost_micro_usd","client_cost_micro_usd","cost_diff_micro_usd","pending_charges"],"description":"One execution’s cost reconciliation (gateway summed vs the client figure vs the difference)."}}},"required":["executions","delivered","held","orphan_calls","cost_reconciliation"],"description":"Workflow (workflow_execution_jsonl) only: the execution counts (delivered / held), the orphan/interrupted calls kept apart, and the per-execution cost reconciliation."}},"description":"The capability report (may be `{}` while running)."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","format","format_version","import_class","status","key_mode","corrections_consent","record_count","accepted_count","duplicate_count","rejected_count","unsupported_count","call_type_id","artifact_type_version_id","report","created_at","updated_at"],"description":"A history import (metadata + capability report; NEVER a body)."}},"next_cursor":{"type":"string","nullable":true}},"required":["object","data","next_cursor"],"description":"A keyset-paginated page of imports (never offset-paginated)."},"CallTypeConfigBody":{"type":"object","properties":{"model_pin":{"type":"string","nullable":true,"minLength":1,"description":"Pinned model id for this call type (the call-type layer of the config precedence chain: request > key defaults > call type > workspace defaults > system defaults)."},"router_mode":{"type":"string","nullable":true,"enum":["pinned","auto","candidates","off"],"description":"Router mode for this call type."},"compression_mode":{"type":"string","nullable":true,"enum":["off","semantic_safe","adaptive","lossless","auto"],"description":"Compression safety tier: off (default, no model-visible rewrite), semantic_safe (deterministic, evidence-qualified) or adaptive (guarded pruning). The legacy lossless/auto values remain parseable for backward compatibility."},"fallbacks":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Ordered fallback model ids (OpenRouter parity)."},"provider_prefs":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"OpenRouter-parity provider preferences object."},"self_improve_mode":{"type":"string","enum":["off","assist","autopilot"],"description":"Self-improve mode: off (capture outcomes only), assist (default — propose/test/push passed improvements to your inbox), or autopilot (adopt passed improvements automatically within guardrails). Omitted ⇒ the current mode is preserved."},"self_improve_guardrails":{"type":"object","properties":{"max_cost_per_success_micro_usd":{"type":"integer","nullable":true,"minimum":0,"description":"Autopilot cost budget: the max cost per successful task (integer µUSD). Null (or omitted) ⇒ NO budget registered, which fails autopilot closed."},"surfaces":{"type":"array","items":{"type":"string","enum":["knowledge_injection","model_routing","hosted_prompt"]},"description":"The surfaces enabled for autopilot. Only knowledge_injection is wired today; model_routing and hosted_prompt are accepted but refuse auto-adopt until wired."}},"description":"Autopilot guardrail config (the cost budget + enabled surfaces). Omitted ⇒ the current guardrails are preserved."},"learned_context_delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"Learned-context DELIVERY for this call type: gateway_inject_after_stable_prefix (default — the gateway injects the learned module after the stable prefix) or off (the gateway never injects; SDK/preflight consumers still resolve the module — off keeps the standing holdout and measurement intact, arms are still assigned and stamped). A FLIP starts a NEW learned_context epoch and invalidates any open confirmation (its baseline moved). \"Inject at end\" is DEFERRED (it returns behind this field once a confirmation has been run with it). Omitted ⇒ the current delivery is preserved."},"case_precedents_enabled":{"type":"boolean","description":"Whether the gateway serves PER-REQUEST CASE PRECEDENTS into the learned data slot for this call type — a CASE is a VIEW over the outcome ledger, retrieved fresh per request (contrastive corrected-failure + success exemplars, ≤ 300 tokens, never an instruction). Default false (the case path is inert; serving byte-identical). Turning this on by default for customers is gated on internal validation, not on this flag. Omitted ⇒ the current value is preserved."}},"description":"Call-type config body (the validated shape). On PATCH, an omitted field keeps its current value and an explicit null clears it."},"CreateCallTypeRequest":{"type":"object","properties":{"slug":{"type":"string","minLength":1,"description":"The explicit call-type slug (workspace-unique)."},"config":{"type":"object","properties":{"model_pin":{"type":"string","nullable":true,"minLength":1,"description":"Pinned model id for this call type (the call-type layer of the config precedence chain: request > key defaults > call type > workspace defaults > system defaults)."},"router_mode":{"type":"string","nullable":true,"enum":["pinned","auto","candidates","off"],"description":"Router mode for this call type."},"compression_mode":{"type":"string","nullable":true,"enum":["off","semantic_safe","adaptive","lossless","auto"],"description":"Compression safety tier: off (default, no model-visible rewrite), semantic_safe (deterministic, evidence-qualified) or adaptive (guarded pruning). The legacy lossless/auto values remain parseable for backward compatibility."},"fallbacks":{"type":"array","nullable":true,"items":{"type":"string"},"description":"Ordered fallback model ids (OpenRouter parity)."},"provider_prefs":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"OpenRouter-parity provider preferences object."},"self_improve_mode":{"type":"string","enum":["off","assist","autopilot"],"description":"Self-improve mode: off (capture outcomes only), assist (default — propose/test/push passed improvements to your inbox), or autopilot (adopt passed improvements automatically within guardrails). Omitted ⇒ the current mode is preserved."},"self_improve_guardrails":{"type":"object","properties":{"max_cost_per_success_micro_usd":{"type":"integer","nullable":true,"minimum":0,"description":"Autopilot cost budget: the max cost per successful task (integer µUSD). Null (or omitted) ⇒ NO budget registered, which fails autopilot closed."},"surfaces":{"type":"array","items":{"type":"string","enum":["knowledge_injection","model_routing","hosted_prompt"]},"description":"The surfaces enabled for autopilot. Only knowledge_injection is wired today; model_routing and hosted_prompt are accepted but refuse auto-adopt until wired."}},"description":"Autopilot guardrail config (the cost budget + enabled surfaces). Omitted ⇒ the current guardrails are preserved."},"learned_context_delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"Learned-context DELIVERY for this call type: gateway_inject_after_stable_prefix (default — the gateway injects the learned module after the stable prefix) or off (the gateway never injects; SDK/preflight consumers still resolve the module — off keeps the standing holdout and measurement intact, arms are still assigned and stamped). A FLIP starts a NEW learned_context epoch and invalidates any open confirmation (its baseline moved). \"Inject at end\" is DEFERRED (it returns behind this field once a confirmation has been run with it). Omitted ⇒ the current delivery is preserved."},"case_precedents_enabled":{"type":"boolean","description":"Whether the gateway serves PER-REQUEST CASE PRECEDENTS into the learned data slot for this call type — a CASE is a VIEW over the outcome ledger, retrieved fresh per request (contrastive corrected-failure + success exemplars, ≤ 300 tokens, never an instruction). Default false (the case path is inert; serving byte-identical). Turning this on by default for customers is gated on internal validation, not on this flag. Omitted ⇒ the current value is preserved."}},"description":"Optional initial config version."}},"required":["slug"],"description":"Create a call type with an explicit slug (POST /v1/call-types)."},"EnqueueEvalRequest":{"type":"object","properties":{"mode":{"type":"string","enum":["request","task"],"description":"Eval runner mode: request (default) or task (whole-trace, $/task evidence)."}},"description":"Optional manual-eval trigger body (selects the eval runner mode)."},"EnqueueEvalResponse":{"oneOf":[{"type":"object","properties":{"object":{"type":"string","enum":["eval_run"]},"enqueued":{"type":"boolean","enum":[true]},"run_id":{"type":"string","description":"The enqueued eval run id (`evr_…`)."},"candidate_count":{"type":"integer","description":"The number of pinned candidate offers selected for this run."}},"required":["object","enqueued","run_id","candidate_count"],"description":"An eval run was enqueued (202)."},{"type":"object","properties":{"object":{"type":"string","enum":["eval_run"]},"enqueued":{"type":"boolean","enum":[false]},"reason":{"type":"string","enum":["no_golden_set","no_candidates","no_incumbent","not_relevant","deduped","auto_eval_disabled","no_op"],"description":"The documented no-op reason."},"deduped":{"type":"boolean","description":"True when the no-op is a dedupe onto a fresh identical run within the window."},"prior_run_id":{"type":"string","description":"The run this request DEDUPED ONTO (`evr_…`) — present only on a dedupe, read through the tenant-scoped reader (never another workspace’s run)."},"trigger":{"type":"string","description":"The prior run’s trigger (e.g. `manual`, `model.release`) — present only on a dedupe."},"status":{"type":"string","description":"The prior run’s current status (`queued`|`running`|`scored`|`failed`) — present only on a dedupe."}},"required":["object","enqueued","reason","deduped"],"description":"A documented no-op (200); a dedupe additionally names the prior run."}],"description":"The manual-eval trigger result: the enqueued run (202) or a documented no-op (200)."},"CallTypeConfigVersion":{"type":"object","properties":{"version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"model_pin":{"type":"string","nullable":true},"router_mode":{"type":"string","nullable":true},"compression_mode":{"type":"string","nullable":true},"fallbacks":{"type":"array","nullable":true,"items":{"type":"string"}},"provider_prefs":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"learned_context_delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"Learned-context delivery on this version (gateway_inject_after_stable_prefix | off)."},"case_precedents_enabled":{"type":"boolean","description":"Whether this version serves PER-REQUEST CASE PRECEDENTS into the learned data slot (default false)."},"created_at":{"type":"string"}},"required":["version","model_pin","router_mode","compression_mode","fallbacks","provider_prefs","created_at"],"description":"One immutable call-type config version."},"CallTypeSummary":{"type":"object","properties":{"object":{"type":"string","enum":["call_type"]},"id":{"type":"string"},"slug":{"type":"string"},"display_name":{"type":"string"},"source":{"type":"string","description":"`explicit` (caller slug) or `fingerprint` (automatically inferred from request shape)."},"current_config_version":{"type":"integer","nullable":true},"config":{"type":"object","nullable":true,"properties":{"version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"model_pin":{"type":"string","nullable":true},"router_mode":{"type":"string","nullable":true},"compression_mode":{"type":"string","nullable":true},"fallbacks":{"type":"array","nullable":true,"items":{"type":"string"}},"provider_prefs":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"learned_context_delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"Learned-context delivery on this version (gateway_inject_after_stable_prefix | off)."},"case_precedents_enabled":{"type":"boolean","description":"Whether this version serves PER-REQUEST CASE PRECEDENTS into the learned data slot (default false)."},"created_at":{"type":"string"}},"required":["version","model_pin","router_mode","compression_mode","fallbacks","provider_prefs","created_at"],"description":"The active config version, or null."},"lifecycle_state":{"type":"string","description":"Audit Autopilot lifecycle state (observing | evaluator_building | benchmarkable | recommendable | canary | verified | held). ZERO serving authority."},"lifecycle_reason":{"type":"string","nullable":true,"description":"The evidence reason for the last automatic lifecycle transition (null before the first)."},"lifecycle_transitioned_at":{"type":"string","nullable":true,"description":"When the last lifecycle transition was applied (ISO 8601), or null."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","slug","display_name","source","current_config_version","config","lifecycle_state","lifecycle_reason","lifecycle_transitioned_at","created_at","updated_at"],"description":"A call type with its active config version."},"CallTypeListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["call_type"]},"id":{"type":"string"},"slug":{"type":"string"},"display_name":{"type":"string"},"source":{"type":"string","description":"`explicit` (caller slug) or `fingerprint` (automatically inferred from request shape)."},"current_config_version":{"type":"integer","nullable":true},"config":{"type":"object","nullable":true,"properties":{"version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"model_pin":{"type":"string","nullable":true},"router_mode":{"type":"string","nullable":true},"compression_mode":{"type":"string","nullable":true},"fallbacks":{"type":"array","nullable":true,"items":{"type":"string"}},"provider_prefs":{"type":"object","nullable":true,"additionalProperties":{"nullable":true}},"learned_context_delivery":{"type":"string","enum":["gateway_inject_after_stable_prefix","off"],"description":"Learned-context delivery on this version (gateway_inject_after_stable_prefix | off)."},"case_precedents_enabled":{"type":"boolean","description":"Whether this version serves PER-REQUEST CASE PRECEDENTS into the learned data slot (default false)."},"created_at":{"type":"string"}},"required":["version","model_pin","router_mode","compression_mode","fallbacks","provider_prefs","created_at"],"description":"The active config version, or null."},"lifecycle_state":{"type":"string","description":"Audit Autopilot lifecycle state (observing | evaluator_building | benchmarkable | recommendable | canary | verified | held). ZERO serving authority."},"lifecycle_reason":{"type":"string","nullable":true,"description":"The evidence reason for the last automatic lifecycle transition (null before the first)."},"lifecycle_transitioned_at":{"type":"string","nullable":true,"description":"When the last lifecycle transition was applied (ISO 8601), or null."},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["object","id","slug","display_name","source","current_config_version","config","lifecycle_state","lifecycle_reason","lifecycle_transitioned_at","created_at","updated_at"],"description":"A call type with its active config version."}}},"required":["object","data"],"description":"Workspace call-type list (GET /v1/call-types)."},"RunSpecComponent":{"type":"object","properties":{"integrity_refused":{"type":"boolean","enum":[false],"description":"Always false on a verified RunSpec (the integrity-refused stub carries true)."},"run_spec_id":{"type":"string","description":"The immutable RunSpec id (`rspec_…`)."},"spec_hash":{"type":"string","description":"The run-spec content hash (the dedupe key)."},"profile_hash":{"type":"string","description":"The ExecutionProfile content hash."},"spec_version":{"type":"integer"},"stage":{"type":"string"},"seed":{"type":"integer","description":"The deterministic seed pinned into the run."},"margin_pp":{"type":"number","description":"The pre-registered non-inferiority margin Δ (pp)."},"cost_min_savings":{"type":"number","nullable":true,"description":"The pre-registered COST BAR: the minimum per-item cost-savings fraction a candidate must clear for its cost gate to pass, SNAPSHOTTED at enqueue. The verdict reads THIS pinned value, never the live config. Null on pre-v3 legacy specs (the cost bar arrived at RunSpec v3)."},"item_count":{"type":"integer","description":"The number of frozen golden items."},"population_weights":{"type":"string"},"task_clusters":{"type":"string"},"billing_assumptions":{"type":"string"},"hypothesis":{"type":"object","properties":{"kind":{"type":"string"},"margin_pp":{"type":"number"},"cost_min_savings":{"type":"number","nullable":true,"description":"The pinned cost-savings bar inside the pre-registered decision hypothesis. Null on pre-v3 legacy specs (the cost bar arrived at RunSpec v3)."},"quality_floor":{"type":"number","nullable":true,"description":"The pinned EMISSION quality floor snapshotted at enqueue from the eval config `recommendation_quality_floor`. Null = not configured (the emission default applies) / a legacy spec that predates this field."},"latency_slo_ms":{"type":"number","nullable":true,"description":"The pinned latency SLO (ms) snapshotted at enqueue from the eval config `latency_slo_ms`. Null = the latency gate is off / a legacy spec that predates this field."}},"required":["kind","margin_pp","cost_min_savings","quality_floor","latency_slo_ms"]},"incumbent":{"type":"object","nullable":true,"properties":{"alias":{"type":"string","description":"The requested logical model id (the mutable alias)."},"model":{"type":"string","description":"The resolved logical model id."},"provider":{"type":"string","description":"The serving provider slug."},"provider_id":{"type":"string","description":"The concrete versioned provider row id."},"custom":{"type":"boolean","description":"Whether this is a workspace custom-provider offer."},"input_micro_usd_per_1m":{"type":"number","description":"Input price snapshot (micro-USD / 1M tokens)."},"output_micro_usd_per_1m":{"type":"number","description":"Output price snapshot (micro-USD / 1M tokens)."}},"required":["alias","model","provider","provider_id","custom","input_micro_usd_per_1m","output_micro_usd_per_1m"],"description":"A resolved offer identity + price snapshot (the alias resolved at enqueue)."},"candidates":{"type":"array","items":{"type":"object","properties":{"alias":{"type":"string","description":"The requested logical model id (the mutable alias)."},"model":{"type":"string","description":"The resolved logical model id."},"provider":{"type":"string","description":"The serving provider slug."},"provider_id":{"type":"string","description":"The concrete versioned provider row id."},"custom":{"type":"boolean","description":"Whether this is a workspace custom-provider offer."},"input_micro_usd_per_1m":{"type":"number","description":"Input price snapshot (micro-USD / 1M tokens)."},"output_micro_usd_per_1m":{"type":"number","description":"Output price snapshot (micro-USD / 1M tokens)."}},"required":["alias","model","provider","provider_id","custom","input_micro_usd_per_1m","output_micro_usd_per_1m"],"description":"A resolved offer identity + price snapshot (the alias resolved at enqueue)."}},"profile":{"type":"object","properties":{"cee_schema_version":{"type":"string"},"harness_version":{"type":"string"},"mode":{"type":"string","description":"Paired execution mode: `request` (paired counterfactual) or `task`."},"runner_mode":{"type":"string"},"prompt_template":{"type":"string"},"parameters":{"type":"object","additionalProperties":{"nullable":true}},"tools":{"type":"string"},"context_policy":{"type":"string"},"compression_policy":{"type":"string"},"routing_policy":{"type":"string"},"retry_policy":{"type":"string"},"fallback_policy":{"type":"string"},"cache_policy":{"type":"string"},"batch_policy":{"type":"string"},"service_tier":{"type":"string"},"task_outcome_adapter":{"type":"string"},"evaluator_suite":{"type":"object","properties":{"family":{"type":"string"},"scorers":{"type":"array","items":{"type":"string"}},"weights":{"type":"object","additionalProperties":{"type":"number"}},"composite_margin":{"type":"number"},"embedding_model":{"type":"string","nullable":true},"judge_disabled":{"type":"boolean","nullable":true,"description":"Whether the pinned run retires the secondary judge phase; null means a legacy v1-v3 RunSpec did not pin this decision."},"suite_hash":{"type":"string","nullable":true,"description":"Content address of the compiled evaluator suite; null for legacy or non-compiler-authored suites."},"scorer_instances":{"type":"array","nullable":true,"items":{"type":"object","properties":{"key":{"type":"string","description":"The stable instance address: the scorer id, or `id#<hash>` when configured."},"id":{"type":"string","description":"The scorer id backing this instance."},"config":{"type":"object","additionalProperties":{"nullable":true},"description":"The instance `scorer_config` (may be empty)."},"weight":{"type":"number","description":"The instance relative composite weight (the composite normalizes)."},"hard":{"type":"boolean","description":"Whether a failure on this instance HARD-fails the candidate on that item."}},"required":["key","id","config","weight","hard"],"description":"A pinned scorer instance in the evaluator ruler."},"description":"The pinned per-scorer INSTANCE ruler the run grades on; null on a legacy (v1-v4) RunSpec or a non-instance suite."},"contract_digest":{"type":"string","nullable":true,"description":"The evaluator-contract content digest backing the suite qualification (activation barrier); null on a legacy RunSpec or when not yet available."},"qualification_provenance":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"The evaluator-suite qualification provenance (activation barrier); null on a legacy RunSpec or when not yet available."},"judge_dominant":{"type":"boolean","nullable":true,"description":"Whether the pinned evaluator suite is judge-dominant (its deterministic tiers do not cover the applicable risks); a judge-dominant ruler can never certify a migration. Null on a legacy RunSpec that predates this field or when no persisted suite matched at enqueue."},"judge":{"type":"object","properties":{"tier_a_model":{"type":"string"},"tier_b_model":{"type":"string"},"prompt_version":{"type":"string","description":"The judge-prompt template version pinned into the run."},"pass_threshold":{"type":"number"},"weight":{"type":"number"},"length_penalty_enabled":{"type":"boolean"},"panel":{"type":"boolean"},"panel_models":{"type":"array","items":{"type":"string"}},"rubric_family":{"type":"string","nullable":true,"description":"The pinned effective judge-rubric family the judge phase grades on; null on a legacy (v1-v4) RunSpec that pinned no family and falls back to the live rubric."}},"required":["tier_a_model","tier_b_model","prompt_version","pass_threshold","weight","length_penalty_enabled","panel","panel_models","rubric_family"],"description":"The pinned judge suite."}},"required":["family","scorers","weights","composite_margin","embedding_model","judge_disabled","suite_hash","scorer_instances","contract_digest","qualification_provenance","judge_dominant","judge"],"description":"The pinned evaluator suite."}},"required":["cee_schema_version","harness_version","mode","runner_mode","prompt_template","parameters","tools","context_policy","compression_policy","routing_policy","retry_policy","fallback_policy","cache_policy","batch_policy","service_tier","task_outcome_adapter","evaluator_suite"],"description":"The immutable ExecutionProfile."}},"required":["integrity_refused","run_spec_id","spec_hash","profile_hash","spec_version","stage","seed","margin_pp","cost_min_savings","item_count","population_weights","task_clusters","billing_assumptions","hypothesis","incumbent","candidates","profile"],"description":"The immutable RunSpec + ExecutionProfile components."},"RunSpecIntegrityRefused":{"type":"object","properties":{"integrity_refused":{"type":"boolean","enum":[true],"description":"Always true — this run’s stored spec FAILED its content-address integrity check."},"run_spec_id":{"type":"string","description":"The immutable RunSpec id (`rspec_…`)."},"spec_hash":{"type":"string","description":"The persisted run-spec content hash (the expected content address)."},"profile_hash":{"type":"string","description":"The persisted ExecutionProfile content hash."},"tamper_class":{"type":"string","description":"The machine-readable observed drift: `spec_version` (nulled/lowered specVersion) | `hash_mismatch` (a pinned component was edited) | `malformed` (a structurally broken spec — a nulled evaluator suite / deleted items / deleted candidates / a non-object spec)."}},"required":["integrity_refused","run_spec_id","spec_hash","profile_hash","tamper_class"],"description":"An integrity-refused RunSpec stub: the stored spec failed its content-address check."},"EvalRunListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"The eval run id (`evr_…`)."},"stage":{"type":"string"},"trigger":{"type":"string"},"status":{"type":"string"},"item_count":{"type":"integer"},"created_at":{"type":"string"},"finished_at":{"type":"string","nullable":true},"judge":{"type":"object","properties":{"tier_a_model":{"type":"string","nullable":true},"tier_b_model":{"type":"string","nullable":true},"judged_pairs":{"type":"integer"},"escalated_pairs":{"type":"integer"},"escalation_rate":{"type":"number"},"judge_cost_usd":{"type":"number"}},"required":["tier_a_model","tier_b_model","judged_pairs","escalated_pairs","escalation_rate","judge_cost_usd"],"description":"Judge cascade bookkeeping."},"run_spec":{"oneOf":[{"type":"object","properties":{"integrity_refused":{"type":"boolean","enum":[false],"description":"Always false on a verified RunSpec (the integrity-refused stub carries true)."},"run_spec_id":{"type":"string","description":"The immutable RunSpec id (`rspec_…`)."},"spec_hash":{"type":"string","description":"The run-spec content hash (the dedupe key)."},"profile_hash":{"type":"string","description":"The ExecutionProfile content hash."},"spec_version":{"type":"integer"},"stage":{"type":"string"},"seed":{"type":"integer","description":"The deterministic seed pinned into the run."},"margin_pp":{"type":"number","description":"The pre-registered non-inferiority margin Δ (pp)."},"cost_min_savings":{"type":"number","nullable":true,"description":"The pre-registered COST BAR: the minimum per-item cost-savings fraction a candidate must clear for its cost gate to pass, SNAPSHOTTED at enqueue. The verdict reads THIS pinned value, never the live config. Null on pre-v3 legacy specs (the cost bar arrived at RunSpec v3)."},"item_count":{"type":"integer","description":"The number of frozen golden items."},"population_weights":{"type":"string"},"task_clusters":{"type":"string"},"billing_assumptions":{"type":"string"},"hypothesis":{"type":"object","properties":{"kind":{"type":"string"},"margin_pp":{"type":"number"},"cost_min_savings":{"type":"number","nullable":true,"description":"The pinned cost-savings bar inside the pre-registered decision hypothesis. Null on pre-v3 legacy specs (the cost bar arrived at RunSpec v3)."},"quality_floor":{"type":"number","nullable":true,"description":"The pinned EMISSION quality floor snapshotted at enqueue from the eval config `recommendation_quality_floor`. Null = not configured (the emission default applies) / a legacy spec that predates this field."},"latency_slo_ms":{"type":"number","nullable":true,"description":"The pinned latency SLO (ms) snapshotted at enqueue from the eval config `latency_slo_ms`. Null = the latency gate is off / a legacy spec that predates this field."}},"required":["kind","margin_pp","cost_min_savings","quality_floor","latency_slo_ms"]},"incumbent":{"type":"object","nullable":true,"properties":{"alias":{"type":"string","description":"The requested logical model id (the mutable alias)."},"model":{"type":"string","description":"The resolved logical model id."},"provider":{"type":"string","description":"The serving provider slug."},"provider_id":{"type":"string","description":"The concrete versioned provider row id."},"custom":{"type":"boolean","description":"Whether this is a workspace custom-provider offer."},"input_micro_usd_per_1m":{"type":"number","description":"Input price snapshot (micro-USD / 1M tokens)."},"output_micro_usd_per_1m":{"type":"number","description":"Output price snapshot (micro-USD / 1M tokens)."}},"required":["alias","model","provider","provider_id","custom","input_micro_usd_per_1m","output_micro_usd_per_1m"],"description":"A resolved offer identity + price snapshot (the alias resolved at enqueue)."},"candidates":{"type":"array","items":{"type":"object","properties":{"alias":{"type":"string","description":"The requested logical model id (the mutable alias)."},"model":{"type":"string","description":"The resolved logical model id."},"provider":{"type":"string","description":"The serving provider slug."},"provider_id":{"type":"string","description":"The concrete versioned provider row id."},"custom":{"type":"boolean","description":"Whether this is a workspace custom-provider offer."},"input_micro_usd_per_1m":{"type":"number","description":"Input price snapshot (micro-USD / 1M tokens)."},"output_micro_usd_per_1m":{"type":"number","description":"Output price snapshot (micro-USD / 1M tokens)."}},"required":["alias","model","provider","provider_id","custom","input_micro_usd_per_1m","output_micro_usd_per_1m"],"description":"A resolved offer identity + price snapshot (the alias resolved at enqueue)."}},"profile":{"type":"object","properties":{"cee_schema_version":{"type":"string"},"harness_version":{"type":"string"},"mode":{"type":"string","description":"Paired execution mode: `request` (paired counterfactual) or `task`."},"runner_mode":{"type":"string"},"prompt_template":{"type":"string"},"parameters":{"type":"object","additionalProperties":{"nullable":true}},"tools":{"type":"string"},"context_policy":{"type":"string"},"compression_policy":{"type":"string"},"routing_policy":{"type":"string"},"retry_policy":{"type":"string"},"fallback_policy":{"type":"string"},"cache_policy":{"type":"string"},"batch_policy":{"type":"string"},"service_tier":{"type":"string"},"task_outcome_adapter":{"type":"string"},"evaluator_suite":{"type":"object","properties":{"family":{"type":"string"},"scorers":{"type":"array","items":{"type":"string"}},"weights":{"type":"object","additionalProperties":{"type":"number"}},"composite_margin":{"type":"number"},"embedding_model":{"type":"string","nullable":true},"judge_disabled":{"type":"boolean","nullable":true,"description":"Whether the pinned run retires the secondary judge phase; null means a legacy v1-v3 RunSpec did not pin this decision."},"suite_hash":{"type":"string","nullable":true,"description":"Content address of the compiled evaluator suite; null for legacy or non-compiler-authored suites."},"scorer_instances":{"type":"array","nullable":true,"items":{"type":"object","properties":{"key":{"type":"string","description":"The stable instance address: the scorer id, or `id#<hash>` when configured."},"id":{"type":"string","description":"The scorer id backing this instance."},"config":{"type":"object","additionalProperties":{"nullable":true},"description":"The instance `scorer_config` (may be empty)."},"weight":{"type":"number","description":"The instance relative composite weight (the composite normalizes)."},"hard":{"type":"boolean","description":"Whether a failure on this instance HARD-fails the candidate on that item."}},"required":["key","id","config","weight","hard"],"description":"A pinned scorer instance in the evaluator ruler."},"description":"The pinned per-scorer INSTANCE ruler the run grades on; null on a legacy (v1-v4) RunSpec or a non-instance suite."},"contract_digest":{"type":"string","nullable":true,"description":"The evaluator-contract content digest backing the suite qualification (activation barrier); null on a legacy RunSpec or when not yet available."},"qualification_provenance":{"type":"object","nullable":true,"additionalProperties":{"nullable":true},"description":"The evaluator-suite qualification provenance (activation barrier); null on a legacy RunSpec or when not yet available."},"judge_dominant":{"type":"boolean","nullable":true,"description":"Whether the pinned evaluator suite is judge-dominant (its deterministic tiers do not cover the applicable risks); a judge-dominant ruler can never certify a migration. Null on a legacy RunSpec that predates this field or when no persisted suite matched at enqueue."},"judge":{"type":"object","properties":{"tier_a_model":{"type":"string"},"tier_b_model":{"type":"string"},"prompt_version":{"type":"string","description":"The judge-prompt template version pinned into the run."},"pass_threshold":{"type":"number"},"weight":{"type":"number"},"length_penalty_enabled":{"type":"boolean"},"panel":{"type":"boolean"},"panel_models":{"type":"array","items":{"type":"string"}},"rubric_family":{"type":"string","nullable":true,"description":"The pinned effective judge-rubric family the judge phase grades on; null on a legacy (v1-v4) RunSpec that pinned no family and falls back to the live rubric."}},"required":["tier_a_model","tier_b_model","prompt_version","pass_threshold","weight","length_penalty_enabled","panel","panel_models","rubric_family"],"description":"The pinned judge suite."}},"required":["family","scorers","weights","composite_margin","embedding_model","judge_disabled","suite_hash","scorer_instances","contract_digest","qualification_provenance","judge_dominant","judge"],"description":"The pinned evaluator suite."}},"required":["cee_schema_version","harness_version","mode","runner_mode","prompt_template","parameters","tools","context_policy","compression_policy","routing_policy","retry_policy","fallback_policy","cache_policy","batch_policy","service_tier","task_outcome_adapter","evaluator_suite"],"description":"The immutable ExecutionProfile."}},"required":["integrity_refused","run_spec_id","spec_hash","profile_hash","spec_version","stage","seed","margin_pp","cost_min_savings","item_count","population_weights","task_clusters","billing_assumptions","hypothesis","incumbent","candidates","profile"],"description":"The immutable RunSpec + ExecutionProfile components."},{"type":"object","properties":{"integrity_refused":{"type":"boolean","enum":[true],"description":"Always true — this run’s stored spec FAILED its content-address integrity check."},"run_spec_id":{"type":"string","description":"The immutable RunSpec id (`rspec_…`)."},"spec_hash":{"type":"string","description":"The persisted run-spec content hash (the expected content address)."},"profile_hash":{"type":"string","description":"The persisted ExecutionProfile content hash."},"tamper_class":{"type":"string","description":"The machine-readable observed drift: `spec_version` (nulled/lowered specVersion) | `hash_mismatch` (a pinned component was edited) | `malformed` (a structurally broken spec — a nulled evaluator suite / deleted items / deleted candidates / a non-object spec)."}},"required":["integrity_refused","run_spec_id","spec_hash","profile_hash","tamper_class"],"description":"An integrity-refused RunSpec stub: the stored spec failed its content-address check."}],"description":"The immutable RunSpec pinning this run; null on legacy runs. A run whose stored spec FAILED its content-address integrity check renders as the integrity-refused stub (`integrity_refused: true` + `tamper_class`), NEVER as authoritative evidence.","nullable":true},"candidates":{"type":"array","items":{"type":"object","properties":{"model":{"type":"string"},"provider":{"type":"string"},"composite_score":{"type":"number","nullable":true},"judge_score":{"type":"number","nullable":true},"passed":{"type":"boolean","nullable":true},"skipped":{"type":"boolean"},"skip_reason":{"type":"string","nullable":true},"is_incumbent":{"type":"boolean"},"cost_evidence_id":{"type":"string","nullable":true,"description":"This arm’s immutable cost-evidence record id (the incumbent arm carries one too now that it is re-invoked + charged); null when the arm was skipped or on a legacy run."},"usage_basis":{"type":"string","nullable":true,"description":"The arm’s folded usage basis (`provider_reported` … `estimated`)."}},"required":["model","provider","composite_score","judge_score","passed","skipped","skip_reason","is_incumbent","cost_evidence_id","usage_basis"],"description":"A candidate aggregate on an eval run."}}},"required":["id","stage","trigger","status","item_count","created_at","finished_at","judge","run_spec","candidates"],"description":"One eval run + its RunSpec + candidate summaries."}}},"required":["object","data"],"description":"A call type's eval runs, each exposing its immutable RunSpec."},"WorkspaceSummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"configVersion":{"type":"integer","description":"Monotonic config version (bumped on every config or key change)."},"createdAt":{"type":"string"},"deletedAt":{"type":"string","nullable":true,"description":"Soft-delete timestamp, or null."}},"required":["id","name","slug","configVersion","createdAt","deletedAt"],"description":"A workspace summary."},"WorkspaceEnvelope":{"type":"object","properties":{"workspace":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"configVersion":{"type":"integer","description":"Monotonic config version (bumped on every config or key change)."},"createdAt":{"type":"string"},"deletedAt":{"type":"string","nullable":true,"description":"Soft-delete timestamp, or null."}},"required":["id","name","slug","configVersion","createdAt","deletedAt"],"description":"A workspace summary."}},"required":["workspace"],"description":"A single workspace."},"MemberSummary":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","description":"owner | admin | developer | billing | member."},"createdAt":{"type":"string"}},"required":["userId","role","createdAt"],"description":"A workspace member."},"MembersListResponse":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","description":"owner | admin | developer | billing | member."},"createdAt":{"type":"string"}},"required":["userId","role","createdAt"],"description":"A workspace member."}}},"required":["members"],"description":"The workspace members."},"MemberEnvelope":{"type":"object","properties":{"member":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","description":"owner | admin | developer | billing | member."},"createdAt":{"type":"string"}},"required":["userId","role","createdAt"],"description":"A workspace member."}},"required":["member"],"description":"A single membership."},"MembershipEnvelope":{"type":"object","properties":{"membership":{"type":"object","properties":{"userId":{"type":"string"},"role":{"type":"string","description":"owner | admin | developer | billing | member."},"createdAt":{"type":"string"}},"required":["userId","role","createdAt"],"description":"A workspace member."}},"required":["membership"],"description":"The membership created by accepting an invitation."},"InvitationSummary":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string"},"expiresAt":{"type":"string"},"acceptedAt":{"type":"string","nullable":true}},"required":["email","role","expiresAt","acceptedAt"],"description":"A workspace invitation (the raw token is never returned — only mailed)."},"InvitationEnvelope":{"type":"object","properties":{"invitation":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string"},"expiresAt":{"type":"string"},"acceptedAt":{"type":"string","nullable":true}},"required":["email","role","expiresAt","acceptedAt"],"description":"A workspace invitation (the raw token is never returned — only mailed)."}},"required":["invitation"],"description":"A single invitation."},"InvitationsListResponse":{"type":"object","properties":{"invitations":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"role":{"type":"string"},"expiresAt":{"type":"string"},"acceptedAt":{"type":"string","nullable":true}},"required":["email","role","expiresAt","acceptedAt"],"description":"A workspace invitation (the raw token is never returned — only mailed)."}}},"required":["invitations"],"description":"The workspace invitations."},"ApiKeySummary":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"Display prefix (`ur_sk_<mode>_` + 8 chars) — safe to show."},"mode":{"type":"string","description":"live | test."},"scopes":{"type":"array","items":{"type":"string"}},"spendCapMicroUsd":{"type":"integer","nullable":true},"rpsLimit":{"type":"integer","nullable":true},"benchSuiteDefault":{"type":"string","nullable":true,"description":"Zero-header bench capture default suite (test keys only); null ⇒ unset."},"defaultCallTypeId":{"type":"string","nullable":true,"description":"The key’s default call type id — attributed to a request that carries no `call_type`/`X-UR-Call-Type`; null ⇒ no default."},"expiresAt":{"type":"string","nullable":true},"lastUsedAt":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"revokedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","name","prefix","mode","scopes","spendCapMicroUsd","rpsLimit","benchSuiteDefault","defaultCallTypeId","expiresAt","lastUsedAt","metadata","revokedAt","createdAt"],"description":"An API key summary (secret-free)."},"IssuedApiKeyResponse":{"type":"object","properties":{"api_key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"Display prefix (`ur_sk_<mode>_` + 8 chars) — safe to show."},"mode":{"type":"string","description":"live | test."},"scopes":{"type":"array","items":{"type":"string"}},"spendCapMicroUsd":{"type":"integer","nullable":true},"rpsLimit":{"type":"integer","nullable":true},"benchSuiteDefault":{"type":"string","nullable":true,"description":"Zero-header bench capture default suite (test keys only); null ⇒ unset."},"defaultCallTypeId":{"type":"string","nullable":true,"description":"The key’s default call type id — attributed to a request that carries no `call_type`/`X-UR-Call-Type`; null ⇒ no default."},"expiresAt":{"type":"string","nullable":true},"lastUsedAt":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"revokedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","name","prefix","mode","scopes","spendCapMicroUsd","rpsLimit","benchSuiteDefault","defaultCallTypeId","expiresAt","lastUsedAt","metadata","revokedAt","createdAt"],"description":"An API key summary (secret-free)."},"secret":{"type":"string","description":"The raw `ur_sk_*` bearer secret — returned exactly once, here, never persisted."}},"required":["api_key","secret"],"description":"A newly created or rolled API key (secret shown once)."},"ApiKeysListResponse":{"type":"object","properties":{"api_keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"Display prefix (`ur_sk_<mode>_` + 8 chars) — safe to show."},"mode":{"type":"string","description":"live | test."},"scopes":{"type":"array","items":{"type":"string"}},"spendCapMicroUsd":{"type":"integer","nullable":true},"rpsLimit":{"type":"integer","nullable":true},"benchSuiteDefault":{"type":"string","nullable":true,"description":"Zero-header bench capture default suite (test keys only); null ⇒ unset."},"defaultCallTypeId":{"type":"string","nullable":true,"description":"The key’s default call type id — attributed to a request that carries no `call_type`/`X-UR-Call-Type`; null ⇒ no default."},"expiresAt":{"type":"string","nullable":true},"lastUsedAt":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"revokedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","name","prefix","mode","scopes","spendCapMicroUsd","rpsLimit","benchSuiteDefault","defaultCallTypeId","expiresAt","lastUsedAt","metadata","revokedAt","createdAt"],"description":"An API key summary (secret-free)."}}},"required":["api_keys"],"description":"The workspace API keys."},"ProviderKeySummary":{"type":"object","properties":{"id":{"type":"string"},"providerId":{"type":"string"},"name":{"type":"string"},"last4":{"type":"string","description":"Last 4 chars of the secret — the only key material ever returned."},"priority":{"type":"integer","description":"Ascending; lower is tried first."},"weight":{"type":"integer","description":"Weighted spread among equal-priority keys."},"byokFallback":{"type":"boolean","description":"Allow platform-key fallback when this key fails."},"healthStatus":{"type":"string","description":"unknown | healthy | unhealthy (save-time + hourly probe)."},"checkedAt":{"type":"string","nullable":true},"disabledAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","providerId","name","last4","priority","weight","byokFallback","healthStatus","checkedAt","disabledAt","createdAt"],"description":"A BYOK provider key summary (write-only secret — never returned)."},"ProviderKeyEnvelope":{"type":"object","properties":{"provider_key":{"type":"object","properties":{"id":{"type":"string"},"providerId":{"type":"string"},"name":{"type":"string"},"last4":{"type":"string","description":"Last 4 chars of the secret — the only key material ever returned."},"priority":{"type":"integer","description":"Ascending; lower is tried first."},"weight":{"type":"integer","description":"Weighted spread among equal-priority keys."},"byokFallback":{"type":"boolean","description":"Allow platform-key fallback when this key fails."},"healthStatus":{"type":"string","description":"unknown | healthy | unhealthy (save-time + hourly probe)."},"checkedAt":{"type":"string","nullable":true},"disabledAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","providerId","name","last4","priority","weight","byokFallback","healthStatus","checkedAt","disabledAt","createdAt"],"description":"A BYOK provider key summary (write-only secret — never returned)."}},"required":["provider_key"],"description":"A single provider key."},"ProviderKeysListResponse":{"type":"object","properties":{"provider_keys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"providerId":{"type":"string"},"name":{"type":"string"},"last4":{"type":"string","description":"Last 4 chars of the secret — the only key material ever returned."},"priority":{"type":"integer","description":"Ascending; lower is tried first."},"weight":{"type":"integer","description":"Weighted spread among equal-priority keys."},"byokFallback":{"type":"boolean","description":"Allow platform-key fallback when this key fails."},"healthStatus":{"type":"string","description":"unknown | healthy | unhealthy (save-time + hourly probe)."},"checkedAt":{"type":"string","nullable":true},"disabledAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","providerId","name","last4","priority","weight","byokFallback","healthStatus","checkedAt","disabledAt","createdAt"],"description":"A BYOK provider key summary (write-only secret — never returned)."}}},"required":["provider_keys"],"description":"The workspace provider keys."},"CustomProviderSummary":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"baseUrl":{"type":"string","nullable":true,"description":"OpenAI-compatible base URL (SSRF-validated: private and internal network targets are refused)."},"active":{"type":"boolean"},"openaiCompatible":{"type":"boolean"},"authTemplate":{"type":"object","nullable":true,"properties":{"header":{"type":"string"},"valueTemplate":{"type":"string"}},"required":["header","valueTemplate"],"description":"Auth header template rendered with the decrypted secret (`{{secret}}`)."},"modelIds":{"type":"array","items":{"type":"string"},"description":"Routing offers exposed by this provider."},"pricing":{"type":"object","nullable":true,"properties":{"input":{"type":"number"},"output":{"type":"number"},"cached":{"type":"number","nullable":true}},"required":["input","output","cached"],"description":"Manual per-1M micro-USD pricing."},"extraHeaders":{"type":"object","additionalProperties":{"type":"string"}},"tlsVerify":{"type":"boolean"},"dataPolicy":{"type":"string","nullable":true,"description":"'strict' (ZDR) | 'open' | null."},"throughputRank":{"type":"integer","nullable":true},"capabilities":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Declared capability flags: tools/json_schema/vision/streaming/embeddings. The router refuses (pre-dispatch) an offer that does not declare a capability the request needs."},"createdAt":{"type":"string"}},"required":["id","slug","name","baseUrl","active","openaiCompatible","authTemplate","modelIds","pricing","extraHeaders","tlsVerify","dataPolicy","throughputRank","capabilities","createdAt"],"description":"A custom provider summary."},"CustomProviderEnvelope":{"type":"object","properties":{"provider":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"baseUrl":{"type":"string","nullable":true,"description":"OpenAI-compatible base URL (SSRF-validated: private and internal network targets are refused)."},"active":{"type":"boolean"},"openaiCompatible":{"type":"boolean"},"authTemplate":{"type":"object","nullable":true,"properties":{"header":{"type":"string"},"valueTemplate":{"type":"string"}},"required":["header","valueTemplate"],"description":"Auth header template rendered with the decrypted secret (`{{secret}}`)."},"modelIds":{"type":"array","items":{"type":"string"},"description":"Routing offers exposed by this provider."},"pricing":{"type":"object","nullable":true,"properties":{"input":{"type":"number"},"output":{"type":"number"},"cached":{"type":"number","nullable":true}},"required":["input","output","cached"],"description":"Manual per-1M micro-USD pricing."},"extraHeaders":{"type":"object","additionalProperties":{"type":"string"}},"tlsVerify":{"type":"boolean"},"dataPolicy":{"type":"string","nullable":true,"description":"'strict' (ZDR) | 'open' | null."},"throughputRank":{"type":"integer","nullable":true},"capabilities":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Declared capability flags: tools/json_schema/vision/streaming/embeddings. The router refuses (pre-dispatch) an offer that does not declare a capability the request needs."},"createdAt":{"type":"string"}},"required":["id","slug","name","baseUrl","active","openaiCompatible","authTemplate","modelIds","pricing","extraHeaders","tlsVerify","dataPolicy","throughputRank","capabilities","createdAt"],"description":"A custom provider summary."}},"required":["provider"],"description":"A single custom provider."},"CustomProvidersListResponse":{"type":"object","properties":{"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"name":{"type":"string"},"baseUrl":{"type":"string","nullable":true,"description":"OpenAI-compatible base URL (SSRF-validated: private and internal network targets are refused)."},"active":{"type":"boolean"},"openaiCompatible":{"type":"boolean"},"authTemplate":{"type":"object","nullable":true,"properties":{"header":{"type":"string"},"valueTemplate":{"type":"string"}},"required":["header","valueTemplate"],"description":"Auth header template rendered with the decrypted secret (`{{secret}}`)."},"modelIds":{"type":"array","items":{"type":"string"},"description":"Routing offers exposed by this provider."},"pricing":{"type":"object","nullable":true,"properties":{"input":{"type":"number"},"output":{"type":"number"},"cached":{"type":"number","nullable":true}},"required":["input","output","cached"],"description":"Manual per-1M micro-USD pricing."},"extraHeaders":{"type":"object","additionalProperties":{"type":"string"}},"tlsVerify":{"type":"boolean"},"dataPolicy":{"type":"string","nullable":true,"description":"'strict' (ZDR) | 'open' | null."},"throughputRank":{"type":"integer","nullable":true},"capabilities":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Declared capability flags: tools/json_schema/vision/streaming/embeddings. The router refuses (pre-dispatch) an offer that does not declare a capability the request needs."},"createdAt":{"type":"string"}},"required":["id","slug","name","baseUrl","active","openaiCompatible","authTemplate","modelIds","pricing","extraHeaders","tlsVerify","dataPolicy","throughputRank","capabilities","createdAt"],"description":"A custom provider summary."}}},"required":["providers"],"description":"The workspace custom providers."},"OkResponse":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]}},"required":["ok"],"description":"A no-content success acknowledgement."},"EchoResponse":{"type":"object","properties":{"workspace_id":{"type":"string"},"key_prefix":{"type":"string"},"mode":{"type":"string"},"request_id":{"type":"string"}},"required":["workspace_id","key_prefix","mode","request_id"],"description":"The API-key-auth smoke echo (proves key auth + the versioned cache)."},"HealthResponse":{"type":"object","properties":{"status":{"type":"string","description":"ok | ready | not_ready."},"checks":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Per-dependency readiness (readyz only)."}},"required":["status"],"description":"An ops health probe result."},"CompanyKnowledgeItem":{"oneOf":[{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["lesson"]},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"]},"lesson_id":{"type":"string"},"version_id":{"type":"string"},"version":{"type":"integer"},"parent_version_id":{"type":"string","nullable":true},"recipe":{"type":"string"},"text":{"type":"string"},"retired":{"type":"boolean"},"retired_reason":{"type":"string","nullable":true},"helpful":{"type":"number"},"harmful":{"type":"number"},"meta":{"type":"object","nullable":true,"properties":{"schema":{"type":"string","enum":["ela1"]},"kind":{"type":"string","enum":["general","tool_fact","procedure"]},"conditions":{"type":"array","items":{"type":"string"}},"exceptions":{"type":"array","items":{"type":"string"}},"requiredTools":{"type":"array","items":{"type":"string"}},"capabilityUnknown":{"type":"boolean"},"scope":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"protocol":{"type":"string","enum":["native","text_api"]},"fingerprints":{"type":"array","items":{"type":"string"}}},"required":["tool","protocol","fingerprints"]}},"supersedes":{"type":"array","items":{"type":"string"}},"admission":{"type":"object","properties":{"policy":{"type":"string"},"disposition":{"type":"string"}},"required":["policy","disposition"]}}},"evidence":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"evidence_count":{"type":"integer"},"evidence_truncated":{"type":"boolean","description":"At most 100 citation metadata entries are returned per lesson."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","lesson_id","version_id","version","parent_version_id","recipe","text","retired","retired_reason","helpful","harmful","meta","evidence","evidence_count","evidence_truncated"]},{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["fact"]},"state":{"type":"string","enum":["current","history"]},"fact_id":{"type":"string"},"fact_kind":{"type":"string"},"description":{"type":"string","description":"Derived type description, not customer source text."},"scope":{"type":"object","additionalProperties":{"type":"string"}},"evidence_tier":{"type":"string"},"n":{"type":"number"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"clusters":{"type":"number"},"window_start":{"type":"string","nullable":true},"window_end":{"type":"string","nullable":true},"superseded_by":{"type":"string","nullable":true},"lineage":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"content_projection":{"type":"string","enum":["derived_statistics"],"description":"Raw fact bodies, correction exemplars and source transcripts are excluded."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","fact_id","fact_kind","description","scope","evidence_tier","n","rate","interval","clusters","window_start","window_end","superseded_by","lineage","content_projection"]}]},"CompanyKnowledgeListResponse":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["lesson"]},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"]},"lesson_id":{"type":"string"},"version_id":{"type":"string"},"version":{"type":"integer"},"parent_version_id":{"type":"string","nullable":true},"recipe":{"type":"string"},"text":{"type":"string"},"retired":{"type":"boolean"},"retired_reason":{"type":"string","nullable":true},"helpful":{"type":"number"},"harmful":{"type":"number"},"meta":{"type":"object","nullable":true,"properties":{"schema":{"type":"string","enum":["ela1"]},"kind":{"type":"string","enum":["general","tool_fact","procedure"]},"conditions":{"type":"array","items":{"type":"string"}},"exceptions":{"type":"array","items":{"type":"string"}},"requiredTools":{"type":"array","items":{"type":"string"}},"capabilityUnknown":{"type":"boolean"},"scope":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"protocol":{"type":"string","enum":["native","text_api"]},"fingerprints":{"type":"array","items":{"type":"string"}}},"required":["tool","protocol","fingerprints"]}},"supersedes":{"type":"array","items":{"type":"string"}},"admission":{"type":"object","properties":{"policy":{"type":"string"},"disposition":{"type":"string"}},"required":["policy","disposition"]}}},"evidence":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"evidence_count":{"type":"integer"},"evidence_truncated":{"type":"boolean","description":"At most 100 citation metadata entries are returned per lesson."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","lesson_id","version_id","version","parent_version_id","recipe","text","retired","retired_reason","helpful","harmful","meta","evidence","evidence_count","evidence_truncated"]},{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["fact"]},"state":{"type":"string","enum":["current","history"]},"fact_id":{"type":"string"},"fact_kind":{"type":"string"},"description":{"type":"string","description":"Derived type description, not customer source text."},"scope":{"type":"object","additionalProperties":{"type":"string"}},"evidence_tier":{"type":"string"},"n":{"type":"number"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"clusters":{"type":"number"},"window_start":{"type":"string","nullable":true},"window_end":{"type":"string","nullable":true},"superseded_by":{"type":"string","nullable":true},"lineage":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"content_projection":{"type":"string","enum":["derived_statistics"],"description":"Raw fact bodies, correction exemplars and source transcripts are excluded."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","fact_id","fact_kind","description","scope","evidence_tier","n","rate","interval","clusters","window_start","window_end","superseded_by","lineage","content_projection"]}]}},"has_more":{"type":"boolean"},"next_cursor":{"type":"string","nullable":true},"snapshot_at":{"type":"string"}},"required":["object","data","has_more","next_cursor","snapshot_at"]},"CompanyKnowledgeDetailResponse":{"type":"object","properties":{"object":{"type":"string","enum":["knowledge_item"]},"item":{"oneOf":[{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["lesson"]},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"]},"lesson_id":{"type":"string"},"version_id":{"type":"string"},"version":{"type":"integer"},"parent_version_id":{"type":"string","nullable":true},"recipe":{"type":"string"},"text":{"type":"string"},"retired":{"type":"boolean"},"retired_reason":{"type":"string","nullable":true},"helpful":{"type":"number"},"harmful":{"type":"number"},"meta":{"type":"object","nullable":true,"properties":{"schema":{"type":"string","enum":["ela1"]},"kind":{"type":"string","enum":["general","tool_fact","procedure"]},"conditions":{"type":"array","items":{"type":"string"}},"exceptions":{"type":"array","items":{"type":"string"}},"requiredTools":{"type":"array","items":{"type":"string"}},"capabilityUnknown":{"type":"boolean"},"scope":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"protocol":{"type":"string","enum":["native","text_api"]},"fingerprints":{"type":"array","items":{"type":"string"}}},"required":["tool","protocol","fingerprints"]}},"supersedes":{"type":"array","items":{"type":"string"}},"admission":{"type":"object","properties":{"policy":{"type":"string"},"disposition":{"type":"string"}},"required":["policy","disposition"]}}},"evidence":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"evidence_count":{"type":"integer"},"evidence_truncated":{"type":"boolean","description":"At most 100 citation metadata entries are returned per lesson."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","lesson_id","version_id","version","parent_version_id","recipe","text","retired","retired_reason","helpful","harmful","meta","evidence","evidence_count","evidence_truncated"]},{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["fact"]},"state":{"type":"string","enum":["current","history"]},"fact_id":{"type":"string"},"fact_kind":{"type":"string"},"description":{"type":"string","description":"Derived type description, not customer source text."},"scope":{"type":"object","additionalProperties":{"type":"string"}},"evidence_tier":{"type":"string"},"n":{"type":"number"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"clusters":{"type":"number"},"window_start":{"type":"string","nullable":true},"window_end":{"type":"string","nullable":true},"superseded_by":{"type":"string","nullable":true},"lineage":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"content_projection":{"type":"string","enum":["derived_statistics"],"description":"Raw fact bodies, correction exemplars and source transcripts are excluded."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","fact_id","fact_kind","description","scope","evidence_tier","n","rate","interval","clusters","window_start","window_end","superseded_by","lineage","content_projection"]}]}},"required":["object","item"]},"CompanyKnowledgeExportResponse":{"type":"object","properties":{"object":{"type":"string","enum":["company_knowledge_export"]},"selection":{"type":"object","properties":{"q":{"type":"string","nullable":true},"kind":{"type":"string","nullable":true,"enum":["lesson","fact"]},"call_type_id":{"type":"string","nullable":true},"version_id":{"type":"string","nullable":true},"include_history":{"type":"boolean"},"limit":{"type":"integer"}},"required":["q","kind","call_type_id","version_id","include_history","limit"]},"schema":{"type":"string","enum":["ur.company_knowledge/v1"]},"workspace_id":{"type":"string"},"generated_at":{"type":"string"},"snapshot_at":{"type":"string"},"content_hash":{"type":"string"},"data":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["lesson"]},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"]},"lesson_id":{"type":"string"},"version_id":{"type":"string"},"version":{"type":"integer"},"parent_version_id":{"type":"string","nullable":true},"recipe":{"type":"string"},"text":{"type":"string"},"retired":{"type":"boolean"},"retired_reason":{"type":"string","nullable":true},"helpful":{"type":"number"},"harmful":{"type":"number"},"meta":{"type":"object","nullable":true,"properties":{"schema":{"type":"string","enum":["ela1"]},"kind":{"type":"string","enum":["general","tool_fact","procedure"]},"conditions":{"type":"array","items":{"type":"string"}},"exceptions":{"type":"array","items":{"type":"string"}},"requiredTools":{"type":"array","items":{"type":"string"}},"capabilityUnknown":{"type":"boolean"},"scope":{"type":"array","items":{"type":"object","properties":{"tool":{"type":"string"},"protocol":{"type":"string","enum":["native","text_api"]},"fingerprints":{"type":"array","items":{"type":"string"}}},"required":["tool","protocol","fingerprints"]}},"supersedes":{"type":"array","items":{"type":"string"}},"admission":{"type":"object","properties":{"policy":{"type":"string"},"disposition":{"type":"string"}},"required":["policy","disposition"]}}},"evidence":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"evidence_count":{"type":"integer"},"evidence_truncated":{"type":"boolean","description":"At most 100 citation metadata entries are returned per lesson."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","lesson_id","version_id","version","parent_version_id","recipe","text","retired","retired_reason","helpful","harmful","meta","evidence","evidence_count","evidence_truncated"]},{"type":"object","properties":{"id":{"type":"string","maxLength":450,"pattern":"^(?:fact:[A-Za-z0-9_-]+|lesson:[A-Za-z0-9_-]+:L[0-9]+)$"},"call_type_id":{"type":"string","nullable":true},"created_at":{"type":"string"},"content_hash":{"type":"string"},"current":{"type":"boolean","description":"In the current knowledge view; candidates can be current without being active."},"active":{"type":"boolean","description":"For lessons, belongs to the incumbent version and is not retired. Does not claim every request serves it."},"kind":{"type":"string","enum":["fact"]},"state":{"type":"string","enum":["current","history"]},"fact_id":{"type":"string"},"fact_kind":{"type":"string"},"description":{"type":"string","description":"Derived type description, not customer source text."},"scope":{"type":"object","additionalProperties":{"type":"string"}},"evidence_tier":{"type":"string"},"n":{"type":"number"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"clusters":{"type":"number"},"window_start":{"type":"string","nullable":true},"window_end":{"type":"string","nullable":true},"superseded_by":{"type":"string","nullable":true},"lineage":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string"},"id":{"type":"string"},"availability":{"type":"string","enum":["available","unavailable","not_checked"]},"outcome":{"type":"string","nullable":true,"enum":["pass","fail"]},"verified_at":{"type":"string","nullable":true}},"required":["kind","id","availability","outcome","verified_at"]}},"content_projection":{"type":"string","enum":["derived_statistics"],"description":"Raw fact bodies, correction exemplars and source transcripts are excluded."}},"required":["id","call_type_id","created_at","content_hash","current","active","kind","state","fact_id","fact_kind","description","scope","evidence_tier","n","rate","interval","clusters","window_start","window_end","superseded_by","lineage","content_projection"]}]}},"complete":{"type":"boolean","description":"This page contains every item matching selection, not necessarily the whole workspace. Continuation pages are fragments."},"truncated":{"type":"boolean"},"next_cursor":{"type":"string","nullable":true},"exclusions":{"type":"array","items":{"type":"string"}}},"required":["object","selection","schema","workspace_id","generated_at","snapshot_at","content_hash","data","complete","truncated","next_cursor","exclusions"]},"LearningPromotionPolicy":{"type":"object","properties":{"mode":{"type":"string","enum":["evaluate","manual","immediate"],"description":"`evaluate`: a candidate must win a prospective randomized evaluation against the incumbent under a rule frozen when the evaluation starts; it serves a randomized share of eligible episodes during that comparison. `manual`: a candidate waits for an owner/admin promote or reject. `immediate`: publication is activation (the legacy behaviour)."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment closes when BOTH arms have this many enrolled episodes (default 30); the selected episodes are then frozen and their verified outcomes are awaited."},"max_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment also closes when EITHER arm reaches this many enrolled episodes; each frozen arm contains at most this many (default 200)."},"alpha":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":0.5,"exclusiveMaximum":true,"description":"One-sided significance level of the interval on the difference (default 0.05)."},"min_effect_pp":{"type":"number","minimum":0,"maximum":100,"description":"`success`: the minimum point improvement in percentage points (default 0)."},"noninferiority_margin_pp":{"type":"number","minimum":0,"maximum":100,"description":"`cost_noninferior`: the success non-inferiority margin in percentage points (default 5)."},"candidate_share":{"type":"number","minimum":0.01,"maximum":0.99,"description":"The share of NEW enrolled episodes assigned the candidate while enrollment is open (default 0.5). After enrollment closes, new episodes use the active version while selected episodes finish."},"max_duration_hours":{"type":"integer","minimum":1,"maximum":8760,"description":"The fixed deadline from evaluation start, including time to receive selected outcomes (default 720). Incomplete evidence cannot promote a candidate; the deadline never resets."}},"required":["mode","objective","min_verified_per_arm","max_verified_per_arm","alpha","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours"],"description":"The promotion policy. Defaults: evaluate / success / enrollment thresholds 30–200 episodes per arm / one-sided alpha 0.05 / 0 pp minimum effect / 5 pp margin / 0.5 candidate share / 720 h. Changeable before an evaluation starts; a running evaluation keeps the rule it froze."},"EnableLearningRequest":{"type":"object","properties":{"reflection_model":{"type":"string","minLength":1,"maxLength":200,"description":"The model the learner reflects with. It must resolve to a WORKSPACE-OWNED offer — one of the workspace’s custom providers, or a catalog provider the workspace stored its own key for. A platform-keyed model is refused; there is no paid fallback."},"lessons_mode":{"type":"string","enum":["only","with_precedents"],"description":"`only` (default): serve the learned lessons; `with_precedents`: lessons first, then similar verified past episodes."},"lessons_k":{"type":"integer","minimum":1,"maximum":20,"description":"Lessons served per episode (1..20; default 8)."},"promotion":{"type":"object","properties":{"mode":{"type":"string","enum":["evaluate","manual","immediate"],"description":"`evaluate`: a candidate must win a prospective randomized evaluation against the incumbent under a rule frozen when the evaluation starts; it serves a randomized share of eligible episodes during that comparison. `manual`: a candidate waits for an owner/admin promote or reject. `immediate`: publication is activation (the legacy behaviour)."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment closes when BOTH arms have this many enrolled episodes (default 30); the selected episodes are then frozen and their verified outcomes are awaited."},"max_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment also closes when EITHER arm reaches this many enrolled episodes; each frozen arm contains at most this many (default 200)."},"alpha":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":0.5,"exclusiveMaximum":true,"description":"One-sided significance level of the interval on the difference (default 0.05)."},"min_effect_pp":{"type":"number","minimum":0,"maximum":100,"description":"`success`: the minimum point improvement in percentage points (default 0)."},"noninferiority_margin_pp":{"type":"number","minimum":0,"maximum":100,"description":"`cost_noninferior`: the success non-inferiority margin in percentage points (default 5)."},"candidate_share":{"type":"number","minimum":0.01,"maximum":0.99,"description":"The share of NEW enrolled episodes assigned the candidate while enrollment is open (default 0.5). After enrollment closes, new episodes use the active version while selected episodes finish."},"max_duration_hours":{"type":"integer","minimum":1,"maximum":8760,"description":"The fixed deadline from evaluation start, including time to receive selected outcomes (default 720). Incomplete evidence cannot promote a candidate; the deadline never resets."}},"description":"Promotion-policy changes, merged over the current policy (or the defaults)."},"recipe":{"type":"object","properties":{"validator":{"type":"string","enum":["elv1","elv2"],"description":"Lesson admission: `elv1` (legacy literal rule, the default) or `elv2` (provenance-aware: evidence support + value handling, documented constants scoped to their tool)."},"generation":{"type":"string","enum":["bundled","atomic"],"description":"Lesson generation: `bundled` (legacy, the default) or `atomic` (one complete rule per item with conditions, exceptions and required tools; never clipped)."},"observations":{"type":"string","enum":["legacy","elo2"],"description":"Observation selection: `legacy` (the default) or `elo2` (error→correction transitions, passed-case results and labelled user turns at the same total budget, with measured omissions)."}},"additionalProperties":false,"description":"The learner recipe the reflection runs — its validator, lesson generation and observation selection, each optional (an absent field is the legacy value). Stored on the call type’s episode-memory setting, the ONE place the recipe lives. Omitted: the call type keeps its current recipe (the legacy learner when it has none)."}},"required":["reflection_model"],"description":"Enable learning for a call type (owner/admin session or a `config:write` key)."},"LearningVersion":{"type":"object","properties":{"object":{"type":"string","enum":["learning_version"]},"id":{"type":"string","description":"The immutable version id (`epb_…`)."},"version":{"type":"integer"},"parent_id":{"type":"string","nullable":true},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"state_reason":{"type":"string","nullable":true,"description":"Why it entered its state (a bounded code); null when the state is derived."},"state_since":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"evaluation_id":{"type":"string","nullable":true,"description":"The evaluation that set the state, if any."},"digest":{"type":"string","description":"A content address of the version’s active lessons (`epb1_…`)."},"recipe":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."},"active_lessons":{"type":"integer","minimum":0},"cohort":{"type":"object","properties":{"size":{"type":"integer","minimum":0},"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0}},"required":["size","pass","fail"],"description":"The verified episodes the version was learned from."},"reflection_model":{"type":"string","nullable":true}},"required":["object","id","version","parent_id","state","state_reason","state_since","evaluation_id","digest","recipe","created_at","active_lessons","cohort","reflection_model"],"description":"A learned playbook version."},"LearningVersionDetail":{"type":"object","properties":{"object":{"type":"string","enum":["learning_version"]},"id":{"type":"string","description":"The immutable version id (`epb_…`)."},"version":{"type":"integer"},"parent_id":{"type":"string","nullable":true},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"state_reason":{"type":"string","nullable":true,"description":"Why it entered its state (a bounded code); null when the state is derived."},"state_since":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"evaluation_id":{"type":"string","nullable":true,"description":"The evaluation that set the state, if any."},"digest":{"type":"string","description":"A content address of the version’s active lessons (`epb1_…`)."},"recipe":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."},"active_lessons":{"type":"integer","minimum":0},"cohort":{"type":"object","properties":{"size":{"type":"integer","minimum":0},"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0}},"required":["size","pass","fail"],"description":"The verified episodes the version was learned from."},"reflection_model":{"type":"string","nullable":true},"lessons":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"text":{"type":"string"},"evidence_cases":{"type":"integer","minimum":0}},"required":["id","text","evidence_cases"]},"description":"The version’s active lessons, in served-ranking order input."},"retired_lessons":{"type":"integer","minimum":0},"known_functions":{"type":"integer","minimum":0},"distiller":{"type":"object","properties":{"provider":{"type":"string","nullable":true},"model":{"type":"string","nullable":true},"request_hash":{"type":"string","nullable":true},"response_hash":{"type":"string","nullable":true},"input_tokens":{"type":"integer","nullable":true},"output_tokens":{"type":"integer","nullable":true}},"required":["provider","model","request_hash","response_hash","input_tokens","output_tokens"],"description":"The body-free reflection receipt (hashes and token counts only)."},"transitions":{"type":"array","items":{"type":"object","properties":{"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"reason":{"type":"string"},"evaluation_id":{"type":"string","nullable":true},"actor_type":{"type":"string","enum":["system","user","api_key"]},"actor_id":{"type":"string","nullable":true},"at":{"type":"string","description":"ISO 8601 instant."}},"required":["state","reason","evaluation_id","actor_type","actor_id","at"]},"description":"Every recorded state transition, oldest first."}},"required":["object","id","version","parent_id","state","state_reason","state_since","evaluation_id","digest","recipe","created_at","active_lessons","cohort","reflection_model","lessons","retired_lessons","known_functions","distiller","transitions"],"description":"One version’s lessons and provenance summary."},"LearningEvaluation":{"type":"object","properties":{"object":{"type":"string","enum":["learning_evaluation"]},"id":{"type":"string","description":"`lev_…`"},"call_type_id":{"type":"string"},"candidate_version_id":{"type":"string"},"incumbent_version_id":{"type":"string","nullable":true,"description":"Null: the candidate is compared with serving no lessons."},"decision":{"type":"string","enum":["running","promoted","retained","inconclusive","rejected","stopped_budget","stopped_manual"],"description":"Every decision except `promoted` keeps the incumbent."},"decision_reason":{"type":"string"},"rule":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"lpr2 freezes enrollment before waiting for outcomes; lpr1 identifies historical verified-only rules."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer"},"max_verified_per_arm":{"type":"integer"},"alpha_one_sided":{"type":"number"},"min_effect_pp":{"type":"number"},"noninferiority_margin_pp":{"type":"number"},"candidate_share":{"type":"number"},"max_duration_hours":{"type":"integer"},"interval":{"type":"string","description":"`newcombe_hybrid_score`."},"outcome_source":{"type":"string","description":"`verified_teaching_episode`."}},"required":["rule_version","objective","min_verified_per_arm","max_verified_per_arm","alpha_one_sided","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours","interval","outcome_source"],"description":"The decision rule frozen when the evaluation started. lpr2 selects episodes before inspecting their outcomes, freezes one cohort, and makes one decision only from complete selected outcomes or the fixed deadline."},"rule_hash":{"type":"string","description":"`lrh1_…` content address of the frozen rule."},"arms":{"type":"object","properties":{"candidate":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]},"incumbent":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]}},"required":["candidate","incumbent"]},"difference":{"type":"object","nullable":true,"properties":{"point":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"}},"required":["point","lower","upper"],"description":"candidate − incumbent success (a fraction) with one-sided bounds at the frozen alpha; null until both arms have a verified episode."},"started_at":{"type":"string","description":"ISO 8601 instant."},"decided_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"decided_by":{"type":"object","nullable":true,"properties":{"type":{"type":"string","enum":["system","user","api_key"]},"id":{"type":"string","nullable":true}},"required":["type","id"]}},"required":["object","id","call_type_id","candidate_version_id","incumbent_version_id","decision","decision_reason","rule","rule_hash","arms","difference","started_at","decided_at","decided_by"],"description":"A prospective randomized evaluation of a candidate against the incumbent."},"LearningStatus":{"type":"object","properties":{"object":{"type":"string","enum":["learning"]},"call_type_id":{"type":"string"},"config_version":{"type":"integer","nullable":true},"state":{"type":"string","enum":["off","collecting","learning","paused","disabled","unavailable","quota_exhausted","budget_exhausted"],"description":"`collecting` (enabled, waiting for evidence), `learning` (a reflection is due or an evaluation runs), `paused`, `disabled` (the kill switch), `unavailable` (consent, provider or repeated failures), `quota_exhausted` / `budget_exhausted` (refused for resources — retried with backoff), `off`."},"reason":{"type":"string","description":"A bounded code explaining the state."},"enabled":{"type":"boolean","description":"Lessons are switched on for the call type."},"self_serve":{"type":"boolean","description":"Enabled through this API (not a staff-granted study)."},"governed":{"type":"boolean","description":"Uses a configured promotion policy. In evaluate mode, candidates receive a randomized share of eligible episodes before any active-version change."},"paused":{"type":"boolean"},"recipe":{"type":"object","nullable":true,"properties":{"validator":{"type":"string","enum":["elv1","elv2"]},"generation":{"type":"string","enum":["bundled","atomic"]},"observations":{"type":"string","enum":["legacy","elo2"]},"legacy":{"type":"boolean","description":"All three are the legacy values (the original learner)."}},"required":["validator","generation","observations","legacy"],"description":"The learner recipe the next reflection runs, read from the call type’s episode-memory setting (the one place it lives); null when the call type has no explicit setting."},"reflection":{"type":"object","properties":{"model":{"type":"string","nullable":true},"provider":{"type":"object","properties":{"available":{"type":"boolean"},"reason":{"type":"string","nullable":true,"description":"Why it is unavailable: `no_reflection_model`, `no_offer`, `platform_offer_only`, `no_workspace_key`, `model_denied_by_policy`."},"ownership":{"type":"string","nullable":true,"enum":["custom","byok","platform"]},"provider_slug":{"type":"string","nullable":true}},"required":["available","reason","ownership","provider_slug"]},"last_attempt_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"last_attempt_status":{"type":"string","nullable":true},"last_attempt_reason":{"type":"string","nullable":true},"last_published_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"next":{"type":"object","properties":{"will_run":{"type":"boolean"},"reason":{"type":"string"},"retry_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"min_episodes":{"type":"integer"},"idle_minutes":{"type":"integer"}},"required":["will_run","reason","retry_at","min_episodes","idle_minutes"],"description":"Whether the next server reflection scan will reflect, and why (not)."}},"required":["model","provider","last_attempt_at","last_attempt_status","last_attempt_reason","last_published_at","next"]},"promotion":{"type":"object","nullable":true,"properties":{"mode":{"type":"string","enum":["evaluate","manual","immediate"],"description":"`evaluate`: a candidate must win a prospective randomized evaluation against the incumbent under a rule frozen when the evaluation starts; it serves a randomized share of eligible episodes during that comparison. `manual`: a candidate waits for an owner/admin promote or reject. `immediate`: publication is activation (the legacy behaviour)."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment closes when BOTH arms have this many enrolled episodes (default 30); the selected episodes are then frozen and their verified outcomes are awaited."},"max_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment also closes when EITHER arm reaches this many enrolled episodes; each frozen arm contains at most this many (default 200)."},"alpha":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":0.5,"exclusiveMaximum":true,"description":"One-sided significance level of the interval on the difference (default 0.05)."},"min_effect_pp":{"type":"number","minimum":0,"maximum":100,"description":"`success`: the minimum point improvement in percentage points (default 0)."},"noninferiority_margin_pp":{"type":"number","minimum":0,"maximum":100,"description":"`cost_noninferior`: the success non-inferiority margin in percentage points (default 5)."},"candidate_share":{"type":"number","minimum":0.01,"maximum":0.99,"description":"The share of NEW enrolled episodes assigned the candidate while enrollment is open (default 0.5). After enrollment closes, new episodes use the active version while selected episodes finish."},"max_duration_hours":{"type":"integer","minimum":1,"maximum":8760,"description":"The fixed deadline from evaluation start, including time to receive selected outcomes (default 720). Incomplete evidence cannot promote a candidate; the deadline never resets."}},"required":["mode","objective","min_verified_per_arm","max_verified_per_arm","alpha","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours"],"description":"The promotion policy (null for an ungoverned study learner — its latest version serves)."},"active_version":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"version":{"type":"integer"},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"active_lessons":{"type":"integer","minimum":0},"digest":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."}},"required":["id","version","state","active_lessons","digest","created_at"],"description":"The incumbent served outside an evaluation."},"latest_candidate":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"version":{"type":"integer"},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"active_lessons":{"type":"integer","minimum":0},"digest":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."}},"required":["id","version","state","active_lessons","digest","created_at"]},"evaluation":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["learning_evaluation"]},"id":{"type":"string","description":"`lev_…`"},"call_type_id":{"type":"string"},"candidate_version_id":{"type":"string"},"incumbent_version_id":{"type":"string","nullable":true,"description":"Null: the candidate is compared with serving no lessons."},"decision":{"type":"string","enum":["running","promoted","retained","inconclusive","rejected","stopped_budget","stopped_manual"],"description":"Every decision except `promoted` keeps the incumbent."},"decision_reason":{"type":"string"},"rule":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"lpr2 freezes enrollment before waiting for outcomes; lpr1 identifies historical verified-only rules."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer"},"max_verified_per_arm":{"type":"integer"},"alpha_one_sided":{"type":"number"},"min_effect_pp":{"type":"number"},"noninferiority_margin_pp":{"type":"number"},"candidate_share":{"type":"number"},"max_duration_hours":{"type":"integer"},"interval":{"type":"string","description":"`newcombe_hybrid_score`."},"outcome_source":{"type":"string","description":"`verified_teaching_episode`."}},"required":["rule_version","objective","min_verified_per_arm","max_verified_per_arm","alpha_one_sided","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours","interval","outcome_source"],"description":"The decision rule frozen when the evaluation started. lpr2 selects episodes before inspecting their outcomes, freezes one cohort, and makes one decision only from complete selected outcomes or the fixed deadline."},"rule_hash":{"type":"string","description":"`lrh1_…` content address of the frozen rule."},"arms":{"type":"object","properties":{"candidate":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]},"incumbent":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]}},"required":["candidate","incumbent"]},"difference":{"type":"object","nullable":true,"properties":{"point":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"}},"required":["point","lower","upper"],"description":"candidate − incumbent success (a fraction) with one-sided bounds at the frozen alpha; null until both arms have a verified episode."},"started_at":{"type":"string","description":"ISO 8601 instant."},"decided_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"decided_by":{"type":"object","nullable":true,"properties":{"type":{"type":"string","enum":["system","user","api_key"]},"id":{"type":"string","nullable":true}},"required":["type","id"]}},"required":["object","id","call_type_id","candidate_version_id","incumbent_version_id","decision","decision_reason","rule","rule_hash","arms","difference","started_at","decided_at","decided_by"],"description":"The RUNNING evaluation, if any."},"last_evaluation":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["learning_evaluation"]},"id":{"type":"string","description":"`lev_…`"},"call_type_id":{"type":"string"},"candidate_version_id":{"type":"string"},"incumbent_version_id":{"type":"string","nullable":true,"description":"Null: the candidate is compared with serving no lessons."},"decision":{"type":"string","enum":["running","promoted","retained","inconclusive","rejected","stopped_budget","stopped_manual"],"description":"Every decision except `promoted` keeps the incumbent."},"decision_reason":{"type":"string"},"rule":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"lpr2 freezes enrollment before waiting for outcomes; lpr1 identifies historical verified-only rules."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer"},"max_verified_per_arm":{"type":"integer"},"alpha_one_sided":{"type":"number"},"min_effect_pp":{"type":"number"},"noninferiority_margin_pp":{"type":"number"},"candidate_share":{"type":"number"},"max_duration_hours":{"type":"integer"},"interval":{"type":"string","description":"`newcombe_hybrid_score`."},"outcome_source":{"type":"string","description":"`verified_teaching_episode`."}},"required":["rule_version","objective","min_verified_per_arm","max_verified_per_arm","alpha_one_sided","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours","interval","outcome_source"],"description":"The decision rule frozen when the evaluation started. lpr2 selects episodes before inspecting their outcomes, freezes one cohort, and makes one decision only from complete selected outcomes or the fixed deadline."},"rule_hash":{"type":"string","description":"`lrh1_…` content address of the frozen rule."},"arms":{"type":"object","properties":{"candidate":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]},"incumbent":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]}},"required":["candidate","incumbent"]},"difference":{"type":"object","nullable":true,"properties":{"point":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"}},"required":["point","lower","upper"],"description":"candidate − incumbent success (a fraction) with one-sided bounds at the frozen alpha; null until both arms have a verified episode."},"started_at":{"type":"string","description":"ISO 8601 instant."},"decided_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"decided_by":{"type":"object","nullable":true,"properties":{"type":{"type":"string","enum":["system","user","api_key"]},"id":{"type":"string","nullable":true}},"required":["type","id"]}},"required":["object","id","call_type_id","candidate_version_id","incumbent_version_id","decision","decision_reason","rule","rule_hash","arms","difference","started_at","decided_at","decided_by"],"description":"The newest evaluation (any decision)."},"evidence":{"type":"object","properties":{"recorded":{"type":"integer","minimum":0,"description":"Episodes recorded."},"verified":{"type":"integer","minimum":0},"verified_pass":{"type":"integer","minimum":0},"verified_fail":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Recorded without a verdict — never counted as success or failure."},"consumed":{"type":"integer","minimum":0,"description":"Verified episodes the learner has reflected over (its working line)."},"incorporated_active":{"type":"integer","minimum":0,"description":"Verified episodes in the ACTIVE version’s line — arrived is not incorporated."},"backlog":{"type":"integer","minimum":0,"description":"Verified, not yet reflected over."},"pending_reflection":{"type":"integer","minimum":0},"latest_verified_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."}},"required":["recorded","verified","verified_pass","verified_fail","unknown","consumed","incorporated_active","backlog","pending_reflection","latest_verified_at"],"description":"Evidence arrived vs verified vs incorporated vs pending."},"budget":{"type":"object","properties":{"state":{"type":"string","enum":["ok","quota_exhausted","budget_exhausted"]},"consecutive_refusals":{"type":"integer","minimum":0},"last_refusal_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"failures_since_reset":{"type":"integer","minimum":0},"failure_ceiling":{"type":"integer"}},"required":["state","consecutive_refusals","last_refusal_at","failures_since_reset","failure_ceiling"]},"usage":{"type":"object","properties":{"reflections":{"type":"integer","minimum":0},"failed_calls":{"type":"integer","minimum":0},"input_tokens":{"type":"integer","minimum":0},"output_tokens":{"type":"integer","minimum":0},"cash_micro_usd":{"type":"integer","minimum":0}},"required":["reflections","failed_calls","input_tokens","output_tokens","cash_micro_usd"],"description":"Subscription / token usage, recorded separately from cash."},"outcome_receipts":{"type":"object","properties":{"pending":{"type":"integer","minimum":0,"description":"Accepted, waiting for the request to be recorded."},"applied":{"type":"integer","minimum":0,"description":"Recorded against the request."},"rejected":{"type":"integer","minimum":0,"description":"Refused (validation or conflict)."},"failed":{"type":"integer","minimum":0,"description":"Given up after repeated database errors while applying."},"expired":{"type":"integer","minimum":0,"description":"The request was never recorded within the receipt’s time limit."},"episode_pending":{"type":"integer","minimum":0,"description":"Applied teaching outcomes still waiting for their episode to be recorded."}},"required":["pending","applied","rejected","failed","expired","episode_pending"],"description":"Outcome receipts (`POST /v1/requests/{id}/outcomes`) attributed to this call type’s requests, by state: a receipt counts once its request or its episode has been recorded for the call type. Settled receipts are counted until they are purged (30 days)."}},"required":["object","call_type_id","config_version","state","reason","enabled","self_serve","governed","paused","recipe","reflection","promotion","active_version","latest_candidate","evaluation","last_evaluation","evidence","budget","usage","outcome_receipts"],"description":"A call type’s learning status."},"LearningControlResponse":{"type":"object","properties":{"object":{"type":"string","enum":["learning_control"]},"action":{"type":"string","enum":["enable","pause","resume","disable","rollback","promote","reject"]},"call_type_id":{"type":"string"},"changed":{"type":"boolean","description":"False when the control was already in effect (idempotent)."},"version_id":{"type":"string","nullable":true,"description":"The version a rollback / promote / reject acted on."},"stopped_evaluation_id":{"type":"string","nullable":true,"description":"A running evaluation the control stopped (`stopped_manual`)."},"learning":{"type":"object","properties":{"object":{"type":"string","enum":["learning"]},"call_type_id":{"type":"string"},"config_version":{"type":"integer","nullable":true},"state":{"type":"string","enum":["off","collecting","learning","paused","disabled","unavailable","quota_exhausted","budget_exhausted"],"description":"`collecting` (enabled, waiting for evidence), `learning` (a reflection is due or an evaluation runs), `paused`, `disabled` (the kill switch), `unavailable` (consent, provider or repeated failures), `quota_exhausted` / `budget_exhausted` (refused for resources — retried with backoff), `off`."},"reason":{"type":"string","description":"A bounded code explaining the state."},"enabled":{"type":"boolean","description":"Lessons are switched on for the call type."},"self_serve":{"type":"boolean","description":"Enabled through this API (not a staff-granted study)."},"governed":{"type":"boolean","description":"Uses a configured promotion policy. In evaluate mode, candidates receive a randomized share of eligible episodes before any active-version change."},"paused":{"type":"boolean"},"recipe":{"type":"object","nullable":true,"properties":{"validator":{"type":"string","enum":["elv1","elv2"]},"generation":{"type":"string","enum":["bundled","atomic"]},"observations":{"type":"string","enum":["legacy","elo2"]},"legacy":{"type":"boolean","description":"All three are the legacy values (the original learner)."}},"required":["validator","generation","observations","legacy"],"description":"The learner recipe the next reflection runs, read from the call type’s episode-memory setting (the one place it lives); null when the call type has no explicit setting."},"reflection":{"type":"object","properties":{"model":{"type":"string","nullable":true},"provider":{"type":"object","properties":{"available":{"type":"boolean"},"reason":{"type":"string","nullable":true,"description":"Why it is unavailable: `no_reflection_model`, `no_offer`, `platform_offer_only`, `no_workspace_key`, `model_denied_by_policy`."},"ownership":{"type":"string","nullable":true,"enum":["custom","byok","platform"]},"provider_slug":{"type":"string","nullable":true}},"required":["available","reason","ownership","provider_slug"]},"last_attempt_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"last_attempt_status":{"type":"string","nullable":true},"last_attempt_reason":{"type":"string","nullable":true},"last_published_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"next":{"type":"object","properties":{"will_run":{"type":"boolean"},"reason":{"type":"string"},"retry_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"min_episodes":{"type":"integer"},"idle_minutes":{"type":"integer"}},"required":["will_run","reason","retry_at","min_episodes","idle_minutes"],"description":"Whether the next server reflection scan will reflect, and why (not)."}},"required":["model","provider","last_attempt_at","last_attempt_status","last_attempt_reason","last_published_at","next"]},"promotion":{"type":"object","nullable":true,"properties":{"mode":{"type":"string","enum":["evaluate","manual","immediate"],"description":"`evaluate`: a candidate must win a prospective randomized evaluation against the incumbent under a rule frozen when the evaluation starts; it serves a randomized share of eligible episodes during that comparison. `manual`: a candidate waits for an owner/admin promote or reject. `immediate`: publication is activation (the legacy behaviour)."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment closes when BOTH arms have this many enrolled episodes (default 30); the selected episodes are then frozen and their verified outcomes are awaited."},"max_verified_per_arm":{"type":"integer","minimum":1,"maximum":5000,"description":"Compatibility field name. Under lpr2, enrollment also closes when EITHER arm reaches this many enrolled episodes; each frozen arm contains at most this many (default 200)."},"alpha":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":0.5,"exclusiveMaximum":true,"description":"One-sided significance level of the interval on the difference (default 0.05)."},"min_effect_pp":{"type":"number","minimum":0,"maximum":100,"description":"`success`: the minimum point improvement in percentage points (default 0)."},"noninferiority_margin_pp":{"type":"number","minimum":0,"maximum":100,"description":"`cost_noninferior`: the success non-inferiority margin in percentage points (default 5)."},"candidate_share":{"type":"number","minimum":0.01,"maximum":0.99,"description":"The share of NEW enrolled episodes assigned the candidate while enrollment is open (default 0.5). After enrollment closes, new episodes use the active version while selected episodes finish."},"max_duration_hours":{"type":"integer","minimum":1,"maximum":8760,"description":"The fixed deadline from evaluation start, including time to receive selected outcomes (default 720). Incomplete evidence cannot promote a candidate; the deadline never resets."}},"required":["mode","objective","min_verified_per_arm","max_verified_per_arm","alpha","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours"],"description":"The promotion policy (null for an ungoverned study learner — its latest version serves)."},"active_version":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"version":{"type":"integer"},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"active_lessons":{"type":"integer","minimum":0},"digest":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."}},"required":["id","version","state","active_lessons","digest","created_at"],"description":"The incumbent served outside an evaluation."},"latest_candidate":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"version":{"type":"integer"},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"active_lessons":{"type":"integer","minimum":0},"digest":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."}},"required":["id","version","state","active_lessons","digest","created_at"]},"evaluation":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["learning_evaluation"]},"id":{"type":"string","description":"`lev_…`"},"call_type_id":{"type":"string"},"candidate_version_id":{"type":"string"},"incumbent_version_id":{"type":"string","nullable":true,"description":"Null: the candidate is compared with serving no lessons."},"decision":{"type":"string","enum":["running","promoted","retained","inconclusive","rejected","stopped_budget","stopped_manual"],"description":"Every decision except `promoted` keeps the incumbent."},"decision_reason":{"type":"string"},"rule":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"lpr2 freezes enrollment before waiting for outcomes; lpr1 identifies historical verified-only rules."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer"},"max_verified_per_arm":{"type":"integer"},"alpha_one_sided":{"type":"number"},"min_effect_pp":{"type":"number"},"noninferiority_margin_pp":{"type":"number"},"candidate_share":{"type":"number"},"max_duration_hours":{"type":"integer"},"interval":{"type":"string","description":"`newcombe_hybrid_score`."},"outcome_source":{"type":"string","description":"`verified_teaching_episode`."}},"required":["rule_version","objective","min_verified_per_arm","max_verified_per_arm","alpha_one_sided","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours","interval","outcome_source"],"description":"The decision rule frozen when the evaluation started. lpr2 selects episodes before inspecting their outcomes, freezes one cohort, and makes one decision only from complete selected outcomes or the fixed deadline."},"rule_hash":{"type":"string","description":"`lrh1_…` content address of the frozen rule."},"arms":{"type":"object","properties":{"candidate":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]},"incumbent":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]}},"required":["candidate","incumbent"]},"difference":{"type":"object","nullable":true,"properties":{"point":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"}},"required":["point","lower","upper"],"description":"candidate − incumbent success (a fraction) with one-sided bounds at the frozen alpha; null until both arms have a verified episode."},"started_at":{"type":"string","description":"ISO 8601 instant."},"decided_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"decided_by":{"type":"object","nullable":true,"properties":{"type":{"type":"string","enum":["system","user","api_key"]},"id":{"type":"string","nullable":true}},"required":["type","id"]}},"required":["object","id","call_type_id","candidate_version_id","incumbent_version_id","decision","decision_reason","rule","rule_hash","arms","difference","started_at","decided_at","decided_by"],"description":"The RUNNING evaluation, if any."},"last_evaluation":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["learning_evaluation"]},"id":{"type":"string","description":"`lev_…`"},"call_type_id":{"type":"string"},"candidate_version_id":{"type":"string"},"incumbent_version_id":{"type":"string","nullable":true,"description":"Null: the candidate is compared with serving no lessons."},"decision":{"type":"string","enum":["running","promoted","retained","inconclusive","rejected","stopped_budget","stopped_manual"],"description":"Every decision except `promoted` keeps the incumbent."},"decision_reason":{"type":"string"},"rule":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"lpr2 freezes enrollment before waiting for outcomes; lpr1 identifies historical verified-only rules."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer"},"max_verified_per_arm":{"type":"integer"},"alpha_one_sided":{"type":"number"},"min_effect_pp":{"type":"number"},"noninferiority_margin_pp":{"type":"number"},"candidate_share":{"type":"number"},"max_duration_hours":{"type":"integer"},"interval":{"type":"string","description":"`newcombe_hybrid_score`."},"outcome_source":{"type":"string","description":"`verified_teaching_episode`."}},"required":["rule_version","objective","min_verified_per_arm","max_verified_per_arm","alpha_one_sided","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours","interval","outcome_source"],"description":"The decision rule frozen when the evaluation started. lpr2 selects episodes before inspecting their outcomes, freezes one cohort, and makes one decision only from complete selected outcomes or the fixed deadline."},"rule_hash":{"type":"string","description":"`lrh1_…` content address of the frozen rule."},"arms":{"type":"object","properties":{"candidate":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]},"incumbent":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]}},"required":["candidate","incumbent"]},"difference":{"type":"object","nullable":true,"properties":{"point":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"}},"required":["point","lower","upper"],"description":"candidate − incumbent success (a fraction) with one-sided bounds at the frozen alpha; null until both arms have a verified episode."},"started_at":{"type":"string","description":"ISO 8601 instant."},"decided_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"decided_by":{"type":"object","nullable":true,"properties":{"type":{"type":"string","enum":["system","user","api_key"]},"id":{"type":"string","nullable":true}},"required":["type","id"]}},"required":["object","id","call_type_id","candidate_version_id","incumbent_version_id","decision","decision_reason","rule","rule_hash","arms","difference","started_at","decided_at","decided_by"],"description":"The newest evaluation (any decision)."},"evidence":{"type":"object","properties":{"recorded":{"type":"integer","minimum":0,"description":"Episodes recorded."},"verified":{"type":"integer","minimum":0},"verified_pass":{"type":"integer","minimum":0},"verified_fail":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Recorded without a verdict — never counted as success or failure."},"consumed":{"type":"integer","minimum":0,"description":"Verified episodes the learner has reflected over (its working line)."},"incorporated_active":{"type":"integer","minimum":0,"description":"Verified episodes in the ACTIVE version’s line — arrived is not incorporated."},"backlog":{"type":"integer","minimum":0,"description":"Verified, not yet reflected over."},"pending_reflection":{"type":"integer","minimum":0},"latest_verified_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."}},"required":["recorded","verified","verified_pass","verified_fail","unknown","consumed","incorporated_active","backlog","pending_reflection","latest_verified_at"],"description":"Evidence arrived vs verified vs incorporated vs pending."},"budget":{"type":"object","properties":{"state":{"type":"string","enum":["ok","quota_exhausted","budget_exhausted"]},"consecutive_refusals":{"type":"integer","minimum":0},"last_refusal_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"failures_since_reset":{"type":"integer","minimum":0},"failure_ceiling":{"type":"integer"}},"required":["state","consecutive_refusals","last_refusal_at","failures_since_reset","failure_ceiling"]},"usage":{"type":"object","properties":{"reflections":{"type":"integer","minimum":0},"failed_calls":{"type":"integer","minimum":0},"input_tokens":{"type":"integer","minimum":0},"output_tokens":{"type":"integer","minimum":0},"cash_micro_usd":{"type":"integer","minimum":0}},"required":["reflections","failed_calls","input_tokens","output_tokens","cash_micro_usd"],"description":"Subscription / token usage, recorded separately from cash."},"outcome_receipts":{"type":"object","properties":{"pending":{"type":"integer","minimum":0,"description":"Accepted, waiting for the request to be recorded."},"applied":{"type":"integer","minimum":0,"description":"Recorded against the request."},"rejected":{"type":"integer","minimum":0,"description":"Refused (validation or conflict)."},"failed":{"type":"integer","minimum":0,"description":"Given up after repeated database errors while applying."},"expired":{"type":"integer","minimum":0,"description":"The request was never recorded within the receipt’s time limit."},"episode_pending":{"type":"integer","minimum":0,"description":"Applied teaching outcomes still waiting for their episode to be recorded."}},"required":["pending","applied","rejected","failed","expired","episode_pending"],"description":"Outcome receipts (`POST /v1/requests/{id}/outcomes`) attributed to this call type’s requests, by state: a receipt counts once its request or its episode has been recorded for the call type. Settled receipts are counted until they are purged (30 days)."}},"required":["object","call_type_id","config_version","state","reason","enabled","self_serve","governed","paused","recipe","reflection","promotion","active_version","latest_candidate","evaluation","last_evaluation","evidence","budget","usage","outcome_receipts"],"description":"A call type’s learning status."}},"required":["object","action","call_type_id","changed","version_id","stopped_evaluation_id","learning"],"description":"The result of a learning control."}},"parameters":{}},"paths":{"/v1/workspaces/{id}/adaptive-rollouts/activate":{"post":{"operationId":"activateAdaptiveRollout","tags":["Adaptive optimization"],"summary":"Activate an independently qualified full policy","security":[{"sessionCookie":[]}],"description":"Requires an owner or admin session with two-factor authentication, current explicit Automatic authorization, a valid independent qualification certificate, and a registered serving adapter. Starts at a root-sticky 1% canary. Unavailable prerequisites do not change serving.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"certificateId":{"type":"string","pattern":"^aqc_[a-f0-9]{64}$"},"applicationId":{"type":"string","minLength":1,"maxLength":256},"expectedAuthorizationVersion":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["certificateId","applicationId","expectedAuthorizationVersion"],"additionalProperties":false}}}},"responses":{"200":{"description":"Activation or a named unavailable prerequisite.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"status":{"type":"string","enum":["active"]},"rolloutId":{"type":"string","pattern":"^apr_[a-f0-9]{64}$"}},"required":["status","rolloutId"],"additionalProperties":false},{"type":"object","properties":{"status":{"type":"string","enum":["unavailable"]},"reason":{"type":"string"}},"required":["status","reason"],"additionalProperties":false}]}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/adaptive-rollouts/revoke":{"post":{"operationId":"revokeAdaptiveRollout","tags":["Adaptive optimization"],"summary":"Revoke a full-policy rollout","security":[{"sessionCookie":[]}],"description":"Requires an owner or admin session with two-factor authentication. Future decisions preserve the original request after revocation. The action is audited and idempotent.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"rolloutId":{"type":"string","pattern":"^apr_[a-f0-9]{64}$"}},"required":["rolloutId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Revoked or already inactive.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["revoked","not_active"]}},"required":["status"],"additionalProperties":false}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/billing/account":{"get":{"operationId":"getPrepaidAccount","tags":["Billing"],"summary":"Read real credit and noncash evaluation balances","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"Balances, selected funding mode, Pro state and whether checkout is configured.","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"billingVersion":{"type":"string","enum":["prepaid-2026-10"]},"fundingMode":{"type":"string","enum":["ur_credits","byok"]},"allowPlatformFallback":{"type":"boolean"},"frozen":{"type":"boolean"},"balanceMicroUsd":{"type":"integer"},"reservedCreditMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"unresolvedCreditMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"availableCreditMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"plan":{"type":"string","enum":["starter","pro"]},"evaluationAllowanceMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"evaluationReservedMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"pendingWaiver":{"type":"boolean"},"paymentConfigured":{"type":"boolean"}},"required":["billingVersion","fundingMode","allowPlatformFallback","frozen","balanceMicroUsd","reservedCreditMicroUsd","unresolvedCreditMicroUsd","availableCreditMicroUsd","plan","evaluationAllowanceMicroUsd","evaluationReservedMicroUsd","pendingWaiver","paymentConfigured"],"additionalProperties":false},{"type":"object","properties":{"billingVersion":{"type":"string","enum":["legacy"]},"plan":{"type":"string","enum":["starter","pro"]},"evaluationAllowanceMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"evaluationReservedMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"pendingWaiver":{"type":"boolean"},"paymentConfigured":{"type":"boolean"}},"required":["billingVersion","plan","evaluationAllowanceMicroUsd","evaluationReservedMicroUsd","pendingWaiver","paymentConfigured"],"additionalProperties":false}]}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/billing/funding":{"post":{"operationId":"setPrepaidFunding","tags":["Billing"],"summary":"Choose UR credits or BYOK explicitly","security":[{"sessionCookie":[]}],"description":"Changes authorization only; does not fund credits. Platform fallback from BYOK requires explicit permission.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mode":{"type":"string","enum":["ur_credits","byok"]},"allowPlatformFallback":{"type":"boolean"},"requestKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["mode","allowPlatformFallback","requestKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"Audited funding selection.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["updated"]},"account":{"type":"object","properties":{"billingVersion":{"type":"string","enum":["prepaid-2026-10"]},"fundingMode":{"type":"string","enum":["ur_credits","byok"]},"allowPlatformFallback":{"type":"boolean"},"frozen":{"type":"boolean"},"balanceMicroUsd":{"type":"integer"},"reservedCreditMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"unresolvedCreditMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991},"availableCreditMicroUsd":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["billingVersion","fundingMode","allowPlatformFallback","frozen","balanceMicroUsd","reservedCreditMicroUsd","unresolvedCreditMicroUsd","availableCreditMicroUsd"],"additionalProperties":false}},"required":["status","account"],"additionalProperties":false}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/billing/credit-checkout":{"post":{"operationId":"createCreditCheckout","tags":["Billing"],"summary":"Purchase prepaid inference credits","security":[{"sessionCookie":[]}],"description":"Minimum credit purchase is $5. A 5.5% service fee is added once at checkout, rounded to cents. $5 credits costs $5.28. Credits are funded only by verified payment settlement, never a return URL.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"creditCents":{"type":"integer","minimum":500,"maximum":1000000},"requestKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["creditCents","requestKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"A Stripe-hosted checkout URL, not a successful payment.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["checkout_ready"]},"url":{"type":"string","format":"uri"},"checkoutId":{"type":"string"},"creditCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"feeCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"totalCents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["status","url","checkoutId","creditCents","feeCents","totalCents"],"additionalProperties":false}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/billing/pro-checkout":{"post":{"operationId":"createProCheckout","tags":["Billing"],"summary":"Start a $49 monthly Pro subscription","security":[{"sessionCookie":[]}],"description":"Includes $5 monthly noncash evaluation allowance. Duplicate pending/active purchases are refused.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"requestKey":{"type":"string","pattern":"^[A-Za-z0-9_-]{16,128}$"}},"required":["requestKey"],"additionalProperties":false}}}},"responses":{"200":{"description":"A Stripe-hosted checkout URL.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["checkout_ready"]},"url":{"type":"string","format":"uri"},"checkoutId":{"type":"string"},"creditCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"feeCents":{"type":"integer","minimum":0,"maximum":9007199254740991},"totalCents":{"type":"integer","minimum":0,"maximum":9007199254740991}},"required":["status","url","checkoutId","creditCents","feeCents","totalCents"],"additionalProperties":false}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/billing/pro-cancel":{"post":{"operationId":"cancelProRenewal","tags":["Billing"],"summary":"Cancel Pro at the paid period end","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false}}}},"responses":{"200":{"description":"Stripe verified cancellation scheduling; current paid access continues through its period.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["cancellation_scheduled"]},"cancelAtPeriodEnd":{"type":"boolean","enum":[true]}},"required":["status","cancelAtPeriodEnd"],"additionalProperties":false}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/chat/completions":{"post":{"operationId":"createChatCompletion","tags":["Chat"],"summary":"Create a chat completion","security":[{"bearerAuth":[]}],"description":"OpenAI-compatible chat completions. Set `stream:true` for OpenAI-shaped SSE: a `text/event-stream` of `chat.completion.chunk` events, a consolidated final chunk carrying `usage` + the `ur` block, then `data: [DONE]`. Requires API-key scope: gateway:invoke.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionsRequest"}}}},"responses":{"200":{"description":"The completion (or an SSE stream when `stream:true`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/embeddings":{"post":{"operationId":"createEmbeddings","tags":["Embeddings"],"summary":"Create embeddings","security":[{"bearerAuth":[]}],"description":"Multi-provider embeddings over the OpenAI Embeddings shape. Requires API-key scope: gateway:invoke.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingsRequest"}}}},"responses":{"200":{"description":"The embedding vectors + usage + the `ur` block.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/responses":{"post":{"operationId":"createResponse","tags":["Passthrough"],"summary":"Create a response (OpenAI Responses API passthrough)","security":[{"bearerAuth":[]}],"description":"Native passthrough for the OpenAI Responses API: point the official `openai` SDK at ultrarouter by changing only the base URL and the key. The JSON body is FORWARDED VERBATIM to OpenAI (no routing, no compression, no model remapping, no field injection) and the response is returned UNTOUCHED — the gateway only meters, caps and captures. `stream:true` forwards the upstream SSE bytes verbatim. The ur extensions ride request headers (`X-UR-Call-Type`, `X-UR-Timeout-Ms` clamped 1 s–600 s (default 300 s), `X-UR-Trace`); the response carries `X-UR-Request-Id` and (non-streaming) `X-UR-Cost-Micro-USD`. An allowlist of request headers (`openai-beta`, `openai-organization`, `openai-project`, `idempotency-key`) is forwarded upstream; the caller's own `Authorization` is never forwarded. Upstream errors pass through with their status and body; gateway failures (auth, caps, timeout) use the normalized error envelope. EXPERIMENT-BOUND calls: a call carrying `X-UR-Experiment-Execution` (an execution enrolled on `POST /v1/flywheel/experiments/{id}/executions`; the key also needs `flywheel:experiment:run`) is authorized against its execution, reserved against the experiment budget before dispatch and settled from the measured cost; it must send `max_output_tokens`, a call type and an `attempt` in `X-UR-Trace`. The learned pack is never placed into a Responses body (a treated lever-stage call here is refused by name). A call without the header is unaffected. Requires API-key scope: gateway:invoke.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","description":"The OpenAI model id to call (e.g. \"gpt-6-sol\"). This exact model is the model called."}},"required":["model"],"description":"OpenAI Responses API request, forwarded verbatim to OpenAI. Every field beyond `model` (input, instructions, tools, text.format, reasoning, include, store, prompt_cache_key, metadata, …) is passed through unchanged — the gateway never injects or rewrites the body."}}}},"responses":{"200":{"description":"The OpenAI Responses object (or an SSE stream when `stream:true`), returned verbatim.","content":{"application/json":{"schema":{"type":"object","properties":{},"description":"The OpenAI Responses object, returned byte-for-byte (the gateway never re-serialises it). Usage is metered from `usage` + the `web_search_call` output items; the ur request id and booked cost ride the `X-UR-Request-Id` / `X-UR-Cost-Micro-USD` response headers."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/messages":{"post":{"operationId":"createMessage","tags":["Passthrough"],"summary":"Create a message (Anthropic Messages API passthrough)","security":[{"bearerAuth":[]}],"description":"Native passthrough for the Anthropic Messages API: point the official `@anthropic-ai/sdk` at ultrarouter by changing only the base URL and the key. The ur key is accepted via `Authorization: Bearer` OR `x-api-key` (the Anthropic SDK style); the body is FORWARDED VERBATIM to Anthropic and the response is returned UNTOUCHED — the gateway only meters, caps and captures. `stream:true` forwards the upstream SSE bytes verbatim. The ur extensions ride request headers (`X-UR-Call-Type`, `X-UR-Timeout-Ms` clamped 1 s–600 s (default 300 s), `X-UR-Trace`); the response carries `X-UR-Request-Id` and (non-streaming) `X-UR-Cost-Micro-USD`. An allowlist of request headers (`anthropic-version`, `anthropic-beta`, `idempotency-key`) is forwarded upstream; the caller's own key headers are never forwarded. Upstream errors pass through with their status and body; gateway failures (auth, caps, timeout) use the normalized error envelope. EXPERIMENT-BOUND calls: a call carrying `X-UR-Experiment-Execution` (an execution enrolled on `POST /v1/flywheel/experiments/{id}/executions`; the key also needs `flywheel:experiment:run`) is authorized against its execution (workspace, live experiment, open phase, bound candidate) BEFORE dispatch, reserved against the experiment budget from `max_tokens` and the dispatched bytes, claimed once (a retry of the same `attempt` is refused) and settled from the measured cost. For the TREATED arm’s lever call type only, the frozen learned pack is placed as a NEW FIRST TEXT BLOCK of the first user message — `system` and every `cache_control` marker are untouched; other stages and the control arm are forwarded unchanged. Refusals are named in the error message. A call without the header is unaffected. Requires API-key scope: gateway:invoke.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"model":{"type":"string","description":"The Anthropic model id to call (e.g. \"claude-opus-5-5\"). This exact model is the model called."}},"required":["model"],"description":"Anthropic Messages API request, forwarded verbatim to Anthropic. Every field beyond `model` (system, messages, tools, output_config, cache_control, continuation blocks, …) is passed through unchanged. Auth may be the ur key via `Authorization: Bearer` or `x-api-key`; the caller's key is never forwarded upstream (the platform/BYOK key is injected server-side)."}}}},"responses":{"200":{"description":"The Anthropic Message object (or an SSE stream when `stream:true`), returned verbatim.","content":{"application/json":{"schema":{"type":"object","properties":{},"description":"The Anthropic Message object, returned byte-for-byte. Usage is metered from `usage` (input_tokens + cache_read_input_tokens + cache_creation_input_tokens + output_tokens); the ur request id and booked cost ride the `X-UR-Request-Id` / `X-UR-Cost-Micro-USD` headers."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/models":{"get":{"operationId":"listModels","tags":["Models"],"summary":"List the model catalog","security":[{"bearerAuth":[]}],"description":"The active model catalog with pricing + capabilities, filterable by provider/capability. Each item separates PROVENANCE from HOSTING: `origin_jurisdiction` + `weights` describe the LOGICAL model (the developing lab — an offer inherits them from the model it serves), while `hosting_jurisdiction` + `hosting_region` describe where THIS offer RUNS. A CN-origin open-weight model hosted in the US shows `origin_jurisdiction: CN`, `weights: open`, `hosting_jurisdiction: US`. Any unestablished fact is `unknown` (fail-closed). Requires API-key scope: gateway:invoke.","parameters":[{"schema":{"type":"string","description":"Filter to one provider slug."},"required":false,"description":"Filter to one provider slug.","name":"provider","in":"query"},{"schema":{"type":"string","description":"Filter to models advertising a capability (e.g. vision)."},"required":false,"description":"Filter to models advertising a capability (e.g. vision).","name":"capability","in":"query"}],"responses":{"200":{"description":"The active catalog.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelsListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/models/{id}":{"get":{"operationId":"getModel","tags":["Models"],"summary":"Get a model with its per-provider offers","security":[{"bearerAuth":[]}],"description":"Logical-model detail incl. every active provider offer. The `{id}` carries the provider-prefixed slash id (e.g. `openai/gpt-5.2`). Provenance vs hosting: top-level `origin_jurisdiction` + `weights` are the LOGICAL model's provenance; each offer carries its OWN `hosting_jurisdiction` + `hosting_region` (where that offer runs). Unestablished facts are `unknown` (fail-closed). Requires API-key scope: gateway:invoke.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The model detail with offers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModelDetailResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/generation":{"get":{"operationId":"getGeneration","tags":["Generation"],"summary":"Get post-hoc stats for one request","security":[{"bearerAuth":[]}],"description":"OpenRouter `/generation` parity — cost/tokens/timing/routing for one prior request. Requires API-key scope: gateway:invoke.","parameters":[{"schema":{"type":"string","description":"The `req_…` id to describe."},"required":true,"description":"The `req_…` id to describe.","name":"id","in":"query"}],"responses":{"200":{"description":"The post-hoc stats block.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerationStats"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/key":{"get":{"operationId":"getKey","tags":["Keys"],"summary":"Introspect the presented API key","security":[{"bearerAuth":[]}],"description":"The presented key describes itself: scopes, caps, and usage this period.","responses":{"200":{"description":"The key introspection.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/KeyIntrospection"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types":{"get":{"operationId":"listCallTypes","tags":["Call types"],"summary":"List call types","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Requires API-key scope: config:read or config:write.","responses":{"200":{"description":"The workspace call types.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTypeListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"post":{"operationId":"createCallType","tags":["Call types"],"summary":"Create a call type","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Requires API-key scope: config:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCallTypeRequest"}}}},"responses":{"201":{"description":"The created call type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTypeSummary"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}":{"get":{"operationId":"getCallType","tags":["Call types"],"summary":"Get a call type","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The call type + its active config version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTypeSummary"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"patch":{"operationId":"updateCallType","tags":["Call types"],"summary":"Update a call type config","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Writes a new immutable config version + repoints + bumps `config_version`. A partial update: a field you omit keeps its current value, and an explicit `null` clears it — so a body that only sets `learned_context_delivery` or `self_improve_mode` never changes the pin, router mode, fallbacks or provider preferences. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTypeConfigBody"}}}},"responses":{"200":{"description":"The updated call type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallTypeSummary"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/evals":{"post":{"operationId":"enqueueCallTypeEval","tags":["Call types"],"summary":"Enqueue a manual eval run","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Kicks an `eval.run` job for this call type. An optional body selects the runner mode (`request` default, or `task` for the whole-trace $/task runner). Returns 202 with the enqueued run, or 200 with a documented no-op — a dedupe (`deduped:true`) also names the prior run it deduped onto (`prior_run_id` + its `trigger`/`status`), so a client can follow it. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnqueueEvalRequest"}}}},"responses":{"202":{"description":"The enqueued eval run (202); a documented no-op is returned with 200.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnqueueEvalResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"get":{"operationId":"listCallTypeEvals","tags":["Call types"],"summary":"List eval runs","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"A call type’s eval runs, their candidate summaries, and each run’s immutable RunSpec (the pinned ExecutionProfile components). Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The eval runs, each exposing its RunSpec.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EvalRunListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/recommendations":{"get":{"operationId":"listCallTypeRecommendations","tags":["Call types"],"summary":"List routing recommendations","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Eval-backed model-migration recommendations for this call type. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The recommendations."},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/prompts":{"post":{"operationId":"createHostedPrompt","tags":["Call types"],"summary":"Create a hosted prompt version","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Append a new (immutable) hosted prompt version for this call type. The version is INACTIVE until activated; activating an older version is the rollback. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"template":{"type":"string","minLength":1,"maxLength":200000,"description":"The prompt template text (`{{name}}` variables substituted at gateway apply)."},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_]+$","description":"The `{{name}}` slot this variable fills."},"required":{"type":"boolean","default":false,"description":"Whether the caller MUST supply a value. A missing REQUIRED variable is a named `prompt_variables_missing` refusal at gateway apply (never a silent blank)."}},"required":["name"],"additionalProperties":false,"description":"A declared hosted-prompt template variable."},"maxItems":256,"description":"The declared template variables (name + required flag). Omitted ⇒ none declared."}},"required":["template"],"additionalProperties":false,"description":"Create a hosted prompt version (POST /v1/call-types/{id}/prompts)."}}}},"responses":{"201":{"description":"The created hosted prompt version.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_version"]},"id":{"type":"string"},"call_type_id":{"type":"string"},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Monotonic per call type; activating an older one rolls back."},"template":{"type":"string"},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_]+$","description":"The `{{name}}` slot this variable fills."},"required":{"type":"boolean","default":false,"description":"Whether the caller MUST supply a value. A missing REQUIRED variable is a named `prompt_variables_missing` refusal at gateway apply (never a silent blank)."}},"required":["name"],"additionalProperties":false,"description":"A declared hosted-prompt template variable."}},"content_sha256":{"type":"string","description":"sha256 of the template — its immutable byte identity."},"source":{"type":"string","enum":["human","flywheel"],"description":"`human` (written through the API) or `flywheel` (a later flywheel-proposed version)."},"created_by":{"type":"string","nullable":true},"created_at":{"type":"string"},"active":{"type":"boolean","description":"Whether this version is the call type’s currently ACTIVE hosted prompt."},"gateway_apply":{"type":"boolean","description":"Whether the gateway applies the ACTIVE version when proxying (false unless active)."}},"required":["object","id","call_type_id","version","template","variables","content_sha256","source","created_by","created_at","active","gateway_apply"],"description":"One immutable hosted prompt version."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"get":{"operationId":"listHostedPrompts","tags":["Call types"],"summary":"List hosted prompt versions","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The call type’s hosted prompt versions (newest first) + the active pointer. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The hosted prompt versions.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_version"]},"id":{"type":"string"},"call_type_id":{"type":"string"},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Monotonic per call type; activating an older one rolls back."},"template":{"type":"string"},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_]+$","description":"The `{{name}}` slot this variable fills."},"required":{"type":"boolean","default":false,"description":"Whether the caller MUST supply a value. A missing REQUIRED variable is a named `prompt_variables_missing` refusal at gateway apply (never a silent blank)."}},"required":["name"],"additionalProperties":false,"description":"A declared hosted-prompt template variable."}},"content_sha256":{"type":"string","description":"sha256 of the template — its immutable byte identity."},"source":{"type":"string","enum":["human","flywheel"],"description":"`human` (written through the API) or `flywheel` (a later flywheel-proposed version)."},"created_by":{"type":"string","nullable":true},"created_at":{"type":"string"},"active":{"type":"boolean","description":"Whether this version is the call type’s currently ACTIVE hosted prompt."},"gateway_apply":{"type":"boolean","description":"Whether the gateway applies the ACTIVE version when proxying (false unless active)."}},"required":["object","id","call_type_id","version","template","variables","content_sha256","source","created_by","created_at","active","gateway_apply"],"description":"One immutable hosted prompt version."}},"active_version":{"type":"integer","nullable":true,"description":"The active version number, or null when code-owned."},"gateway_apply":{"type":"boolean","description":"Whether the active version is gateway-applied (false if none)."}},"required":["object","data","active_version","gateway_apply"],"description":"A call type’s hosted prompt versions + the active pointer."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/prompts/proposal":{"get":{"operationId":"getHostedPromptProposal","tags":["Call types"],"summary":"Get the host-your-prompt onboarding proposal","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The \"host your prompt\" onboarding proposal for a CODE-OWNED call type: v1 is the MOST COMMON leading system message in the call type’s CONSENTED captured traffic (no body is read without consent). Accepting it is the ordinary create + activate with gateway_apply:false — nothing is applied silently. `available:false` carries a NAMED reason. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The host-your-prompt proposal (or a named unavailable reason).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_proposal"]},"call_type_id":{"type":"string"},"available":{"type":"boolean","description":"Whether a proposal is available (a most-common leading instruction was found)."},"reason":{"type":"string","nullable":true,"enum":["already_hosted","no_consent","no_system_message","capture_unavailable"],"description":"The NAMED reason `available` is false (null when a proposal WAS found)."},"template":{"type":"string","nullable":true,"description":"The proposed v1 template — the most common leading system instruction. Present only when available."},"content_sha256":{"type":"string","nullable":true,"description":"sha256 of the proposed template (its byte identity), or null when unavailable."},"template_length":{"type":"integer","nullable":true,"minimum":0,"description":"Character length of the proposed template, or null when unavailable."},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_]+$","description":"The `{{name}}` slot this variable fills."},"required":{"type":"boolean","default":false,"description":"Whether the caller MUST supply a value. A missing REQUIRED variable is a named `prompt_variables_missing` refusal at gateway apply (never a silent blank)."}},"required":["name"],"additionalProperties":false,"description":"A declared hosted-prompt template variable."},"description":"The declared template variables (none are inferred from captured traffic; always [])."},"occurrences":{"type":"integer","minimum":0,"description":"How many sampled consented requests carried EXACTLY this leading instruction."},"distinct_instructions":{"type":"integer","minimum":0,"description":"How many DISTINCT leading instructions were observed across the sample."},"sample_size":{"type":"integer","minimum":0,"description":"How many consented captured requests were inspected to build the proposal."}},"required":["object","call_type_id","available","reason","template","content_sha256","template_length","variables","occurrences","distinct_instructions","sample_size"],"description":"The host-your-prompt onboarding proposal for a call type."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/prompts/{version}":{"get":{"operationId":"getHostedPrompt","tags":["Call types"],"summary":"Get a hosted prompt version","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `version`."},"required":true,"description":"Path parameter `version`.","name":"version","in":"path"}],"responses":{"200":{"description":"The hosted prompt version.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_version"]},"id":{"type":"string"},"call_type_id":{"type":"string"},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Monotonic per call type; activating an older one rolls back."},"template":{"type":"string"},"variables":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9_]+$","description":"The `{{name}}` slot this variable fills."},"required":{"type":"boolean","default":false,"description":"Whether the caller MUST supply a value. A missing REQUIRED variable is a named `prompt_variables_missing` refusal at gateway apply (never a silent blank)."}},"required":["name"],"additionalProperties":false,"description":"A declared hosted-prompt template variable."}},"content_sha256":{"type":"string","description":"sha256 of the template — its immutable byte identity."},"source":{"type":"string","enum":["human","flywheel"],"description":"`human` (written through the API) or `flywheel` (a later flywheel-proposed version)."},"created_by":{"type":"string","nullable":true},"created_at":{"type":"string"},"active":{"type":"boolean","description":"Whether this version is the call type’s currently ACTIVE hosted prompt."},"gateway_apply":{"type":"boolean","description":"Whether the gateway applies the ACTIVE version when proxying (false unless active)."}},"required":["object","id","call_type_id","version","template","variables","content_sha256","source","created_by","created_at","active","gateway_apply"],"description":"One immutable hosted prompt version."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/prompts/{version}/activate":{"post":{"operationId":"activateHostedPrompt","tags":["Call types"],"summary":"Activate a hosted prompt version","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Make this version the call type’s ACTIVE hosted prompt (writes a new config version + bumps `config_version`; visible to the gateway within one 5 s config window). Activating an OLDER version is the rollback. `gateway_apply` makes the proxy path render + substitute it as the leading system instruction. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `version`."},"required":true,"description":"Path parameter `version`.","name":"version","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"gateway_apply":{"type":"boolean","description":"Whether the gateway renders + applies this version when proxying (replacing the leading system instruction). Default false — preflight/SDK read the version regardless."}},"additionalProperties":false,"description":"Activate a hosted prompt version (optional gateway_apply)."}}}},"responses":{"200":{"description":"The active hosted-prompt pointer after activation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_activation"]},"call_type_id":{"type":"string"},"active_version":{"type":"integer","nullable":true,"description":"The active version number AFTER the write (null when deactivated ⇒ code-owned)."},"active_version_id":{"type":"string","nullable":true},"gateway_apply":{"type":"boolean"},"config_version":{"type":"integer","description":"The new call-type config version the change landed on."}},"required":["object","call_type_id","active_version","active_version_id","gateway_apply","config_version"],"description":"The active hosted-prompt pointer after an activate/deactivate."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/prompts/deactivate":{"post":{"operationId":"deactivateHostedPrompt","tags":["Call types"],"summary":"Deactivate the hosted prompt","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Back to CODE-OWNED (the request’s own messages pass through untouched). Writes a new config version with the hosted-prompt pointer cleared. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The active hosted-prompt pointer after deactivation (cleared).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_activation"]},"call_type_id":{"type":"string"},"active_version":{"type":"integer","nullable":true,"description":"The active version number AFTER the write (null when deactivated ⇒ code-owned)."},"active_version_id":{"type":"string","nullable":true},"gateway_apply":{"type":"boolean"},"config_version":{"type":"integer","description":"The new call-type config version the change landed on."}},"required":["object","call_type_id","active_version","active_version_id","gateway_apply","config_version"],"description":"The active hosted-prompt pointer after an activate/deactivate."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/verified-memory":{"get":{"operationId":"getVerifiedMemory","tags":["Call types"],"summary":"Get the verified-memory status","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The frozen verified-memory setting on the call type’s ACTIVE config version (rule version, thresholds, pool hash, the calibration + pool accounting), the workspace’s lab authorisation, and a LIVE servability check of the pinned pool (consent, revocation / dispute tombstones, the per-snapshot item budget — `over_budget` — and the pool hash). A stored setting the gateway cannot load is reported `enabled:true`, `setting:null`, `servable.reason = setting_unreadable` — never shown as off. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The verified-memory status.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verified_memory"]},"call_type_id":{"type":"string"},"config_version":{"type":"integer","nullable":true},"enabled":{"type":"boolean","description":"Whether the active config version carries a setting (readable or not — an unreadable one is `setting: null` + `servable.reason = setting_unreadable`)."},"lab_authorised":{"type":"boolean","description":"The workspace’s staff-granted lab authorisation (`flywheel.verified_memory_lab`)."},"setting":{"type":"object","nullable":true,"properties":{"v":{"type":"number","enum":[1]},"lever_version":{"type":"string","description":"`vmv1_…` — a content address over everything that can change an answer."},"rule_version":{"type":"string","description":"`vmr1_…` — the pure rule the thresholds were calibrated for."},"pool_fact_id":{"type":"string","description":"The materialized `verified_memory_pool` knowledge fact."},"pool_hash":{"type":"string","description":"`vmp1_…` — the frozen pool (serving refuses any other)."},"pool_size":{"type":"integer","minimum":0},"operating_point":{"type":"object","properties":{"k":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Neighbour depth."},"tau_s":{"type":"number","minimum":0,"maximum":1,"description":"Minimum top-1 lexical similarity."},"tau_a":{"type":"number","minimum":0,"maximum":1,"description":"Minimum top-k label agreement share."}},"required":["k","tau_s","tau_a"]},"target_precision":{"type":"number","description":"The DECLARED precision the Wilson lower bound had to clear."},"alpha":{"type":"number"},"candidates_evaluated":{"type":"integer","minimum":0},"calibration":{"type":"object","properties":{"items":{"type":"integer","minimum":0,"description":"Calibration rows (one per pool item)."},"answered":{"type":"integer","minimum":0,"description":"Rows the rule answers at the point."},"correct":{"type":"integer","minimum":0},"wrong":{"type":"integer","minimum":0},"deferred":{"type":"integer","minimum":0,"description":"Rows with a neighbour the rule declines (a threshold) — correctness UNKNOWN."},"abstained":{"type":"integer","minimum":0,"description":"Rows with no neighbour once their own artifact cluster (fold) was held out — correctness UNKNOWN."},"coverage":{"type":"number","minimum":0,"maximum":1},"answered_accuracy":{"type":"number","minimum":0,"maximum":1},"wilson_low":{"type":"number","minimum":0,"maximum":1},"wilson_high":{"type":"number","minimum":0,"maximum":1},"method":{"type":"string","enum":["grouped_cross_fitting"]},"folds":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["items","answered","correct","wrong","deferred","abstained","coverage","answered_accuracy","wilson_low","wilson_high","method","folds"],"description":"The held-out read of the frozen operating point (grouped cross-fitting by cluster: each item’s ARTIFACT cluster is held out — not the clusters of the cases a memory-answered item was decided by). Its Wilson bound is computed on the SAME rows the threshold was searched on — a selection-optimistic in-sample estimate, NOT an independent precision guarantee (the independent read is `post_pin`)."},"pool":{"type":"object","properties":{"admitted_outcomes":{"type":"integer","minimum":0},"items":{"type":"integer","minimum":0},"dropped":{"type":"object","properties":{"no_content":{"type":"integer","minimum":0},"no_input":{"type":"integer","minimum":0},"masked_empty":{"type":"integer","minimum":0},"over_cap":{"type":"integer","minimum":0}},"required":["no_content","no_input","masked_empty","over_cap"]}},"required":["admitted_outcomes","items","dropped"]},"frozen_at":{"type":"string","description":"When the thresholds were frozen (ISO; provenance only)."}},"required":["v","lever_version","rule_version","pool_fact_id","pool_hash","pool_size","operating_point","target_precision","alpha","candidates_evaluated","calibration","pool","frozen_at"],"description":"The frozen verified-memory setting on a call-type config version."},"servable":{"type":"object","nullable":true,"properties":{"ok":{"type":"boolean"},"reason":{"type":"string","nullable":true,"enum":["setting_unreadable","not_lab_authorised","rule_version_unsupported","pool_unavailable","pool_changed"],"description":"`setting_unreadable`: the active config version stores a setting the gateway cannot load (it serves the call type model-only, stamps `setting_unreadable` on every request row and logs it per snapshot read) — disable + re-enable to re-freeze it."}},"required":["ok","reason"],"description":"Whether the setting can answer NOW (null when memory is off)."},"live_pool":{"type":"object","nullable":true,"properties":{"status":{"type":"string","enum":["loaded","unavailable","unreadable","too_large","over_budget"],"description":"`over_budget`: never loaded — the workspace’s memory call types already fill the per-snapshot item budget (earliest pins first); requests are refused `pool_unavailable` and reach the model."},"size":{"type":"integer","minimum":0},"hash":{"type":"string","nullable":true}},"required":["status","size","hash"]},"post_pin":{"type":"object","nullable":true,"properties":{"answered":{"type":"integer","minimum":0,"description":"Requests this lever version answered from memory."},"with_verdict":{"type":"integer","minimum":0,"description":"Of those, how many carry a DECLARED correction-channel verdict (never an inferred proxy)."},"correct":{"type":"integer","minimum":0,"description":"Accepted as-is (`accepted_unchanged` / edit ratio 0)."},"wrong":{"type":"integer","minimum":0,"description":"Edited by the customer (edit ratio > 0)."},"unknown":{"type":"integer","minimum":0,"description":"Answered, no verdict yet — correctness UNKNOWN."},"precision":{"type":"number","nullable":true,"minimum":0,"maximum":1,"description":"correct / with_verdict (null before any verdict)."},"wilson_low":{"type":"number","nullable":true,"minimum":0,"maximum":1},"wilson_high":{"type":"number","nullable":true,"minimum":0,"maximum":1}},"required":["answered","with_verdict","correct","wrong","unknown","precision","wilson_low","wilson_high"],"description":"The CURRENT lever version’s precision on verdicts that arrived after its pin (null when memory is off)."}},"required":["object","call_type_id","config_version","enabled","lab_authorised","setting","servable","live_pool","post_pin"],"description":"A call type’s verified-memory status."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/verified-memory/enable":{"post":{"operationId":"enableVerifiedMemory","tags":["Call types"],"summary":"Enable verified memory","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"A LAB-AUTHORISED pre-evidence lever (staff grant `flywheel.verified_memory_lab`; no customer route grants it — 403 without it). Builds the call type’s pool from its FULL admitted, non-holdout verified outcomes, calibrates the confidence rule (similarity + top-k agreement) by grouped cross-fitting against the DECLARED target precision, and — only when an operating point clears it — persists the pool and appends a config version carrying the frozen setting (config_version bumped: served within one 5 s window). The pool holds at most 250 items (the newest), and the workspace’s memory call types together at most 250 — the budget one config snapshot re-loads on every 5 s refresh (a gateway-overhead bound); past it the enable is refused `snapshot_budget_exceeded`. The frozen setting is re-parsed from its own stored form before any config version carries it: a setting the gateway could not load is refused `setting_unreadable`, so an enable that succeeds always serves. An evidence refusal (`enabled:false` + a NAMED reason + the pool / calibration read) writes no config version. Re-enabling re-derives the pool (e.g. after a revoked or disputed item tombstoned it). Once enabled, memory answers only a request whose meaning its key captures (one instruction message + one text user turn; no image / audio part, earlier turn, extra context message, prompt variables or unsupported parameter) and whose `response_format`, `stop` and `max_tokens` the verbatim answer provably honours — every other request reaches the model, the reason named on its request row. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"target_precision":{"type":"number","minimum":0.8,"maximum":0.999,"description":"The DECLARED precision the calibration’s Wilson lower bound (α = 0.05) must clear (default 0.95)."}},"additionalProperties":false,"description":"Enable verified memory for a label-contract call type."}}}},"responses":{"200":{"description":"The frozen setting, or a named evidence refusal.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verified_memory_enable"]},"call_type_id":{"type":"string"},"enabled":{"type":"boolean"},"reason":{"type":"string","nullable":true,"enum":["not_label_contract","capture_unavailable","pool_empty","calibration_below_target","snapshot_budget_exceeded","setting_unreadable"],"description":"Why the enable was refused (null when enabled). A refusal writes no config version."},"message":{"type":"string","nullable":true},"config_version":{"type":"integer","nullable":true,"description":"The new call-type config version carrying the setting (null when refused)."},"setting":{"type":"object","nullable":true,"properties":{"v":{"type":"number","enum":[1]},"lever_version":{"type":"string","description":"`vmv1_…` — a content address over everything that can change an answer."},"rule_version":{"type":"string","description":"`vmr1_…` — the pure rule the thresholds were calibrated for."},"pool_fact_id":{"type":"string","description":"The materialized `verified_memory_pool` knowledge fact."},"pool_hash":{"type":"string","description":"`vmp1_…` — the frozen pool (serving refuses any other)."},"pool_size":{"type":"integer","minimum":0},"operating_point":{"type":"object","properties":{"k":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"Neighbour depth."},"tau_s":{"type":"number","minimum":0,"maximum":1,"description":"Minimum top-1 lexical similarity."},"tau_a":{"type":"number","minimum":0,"maximum":1,"description":"Minimum top-k label agreement share."}},"required":["k","tau_s","tau_a"]},"target_precision":{"type":"number","description":"The DECLARED precision the Wilson lower bound had to clear."},"alpha":{"type":"number"},"candidates_evaluated":{"type":"integer","minimum":0},"calibration":{"type":"object","properties":{"items":{"type":"integer","minimum":0,"description":"Calibration rows (one per pool item)."},"answered":{"type":"integer","minimum":0,"description":"Rows the rule answers at the point."},"correct":{"type":"integer","minimum":0},"wrong":{"type":"integer","minimum":0},"deferred":{"type":"integer","minimum":0,"description":"Rows with a neighbour the rule declines (a threshold) — correctness UNKNOWN."},"abstained":{"type":"integer","minimum":0,"description":"Rows with no neighbour once their own artifact cluster (fold) was held out — correctness UNKNOWN."},"coverage":{"type":"number","minimum":0,"maximum":1},"answered_accuracy":{"type":"number","minimum":0,"maximum":1},"wilson_low":{"type":"number","minimum":0,"maximum":1},"wilson_high":{"type":"number","minimum":0,"maximum":1},"method":{"type":"string","enum":["grouped_cross_fitting"]},"folds":{"type":"integer","minimum":0,"exclusiveMinimum":true}},"required":["items","answered","correct","wrong","deferred","abstained","coverage","answered_accuracy","wilson_low","wilson_high","method","folds"],"description":"The held-out read of the frozen operating point (grouped cross-fitting by cluster: each item’s ARTIFACT cluster is held out — not the clusters of the cases a memory-answered item was decided by). Its Wilson bound is computed on the SAME rows the threshold was searched on — a selection-optimistic in-sample estimate, NOT an independent precision guarantee (the independent read is `post_pin`)."},"pool":{"type":"object","properties":{"admitted_outcomes":{"type":"integer","minimum":0},"items":{"type":"integer","minimum":0},"dropped":{"type":"object","properties":{"no_content":{"type":"integer","minimum":0},"no_input":{"type":"integer","minimum":0},"masked_empty":{"type":"integer","minimum":0},"over_cap":{"type":"integer","minimum":0}},"required":["no_content","no_input","masked_empty","over_cap"]}},"required":["admitted_outcomes","items","dropped"]},"frozen_at":{"type":"string","description":"When the thresholds were frozen (ISO; provenance only)."}},"required":["v","lever_version","rule_version","pool_fact_id","pool_hash","pool_size","operating_point","target_precision","alpha","candidates_evaluated","calibration","pool","frozen_at"],"description":"The frozen verified-memory setting on a call-type config version."},"pool":{"type":"object","nullable":true,"properties":{"admitted_outcomes":{"type":"integer","minimum":0,"description":"Admitted, non-holdout verified outcomes of the call type (the ONE admission gate)."},"items":{"type":"integer","minimum":0,"description":"The effective pool size."},"dropped":{"type":"object","properties":{"no_content":{"type":"integer","minimum":0},"no_input":{"type":"integer","minimum":0},"masked_empty":{"type":"integer","minimum":0},"over_cap":{"type":"integer","minimum":0}},"required":["no_content","no_input","masked_empty","over_cap"]},"admission":{"type":"object","properties":{"admitted_declared":{"type":"integer","minimum":0},"admitted_inferred":{"type":"integer","minimum":0},"dropped_by_reason":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"receipt_rejected_by_reason":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"receipt_candidates":{"type":"integer","minimum":0}},"required":["admitted_declared","admitted_inferred","dropped_by_reason","receipt_rejected_by_reason","receipt_candidates"],"description":"The ONE correction gate’s accounting."},"content":{"type":"object","properties":{"final":{"type":"integer","minimum":0},"verified_replacement":{"type":"integer","minimum":0},"magnitude_only":{"type":"integer","minimum":0},"verified_replacement_withheld_consent":{"type":"integer","minimum":0}},"required":["final","verified_replacement","magnitude_only","verified_replacement_withheld_consent"],"description":"Where each outcome’s content came from."},"corrections_consent":{"type":"boolean"}},"required":["admitted_outcomes","items","dropped","admission","content","corrections_consent"],"description":"The verified pool an enable attempt built (counts only)."},"calibration":{"type":"object","nullable":true,"properties":{"items":{"type":"integer","minimum":0,"description":"Calibration rows (one per pool item)."},"answered":{"type":"integer","minimum":0,"description":"Rows the rule answers at the point."},"correct":{"type":"integer","minimum":0},"wrong":{"type":"integer","minimum":0},"deferred":{"type":"integer","minimum":0,"description":"Rows with a neighbour the rule declines (a threshold) — correctness UNKNOWN."},"abstained":{"type":"integer","minimum":0,"description":"Rows with no neighbour once their own artifact cluster (fold) was held out — correctness UNKNOWN."},"coverage":{"type":"number","minimum":0,"maximum":1},"answered_accuracy":{"type":"number","minimum":0,"maximum":1},"wilson_low":{"type":"number","minimum":0,"maximum":1},"wilson_high":{"type":"number","minimum":0,"maximum":1}},"required":["items","answered","correct","wrong","deferred","abstained","coverage","answered_accuracy","wilson_low","wilson_high"],"description":"The held-out read of the frozen operating point (grouped cross-fitting by cluster: each item’s ARTIFACT cluster is held out — not the clusters of the cases a memory-answered item was decided by). Its Wilson bound is computed on the SAME rows the threshold was searched on — a selection-optimistic in-sample estimate, NOT an independent precision guarantee (the independent read is `post_pin`)."},"previous_lever_version":{"type":"string","nullable":true,"description":"The lever version this setting replaced (null when memory was off)."}},"required":["object","call_type_id","enabled","reason","message","config_version","setting","pool","calibration","previous_lever_version"],"description":"The result of enabling verified memory."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/verified-memory/disable":{"post":{"operationId":"disableVerifiedMemory","tags":["Call types"],"summary":"Disable verified memory (kill switch)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The KILL SWITCH / rollback: appends a config version with memory OFF (config_version bumped), so every request of the call type reaches the model again within one 5 s window. Never gated on the lab authorisation; idempotent (`changed:false` when already off). Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The disable result.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verified_memory_disable"]},"call_type_id":{"type":"string"},"changed":{"type":"boolean","description":"False when memory was already off (nothing written — idempotent)."},"config_version":{"type":"integer","nullable":true},"previous_lever_version":{"type":"string","nullable":true}},"required":["object","call_type_id","changed","config_version","previous_lever_version"],"description":"The result of disabling verified memory (model-only serving within one 5 s window)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/episode-memory":{"get":{"operationId":"getEpisodeMemory","tags":["Call types"],"summary":"Get the episode-memory status","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The frozen episode-memory setting on the call type’s ACTIVE config version (k, char budgets, the pinned/live memory instant, an optional source call type, the record switch), the workspace’s lab authorisation, the episode-trace accounting (total / pass / fail / unverified + the latest pass verification), and a content-addressed PREVIEW of the memory the setting would serve now (`memory.digest` = `emd1_…` over the ordered eligible set, `memory.verified_pass` its size). The optional `?as_of=<iso>` overrides the pin FOR THIS READ ONLY, so a checkpoint instant can be digested before the call type is pinned to it. The preview is consent-gated (empty without consent). Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Override the setting’s pin (ISO instant) for this read only — digest a checkpoint instant."},"required":false,"description":"Override the setting’s pin (ISO instant) for this read only — digest a checkpoint instant.","name":"as_of","in":"query"}],"responses":{"200":{"description":"The episode-memory status.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["episode_memory"]},"call_type_id":{"type":"string"},"config_version":{"type":"integer","nullable":true},"enabled":{"type":"boolean","description":"Whether the active config version carries a readable EXPLICIT setting (false for the explicit-off marker, an unreadable value, or no setting)."},"source":{"type":"string","enum":["explicit","default","off"],"description":"The per-call-type state — `explicit` (a readable setting is stored), `off` (an explicit opt-out, or an unreadable value fail-closed), or `default` (nothing stored — the call type follows the workspace default `flywheel.episode_memory_default`)."},"lab_authorised":{"type":"boolean","description":"The workspace’s staff-granted lab authorisation (`flywheel.episode_memory_lab`)."},"setting":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"`epm1` — the pure rule version a stored setting is parsed under."},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"max_chars_per_episode":{"type":"integer","minimum":0},"observation_chars":{"type":"integer","minimum":0},"as_of":{"type":"string","nullable":true,"description":"A frozen memory version (ISO), or null for live memory."},"source_call_type_id":{"type":"string","nullable":true},"record":{"type":"boolean"},"retrieval_key":{"type":"string","enum":["first_user_message","content_lines"],"description":"Present only when not the default `first_user_message`."},"min_similarity":{"type":"number","description":"Present only when set (not 0)."},"prefer_shorter":{"type":"boolean","description":"Present only when true."},"dedupe":{"type":"boolean","description":"Present only when true."},"framing":{"type":"string","enum":["reuse","adapt"],"description":"Present only when not the default `reuse`."},"lessons":{"type":"object","properties":{"mode":{"type":"string","enum":["off","only","with_precedents"]},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"distiller_model":{"type":"string","nullable":true},"version_id":{"type":"string","nullable":true},"recipe":{"type":"object","properties":{"validator":{"type":"string","enum":["elv1","elv2"]},"generation":{"type":"string","enum":["bundled","atomic"]},"observations":{"type":"string","enum":["legacy","elo2"]}},"required":["validator","generation","observations"],"description":"Present only for a non-legacy learner recipe (absent ⇒ the legacy learner)."}},"required":["mode","k","distiller_model","version_id"],"description":"Present only when the learned-playbook mode is not `off`."},"self_serve":{"type":"boolean","description":"Present (true) only when learning was enabled self-serve through `POST /v1/call-types/{id}/learning/enable` — a published version is then a candidate. In evaluate mode it receives a randomized share of eligible episodes before the policy can make it the active version."}},"required":["rule_version","k","max_chars_per_episode","observation_chars","as_of","source_call_type_id","record"],"description":"The frozen episode-memory setting on a call-type config version."},"traces":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pass":{"type":"integer","minimum":0,"description":"Episodes a whole-episode teaching outcome verified as passing."},"fail":{"type":"integer","minimum":0},"unverified":{"type":"integer","minimum":0,"description":"Episodes still recording (no verdict yet)."},"latest_verified_at":{"type":"string","nullable":true,"description":"The newest pass verification instant (ISO), or null."}},"required":["total","pass","fail","unverified","latest_verified_at"],"description":"The call type’s episode-trace accounting (counts only)."},"memory":{"type":"object","properties":{"source_call_type_id":{"type":"string","description":"The call type whose verified episodes would be served."},"as_of":{"type":"string","nullable":true,"description":"The pin the digest was taken under (ISO), or null = live."},"verified_pass":{"type":"integer","minimum":0,"description":"Eligible verified pass episodes of the source (verified_at ≤ pin, or all when live)."},"digest":{"type":"string","description":"`emd1_…` — a content address of the ordered eligible set (stable for a frozen checkpoint)."}},"required":["source_call_type_id","as_of","verified_pass","digest"],"description":"A content-addressed preview of the memory the setting (or `?as_of`) would serve now."},"playbook":{"type":"object","properties":{"source_call_type_id":{"type":"string","description":"The call type whose playbook is reported."},"version":{"type":"integer","nullable":true,"description":"The latest version number, or null when none."},"version_id":{"type":"string","nullable":true,"description":"The latest version row id (`epb_…`), or null."},"cohort_size":{"type":"integer","minimum":0,"description":"The sealed cohort size of the latest version."},"active_lessons":{"type":"integer","minimum":0,"description":"The active-lesson count of the latest version."},"digest":{"type":"string","nullable":true,"description":"The latest version digest (`epb1_…`), or null."}},"required":["source_call_type_id","version","version_id","cohort_size","active_lessons","digest"],"description":"The latest learned playbook of the source call type (version null when none)."}},"required":["object","call_type_id","config_version","enabled","source","lab_authorised","setting","traces","memory","playbook"],"description":"A call type’s episode-memory status."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/episode-memory/enable":{"post":{"operationId":"enableEpisodeMemory","tags":["Call types"],"summary":"Enable episode memory","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"A LAB-AUTHORISED pre-evidence lever (staff grant `flywheel.episode_memory_lab`; no customer route grants it — 403 without it). Freezes a setting on a new config version (config_version bumped: served within one 5 s window), so the gateway records this call type’s agent episodes and injects the most similar VERIFIED past episodes (by task) into EVERY step of later episodes. Invalid knobs are a 400 (the named reason); an unknown `source_call_type_id` is a 404. No client-side code, no special headers. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"k":{"type":"integer","minimum":1,"maximum":5,"description":"Precedents served per episode (1..5; default 3)."},"max_chars_per_episode":{"type":"integer","minimum":500,"maximum":8000,"description":"Characters of actions shown per precedent (500..8000; default 3500)."},"observation_chars":{"type":"integer","minimum":0,"maximum":2000,"description":"Characters of each kept action’s observation shown under it (0 = actions only; default 0)."},"as_of":{"type":"string","nullable":true,"description":"Serve only episodes verified at or before this instant (ISO) — a frozen memory version; null = live."},"source_call_type_id":{"type":"string","nullable":true,"description":"The call type whose verified episodes are served (same workspace); null = this call type."},"record":{"type":"boolean","description":"Record this call type’s episodes so outcomes can verify them (default true); false = serve only."},"retrieval_key":{"type":"string","enum":["first_user_message","content_lines"],"description":"What precedents are ranked on: the whole first user message (default) or its content lines — without lines carrying a personal identifier or a timestamp."},"min_similarity":{"type":"number","minimum":0,"maximum":1,"description":"Serve only precedents at least this similar to the task (0..1; default 0, no floor)."},"prefer_shorter":{"type":"boolean","description":"Among near-equally similar precedents, serve the shortest verified solutions first (default false)."},"dedupe":{"type":"boolean","description":"Serve at most one of near-identical precedents (default false)."},"framing":{"type":"string","enum":["reuse","adapt"],"description":"How served precedents are framed: `reuse` (default) invites reusing their calls; `adapt` presents them as evidence of how the tools behave, not values to copy."},"lessons":{"type":"object","properties":{"mode":{"type":"string","enum":["off","only","with_precedents"],"description":"Serve a distilled playbook — `off` (default, byte-identical), `only` (lessons, no precedents), `with_precedents` (lessons before precedents)."},"k":{"type":"integer","minimum":1,"maximum":20,"description":"Lessons served per episode (1..20; default 8)."},"distiller_model":{"type":"string","nullable":true,"description":"The model the distiller uses; null = the call type’s own model."},"version_id":{"type":"string","nullable":true,"description":"A frozen-arm pin: serve exactly this playbook version (`epb_…`) of the source call type; null = the latest."},"recipe":{"type":"object","properties":{"validator":{"type":"string","enum":["elv1","elv2"],"description":"Lesson admission: `elv1` (legacy literal rule, the default) or `elv2` (provenance-aware: evidence support + value handling, documented constants scoped to their tool)."},"generation":{"type":"string","enum":["bundled","atomic"],"description":"Lesson generation: `bundled` (legacy, the default) or `atomic` (one complete rule per item with conditions, exceptions and required tools; never clipped)."},"observations":{"type":"string","enum":["legacy","elo2"],"description":"Observation selection: `legacy` (the default) or `elo2` (error→correction transitions, passed-case results and labelled user turns at the same total budget, with measured omissions)."}},"additionalProperties":false,"description":"The learner recipe the distiller runs (absent ⇒ the legacy learner)."}},"required":["mode"],"description":"The learned-playbook block (absent ⇒ lessons off, byte-identical)."}},"additionalProperties":false,"description":"Enable episode memory for a call type (the lab-authorised, pre-evidence activation)."}}}},"responses":{"200":{"description":"The frozen setting on a new config version.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["episode_memory_enable"]},"call_type_id":{"type":"string"},"enabled":{"type":"boolean","enum":[true]},"config_version":{"type":"integer","description":"The new config version carrying the setting."},"setting":{"type":"object","properties":{"rule_version":{"type":"string","description":"`epm1` — the pure rule version a stored setting is parsed under."},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"max_chars_per_episode":{"type":"integer","minimum":0},"observation_chars":{"type":"integer","minimum":0},"as_of":{"type":"string","nullable":true,"description":"A frozen memory version (ISO), or null for live memory."},"source_call_type_id":{"type":"string","nullable":true},"record":{"type":"boolean"},"retrieval_key":{"type":"string","enum":["first_user_message","content_lines"],"description":"Present only when not the default `first_user_message`."},"min_similarity":{"type":"number","description":"Present only when set (not 0)."},"prefer_shorter":{"type":"boolean","description":"Present only when true."},"dedupe":{"type":"boolean","description":"Present only when true."},"framing":{"type":"string","enum":["reuse","adapt"],"description":"Present only when not the default `reuse`."},"lessons":{"type":"object","properties":{"mode":{"type":"string","enum":["off","only","with_precedents"]},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"distiller_model":{"type":"string","nullable":true},"version_id":{"type":"string","nullable":true},"recipe":{"type":"object","properties":{"validator":{"type":"string","enum":["elv1","elv2"]},"generation":{"type":"string","enum":["bundled","atomic"]},"observations":{"type":"string","enum":["legacy","elo2"]}},"required":["validator","generation","observations"],"description":"Present only for a non-legacy learner recipe (absent ⇒ the legacy learner)."}},"required":["mode","k","distiller_model","version_id"],"description":"Present only when the learned-playbook mode is not `off`."},"self_serve":{"type":"boolean","description":"Present (true) only when learning was enabled self-serve through `POST /v1/call-types/{id}/learning/enable` — a published version is then a candidate. In evaluate mode it receives a randomized share of eligible episodes before the policy can make it the active version."}},"required":["rule_version","k","max_chars_per_episode","observation_chars","as_of","source_call_type_id","record"],"description":"The frozen episode-memory setting on a call-type config version."},"previous":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"`epm1` — the pure rule version a stored setting is parsed under."},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"max_chars_per_episode":{"type":"integer","minimum":0},"observation_chars":{"type":"integer","minimum":0},"as_of":{"type":"string","nullable":true,"description":"A frozen memory version (ISO), or null for live memory."},"source_call_type_id":{"type":"string","nullable":true},"record":{"type":"boolean"},"retrieval_key":{"type":"string","enum":["first_user_message","content_lines"],"description":"Present only when not the default `first_user_message`."},"min_similarity":{"type":"number","description":"Present only when set (not 0)."},"prefer_shorter":{"type":"boolean","description":"Present only when true."},"dedupe":{"type":"boolean","description":"Present only when true."},"framing":{"type":"string","enum":["reuse","adapt"],"description":"Present only when not the default `reuse`."},"lessons":{"type":"object","properties":{"mode":{"type":"string","enum":["off","only","with_precedents"]},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"distiller_model":{"type":"string","nullable":true},"version_id":{"type":"string","nullable":true},"recipe":{"type":"object","properties":{"validator":{"type":"string","enum":["elv1","elv2"]},"generation":{"type":"string","enum":["bundled","atomic"]},"observations":{"type":"string","enum":["legacy","elo2"]}},"required":["validator","generation","observations"],"description":"Present only for a non-legacy learner recipe (absent ⇒ the legacy learner)."}},"required":["mode","k","distiller_model","version_id"],"description":"Present only when the learned-playbook mode is not `off`."},"self_serve":{"type":"boolean","description":"Present (true) only when learning was enabled self-serve through `POST /v1/call-types/{id}/learning/enable` — a published version is then a candidate. In evaluate mode it receives a randomized share of eligible episodes before the policy can make it the active version."}},"required":["rule_version","k","max_chars_per_episode","observation_chars","as_of","source_call_type_id","record"],"description":"The setting this one replaced (null when off)."}},"required":["object","call_type_id","enabled","config_version","setting","previous"],"description":"The result of enabling episode memory (a refusal is a named HTTP error, never a 200)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/episode-memory/disable":{"post":{"operationId":"disableEpisodeMemory","tags":["Call types"],"summary":"Disable episode memory (kill switch)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The KILL SWITCH / rollback: appends a config version with episode memory OFF (config_version bumped), so the call type serves model-only again within one 5 s window. Never gated on the lab authorisation; idempotent (`changed:false` when already off). Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The disable result.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["episode_memory_disable"]},"call_type_id":{"type":"string"},"changed":{"type":"boolean","description":"False when memory was already off (nothing written — idempotent)."},"config_version":{"type":"integer","nullable":true},"previous":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"`epm1` — the pure rule version a stored setting is parsed under."},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"max_chars_per_episode":{"type":"integer","minimum":0},"observation_chars":{"type":"integer","minimum":0},"as_of":{"type":"string","nullable":true,"description":"A frozen memory version (ISO), or null for live memory."},"source_call_type_id":{"type":"string","nullable":true},"record":{"type":"boolean"},"retrieval_key":{"type":"string","enum":["first_user_message","content_lines"],"description":"Present only when not the default `first_user_message`."},"min_similarity":{"type":"number","description":"Present only when set (not 0)."},"prefer_shorter":{"type":"boolean","description":"Present only when true."},"dedupe":{"type":"boolean","description":"Present only when true."},"framing":{"type":"string","enum":["reuse","adapt"],"description":"Present only when not the default `reuse`."},"lessons":{"type":"object","properties":{"mode":{"type":"string","enum":["off","only","with_precedents"]},"k":{"type":"integer","minimum":0,"exclusiveMinimum":true},"distiller_model":{"type":"string","nullable":true},"version_id":{"type":"string","nullable":true},"recipe":{"type":"object","properties":{"validator":{"type":"string","enum":["elv1","elv2"]},"generation":{"type":"string","enum":["bundled","atomic"]},"observations":{"type":"string","enum":["legacy","elo2"]}},"required":["validator","generation","observations"],"description":"Present only for a non-legacy learner recipe (absent ⇒ the legacy learner)."}},"required":["mode","k","distiller_model","version_id"],"description":"Present only when the learned-playbook mode is not `off`."},"self_serve":{"type":"boolean","description":"Present (true) only when learning was enabled self-serve through `POST /v1/call-types/{id}/learning/enable` — a published version is then a candidate. In evaluate mode it receives a randomized share of eligible episodes before the policy can make it the active version."}},"required":["rule_version","k","max_chars_per_episode","observation_chars","as_of","source_call_type_id","record"],"description":"The frozen episode-memory setting on a call-type config version."}},"required":["object","call_type_id","changed","config_version","previous"],"description":"The result of disabling episode memory (model-only serving within one 5 s window)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning":{"get":{"operationId":"getLearningStatus","tags":["Learning"],"summary":"Get the learning status of a call type","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The learner’s state (`off`, `collecting`, `learning`, `paused`, `disabled`, `unavailable`, `quota_exhausted`, `budget_exhausted`) and its reason; the reflection model and whether it resolves to a workspace-owned provider; the promotion policy; the ACTIVE version (the incumbent) and the latest candidate; the running evaluation; the evidence arrived vs verified vs incorporated vs backlog; whether the next reflection will run and why; the budget / quota state; and token usage separate from cash. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The learning status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningStatus"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/enable":{"post":{"operationId":"enableLearning","tags":["Learning"],"summary":"Enable learning for a call type (self-serve)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Turns learning on with a reflection model, a promotion policy and a recipe. Requires the workspace’s corrections and knowledge consent (409 `conflict`, message `corrections_consent_required` if either is missing). The owner grants both through the dashboard Allow learning opt-in or the session-authenticated `PUT /v1/workspaces/{id}/self-learning` with `{\"enabled\":true}`; a bearer key cannot grant workspace consent. Also requires a reflection model that resolves to a WORKSPACE-OWNED offer — a custom provider or a provider the workspace stored its own key for (400 `invalid_request`, message `reflection_model_not_workspace_owned`). No staff grant is needed. A published version is a candidate. In evaluate mode it receives a randomized share of eligible episodes during comparison; only a win makes it the active version. Re-enabling updates the policy; a running evaluation keeps its frozen rule. Owner/admin session or a `config:write` key. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnableLearningRequest"}}}},"responses":{"200":{"description":"Learning enabled; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/pause":{"post":{"operationId":"pauseLearning","tags":["Learning"],"summary":"Pause learning","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Stops reflecting and stops evaluation decisions; the ACTIVE version keeps serving and no evaluation arm is assigned while paused. Idempotent. 409 `conflict` (`learning_not_enabled`) for a call type that was never enabled through this API. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"Paused; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/resume":{"post":{"operationId":"resumeLearning","tags":["Learning"],"summary":"Resume learning","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Resumes reflection and evaluation decisions and resets the bounded-retry counters (a learner that stopped after repeated failures or quota refusals tries again). Idempotent. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"Resumed; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/disable":{"post":{"operationId":"disableLearning","tags":["Learning"],"summary":"Disable learning (kill switch)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Stops serving lessons and stops reflecting within one 5 s config window (the episode-memory kill switch); a running evaluation stops (`stopped_manual`). Versions and history are kept; enabling again resumes from the active version. Idempotent. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"Disabled; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/versions":{"get":{"operationId":"listLearningVersions","tags":["Learning"],"summary":"List learned versions with their states","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The immutable versions, newest first, each with its state (`candidate`, `evaluating`, `active`, `retired`, `rejected`, `superseded`), why and since when. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The version history.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["learning_version"]},"id":{"type":"string","description":"The immutable version id (`epb_…`)."},"version":{"type":"integer"},"parent_id":{"type":"string","nullable":true},"state":{"type":"string","enum":["candidate","evaluating","active","retired","rejected","superseded"],"description":"`candidate` (published, waiting), `evaluating`, `active` (served outside an evaluation), `retired` (replaced), `rejected` (lost / stopped / rejected by an owner), `superseded` (a newer candidate, or identical to the active version)."},"state_reason":{"type":"string","nullable":true,"description":"Why it entered its state (a bounded code); null when the state is derived."},"state_since":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"evaluation_id":{"type":"string","nullable":true,"description":"The evaluation that set the state, if any."},"digest":{"type":"string","description":"A content address of the version’s active lessons (`epb1_…`)."},"recipe":{"type":"string"},"created_at":{"type":"string","description":"ISO 8601 instant."},"active_lessons":{"type":"integer","minimum":0},"cohort":{"type":"object","properties":{"size":{"type":"integer","minimum":0},"pass":{"type":"integer","minimum":0},"fail":{"type":"integer","minimum":0}},"required":["size","pass","fail"],"description":"The verified episodes the version was learned from."},"reflection_model":{"type":"string","nullable":true}},"required":["object","id","version","parent_id","state","state_reason","state_since","evaluation_id","digest","recipe","created_at","active_lessons","cohort","reflection_model"],"description":"A learned playbook version."}}},"required":["object","data"],"description":"The version history, newest first."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/versions/{version_id}":{"get":{"operationId":"getLearningVersion","tags":["Learning"],"summary":"Get one learned version","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The version’s active lessons, how many retired, the evidence it was learned from, the body-free reflection receipt (hashes and token counts) and every recorded state transition. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `version_id`."},"required":true,"description":"Path parameter `version_id`.","name":"version_id","in":"path"}],"responses":{"200":{"description":"The version detail.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningVersionDetail"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/rollback":{"post":{"operationId":"rollbackLearning","tags":["Learning"],"summary":"Roll back to an earlier version","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Points the active version at an EARLIER immutable version (`version_id`, or the version active immediately before the current one) so it serves exactly that version’s lessons again. A running evaluation stops. 409 `conflict` (`no_rollback_target` / `rollback_target_not_earlier`) when there is nothing to roll back to. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"version_id":{"type":"string","minLength":1,"maxLength":80,"description":"The EARLIER version to make active (`epb_…`). Omitted: the version that was active immediately before the current one."}},"description":"Roll the active pointer back to an earlier immutable version."}}}},"responses":{"200":{"description":"Rolled back; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/versions/{version_id}/promote":{"post":{"operationId":"promoteLearningVersion","tags":["Learning"],"summary":"Promote a version to active (manual decision)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"An owner/admin (or `config:write` key) decision: the version becomes the active version now; a running evaluation stops. 409 `conflict` (`version_already_active`) when it already is. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `version_id`."},"required":true,"description":"Path parameter `version_id`.","name":"version_id","in":"path"}],"responses":{"200":{"description":"Promoted; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/versions/{version_id}/reject":{"post":{"operationId":"rejectLearningVersion","tags":["Learning"],"summary":"Reject a candidate (manual decision)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"An owner/admin (or `config:write` key) decision: the candidate is never activated by the system; its running evaluation stops. 409 `conflict` (`version_active`) for the active version — roll back instead. Idempotent. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `version_id`."},"required":true,"description":"Path parameter `version_id`.","name":"version_id","in":"path"}],"responses":{"200":{"description":"Rejected; the resulting status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LearningControlResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/evaluations":{"get":{"operationId":"listLearningEvaluations","tags":["Learning"],"summary":"List evaluations","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Every evaluation, newest first: the frozen rule and its hash, each arm’s verified / pass / unknown episodes, the one-sided interval on the success difference, and the decision with its reason. Under lpr2, enrollment closes before outcomes are inspected; the frozen episodes remain selected while their outcomes are awaited. Missing outcomes cannot produce a promotion. Historical lpr1 results retain their original rule. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The evaluations.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["learning_evaluation"]},"id":{"type":"string","description":"`lev_…`"},"call_type_id":{"type":"string"},"candidate_version_id":{"type":"string"},"incumbent_version_id":{"type":"string","nullable":true,"description":"Null: the candidate is compared with serving no lessons."},"decision":{"type":"string","enum":["running","promoted","retained","inconclusive","rejected","stopped_budget","stopped_manual"],"description":"Every decision except `promoted` keeps the incumbent."},"decision_reason":{"type":"string"},"rule":{"type":"object","nullable":true,"properties":{"rule_version":{"type":"string","description":"lpr2 freezes enrollment before waiting for outcomes; lpr1 identifies historical verified-only rules."},"objective":{"type":"string","enum":["success","cost_noninferior"],"description":"`success`: a higher whole-task success rate (the one-sided lower bound of the difference > 0 and the point difference ≥ `min_effect_pp`). `cost_noninferior`: a lower mean cost per episode with success not worse than the incumbent by more than `noninferiority_margin_pp`."},"min_verified_per_arm":{"type":"integer"},"max_verified_per_arm":{"type":"integer"},"alpha_one_sided":{"type":"number"},"min_effect_pp":{"type":"number"},"noninferiority_margin_pp":{"type":"number"},"candidate_share":{"type":"number"},"max_duration_hours":{"type":"integer"},"interval":{"type":"string","description":"`newcombe_hybrid_score`."},"outcome_source":{"type":"string","description":"`verified_teaching_episode`."}},"required":["rule_version","objective","min_verified_per_arm","max_verified_per_arm","alpha_one_sided","min_effect_pp","noninferiority_margin_pp","candidate_share","max_duration_hours","interval","outcome_source"],"description":"The decision rule frozen when the evaluation started. lpr2 selects episodes before inspecting their outcomes, freezes one cohort, and makes one decision only from complete selected outcomes or the fixed deadline."},"rule_hash":{"type":"string","description":"`lrh1_…` content address of the frozen rule."},"arms":{"type":"object","properties":{"candidate":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]},"incumbent":{"type":"object","properties":{"verified":{"type":"integer","minimum":0,"description":"Episodes with a verified teaching outcome."},"pass":{"type":"integer","minimum":0},"unknown":{"type":"integer","minimum":0,"description":"Selected episodes without an eligible verified outcome, including reports after the fixed deadline. Under lpr2 they remain in the frozen cohort and block promotion; missing outcomes at the fixed deadline leave the incumbent active. Historical lpr1 evaluations excluded and counted unknown outcomes."},"success_rate":{"type":"number","nullable":true,"description":"Descriptive pass / verified rate. Under lpr2 a promotion decision waits for complete outcomes in the frozen cohort."},"cost_micro_usd":{"type":"integer","nullable":true,"description":"Summed request cost of verified episodes within the selected cohort (cost objective only)."},"mean_cost_micro_usd":{"type":"number","nullable":true}},"required":["verified","pass","unknown","success_rate","cost_micro_usd","mean_cost_micro_usd"]}},"required":["candidate","incumbent"]},"difference":{"type":"object","nullable":true,"properties":{"point":{"type":"number"},"lower":{"type":"number"},"upper":{"type":"number"}},"required":["point","lower","upper"],"description":"candidate − incumbent success (a fraction) with one-sided bounds at the frozen alpha; null until both arms have a verified episode."},"started_at":{"type":"string","description":"ISO 8601 instant."},"decided_at":{"type":"string","nullable":true,"description":"ISO 8601 instant."},"decided_by":{"type":"object","nullable":true,"properties":{"type":{"type":"string","enum":["system","user","api_key"]},"id":{"type":"string","nullable":true}},"required":["type","id"]}},"required":["object","id","call_type_id","candidate_version_id","incumbent_version_id","decision","decision_reason","rule","rule_hash","arms","difference","started_at","decided_at","decided_by"],"description":"A prospective randomized evaluation of a candidate against the incumbent."}}},"required":["object","data"],"description":"The evaluations, newest first."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/call-types/{id}/learning/tool-documentation":{"get":{"operationId":"getLearningToolDocumentation","tags":["Learning"],"summary":"Get the tool documentation the learner reads","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The call type’s customer-supplied tool documentation as stored: per tool its name, schema fingerprint, parameter names and documented constants (never description prose), plus the set’s `etd1_` digest. Empty (`tool_count` 0, `digest` null) when none is stored. Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The stored tool documentation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_tool_documentation"]},"call_type_id":{"type":"string"},"changed":{"type":"boolean","description":"PUT only: false when the same documentation was already stored (idempotent)."},"tool_count":{"type":"integer","minimum":0},"digest":{"type":"string","nullable":true,"description":"`etd1_…` — the content address of the stored set; null when none is stored."},"updated_at":{"type":"string","nullable":true},"tools":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"fingerprint":{"type":"string","description":"`tsf1_…` — the schema fingerprint the documented constants are scoped to."},"params":{"type":"array","items":{"type":"string"},"description":"Parameter names (bounded)."},"documented":{"type":"array","items":{"type":"object","properties":{"param":{"type":"string","nullable":true,"description":"The parameter it belongs to, or null for the function’s own description."},"value":{"type":"string"},"source":{"type":"string","enum":["enum","const","default","description"]}},"required":["param","value","source"]},"description":"Every constant the spec documents (bounded)."}},"required":["name","fingerprint","params","documented"],"description":"One tool’s stored summary."}}},"required":["object","call_type_id","tool_count","digest","updated_at","tools"],"description":"A call type’s customer-supplied tool documentation (bounded summaries; no prose)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"put":{"operationId":"putLearningToolDocumentation","tags":["Learning"],"summary":"Replace the tool documentation the learner reads","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"For agents whose tools are not sent as native `tools[]` (a code-style `api.<name>(…)` protocol): up to 256 OpenAI-style function specs (unique names; body at most 1 MiB). Each is stored as a bounded summary — name, schema fingerprint, parameter names and the constants it documents (enum / const / default / a number or quoted token its description states); description prose is never stored. When learning admits a lesson (`elv2`), such a constant is admissible only in a lesson that names the documenting tool. Replaces any stored set; an empty `tools` list clears it; the same set again is a no-op (`changed: false`). Erased with the learning data when corrections consent is revoked. 400 `invalid_request` (`tool_documentation_too_large`, `tool_documentation_invalid (<reason>)`). Dual auth: an api key (`config:read` to read, `config:write` to change) or an owner/admin session with the `X-UR-Workspace` header; a viewer may read only. A call type of another workspace is a 404. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"tools":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["function"]},"function":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":64,"pattern":"^[A-Za-z0-9_.-]+$","description":"The tool’s name exactly as the agent calls it (`fillFuelTank`, `api.fillFuelTank` → `fillFuelTank`)."},"description":{"type":"string","maxLength":4096,"description":"Read for the CONSTANTS it states (numbers and quoted tokens) — the prose itself is never stored."},"parameters":{"type":"object","additionalProperties":{"nullable":true},"description":"The JSON Schema of the arguments; its `enum` / `const` / `default` values are documented constants."},"strict":{"type":"boolean"}},"required":["name"],"description":"The function declaration."}},"required":["type","function"],"description":"One OpenAI-style function tool spec."},"maxItems":256,"description":"At most 256 specs with unique names; an empty list clears the documentation."}},"required":["tools"],"additionalProperties":false,"description":"The call type’s tool documentation (replaces any stored set)."}}}},"responses":{"200":{"description":"The stored tool documentation after the replace.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_tool_documentation"]},"call_type_id":{"type":"string"},"changed":{"type":"boolean","description":"PUT only: false when the same documentation was already stored (idempotent)."},"tool_count":{"type":"integer","minimum":0},"digest":{"type":"string","nullable":true,"description":"`etd1_…` — the content address of the stored set; null when none is stored."},"updated_at":{"type":"string","nullable":true},"tools":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"fingerprint":{"type":"string","description":"`tsf1_…` — the schema fingerprint the documented constants are scoped to."},"params":{"type":"array","items":{"type":"string"},"description":"Parameter names (bounded)."},"documented":{"type":"array","items":{"type":"object","properties":{"param":{"type":"string","nullable":true,"description":"The parameter it belongs to, or null for the function’s own description."},"value":{"type":"string"},"source":{"type":"string","enum":["enum","const","default","description"]}},"required":["param","value","source"]},"description":"Every constant the spec documents (bounded)."}},"required":["name","fingerprint","params","documented"],"description":"One tool’s stored summary."}}},"required":["object","call_type_id","tool_count","digest","updated_at","tools"],"description":"A call type’s customer-supplied tool documentation (bounded summaries; no prose)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/knowledge":{"get":{"operationId":"listCompanyKnowledge","tags":["Knowledge"],"summary":"Search company knowledge","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Workspace members or config:read/config:write keys. Knowledge and corrections consent required; unavailable content is omitted. Lessons include stored text and atomic metadata; citations expose metadata only. Facts expose allowlisted derived statistics and structured scope, never arbitrary bodies. Current candidates are not active or proven. No training or provider calls. Existing consent and erasure rules apply. Evidence availability refers to retained metadata, not raw source bodies; correction-body TTL does not expire derived lessons. snapshot_at is an observation time, not a durable database snapshot. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Literal lexical substring (max 200 characters); no embeddings or model calls."},"required":false,"description":"Literal lexical substring (max 200 characters); no embeddings or model calls.","name":"q","in":"query"},{"schema":{"type":"string","description":"lesson or fact; omitted includes both."},"required":false,"description":"lesson or fact; omitted includes both.","name":"kind","in":"query"},{"schema":{"type":"string","description":"Filter to one workspace workflow."},"required":false,"description":"Filter to one workspace workflow.","name":"call_type_id","in":"query"},{"schema":{"type":"string","description":"Filter to lessons of one immutable playbook version."},"required":false,"description":"Filter to lessons of one immutable playbook version.","name":"version_id","in":"query"},{"schema":{"type":"string","description":"true includes historical and retired items; false (default) includes current facts, incumbent lessons and pending candidate/evaluating lessons."},"required":false,"description":"true includes historical and retired items; false (default) includes current facts, incumbent lessons and pending candidate/evaluating lessons.","name":"include_history","in":"query"},{"schema":{"type":"string","description":"Page size 1–100, default 50."},"required":false,"description":"Page size 1–100, default 50.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque continuation bound to workspace and unchanged filters. 400 on invalid/mismatched cursor; 409 knowledge_cursor_stale on source changes or after 15 minutes. Restart listing."},"required":false,"description":"Opaque continuation bound to workspace and unchanged filters. 400 on invalid/mismatched cursor; 409 knowledge_cursor_stale on source changes or after 15 minutes. Restart listing.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A bounded page of owned knowledge.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyKnowledgeListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/knowledge/export":{"get":{"operationId":"exportCompanyKnowledge","tags":["Knowledge"],"summary":"Export retained company knowledge content","security":[{"sessionCookie":[]}],"description":"Session-only owner/admin with 2FA and flywheel.export permission. Requires knowledge, corrections and training_export consent. Audited explicit content export ur.company_knowledge/v1; preserved /v1/flywheel/knowledge/export remains the metadata bundle. Normalized selection filters are included in the hash and manifest; complete is true only when this page contains every match of that selection, truncated includes omitted preceding pages. Resume with next_cursor; clocks and cursor excluded from content_hash. Exclusions explicitly identify unsupported/raw content. No import, activation or owned model weights.","parameters":[{"schema":{"type":"string","description":"Literal lexical substring (max 200 characters); no embeddings or model calls."},"required":false,"description":"Literal lexical substring (max 200 characters); no embeddings or model calls.","name":"q","in":"query"},{"schema":{"type":"string","description":"lesson or fact; omitted includes both."},"required":false,"description":"lesson or fact; omitted includes both.","name":"kind","in":"query"},{"schema":{"type":"string","description":"Filter to one workspace workflow."},"required":false,"description":"Filter to one workspace workflow.","name":"call_type_id","in":"query"},{"schema":{"type":"string","description":"Filter to lessons of one immutable playbook version."},"required":false,"description":"Filter to lessons of one immutable playbook version.","name":"version_id","in":"query"},{"schema":{"type":"string","description":"true includes historical and retired items; false (default) includes current facts, incumbent lessons and pending candidate/evaluating lessons."},"required":false,"description":"true includes historical and retired items; false (default) includes current facts, incumbent lessons and pending candidate/evaluating lessons.","name":"include_history","in":"query"},{"schema":{"type":"string","description":"Page size 1–100, default 50."},"required":false,"description":"Page size 1–100, default 50.","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque continuation bound to workspace and unchanged filters. 400 on invalid/mismatched cursor; 409 knowledge_cursor_stale on source changes or after 15 minutes. Restart listing."},"required":false,"description":"Opaque continuation bound to workspace and unchanged filters. 400 on invalid/mismatched cursor; 409 knowledge_cursor_stale on source changes or after 15 minutes. Restart listing.","name":"cursor","in":"query"}],"responses":{"200":{"description":"One bounded content export page.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyKnowledgeExportResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/knowledge/{id}":{"get":{"operationId":"readCompanyKnowledge","tags":["Knowledge"],"summary":"Read one company knowledge item","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Workspace members or config:read/config:write keys. Knowledge and corrections consent required; unavailable content is omitted. Lessons include stored text and atomic metadata; citations expose metadata only. Facts expose allowlisted derived statistics and structured scope, never arbitrary bodies. Current candidates are not active or proven. No training or provider calls. Existing consent and erasure rules apply. Evidence availability refers to retained metadata, not raw source bodies; correction-body TTL does not expire derived lessons. snapshot_at is an observation time, not a durable database snapshot. IDs: `fact:<fact_id>` or `lesson:<version_id>:<lesson_id>`. Unknown, foreign or erased items return 404. Requires API-key scope: config:read or config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"One retained knowledge item.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyKnowledgeDetailResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/suites/{slug}/status":{"get":{"operationId":"getBenchSuiteStatus","tags":["Bench"],"summary":"Get a bench suite readiness meter","security":[{"bearerAuth":[]}],"description":"Per-call-type confirmed capture counts (provenance) + the QUALIFIED-EVIDENCE readiness — the latest frozen dataset card (unique/cluster n, strata, preregistered power plan). There is NO raw-count `n<30` verdict — readiness is judged on the frozen, qualified evidence. Triggering a run needs the `bench:run` scope; this readiness read needs `config:read`. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"Path parameter `slug`."},"required":true,"description":"Path parameter `slug`.","name":"slug","in":"path"}],"responses":{"200":{"description":"The bench suite readiness meter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchSuiteStatusResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/suites/{slug}/freeze":{"post":{"operationId":"freezeBenchSuite","tags":["Bench"],"summary":"Freeze a bench suite into immutable weighted datasets","security":[{"bearerAuth":[]}],"description":"Snapshot the suite’s CONFIRMED capture envelopes into immutable, content-addressed, per-call-type WEIGHTED datasets (exact dedupe + near-duplicate clustering, retained frequency, golden-set strata, strict PII admission) and return each dataset CARD (counts, strata, exclusions, preregistered power plan). Re-freezing identical captures is idempotent (same `dataset_hash`). Requires scope `config:write`. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `slug`."},"required":true,"description":"Path parameter `slug`.","name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchFreezeRequest"}}}},"responses":{"200":{"description":"The frozen dataset card(s).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchDatasetFreezeResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/suites/{slug}/runs":{"post":{"operationId":"triggerBenchRun","tags":["Bench"],"summary":"Trigger an on-demand paired Bench run","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Plan one paired eval per otherwise-runnable (frozen, ≥10-unique) call type over the suite’s FROZEN dataset. `max_cost_usd` is one global umbrella reservation ceiling, never a per-child clamp and never the continuous eval envelope. Live paid dispatch is gated by the `bench.paid_dispatch` kill switch (default ON): when ON, omitting `dry_run` dispatches a real paired run (it reserves the prepaid allowance under the ceiling and makes paid provider calls, each child settling its hold truthfully); when OFF (or on an unseeded DB ⇒ fail-closed) live dispatch is refused before mutation or fan-out with HTTP 503 `atomic_spend_guard_unavailable`. `dry_run: true` always returns the estimate with no mutation and, when the switch is OFF, labels otherwise-valid paid shapes `not_runnable` with that blocker. `selection` mode emits ranked evidence and NEVER a recommendation. DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC (workspace named via `X-UR-Workspace`). Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `slug`."},"required":true,"description":"Path parameter `slug`.","name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchRunTriggerRequest"}}}},"responses":{"200":{"description":"The estimate + allowance + per-call-type dispositions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchRunTriggerResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}":{"get":{"operationId":"getBenchRun","tags":["Bench"],"summary":"Get an on-demand Bench run","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The umbrella run (status + estimate + allowance + per-call-type dispositions) plus each child eval run’s planning verdict TIER and PER-ARM evidence (incumbent + challengers: composite score, pass flag, arm cost) + the composite TRUST CLASS (A/B/C) and evidence-class tags. Read-only. DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The bench run + its child eval runs’ evidence.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchRunResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/report":{"get":{"operationId":"getBenchRunReport","tags":["Bench"],"summary":"Get the immutable Bench evidence report","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The IMMUTABLE, content-addressed evidence report for a completed on-demand Bench run. Renders IN ORDER: (1) the dataset card; (2) the power statement (unique n, planning MDE, the pre-registered margins with snapshot provenance); (3) the headline table per call type × arm — cost views BY BASIS with `$/request` vs `$/task` units honestly labeled, token components as billed units, inversion callouts, latency, quality ± intervals, evidence classes + the PINNED trust class; (4) the dual-interval verdict (or the recommendation-free selection table) with keep/inconclusive first-class + a named remediation — NO realized-savings inference, NO fictitious $0 incumbent; (5) the honest projection ONLY where trailing production volume exists; (6) the per-trace task view; (7) auto-generated limitations; (8) the reproducibility appendix. `?format=json` (default) returns this report; `?format=md` a Markdown export; `?format=bundle` an offline-verifiable evidence bundle (`pnpm evidence:verify`-consumable). All formats are audited (`bench.report.downloaded`). DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The immutable 8-section Bench evidence report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchReportResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/baseline":{"post":{"operationId":"pinBenchBaseline","tags":["Bench"],"summary":"Pin a completed Bench run as the suite baseline","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Pin a COMPLETED bench run as the suite’s baseline. The baseline anchors COMPARE mode: it captures the run’s immutable RunSpec + RETAINED arm artifacts (never a mutable config pointer). Re-pinning advances the baseline; audited (`bench.baseline.pinned`). Fails closed on an unknown / wrong-suite / not-complete run. DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The pinned suite baseline.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchBaselineResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/gate":{"get":{"operationId":"getBenchCompareGate","tags":["Bench"],"summary":"Get a compare run’s baseline-compare gate","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The interval-based tri-state verdict for a COMPARE run. Pairs the candidate’s (current-config) per-item results against the pinned BASELINE run’s RETAINED artifacts (real retained outputs, never re-invoked) BY CONTENT HASH, then yields `pass | fail | inconclusive` per call type + an INDEPENDENT absolute measured-cost ceiling check. `pass` requires BOTH the quality non-inferiority interval AND the cost-savings interval to clear their registered bars; a ceiling breach FAILS independent of quality; a missing/expired baseline artifact makes the pair ineligible and degrades toward `inconclusive` (never silently green). MDE is a POWER DIAGNOSTIC only. The umbrella verdict is the STRICTEST across call types. DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The baseline-compare gate (tri-state + intervals + ceiling).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchCompareGateResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/share":{"post":{"operationId":"mintBenchShare","tags":["Bench"],"summary":"Mint a shareable public bench-report link","security":[{"sessionCookie":[]}],"description":"Mint an IMMUTABLE, REVOCABLE, unguessable-token PUBLIC render of a completed bench run’s report SNAPSHOT (the product’s first UNAUTHENTICATED tenant-data surface). The public payload is BUILT AT MINT TIME from the immutable evidence report and frozen — a later report/config change NEVER changes a minted share. It carries aggregate metrics, model names, methodology/limitations, trust class and the evidence-contribution footer — never workspace identity beyond the chosen `display_name`, never un-redacted content, never id/key material. REDACTED example previews appear ONLY when the suite carries the audited attestation AND `include_previews` is set (opt-in never bypasses redaction). The raw token is returned exactly once (only its SHA-256 hash is stored); the public read is by token at `/share/bench/<token>`. The \"Benchmarked with ultrarouter\" footer renders on free and is removable only on Team. SESSION + owner|admin RBAC (`bench.share`) only — there is deliberately no api-key scope. Audited.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchShareMintRequest"}}}},"responses":{"201":{"description":"The share + its once-shown token + public URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchShareMintResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/shares":{"get":{"operationId":"listBenchShares","tags":["Bench"],"summary":"List a bench run’s public shares","security":[{"sessionCookie":[]}],"description":"The run’s public shares for the revoke list: metadata + coarse view counters, NEVER the token (a bearer secret shown once at mint). SESSION + owner|admin RBAC (`bench.share`).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The run’s public shares (secret-free).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchSharesListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/share/{shareId}":{"delete":{"operationId":"revokeBenchShare","tags":["Bench"],"summary":"Revoke a public bench-report share","security":[{"sessionCookie":[]}],"description":"Revoke a minted share. A revoked share becomes a public 404 (indistinguishable from unknown), effective ≤ one public-cache TTL window. SESSION + owner|admin RBAC (`bench.share`). Audited (`bench_share.revoked`).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `shareId`."},"required":true,"description":"Path parameter `shareId`.","name":"shareId","in":"path"}],"responses":{"200":{"description":"Acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/suites/{slug}/expectations":{"post":{"operationId":"attachBenchExpectations","tags":["Bench"],"summary":"Attach customer assertions to a bench suite","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Attach (`ur.bench.expect`) one or more customer ASSERTIONS mapped onto the CLOSED programmatic scorer vocabulary (json_schema / exact_field / regex_match / citation_substring). Assertions are validated (an unknown kind or malformed config is rejected), versioned and append-only; at FREEZE the applicable ones are MERGED into the call type’s compiled evaluator suite as tier-1-class evidence and the merged suite re-passes mutation qualification (a vacuous/contradictory assertion is rejected with a visible reason). They NEVER mutate a frozen dataset — they attach FORWARD. DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `slug`."},"required":true,"description":"Path parameter `slug`.","name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchExpectationsRequest"}}}},"responses":{"200":{"description":"The attached (or rejected) assertions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchExpectationsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/suites/{slug}/outcomes":{"post":{"operationId":"recordBenchSuiteOutcomes","tags":["Bench"],"summary":"Record per-trace outcomes on a bench suite","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Record (`ur.bench.record`) first-party per-trace binary OUTCOMES (pass/fail + optional labels) as the strongest human/outcome evidence class (above the LLM judge). Outcomes are scored via the McNemar/binary machinery on paired arms and feed the trace-clustered decision; they are append-only (a superseding verdict wins by version) and attach FORWARD (the next run consumes them). DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `slug`."},"required":true,"description":"Path parameter `slug`.","name":"slug","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchOutcomesRequest"}}}},"responses":{"200":{"description":"The recorded per-trace outcomes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchOutcomesResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/bench/runs/{id}/outcomes":{"post":{"operationId":"recordBenchRunOutcomes","tags":["Bench"],"summary":"Record per-trace outcomes on a bench run","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Record (`ur.bench.record`) first-party per-trace binary OUTCOMES scoped to a specific run (its suite is resolved from the run). Same McNemar/binary + trace-cluster semantics as the suite route; append-only + append-forward. DUAL AUTH: the `bench:run` scope OR a session + `bench.write` RBAC. Requires API-key scope: bench:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchOutcomesRequest"}}}},"responses":{"200":{"description":"The recorded per-trace outcomes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BenchOutcomesResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/audit/readiness":{"get":{"operationId":"getAuditReadiness","tags":["Audit"],"summary":"Get the passive Audit Autopilot readiness report","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The zero-config passive readiness rollup: inferred call types with confidence + evidence coverage, a models/providers inventory, a benchmark-readiness map that names what evidence is unavailable under the current privacy settings, and a DISCOVERY-labeled savings opportunity queue. Read-only — audit has zero authority. Requires API-key scope: config:read or config:write.","responses":{"200":{"description":"The passive readiness report (or an honest empty when not yet computed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditReadinessResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/requests/{id}/feedback":{"post":{"operationId":"submitFeedback","tags":["Feedback"],"summary":"Submit feedback on a request","security":[{"bearerAuth":[]}],"description":"Thumbs up/down + tags + optional comment, scoped to the key’s workspace. Requires API-key scope: gateway:invoke.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackRequest"}}}},"responses":{"201":{"description":"The stored feedback row, wrapped in the `feedback` envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/artifact-types":{"post":{"operationId":"upsertArtifactType","tags":["Flywheel"],"summary":"Register an artifact type / append an objective version","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Declare what “it worked” MEANS for a type of artifact (the ONE thing the product refuses to infer), so every later artifact of that type pins this objective version. Objective versions are APPEND-ONLY: an upsert whose `archetype` + `objective` are unchanged is an idempotent NO-OP returning the EXISTING version; any change APPENDS version `max+1`. Never an UPDATE, never a rewrite. NEVER a body — `resolution_criteria` is redacted free text. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpsertArtifactTypeRequest"}}}},"responses":{"200":{"description":"The CURRENT objective version (freshly appended, or the unchanged existing one).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactTypeEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/artifacts":{"post":{"operationId":"createArtifact","tags":["Flywheel"],"summary":"Create or upsert an artifact by key","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Create/upsert the customer’s unit of value by `key` (archetype, artifact_type, occurred_at, request_ids[], declared claims[], situation facets). A request already grouped into ANOTHER artifact is a `conflict` (409) with the owning artifact id. Declared claims always win their claim_key: a key the platform extractor already owns is SUPERSEDED — the extracted claim is kept under `superseded_claims` (state `superseded`, linked by `superseded_by_claim_id`) and your claim becomes the active one; re-declaring a key you already declared keeps the first declaration. NEVER a body. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateArtifactRequest"}}}},"responses":{"201":{"description":"The created/upserted artifact (metadata only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"get":{"operationId":"listArtifacts","tags":["Flywheel"],"summary":"List artifacts (metadata only)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Keyset-paginated artifact metadata (never OFFSET). Filter by archetype/key. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Page size (1–200, default 50)."},"required":false,"description":"Page size (1–200, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque keyset cursor from the prior page."},"required":false,"description":"Opaque keyset cursor from the prior page.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Filter to one archetype."},"required":false,"description":"Filter to one archetype.","name":"archetype","in":"query"},{"schema":{"type":"string","description":"Filter to one artifact key."},"required":false,"description":"Filter to one artifact key.","name":"key","in":"query"}],"responses":{"200":{"description":"A keyset page of artifacts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/artifacts/{id}":{"get":{"operationId":"getArtifact","tags":["Flywheel"],"summary":"Get an artifact (metadata only)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"One artifact + its claims (cached reducer state) + active request memberships. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The artifact (metadata only).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArtifactEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/artifacts/{id}/outcomes":{"post":{"operationId":"recordArtifactOutcomes","tags":["Flywheel"],"summary":"Record 1..N outcome events on an artifact","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Record 1..N typed outcome events for the artifact or a claim (by `claim_id`/`claim_key`). Provenance (`source`/`producer`), `latency_class` and `learning_use` are SERVER-assigned; a caller-supplied value is ignored. Idempotent on `(producer, target, kind, source_event_id)`: an identical replay is `duplicate`, a same-key different payload is `conflict`. A `claim_key` targets the key’s ACTIVE claim; a NEW event addressed by `claim_id` to a claim a declared claim superseded is `rejected` (`claim_superseded: …`, naming the active claim) — a replay of an event recorded before the supersession stays `duplicate`. 202 only after the durable insert. NEVER a body. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordOutcomesRequest"}}}},"responses":{"202":{"description":"The per-event results (accepted | duplicate | conflict | rejected).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecordOutcomesResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/artifacts/{id}/final":{"post":{"operationId":"recordArtifactFinal","tags":["Flywheel"],"summary":"Record the human-approved final output (channel 2)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Outcome channel 2 — the ONLY route that may carry a body, and ONLY under `corrections_consent`: the final is stored in the workspace’s encrypted evidence blob store and `diff_stats` are computed server-side against the draft. WITHOUT consent the caller sends CLIENT-computed `diff_stats` + `final_hash` (the SDK `diffStats` helper) and the row is `stored:\"metadata_only\"`, `client_computed:true`. A body without consent is rejected (400). Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalRequest"}}}},"responses":{"200":{"description":"The appended final artifact version.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinalResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/outcomes/batch":{"post":{"operationId":"recordOutcomesBatch","tags":["Flywheel"],"summary":"Record ≤ 1,000 outcome events in a batch","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Record ≤ 1,000 events keyed by `request_id | artifact_id | artifact_key` (+ optional `claim_key`) with per-row acceptance (`accepted | duplicate | conflict | rejected{reason} | pending`) + a verdict rollup. Same idempotency + server-assigned provenance as the single routes. A `request_id` row follows the request-outcome contract: when the request has not been recorded yet it is `pending` with a durable `receipt` (applied when the request lands), every such row carries its `receipt` (the same one the request-outcome route returns for the same `source_event_id`), and a refusal is in-row (`rejected` with `request_not_found` / `outcome_backlog_full`). NEVER a body. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchOutcomesRequest"}}}},"responses":{"200":{"description":"The per-row batch results + a verdict rollup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchOutcomesResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/outcomes/pending":{"get":{"operationId":"listPendingOutcomes","tags":["Flywheel"],"summary":"List claims awaiting resolution","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Keyset-paginated claims awaiting resolution (`state=pending|overdue`). A claim past its `resolves_by` with no resolution reads as `overdue` (never voided). Filter by `since`/`archetype`. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Page size (1–200, default 50)."},"required":false,"description":"Page size (1–200, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque keyset cursor from the prior page."},"required":false,"description":"Opaque keyset cursor from the prior page.","name":"cursor","in":"query"},{"schema":{"type":"string","description":"Only claims created at/after this ISO-8601 instant."},"required":false,"description":"Only claims created at/after this ISO-8601 instant.","name":"since","in":"query"},{"schema":{"type":"string","description":"Filter to one archetype."},"required":false,"description":"Filter to one archetype.","name":"archetype","in":"query"},{"schema":{"type":"string","description":"Filter to `pending` or `overdue` (default: both)."},"required":false,"description":"Filter to `pending` or `overdue` (default: both).","name":"state","in":"query"}],"responses":{"200":{"description":"A keyset page of claims awaiting resolution.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PendingClaimsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/requests/{id}/outcomes":{"post":{"operationId":"recordRequestOutcome","tags":["Flywheel"],"summary":"Record an outcome via the request shortcut","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Record ONE outcome for a request: it lands on the request’s existing artifact, else a one-request `answer` artifact is created. Replay identity SURVIVES regrouping (the `(producer, request_id, kind, source_event_id)` binding pins the original target/version). Report it the moment you hold the final response: when the request has not been recorded yet the answer is still 202, with `status: \"pending\"` and a durable `receipt` that is applied once the request lands (or expires `request_not_found` after 15 minutes). Every 202 carries the `receipt`; a retry with the same `source_event_id` and payload returns the same receipt and never counts twice. 400 invalid id or outcome, 404 a gateway-minted `req_…` id too old (or too far ahead) to still be in flight, 409 the same key with a different payload, 429 `outcome_backlog_full` when your workspace already holds 5,000 pending receipts. NEVER a body. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeInput"}}}},"responses":{"202":{"description":"The outcome’s result and its durable receipt.","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["accepted","duplicate","conflict","rejected","pending"],"description":"`accepted` — recorded now; `duplicate` — a retry of an outcome already recorded (no-op); `pending` — the request has not been recorded yet: the outcome is stored durably and applied when it is (poll the `receipt`). A conflict is answered 409 and a rejection 400 on this route."},"id":{"type":"string","nullable":true,"description":"The outcome-event id when accepted/duplicate; else null."},"source_event_id":{"type":"string","nullable":true},"canonical_target_id":{"type":"string","nullable":true},"target_kind":{"type":"string","nullable":true,"enum":["artifact","claim"]},"artifact_version":{"type":"integer","nullable":true},"latency_class":{"type":"string","nullable":true,"enum":["instant","delayed"]},"source":{"type":"string","nullable":true,"enum":["declared","inferred","gateway","imported"]},"learning_use":{"type":"array","nullable":true,"items":{"type":"string","enum":["train","calibrate","rank","audit"]}},"reason":{"type":"string","nullable":true,"description":"The rejection/conflict reason when not accepted."},"object":{"type":"string","enum":["outcome"]},"artifact_id":{"type":"string","nullable":true,"description":"The artifact the outcome landed on (null while `pending`)."},"receipt":{"type":"object","properties":{"object":{"type":"string","enum":["outcome_receipt"]},"id":{"type":"string","description":"The receipt id (`ocr_…`)."},"request_id":{"type":"string","description":"The request the outcome names."},"status":{"type":"string","enum":["pending","applied","rejected","failed","expired"],"description":"`pending` — the request has not been recorded yet; `applied` — the outcome is recorded; `rejected` — it failed validation once the request was known (see `reason`); `failed` — recording kept hitting an internal error; `expired` — no request with this id appeared in your workspace within 15 minutes (`reason: request_not_found`)."},"reason":{"type":"string","nullable":true,"description":"A stable machine reason when not applied: `request_not_found`, `idempotency_conflict`, `apply_failed`, or the validation reason."},"channel":{"type":"string","description":"The outcome channel as sent."},"kind":{"type":"string","description":"The outcome kind as sent."},"source_event_id":{"type":"string","description":"Your idempotency discriminator, or a server-minted one when none was sent (then a retry is a new outcome)."},"outcome_event_id":{"type":"string","nullable":true,"description":"The recorded outcome event (`oev_…`) once applied."},"outcome_status":{"type":"string","nullable":true,"enum":["accepted","duplicate"],"description":"Whether applying recorded the event for the first time (`accepted`) or found it (`duplicate`)."},"artifact_id":{"type":"string","nullable":true,"description":"The artifact the outcome landed on, once applied."},"episode":{"type":"object","properties":{"status":{"type":"string","enum":["associated","pending","not_recorded","not_applicable"],"description":"`associated` — the episode holding this request carries a verdict; `pending` — a teaching outcome waiting for its episode to be recorded; `not_recorded` — the persisted request was held out and recording was intentionally suppressed, or no episode held the request within 15 minutes (episode memory or recording off, no consent); `not_applicable` — the outcome does not teach (a proxy, behavioral or mechanical signal) or was not applied."},"trace_id":{"type":"string","nullable":true,"description":"The episode (`ept_…`) the outcome was associated with, once associated."},"verdict":{"type":"string","nullable":true,"enum":["recorded","kept_earlier","revised","revised_after_incorporation"],"description":"What the outcome did to the episode: `recorded` — it is the episode verdict; `kept_earlier` — the episode already had a verdict (the first verdict wins); `revised` — it superseded the verdict (`supersedes_event_id`) before any learned version used the episode, so the verdict was replaced; `revised_after_incorporation` — the superseded verdict was already used by a learned version: the revision is recorded and counted, the episode is not silently unlearned."}},"required":["status","trace_id","verdict"],"description":"The episode association of an applied teaching outcome."},"attempts":{"type":"integer","description":"Recording attempts that hit an internal error (bounded; then `failed`)."},"created_at":{"type":"string","description":"When the outcome was accepted."},"updated_at":{"type":"string"},"applied_at":{"type":"string","nullable":true,"description":"When the outcome was recorded."},"expires_at":{"type":"string","description":"The receipt’s next deadline: while `pending`, when it expires; while its episode association is `pending`, when that becomes `not_recorded`; once settled, when the receipt itself is deleted (30 days)."}},"required":["object","id","request_id","status","reason","channel","kind","source_event_id","outcome_event_id","outcome_status","artifact_id","episode","attempts","created_at","updated_at","applied_at","expires_at"],"description":"A durable receipt for one reported outcome."}},"required":["status","id","source_event_id","canonical_target_id","target_kind","artifact_version","latency_class","source","learning_use","reason","object","artifact_id","receipt"],"description":"One request-shortcut outcome result with its durable receipt."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/requests/{id}/outcome-receipts":{"get":{"operationId":"listRequestOutcomeReceipts","tags":["Flywheel"],"summary":"List the outcome receipts for a request","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Every outcome receipt for one request in your workspace, oldest first — `pending` until the request is recorded, then `applied` / `rejected` / `failed` / `expired`, with the episode association. A request you reported nothing for (or one of another workspace) is an empty list. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The request’s outcome receipts.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["outcome_receipt"]},"id":{"type":"string","description":"The receipt id (`ocr_…`)."},"request_id":{"type":"string","description":"The request the outcome names."},"status":{"type":"string","enum":["pending","applied","rejected","failed","expired"],"description":"`pending` — the request has not been recorded yet; `applied` — the outcome is recorded; `rejected` — it failed validation once the request was known (see `reason`); `failed` — recording kept hitting an internal error; `expired` — no request with this id appeared in your workspace within 15 minutes (`reason: request_not_found`)."},"reason":{"type":"string","nullable":true,"description":"A stable machine reason when not applied: `request_not_found`, `idempotency_conflict`, `apply_failed`, or the validation reason."},"channel":{"type":"string","description":"The outcome channel as sent."},"kind":{"type":"string","description":"The outcome kind as sent."},"source_event_id":{"type":"string","description":"Your idempotency discriminator, or a server-minted one when none was sent (then a retry is a new outcome)."},"outcome_event_id":{"type":"string","nullable":true,"description":"The recorded outcome event (`oev_…`) once applied."},"outcome_status":{"type":"string","nullable":true,"enum":["accepted","duplicate"],"description":"Whether applying recorded the event for the first time (`accepted`) or found it (`duplicate`)."},"artifact_id":{"type":"string","nullable":true,"description":"The artifact the outcome landed on, once applied."},"episode":{"type":"object","properties":{"status":{"type":"string","enum":["associated","pending","not_recorded","not_applicable"],"description":"`associated` — the episode holding this request carries a verdict; `pending` — a teaching outcome waiting for its episode to be recorded; `not_recorded` — the persisted request was held out and recording was intentionally suppressed, or no episode held the request within 15 minutes (episode memory or recording off, no consent); `not_applicable` — the outcome does not teach (a proxy, behavioral or mechanical signal) or was not applied."},"trace_id":{"type":"string","nullable":true,"description":"The episode (`ept_…`) the outcome was associated with, once associated."},"verdict":{"type":"string","nullable":true,"enum":["recorded","kept_earlier","revised","revised_after_incorporation"],"description":"What the outcome did to the episode: `recorded` — it is the episode verdict; `kept_earlier` — the episode already had a verdict (the first verdict wins); `revised` — it superseded the verdict (`supersedes_event_id`) before any learned version used the episode, so the verdict was replaced; `revised_after_incorporation` — the superseded verdict was already used by a learned version: the revision is recorded and counted, the episode is not silently unlearned."}},"required":["status","trace_id","verdict"],"description":"The episode association of an applied teaching outcome."},"attempts":{"type":"integer","description":"Recording attempts that hit an internal error (bounded; then `failed`)."},"created_at":{"type":"string","description":"When the outcome was accepted."},"updated_at":{"type":"string"},"applied_at":{"type":"string","nullable":true,"description":"When the outcome was recorded."},"expires_at":{"type":"string","description":"The receipt’s next deadline: while `pending`, when it expires; while its episode association is `pending`, when that becomes `not_recorded`; once settled, when the receipt itself is deleted (30 days)."}},"required":["object","id","request_id","status","reason","channel","kind","source_event_id","outcome_event_id","outcome_status","artifact_id","episode","attempts","created_at","updated_at","applied_at","expires_at"],"description":"A durable receipt for one reported outcome."}}},"required":["object","data"],"description":"Every outcome receipt for one request in your workspace, oldest first."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/outcome-receipts/{id}":{"get":{"operationId":"getOutcomeReceipt","tags":["Flywheel"],"summary":"Read one outcome receipt","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"One receipt (`ocr_…`): `status`, `reason`, the episode association, `channel`, `kind`, timestamps and the recorded `outcome_event_id`. 404 when it does not exist in your workspace. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The outcome receipt.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["outcome_receipt"]},"id":{"type":"string","description":"The receipt id (`ocr_…`)."},"request_id":{"type":"string","description":"The request the outcome names."},"status":{"type":"string","enum":["pending","applied","rejected","failed","expired"],"description":"`pending` — the request has not been recorded yet; `applied` — the outcome is recorded; `rejected` — it failed validation once the request was known (see `reason`); `failed` — recording kept hitting an internal error; `expired` — no request with this id appeared in your workspace within 15 minutes (`reason: request_not_found`)."},"reason":{"type":"string","nullable":true,"description":"A stable machine reason when not applied: `request_not_found`, `idempotency_conflict`, `apply_failed`, or the validation reason."},"channel":{"type":"string","description":"The outcome channel as sent."},"kind":{"type":"string","description":"The outcome kind as sent."},"source_event_id":{"type":"string","description":"Your idempotency discriminator, or a server-minted one when none was sent (then a retry is a new outcome)."},"outcome_event_id":{"type":"string","nullable":true,"description":"The recorded outcome event (`oev_…`) once applied."},"outcome_status":{"type":"string","nullable":true,"enum":["accepted","duplicate"],"description":"Whether applying recorded the event for the first time (`accepted`) or found it (`duplicate`)."},"artifact_id":{"type":"string","nullable":true,"description":"The artifact the outcome landed on, once applied."},"episode":{"type":"object","properties":{"status":{"type":"string","enum":["associated","pending","not_recorded","not_applicable"],"description":"`associated` — the episode holding this request carries a verdict; `pending` — a teaching outcome waiting for its episode to be recorded; `not_recorded` — the persisted request was held out and recording was intentionally suppressed, or no episode held the request within 15 minutes (episode memory or recording off, no consent); `not_applicable` — the outcome does not teach (a proxy, behavioral or mechanical signal) or was not applied."},"trace_id":{"type":"string","nullable":true,"description":"The episode (`ept_…`) the outcome was associated with, once associated."},"verdict":{"type":"string","nullable":true,"enum":["recorded","kept_earlier","revised","revised_after_incorporation"],"description":"What the outcome did to the episode: `recorded` — it is the episode verdict; `kept_earlier` — the episode already had a verdict (the first verdict wins); `revised` — it superseded the verdict (`supersedes_event_id`) before any learned version used the episode, so the verdict was replaced; `revised_after_incorporation` — the superseded verdict was already used by a learned version: the revision is recorded and counted, the episode is not silently unlearned."}},"required":["status","trace_id","verdict"],"description":"The episode association of an applied teaching outcome."},"attempts":{"type":"integer","description":"Recording attempts that hit an internal error (bounded; then `failed`)."},"created_at":{"type":"string","description":"When the outcome was accepted."},"updated_at":{"type":"string"},"applied_at":{"type":"string","nullable":true,"description":"When the outcome was recorded."},"expires_at":{"type":"string","description":"The receipt’s next deadline: while `pending`, when it expires; while its episode association is `pending`, when that becomes `not_recorded`; once settled, when the receipt itself is deleted (30 days)."}},"required":["object","id","request_id","status","reason","channel","kind","source_event_id","outcome_event_id","outcome_status","artifact_id","episode","attempts","created_at","updated_at","applied_at","expires_at"],"description":"A durable receipt for one reported outcome."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/workspaces/{id}/flywheel-consents":{"patch":{"operationId":"patchFlywheelConsents","tags":["Flywheel"],"summary":"Update the workspace Flywheel consents","security":[{"sessionCookie":[]}],"description":"Owner-only, audited, bumps `config_version`: `corrections_consent` (store finals), `training_export_consent` (allow the training-READY export), `corrections_retention_days`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchFlywheelConsentsRequest"}}}},"responses":{"200":{"description":"The updated Flywheel consents.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlywheelConsentsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/self-learning":{"get":{"operationId":"getSelfLearning","tags":["Flywheel"],"summary":"Read the workspace self-learning status","security":[{"sessionCookie":[]}],"description":"The effective self-learning state: knowledge + corrections consent, the retention mode (a warning when `none`, so episode memory cannot record), whether episode memory is served by default for the workspace, and every call type’s per-call-type source (`explicit` / `default` / `off`). Any member.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The workspace self-learning status.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["self_learning"]},"enabled":{"type":"boolean","description":"The one-step opt-in state: knowledge AND corrections consent are both on."},"knowledge_consent":{"type":"boolean"},"corrections_consent":{"type":"boolean"},"retention_mode":{"type":"string","description":"The workspace retention mode (`none` / `metadata` / `full`)."},"retention_warning":{"type":"string","nullable":true,"description":"A warning when retention is `none` (episode memory cannot record), else null."},"served_by_default":{"type":"boolean","description":"Whether episode memory is served by default for the workspace (the platform default-on switch is on AND the knowledge permission holds)."},"lab_authorised":{"type":"boolean","description":"The staff-granted per-workspace lab authorisation (`flywheel.episode_memory_lab`)."},"config_version":{"type":"integer"},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"slug":{"type":"string"},"source":{"type":"string","enum":["explicit","default","off"],"description":"`explicit` (a per-call-type setting), `default` (follows the workspace default), or `off`."},"active":{"type":"boolean","description":"Whether episode memory would serve + record for this call type now (lab / default honoured)."}},"required":["call_type_id","slug","source","active"],"description":"A call type’s episode-memory state."}}},"required":["object","enabled","knowledge_consent","corrections_consent","retention_mode","retention_warning","served_by_default","lab_authorised","config_version","call_types"],"description":"The workspace’s effective self-learning state."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"putSelfLearning","tags":["Flywheel"],"summary":"Set the one-step self-learning opt-in","security":[{"sessionCookie":[]}],"description":"The ONE-STEP owner opt-in that makes episode memory plug-and-play. ON turns on knowledge consent (a new optimization-authorization version preserving every other field — or the manual-routing / byok onboarding defaults when none exists) AND corrections consent, so every call type with no explicit setting learns by default. OFF revokes both (which hard-deletes the workspace’s episode traces). owner|admin, audited, bumps `config_version`; idempotent. This never flips the platform default-on switch.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Turn self-learning ON or OFF. ON = knowledge + corrections consent on (episode memory learns from the workspace's own verified episodes by default); OFF revokes both and deletes the episode traces."}},"required":["enabled"],"additionalProperties":false,"description":"Set the one-step self-learning opt-in (owner/admin, audited, bumps config_version)."}}}},"responses":{"200":{"description":"The updated self-learning status.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["self_learning"]},"enabled":{"type":"boolean","description":"The one-step opt-in state: knowledge AND corrections consent are both on."},"knowledge_consent":{"type":"boolean"},"corrections_consent":{"type":"boolean"},"retention_mode":{"type":"string","description":"The workspace retention mode (`none` / `metadata` / `full`)."},"retention_warning":{"type":"string","nullable":true,"description":"A warning when retention is `none` (episode memory cannot record), else null."},"served_by_default":{"type":"boolean","description":"Whether episode memory is served by default for the workspace (the platform default-on switch is on AND the knowledge permission holds)."},"lab_authorised":{"type":"boolean","description":"The staff-granted per-workspace lab authorisation (`flywheel.episode_memory_lab`)."},"config_version":{"type":"integer"},"call_types":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"slug":{"type":"string"},"source":{"type":"string","enum":["explicit","default","off"],"description":"`explicit` (a per-call-type setting), `default` (follows the workspace default), or `off`."},"active":{"type":"boolean","description":"Whether episode memory would serve + record for this call type now (lab / default honoured)."}},"required":["call_type_id","slug","source","active"],"description":"A call type’s episode-memory state."}}},"required":["object","enabled","knowledge_consent","corrections_consent","retention_mode","retention_warning","served_by_default","lab_authorised","config_version","call_types"],"description":"The workspace’s effective self-learning state."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/training":{"get":{"operationId":"getTrainingStatus","tags":["Flywheel"],"summary":"Read the workspace training-authorisation status","security":[{"sessionCookie":[]}],"description":"The training AUTHORISATION status: the two switches (customer `training_enabled` + the superadmin-only platform switch), the pure six-conjunct `train_allowed` verdict and the conjuncts that FAILED (fail-closed), and the authorisation epoch. Training is allowed ONLY per-workspace, behind the gate; `training_export_consent` is NOT a conjunct (enabling the export never authorises training). RBAC `training.read` (any member).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The workspace training-authorisation status.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["training_status"]},"training_enabled":{"type":"boolean","description":"The customer switch (the workspace_enabled conjunct)."},"platform_enabled":{"type":"boolean","description":"The superadmin-only platform switch (the platform_enabled conjunct)."},"train_allowed":{"type":"boolean","description":"Whether the six-conjunct `train_allowed` gate holds (allowed ⇒ every conjunct true)."},"failed_conjuncts":{"type":"array","items":{"type":"string","enum":["platform_enabled","workspace_enabled","contract_authorized","source_eligible","retention_valid","provider_approved"]},"description":"The conjuncts that failed, fail-closed (empty ⇒ train_allowed)."},"training_epoch":{"type":"integer","description":"The current authorisation epoch (advances on revocation)."},"config_version":{"type":"integer"}},"required":["object","training_enabled","platform_enabled","train_allowed","failed_conjuncts","training_epoch","config_version"],"description":"The workspace training-authorisation status."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"patchTraining","tags":["Flywheel"],"summary":"Set the per-workspace training switch","security":[{"sessionCookie":[]}],"description":"Flip the CUSTOMER-VISIBLE per-workspace training switch (the `workspace_enabled` conjunct). owner|admin, audited, bumps `config_version`. Turning it OFF invalidates the authorisation epoch: serving of this workspace's adapters stops and active jobs are cancelled within one 5 s window, and a stale provider callback restores nothing (even after re-enabling). A superadmin can NEVER reach this action, so a customer OFF is never overridable. RBAC `training.write`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","description":"Turn per-workspace training ON or OFF. OFF invalidates the authorisation epoch: serving of this workspace's adapters stops and active jobs are cancelled; re-enabling never restores a stale artifact."}},"required":["enabled"],"additionalProperties":false,"description":"Set the per-workspace training switch (owner/admin, audited, bumps config_version)."}}}},"responses":{"200":{"description":"The updated training-authorisation status.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["training_status"]},"training_enabled":{"type":"boolean","description":"The customer switch (the workspace_enabled conjunct)."},"platform_enabled":{"type":"boolean","description":"The superadmin-only platform switch (the platform_enabled conjunct)."},"train_allowed":{"type":"boolean","description":"Whether the six-conjunct `train_allowed` gate holds (allowed ⇒ every conjunct true)."},"failed_conjuncts":{"type":"array","items":{"type":"string","enum":["platform_enabled","workspace_enabled","contract_authorized","source_eligible","retention_valid","provider_approved"]},"description":"The conjuncts that failed, fail-closed (empty ⇒ train_allowed)."},"training_epoch":{"type":"integer","description":"The current authorisation epoch (advances on revocation)."},"config_version":{"type":"integer"}},"required":["object","training_enabled","platform_enabled","train_allowed","failed_conjuncts","training_epoch","config_version"],"description":"The workspace training-authorisation status."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/model-policy":{"get":{"operationId":"getModelPolicy","tags":["Workspaces"],"summary":"Read the workspace model policy","security":[{"sessionCookie":[]}],"description":"The workspace MODEL POLICY (which models this workspace may run): a preset (`us_only` | `global` | `custom`) plus per-model/per-provider/per-lab allow-deny rules and the US-hosted open-weight exception. Default `global` when unset. RBAC `model_policy.read`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The workspace model policy.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["model_policy"]},"preset":{"type":"string","enum":["us_only","global","custom"]},"custom_base":{"type":"string","enum":["allow","deny"]},"rules":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["model"]},"model_id":{"type":"string","minLength":1,"description":"The logical or concrete catalog model id."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","model_id","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["provider"]},"provider_slug":{"type":"string","minLength":1,"description":"The serving provider slug (e.g. `together`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","provider_slug","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["lab"]},"jurisdiction":{"type":"string","minLength":1,"description":"The developing lab's ISO 3166-1 alpha-2 jurisdiction (e.g. `CN`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","jurisdiction","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["allow_us_hosted_open_weight"]}},"required":["type"],"additionalProperties":false,"description":"Exception: allow a denied lab’s OPEN-WEIGHT models WHEN they are US-hosted (both established)."}],"description":"A workspace model-policy rule."}},"phi_handling":{"type":"boolean"},"updated_at":{"type":"string","nullable":true},"updated_by":{"type":"string","nullable":true},"config_version":{"type":"integer","nullable":true}},"required":["object","preset","custom_base","rules","phi_handling","updated_at","updated_by","config_version"],"description":"The workspace model policy."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"putModelPolicy","tags":["Workspaces"],"summary":"Replace the workspace model policy","security":[{"sessionCookie":[]}],"description":"REPLACE the workspace MODEL POLICY. Enforced everywhere a model is picked (routing/fallbacks, eval/bench candidates, recommendations, flywheel/eval replays) through the ONE versioned-config snapshot; a denied model is a pre-dispatch `model_denied_by_policy` refusal. owner|admin, audited, bumps `config_version`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preset":{"type":"string","enum":["us_only","global","custom"],"description":"The base preset."},"custom_base":{"type":"string","enum":["allow","deny"],"default":"allow","description":"Base verdict when no rule matches AND preset=custom (ignored otherwise)."},"rules":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["model"]},"model_id":{"type":"string","minLength":1,"description":"The logical or concrete catalog model id."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","model_id","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["provider"]},"provider_slug":{"type":"string","minLength":1,"description":"The serving provider slug (e.g. `together`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","provider_slug","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["lab"]},"jurisdiction":{"type":"string","minLength":1,"description":"The developing lab's ISO 3166-1 alpha-2 jurisdiction (e.g. `CN`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","jurisdiction","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["allow_us_hosted_open_weight"]}},"required":["type"],"additionalProperties":false,"description":"Exception: allow a denied lab’s OPEN-WEIGHT models WHEN they are US-hosted (both established)."}],"description":"A workspace model-policy rule."},"default":[],"description":"The allow/deny rules + exception."},"phi_handling":{"type":"boolean","default":false,"description":"Mark this workspace PHI-bearing. When true the policy DENIES any model whose serving provider is not recorded as BAA-covered (unknown ⇒ deny, fail-closed) and payload retention tightens to metadata. NOTE: this is a technical control only — a signed BAA with each subprocessor and with the customer is a separate legal step."}},"required":["preset"],"additionalProperties":false,"description":"Replace the workspace model policy (owner|admin, audited, bumps config_version)."}}}},"responses":{"200":{"description":"The stored workspace model policy.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["model_policy"]},"preset":{"type":"string","enum":["us_only","global","custom"]},"custom_base":{"type":"string","enum":["allow","deny"]},"rules":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["model"]},"model_id":{"type":"string","minLength":1,"description":"The logical or concrete catalog model id."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","model_id","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["provider"]},"provider_slug":{"type":"string","minLength":1,"description":"The serving provider slug (e.g. `together`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","provider_slug","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["lab"]},"jurisdiction":{"type":"string","minLength":1,"description":"The developing lab's ISO 3166-1 alpha-2 jurisdiction (e.g. `CN`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","jurisdiction","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["allow_us_hosted_open_weight"]}},"required":["type"],"additionalProperties":false,"description":"Exception: allow a denied lab’s OPEN-WEIGHT models WHEN they are US-hosted (both established)."}],"description":"A workspace model-policy rule."}},"phi_handling":{"type":"boolean"},"updated_at":{"type":"string","nullable":true},"updated_by":{"type":"string","nullable":true},"config_version":{"type":"integer","nullable":true}},"required":["object","preset","custom_base","rules","phi_handling","updated_at","updated_by","config_version"],"description":"The workspace model policy."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/passthrough-policy":{"get":{"operationId":"getPassthroughPolicy","tags":["Workspaces"],"summary":"Read the workspace native-passthrough routing policy","security":[{"sessionCookie":[]}],"description":"The per-workspace NATIVE-PASSTHROUGH routing policy: stage-keyed rules that let the gateway swap a `POST /v1/responses` / `POST /v1/messages` request’s model from its call tags (`X-UR-Call-Type` / `X-UR-Trace.stage` / body model), optionally injecting Anthropic prefix caching — the product form of moving a cheap stage off the frontier model with no code change. Default disabled when unset. RBAC `passthrough_policy.read`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The workspace passthrough routing policy.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["passthrough_policy"]},"enabled":{"type":"boolean"},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"description":"A stable, workspace-unique rule id (echoed into routing_decision.passthrough_rule)."},"match":{"type":"object","properties":{"call_type":{"type":"string","minLength":1,"description":"Match the `X-UR-Call-Type` slug the request is tagged with."},"trace_stage":{"type":"string","minLength":1,"description":"Match the `stage` field inside the request’s `X-UR-Trace` JSON object."},"model":{"type":"string","minLength":1,"description":"Match the model the request body names (the caller’s requested model)."},"api_key_id":{"type":"string","minLength":1,"description":"Match only requests made with THIS API key (`key_…`) — run several arms side by side, one per key."}},"default":{},"additionalProperties":false,"description":"A passthrough rule match predicate (an empty object is a catch-all)."},"serve":{"type":"object","properties":{"model":{"type":"string","minLength":1,"description":"The model the gateway serves instead of the requested one."},"protocol":{"type":"string","enum":["native","openai_chat"],"default":"native","description":"How the served model is reached. `native` (default) forwards the body verbatim on its own family (same-family, or a custom provider speaking the native API). `openai_chat` serves a model that speaks OpenAI chat completions — the gateway translates the request, response and stream both ways, so an Anthropic or OpenAI SDK app can be served by an open model across families with no code change."},"reasoning_effort":{"type":"string","enum":["low","medium","high"],"description":"Force this reasoning effort on the cross-family translated request, overriding whatever the client asked (Anthropic `output_config.effort` / `thinking`, Responses `reasoning.effort`) — so a heavy reasoner can be served at a lower effort instead of spending the whole `max_tokens` budget on reasoning and never answering. Valid ONLY with `protocol: \"openai_chat\"` (the policy is refused, naming the rule, otherwise)."}},"required":["model"],"additionalProperties":false,"description":"What the matched request is served with (the model rewrite). OPTIONAL: an inject-only rule leaves the model verbatim."},"cache":{"type":"string","enum":["off","anthropic_prefix"],"default":"off","description":"Prompt-cache strategy: `anthropic_prefix` injects `cache_control: ephemeral` on the Anthropic system block + the first user message’s largest text block (ignored for OpenAI)."},"inject":{"type":"object","properties":{"experiment_pack_id":{"type":"string","minLength":1,"description":"The experiment pack id (`xpk_…`) whose ≤ 800-token learned pack is inserted into the matched request’s learned reference slot. Validated (exists, not revoked, same workspace) at set time."}},"required":["experiment_pack_id"],"additionalProperties":false,"description":"Insert a learned experiment pack into the matched request’s learned reference slot. Carried ALONGSIDE or INSTEAD OF `serve`; an inject rule must match a call type. May be combined with a cross-family (`openai_chat`) serve — the pack is placed into the native body, then that body is translated."}},"required":["id"],"additionalProperties":false,"description":"A native-passthrough stage-keyed routing + live-injection rule."}},"updated_at":{"type":"string","nullable":true},"updated_by":{"type":"string","nullable":true},"config_version":{"type":"integer","nullable":true}},"required":["object","enabled","rules","updated_at","updated_by","config_version"],"description":"The workspace passthrough routing policy."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"put":{"operationId":"putPassthroughPolicy","tags":["Workspaces"],"summary":"Replace the workspace native-passthrough routing policy","security":[{"sessionCookie":[]}],"description":"REPLACE the per-workspace native-passthrough routing policy. Applied on `POST /v1/responses` and `POST /v1/messages`: the FIRST matching rule rewrites the body’s model to its served model (SAME provider family only — a cross-family rule is refused here by name), which must be priced and active in the catalog; everything else in the body is left verbatim. owner|admin, audited, bumps `config_version` (visible within one 5 s cache window).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"enabled":{"type":"boolean","default":false,"description":"Master switch — when false no rule fires (the kill switch)."},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"description":"A stable, workspace-unique rule id (echoed into routing_decision.passthrough_rule)."},"match":{"type":"object","properties":{"call_type":{"type":"string","minLength":1,"description":"Match the `X-UR-Call-Type` slug the request is tagged with."},"trace_stage":{"type":"string","minLength":1,"description":"Match the `stage` field inside the request’s `X-UR-Trace` JSON object."},"model":{"type":"string","minLength":1,"description":"Match the model the request body names (the caller’s requested model)."},"api_key_id":{"type":"string","minLength":1,"description":"Match only requests made with THIS API key (`key_…`) — run several arms side by side, one per key."}},"default":{},"additionalProperties":false,"description":"A passthrough rule match predicate (an empty object is a catch-all)."},"serve":{"type":"object","properties":{"model":{"type":"string","minLength":1,"description":"The model the gateway serves instead of the requested one."},"protocol":{"type":"string","enum":["native","openai_chat"],"default":"native","description":"How the served model is reached. `native` (default) forwards the body verbatim on its own family (same-family, or a custom provider speaking the native API). `openai_chat` serves a model that speaks OpenAI chat completions — the gateway translates the request, response and stream both ways, so an Anthropic or OpenAI SDK app can be served by an open model across families with no code change."},"reasoning_effort":{"type":"string","enum":["low","medium","high"],"description":"Force this reasoning effort on the cross-family translated request, overriding whatever the client asked (Anthropic `output_config.effort` / `thinking`, Responses `reasoning.effort`) — so a heavy reasoner can be served at a lower effort instead of spending the whole `max_tokens` budget on reasoning and never answering. Valid ONLY with `protocol: \"openai_chat\"` (the policy is refused, naming the rule, otherwise)."}},"required":["model"],"additionalProperties":false,"description":"What the matched request is served with (the model rewrite). OPTIONAL: an inject-only rule leaves the model verbatim."},"cache":{"type":"string","enum":["off","anthropic_prefix"],"default":"off","description":"Prompt-cache strategy: `anthropic_prefix` injects `cache_control: ephemeral` on the Anthropic system block + the first user message’s largest text block (ignored for OpenAI)."},"inject":{"type":"object","properties":{"experiment_pack_id":{"type":"string","minLength":1,"description":"The experiment pack id (`xpk_…`) whose ≤ 800-token learned pack is inserted into the matched request’s learned reference slot. Validated (exists, not revoked, same workspace) at set time."}},"required":["experiment_pack_id"],"additionalProperties":false,"description":"Insert a learned experiment pack into the matched request’s learned reference slot. Carried ALONGSIDE or INSTEAD OF `serve`; an inject rule must match a call type. May be combined with a cross-family (`openai_chat`) serve — the pack is placed into the native body, then that body is translated."}},"required":["id"],"additionalProperties":false,"description":"A native-passthrough stage-keyed routing + live-injection rule."},"maxItems":100,"default":[],"description":"The stage-keyed rules, evaluated in order (first match wins)."}},"additionalProperties":false,"description":"Replace the workspace passthrough routing policy (owner|admin, audited, bumps config_version)."}}}},"responses":{"200":{"description":"The stored workspace passthrough routing policy.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["passthrough_policy"]},"enabled":{"type":"boolean"},"rules":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1,"maxLength":128,"description":"A stable, workspace-unique rule id (echoed into routing_decision.passthrough_rule)."},"match":{"type":"object","properties":{"call_type":{"type":"string","minLength":1,"description":"Match the `X-UR-Call-Type` slug the request is tagged with."},"trace_stage":{"type":"string","minLength":1,"description":"Match the `stage` field inside the request’s `X-UR-Trace` JSON object."},"model":{"type":"string","minLength":1,"description":"Match the model the request body names (the caller’s requested model)."},"api_key_id":{"type":"string","minLength":1,"description":"Match only requests made with THIS API key (`key_…`) — run several arms side by side, one per key."}},"default":{},"additionalProperties":false,"description":"A passthrough rule match predicate (an empty object is a catch-all)."},"serve":{"type":"object","properties":{"model":{"type":"string","minLength":1,"description":"The model the gateway serves instead of the requested one."},"protocol":{"type":"string","enum":["native","openai_chat"],"default":"native","description":"How the served model is reached. `native` (default) forwards the body verbatim on its own family (same-family, or a custom provider speaking the native API). `openai_chat` serves a model that speaks OpenAI chat completions — the gateway translates the request, response and stream both ways, so an Anthropic or OpenAI SDK app can be served by an open model across families with no code change."},"reasoning_effort":{"type":"string","enum":["low","medium","high"],"description":"Force this reasoning effort on the cross-family translated request, overriding whatever the client asked (Anthropic `output_config.effort` / `thinking`, Responses `reasoning.effort`) — so a heavy reasoner can be served at a lower effort instead of spending the whole `max_tokens` budget on reasoning and never answering. Valid ONLY with `protocol: \"openai_chat\"` (the policy is refused, naming the rule, otherwise)."}},"required":["model"],"additionalProperties":false,"description":"What the matched request is served with (the model rewrite). OPTIONAL: an inject-only rule leaves the model verbatim."},"cache":{"type":"string","enum":["off","anthropic_prefix"],"default":"off","description":"Prompt-cache strategy: `anthropic_prefix` injects `cache_control: ephemeral` on the Anthropic system block + the first user message’s largest text block (ignored for OpenAI)."},"inject":{"type":"object","properties":{"experiment_pack_id":{"type":"string","minLength":1,"description":"The experiment pack id (`xpk_…`) whose ≤ 800-token learned pack is inserted into the matched request’s learned reference slot. Validated (exists, not revoked, same workspace) at set time."}},"required":["experiment_pack_id"],"additionalProperties":false,"description":"Insert a learned experiment pack into the matched request’s learned reference slot. Carried ALONGSIDE or INSTEAD OF `serve`; an inject rule must match a call type. May be combined with a cross-family (`openai_chat`) serve — the pack is placed into the native body, then that body is translated."}},"required":["id"],"additionalProperties":false,"description":"A native-passthrough stage-keyed routing + live-injection rule."}},"updated_at":{"type":"string","nullable":true},"updated_by":{"type":"string","nullable":true},"config_version":{"type":"integer","nullable":true}},"required":["object","enabled","rules","updated_at","updated_by","config_version"],"description":"The workspace passthrough routing policy."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/experiment-packs":{"post":{"operationId":"createExperimentPack","tags":["Workspaces"],"summary":"Load a live-injection experiment pack","security":[{"sessionCookie":[]}],"description":"Load a small, experiment-labeled learned PLAYBOOK (a `ur:learned` reference block ≤ 800 tokens) that a passthrough rule’s `inject` can bind to a (call type × api key). A matching `POST /v1/messages` / `POST /v1/responses` request gets the pack inserted into the learned reference slot, stamped, bounded and fail-safe. The module TEXT is stored in encrypted blob storage under `corrections_consent` — a create is REFUSED when consent is off, when the text exceeds 800 tokens by the core estimator, or when it is not a `ur:learned` shape. NOT a product lever adoption, NOT a holdout arm. owner|admin session (`flywheel.write`), audited (ids / hashes only); never returns the text.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":200,"description":"A human label for the pack (e.g. the lab build it came from)."},"call_type_id":{"type":"string","minLength":1,"description":"The call type (`ct_…`) the pack is for — a bound inject rule matches this call type."},"module_text":{"type":"string","minLength":1,"description":"The learned pack TEXT — a `ur:learned` reference block (≤ 800 tokens by the core estimator). Stored in encrypted blob storage under `corrections_consent`; never echoed back in any response."},"source":{"type":"string","minLength":1,"maxLength":120,"default":"lab_build:ai","description":"The pack provenance tag (e.g. `lab_build:ai`) — analysis separates the injected arm by it."}},"required":["name","call_type_id","module_text"],"additionalProperties":false,"description":"Load a new experiment pack (owner|admin, session only, audited; refused when consent is off)."}}}},"responses":{"201":{"description":"The loaded experiment pack (metadata only).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["experiment_pack"]},"id":{"type":"string","description":"The pack id (`xpk_…`)."},"call_type_id":{"type":"string","description":"The call type the pack is for."},"name":{"type":"string"},"module_hash":{"type":"string"},"tokens":{"type":"integer"},"source":{"type":"string"},"created_by":{"type":"string","nullable":true},"created_at":{"type":"string"},"revoked_at":{"type":"string","nullable":true}},"required":["object","id","call_type_id","name","module_hash","tokens","source","created_by","created_at","revoked_at"],"description":"An experiment pack (metadata only — the module text is never returned)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listExperimentPacks","tags":["Workspaces"],"summary":"List the workspace live-injection experiment packs","security":[{"sessionCookie":[]}],"description":"LIST the workspace experiment packs, newest first — ids / `module_hash` / token count / source / created + revoked timestamps only (never the module text). owner|admin session (`flywheel.write`).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The workspace experiment packs (empty when none).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["experiment_pack_list"]},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["experiment_pack"]},"id":{"type":"string","description":"The pack id (`xpk_…`)."},"call_type_id":{"type":"string","description":"The call type the pack is for."},"name":{"type":"string"},"module_hash":{"type":"string"},"tokens":{"type":"integer"},"source":{"type":"string"},"created_by":{"type":"string","nullable":true},"created_at":{"type":"string"},"revoked_at":{"type":"string","nullable":true}},"required":["object","id","call_type_id","name","module_hash","tokens","source","created_by","created_at","revoked_at"],"description":"An experiment pack (metadata only — the module text is never returned)."}}},"required":["object","data"],"description":"The workspace experiment packs (empty when none)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/experiment-packs/{packId}":{"delete":{"operationId":"revokeExperimentPack","tags":["Workspaces"],"summary":"Revoke a live-injection experiment pack","security":[{"sessionCookie":[]}],"description":"REVOKE an experiment pack (set `revoked_at`). A revoked pack is no longer injected on any matching request — the gateway serves verbatim with a recorded skip — within one 5 s config window (a revoke bumps `config_version`). The module body rides the corrections-body retention sweep. owner|admin session (`flywheel.write`), audited.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `packId`."},"required":true,"description":"Path parameter `packId`.","name":"packId","in":"path"}],"responses":{"200":{"description":"The revoked experiment pack (metadata only).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["experiment_pack"]},"id":{"type":"string","description":"The pack id (`xpk_…`)."},"call_type_id":{"type":"string","description":"The call type the pack is for."},"name":{"type":"string"},"module_hash":{"type":"string"},"tokens":{"type":"integer"},"source":{"type":"string"},"created_by":{"type":"string","nullable":true},"created_at":{"type":"string"},"revoked_at":{"type":"string","nullable":true}},"required":["object","id","call_type_id","name","module_hash","tokens","source","created_by","created_at","revoked_at"],"description":"An experiment pack (metadata only — the module text is never returned)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/model-policy/preview":{"post":{"operationId":"previewModelPolicy","tags":["Workspaces"],"summary":"Preview a proposed model policy against the live catalog","security":[{"sessionCookie":[]}],"description":"Evaluate a PROPOSED policy against the LIVE catalog WITHOUT mutating anything: allow/deny counts by lab and by provider, the denied logical models, and the input-price range lost. Exactly what the dashboard onboarding wizard shows. RBAC `model_policy.read`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"preset":{"type":"string","enum":["us_only","global","custom"],"description":"The base preset."},"custom_base":{"type":"string","enum":["allow","deny"],"default":"allow","description":"Base verdict when no rule matches AND preset=custom (ignored otherwise)."},"rules":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"type":{"type":"string","enum":["model"]},"model_id":{"type":"string","minLength":1,"description":"The logical or concrete catalog model id."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","model_id","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["provider"]},"provider_slug":{"type":"string","minLength":1,"description":"The serving provider slug (e.g. `together`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","provider_slug","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["lab"]},"jurisdiction":{"type":"string","minLength":1,"description":"The developing lab's ISO 3166-1 alpha-2 jurisdiction (e.g. `CN`)."},"effect":{"type":"string","enum":["allow","deny"]}},"required":["type","jurisdiction","effect"],"additionalProperties":false},{"type":"object","properties":{"type":{"type":"string","enum":["allow_us_hosted_open_weight"]}},"required":["type"],"additionalProperties":false,"description":"Exception: allow a denied lab’s OPEN-WEIGHT models WHEN they are US-hosted (both established)."}],"description":"A workspace model-policy rule."},"default":[],"description":"The allow/deny rules + exception."},"phi_handling":{"type":"boolean","default":false,"description":"Mark this workspace PHI-bearing. When true the policy DENIES any model whose serving provider is not recorded as BAA-covered (unknown ⇒ deny, fail-closed) and payload retention tightens to metadata. NOTE: this is a technical control only — a signed BAA with each subprocessor and with the customer is a separate legal step."}},"required":["preset"],"additionalProperties":false,"description":"A proposed model policy to evaluate against the live catalog (no mutation)."}}}},"responses":{"200":{"description":"What the proposed policy would allow/deny.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["model_policy_preview"]},"total_offers":{"type":"integer"},"allowed_offers":{"type":"integer"},"denied_offers":{"type":"integer"},"by_lab":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"allowed":{"type":"integer"},"denied":{"type":"integer"}},"required":["key","allowed","denied"],"additionalProperties":false}},"by_provider":{"type":"array","items":{"type":"object","properties":{"key":{"type":"string"},"allowed":{"type":"integer"},"denied":{"type":"integer"}},"required":["key","allowed","denied"],"additionalProperties":false}},"cheapest_denied_input_micro_usd_per_1m":{"type":"integer","nullable":true},"dearest_denied_input_micro_usd_per_1m":{"type":"integer","nullable":true},"denied_models":{"type":"array","items":{"type":"string"}}},"required":["object","total_offers","allowed_offers","denied_offers","by_lab","by_provider","cheapest_denied_input_micro_usd_per_1m","dearest_denied_input_micro_usd_per_1m","denied_models"],"description":"The result of evaluating a proposed model policy against the live catalog."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/site-brief":{"put":{"operationId":"putSiteBrief","tags":["Flywheel"],"summary":"Request the site-brief fetch (hybrid onboarding)","security":[{"sessionCookie":[]}],"description":"Request a fetch of the customer’s public website/docs (hybrid onboarding’s first source). Give an explicit `url`, or omit it to INFER `https://<signup-email-domain>` (only for a non-public-mailbox domain). The URL is validated through the ONE shared SSRF guard synchronously (a private/loopback host is a 400) before a `site_brief.fetch` job is enqueued. RBAC `flywheel.write`; audited. The brief is stored REDACTED bytes read by no consumer yet — never a page body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutSiteBriefRequest"}}}},"responses":{"202":{"description":"The accepted (pending) site-brief status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteBriefResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"getSiteBrief","tags":["Flywheel"],"summary":"The workspace site-brief status","security":[{"sessionCookie":[]}],"description":"The newest site-brief status: status, source, the fetched URL, the content hash + retrieval date, the redacted text length, and the per-category redaction counts. NEVER the page text (it is read server-side only). RBAC `flywheel.read`.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The workspace site-brief status (never the page text).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SiteBriefResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/flywheel/grants":{"post":{"operationId":"mintExposureGrant","tags":["Flywheel"],"summary":"Mint an exposure grant for a non-proxied call","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The deterministic derivation of the SAME `assignExposure` the gateway stamps at dispatch, minted by the sanctioned owner so a NON-proxied call (the SDK/preflight) can join the treated/holdout arm and have its lift measured. Body: `{ call_type?, artifact_key | trace_id }` (one of artifact_key/trace_id REQUIRED). Idempotent: the SAME key in the SAME epoch returns the SAME grant and writes NO second `requests` row. Writes a zero-cost `status=preflight` served record so lift denominators + `/v1/generation` see it. Auth: an api key with `outcomes:write`, OR a Better Auth session + `flywheel.write` RBAC. NEVER cached; NEVER a body. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"call_type":{"type":"string","maxLength":256,"description":"The call type the grant is for (resolves the lever state + the recommended pin)."},"artifact_key":{"type":"string","minLength":1,"maxLength":512,"description":"The declared artifact key — the cluster key (REQUIRED unless `trace_id` is given)."},"trace_id":{"type":"string","minLength":1,"maxLength":512,"description":"The trace id — the cluster key when no artifact is declared (REQUIRED unless `artifact_key`)."}},"additionalProperties":false,"description":"Mint the deterministic exposure grant for a non-proxied call (never cached)."}}}},"responses":{"200":{"description":"The exposure grant + its served-record id (arm assigned by the sanctioned owner).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["exposure_grant"]},"grant_id":{"type":"string","description":"Deterministic: hash of workspace + cluster key + epoch (idempotent)."},"arm":{"type":"string","enum":["treated","holdout","lever_holdout","pre_lever"],"description":"The exposure arm the grant assigns (the SAME assignment the gateway stamps at dispatch)."},"lever_id":{"type":"string","nullable":true,"description":"The lever family when the arm is lever-derived, else null."},"epoch":{"type":"integer","description":"The assignment epoch (lift is never pooled across epochs)."},"valid_until_epoch_close":{"type":"string","description":"A conservative ISO validity horizon; re-mint on a newer epoch (never cached)."},"request_id":{"type":"string","description":"The zero-cost `status=preflight` served-record id (the served proof)."}},"required":["object","grant_id","arm","lever_id","epoch","valid_until_epoch_close","request_id"],"description":"The exposure grant for a non-proxied call (the arm is assigned by the server, never the caller)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/review/assist":{"post":{"operationId":"reviewAssist","tags":["Flywheel"],"summary":"Fix with AI — revise a review-queue draft (billed as the customer’s own usage)","security":[{"sessionCookie":[]}],"description":"The review queue’s \"Fix with AI\": the server reads the FULL draft of `item_id` (consent + retention gated, audited), composes a prompt from the draft + the reviewer’s optional `note` + optional `reject_reason`, and dispatches ONE chat completion through the SAME metered gateway path as `/v1/chat/completions` — call type `ur_review_assist`, the model fixed by the server — so it is the customer’s OWN usage (a `requests` row + `gateway_call` ledger row + the workspace spend caps all apply). The returned `revision` fills the editor for the human to accept / change / discard — it is NEVER stored as a Final or an outcome by itself. A workspace spend-cap breach is a named 402. OWNER/member SESSION only (`flywheel.write`), never an api key; audited (`flywheel.review.assist`, ids / hashes only). The session path names its workspace via the `X-UR-Workspace` header. NEVER a body in a log.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewAssistRequest"}}}},"responses":{"200":{"description":"The revision + the metered request id + the cost in micro-USD.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewAssistResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/status":{"get":{"operationId":"getFlywheelStatus","tags":["Flywheel"],"summary":"Flywheel status — capture counts + integration health","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The four SEPARATED usage quantities (operational capture counters vs the PAID analysis units + evaluation compute, never merged), integration health (channels detected + history-import summary), with the LEARNING fields (confirmation/class/calibration) explicitly UNAVAILABLE on this read. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC (the session path names its workspace via the `X-UR-Workspace` header). NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The Flywheel status (capture counts + integration health + unavailable learning fields).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FlywheelStatusResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/moat-next":{"get":{"operationId":"getMoatNext","tags":["Flywheel"],"summary":"What your moat needs next — per-unit readiness + the missing precondition","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The meta-scheduler status projection. Per scheduling unit (call type × lever family × situation class): whether it is ready to improve and its scheduling verdict, or WHICH readiness precondition is missing, in the customer’s terms (\"this call type needs 140 more resolved claims in this situation class\"). A bare `false` is never returned — `next_action` is always a sentence. Reads the LATEST scheduling decision per unit. Optional `lever_family` filter. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"Filter to one lever family (e.g. `learned_context`)."},"required":false,"description":"Filter to one lever family (e.g. `learned_context`).","name":"lever_family","in":"query"},{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The per-unit \"what your moat needs next\" list.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoatNextResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments":{"post":{"operationId":"createFlywheelExperiment","tags":["Flywheel"],"summary":"Declare a bounded, preregistered experiment on a unit below the protected floor","security":[{"sessionCookie":[]}],"description":"Declare ONE bounded EXPERIMENT on a unit (call type × situation × lever) whose history is below the protected benchmarkable floor. The platform admits it ONLY by its own FROZEN rule — the readiness unmet ONLY on the lifecycle floor + the evaluator qualification, and the imported history reproduced by the frozen workflow verifier from its receipts. Declaring it changes nothing in serving: nothing is produced, injected, served, adopted or spent; the floor is never changed and the unit is never labelled benchmarkable. The row lands `admitted` or `refused` (the owner receipt names why). OWNER SESSION only (`flywheel.experiment`), never an api key; audited. NEVER a body.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"call_type_id":{"type":"string","minLength":1},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"import_id":{"type":"string","nullable":true},"preregistration":{"type":"object","properties":{"verifier_version":{"type":"string","description":"The frozen workflow-verifier version the imported history must reproduce under."},"min_resolved_fit":{"type":"integer","minimum":0,"exclusiveMinimum":true},"min_delivered_fit":{"type":"integer","minimum":0,"exclusiveMinimum":true},"min_held_fit":{"type":"integer","minimum":0,"exclusiveMinimum":true},"min_contrast_ideas":{"type":"integer","minimum":0,"exclusiveMinimum":true},"budget_cap_micro_usd":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"≤ $30 (30_000_000 µUSD)."},"screen_subcap_micro_usd":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"≤ $2 (2_000_000 µUSD)."},"expiry_days":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"≤ 30 days."},"fit_families":{"type":"array","items":{"type":"string"},"minItems":1,"description":"The FIT idea families (the admission counts these)."},"screen_families":{"type":"array","items":{"type":"string"},"minItems":1,"description":"The SCREEN idea families (disjoint from fit + test)."},"test_families":{"type":"array","items":{"type":"string"},"minItems":1,"description":"The TEST idea families (disjoint from fit + screen)."},"labels":{"type":"boolean","description":"Whether the producer's optional semantic teacher is preregistered ON (default off, structural-only)."},"screen_rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer","description":"Treated first drafts showing the predicted value minus control ones must be ≥ this (default 1 — positive movement; a tie never passes)."},"min_first_pass_rescues":{"type":"integer","description":"Pairs where treated delivers first-pass and control does not must be ≥ this (default 1)."}},"additionalProperties":false,"description":"The preregistered screen-rule numbers — may only tighten the defaults."},"screen_judging":{"type":"object","properties":{"rubric_id":{"type":"string","minLength":1,"maxLength":200,"description":"The frozen rubric id the judges judge under."},"judges":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"description":"Exactly two distinct blind-judge keys."}},"required":["rubric_id","judges"],"additionalProperties":false,"description":"The two preregistered blind judges — absent, the screen can never pass."},"test_block":{"type":"object","properties":{"n":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The number of fresh paired ideas the test manifest commits (default 30)."},"alpha":{"type":"number","minimum":0,"exclusiveMinimum":true,"description":"The one-sided exact sign test α (default .05; may only shrink)."},"economics_min_ratio":{"type":"number","description":"The deliveries-per-dollar ratio floor (default 1.20; may only rise)."},"economics_permutations":{"type":"integer","description":"The economics permutation count (default 199,999; may only rise)."},"economics_seed":{"type":"integer","description":"The economics permutation seed (default 20261019; frozen, part of the hash)."},"quality_min_delta":{"type":"number","description":"The quality degradation floor (default −0.21; may only tighten toward 0)."},"test_judging":{"type":"object","properties":{"rubric_id":{"type":"string","minLength":1,"maxLength":200},"judges":{"type":"array","items":{"type":"string","minLength":1,"maxLength":100},"description":"Exactly two distinct blind-judge keys."}},"required":["rubric_id","judges"],"additionalProperties":false,"description":"The two preregistered blind test judges — absent, the test can never pass."}},"additionalProperties":false,"description":"The preregistered prospective-test block (may only tighten the defaults; part of the prereg hash)."}},"required":["verifier_version","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days","fit_families","screen_families","test_families"],"description":"The frozen preregistration — the admission numbers, splits, budget caps and expiry."}},"required":["call_type_id","preregistration"],"description":"Declare a bounded, preregistered experiment — owner session only."}}}},"responses":{"201":{"description":"The experiment (state admitted | refused) + its frozen admission receipt.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_envelope"]},"experiment":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]},"object":{"type":"string","enum":["flywheel_experiment"]},"workspace_id":{"type":"string"},"call_type_id":{"type":"string"},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"candidate_hash":{"type":"string","nullable":true},"candidate":{"type":"object","nullable":true,"properties":{"state":{"type":"string","enum":["producing","frozen","abstained","invalidated"]},"labels_requested":{"type":"boolean"},"teacher_calls":{"type":"integer","minimum":0},"abstention_reason":{"type":"string","nullable":true},"candidate_hash":{"type":"string","nullable":true},"token_estimate":{"type":"integer","minimum":0},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"attribute_label":{"type":"string"},"focus_value":{"type":"string"},"comparison_label":{"type":"string"},"ideas":{"type":"integer","minimum":0},"drafts":{"type":"integer","minimum":0},"first_pass_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"first_pass_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"within_idea":{"type":"object","properties":{"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"ties":{"type":"integer","minimum":0}},"required":["wins","losses","ties"]},"matched_idea_support":{"type":"integer","minimum":0},"evidence_ids":{"type":"array","items":{"type":"string"}}},"required":["attribute","attribute_label","focus_value","comparison_label","ideas","drafts","first_pass_focus","first_pass_rest","terminal_focus","terminal_rest","within_idea","matched_idea_support","evidence_ids"],"description":"One structured candidate observation — counts + cited ids only, never a body."}},"cited_execution_ids":{"type":"array","items":{"type":"string"}},"label_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"drops":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"reason":{"type":"string"}},"required":["attribute","focus_value","reason"]}},"pack_text":{"type":"string","nullable":true,"description":"The rendered reference text — owner session only; never in an audit diff or a log."}},"default":null,"required":["state","labels_requested","teacher_calls","abstention_reason","candidate_hash","token_estimate","observations","cited_execution_ids","label_counts","drops","pack_text"],"description":"The frozen structured candidate (counts only), or a named abstention."},"screen":{"type":"object","nullable":true,"properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"default":null,"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."},"test":{"type":"object","nullable":true,"properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"default":null,"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."},"import_id":{"type":"string","nullable":true},"created_by_user_id":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable","object","workspace_id","call_type_id","situation_class","lever_key","candidate_hash","import_id","created_by_user_id","created_at","updated_at"],"description":"A bounded experiment — ids / hashes / counts / state only, never a body."}},"required":["object","experiment"],"description":"One bounded experiment."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"get":{"operationId":"listFlywheelExperiments","tags":["Flywheel"],"summary":"List the workspace bounded experiments","security":[{"sessionCookie":[]}],"description":"LIST the workspace bounded experiments, newest first — ids / hashes / state / admission receipt / budget / expiry only (never a body). OWNER SESSION only (`flywheel.experiment`).","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The workspace bounded experiments (empty when none).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_list"]},"workspace_id":{"type":"string"},"experiments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]},"object":{"type":"string","enum":["flywheel_experiment"]},"workspace_id":{"type":"string"},"call_type_id":{"type":"string"},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"candidate_hash":{"type":"string","nullable":true},"candidate":{"type":"object","nullable":true,"properties":{"state":{"type":"string","enum":["producing","frozen","abstained","invalidated"]},"labels_requested":{"type":"boolean"},"teacher_calls":{"type":"integer","minimum":0},"abstention_reason":{"type":"string","nullable":true},"candidate_hash":{"type":"string","nullable":true},"token_estimate":{"type":"integer","minimum":0},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"attribute_label":{"type":"string"},"focus_value":{"type":"string"},"comparison_label":{"type":"string"},"ideas":{"type":"integer","minimum":0},"drafts":{"type":"integer","minimum":0},"first_pass_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"first_pass_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"within_idea":{"type":"object","properties":{"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"ties":{"type":"integer","minimum":0}},"required":["wins","losses","ties"]},"matched_idea_support":{"type":"integer","minimum":0},"evidence_ids":{"type":"array","items":{"type":"string"}}},"required":["attribute","attribute_label","focus_value","comparison_label","ideas","drafts","first_pass_focus","first_pass_rest","terminal_focus","terminal_rest","within_idea","matched_idea_support","evidence_ids"],"description":"One structured candidate observation — counts + cited ids only, never a body."}},"cited_execution_ids":{"type":"array","items":{"type":"string"}},"label_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"drops":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"reason":{"type":"string"}},"required":["attribute","focus_value","reason"]}},"pack_text":{"type":"string","nullable":true,"description":"The rendered reference text — owner session only; never in an audit diff or a log."}},"default":null,"required":["state","labels_requested","teacher_calls","abstention_reason","candidate_hash","token_estimate","observations","cited_execution_ids","label_counts","drops","pack_text"],"description":"The frozen structured candidate (counts only), or a named abstention."},"screen":{"type":"object","nullable":true,"properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"default":null,"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."},"test":{"type":"object","nullable":true,"properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"default":null,"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."},"import_id":{"type":"string","nullable":true},"created_by_user_id":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable","object","workspace_id","call_type_id","situation_class","lever_key","candidate_hash","import_id","created_by_user_id","created_at","updated_at"],"description":"A bounded experiment — ids / hashes / counts / state only, never a body."}}},"required":["object","workspace_id","experiments"],"description":"The workspace bounded experiments (newest first)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}":{"get":{"operationId":"getFlywheelExperiment","tags":["Flywheel"],"summary":"Read one bounded experiment","security":[{"sessionCookie":[]}],"description":"Read ONE bounded experiment by id — the frozen preregistration hash, the verifier version, the admission receipt, the budget caps + spend, the state and the expiry. OWNER SESSION only (`flywheel.experiment`). NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The bounded experiment.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_envelope"]},"experiment":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]},"object":{"type":"string","enum":["flywheel_experiment"]},"workspace_id":{"type":"string"},"call_type_id":{"type":"string"},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"candidate_hash":{"type":"string","nullable":true},"candidate":{"type":"object","nullable":true,"properties":{"state":{"type":"string","enum":["producing","frozen","abstained","invalidated"]},"labels_requested":{"type":"boolean"},"teacher_calls":{"type":"integer","minimum":0},"abstention_reason":{"type":"string","nullable":true},"candidate_hash":{"type":"string","nullable":true},"token_estimate":{"type":"integer","minimum":0},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"attribute_label":{"type":"string"},"focus_value":{"type":"string"},"comparison_label":{"type":"string"},"ideas":{"type":"integer","minimum":0},"drafts":{"type":"integer","minimum":0},"first_pass_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"first_pass_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"within_idea":{"type":"object","properties":{"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"ties":{"type":"integer","minimum":0}},"required":["wins","losses","ties"]},"matched_idea_support":{"type":"integer","minimum":0},"evidence_ids":{"type":"array","items":{"type":"string"}}},"required":["attribute","attribute_label","focus_value","comparison_label","ideas","drafts","first_pass_focus","first_pass_rest","terminal_focus","terminal_rest","within_idea","matched_idea_support","evidence_ids"],"description":"One structured candidate observation — counts + cited ids only, never a body."}},"cited_execution_ids":{"type":"array","items":{"type":"string"}},"label_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"drops":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"reason":{"type":"string"}},"required":["attribute","focus_value","reason"]}},"pack_text":{"type":"string","nullable":true,"description":"The rendered reference text — owner session only; never in an audit diff or a log."}},"default":null,"required":["state","labels_requested","teacher_calls","abstention_reason","candidate_hash","token_estimate","observations","cited_execution_ids","label_counts","drops","pack_text"],"description":"The frozen structured candidate (counts only), or a named abstention."},"screen":{"type":"object","nullable":true,"properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"default":null,"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."},"test":{"type":"object","nullable":true,"properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"default":null,"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."},"import_id":{"type":"string","nullable":true},"created_by_user_id":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable","object","workspace_id","call_type_id","situation_class","lever_key","candidate_hash","import_id","created_by_user_id","created_at","updated_at"],"description":"A bounded experiment — ids / hashes / counts / state only, never a body."}},"required":["object","experiment"],"description":"One bounded experiment."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/admit":{"post":{"operationId":"admitFlywheelExperiment","tags":["Flywheel"],"summary":"Re-affirm an admitted experiment against the current evidence","security":[{"sessionCookie":[]}],"description":"RE-AFFIRM an `admitted` experiment: re-run the admission against the CURRENT readiness + the verifier. If it no longer holds (consent revoked, the verifier now refuses) it transitions `admitted → refused`; otherwise it stays admitted (idempotent). The frozen create-time admission receipt is NEVER rewritten. OWNER SESSION only (`flywheel.experiment`); audited. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The experiment after re-affirmation (admitted, or refused if it no longer holds).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_envelope"]},"experiment":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]},"object":{"type":"string","enum":["flywheel_experiment"]},"workspace_id":{"type":"string"},"call_type_id":{"type":"string"},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"candidate_hash":{"type":"string","nullable":true},"candidate":{"type":"object","nullable":true,"properties":{"state":{"type":"string","enum":["producing","frozen","abstained","invalidated"]},"labels_requested":{"type":"boolean"},"teacher_calls":{"type":"integer","minimum":0},"abstention_reason":{"type":"string","nullable":true},"candidate_hash":{"type":"string","nullable":true},"token_estimate":{"type":"integer","minimum":0},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"attribute_label":{"type":"string"},"focus_value":{"type":"string"},"comparison_label":{"type":"string"},"ideas":{"type":"integer","minimum":0},"drafts":{"type":"integer","minimum":0},"first_pass_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"first_pass_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"within_idea":{"type":"object","properties":{"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"ties":{"type":"integer","minimum":0}},"required":["wins","losses","ties"]},"matched_idea_support":{"type":"integer","minimum":0},"evidence_ids":{"type":"array","items":{"type":"string"}}},"required":["attribute","attribute_label","focus_value","comparison_label","ideas","drafts","first_pass_focus","first_pass_rest","terminal_focus","terminal_rest","within_idea","matched_idea_support","evidence_ids"],"description":"One structured candidate observation — counts + cited ids only, never a body."}},"cited_execution_ids":{"type":"array","items":{"type":"string"}},"label_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"drops":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"reason":{"type":"string"}},"required":["attribute","focus_value","reason"]}},"pack_text":{"type":"string","nullable":true,"description":"The rendered reference text — owner session only; never in an audit diff or a log."}},"default":null,"required":["state","labels_requested","teacher_calls","abstention_reason","candidate_hash","token_estimate","observations","cited_execution_ids","label_counts","drops","pack_text"],"description":"The frozen structured candidate (counts only), or a named abstention."},"screen":{"type":"object","nullable":true,"properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"default":null,"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."},"test":{"type":"object","nullable":true,"properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"default":null,"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."},"import_id":{"type":"string","nullable":true},"created_by_user_id":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable","object","workspace_id","call_type_id","situation_class","lever_key","candidate_hash","import_id","created_by_user_id","created_at","updated_at"],"description":"A bounded experiment — ids / hashes / counts / state only, never a body."}},"required":["object","experiment"],"description":"One bounded experiment."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/produce":{"post":{"operationId":"produceFlywheelExperimentCandidate","tags":["Flywheel"],"summary":"Launch the one structured-candidate production attempt","security":[{"sessionCookie":[]}],"description":"LAUNCH the ONE structured-candidate production attempt for an admitted experiment: the worker reads the FROZEN fit split, optionally runs ONE outcome-blind teacher call (reserved + settled through the experiment budget), and freezes AT MOST ONE candidate (at most two first-draft observations) or ABSTAINS by name. One attempt per experiment (a claim prevents a second). Read the candidate back on `GET /v1/flywheel/experiments/{id}` (`candidate`). OWNER SESSION only (`flywheel.experiment`); audited (ids/hashes/counts — never the pack text). NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"202":{"description":"The production attempt was launched (the candidate is produced asynchronously).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_produce"]},"experiment_id":{"type":"string"},"enqueued":{"type":"boolean","description":"True when the production attempt was enqueued."}},"required":["object","experiment_id","enqueued"],"description":"The structured-candidate production attempt was launched."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/executions":{"post":{"operationId":"enrolFlywheelExperimentExecution","tags":["Flywheel"],"summary":"Enrol one execution slot of a candidate-frozen experiment (the gateway decides the arm)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"ENROL one execution slot of an experiment whose candidate is frozen: name the `phase`, the `pair_key` (one idea family frozen in the preregistration’s screen or test split) and the `slot` (0 or 1). The gateway — never the caller — decides the ARM from the experiment’s sealed assignment: a keyed hash of the frozen preregistration hash and the pair picks which slot is treated, so the two slots of a pair always get opposite arms. A repeat of the same `{phase, pair_key, slot}` returns the SAME execution (`created: false`). Send the returned `execution_id` as the `X-UR-Experiment-Execution` header on EVERY call of the execution (on `POST /v1/messages` and `POST /v1/responses`). Refusals are named in the error message: `experiment_not_live`, `candidate_not_frozen`, `phase_not_open`, `phase_unfunded`, `pair_not_in_manifest`, `slot_invalid` (and `experiment_not_found`). Auth: an api key with `flywheel:experiment:run` (never implied by `gateway:invoke`), OR the owner session (`flywheel.experiment`). Audited on creation (ids only). NEVER a body. Requires API-key scope: flywheel:experiment:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"],"description":"The fundable phase the execution runs in: `screen` (the historical screen pairs) or `test`."},"pair_key":{"type":"string","minLength":1,"maxLength":200,"description":"The pair — one idea family frozen in the preregistration's screen or test split."},"slot":{"type":"number","description":"One of the pair’s two slots: 0 or 1 (anything else is refused `slot_invalid`)."}},"required":["phase","pair_key","slot"],"additionalProperties":false,"description":"Enrol one execution slot — the gateway decides the arm."}}}},"responses":{"200":{"description":"The enrolled execution (its id + the arm the sealed assignment gave the slot).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_execution"]},"execution_id":{"type":"string","description":"Send as the `X-UR-Experiment-Execution` header on every call of this execution."},"experiment_id":{"type":"string"},"phase":{"type":"string","enum":["screen","test"]},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"],"description":"Decided by the sealed assignment — never by the caller."},"candidate_hash":{"type":"string","description":"The frozen candidate this execution is bound to (every call re-checks it)."},"assignment_version":{"type":"string","description":"The sealed assignment rule version."},"created":{"type":"boolean","description":"False when the same {phase, pair_key, slot} was already enrolled (idempotent)."},"created_at":{"type":"string"}},"required":["object","execution_id","experiment_id","phase","pair_key","slot","arm","candidate_hash","assignment_version","created","created_at"],"description":"One enrolled experiment execution — ids / arm / hashes only."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/executions/{execution_id}/outcome":{"post":{"operationId":"recordFlywheelExperimentExecutionOutcome","tags":["Flywheel"],"summary":"Record the one terminal outcome of an enrolled execution (no bodies)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"RECORD the ONE terminal outcome of an enrolled execution: `terminal` (delivered | held), its typed `reason_codes` under the frozen `reason_vocab`, one body-free `receipts[]` entry per member call (the workflow-import receipt shape, stamped with its `extractor_version`), the `final_content_hash` and EVERY gateway request id the execution made (`request_ids`). NO bodies. Idempotent on the execution: the same payload converges (`created: false`); a different one is refused `outcome_conflict`. The platform validates it against the experiment’s FROZEN verifier and its OWN rows, refusing by name: `request_not_bound` (a listed request is not a call of this execution), `membership_incomplete` (a call of the execution is not listed), `receipt_missing:<stage>` (a successful member call — a writer, review, stranger read or repair that returned a 2xx — has no receipt; only failed attempts may lack one), `verifier_mismatch:<gate>` (the receipts do not reproduce the recorded terminal; codes the verifier cannot reconstruct are returned as `trusted_recorded`), `receipt_extractor_mismatch`, `receipt_request_mismatch`, `reason_vocab_mismatch`, `reason_code_unregistered` (and `execution_unknown`, `experiment_not_live`, `phase_not_open`). An outcome posted before the last call’s row lands is accepted as `pending_rows` and completes when the rows land (an outcome that turns invalid when they land makes the screen incomplete for good). Each execution’s cost is reconciled (measured rows vs settled, ambiguous and reconciled holds); an open, pending, unpriced or unexplained one is incomplete. Recording an outcome re-evaluates the screen: the verdict is computed exactly once, only when every preregistered screen pair is complete and no hold of the phase is reserved or ambiguous. With `?dry_run=true` the SAME validation runs against the current rows and holds and its answer is returned (`status`, the named `refusal`, `missing_request_ids`, `unlisted_request_ids` — the execution’s own calls the payload does not list — and `open_holds`) with NOTHING written: no outcome, no state change, no audit; on an execution with a recorded outcome it reports whether the payload would converge or conflict. A live experiment outcome is never an imported row. Auth: an api key with `flywheel:experiment:run`, OR the owner session (`flywheel.experiment`). Audited (ids / hashes only). Requires API-key scope: flywheel:experiment:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `execution_id`."},"required":true,"description":"Path parameter `execution_id`.","name":"execution_id","in":"path"},{"schema":{"type":"string","description":"`true` runs the validation and returns its answer without recording anything (default `false`)."},"required":false,"description":"`true` runs the validation and returns its answer without recording anything (default `false`).","name":"dry_run","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"terminal":{"type":"string","enum":["delivered","held"]},"reason_codes":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"The typed reason codes (empty for a clean delivery)."},"reason_vocab":{"type":"string","minLength":1,"maxLength":100,"description":"The reason vocabulary id — must be the frozen verifier’s."},"receipts":{"type":"array","items":{"type":"object","properties":{"ordinal":{"type":"integer","minimum":0,"description":"The call’s position in the execution."},"stage":{"type":"string","minLength":1,"maxLength":200,"description":"The stage (as the call declared it in `X-UR-Trace`)."},"call_type":{"type":"string","minLength":1,"maxLength":200},"request_id":{"type":"string","minLength":1,"maxLength":200,"description":"The gateway request id of this member call (must be listed in `request_ids`)."},"extractor_version":{"type":"string","minLength":1,"maxLength":100,"description":"The receipt-extraction recipe version — must be the experiment verifier’s."},"system_len":{"type":"integer","minimum":0},"user_len":{"type":"integer","minimum":0},"response_len":{"type":"integer","minimum":0},"system_hash":{"type":"string","nullable":true,"maxLength":200},"user_hash":{"type":"string","nullable":true,"maxLength":200},"response_hash":{"type":"string","nullable":true,"maxLength":200},"parsed_hash":{"type":"string","nullable":true,"maxLength":200},"quote_ids":{"type":"array","items":{"type":"string","maxLength":200},"maxItems":500},"numbers":{"type":"object","additionalProperties":{"type":"number"},"description":"The stage-aware body-free numbers (e.g. `post_length`, `line_count`, `distinct`, `usefulness`)."}},"required":["ordinal","stage","call_type","request_id","extractor_version","numbers"],"additionalProperties":false,"description":"One member-call receipt — numbers, hashes and ids only, never a body."},"minItems":1,"maxItems":200},"final_content_hash":{"type":"string","minLength":1,"maxLength":200,"description":"The hash of the final content (the delivered post, or the last draft when held)."},"request_ids":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"minItems":1,"maxItems":500,"description":"Every gateway request id the execution made — members and failed attempts alike."}},"required":["terminal","reason_codes","reason_vocab","receipts","final_content_hash","request_ids"],"additionalProperties":false,"description":"One live execution outcome — ids, hashes and numbers only, never a body."}}}},"responses":{"200":{"description":"The recorded outcome — `complete` or `pending_rows` — with its cost reconciliation; or, with `?dry_run=true`, the dry-run answer.","content":{"application/json":{"schema":{"oneOf":[{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_execution_outcome"]},"experiment_id":{"type":"string"},"execution_id":{"type":"string"},"status":{"type":"string","enum":["complete","pending_rows"],"description":"pending_rows: a call’s row has not landed yet — it completes when the rows land."},"created":{"type":"boolean","description":"False when the same outcome was already recorded (an idempotent repeat)."},"outcome_hash":{"type":"string"},"trusted_recorded":{"type":"array","items":{"type":"string"},"description":"Reason codes the verifier cannot reconstruct — listed, never silently passed."},"missing_request_ids":{"type":"array","items":{"type":"string"}},"cost":{"type":"object","properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0,"description":"Unpriced rows whose hold the owner has not reconciled — each keeps the cost incomplete."},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer","description":"rows_measured − settled — non-zero while a hold is unsettled or ambiguous, or settled at its reserve."},"unexplained_micro_usd":{"type":"integer","description":"The difference NOT accounted for by an owner reconciliation (over the holds the gateway settled) — must be 0."},"holds_reconciled":{"type":"integer","minimum":0,"description":"Holds the owner reconciled (settle, settle_at_reserve or release) — each counts as resolved."},"holds_released_after_dispatch":{"type":"integer","minimum":0,"description":"Holds released after their call was sent without a reconciliation — incomplete."},"unlanded_holds":{"type":"integer","minimum":0,"description":"Open holds whose request row has not landed yet."},"rowless_resolved_holds":{"type":"integer","minimum":0,"description":"Reconciled holds whose request row never landed (a stale claim)."},"complete":{"type":"boolean","description":"True only when every hold is settled, released before dispatch or reconciled, no open hold awaits its row, no unpriced row is unreconciled and the difference is fully explained."}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"],"description":"The execution’s cost reconciliation — an ambiguous, pending or unexplained one is incomplete."},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]}},"required":["object","experiment_id","execution_id","status","created","outcome_hash","trusted_recorded","missing_request_ids","cost","experiment_state"],"description":"One recorded live execution outcome."},{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_execution_outcome_dry_run"]},"experiment_id":{"type":"string"},"execution_id":{"type":"string"},"status":{"type":"string","enum":["complete","pending_rows","refused"],"description":"What recording it now would return (refused: the named refusal)."},"refusal":{"type":"string","nullable":true,"description":"The named refusal (e.g. `verifier_mismatch:<gate>`, `receipt_missing:<stage>`), or null."},"detail":{"type":"string","nullable":true},"recorded_outcome":{"type":"string","enum":["none","converges","conflicts"],"description":"Whether an outcome is already recorded and this payload would converge on it or conflict."},"outcome_hash":{"type":"string","description":"The content address of this payload."},"trusted_recorded":{"type":"array","items":{"type":"string"}},"missing_request_ids":{"type":"array","items":{"type":"string"},"description":"Listed request ids whose row has not landed (yet)."},"unlisted_request_ids":{"type":"array","items":{"type":"string"},"description":"The execution’s own landed calls the payload does NOT list (e.g. a failed attempt the client lost)."},"open_holds":{"type":"array","items":{"type":"object","properties":{"hold_key":{"type":"string"},"state":{"type":"string","enum":["reserved","ambiguous"]},"amount_micro_usd":{"type":"integer","minimum":0}},"required":["hold_key","state","amount_micro_usd"]},"description":"The execution’s holds still reserved or ambiguous."}},"required":["object","experiment_id","execution_id","status","refusal","detail","recorded_outcome","outcome_hash","trusted_recorded","missing_request_ids","unlisted_request_ids","open_holds"],"description":"An outcome dry run — the answer the record would give now; nothing was written."}],"description":"The recorded outcome, or — with `?dry_run=true` — the dry-run answer."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/screen/evaluate":{"post":{"operationId":"evaluateFlywheelExperimentScreen","tags":["Flywheel"],"summary":"Evaluate the screen now (idempotent) and read it","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"EVALUATE the screen explicitly — the same exactly-once evaluation a recorded outcome, judgement or hold reconciliation runs — so facts that changed since (a call’s row landing, a hold settling) are picked up. When the completion barrier is met the verdict is computed and stored ONCE (concurrent calls make one verdict and one audit event; `computed` is true only for that call); otherwise nothing is written. Returns the screen read: counts only before the verdict, the verdict after it. Idempotent; reads no body. Auth: an api key with `flywheel:experiment:run`, OR the owner session (`flywheel.experiment`). Requires API-key scope: flywheel:experiment:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The screen after the evaluation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_screen_evaluation"]},"experiment_id":{"type":"string"},"computed":{"type":"boolean","description":"True only for the ONE call that computed and stored the verdict."},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"screen":{"type":"object","properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."}},"required":["object","experiment_id","computed","experiment_state","screen"],"description":"The screen after an explicit evaluation (counts only until the verdict)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/holds":{"get":{"operationId":"listFlywheelExperimentHolds","tags":["Flywheel"],"summary":"List an experiment’s holds (the money each call reserved)","security":[{"sessionCookie":[]}],"description":"LIST the experiment’s holds, oldest first — one per paid call it reserved: the hold key, phase, state (reserved | settled | released | ambiguous), the reserved and settled amounts, the request ids, when it was reserved, claimed for dispatch and settled, when a claimed hold becomes a stale claim, whether it can be reconciled now, and the owner’s resolution + reason if it was. `?state=open` returns only the reserved and ambiguous holds — the ones that keep a screen waiting. Ids, money and timestamps only (never an arm, a terminal or a body). OWNER SESSION only (`flywheel.experiment`).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"`open` — only reserved + ambiguous holds."},"required":false,"description":"`open` — only reserved + ambiguous holds.","name":"state","in":"query"},{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The experiment’s holds.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_hold_list"]},"experiment_id":{"type":"string"},"holds":{"type":"array","items":{"type":"object","properties":{"hold_key":{"type":"string"},"phase":{"type":"string","enum":["screen","test"]},"state":{"type":"string","enum":["reserved","settled","released","ambiguous"]},"amount_micro_usd":{"type":"integer","minimum":0,"description":"The reserved worst case (micro-USD)."},"settled_micro_usd":{"type":"integer","minimum":0},"request_ids":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string"},"claimed_at":{"type":"string","nullable":true,"description":"When the hold was claimed for dispatch (its call was sent), or null."},"settled_at":{"type":"string","nullable":true},"stale_claim_at":{"type":"string","nullable":true,"description":"A claimed, still-reserved hold: when it becomes a stale claim (its dispatch deadline plus a fixed margin)."},"reconcilable":{"type":"boolean","description":"Whether the owner may reconcile it now (an ambiguous hold, or a stale claim)."},"resolution":{"type":"string","nullable":true,"enum":["settle","settle_at_reserve","release"],"description":"The owner’s reconcile resolution, when it was reconciled."},"reason":{"type":"string","nullable":true,"enum":["stream_dropped","client_cancel","upstream_5xx","no_usage","stale_claim","operator"]}},"required":["hold_key","phase","state","amount_micro_usd","settled_micro_usd","request_ids","created_at","claimed_at","settled_at","stale_claim_at","reconcilable","resolution","reason"],"description":"One experiment hold."}}},"required":["object","experiment_id","holds"],"description":"The experiment’s holds, oldest first (`?state=open`: reserved + ambiguous only)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/holds/reconcile":{"post":{"operationId":"reconcileFlywheelExperimentHold","tags":["Flywheel"],"summary":"Reconcile one open hold (settle, settle at reserve, or release)","security":[{"sessionCookie":[]}],"description":"RECONCILE one OPEN hold — explicit and audited — so a screen held by money whose outcome is unknown can finish. Open means `ambiguous` (the call’s provider outcome was unknown: a dropped stream, a client cancel, an upstream 5xx, a 2xx without usage) or a STALE CLAIM (a hold claimed for dispatch that never settled — its request row never landed — past the hard request deadline plus a fixed margin; reason `stale_claim`). `resolution`: `settle` (the measured cost of the hold’s own request rows — refused `settle_cost_unknown` when a row is missing, unpriced or not a measurement, e.g. an interrupted call), `settle_at_reserve` (its full reserved amount — the conservative resolution: the caps never undercount money that may have been spent), or `release` ($0 — the owner asserts no provider charge). `reason` is a closed vocabulary (`stream_dropped`, `client_cancel`, `upstream_5xx`, `no_usage`, `stale_claim`, `operator`). Refusals by name: `hold_not_found`, `hold_not_open` (a settled / released hold, a hold claimed within its deadline, a hold never sent), `settle_cost_unknown`, `reason_invalid`. A repeat of the SAME resolution on a hold it already resolved converges and returns the stored result (`created: false`). Each resolution is audited (ids, amounts, resolution, reason, actor) and then re-evaluates the screen. OWNER SESSION only (`flywheel.experiment`), never an api key.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"hold_key":{"type":"string","minLength":1,"maxLength":500},"resolution":{"type":"string","enum":["settle","settle_at_reserve","release"],"description":"`settle`: the measured cost of the hold’s own request rows; `settle_at_reserve`: its full reserved amount (conservative); `release`: $0 (the owner asserts no provider charge)."},"request_ids":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":50,"description":"`settle` only: the hold’s request ids to measure (default: every landed row of the hold)."},"reason":{"type":"string","minLength":1,"maxLength":64,"description":"Why — one of `stream_dropped`, `client_cancel`, `upstream_5xx`, `no_usage`, `stale_claim` (a claimed hold that never settled), `operator`; anything else is refused `reason_invalid`."}},"required":["hold_key","resolution","reason"],"additionalProperties":false,"description":"Reconcile one open hold — explicit, audited."}}}},"responses":{"200":{"description":"The reconciled hold and the experiment state after the re-evaluation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_hold_reconcile"]},"experiment_id":{"type":"string"},"created":{"type":"boolean","description":"False when the same resolution had already resolved the hold (the stored result)."},"resolution":{"type":"string","enum":["settle","settle_at_reserve","release"]},"reason":{"type":"string","nullable":true,"enum":["stream_dropped","client_cancel","upstream_5xx","no_usage","stale_claim","operator"]},"settled_micro_usd":{"type":"integer","minimum":0},"hold":{"type":"object","properties":{"hold_key":{"type":"string"},"phase":{"type":"string","enum":["screen","test"]},"state":{"type":"string","enum":["reserved","settled","released","ambiguous"]},"amount_micro_usd":{"type":"integer","minimum":0,"description":"The reserved worst case (micro-USD)."},"settled_micro_usd":{"type":"integer","minimum":0},"request_ids":{"type":"array","items":{"type":"string"}},"created_at":{"type":"string"},"claimed_at":{"type":"string","nullable":true,"description":"When the hold was claimed for dispatch (its call was sent), or null."},"settled_at":{"type":"string","nullable":true},"stale_claim_at":{"type":"string","nullable":true,"description":"A claimed, still-reserved hold: when it becomes a stale claim (its dispatch deadline plus a fixed margin)."},"reconcilable":{"type":"boolean","description":"Whether the owner may reconcile it now (an ambiguous hold, or a stale claim)."},"resolution":{"type":"string","nullable":true,"enum":["settle","settle_at_reserve","release"],"description":"The owner’s reconcile resolution, when it was reconciled."},"reason":{"type":"string","nullable":true,"enum":["stream_dropped","client_cancel","upstream_5xx","no_usage","stale_claim","operator"]}},"required":["hold_key","phase","state","amount_micro_usd","settled_micro_usd","request_ids","created_at","claimed_at","settled_at","stale_claim_at","reconcilable","resolution","reason"],"description":"One experiment hold."},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]}},"required":["object","experiment_id","created","resolution","reason","settled_micro_usd","hold","experiment_state"],"description":"The reconciled hold; the screen is re-evaluated after it."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/screen/judgements":{"post":{"operationId":"recordFlywheelExperimentScreenJudgement","tags":["Flywheel"],"summary":"Record one preregistered blind judge’s screen verdict","security":[{"sessionCookie":[]}],"description":"RECORD one PREREGISTERED blind judge’s verdict on the screen’s final outputs (the judges run outside the platform): `verdict` (no_evident_degradation | evident_degradation) under the frozen `rubric_id`, the `reviewed_content_hashes` it judged and the final-content hashes it flags as a serious defect. Accepted only once every preregistered screen pair has its two complete executions (`judging_not_open` before that) and only when the reviewed set EQUALS the screen’s output manifest — every screen execution’s final content (`judgement_manifest_mismatch`); the manifest’s content address is stored with the judgement and enters the verdict’s inputs hash. One per judge — the same judgement converges, a different one is refused `judgement_conflict`. Other refusals by name: `judging_not_preregistered`, `judge_not_preregistered`, `rubric_mismatch`, `judgement_unknown_item` (a flagged hash is not a screen output). Recording a judgement re-evaluates the screen (the verdict needs both judges). OWNER SESSION only (`flywheel.experiment`); audited (ids / hashes only).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"judge":{"type":"string","minLength":1,"maxLength":100,"description":"One of the two preregistered judge keys."},"rubric_id":{"type":"string","minLength":1,"maxLength":200,"description":"Must be the frozen rubric id."},"verdict":{"type":"string","enum":["no_evident_degradation","evident_degradation"]},"serious_defects":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":500,"description":"Final-content hashes of screen outputs the judge flags as a serious defect (each one it reviewed)."},"reviewed_content_hashes":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"minItems":1,"maxItems":2000,"description":"The final-content hashes the judge reviewed — must equal the screen’s output manifest (every screen execution’s final content); accepted only once every screen pair is complete."}},"required":["judge","rubric_id","verdict","reviewed_content_hashes"],"additionalProperties":false,"description":"One blind judgement — the judges run outside the platform."}}}},"responses":{"200":{"description":"The recorded judgement.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_screen_judgement"]},"experiment_id":{"type":"string"},"judge":{"type":"string"},"created":{"type":"boolean","description":"False when the same judgement was already recorded (an idempotent repeat)."},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The content address of the output manifest the judge reviewed."},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]}},"required":["object","experiment_id","judge","created","judgement_hash","manifest_hash","experiment_state"],"description":"One recorded blind judgement."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/screen/acknowledge":{"post":{"operationId":"acknowledgeFlywheelExperimentScreen","tags":["Flywheel"],"summary":"Acknowledge a passed screen — the experiment then awaits test funding","security":[{"sessionCookie":[]}],"description":"ACKNOWLEDGE a passed screen: the owner has read it, and the experiment moves `screen_passed → awaiting_test_funding`. This opens nothing, funds nothing and adopts nothing — a screen pass proves nothing prospectively. Any other state is refused `illegal_transition` (409). OWNER SESSION only (`flywheel.experiment`); audited.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The experiment, now awaiting test funding.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_envelope"]},"experiment":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]},"object":{"type":"string","enum":["flywheel_experiment"]},"workspace_id":{"type":"string"},"call_type_id":{"type":"string"},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"candidate_hash":{"type":"string","nullable":true},"candidate":{"type":"object","nullable":true,"properties":{"state":{"type":"string","enum":["producing","frozen","abstained","invalidated"]},"labels_requested":{"type":"boolean"},"teacher_calls":{"type":"integer","minimum":0},"abstention_reason":{"type":"string","nullable":true},"candidate_hash":{"type":"string","nullable":true},"token_estimate":{"type":"integer","minimum":0},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"attribute_label":{"type":"string"},"focus_value":{"type":"string"},"comparison_label":{"type":"string"},"ideas":{"type":"integer","minimum":0},"drafts":{"type":"integer","minimum":0},"first_pass_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"first_pass_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"within_idea":{"type":"object","properties":{"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"ties":{"type":"integer","minimum":0}},"required":["wins","losses","ties"]},"matched_idea_support":{"type":"integer","minimum":0},"evidence_ids":{"type":"array","items":{"type":"string"}}},"required":["attribute","attribute_label","focus_value","comparison_label","ideas","drafts","first_pass_focus","first_pass_rest","terminal_focus","terminal_rest","within_idea","matched_idea_support","evidence_ids"],"description":"One structured candidate observation — counts + cited ids only, never a body."}},"cited_execution_ids":{"type":"array","items":{"type":"string"}},"label_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"drops":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"reason":{"type":"string"}},"required":["attribute","focus_value","reason"]}},"pack_text":{"type":"string","nullable":true,"description":"The rendered reference text — owner session only; never in an audit diff or a log."}},"default":null,"required":["state","labels_requested","teacher_calls","abstention_reason","candidate_hash","token_estimate","observations","cited_execution_ids","label_counts","drops","pack_text"],"description":"The frozen structured candidate (counts only), or a named abstention."},"screen":{"type":"object","nullable":true,"properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"default":null,"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."},"test":{"type":"object","nullable":true,"properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"default":null,"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."},"import_id":{"type":"string","nullable":true},"created_by_user_id":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable","object","workspace_id","call_type_id","situation_class","lever_key","candidate_hash","import_id","created_by_user_id","created_at","updated_at"],"description":"A bounded experiment — ids / hashes / counts / state only, never a body."}},"required":["object","experiment"],"description":"One bounded experiment."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/test/manifest":{"post":{"operationId":"commitFlywheelExperimentTestManifest","tags":["Flywheel"],"summary":"Commit the content-addressed test manifest (before any test enrolment)","security":[{"sessionCookie":[]}],"description":"COMMIT, in state `awaiting_test_funding` and BEFORE any test enrolment, EXACTLY N fresh pair identities (N from the preregistration) with per-pair body-free eligibility facts (the idea key, the quote ids it draws on, the ideation run id). Refusals by name: `manifest_size` (the wrong count), `pair_duplicate`, `pair_not_fresh` (an idea key in the fit or screen families), `quote_overlap` (a quote id a fit or screen receipt already used). Content-addressed + immutable: a different second manifest is refused `manifest_conflict`; the same one converges (`created: false`). OWNER SESSION only (`flywheel.experiment`); audited (the manifest hash + N only, never a body).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"object","properties":{"idea_key":{"type":"string","minLength":1,"maxLength":200,"description":"The fresh idea key — the test pair key."},"quote_ids":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":500,"description":"The quote ids the idea draws on (checked for fit/screen overlap)."},"ideation_run_id":{"type":"string","minLength":1,"maxLength":200,"description":"The ideation run the fresh idea came from."}},"required":["idea_key","quote_ids","ideation_run_id"],"additionalProperties":false,"description":"One committed test pair — ids only, never a body."},"minItems":1,"maxItems":1000,"description":"EXACTLY N pair identities (N from the preregistration; `manifest_size` otherwise)."}},"required":["pairs"],"additionalProperties":false,"description":"Commit the immutable, content-addressed test manifest — before any test enrolment."}}}},"responses":{"200":{"description":"The committed test manifest.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_test_manifest"]},"experiment_id":{"type":"string"},"created":{"type":"boolean","description":"False when the same manifest was already committed (an idempotent converge)."},"n":{"type":"integer","minimum":0},"manifest_hash":{"type":"string"},"pairs":{"type":"array","items":{"type":"object","properties":{"idea_key":{"type":"string","minLength":1,"maxLength":200,"description":"The fresh idea key — the test pair key."},"quote_ids":{"type":"array","items":{"type":"string","minLength":1,"maxLength":200},"maxItems":500,"description":"The quote ids the idea draws on (checked for fit/screen overlap)."},"ideation_run_id":{"type":"string","minLength":1,"maxLength":200,"description":"The ideation run the fresh idea came from."}},"required":["idea_key","quote_ids","ideation_run_id"],"additionalProperties":false,"description":"One committed test pair — ids only, never a body."}}},"required":["object","experiment_id","created","n","manifest_hash","pairs"],"description":"The committed test manifest."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/test/fund":{"post":{"operationId":"fundFlywheelExperimentTest","tags":["Flywheel"],"summary":"Fund + open the prospective test phase","security":[{"sessionCookie":[]}],"description":"FUND the prospective `test` phase and OPEN it (`awaiting_test_funding → test_open`). Refuses unless the state is `awaiting_test_funding` and the test manifest is committed (`test_manifest_missing`); the cap must be positive and ≤ the preregistered parent cap’s REMAINING budget (`funding_exceeds_budget`); `approval` is 1–500 chars of the owner’s words + date, recorded in the audit event (never a body). It calls the ONE funding path and moves to `test_open` in the SAME transaction. A repeat with the same cap + approval converges (`created: false`); a different one is `already_funded`. OWNER SESSION only (`flywheel.experiment`); an api key is 403.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0,"exclusiveMinimum":true,"description":"The test-phase cap (micro-USD) — must be ≤ the parent cap’s remaining budget."},"approval":{"type":"string","minLength":1,"maxLength":500,"description":"The owner’s approval — their words + the date (recorded in the audit, never a body)."}},"required":["cap_micro_usd","approval"],"additionalProperties":false,"description":"Fund + open the prospective test phase — owner session only."}}}},"responses":{"200":{"description":"The funded + opened test (now test_open).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_test_fund"]},"experiment_id":{"type":"string"},"created":{"type":"boolean","description":"False when the test was already funded with the same cap + approval (an idempotent repeat)."},"cap_micro_usd":{"type":"integer","minimum":0},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]}},"required":["object","experiment_id","created","cap_micro_usd","experiment_state"],"description":"The funded + opened prospective test (now test_open)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/test/judgements":{"post":{"operationId":"recordFlywheelExperimentTestJudgement","tags":["Flywheel"],"summary":"Record one preregistered blind judge’s per-item test verdict","security":[{"sessionCookie":[]}],"description":"RECORD one PREREGISTERED blind judge’s per-item publishability verdict on the DELIVERED test outputs: `items: [{final_content_hash, publishable, serious_unsupported_claim}]` under the frozen `rubric_id`. Accepted only once every manifest pair has its two complete executions (`judging_not_open` before that) and only when the items EQUAL the test output manifest — every delivered final content (`judgement_manifest_mismatch`; `judgement_unknown_item` for an item outside it). One per judge — the same judgement converges, a different one is `judgement_conflict`; `judging_not_preregistered`, `judge_not_preregistered`, `rubric_mismatch` by name. Recording a judgement re-evaluates the test. OWNER SESSION only (`flywheel.experiment`); audited (ids / hashes only).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"judge":{"type":"string","minLength":1,"maxLength":100,"description":"One of the two preregistered test judge keys."},"rubric_id":{"type":"string","minLength":1,"maxLength":200,"description":"Must be the frozen rubric id."},"items":{"type":"array","items":{"type":"object","properties":{"final_content_hash":{"type":"string","minLength":1,"maxLength":200},"publishable":{"type":"boolean"},"serious_unsupported_claim":{"type":"boolean"}},"required":["final_content_hash","publishable","serious_unsupported_claim"],"additionalProperties":false,"description":"One delivered output’s judgement (publishable + a serious-unsupported-claim flag)."},"minItems":1,"maxItems":2000,"description":"One item per DELIVERED final content — must equal the test output manifest."}},"required":["judge","rubric_id","items"],"additionalProperties":false,"description":"One per-item blind judgement — the judges run outside the platform."}}}},"responses":{"200":{"description":"The recorded per-item judgement.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_test_judgement"]},"experiment_id":{"type":"string"},"judge":{"type":"string"},"created":{"type":"boolean"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string"},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]}},"required":["object","experiment_id","judge","created","judgement_hash","manifest_hash","experiment_state"],"description":"One recorded per-item test judgement."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/test/evaluate":{"post":{"operationId":"evaluateFlywheelExperimentTest","tags":["Flywheel"],"summary":"Evaluate the prospective test now (idempotent) and read it","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"EVALUATE the prospective test explicitly — the same exactly-once decision a recorded outcome, judgement or hold reconciliation runs. When every manifest pair is complete, no test hold is open and both judges have recorded, the ONE decision is computed and stored ONCE (concurrent calls make one verdict and one audit event; `computed` is true only for that call): the PRIMARY one-sided exact paired sign test, the ECONOMICS guard (ratio ≥ min AND a within-pair permutation p ≤ .05) and the weak QUALITY degradation screen. Returns the test read: counts only before the verdict, the decision + the Goodhart report after it. Idempotent; reads no body. Auth: an api key with `flywheel:experiment:run`, OR the owner session (`flywheel.experiment`). Requires API-key scope: flywheel:experiment:run.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The test after the evaluation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_test_evaluation"]},"experiment_id":{"type":"string"},"computed":{"type":"boolean","description":"True only for the ONE call that computed and stored the decision."},"experiment_state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"test":{"type":"object","properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."}},"required":["object","experiment_id","computed","experiment_state","test"],"description":"The test after an explicit evaluation (counts only until the verdict)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/experiments/{id}/abandon":{"post":{"operationId":"abandonFlywheelExperiment","tags":["Flywheel"],"summary":"Abandon a live experiment","security":[{"sessionCookie":[]}],"description":"ABANDON a live experiment — transition it to `abandoned` (terminal). A refused / closed / expired experiment cannot be abandoned (409). OWNER SESSION only (`flywheel.experiment`); audited. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The abandoned experiment.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_experiment_envelope"]},"experiment":{"type":"object","properties":{"id":{"type":"string"},"state":{"type":"string","enum":["admitted","refused","candidate_frozen","screening","screen_passed","screen_failed","screen_incomplete","awaiting_test_funding","test_open","test_passed","test_failed","test_incomplete","closed","expired","abandoned"]},"admission":{"type":"object","nullable":true,"properties":{"admitted":{"type":"boolean"},"refusals":{"type":"array","items":{"type":"string"},"description":"Every failing admission rule, by name (empty ⇒ admitted)."},"applied":{"type":"object","properties":{"verifier_version":{"type":"string"},"min_resolved_fit":{"type":"integer","minimum":0},"min_delivered_fit":{"type":"integer","minimum":0},"min_held_fit":{"type":"integer","minimum":0},"min_contrast_ideas":{"type":"integer","minimum":0},"budget_cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"expiry_days":{"type":"integer","minimum":0}},"required":["verifier_version","min_resolved_fit","min_delivered_fit","min_held_fit","min_contrast_ideas","budget_cap_micro_usd","screen_subcap_micro_usd","expiry_days"],"description":"The frozen thresholds the admission applied."},"evidence":{"type":"object","properties":{"verifier_version":{"type":"string"},"verifier_refusals":{"type":"array","items":{"type":"string"}},"resolved_fit_executions":{"type":"integer","minimum":0},"delivered_fit":{"type":"integer","minimum":0},"held_fit":{"type":"integer","minimum":0},"contrast_ideas_fit":{"type":"integer","minimum":0}},"required":["verifier_version","verifier_refusals","resolved_fit_executions","delivered_fit","held_fit","contrast_ideas_fit"],"description":"The mechanical evidence the admission weighed (verifier verdict + the fit-split counts)."}},"required":["admitted","refusals","applied","evidence"],"description":"The frozen admission verdict — admitted + the rules applied + the evidence (the owner receipt)."},"prereg_hash":{"type":"string"},"verifier_version":{"type":"string"},"budget":{"type":"object","properties":{"cap_micro_usd":{"type":"integer","minimum":0},"screen_subcap_micro_usd":{"type":"integer","minimum":0},"spend_micro_usd":{"type":"integer","minimum":0}},"required":["cap_micro_usd","screen_subcap_micro_usd","spend_micro_usd"],"description":"The experiment budget caps + running spend (micro-USD)."},"reservations":{"type":"object","nullable":true,"properties":{"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0},"remaining_micro_usd":{"type":"integer","minimum":0},"phases":{"type":"array","items":{"type":"object","properties":{"phase":{"type":"string","enum":["screen","test"]},"funded":{"type":"boolean","description":"Whether the phase has a funded cap (the prospective-test phase starts unfunded)."},"cap_micro_usd":{"type":"integer","minimum":0},"reserved_micro_usd":{"type":"integer","minimum":0},"spent_micro_usd":{"type":"integer","minimum":0},"ambiguous_micro_usd":{"type":"integer","minimum":0,"description":"Reserve held for an interrupted/unknown-outcome call, still counted against the cap."},"remaining_micro_usd":{"type":"integer","minimum":0}},"required":["phase","funded","cap_micro_usd","reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd"],"description":"One phase of the atomic reservation ledger (micro-USD)."}}},"default":null,"required":["reserved_micro_usd","spent_micro_usd","ambiguous_micro_usd","remaining_micro_usd","phases"],"description":"The atomic per-call reservation ledger: the experiment total + each phase (micro-USD)."},"expires_at":{"type":"string","nullable":true},"benchmarkable":{"type":"boolean","enum":[false]},"object":{"type":"string","enum":["flywheel_experiment"]},"workspace_id":{"type":"string"},"call_type_id":{"type":"string"},"situation_class":{"type":"string"},"lever_key":{"type":"string"},"candidate_hash":{"type":"string","nullable":true},"candidate":{"type":"object","nullable":true,"properties":{"state":{"type":"string","enum":["producing","frozen","abstained","invalidated"]},"labels_requested":{"type":"boolean"},"teacher_calls":{"type":"integer","minimum":0},"abstention_reason":{"type":"string","nullable":true},"candidate_hash":{"type":"string","nullable":true},"token_estimate":{"type":"integer","minimum":0},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"attribute_label":{"type":"string"},"focus_value":{"type":"string"},"comparison_label":{"type":"string"},"ideas":{"type":"integer","minimum":0},"drafts":{"type":"integer","minimum":0},"first_pass_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"first_pass_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_focus":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"terminal_rest":{"type":"object","properties":{"num":{"type":"integer","minimum":0},"den":{"type":"integer","minimum":0}},"required":["num","den"],"description":"A counts-only fraction num/den."},"within_idea":{"type":"object","properties":{"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"ties":{"type":"integer","minimum":0}},"required":["wins","losses","ties"]},"matched_idea_support":{"type":"integer","minimum":0},"evidence_ids":{"type":"array","items":{"type":"string"}}},"required":["attribute","attribute_label","focus_value","comparison_label","ideas","drafts","first_pass_focus","first_pass_rest","terminal_focus","terminal_rest","within_idea","matched_idea_support","evidence_ids"],"description":"One structured candidate observation — counts + cited ids only, never a body."}},"cited_execution_ids":{"type":"array","items":{"type":"string"}},"label_counts":{"type":"object","additionalProperties":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"drops":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"reason":{"type":"string"}},"required":["attribute","focus_value","reason"]}},"pack_text":{"type":"string","nullable":true,"description":"The rendered reference text — owner session only; never in an audit diff or a log."}},"default":null,"required":["state","labels_requested","teacher_calls","abstention_reason","candidate_hash","token_estimate","observations","cited_execution_ids","label_counts","drops","pack_text"],"description":"The frozen structured candidate (counts only), or a named abstention."},"screen":{"type":"object","nullable":true,"properties":{"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled screen execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["screen_pass","screen_fail","screen_incomplete"]},"failing_clauses":{"type":"array","items":{"type":"string"},"description":"Every failing clause (screen_fail); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why the screen can never complete (screen_incomplete): cap_stop, candidate_withdrawn, outcome_invalid:<execution>:<refusal>, pair_arms_not_opposite:<pair>, judging_not_preregistered, judgement_manifest_mismatch:<judge>."},"clauses":{"type":"array","items":{"type":"object","properties":{"clause":{"type":"string","enum":["a_feature_moved","b_first_pass_rescue","c_no_net_delivery_loss","d_no_serious_treated_defect","e_judges_no_degradation"]},"holds":{"type":"boolean"},"detail":{"type":"object","properties":{"min_margin":{"type":"integer"},"features":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"},"measurable":{"type":"boolean"},"reason":{"type":"string"},"treated_first_drafts_with_value":{"type":"integer"},"control_first_drafts_with_value":{"type":"integer"},"first_drafts_unmeasured":{"type":"integer"},"moved":{"type":"boolean"}},"required":["attribute","focus_value","measurable"]},"description":"(a) each predicted feature, on the treated vs the control first drafts."},"rescues":{"type":"integer"},"min_rescues":{"type":"integer"},"treated_delivered":{"type":"integer"},"control_delivered":{"type":"integer"},"treated_deliveries_with_unsupported_claim":{"type":"integer"},"treated_deliveries_judge_flagged":{"type":"integer"},"verdicts":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"verdict":{"type":"string","nullable":true,"enum":["no_evident_degradation","evident_degradation"]}},"required":["judge","verdict"]},"description":"(e) each preregistered judge’s verdict."}},"description":"The clause counts (each clause fills its own members; never a body)."}},"required":["clause","holds","detail"],"description":"One screen-rule clause and its counts."},"description":"Every clause with its counts (empty when incomplete — nothing is analysed)."},"progress":{"type":"object","properties":{"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean","description":"True once a call of the phase was refused for want of money — incomplete forever."}},"required":["pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The screen completion-barrier counts (complete / incomplete only — no per-arm outcome)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"feature_min_margin":{"type":"integer"},"min_first_pass_rescues":{"type":"integer"},"unsupported_claim_codes":{"type":"array","items":{"type":"string"}}},"required":["feature_min_margin","min_first_pass_rescues","unsupported_claim_codes"],"description":"The frozen rule the verdict applied."},"inputs":{"type":"object","properties":{"pairs":{"type":"array","items":{"type":"string"}},"observations":{"type":"array","items":{"type":"object","properties":{"attribute":{"type":"string"},"focus_value":{"type":"string"}},"required":["attribute","focus_value"]}},"phase_holds":{"type":"object","properties":{"reserved":{"type":"integer","minimum":0},"ambiguous":{"type":"integer","minimum":0}},"required":["reserved","ambiguous"]},"cap_stopped":{"type":"boolean"},"candidate_withdrawn":{"type":"boolean"},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"state":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."},"outcome_hash":{"type":"string","nullable":true},"cost":{"type":"object","nullable":true,"properties":{"rows_measured_micro_usd":{"type":"integer"},"rows_unpriced":{"type":"integer","minimum":0},"rows_unpriced_unresolved":{"type":"integer","minimum":0},"rows":{"type":"integer","minimum":0},"holds":{"type":"integer","minimum":0},"settled_micro_usd":{"type":"integer"},"ambiguous_micro_usd":{"type":"integer"},"reserved_micro_usd":{"type":"integer"},"difference_micro_usd":{"type":"integer"},"unexplained_micro_usd":{"type":"integer"},"holds_reconciled":{"type":"integer","minimum":0},"holds_released_after_dispatch":{"type":"integer","minimum":0},"unlanded_holds":{"type":"integer","minimum":0},"rowless_resolved_holds":{"type":"integer","minimum":0},"complete":{"type":"boolean"}},"required":["rows_measured_micro_usd","rows_unpriced","rows_unpriced_unresolved","rows","holds","settled_micro_usd","ambiguous_micro_usd","reserved_micro_usd","difference_micro_usd","unexplained_micro_usd","holds_reconciled","holds_released_after_dispatch","unlanded_holds","rowless_resolved_holds","complete"]}},"required":["execution_id","pair_key","slot","arm","state","outcome_hash","cost"]}},"output_manifest_hash":{"type":"string","nullable":true,"description":"The content address of the screen’s output manifest (every screen execution’s final-content hash)."},"judgements":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"judgement_hash":{"type":"string"},"manifest_hash":{"type":"string","description":"The output manifest the judge reviewed."}},"required":["judge","judgement_hash","manifest_hash"]}}},"required":["pairs","observations","phase_holds","cap_stopped","candidate_withdrawn","executions","output_manifest_hash","judgements"],"description":"The verdict inputs: each execution’s identity, arm, standing, outcome hash and cost reconciliation, the output manifest, and each judgement’s hash and reviewed manifest."},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_clauses","incomplete_reasons","clauses","progress","rule_version","rule","inputs","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the verdict is stored."}},"default":null,"required":["progress","executions","verdict"],"description":"The screen: barrier counts (no peeking) and, once computed, the verdict."},"test":{"type":"object","nullable":true,"properties":{"manifest_committed":{"type":"boolean"},"manifest_hash":{"type":"string","nullable":true},"n":{"type":"integer","minimum":0},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"executions":{"type":"array","items":{"type":"object","properties":{"execution_id":{"type":"string"},"pair_key":{"type":"string"},"slot":{"type":"integer","minimum":0,"maximum":1},"arm":{"type":"string","enum":["control","treated"]},"status":{"type":"string","enum":["no_outcome","pending_rows","cost_unsettled","invalid","complete"],"description":"no_outcome: none recorded yet; pending_rows: recorded, a call’s row has not landed; cost_unsettled: a hold is still reserved or ambiguous; invalid: the recorded outcome fails now that its rows landed; complete."}},"required":["execution_id","pair_key","slot","arm","status"],"description":"One enrolled test execution — ids, arm and standing only."}},"verdict":{"type":"object","nullable":true,"properties":{"verdict":{"type":"string","enum":["test_passed","test_failed","test_incomplete"]},"failing_parts":{"type":"array","items":{"type":"string"},"description":"Every failing part (test_failed); empty otherwise."},"incomplete_reasons":{"type":"array","items":{"type":"string"},"description":"Why it can never complete (test_incomplete); else empty."},"primary":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"p_value":{"type":"number"},"alpha":{"type":"number"},"wins":{"type":"integer","minimum":0},"losses":{"type":"integer","minimum":0},"treated_delivered":{"type":"integer","minimum":0},"control_delivered":{"type":"integer","minimum":0},"pairs_analysed":{"type":"integer","minimum":0}},"required":["pass","p_value","alpha","wins","losses","treated_delivered","control_delivered","pairs_analysed"]},"economics":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"inconclusive":{"type":"boolean"},"ratio":{"type":"number","nullable":true},"min_ratio":{"type":"number"},"permutation_p_value":{"type":"number","nullable":true},"permutations":{"type":"integer","minimum":0},"seed":{"type":"integer"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_cost_micro_usd":{"type":"integer","minimum":0},"control_cost_micro_usd":{"type":"integer","minimum":0}},"required":["pass","inconclusive","ratio","min_ratio","permutation_p_value","permutations","seed","treated_deliveries","control_deliveries","treated_cost_micro_usd","control_cost_micro_usd"]},"quality":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"min_delta":{"type":"number"},"per_judge":{"type":"array","items":{"type":"object","properties":{"judge":{"type":"string"},"recorded":{"type":"boolean"},"treated_deliveries":{"type":"integer","minimum":0},"control_deliveries":{"type":"integer","minimum":0},"treated_publishable":{"type":"integer","minimum":0},"control_publishable":{"type":"integer","minimum":0},"treated_publishable_rate":{"type":"number","nullable":true},"control_publishable_rate":{"type":"number","nullable":true},"delta":{"type":"number","nullable":true},"serious_treated_defects":{"type":"integer","minimum":0},"clears":{"type":"boolean"}},"required":["judge","recorded","treated_deliveries","control_deliveries","treated_publishable","control_publishable","treated_publishable_rate","control_publishable_rate","delta","serious_treated_defects","clears"]}}},"required":["pass","min_delta","per_judge"]},"goodhart":{"type":"object","nullable":true,"properties":{"arms":{"type":"array","items":{"type":"object","properties":{"arm":{"type":"string","enum":["control","treated"]},"first_draft_length_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"first_draft_cited_quotes_band":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"stranger_usefulness":{"type":"object","additionalProperties":{"type":"integer","minimum":0}},"repair_count":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["arm","first_draft_length_band","first_draft_cited_quotes_band","stranger_usefulness","repair_count"]}}},"required":["arms"]},"claim_text":{"type":"string","nullable":true,"description":"The frozen claim text (a pass only) — never more than it is licensed to say."},"progress":{"type":"object","properties":{"n":{"type":"integer","minimum":0},"pairs_total":{"type":"integer","minimum":0},"pairs_complete":{"type":"integer","minimum":0},"executions_enrolled":{"type":"integer","minimum":0},"outcomes_recorded":{"type":"integer","minimum":0},"executions_complete":{"type":"integer","minimum":0},"executions_incomplete":{"type":"integer","minimum":0},"executions_pending_rows":{"type":"integer","minimum":0},"executions_cost_unsettled":{"type":"integer","minimum":0},"executions_invalid":{"type":"integer","minimum":0},"holds_reserved":{"type":"integer","minimum":0},"holds_ambiguous":{"type":"integer","minimum":0},"judgements_recorded":{"type":"integer","minimum":0},"judges_required":{"type":"integer","minimum":0},"cap_stopped":{"type":"boolean"}},"required":["n","pairs_total","pairs_complete","executions_enrolled","outcomes_recorded","executions_complete","executions_incomplete","executions_pending_rows","executions_cost_unsettled","executions_invalid","holds_reserved","holds_ambiguous","judgements_recorded","judges_required","cap_stopped"],"description":"The test completion-barrier counts (no per-arm outcome before the verdict)."},"rule_version":{"type":"string"},"rule":{"type":"object","properties":{"version":{"type":"string"},"n":{"type":"integer","minimum":0},"alpha":{"type":"number"},"economics_min_ratio":{"type":"number"},"economics_permutations":{"type":"integer","minimum":0},"economics_seed":{"type":"integer"},"quality_min_delta":{"type":"number"}},"required":["version","n","alpha","economics_min_ratio","economics_permutations","economics_seed","quality_min_delta"]},"economics_seed":{"type":"integer"},"economics_permutations":{"type":"integer","minimum":0},"inputs_hash":{"type":"string"},"candidate_hash":{"type":"string"},"prereg_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["verdict","failing_parts","incomplete_reasons","primary","economics","quality","goodhart","claim_text","progress","rule_version","rule","economics_seed","economics_permutations","inputs_hash","candidate_hash","prereg_hash","created_at"],"description":"Null until the completion barrier is met and the decision is stored."}},"default":null,"required":["manifest_committed","manifest_hash","n","progress","executions","verdict"],"description":"The prospective test: barrier counts (no peeking) and, once computed, the decision."},"import_id":{"type":"string","nullable":true},"created_by_user_id":{"type":"string"},"created_at":{"type":"string"},"updated_at":{"type":"string"}},"required":["id","state","admission","prereg_hash","verifier_version","budget","expires_at","benchmarkable","object","workspace_id","call_type_id","situation_class","lever_key","candidate_hash","import_id","created_by_user_id","created_at","updated_at"],"description":"A bounded experiment — ids / hashes / counts / state only, never a body."}},"required":["object","experiment"],"description":"One bounded experiment."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/confirmations":{"get":{"operationId":"listConfirmations","tags":["Flywheel"],"summary":"List the workspace confirmations — find what to adopt","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"LIST the workspace’s live-improvement confirmations, newest first. Each carries its candidate reference (the id the adopt/reject decision route takes), call type, lever family, the servable module id/version, its lifecycle status, the one-look live result (pending | confirmed | refuted | inconclusive) and whether it is adoptable now (open AND confirmed). This is the discovery surface a customer or SDK reads to find the CONFIRMED candidate to adopt via `POST /v1/flywheel/confirmations/{ref}/decision`. Read-only. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The workspace confirmations ledger (empty when none exist).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_confirmations"]},"workspace_id":{"type":"string"},"confirmations":{"type":"array","items":{"type":"object","properties":{"candidate_ref":{"type":"string","description":"The candidate reference — the id a decision route (adopt/reject) takes."},"call_type_id":{"type":"string","nullable":true,"description":"The call type this confirmation is measured on."},"lever_key":{"type":"string","description":"The lever family (e.g. `learned_context`)."},"module_id":{"type":"string","description":"The servable learned-context module id of this confirmation candidate."},"module_version":{"type":"string","description":"The recipe-hash module version."},"epoch":{"type":"integer","description":"The measurement epoch the candidate is bound to."},"status":{"type":"string","description":"The lifecycle: open | adopted | rolled_back | invalidated | closed."},"result_outcome":{"type":"string","description":"The one-look live result: pending | confirmed | refuted | inconclusive."},"adoptable":{"type":"boolean","description":"True ONLY when the confirmation is open AND its live result is confirmed."},"opened_at":{"type":"string","nullable":true,"description":"When the confirmation was opened (ISO), or null on a legacy row."}},"required":["candidate_ref","call_type_id","lever_key","module_id","module_version","epoch","status","result_outcome","adoptable","opened_at"],"description":"One confirmation in the workspace ledger — metadata only, never a body."}}},"required":["object","workspace_id","confirmations"],"description":"The workspace confirmations ledger — the discovery surface for what to adopt."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/candidates":{"get":{"operationId":"listFlywheelCandidates","tags":["Flywheel"],"summary":"List the inbox candidates — each with its offline deciding axis","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The Improvements-inbox candidate LIST: ONE list of every discrete candidate the flywheel produced (no lever filter), newest first. Each carries its screening run id, lever coordinates, a provenance chip DERIVED from the run’s own trigger evidence, its offline screening verdict and its live status. When a candidate has been screened it carries an `offline` DECIDING reading: the decision-contract intent it was decided under, the quality + cost intervals with their tri-states (labelled as the evidence tier they are — never a savings or quality claim), and the `deciding` axis (whether QUALITY or COST made the outcome) — so a customer can tell \"did not help\" from \"helped but over your cost budget\". Read-only. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body — ids/coordinates/interval numbers only. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The workspace inbox candidates with their offline deciding axis (empty when none).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_candidates"]},"workspace_id":{"type":"string"},"candidates":{"type":"array","items":{"type":"object","properties":{"run_id":{"type":"string","description":"The screening run id (the evidence trace)."},"call_type_id":{"type":"string","nullable":true,"description":"The call type the candidate is measured on."},"lever_key":{"type":"string","description":"The lever family (e.g. `learned_context` / `hosted_prompt`)."},"epoch":{"type":"integer","description":"The measurement epoch the candidate is bound to."},"module_id":{"type":"string","nullable":true,"description":"The candidate module/version id, or null."},"module_version":{"type":"string","nullable":true,"description":"The candidate module version (recipe hash), or null."},"provenance":{"type":"string","enum":["corrections","eval_set","human_draft","unknown"],"description":"WHERE the proposal came from — DERIVED from the run’s trigger evidence, never a prop."},"offline_verdict":{"type":"string","enum":["none","screening","screened","rejected","parked"],"description":"The offline screening verdict for this candidate."},"offline":{"type":"object","nullable":true,"properties":{"contract":{"type":"string","description":"The decision intent the screen was decided under (e.g. `product_improvement`)."},"quality":{"type":"object","properties":{"low":{"type":"number","description":"The lower confidence bound."},"point":{"type":"number","description":"The point estimate."},"high":{"type":"number","description":"The upper confidence bound."},"state":{"type":"string","enum":["pass","fail","inconclusive"],"description":"The tri-state for this axis — a labelled tier, never a claim."}},"required":["low","point","high","state"],"description":"The quality (non-inferiority / superiority) interval."},"cost":{"type":"object","properties":{"low":{"type":"number","description":"The lower confidence bound."},"point":{"type":"number","description":"The point estimate."},"high":{"type":"number","description":"The upper confidence bound."},"state":{"type":"string","enum":["pass","fail","inconclusive"],"description":"The tri-state for this axis — a labelled tier, never a claim."}},"required":["low","point","high","state"],"description":"The cost (savings / budget) interval."},"deciding":{"type":"array","items":{"type":"string","enum":["quality","cost","guardrail","evidence"]},"description":"The conjunct axes whose state made the outcome — EMPTY on a screened pass."},"economics":{"type":"object","nullable":true,"properties":{"version":{"type":"integer","description":"The absolute-economics derivation version."},"design":{"type":"string","enum":["paired","independent"],"description":"`paired` for an offline contrast on the same clusters; `independent` for live arms."},"extra_cost_per_1000_micro_usd":{"type":"object","properties":{"low":{"type":"number"},"point":{"type":"number"},"high":{"type":"number"}},"required":["low","point","high"],"description":"EXTRA cost per 1,000 requests, µUSD (treated − baseline). Negative ⇒ the lever is CHEAPER."},"errors_avoided_per_1000":{"type":"object","properties":{"low":{"type":"number"},"point":{"type":"number"},"high":{"type":"number"}},"required":["low","point","high"],"description":"ERRORS AVOIDED per 1,000 requests (the treated − baseline success-rate gap, scaled)."},"cost_per_avoided_error_micro_usd":{"type":"object","properties":{"status":{"type":"string","enum":["measured","unavailable"],"description":"`unavailable` ⇒ the ratio is undefined/unbounded; there is no number to show."},"low":{"type":"number","nullable":true,"description":"The lower bound (null when unavailable)."},"point":{"type":"number","nullable":true,"description":"The point estimate (null when unavailable)."},"high":{"type":"number","nullable":true,"description":"The upper bound (null when unavailable)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason the figure is unavailable (null when measured)."}},"required":["status","low","point","high","reason"],"description":"$ per AVOIDED ERROR, µUSD — `unavailable` whenever the errors-avoided interval crosses zero."},"net_value_per_1000_micro_usd":{"type":"object","nullable":true,"properties":{"status":{"type":"string","enum":["measured","unavailable"],"description":"`unavailable` ⇒ the ratio is undefined/unbounded; there is no number to show."},"low":{"type":"number","nullable":true,"description":"The lower bound (null when unavailable)."},"point":{"type":"number","nullable":true,"description":"The point estimate (null when unavailable)."},"high":{"type":"number","nullable":true,"description":"The upper bound (null when unavailable)."},"reason":{"type":"string","nullable":true,"description":"The NAMED reason the figure is unavailable (null when measured)."}},"required":["status","low","point","high","reason"],"description":"The JOINT `value × Δsuccess − Δcost` per 1,000 requests — null when no value was preregistered."},"value_per_avoided_error_micro_usd":{"type":"number","nullable":true,"description":"The PREREGISTERED value the joint bound was computed with (null when none)."},"n_clusters_treated":{"type":"integer"},"n_clusters_baseline":{"type":"integer"}},"required":["version","design","extra_cost_per_1000_micro_usd","errors_avoided_per_1000","cost_per_avoided_error_micro_usd","net_value_per_1000_micro_usd","value_per_avoided_error_micro_usd","n_clusters_treated","n_clusters_baseline"],"description":"The ABSOLUTE economics beside the ratio; null when the screen measured no absolute cost."}},"required":["contract","quality","cost","deciding","economics"],"description":"The deciding reading (contract + intervals + deciding axes), or null before the screen ran."},"live_verdict":{"type":"string","description":"The live-confirmation verdict (`not_run` until a confirmation opens)."},"started_at":{"type":"string","description":"When the screening run opened (ISO)."}},"required":["run_id","call_type_id","lever_key","epoch","module_id","module_version","provenance","offline_verdict","offline","live_verdict","started_at"],"description":"One inbox candidate with its offline deciding reading — metadata only, never a body."}}},"required":["object","workspace_id","candidates"],"description":"The workspace Improvements-inbox candidates with their offline deciding axis."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/improvement-reads":{"get":{"operationId":"listImprovementReads","tags":["Flywheel"],"summary":"Both goals for every call type — spend less AND get better","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"MULTI-GOAL BY DEFAULT. For EVERY call type the workspace has, BOTH reads WITHOUT being asked: \"a cheaper model is enough here\" (the eval-backed model-migration recommendation evidence) AND \"quality can improve here\" (the Flywheel candidate + learning-plan evidence). Each half resolves to ONE closed state — `evidence` (a source row id + its evidence tier + an ESTIMATE label where it is one + the next action), `collecting` (n of a NAMED engine floor), `needs_confirmation` (a learning-plan proposal to confirm), `keep_incumbent` (the recommendation engine’s neutral result) or `unavailable` (a NAMED reason). A PURE composition over the existing engines — no new statistic, no ranking; an estimate is never shown as realized and a screened candidate is never shown as confirmed (fail-closed). The get-better default intent is `product_improvement`; a customer-stated intent is reported, never overridden. Read-only. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body — ids/tiers/counts/sentences only. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"Both improvement reads for every call type the workspace has (empty when it has none).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImprovementReadsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/knowledge/export":{"get":{"operationId":"exportKnowledgeBundle","tags":["Flywheel"],"summary":"Export the knowledge DB as a bundle — the customer’s to take","security":[{"sessionCookie":[]}],"description":"EXPORT the workspace’s knowledge DB as a portable, content-addressed bundle: every distilled fact, exemplar, prior and process pattern (each with its n / interval / window / lineage back to the customer’s OWN outcome events) plus the learned modules and their lift history. A DISTINCT object from the training-ready SFT export — the bundle is FOR the customer; any training runs only per-workspace under the `train_allowed` gate, never a shared or cross-workspace model (raw customer items never cross a workspace). Consent- + retention-bound: a revoked or suppressed item is dropped, items past retention are absent, and a workspace without export consent gets the NAMED refusal `EXPORT_CONSENT_REVOKED` (409). Deterministic: the same data reproduces a byte-identical bundle (generated_at excluded from the hash). Session + `flywheel.export` RBAC (owner|admin; a viewer is 403). NEVER a body.","parameters":[{"schema":{"type":"string","description":"Optional — restrict every section to knowledge/modules scoped to this call type."},"required":false,"description":"Optional — restrict every section to knowledge/modules scoped to this call type.","name":"call_type","in":"query"},{"schema":{"type":"string","description":"The workspace id (or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The content-addressed knowledge-DB bundle (empty sections when none exist).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["knowledge_bundle"]},"bundle":{"type":"object","properties":{"schema":{"type":"string","enum":["ur.knowledge_bundle/v1"]},"workspace_id":{"type":"string"},"redaction_version":{"type":"string"},"bundle_hash":{"type":"string","description":"The content address of the bundle — `generated_at` is EXCLUDED."},"generated_at":{"type":"string","description":"When the bundle was generated (ISO) — NOT part of `bundle_hash`."},"counts":{"type":"object","properties":{"facts":{"type":"object","properties":{"current":{"type":"integer"},"history":{"type":"integer"}},"required":["current","history"],"description":"A fact section count split into current live facts and superseded history."},"exemplars":{"type":"object","properties":{"current":{"type":"integer"},"history":{"type":"integer"}},"required":["current","history"],"description":"A fact section count split into current live facts and superseded history."},"priors":{"type":"object","properties":{"current":{"type":"integer"},"history":{"type":"integer"}},"required":["current","history"],"description":"A fact section count split into current live facts and superseded history."},"process_patterns":{"type":"object","properties":{"current":{"type":"integer"},"history":{"type":"integer"}},"required":["current","history"],"description":"A fact section count split into current live facts and superseded history."},"modules":{"type":"integer"},"lineage":{"type":"integer"}},"required":["facts","exemplars","priors","process_patterns","modules","lineage"],"description":"Per-section (current/history split) + lineage counts."},"facts":{"type":"array","items":{"type":"object","properties":{"factId":{"type":"string"},"kind":{"type":"string"},"contentHash":{"type":"string"},"scope":{"type":"object","properties":{"callTypeId":{"type":"string"},"modelId":{"type":"string"},"provider":{"type":"string"},"domain":{"type":"string"},"claimType":{"type":"string"},"scaffoldClass":{"type":"string"}},"description":"The structured scope a fact is about — allowlisted keys only."},"n":{"type":"integer"},"clusters":{"type":"integer"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"evidenceTier":{"type":"string"},"arms":{"type":"array","items":{"type":"string"}},"windowStart":{"type":"string","nullable":true},"windowEnd":{"type":"string","nullable":true},"current":{"type":"boolean","description":"True when this is the CURRENT fact for its scope identity (supersession is resolved at read time)."},"supersededBy":{"type":"string","nullable":true,"description":"The factId of the current fact that superseded this predecessor; null when current."},"lineageRefs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The ref kind (e.g. `outcome_event`, `confirmation`)."},"id":{"type":"string","description":"The id of the referenced row (the customer joins it back to their own data)."}},"required":["kind","id"],"description":"A typed lineage ref linking a bundle item to the customer’s own outcome events / ledger."}}},"required":["factId","kind","contentHash","scope","n","clusters","rate","interval","evidenceTier","arms","windowStart","windowEnd","current","supersededBy","lineageRefs"],"description":"A distilled fact/exemplar/prior/pattern with its n / interval / window / lineage — never a body."}},"exemplars":{"type":"array","items":{"type":"object","properties":{"factId":{"type":"string"},"kind":{"type":"string"},"contentHash":{"type":"string"},"scope":{"type":"object","properties":{"callTypeId":{"type":"string"},"modelId":{"type":"string"},"provider":{"type":"string"},"domain":{"type":"string"},"claimType":{"type":"string"},"scaffoldClass":{"type":"string"}},"description":"The structured scope a fact is about — allowlisted keys only."},"n":{"type":"integer"},"clusters":{"type":"integer"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"evidenceTier":{"type":"string"},"arms":{"type":"array","items":{"type":"string"}},"windowStart":{"type":"string","nullable":true},"windowEnd":{"type":"string","nullable":true},"current":{"type":"boolean","description":"True when this is the CURRENT fact for its scope identity (supersession is resolved at read time)."},"supersededBy":{"type":"string","nullable":true,"description":"The factId of the current fact that superseded this predecessor; null when current."},"lineageRefs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The ref kind (e.g. `outcome_event`, `confirmation`)."},"id":{"type":"string","description":"The id of the referenced row (the customer joins it back to their own data)."}},"required":["kind","id"],"description":"A typed lineage ref linking a bundle item to the customer’s own outcome events / ledger."}}},"required":["factId","kind","contentHash","scope","n","clusters","rate","interval","evidenceTier","arms","windowStart","windowEnd","current","supersededBy","lineageRefs"],"description":"A distilled fact/exemplar/prior/pattern with its n / interval / window / lineage — never a body."}},"priors":{"type":"array","items":{"type":"object","properties":{"factId":{"type":"string"},"kind":{"type":"string"},"contentHash":{"type":"string"},"scope":{"type":"object","properties":{"callTypeId":{"type":"string"},"modelId":{"type":"string"},"provider":{"type":"string"},"domain":{"type":"string"},"claimType":{"type":"string"},"scaffoldClass":{"type":"string"}},"description":"The structured scope a fact is about — allowlisted keys only."},"n":{"type":"integer"},"clusters":{"type":"integer"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"evidenceTier":{"type":"string"},"arms":{"type":"array","items":{"type":"string"}},"windowStart":{"type":"string","nullable":true},"windowEnd":{"type":"string","nullable":true},"current":{"type":"boolean","description":"True when this is the CURRENT fact for its scope identity (supersession is resolved at read time)."},"supersededBy":{"type":"string","nullable":true,"description":"The factId of the current fact that superseded this predecessor; null when current."},"lineageRefs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The ref kind (e.g. `outcome_event`, `confirmation`)."},"id":{"type":"string","description":"The id of the referenced row (the customer joins it back to their own data)."}},"required":["kind","id"],"description":"A typed lineage ref linking a bundle item to the customer’s own outcome events / ledger."}}},"required":["factId","kind","contentHash","scope","n","clusters","rate","interval","evidenceTier","arms","windowStart","windowEnd","current","supersededBy","lineageRefs"],"description":"A distilled fact/exemplar/prior/pattern with its n / interval / window / lineage — never a body."}},"process_patterns":{"type":"array","items":{"type":"object","properties":{"factId":{"type":"string"},"kind":{"type":"string"},"contentHash":{"type":"string"},"scope":{"type":"object","properties":{"callTypeId":{"type":"string"},"modelId":{"type":"string"},"provider":{"type":"string"},"domain":{"type":"string"},"claimType":{"type":"string"},"scaffoldClass":{"type":"string"}},"description":"The structured scope a fact is about — allowlisted keys only."},"n":{"type":"integer"},"clusters":{"type":"integer"},"rate":{"type":"number","nullable":true},"interval":{"type":"array","nullable":true,"items":{"type":"number"},"minItems":2,"maxItems":2},"evidenceTier":{"type":"string"},"arms":{"type":"array","items":{"type":"string"}},"windowStart":{"type":"string","nullable":true},"windowEnd":{"type":"string","nullable":true},"current":{"type":"boolean","description":"True when this is the CURRENT fact for its scope identity (supersession is resolved at read time)."},"supersededBy":{"type":"string","nullable":true,"description":"The factId of the current fact that superseded this predecessor; null when current."},"lineageRefs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The ref kind (e.g. `outcome_event`, `confirmation`)."},"id":{"type":"string","description":"The id of the referenced row (the customer joins it back to their own data)."}},"required":["kind","id"],"description":"A typed lineage ref linking a bundle item to the customer’s own outcome events / ledger."}}},"required":["factId","kind","contentHash","scope","n","clusters","rate","interval","evidenceTier","arms","windowStart","windowEnd","current","supersededBy","lineageRefs"],"description":"A distilled fact/exemplar/prior/pattern with its n / interval / window / lineage — never a body."}},"modules":{"type":"array","items":{"type":"object","properties":{"candidateRef":{"type":"string"},"callTypeId":{"type":"string","nullable":true},"leverKey":{"type":"string"},"moduleId":{"type":"string"},"moduleVersion":{"type":"string"},"epoch":{"type":"integer"},"status":{"type":"string"},"verdict":{"type":"string","description":"The one-look live verdict: pending | confirmed | refuted | inconclusive."},"openedAt":{"type":"string","nullable":true},"lift":{"type":"object","nullable":true,"properties":{"estimate":{"type":"number"},"ciLow":{"type":"number"},"ciHigh":{"type":"number"},"nTreated":{"type":"integer"},"nLeverHoldout":{"type":"integer"}},"required":["estimate","ciLow","ciHigh","nTreated","nLeverHoldout"],"description":"The recorded lift interval + per-arm n for a learned module."}},"required":["candidateRef","callTypeId","leverKey","moduleId","moduleVersion","epoch","status","verdict","openedAt","lift"],"description":"A learned module + its lift history from the confirmation ledger — metadata only."}},"lineage":{"type":"array","items":{"type":"object","properties":{"itemId":{"type":"string"},"section":{"type":"string","enum":["facts","exemplars","priors","process_patterns","modules"]},"contentHash":{"type":"string"},"refs":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","description":"The ref kind (e.g. `outcome_event`, `confirmation`)."},"id":{"type":"string","description":"The id of the referenced row (the customer joins it back to their own data)."}},"required":["kind","id"],"description":"A typed lineage ref linking a bundle item to the customer’s own outcome events / ledger."}}},"required":["itemId","section","contentHash","refs"],"description":"A lineage row linking one exported item to its outcome-event ids + content hash."}}},"required":["schema","workspace_id","redaction_version","bundle_hash","generated_at","counts","facts","exemplars","priors","process_patterns","modules","lineage"],"description":"The customer-owned knowledge-DB bundle — a content-addressed projection of the ledger."}},"required":["object","bundle"],"description":"The customer-owned knowledge-DB export bundle."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/candidates/{ref}/confirmation":{"get":{"operationId":"getCandidateConfirmation","tags":["Flywheel"],"summary":"Live confirmation state for a candidate — status + one-look result + lift","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The LIVE confirmation state for a candidate reference: its lifecycle status, the ONE-LOOK result (pending | confirmed | refuted | inconclusive), whether a human may adopt it (adoptable ONLY when the confirmation is open AND its live result is confirmed — never a screening pass alone; the refusal is NAMED, e.g. `not_yet_confirmed_live`), and the recorded live lift (the treated − lever_holdout interval + n per arm). Read-only. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"Path parameter `ref`."},"required":true,"description":"Path parameter `ref`.","name":"ref","in":"path"}],"responses":{"200":{"description":"The live-confirmation state for the candidate (present:false when none exists).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmationStatusResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/plans":{"get":{"operationId":"listLearningPlans","tags":["Flywheel"],"summary":"List the workspace proposals — find the plan ids to confirm","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"LIST the workspace’s learning-plan PROPOSALS, newest first. Each carries the plan id the confirm route (`POST /v1/flywheel/plan/{id}/confirm`) accepts, its workflow id, the lifecycle state, its provenance (`inferred` = derived from the inferred site brief / a zero-traffic seed; `declared` = derived from the workspace’s own traffic) and when it was created. This is the self-serve discovery surface a customer or SDK reads to find WHAT it may confirm — the dashboard derives the id client-side today. Read-only; a proposal never teaches. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The workspace learning-plan proposals (empty when none exist).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_plan_list"]},"workspace_id":{"type":"string"},"plans":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["learning_plan_proposal"]},"id":{"type":"string","description":"The plan id — the id `POST /v1/flywheel/plan/{id}/confirm` accepts."},"workflow_id":{"type":"string"},"review_state":{"type":"string","enum":["proposed","confirmed","declined","deferred","stale"],"description":"The learning-plan lifecycle state."},"provenance":{"type":"string","enum":["inferred","declared"],"description":"inferred = derived from the inferred site brief (a zero-traffic seed); declared = derived from the workspace's OWN traffic. Declared, inferred and gateway provenance are never conflated."},"created_at":{"type":"string"}},"required":["object","id","workflow_id","review_state","provenance","created_at"],"description":"One learning-plan proposal in the discovery list (metadata only, never a body)."}}},"required":["object","workspace_id","plans"],"description":"The workspace's learning-plan proposals — the discovery surface for what to confirm."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"post":{"operationId":"proposeLearningPlan","tags":["Flywheel"],"summary":"Propose a named workflow’s learning plan (the history-first unblock)","security":[{"sessionCookie":[]}],"description":"A member proposes a NAMED call type’s workflow so a workspace with traffic but NO outcome events has a proposal to confirm — discovery only proposes the spend-ranked recommendation, so most workflows never get a proposal row. The server re-derives the SAME draft the confirm route reads and selects the candidate(s) carrying the call type. SESSION + `flywheel.write` RBAC (owner / admin / developer), NEVER an api key. No model call, no paid analysis is authorised. Each named refusal writes nothing and LEADS the error `message` with its stable refusal token (the error envelope carries no separate details field): `call_type_not_found` (404); `unknown_workflow` (409, no candidate carries it); `ambiguous_workflow` (409, > 1 candidate and `workflow_id` absent / not one of them — the candidate ids are in the message); `proposal_pending` (409, the workflow already has a pending proposal — its id is in the message); `workflow_confirmed` (409, a confirmed plan changes only through discovery’s material-change path). One pending proposal per workflow bounds it. NEVER a body.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"call_type_id":{"type":"string","minLength":1,"maxLength":128,"description":"The call type (`ct_…`) whose workflow to propose. The `wfc_…` id is derived server-side."},"workflow_id":{"type":"string","minLength":1,"maxLength":128,"description":"The derived workflow (`wfc_…`) to disambiguate when the call type belongs to more than one candidate. Absent is fine when the call type belongs to exactly one."}},"required":["call_type_id"],"additionalProperties":false,"description":"A member request to propose a named workflow’s learning plan (session-only)."}}}},"responses":{"201":{"description":"The appended proposal (the id to confirm + the selected workflow’s complete bindings).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_plan_proposal"]},"plan_id":{"type":"string"},"workflow_id":{"type":"string"},"call_type_id":{"type":"string"},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"call_type_bindings":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"role":{"type":"string","enum":["intermediate","terminal","reviewer"]}},"required":["call_type_id","role"],"description":"A derived call-type role binding on the proposed workflow."}}},"required":["object","plan_id","workflow_id","call_type_id","version","call_type_bindings"],"description":"The appended learning-plan proposal (the id to confirm + the reviewable binding scope)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/plan":{"get":{"operationId":"getLearningPlan","tags":["Flywheel"],"summary":"The learning plan for a workflow (the discovery projection)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The LEARNING-PLAN projection for one workflow: the derived workflow candidate, its call-type roles, the per-field provenance (structural / drafted / customer), the lifecycle state and the compiled TriggerSpec content address. A PROPOSED plan carries no `artifact_type_version_id` and no `spec_hash` — a proposal never teaches (the type + table boundary, re-checked at consumption). `plan` is null while the workflow is still `collecting` (an honest state, never a faked plan). Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The derived workflow candidate id."},"required":true,"description":"The derived workflow candidate id.","name":"workflow","in":"query"},{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The learning plan for the workflow (or null while collecting).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_plan_envelope"]},"workflow_id":{"type":"string"},"plan":{"type":"object","nullable":true,"properties":{"object":{"type":"string","enum":["learning_plan"]},"id":{"type":"string"},"workflow_id":{"type":"string"},"artifact_type_version_id":{"type":"string"},"version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"review_state":{"type":"string","enum":["proposed","confirmed","declined","deferred","stale"],"description":"The learning-plan lifecycle state."},"plan_input_digest":{"type":"string"},"spec_hash":{"type":"string"},"call_type_bindings":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"role":{"type":"string","enum":["intermediate","terminal","reviewer"]},"label_field_proposal":{"type":"object","nullable":true,"properties":{"path":{"type":"string","nullable":true},"basis":{"type":"string","enum":["corrections","convention","none"]},"candidates":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"changed":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0}},"required":["path","changed","total"],"description":"A candidate reference-agreement label field + its change evidence (counts only)."}}},"required":["path","basis","candidates"],"description":"The structurally-proposed reference-agreement label field for a bound call type."},"label_field":{"type":"string","nullable":true},"label_field_origin":{"type":"string","nullable":true,"enum":["plan_confirmed","schema_convention"]}},"required":["call_type_id","role"],"description":"A derived call-type role binding + its label-field proposal / confirmed field."}},"fields":{"type":"array","items":{"type":"object","additionalProperties":{"nullable":true}}},"proposal_version":{"type":"integer","minimum":0,"exclusiveMinimum":true},"created_at":{"type":"string"}},"required":["object","id","workflow_id","artifact_type_version_id","version","review_state","plan_input_digest","spec_hash","call_type_bindings","fields","proposal_version","created_at"],"description":"One learning-plan version (metadata + the compiled program, never a body)."}},"required":["object","workflow_id","plan"],"description":"The learning plan for a workflow (null while collecting)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/plan/{id}/review":{"post":{"operationId":"reviewLearningPlan","tags":["Flywheel"],"summary":"Record a learning-plan review verb","security":[{"sessionCookie":[]}],"description":"Record ONE review verb on a plan (confirm / edit / decline / defer / accept_diff / keep_mine / merge / split). The verb is PRODUCT TELEMETRY, never a correctness label; `decline` carries a coded reason from the closed menu. Session + `flywheel.write` RBAC (the session names its workspace via the `X-UR-Workspace` header); audited. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["confirm","edit","decline","defer","accept_diff","keep_mine","merge","split"],"description":"The review verb (product telemetry, never a correctness label)."},"path":{"type":"string","maxLength":256},"reason_code":{"type":"string","enum":["wrong_archetype","not_valuable","cannot_observe","already_measured_elsewhere"],"description":"The coded decline reason (the only place the closed menus evolve)."},"proposal_origin":{"type":"string","enum":["structural","drafted","customer"]}},"required":["action"],"additionalProperties":false,"description":"A learning-plan review verb."}}}},"responses":{"202":{"description":"The recorded review verb (product telemetry).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_plan_review_event"]},"id":{"type":"string"},"plan_id":{"type":"string"},"action":{"type":"string","enum":["confirm","edit","decline","defer","accept_diff","keep_mine","merge","split"],"description":"The review verb (product telemetry, never a correctness label)."},"created_at":{"type":"string"}},"required":["object","id","plan_id","action","created_at"],"description":"The recorded review verb (product telemetry)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/preflight":{"post":{"operationId":"preflight","tags":["Preflight"],"summary":"Ask what the gateway would decide — model, fallbacks, learned knowledge, placement, grant","security":[{"bearerAuth":[]}],"description":"For a customer who does NOT proxy through the gateway: which model + fallbacks would route (the SAME routing engine the proxy runs), which learned module would inject (through the ONE shared resolve→rebuild→admit path the inject seam runs) and WHERE (`after_stable_prefix`), PLUS the exposure `grant` so ONE call gives both what to apply AND the arm it is in. The grant is minted by the SAME sanctioned owner the `POST /v1/flywheel/grants` route uses — supply an `artifact_key` or `trace_id` to receive one (else `grant` is null with `grant_reason`). The standing holdout is honoured: a holdout-arm grant withholds the learned module in the same response (`knowledge_reason: \"holdout\"`). Profile level only — there is no request-to-situation ranker. Two cache lifetimes: the module/pin/candidates part is config-versioned (`Cache-Control: private, max-age=5` + a strong `ETag`; `If-None-Match` ⇒ 304); the health-ordered fallbacks are the 30 s live part (`routing.max_age_s`). The grant is NEVER cached — it is excluded from the ETag and served on the uncached `X-UR-Grant` header (a 304 revalidation still carries a fresh one). Requires the `gateway:invoke` scope (a READ of what an invoke would do). NEVER a body/PII in logs. Requires API-key scope: gateway:invoke.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightRequest"}}}},"responses":{"200":{"description":"The routing decision + learned knowledge + placement + the exposure grant (or a 304 via ETag).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/plan/{id}/confirm":{"post":{"operationId":"confirmLearningPlan","tags":["Flywheel"],"summary":"Confirm a proposal (the human step that mints a teaching objective)","security":[{"sessionCookie":[]}],"description":"CONFIRM a proposed learning plan: mint the ConfirmedPlan objective version + compile its TriggerSpec + bump config_version, in one audited transaction. A PROPOSED objective never teaches, so this is a HUMAN step: SESSION + `flywheel.write` RBAC, NEVER an api key. The body carries only the customer's edits to the drafted bundle (value axis + decision policy + the optional `objective_metric` the customer CHOOSES when nothing has been observed yet). This is the SAME assembly the dashboard uses (one implementation). The response echoes `objective_source` (`declared` | `observed` | `inferred`), server-derived. Fail-closed: a missing plan is 404; a re-derivation miss / no-measurable-signal (pass `objective_metric` to declare one) is 409 with the coded reason. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"value_per_unit":{"type":"string","maxLength":256},"decision_policy":{"type":"string","enum":["first","final"]},"objective_metric":{"type":"string","enum":["claim_resolution","oracle_delta","correction_rate","acceptance_rate","engagement_rate","task_success"],"description":"The objective metric (closed vocabulary)."},"label_field":{"type":"string","maxLength":256},"decision_intent":{"type":"string","enum":["cost_optimization","required_migration","product_improvement"]},"cost_ceiling_micro_usd":{"type":"integer","minimum":0},"value_per_avoided_error":{"type":"object","properties":{"value_micro_usd":{"type":"integer","minimum":0,"description":"The value of ONE avoided error in integer µUSD (finite, non-negative)."},"outcome":{"type":"string","minLength":1,"maxLength":256,"description":"The OUTCOME this value applies to — never a blank cheque across every outcome."},"population":{"type":"string","minLength":1,"maxLength":256,"description":"The POPULATION this value applies to (the call type / situation stratum)."},"cost_horizon_days":{"type":"integer","minimum":1,"maximum":365,"description":"The cost-allocation HORIZON in days the value is stated over."},"total_cost_ceiling_micro_usd":{"type":"integer","minimum":0,"description":"The hard TOTAL-COST ceiling the contract may never exceed, whatever the value implies."}},"required":["value_micro_usd","outcome","population","cost_horizon_days","total_cost_ceiling_micro_usd"],"additionalProperties":false},"repair_policy":{"type":"object","properties":{"oracle_id":{"type":"string","minLength":1,"maxLength":64,"description":"The registered check (`orc_…`) whose certifier verdicts may mint receipts."},"monthly_cap_micro_usd":{"type":"integer","minimum":0,"description":"The EXPLICIT monthly repair budget in integer µUSD (REQUIRED — no default; 0 spends nothing)."},"teacher_model":{"type":"string","nullable":true,"minLength":1,"maxLength":200,"description":"The confirmed stronger TEACHER model for the last rung (absent / null ⇒ that rung abstains)."},"sample_rate":{"type":"number","minimum":0,"exclusiveMinimum":true,"maximum":1,"description":"The frozen sampling fraction over eligible outputs, in (0, 1] (default 1)."}},"required":["oracle_id","monthly_cap_micro_usd"],"additionalProperties":false}},"additionalProperties":false,"description":"A learning-plan confirm (the customer's edits to the drafted bundle)."}}}},"responses":{"200":{"description":"The confirmed objective version + its compiled capture levels.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["learning_plan_confirm"]},"plan_id":{"type":"string"},"artifact_type_version":{"type":"integer"},"config_version":{"type":"integer"},"capture_levels":{"type":"object","additionalProperties":{"type":"string"}},"objective_source":{"type":"string","enum":["declared","observed","inferred"]},"decision_contract_ids":{"type":"array","items":{"type":"string"}},"repair_policies":{"type":"array","items":{"type":"object","properties":{"call_type_id":{"type":"string"},"oracle_id":{"type":"string"},"oracle_version":{"type":"string"},"monthly_cap_micro_usd":{"type":"integer"},"teacher_model":{"type":"string","nullable":true},"sample_rate":{"type":"number"},"config_version":{"type":"integer"}},"required":["call_type_id","oracle_id","oracle_version","monthly_cap_micro_usd","teacher_model","sample_rate","config_version"]}}},"required":["object","plan_id","artifact_type_version","config_version","capture_levels","objective_source","decision_contract_ids","repair_policies"],"description":"The confirmed objective version + its compiled capture levels."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/confirmations/{ref}/decision":{"post":{"operationId":"decideCandidateConfirmation","tags":["Flywheel"],"summary":"The human accept/reject/revert press on a candidate confirmation","security":[{"sessionCookie":[]}],"description":"The HUMAN accept/reject/revert PRESS. An `accept` ADOPTS the candidate as an expiring lease ONLY when its live confirmation recorded a `confirmed` superior result (never on a screening pass alone); a `reject` closes the confirmation as refused; a `revert` is audit-only. Adoption is a HUMAN step: SESSION + `flywheel.write` RBAC, NEVER an api key. A MANDATORY coded reason. A human decision is HARD-WIRED to `learning_use:audit` (it can never train). Fail-closed: a missing/cross-workspace confirmation is 404; a not-yet-confirmed candidate is 409. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `ref`."},"required":true,"description":"Path parameter `ref`.","name":"ref","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["accept","reject","revert"]},"reason":{"type":"string","minLength":1,"maxLength":2000},"evidence_hash":{"type":"string","maxLength":128}},"required":["decision","reason"],"additionalProperties":false,"description":"A human accept/reject/revert decision on a candidate confirmation."}}}},"responses":{"200":{"description":"The recorded human decision (audit-only; the adopted lease when an accept adopted).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_candidate_decision"]},"candidate_ref":{"type":"string"},"decision":{"type":"string","enum":["accept","reject","revert"]},"learning_use":{"type":"string","enum":["audit"]},"adopted":{"type":"object","nullable":true,"properties":{"lease_id":{"type":"string"},"config_version":{"type":"integer"}},"required":["lease_id","config_version"]}},"required":["object","candidate_ref","decision","learning_use","adopted"],"description":"The recorded human decision (audit-only; the adopted lease when an accept adopted)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/candidates/{runId}/accept":{"post":{"operationId":"acceptCostRefusedCandidate","tags":["Flywheel"],"summary":"Accept a lever the screen refused on cost — opens a controlled confirmation","security":[{"sessionCookie":[]}],"description":"The EXPLICIT customer ACCEPT of a quality lever the offline screen refused ON COST ALONE (it helped, but it was over the stated cost budget). Such a lever stays a RECOMMENDATION, shown beside its ABSOLUTE economics: extra $ per 1,000 requests, errors avoided per 1,000 and $ per avoided error, each with its interval (an undefined ratio reads `unavailable`, never a number). A customer who reads those figures may accept the trade. The accept writes an audit event and OPENS A CONTROLLED CONFIRMATION — nothing more: the screen’s verdict is NOT rewritten (the response echoes the unchanged `offline_verdict`), nothing is adopted (`adopted` is always false) and no serving configuration changes; the candidate is served to nobody until the live comparison it opened produces a result and a human adopts THAT. SESSION + `flywheel.write` RBAC, NEVER an api key. A MANDATORY reason. Fail-closed: a missing run is 404; a run that was NOT cost-refused (a screened, parked or quality-refused one) or a full confirmation-slot pool is 409. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `runId`."},"required":true,"description":"Path parameter `runId`.","name":"runId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reason":{"type":"string","minLength":1,"maxLength":2000}},"required":["reason"],"additionalProperties":false,"description":"An explicit customer accept of a cost-refused lever — opens a confirmation only."}}}},"responses":{"200":{"description":"The opened controlled confirmation — never an adoption, never a changed screen verdict.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["flywheel_candidate_accept"]},"run_id":{"type":"string"},"candidate_ref":{"type":"string"},"confirmation_id":{"type":"string","description":"The CONTROLLED CONFIRMATION this accept opened."},"offline_verdict":{"type":"string"},"adopted":{"type":"boolean","enum":[false]}},"required":["object","run_id","candidate_ref","confirmation_id","offline_verdict","adopted"],"description":"The opened controlled confirmation — never an adoption, never a changed verdict."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/prompt-candidates":{"get":{"operationId":"listPromptCandidates","tags":["Flywheel"],"summary":"List customer-drafted hosted-prompt candidates — the inbox","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"LIST the workspace’s customer-drafted hosted-prompt CANDIDATES, newest first: a non-active `source:human` hosted-prompt version that earned an offline screening on the SAME learned_context path. Each carries its screening run id (the id the approve/reject decision takes), the candidate version id + content sha (the diff-as-ids — never the template text), the derived run status (its screening verdict), the `human_draft` provenance chip, whether it is already the active version, and the NAMED one-lever-family approve gate (`one_family_open`) or null. This is the inbox discovery surface. Read-only. Auth: an api key with `config:read`, OR a Better Auth session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The workspace hosted-prompt candidates (empty when none exist).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_candidates"]},"workspace_id":{"type":"string"},"candidates":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_candidate"]},"run_id":{"type":"string","description":"The screening run id — the id a decision (approve/reject) takes."},"call_type_id":{"type":"string","nullable":true},"version_id":{"type":"string","description":"The candidate hosted-prompt VERSION id (the diff-as-ids identity)."},"content_sha256":{"type":"string","description":"The candidate template content sha (the diff-as-shas — never the template text)."},"epoch":{"type":"integer","description":"The learned_context measurement epoch the run is bound to."},"status":{"type":"string","description":"The DERIVED run status: screening | screened | confirming | rejected | parked | …"},"provenance":{"type":"string","enum":["human_draft"],"description":"Always \"your draft\" — a customer-drafted version, neither correction- nor eval-derived."},"is_active_version":{"type":"boolean","description":"True when this version is ALREADY the call type’s active version (approved)."},"live_status":{"type":"string","nullable":true,"description":"The candidate’s live-confirmation status (open | adopted | closed | …), or null when none opened."},"live_result":{"type":"string","nullable":true,"description":"The live confirmation’s one-look result (pending | confirmed | refuted | inconclusive), or null."},"approve_refusal":{"type":"string","nullable":true,"description":"The NAMED approve gate (`not_confirmed_live` until the live confirmation is confirmed), or null (approvable)."},"started_at":{"type":"string"}},"required":["object","run_id","call_type_id","version_id","content_sha256","epoch","status","provenance","is_active_version","live_status","live_result","approve_refusal","started_at"],"description":"One customer-drafted hosted-prompt candidate in the ONE Improvements inbox."}}},"required":["object","workspace_id","candidates"],"description":"The workspace hosted-prompt candidates — the inbox discovery surface."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/prompt-candidates/{runId}/decision":{"post":{"operationId":"decidePromptCandidate","tags":["Flywheel"],"summary":"Approve (activate) or reject a screened hosted-prompt candidate","security":[{"sessionCookie":[]}],"description":"The HUMAN approve/reject PRESS on a screened customer-drafted hosted-prompt candidate. `approve` ACTIVATES that version through the hosted-prompt activation’s atomic path (a new immutable config version + a new learned_context epoch, gateway-applied) ONLY when the run parked at `screened`, the version is not already active, and NO other lever family holds an open confirmation for the call type (one lever family per call type in confirmation — else the NAMED `one_family_open`, 409); `reject` records the \"did not help\" archive reason. Adoption is a HUMAN step: SESSION + `flywheel.write` RBAC, NEVER an api key. A MANDATORY reason. A human decision is HARD-WIRED to `learning_use:audit`. Fail-closed: a missing/cross-workspace or non-hosted-prompt run is 404. NEVER a body.","parameters":[{"schema":{"type":"string","description":"Path parameter `runId`."},"required":true,"description":"Path parameter `runId`.","name":"runId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","reject"]},"reason":{"type":"string","minLength":1,"maxLength":2000}},"required":["decision","reason"],"additionalProperties":false,"description":"A human approve/reject decision on a hosted-prompt candidate."}}}},"responses":{"200":{"description":"The recorded decision (audit-only; the activated version when an approve activated).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["hosted_prompt_candidate_decision"]},"run_id":{"type":"string"},"decision":{"type":"string","enum":["approve","reject"]},"learning_use":{"type":"string","enum":["audit"]},"activated":{"type":"object","nullable":true,"properties":{"call_type_id":{"type":"string"},"version":{"type":"integer"},"config_version":{"type":"integer"}},"required":["call_type_id","version","config_version"]}},"required":["object","run_id","decision","learning_use","activated"],"description":"The recorded decision (audit-only; the adopted version when an approve adopted)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/reviewer/setup":{"get":{"operationId":"getReviewerSetup","tags":["Flywheel"],"summary":"Guided setup for the reviewer adapter (mapping preview + signature recipe)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Everything needed to wire the ONE supported reviewer integration: the endpoint, the signed-webhook recipe (`HMAC-SHA256` over `\"<unix-seconds>.<raw body>\"`, keyed by your API key, in `X-UR-Reviewer-Signature` + `X-UR-Reviewer-Timestamp`), the required scope, the current `corrections_consent` state, and the MAPPING PREVIEW — what each of your reviewer verdicts becomes in the ledger, shown before a single event is recorded. NEVER echoes a secret. Requires API-key scope: outcomes:write.","responses":{"200":{"description":"The guided-setup payload (mapping preview + signature recipe).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerSetupResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/reviewer/test":{"post":{"operationId":"runReviewerTest","tags":["Flywheel"],"summary":"Run one guided-setup reviewer scenario end to end","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Sends a test artifact and an edited approved final through the REAL ingestion path and returns the JOINED pair. `scenario=replay` re-sends the identical event id (a `duplicate` — a visible no-op, never a second row); `scenario=version_mismatch` deliberately pins a version that does not exist, producing a dead letter for `/v1/flywheel/reviewer/repair` to fix. Test data NEVER enters learning (the reserved artifact carries no exposure arm, so the per-arm attribution rollup excludes it) or invoicing (the path is unmetered). Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerTestRequest"}}}},"responses":{"200":{"description":"The joined artifact + review event pair.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerTestResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/reviewer/events":{"post":{"operationId":"recordReviewerEvents","tags":["Flywheel"],"summary":"Record signed reviewer decisions (the standard reviewer webhook)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The ONE supported reviewer-integration endpoint. Each event carries a stable `artifact_key` (or `artifact_id`), the EXACT `artifact_version` the human reviewed, the reviewer system’s own `event_id`, an `effective_at` and an OPTIONAL consented `final`. The request MUST be signed: `X-UR-Reviewer-Signature: sha256=<hex>` over `\"<X-UR-Reviewer-Timestamp>.<raw body>\"`, keyed by the API key you authenticate with — a missing, stale or invalid signature FAILS CLOSED (403) with a distinct named reason and nothing is written. Per event: a replay of an already-recorded `event_id` is `duplicate` (a visible no-op, never a second row and never an error); an artifact link that does not resolve in this workspace is `unmatched_artifact_key` / `wrong_tenant_artifact_id`; a stale pin is `version_mismatch` and is HELD for repair, never guessed; a final BODY without `corrections_consent` is refused and never stored. An `approved` decision with NO final records the decision and says `final_absent` — a missing final is NEVER auto-declared accepted. Provenance, `latency_class` and `learning_use` are SERVER-assigned; the event schema has no field for them, so an adapter cannot supply them and cannot impersonate another producer. The reviewer decides whether a final is approved — an edit is not an oracle of correctness. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerEventsRequest"}}}},"responses":{"200":{"description":"The per-event verdicts + a rollup.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerEventsResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/reviewer/repair":{"post":{"operationId":"repairReviewerEvent","tags":["Flywheel"],"summary":"Repair one dead-lettered reviewer event","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Re-drive ONE dead-lettered event with an explicit correction. We keep RECEIPTS (ids, hashes, named reasons), not payloads, so send the full original event your durable queue still holds. `repin_to_current_version` is OPT-IN — a stale pin is never silently corrected during normal ingestion, because “the human reviewed draft 2” and “draft 3 exists now” are different facts. A receipt that is already `accepted` is never rewritten (404 on an unknown event id). Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerRepairRequest"}}}},"responses":{"200":{"description":"The refusal before, and the verdict after re-driving.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerRepairResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/reviewer/health":{"get":{"operationId":"getReviewerHealth","tags":["Flywheel"],"summary":"Reviewer-integration health (the six named states + the next repair action)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Last successful event; unmatched / delayed / rejected events; duplicates absorbed; backfill progress per declared id; and the ONE next repair action with the event id it applies to. Every figure comes from the durable receipts, so health survives a restart and cannot disagree with what was ingested. Counts only — NEVER a body. Requires API-key scope: outcomes:write.","responses":{"200":{"description":"The reviewer integration health view.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewerHealthResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/source-checks":{"post":{"operationId":"issueVerdictSourceCheck","tags":["Flywheel"],"summary":"Issue a planted-failure check to your verdict source","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"A claim-less task outcome counts toward the protected readiness floor ONLY when the source that reported it (the server-assigned producer of its credential) has shown it reports KNOWN failures as failures. Name a `call_type_id` — the known-good references are drawn from that call type’s GOLDEN SET (the references its compiled evaluator is qualified against; up to 50 distinct, seeded by the check id), never from items the source picks. The platform plants ONE failure (omission / wrong value / truncation / instruction loss) and ONE valid alternative per reference, renders them in one surface format, shuffles them and returns the probes ONCE. Answer EVERY probe with `POST /v1/flywheel/source-checks/{id}/verdicts` using the SAME credential. The probe bodies (golden-set inputs + probe outputs) are never stored (hashes + the hidden truth only) and never logged. Auth: an api key with `outcomes:write` AND `logs:read` (the probes carry the workspace’s golden-set content, which the default-granted `outcomes:write` alone never reads), OR a Better Auth session + `flywheel.write` RBAC. Refusals (409, named): `no_golden_set`, `insufficient_golden_items` (fewer than 10 distinct references), `insufficient_probes`, `source_revoked`. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"call_type_id":{"type":"string","minLength":1,"maxLength":128,"description":"The call type whose GOLDEN SET supplies the known-good references: up to 50 distinct golden references, each yielding ONE planted failure (an omission / wrong value / truncation / instruction-loss mutation) and ONE valid alternative, shuffled. The source never supplies its own references — a legacy `items` field is refused (400)."}},"required":["call_type_id"],"additionalProperties":false,"description":"Issue a planted-failure check to the calling verdict source."}}}},"responses":{"201":{"description":"The issued check and its probes (returned once).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verdict_source_check"]},"id":{"type":"string","description":"The check id (`vsc_…`) the verdicts are posted to."},"verdict_source":{"type":"string","description":"The verdict source under test — the server-assigned producer of the issuing credential (`api_key:<id>` | `session:<user>`). Only this source may answer the check."},"call_type_id":{"type":"string","description":"The call type whose golden set supplied the references."},"golden_set_id":{"type":"string","description":"The golden set the known-good references were drawn from."},"status":{"type":"string","enum":["open"]},"probe_count":{"type":"integer","minimum":0},"probes":{"type":"array","items":{"type":"object","properties":{"probe_id":{"type":"string","description":"The opaque probe id (shuffled order — reveals nothing)."},"input":{"type":"string","description":"The task input (verbatim from the supplied item)."},"output":{"type":"string","description":"The probe output to judge (a planted failure OR a valid alternative)."}},"required":["probe_id","input","output"],"description":"One planted-failure-check probe (its planted/control truth is hidden)."}},"created_at":{"type":"string"}},"required":["object","id","verdict_source","call_type_id","golden_set_id","status","probe_count","probes","created_at"],"description":"An issued planted-failure check — the probes are returned ONCE and never stored."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/source-checks/{id}/verdicts":{"post":{"operationId":"gradeVerdictSourceCheck","tags":["Flywheel"],"summary":"Answer a planted-failure check — graded once into the qualification ledger","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The verdict source reports `resolved_true` / `resolved_false` for EVERY probe exactly once. PASS needs recall ≥ 0.8 on the planted failures AND specificity ≥ 0.9 on the valid alternatives (the evaluator-qualification bars) — an auto-close source that says success to everything FAILS. A pass qualifies the source (its task verdicts recorded FROM NOW ON count — never retro-qualified) or clears its review flag; a fail REVOKES it. Graded once into an append-only, versioned ledger. Only the SAME credential that issued the check may answer it (another source ⇒ 404); a missing / duplicate / unknown probe is a 400 and records nothing; a second grade is a 409. Auth: an api key with `outcomes:write`, OR a session + `flywheel.write`. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"verdicts":{"type":"array","items":{"type":"object","properties":{"probe_id":{"type":"string","minLength":1,"maxLength":64},"kind":{"type":"string","enum":["resolved_true","resolved_false"],"description":"`resolved_true` = the probe output meets the objective; `resolved_false` = it fails it."}},"required":["probe_id","kind"],"additionalProperties":false,"description":"The source’s verdict on one probe (the outcome-event resolution vocabulary, binary)."},"minItems":1,"maxItems":100,"description":"Exactly ONE verdict per probe. A missing, duplicate or unknown probe is a 400 and records NOTHING."}},"required":["verdicts"],"additionalProperties":false,"description":"The source’s verdicts on a planted-failure check."}}}},"responses":{"200":{"description":"The graded check (passed | failed) and the source’s qualification after it.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verdict_source_check_result"]},"check_id":{"type":"string"},"verdict_source":{"type":"string"},"result":{"type":"string","enum":["passed","failed"],"description":"`passed` qualifies (or clears) the source; `failed` REVOKES its qualification."},"qualified":{"type":"boolean","description":"Whether the source is qualified AFTER this grade."},"recall":{"type":"object","properties":{"applicable":{"type":"integer","minimum":0},"hits":{"type":"integer","minimum":0},"value":{"type":"number"},"bar":{"type":"number"},"min_applicable":{"type":"integer","minimum":0},"pass":{"type":"boolean"}},"required":["applicable","hits","value","bar","min_applicable","pass"],"description":"Planted failures reported `resolved_false` (bar = the per-family recall bar 0.8)."},"specificity":{"type":"object","properties":{"applicable":{"type":"integer","minimum":0},"hits":{"type":"integer","minimum":0},"value":{"type":"number"},"bar":{"type":"number"},"min_applicable":{"type":"integer","minimum":0},"pass":{"type":"boolean"}},"required":["applicable","hits","value","bar","min_applicable","pass"],"description":"Valid alternatives reported `resolved_true` (bar = the specificity bar 0.9)."},"per_family":{"type":"array","items":{"type":"object","properties":{"family":{"type":"string"},"planted":{"type":"integer","minimum":0},"caught":{"type":"integer","minimum":0}},"required":["family","planted","caught"]},"description":"Recall per planted-failure family (diagnostic)."},"errors":{"type":"array","items":{"type":"string"},"description":"Machine-readable reasons a check did not pass."},"graded_at":{"type":"string"}},"required":["object","check_id","verdict_source","result","qualified","recall","specificity","per_family","errors","graded_at"],"description":"A graded planted-failure check — an append-only, versioned qualification event."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/sources":{"get":{"operationId":"listVerdictSources","tags":["Flywheel"],"summary":"Verdict-source health — who may count toward readiness, and why not","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Every verdict source of the workspace (the producers of artifact-level resolutions + every source with a check) with: `eligible` + the NAMED `reason` (`not_qualified` | `review_flag` | `eligible` | `revoked`), the qualified period and last clearance, the review flag over the outcomes since the last clearance (≥ 99 % success over ≥ 200 outcomes ⇒ held until a re-run check or a 40-task blind audit), `admitted_until` (history a passed ADMISSION audit vouches for — an import batch `import:<import_id>` is its own source) and `revoked` (the credential was deleted — terminal), how many of its task verdicts count NOW (the SAME rule the readiness count applies), and its latest check / clearance audit / admission audit. Read-only. Auth: an api key with `config:read`, OR a session + `flywheel.read` RBAC. NEVER a body. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"The workspace id (session path; or the X-UR-Workspace header)."},"required":false,"description":"The workspace id (session path; or the X-UR-Workspace header).","name":"workspace_id","in":"query"}],"responses":{"200":{"description":"The workspace’s verdict sources and their health.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"data":{"type":"array","items":{"type":"object","properties":{"verdict_source":{"type":"string"},"eligible":{"type":"boolean","description":"Whether this source’s NEW task verdicts count toward readiness now."},"reason":{"type":"string","enum":["eligible","not_qualified","review_flag","revoked"],"description":"`not_qualified` = no passed planted-failure check (or a failed one revoked it); `review_flag` = ≥ 99 % success over ≥ 200 task outcomes since the last clearance (held, not rejected — clear it with a re-run check or a 40-task blind audit); `revoked` = the source’s credential was deleted (terminal — none of its verdicts count any more)."},"revoked":{"type":"boolean","description":"The source’s credential was deleted — terminal."},"qualified":{"type":"boolean"},"qualified_since":{"type":"string","nullable":true,"description":"When the current qualified period began."},"last_clearance_at":{"type":"string","nullable":true,"description":"The newest verdict time a passed check or blind audit vouches for."},"admitted_until":{"type":"string","nullable":true,"description":"The newest verdict time a passed ADMISSION audit vouches for — verdicts recorded at or before it count (retrospective only); null when no admission passed."},"review_flag":{"type":"object","properties":{"outcomes":{"type":"integer","minimum":0},"success_rate":{"type":"number","nullable":true},"flagged":{"type":"boolean"},"min_outcomes":{"type":"integer"},"success_rate_bar":{"type":"number"}},"required":["outcomes","success_rate","flagged","min_outcomes","success_rate_bar"],"description":"The review flag over the task outcomes recorded since the last clearance."},"task_verdicts":{"type":"integer","minimum":0,"description":"Resolved task verdicts this source reported (one per artifact)."},"eligible_task_verdicts":{"type":"integer","minimum":0,"description":"Of those, how many count toward readiness now (the SAME rule the readiness count applies)."},"last_check":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"result":{"type":"string","enum":["passed","failed"]},"at":{"type":"string"},"metrics":{"type":"object","additionalProperties":{"nullable":true},"description":"The graded metrics (never a body)."}},"required":["id","result","at","metrics"],"description":"The latest graded check or audit of a verdict source."},"last_audit":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"result":{"type":"string","enum":["passed","failed"]},"at":{"type":"string"},"metrics":{"type":"object","additionalProperties":{"nullable":true},"description":"The graded metrics (never a body)."}},"required":["id","result","at","metrics"],"description":"The latest graded CLEARANCE audit."},"last_admission":{"type":"object","nullable":true,"properties":{"id":{"type":"string"},"result":{"type":"string","enum":["passed","failed"]},"at":{"type":"string"},"metrics":{"type":"object","additionalProperties":{"nullable":true},"description":"The graded metrics (never a body)."}},"required":["id","result","at","metrics"],"description":"The latest graded ADMISSION audit."}},"required":["verdict_source","eligible","reason","revoked","qualified","qualified_since","last_clearance_at","admitted_until","review_flag","task_verdicts","eligible_task_verdicts","last_check","last_audit","last_admission"],"description":"One verdict source’s health."}}},"required":["object","data"],"description":"The workspace’s verdict sources and their health."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/source-audits":{"post":{"operationId":"openVerdictSourceAudit","tags":["Flywheel"],"summary":"Open a 40-task BLIND audit of a verdict source","security":[{"sessionCookie":[]}],"description":"Samples 40 INDEPENDENT tasks (distinct artifacts, deterministic) from ONE population of the source’s resolved task verdicts and returns their ids WITHOUT the source’s verdicts. `purpose: clearance` (default) — the human alternative to a re-run check for clearing a review flag: the post-clearance window of a QUALIFIED source. `purpose: admission` — history a check can never reach: an import batch (`import:<import_id>`, one source per batch) or a live source’s verdicts recorded before its qualified period; a pass admits EXACTLY that population (never verdicts recorded later, never another batch). Label each task BLIND through the outcome API (`POST /v1/artifacts/{id}/outcomes`, a `resolution` event) — then grade. SESSION + `flywheel.write` RBAC only (an audit is human adjudication — never an api key). Refuses (named): the auditor is the source (400), a clearance on an unqualified source (409), a revoked source (409), fewer than 40 tasks (409).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"verdict_source":{"type":"string","minLength":1,"maxLength":256,"description":"The verdict source to audit (as listed by `GET /v1/flywheel/sources`); never the auditor."},"purpose":{"type":"string","enum":["clearance","admission"],"description":"`clearance` (default) = the review-flag audit of a QUALIFIED source’s post-clearance window. `admission` = a retrospective admission of the history a check can never reach — an import batch (`import:<import_id>`) or a live source’s verdicts recorded before its qualified period; a pass admits exactly the sampled population (never verdicts recorded later)."}},"required":["verdict_source"],"additionalProperties":false,"description":"Open a blind audit of a verdict source."}}}},"responses":{"201":{"description":"The opened audit — the 40 sampled task ids only.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verdict_source_audit"]},"id":{"type":"string","description":"The audit id (`vsa_…`)."},"verdict_source":{"type":"string"},"auditor":{"type":"string","description":"The auditor’s server-assigned producer (a session)."},"purpose":{"type":"string","enum":["clearance","admission"],"description":"`clearance` (default) = the review-flag audit of a QUALIFIED source’s post-clearance window. `admission` = a retrospective admission of the history a check can never reach — an import batch (`import:<import_id>`) or a live source’s verdicts recorded before its qualified period; a pass admits exactly the sampled population (never verdicts recorded later)."},"population_until":{"type":"string","description":"The newest verdict time the sampled population holds (an admission admits verdicts up to it)."},"sample_size":{"type":"integer","minimum":0},"tasks":{"type":"array","items":{"type":"object","properties":{"artifact_id":{"type":"string"},"artifact_key":{"type":"string"}},"required":["artifact_id","artifact_key"]},"description":"The 40 independent tasks to label BLIND — record each label with `POST /v1/artifacts/{id}/outcomes` (a `resolution` event) AFTER this audit opened."},"opened_at":{"type":"string"}},"required":["object","id","verdict_source","auditor","purpose","population_until","sample_size","tasks","opened_at"],"description":"An opened blind audit — ids only; the source’s verdicts are never shown."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/source-audits/{id}/grade":{"post":{"operationId":"gradeVerdictSourceAudit","tags":["Flywheel"],"summary":"Grade a blind audit from the labels recorded through the outcome API (never a one-click accept)","security":[{"sessionCookie":[]}],"description":"Compares, per sampled task, the source’s verdict (up to the sampled population’s bound) with the auditor’s label recorded through the outcome API AFTER the audit opened (an earlier label is not blind and never grades it). ZERO mislabels over ≥ 40 tasks ⇒ `passed` (the Wilson 95 % upper bound on the source’s error rate is ≈ 8.76 %): a clearance clears the review flag; an admission admits the sampled population (`admitted_until`). One mislabel ⇒ `failed` (nothing changes). An unlabelled task ⇒ 400 `audit_incomplete`, nothing recorded — there is no accept button. Only the auditor who opened it may grade it; a second grade is a 409; a revoked source is a 409. The body is EMPTY and STRICT — an `accept` / override field is a 400. SESSION + `flywheel.write` RBAC only.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"description":"Grade a blind audit — no fields: the labels recorded as outcome events are the only input."}}}},"responses":{"200":{"description":"The graded audit and the source’s eligibility after it.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["verdict_source_audit_result"]},"audit_id":{"type":"string"},"verdict_source":{"type":"string"},"purpose":{"type":"string","enum":["clearance","admission"],"description":"`clearance` (default) = the review-flag audit of a QUALIFIED source’s post-clearance window. `admission` = a retrospective admission of the history a check can never reach — an import batch (`import:<import_id>`) or a live source’s verdicts recorded before its qualified period; a pass admits exactly the sampled population (never verdicts recorded later)."},"result":{"type":"string","enum":["passed","failed"],"description":"`passed` = zero mislabels over ≥ 40 tasks ⇒ a clearance clears the review flag; an admission admits the sampled population."},"tasks":{"type":"integer","minimum":0},"mislabels":{"type":"integer","minimum":0},"error_rate_upper":{"type":"number","description":"The Wilson 95 % upper bound on the source’s error rate (0/40 ⇒ ≈ 0.0876)."},"max_mislabels":{"type":"integer","minimum":0},"eligible":{"type":"boolean","description":"Whether the source’s NEW task verdicts count AFTER this grade."},"reason":{"type":"string","enum":["eligible","not_qualified","review_flag","revoked"],"description":"`not_qualified` = no passed planted-failure check (or a failed one revoked it); `review_flag` = ≥ 99 % success over ≥ 200 task outcomes since the last clearance (held, not rejected — clear it with a re-run check or a 40-task blind audit); `revoked` = the source’s credential was deleted (terminal — none of its verdicts count any more)."},"admitted_until":{"type":"string","nullable":true,"description":"The newest verdict time an admission vouches for after this grade."},"errors":{"type":"array","items":{"type":"string"}},"graded_at":{"type":"string"}},"required":["object","audit_id","verdict_source","purpose","result","tasks","mislabels","error_rate_upper","max_mislabels","eligible","reason","admitted_until","errors","graded_at"],"description":"A graded blind audit — an append-only, versioned qualification event."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles":{"post":{"operationId":"registerOracle","tags":["Flywheel"],"summary":"Register a check (an oracle) — or append a new version of one","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"A CHECK that can tell a right answer from a wrong one (a system that can PRODUCE the right answer sends a declared correction instead). Platform kinds (`label_set`, `schema_rules`) run in-process; a PUSH endpoint (`test_endpoint`, push `reconciliation`) is called by the platform through the SSRF egress guard (https, pinned IP, 64 KB, 10 s, JSON only, ≤ 2 re-validated redirects — validated here AND on every call); a PULL transport (`customer_ci`, pull `reconciliation`) is claimed by your worker / CI. The VERSION is the content hash of the canonical definition: the same spec is an idempotent no-op (200), a new spec appends a version (201) that supersedes the old one (its receipts stop admitting; a push / pull new version cancels the old version’s open jobs). A new push / pull oracle gets ONE HMAC signing secret, returned ONCE (`secret`; the audit keeps its last 4). The role (detector / certifier) is EARNED by qualification, never declared. Auth: platform kinds — an api key with `config:write`, OR a session + `config.write` RBAC; push / pull — a SESSION + the owner/admin `flywheel.oracle` RBAC ONLY (an egress target / a signing credential is a human decision, like `custom_provider.create`). Refusals: `invalid_spec` / `egress_blocked` (400), `oracle_not_found` (404), `oracle_revoked` / `kind_changed` (409). Requires API-key scope: config:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"oracle_id":{"type":"string","minLength":1,"maxLength":64,"description":"Append a new VERSION of this workspace’s existing oracle (same kind + transport). Absent ⇒ a new `orc_` id."},"kind":{"type":"string","enum":["label_set","schema_rules","test_endpoint","reconciliation","customer_ci"],"description":"`label_set` / `schema_rules` = platform checks (in-process, no egress); `test_endpoint` = a PUSH endpoint; `reconciliation` = push or pull; `customer_ci` = a PULL harness."},"transport":{"type":"string","enum":["platform","push","pull"],"description":"Default: the kind’s first transport."},"spec":{"type":"object","additionalProperties":{"nullable":true},"description":"The check definition (strict — an unknown key is refused). `label_set`: `{labels[], field?, case_insensitive?}`. `schema_rules`: `{schema, rules[]}` (rules over `equals | within_tolerance | ge | le`). Push (`test_endpoint` / push `reconciliation`): `{url, contract_version}` — the URL must pass the SSRF egress guard (https; never a private / metadata / link-local host). Pull `reconciliation`: `{contract_version}`. `customer_ci`: `{harness_identity}`. The VERSION is the sha256 of the canonical definition: a new spec is a new version (its qualification starts from nothing)."}},"required":["kind","spec"],"additionalProperties":false,"description":"Register a check (a platform-evaluated kind, or a push / pull check you host)."}}}},"responses":{"201":{"description":"The registered version (200 on an idempotent replay).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_registration"]},"oracle_id":{"type":"string","description":"The platform-minted `orc_…` id (a receipt’s verifier id)."},"version_id":{"type":"string"},"version_hash":{"type":"string","description":"The content hash of the canonical definition."},"kind":{"type":"string","enum":["label_set","schema_rules","test_endpoint","reconciliation","customer_ci"],"description":"`label_set` / `schema_rules` = platform checks (in-process, no egress); `test_endpoint` = a PUSH endpoint; `reconciliation` = push or pull; `customer_ci` = a PULL harness."},"transport":{"type":"string","enum":["platform","push","pull"],"description":"`platform` = evaluated in-process; `push` = the platform POSTs each job to your HTTPS endpoint (SSRF-guarded); `pull` = your worker / CI claims jobs and posts signed verdicts."},"inserted":{"type":"boolean","description":"False when the spec equals the current version (a no-op)."},"superseded_version_hash":{"type":"string","nullable":true,"description":"The version this one superseded (its receipts stop admitting), or null."},"source":{"type":"string","description":"The verdict source the version is qualified as: `oracle:<id>@<version>`."},"secret":{"type":"string","nullable":true,"description":"The push / pull HMAC SIGNING SECRET — returned exactly ONCE, when a new push / pull oracle is registered (null otherwise). Store it now: it is never shown again (rotate it with `…/rotate-secret`)."},"secret_last4":{"type":"string","nullable":true,"description":"The last 4 characters of a newly minted secret."},"cancelled_jobs":{"type":"integer","minimum":0,"description":"Open jobs of a superseded version this registration cancelled."}},"required":["object","oracle_id","version_id","version_hash","kind","transport","inserted","superseded_version_hash","source","secret","secret_last4","cancelled_jobs"],"description":"A registered oracle version."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}":{"get":{"operationId":"getOracle","tags":["Flywheel"],"summary":"Read an oracle, the role its current version earned, and its transport state","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The current version + every version, the verdict source `oracle:<id>@<version>`, whether it was revoked, and the role reduced from the tenant qualification ledger (a canary false pass or any observed false pass means the version can never certify again — a fixed check is a new version). Push / pull checks add the transport state: the secret’s LAST 4 (never the secret), the canary pool, job counts by status, the latest qualification’s progress and the RESOLVED canary outcomes. Auth: an api key with `config:read`, OR a session + `flywheel.read` RBAC. Another workspace’s oracle is a 404. Requires API-key scope: config:read.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The oracle.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["oracle"]},"oracle_id":{"type":"string"},"kind":{"type":"string","enum":["label_set","schema_rules","test_endpoint","reconciliation","customer_ci"],"description":"`label_set` / `schema_rules` = platform checks (in-process, no egress); `test_endpoint` = a PUSH endpoint; `reconciliation` = push or pull; `customer_ci` = a PULL harness."},"transport":{"type":"string","enum":["platform","push","pull"],"description":"`platform` = evaluated in-process; `push` = the platform POSTs each job to your HTTPS endpoint (SSRF-guarded); `pull` = your worker / CI claims jobs and posts signed verdicts."},"current":{"type":"object","properties":{"version_id":{"type":"string"},"version_hash":{"type":"string"},"spec":{"nullable":true,"description":"The canonical spec (configuration — never a secret)."},"created_by":{"type":"string"},"created_at":{"type":"string"}},"required":["version_id","version_hash","created_by","created_at"]},"versions":{"type":"array","items":{"type":"object","properties":{"version_id":{"type":"string"},"version_hash":{"type":"string"},"created_at":{"type":"string"}},"required":["version_id","version_hash","created_at"]}},"source":{"type":"string"},"revoked":{"type":"boolean"},"role":{"type":"object","properties":{"role":{"type":"string","nullable":true,"enum":["detector","certifier"],"description":"`detector` = the source-health bars (planted recall ≥ 0.8, control specificity ≥ 0.9); `certifier` = those bars + ZERO false passes over ≥ 73 planted probes (Wilson 95 % upper ≤ 5 %) and no false pass ever observed on this version; null = not qualified (or revoked / failed / a canary false pass)."},"reason":{"type":"string","enum":["certifier","detector","not_qualified","revoked"]},"certifier_refusal":{"type":"string","nullable":true,"enum":["false_pass_observed","not_certified"]},"false_passes_observed":{"type":"integer","minimum":0},"measurements":{"type":"integer","minimum":0},"qualified":{"type":"boolean"}},"required":["role","reason","certifier_refusal","false_passes_observed","measurements","qualified"]},"transport_state":{"type":"object","nullable":true,"properties":{"secret_last4":{"type":"string"},"secret_rotated_at":{"type":"string","nullable":true},"canary_pool":{"type":"object","properties":{"examples":{"type":"integer","minimum":0},"stored_at":{"type":"string","nullable":true},"available":{"type":"boolean"}},"required":["examples","stored_at","available"]},"jobs":{"type":"object","properties":{"pending":{"type":"integer","minimum":0},"claimed":{"type":"integer","minimum":0},"answered":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0},"cancelled":{"type":"integer","minimum":0},"lapsed_leases":{"type":"integer","minimum":0}},"required":["pending","claimed","answered","failed","cancelled","lapsed_leases"]},"qualification":{"type":"object","nullable":true,"properties":{"check_id":{"type":"string"},"total":{"type":"integer","minimum":0},"answered":{"type":"integer","minimum":0},"open":{"type":"integer","minimum":0},"dead":{"type":"integer","minimum":0}},"required":["check_id","total","answered","open","dead"]},"canaries":{"type":"object","properties":{"caught":{"type":"integer","minimum":0},"false_passes":{"type":"integer","minimum":0},"unanswered":{"type":"integer","minimum":0}},"required":["caught","false_passes","unanswered"],"description":"RESOLVED canary outcomes only."}},"required":["secret_last4","secret_rotated_at","canary_pool","jobs","qualification","canaries"],"description":"Push / pull only (null for a platform check). Never a secret, a salt or a body."}},"required":["object","oracle_id","kind","transport","current","versions","source","revoked","role","transport_state"],"description":"An oracle and the role its current version earned."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}/test":{"post":{"operationId":"testOracle","tags":["Flywheel"],"summary":"Send test — prove a check end to end (nothing is graded)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"A platform check evaluates `probe` (or the synthetic probe) in-process. A PUSH check is called at once with the platform’s SYNTHETIC probe (never customer content) and the response returns the EXACT job payload sent + the verdict or a closed transport-error code (`egress_blocked`, `timeout`, `too_large`, `content_type`, `http_status`, `missing_signature`, `invalid_signature`, `version_mismatch`, …). A PULL check queues the synthetic job (`pending`) — claim + answer it like any job. Logged as a `test` run; never graded, never a canary. Auth: platform — an api key with `config:write` OR a session + `config.write`; push / pull — a session + `flywheel.oracle`. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"probe":{"type":"object","properties":{"input":{"type":"string","maxLength":16000},"output":{"type":"string","maxLength":16000}},"required":["input","output"],"additionalProperties":false,"description":"PLATFORM checks only: the probe to evaluate in-process (default: the synthetic test probe). A push / pull test always carries the platform’s synthetic probe (400 `test_probe_not_allowed` otherwise)."}},"additionalProperties":false,"description":"Send test — prove the check end to end; nothing is graded."}}}},"responses":{"200":{"description":"The test result.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_test"]},"oracle_id":{"type":"string"},"version_hash":{"type":"string"},"transport":{"type":"string","enum":["platform","push","pull"],"description":"`platform` = evaluated in-process; `push` = the platform POSTs each job to your HTTPS endpoint (SSRF-guarded); `pull` = your worker / CI claims jobs and posts signed verdicts."},"status":{"type":"string","enum":["answered","error","pending"],"description":"`pending` = a pull test job awaits your worker (claim + answer it like any job)."},"job_id":{"type":"string","nullable":true},"request":{"type":"object","nullable":true,"properties":{"url":{"type":"string","nullable":true},"body":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_job"]},"schema":{"type":"string","enum":["ur.oracle.v1"]},"job_id":{"type":"string","description":"The server-issued job id your verdict must echo."},"oracle_id":{"type":"string"},"oracle_version":{"type":"string","description":"The oracle version your verdict must ECHO (a mismatch is refused)."},"input":{"type":"string","description":"The task input."},"output":{"type":"string","description":"The candidate output to judge."},"candidate_sha256":{"type":"string","description":"sha256 of `output` — your verdict must echo it (binds the verdict to this candidate)."},"due_at":{"type":"string"},"issued_at":{"type":"string"}},"required":["object","schema","job_id","oracle_id","oracle_version","input","output","candidate_sha256","due_at","issued_at"],"description":"One oracle job (the push request body / a pull claim entry)."}},"required":["url","body"],"description":"The EXACT job payload sent (push) / queued (pull) — the synthetic probe; null in-process."},"verdict":{"type":"string","nullable":true,"enum":["pass","fail"],"description":"`pass` = the candidate is right; `fail` = it is wrong. An error is never a pass."},"reasons":{"type":"array","items":{"type":"string"}},"error":{"type":"string","nullable":true,"description":"A closed transport-error code when the call failed."},"latency_ms":{"type":"integer","nullable":true,"minimum":0}},"required":["object","oracle_id","version_hash","transport","status","job_id","request","verdict","reasons","error","latency_ms"],"description":"A send-test result (logged as a `test` run; never graded)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}/qualify":{"post":{"operationId":"qualifyOracle","tags":["Flywheel"],"summary":"Qualify the current version — the role is EARNED against planted failures","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"From your ≥ 10 distinct known-good examples the platform plants TWO failures (omission / wrong value / truncation / instruction loss) + ONE valid rewrite per example, homogenized and shuffled, and your check judges every probe: DETECTOR = planted recall ≥ 0.8 AND control specificity ≥ 0.9; CERTIFIER = those bars + ZERO false passes over ≥ 73 planted probes. A platform check is graded in-process. A PUSH check receives every probe as an ORDINARY job (indistinguishable) and is graded when the last is answered (`incomplete` if any call errored — an error is never a pass). A PULL check’s probes wait for your worker (`pending`; graded when the last verdict arrives). Push / pull probes and the canary pool are stored as customer content: they need corrections consent AND full retention (409 `no_consent`). One graded event per qualification in the tenant ledger; a false pass is never erased. Auth: platform — an api key with `config:write` OR a session + `config.write`; push / pull — a session + `flywheel.oracle`. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"examples":{"type":"array","items":{"type":"object","properties":{"input":{"type":"string","maxLength":16000},"output":{"type":"string","minLength":1,"maxLength":16000}},"required":["input","output"],"additionalProperties":false,"description":"A known-good example: the platform plants failures into it and keeps it as a control."},"minItems":1,"maxItems":200,"description":"≥ 10 DISTINCT known-good examples (duplicates collapse; ≤ 50 are used). Each yields TWO planted failures (omission / wrong value / truncation / instruction loss) and ONE valid rewrite. The certifier bar needs ≥ 73 planted probes, so ≥ 37 distinct examples."}},"required":["examples"],"additionalProperties":false,"description":"Qualify an oracle (the role is EARNED in the tenant ledger)."}}}},"responses":{"200":{"description":"The qualification (graded, pending or incomplete).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_qualification"]},"oracle_id":{"type":"string"},"version_hash":{"type":"string"},"source":{"type":"string"},"transport":{"type":"string","enum":["platform","push","pull"],"description":"`platform` = evaluated in-process; `push` = the platform POSTs each job to your HTTPS endpoint (SSRF-guarded); `pull` = your worker / CI claims jobs and posts signed verdicts."},"status":{"type":"string","enum":["graded","pending","incomplete"],"description":"`graded` = one ledger event recorded; `pending` = pull probes await your worker (graded when the last is answered); `incomplete` = a push probe errored (timeout / refusal / bad signature …) — nothing recorded, fix the endpoint and qualify again (an error is never a pass)."},"check_id":{"type":"string"},"result":{"type":"string","nullable":true,"enum":["passed","failed"]},"bar":{"type":"string","nullable":true,"enum":["source_health","certifier"]},"role":{"type":"string","nullable":true,"enum":["detector","certifier"],"description":"`detector` = the source-health bars (planted recall ≥ 0.8, control specificity ≥ 0.9); `certifier` = those bars + ZERO false passes over ≥ 73 planted probes (Wilson 95 % upper ≤ 5 %) and no false pass ever observed on this version; null = not qualified (or revoked / failed / a canary false pass)."},"planted":{"type":"integer","minimum":0},"controls":{"type":"integer","minimum":0},"examples":{"type":"object","properties":{"supplied":{"type":"integer","minimum":0},"used":{"type":"integer","minimum":0},"skipped":{"type":"object","additionalProperties":{"type":"integer","minimum":0}}},"required":["supplied","used","skipped"]},"jobs":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"answered":{"type":"integer","minimum":0},"open":{"type":"integer","minimum":0},"failed":{"type":"integer","minimum":0}},"required":["total","answered","open","failed"],"description":"The probe jobs (a platform qualification has none — all zero)."},"delivery_errors":{"type":"object","additionalProperties":{"type":"integer","minimum":0},"description":"Push only: failed deliveries by closed transport-error code."},"detector":{"type":"object","nullable":true,"properties":{"recall":{"type":"number"},"specificity":{"type":"number"}},"required":["recall","specificity"],"description":"The source-health detector bars (null until graded)."},"certifier":{"type":"object","nullable":true,"properties":{"pass":{"type":"boolean"},"planted":{"type":"integer","minimum":0},"false_passes":{"type":"integer","minimum":0},"false_pass_upper":{"type":"number"},"errors":{"type":"array","items":{"type":"string"}}},"required":["pass","planted","false_passes","false_pass_upper","errors"],"description":"The certifier bar (null until graded)."}},"required":["object","oracle_id","version_hash","source","transport","status","check_id","result","bar","role","planted","controls","examples","jobs","delivery_errors","detector","certifier"],"description":"An oracle qualification."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}/revoke":{"post":{"operationId":"revokeOracle","tags":["Flywheel"],"summary":"Revoke an oracle (terminal) — every receipt of every version stops admitting","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Appends the terminal `source_revoked` for every version (idempotent), cancels every open push / pull job and drops the canary pool (the bodies are deleted). The oracle registers no new version and is never qualified again. The body is EMPTY and STRICT. Auth: platform — an api key with `config:write` OR a session + `config.write`; push / pull — a session + `flywheel.oracle`. Requires API-key scope: config:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"description":"Revoke an oracle (terminal) — no fields."}}}},"responses":{"200":{"description":"The revocation.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_revocation"]},"oracle_id":{"type":"string"},"revoked_sources":{"type":"array","items":{"type":"string"},"description":"The version sources newly revoked."},"already_revoked":{"type":"boolean"},"cancelled_jobs":{"type":"integer","minimum":0}},"required":["object","oracle_id","revoked_sources","already_revoked","cancelled_jobs"],"description":"A revoked oracle: every receipt of every version stops admitting; open jobs are cancelled."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}/rotate-secret":{"post":{"operationId":"rotateOracleSecret","tags":["Flywheel"],"summary":"Rotate a push / pull oracle’s HMAC signing secret (returned once)","security":[{"sessionCookie":[]}],"description":"A fresh secret sealed by the workspace key (envelope encryption), returned exactly ONCE; the old secret stops verifying immediately (the workspace `config_version` is bumped). The audit keeps the last 4 of the new and the old secret only. A platform check has no secret (409 `transport_mismatch`). The body is EMPTY and STRICT. SESSION + `flywheel.oracle` RBAC only.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"description":"Rotate a push / pull oracle’s signing secret — no fields."}}}},"responses":{"200":{"description":"The new secret (once).","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_secret"]},"oracle_id":{"type":"string"},"secret":{"type":"string","description":"The NEW signing secret — returned exactly ONCE; the old one stops verifying now."},"secret_last4":{"type":"string"},"rotated_at":{"type":"string"}},"required":["object","oracle_id","secret","secret_last4","rotated_at"],"description":"A rotated oracle signing secret."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}/jobs/claim":{"post":{"operationId":"claimOracleJobs","tags":["Flywheel"],"summary":"PULL transport — lease due jobs (each payload returned once)","security":[{"bearerAuth":[]}],"description":"Your worker / CI leases up to `max` due jobs for `lease_seconds`. Each payload (the task input + the candidate to judge) is returned in THIS response exactly once and then deleted; a qualification probe, a canary and an ordinary job look the same. The request is SIGNED with the oracle secret: `x-ur-oracle-signature: sha256=<hex HMAC of \"<x-ur-oracle-timestamp>.<raw body>\">` + `x-ur-oracle-timestamp` (unix seconds, ±15 min) — a missing / stale / wrong signature is a 403 naming the reason. Auth: an api key with `outcomes:write` AND `logs:read` (the jobs carry stored content) + the signature. Refusals: `oracle_not_found` (404), `oracle_revoked` / `transport_mismatch` (409). Requires API-key scope: outcomes:write or logs:read.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"max":{"type":"integer","minimum":1,"maximum":50,"description":"At most this many jobs (default 10)."},"lease_seconds":{"type":"integer","minimum":30,"maximum":3600,"description":"The lease (default 900 s): a verdict after it is refused `lease_expired`."}},"additionalProperties":false,"description":"Claim pull jobs."}}}},"responses":{"200":{"description":"The leased jobs.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"oracle_id":{"type":"string"},"lease_until":{"type":"string"},"unavailable":{"type":"integer","minimum":0,"description":"Due jobs whose payload was already swept (failed `payload_unavailable`)."},"data":{"type":"array","items":{"type":"object","properties":{"object":{"type":"string","enum":["oracle_job"]},"schema":{"type":"string","enum":["ur.oracle.v1"]},"job_id":{"type":"string","description":"The server-issued job id your verdict must echo."},"oracle_id":{"type":"string"},"oracle_version":{"type":"string","description":"The oracle version your verdict must ECHO (a mismatch is refused)."},"input":{"type":"string","description":"The task input."},"output":{"type":"string","description":"The candidate output to judge."},"candidate_sha256":{"type":"string","description":"sha256 of `output` — your verdict must echo it (binds the verdict to this candidate)."},"due_at":{"type":"string"},"issued_at":{"type":"string"}},"required":["object","schema","job_id","oracle_id","oracle_version","input","output","candidate_sha256","due_at","issued_at"],"description":"One oracle job (the push request body / a pull claim entry)."}}},"required":["object","oracle_id","lease_until","unavailable","data"],"description":"Claimed jobs — the payloads are returned ONCE and deleted; judge each and post a verdict."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/oracles/{id}/verdicts":{"post":{"operationId":"submitOracleVerdicts","tags":["Flywheel"],"summary":"PULL transport — post signed verdicts (idempotent per job)","security":[{"bearerAuth":[]}],"description":"One verdict per claimed job, bound to the SERVER-ISSUED job: it must echo the `job_id`, the `oracle_version` the job was issued under and the `candidate_sha256` it carried (a mismatch is refused by name, never recorded as an answer). SIGNED like the claim (a forged MAC is a 403). Per verdict: `accepted`; `duplicate` (the SAME verdict again — a visible no-op, forever); `conflict` (another answer for an answered job — never overwritten); `refused` with `job_not_found` | `job_not_claimed` | `job_closed` | `lease_expired` | `version_mismatch` | `candidate_mismatch` | `malformed_reply`. When nothing is accepted or duplicate the post is a 409 naming the first refusal. A canary answered `pass` is a FALSE PASS: the version gets `check_failed` and every receipt of it stops admitting. A qualification is graded when its last probe is answered. Auth: an api key with `outcomes:write` + the signature. No verdict ever writes a receipt. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"verdicts":{"type":"array","items":{"type":"object","properties":{"job_id":{"type":"string","minLength":1,"maxLength":64},"oracle_version":{"type":"string","minLength":1,"maxLength":128},"candidate_sha256":{"type":"string","minLength":1,"maxLength":128},"verdict":{"type":"string","enum":["pass","fail"],"description":"`pass` = the candidate is right; `fail` = it is wrong. An error is never a pass."},"reasons":{"type":"array","items":{"type":"string","enum":["wrong_value","missing_field","extra_field","format_invalid","schema_invalid","rule_failed","execution_failed","truncated","off_task","mismatch","other"],"description":"A closed diagnostic code — never free text, never a body."},"maxItems":8,"description":"Closed reason codes for a `fail` (a `pass` carries none)."}},"required":["job_id","oracle_version","candidate_sha256","verdict"],"additionalProperties":false,"description":"One verdict, bound to its server-issued job (id + echoed version + candidate hash)."},"minItems":1,"maxItems":100}},"required":["verdicts"],"additionalProperties":false,"description":"Post verdicts for claimed jobs."}}}},"responses":{"200":{"description":"The per-verdict results.","content":{"application/json":{"schema":{"type":"object","properties":{"object":{"type":"string","enum":["list"]},"oracle_id":{"type":"string"},"data":{"type":"array","items":{"type":"object","properties":{"job_id":{"type":"string"},"status":{"type":"string","enum":["accepted","duplicate","conflict","refused"]},"reason":{"type":"string","nullable":true,"description":"The NAMED refusal: `job_not_found` | `job_not_claimed` | `job_closed` | `lease_expired` | `version_mismatch` | `candidate_mismatch` | `malformed_reply` | `conflict`."}},"required":["job_id","status","reason"]}},"accepted":{"type":"integer","minimum":0},"duplicate":{"type":"integer","minimum":0},"conflict":{"type":"integer","minimum":0},"refused":{"type":"integer","minimum":0},"qualification":{"type":"array","items":{"type":"object","properties":{"check_id":{"type":"string"},"result":{"type":"string","enum":["passed","failed"]},"bar":{"type":"string","enum":["source_health","certifier"]},"role":{"type":"string","nullable":true,"enum":["detector","certifier"],"description":"`detector` = the source-health bars (planted recall ≥ 0.8, control specificity ≥ 0.9); `certifier` = those bars + ZERO false passes over ≥ 73 planted probes (Wilson 95 % upper ≤ 5 %) and no false pass ever observed on this version; null = not qualified (or revoked / failed / a canary false pass)."}},"required":["check_id","result","bar","role"]},"description":"Qualification checks this post completed (graded now)."}},"required":["object","oracle_id","data","accepted","duplicate","conflict","refused","qualification"],"description":"The recorded verdicts (a replay of the same verdict is `duplicate` — a visible no-op)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/candidates/{ref}/rollout":{"post":{"operationId":"evaluateCandidateRollout","tags":["Flywheel"],"summary":"Evaluate the controlled-rollout preconditions for a screened candidate (never presses)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"The ONE server-side rollout-gate implementation. The CI run supplies the facts only IT observes (the current bound identity + the application CI gate’s headline); the SERVER decides the unlock from permissions, consent, budget, qualification and the frozen baseline, each REFUSING BY NAME. The response is ALWAYS `pressed: false` — pressing the button (live confirmation + adoption) is a human action in the dashboard, performed there, never by this endpoint. Auth: an api key with `outcomes:write`, OR a session + `flywheel.write`. NEVER a body. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `ref`."},"required":true,"description":"Path parameter `ref`.","name":"ref","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schema":{"type":"string","enum":["ur.flywheel.rollout.request.v1"]},"candidate_ref":{"type":"string"},"candidate_state":{"type":"string"},"observed_identity":{"type":"object","properties":{"repository":{"type":"string"},"baseSha":{"type":"string"},"headSha":{"type":"string"},"lockDigest":{"type":"string"},"harnessHash":{"type":"string"},"configHash":{"type":"string"},"datasetSplit":{"type":"string"},"workflowId":{"type":"string"},"objective":{"type":"string"},"evaluatorVersion":{"type":"string"},"evidenceEpoch":{"type":"string"},"candidateRef":{"type":"string"}},"required":["repository","baseSha","headSha","lockDigest","harnessHash","configHash","datasetSplit","workflowId","objective","evaluatorVersion","evidenceEpoch"],"description":"The bound application-evidence identity (matches the SDK `EvidenceContract`)."},"application_headline":{"type":"string","nullable":true},"requires_repository_write":{"type":"boolean"},"change_shape":{"type":"string"}},"required":["schema","candidate_ref","candidate_state","observed_identity","application_headline","requires_repository_write","change_shape"],"description":"Rollout-gate request: the CI-observed facts the server decides the unlock from."}}}},"responses":{"200":{"description":"The full blocker list + the immutable evidence address. Never pressed.","content":{"application/json":{"schema":{"type":"object","properties":{"unlocked":{"type":"boolean"},"pressed":{"type":"boolean","enum":[false]},"blockers":{"type":"array","items":{"type":"object","properties":{"reason":{"type":"string"},"family":{"type":"string"},"message":{"type":"string"},"detail":{"type":"string"}},"required":["reason","family","message"],"description":"A named rollout precondition failure + the family it belongs to."}},"evidence_hash":{"type":"string"},"candidate_ref":{"type":"string"}},"required":["unlocked","pressed","blockers","evidence_hash","candidate_ref"],"description":"Rollout gate: the full blocker list + the immutable evidence address. Never pressed."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/flywheel/candidates/{ref}/decisions":{"post":{"operationId":"recordCandidateDecision","tags":["Flywheel"],"summary":"Record a human accept/reject/revert of a flywheel candidate (signed, replay-safe)","security":[{"bearerAuth":[]}],"description":"A human accept/reject/revert on a candidate, recorded as an AUDIT event + product feedback (the feedback is HARD-WIRED `learning_use:\"audit\"` — a human’s opinion of a candidate is never an independently-verified learning label). The candidate BODY never travels, only its reference. The request MUST be signed (`X-UR-AppCI-Signature: sha256=<hex>` over `\"<X-UR-AppCI-Timestamp>.<raw body>\"`, keyed by the API key — the reviewer-webhook MAC recipe in a DISTINCT header namespace, so a captured reviewer delivery can never be replayed here) and is replay-safe on the deterministic `callback_id` (a replay is a visible `duplicate` no-op). A missing/stale/invalid signature FAILS CLOSED (403). Api-key only (the signed webhook needs a shared secret). Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `ref`."},"required":true,"description":"Path parameter `ref`.","name":"ref","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"schema":{"type":"string","enum":["ur.appci.callback.v1"]},"kind":{"type":"string","enum":["decision"]},"callback_id":{"type":"string"},"workspace_id":{"type":"string"},"candidate_ref":{"type":"string"},"evidence_hash":{"type":"string"},"decision":{"type":"string","enum":["accept","reject","revert"]},"actor_id":{"type":"string"},"reason":{"type":"string","minLength":1},"surface":{"type":"string","enum":["pull_request","dashboard","cli"]},"decided_at":{"type":"string"}},"required":["schema","kind","callback_id","workspace_id","candidate_ref","evidence_hash","decision","actor_id","reason","surface","decided_at"],"description":"Human decision callback: accept/reject/revert with actor + mandatory reason (audit-only)."}}}},"responses":{"200":{"description":"The decision verdict — accepted, or a visible duplicate (a replay).","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["accepted","duplicate"]},"callback_id":{"type":"string"},"learning_use":{"type":"string","enum":["audit"]}},"required":["status","callback_id","learning_use"],"description":"Decision verdict: accepted or a visible duplicate no-op (a replay). Never a learning label."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/imports":{"post":{"operationId":"createImport","tags":["Flywheel"],"summary":"Import history (usage-only export or intact traces)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Day-1 value without the proxy. Upload a USAGE-ONLY export (model/spend summaries — never a prompt, output, quality figure or replayable case) OR INTACT TRACES (request, response, occurred_at and an optional outcome). `mode=preview` returns the capability report with nothing stored; a commit ingests. Only intact, CONSENTED (corrections_consent), semantically eligible records become redacted capture-equivalent bodies + `exposure_arm=imported` artifacts (never a live-lift contrast). Per-record content-hash idempotency (resume never double-ingests). `call_type_id` names the call type the history belongs to — validated against the workspace’s call types and its CONFIRMED objective (named 404/409/400 refusals, nothing written), pinned on the batch (insert-only) and stamped on every accepted record’s artifact at assembly, so the batch’s task verdicts count toward that call type’s readiness once a blind ADMISSION audit of the batch passes; without it the batch is unbound and never counts. Owner/admin session + `flywheel.import`, OR an api key with `outcomes:write`. No paid analysis is authorized by an upload. Requires API-key scope: outcomes:write.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportRequest"}}}},"responses":{"200":{"description":"The import + capability report (preview or committed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}},"get":{"operationId":"listImports","tags":["Flywheel"],"summary":"List history imports (metadata only)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Keyset-paginated import metadata + capability reports (never OFFSET). Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Page size (1–200, default 50)."},"required":false,"description":"Page size (1–200, default 50).","name":"limit","in":"query"},{"schema":{"type":"string","description":"Opaque keyset cursor from the prior page."},"required":false,"description":"Opaque keyset cursor from the prior page.","name":"cursor","in":"query"}],"responses":{"200":{"description":"A keyset page of imports.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/imports/{id}":{"get":{"operationId":"getImport","tags":["Flywheel"],"summary":"Get a history import (metadata + capability report)","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"One import + its capability report (accepted/duplicate/rejected/unsupported). Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The import (metadata + capability report).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/imports/{id}/cancel":{"post":{"operationId":"cancelImport","tags":["Flywheel"],"summary":"Cancel a non-terminal history import","security":[{"bearerAuth":[]},{"sessionCookie":[]}],"description":"Cancel a `preview`/`running` import (→ `cancelled`). A terminal import is a 409. Cancellation releases nothing to spend (no budgets) and preserves per-record idempotency. Requires API-key scope: outcomes:write.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The cancelled import.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayError"}}}}}}},"/v1/workspaces":{"post":{"operationId":"createWorkspace","tags":["Workspaces"],"summary":"Create a workspace","security":[{"sessionCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"Workspace display name."}},"required":["name"],"description":"Create a workspace."}}}},"responses":{"201":{"description":"The created workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}":{"patch":{"operationId":"renameWorkspace","tags":["Workspaces"],"summary":"Rename a workspace","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"description":"New workspace display name."}},"required":["name"],"description":"Rename a workspace."}}}},"responses":{"200":{"description":"The renamed workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspaceEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteWorkspace","tags":["Workspaces"],"summary":"Soft-delete a workspace","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"Acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/members":{"get":{"operationId":"listMembers","tags":["Members"],"summary":"List workspace members","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The members.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembersListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/members/{userId}":{"patch":{"operationId":"changeMemberRole","tags":["Members"],"summary":"Change a member role","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `userId`."},"required":true,"description":"Path parameter `userId`.","name":"userId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","minLength":1,"description":"The new role (owner|admin|developer|billing|member)."}},"required":["role"],"description":"Change a member role."}}}},"responses":{"200":{"description":"The updated membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"removeMember","tags":["Members"],"summary":"Remove a member","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `userId`."},"required":true,"description":"Path parameter `userId`.","name":"userId","in":"path"}],"responses":{"200":{"description":"Acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/invitations":{"post":{"operationId":"createInvitation","tags":["Invitations"],"summary":"Invite a member","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Invitee email."},"role":{"type":"string","description":"Role to grant on accept."}},"required":["email","role"],"description":"Invite a member."}}}},"responses":{"201":{"description":"The created invitation (token is mailed, never returned).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listInvitations","tags":["Invitations"],"summary":"List invitations","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The invitations.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationsListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/invitations/accept":{"post":{"operationId":"acceptInvitation","tags":["Invitations"],"summary":"Accept an invitation","security":[{"sessionCookie":[]}],"description":"Accepts the raw token from the JSON body or the `?token=` query (the mailed link).","parameters":[{"schema":{"type":"string","description":"The raw invitation token (alternative to the body)."},"required":false,"description":"The raw invitation token (alternative to the body).","name":"token","in":"query"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The raw invitation token from the mailed link (or the `?token=` query)."}},"required":["token"],"description":"Accept an invitation."}}}},"responses":{"201":{"description":"The created membership.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/api-keys":{"post":{"operationId":"createApiKey","tags":["API keys"],"summary":"Create an API key","security":[{"sessionCookie":[]}],"description":"The raw `ur_sk_*` secret is returned exactly once — never persisted, never logged.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"mode":{"type":"string","description":"live | test (default live)."},"scopes":{"type":"array","items":{"type":"string"},"description":"Closed vocabulary: gateway:invoke, logs:read, config:read, config:write, bench:run, outcomes:write, flywheel:experiment:run. Omitted ⇒ gateway:invoke + outcomes:write (flywheel:experiment:run is never granted by default)."},"expiresAt":{"type":"string","description":"ISO-8601 expiry, or omit for a non-expiring key."},"spendCapMicroUsd":{"type":"integer","description":"Per-key monthly hard cap (integer micro-USD)."},"bench_suite_default":{"type":"string","description":"Zero-header bench capture: default suite slug stamped on every request served with this key. TEST-mode keys only (the live-key consent gate cannot be bypassed via a key default) — a live-mode create with this set is a 400."},"default_call_type":{"type":"string","description":"A slug or id of an existing call type of this workspace. The key then attributes any request that carries no `call_type` (body) and no `X-UR-Call-Type` header to it — so a plug-and-play client needs only the base URL + key. Unknown ⇒ 404."},"metadata":{"type":"object","additionalProperties":{"nullable":true}}},"description":"Create an API key."}}}},"responses":{"201":{"description":"The created key + its once-shown secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedApiKeyResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listApiKeys","tags":["API keys"],"summary":"List API keys","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The keys (secret-free).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeysListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/api-keys/{keyId}/roll":{"post":{"operationId":"rollApiKey","tags":["API keys"],"summary":"Roll an API key secret","security":[{"sessionCookie":[]}],"description":"Issues a fresh secret on the SAME key identity; the new secret is shown once.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `keyId`."},"required":true,"description":"Path parameter `keyId`.","name":"keyId","in":"path"}],"responses":{"200":{"description":"The key + its new once-shown secret.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedApiKeyResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/api-keys/{keyId}":{"patch":{"operationId":"updateApiKey","tags":["API keys"],"summary":"Update an API key's default call type","security":[{"sessionCookie":[]}],"description":"Set (a slug/id of an existing call type of this workspace) or clear (null) the key’s DEFAULT call type. A request served by this key that carries no `call_type` (body) and no `X-UR-Call-Type` header is then attributed to it — so a plug-and-play OpenAI-compatible client needs only the base URL + the key. An unknown slug/id is a 404. Bumps config_version (visible ≤ 5 s).","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `keyId`."},"required":true,"description":"Path parameter `keyId`.","name":"keyId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"default_call_type":{"type":"string","nullable":true,"description":"A slug or id of an existing call type of this workspace to SET as the key default, or null to CLEAR it. An unknown slug/id is a 404."}},"required":["default_call_type"],"description":"Update an API key's default call type."}}}},"responses":{"200":{"description":"The updated key (secret-free).","content":{"application/json":{"schema":{"type":"object","properties":{"api_key":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","description":"Display prefix (`ur_sk_<mode>_` + 8 chars) — safe to show."},"mode":{"type":"string","description":"live | test."},"scopes":{"type":"array","items":{"type":"string"}},"spendCapMicroUsd":{"type":"integer","nullable":true},"rpsLimit":{"type":"integer","nullable":true},"benchSuiteDefault":{"type":"string","nullable":true,"description":"Zero-header bench capture default suite (test keys only); null ⇒ unset."},"defaultCallTypeId":{"type":"string","nullable":true,"description":"The key’s default call type id — attributed to a request that carries no `call_type`/`X-UR-Call-Type`; null ⇒ no default."},"expiresAt":{"type":"string","nullable":true},"lastUsedAt":{"type":"string","nullable":true},"metadata":{"type":"object","additionalProperties":{"nullable":true}},"revokedAt":{"type":"string","nullable":true},"createdAt":{"type":"string"}},"required":["id","name","prefix","mode","scopes","spendCapMicroUsd","rpsLimit","benchSuiteDefault","defaultCallTypeId","expiresAt","lastUsedAt","metadata","revokedAt","createdAt"],"description":"An API key summary (secret-free)."}},"required":["api_key"],"description":"A single API key summary (secret-free)."}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"revokeApiKey","tags":["API keys"],"summary":"Revoke an API key","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `keyId`."},"required":true,"description":"Path parameter `keyId`.","name":"keyId","in":"path"}],"responses":{"200":{"description":"Acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/provider-keys":{"post":{"operationId":"createProviderKey","tags":["Provider keys"],"summary":"Register a BYOK provider key","security":[{"sessionCookie":[]}],"description":"The secret is envelope-encrypted at rest; responses carry last-4 + health only.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"provider_id":{"type":"string","description":"The provider slug this key authenticates (e.g. \"openai\")."},"secret":{"type":"string","minLength":1,"description":"The raw provider secret — WRITE-ONLY: envelope-encrypted at rest, never returned."},"name":{"type":"string"},"priority":{"type":"integer","description":"Ascending; lower is tried first."},"weight":{"type":"integer","description":"Weighted spread among equal-priority keys."},"byok_fallback":{"type":"boolean","description":"Allow platform-key fallback (default true)."}},"required":["provider_id","secret"],"description":"Register a BYOK provider key."}}}},"responses":{"201":{"description":"The provider key summary (secret-free).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listProviderKeys","tags":["Provider keys"],"summary":"List provider keys","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Filter to one provider slug."},"required":false,"description":"Filter to one provider slug.","name":"provider","in":"query"}],"responses":{"200":{"description":"The provider keys (secret-free).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeysListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/provider-keys/{keyId}":{"patch":{"operationId":"updateProviderKey","tags":["Provider keys"],"summary":"Update a provider key","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `keyId`."},"required":true,"description":"Path parameter `keyId`.","name":"keyId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"priority":{"type":"integer"},"weight":{"type":"integer"},"byok_fallback":{"type":"boolean"},"disabled":{"type":"boolean","description":"Disable this key without deleting it."}},"description":"Update a provider key (secret unchanged — rotate via a fresh create)."}}}},"responses":{"200":{"description":"The updated provider key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteProviderKey","tags":["Provider keys"],"summary":"Delete a provider key","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `keyId`."},"required":true,"description":"Path parameter `keyId`.","name":"keyId","in":"path"}],"responses":{"200":{"description":"Acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/provider-keys/{keyId}/health-check":{"post":{"operationId":"healthCheckProviderKey","tags":["Provider keys"],"summary":"Health-check a provider key","security":[{"sessionCookie":[]}],"description":"Runs one cheap probe and returns the refreshed health status.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `keyId`."},"required":true,"description":"Path parameter `keyId`.","name":"keyId","in":"path"}],"responses":{"200":{"description":"The provider key with refreshed health.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderKeyEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/providers":{"post":{"operationId":"createCustomProvider","tags":["Custom providers"],"summary":"Register a custom provider","security":[{"sessionCookie":[]}],"description":"The base URL is SSRF-validated on save.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"base_url":{"type":"string","description":"OpenAI-compatible base URL (SSRF-validated on save: private and internal network targets are refused)."},"model_ids":{"type":"array","items":{"type":"string"},"description":"Model ids this provider serves."},"auth":{"type":"object","properties":{"header":{"type":"string","description":"Header name (e.g. \"Authorization\" or \"x-api-key\")."},"value_template":{"type":"string","description":"Value template; `{{secret}}` is the decrypted key."}},"required":["header","value_template"],"description":"Custom provider auth header template."},"pricing":{"type":"object","properties":{"input":{"type":"number","description":"Input price, micro-USD per 1M tokens."},"output":{"type":"number","description":"Output price, micro-USD per 1M tokens."},"cached":{"type":"number","description":"Cached-input price, micro-USD per 1M tokens."}},"required":["input","output"],"description":"Manual custom-provider pricing."},"headers":{"type":"object","additionalProperties":{"type":"string"},"description":"Extra static request headers."},"tls_verify":{"type":"boolean"},"data_policy":{"type":"string","description":"'strict' (ZDR) | 'open'."},"capabilities":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Declared capability flags: tools/json_schema/vision/streaming/embeddings. Omit to inherit the assumed OpenAI-compatible set; a flag set false makes the router refuse this endpoint (pre-dispatch) for a request that needs it."}},"required":["name","base_url"],"description":"Register a custom OpenAI-compatible provider."}}}},"responses":{"201":{"description":"The created custom provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomProviderEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"get":{"operationId":"listCustomProviders","tags":["Custom providers"],"summary":"List custom providers","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"}],"responses":{"200":{"description":"The custom providers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomProvidersListResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/workspaces/{id}/providers/{providerId}":{"get":{"operationId":"getCustomProvider","tags":["Custom providers"],"summary":"Get a custom provider","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `providerId`."},"required":true,"description":"Path parameter `providerId`.","name":"providerId","in":"path"}],"responses":{"200":{"description":"The custom provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomProviderEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"patch":{"operationId":"updateCustomProvider","tags":["Custom providers"],"summary":"Update a custom provider","security":[{"sessionCookie":[]}],"description":"A changed base URL is re-validated through the SSRF guard.","parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `providerId`."},"required":true,"description":"Path parameter `providerId`.","name":"providerId","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"base_url":{"type":"string","description":"Re-validated through the SSRF guard on change."},"model_ids":{"type":"array","items":{"type":"string"}},"auth":{"type":"object","properties":{"header":{"type":"string","description":"Header name (e.g. \"Authorization\" or \"x-api-key\")."},"value_template":{"type":"string","description":"Value template; `{{secret}}` is the decrypted key."}},"required":["header","value_template"],"description":"Custom provider auth header template."},"pricing":{"type":"object","properties":{"input":{"type":"number","description":"Input price, micro-USD per 1M tokens."},"output":{"type":"number","description":"Output price, micro-USD per 1M tokens."},"cached":{"type":"number","description":"Cached-input price, micro-USD per 1M tokens."}},"required":["input","output"],"description":"Manual custom-provider pricing."},"headers":{"type":"object","additionalProperties":{"type":"string"}},"tls_verify":{"type":"boolean"},"active":{"type":"boolean"},"capabilities":{"type":"object","additionalProperties":{"type":"boolean"},"description":"Declared capability flags: tools/json_schema/vision/streaming/embeddings. Replaces the stored set; a flag set false makes the router refuse this endpoint (pre-dispatch) for a request that needs it."}},"description":"Update a custom provider."}}}},"responses":{"200":{"description":"The updated custom provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomProviderEnvelope"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}},"delete":{"operationId":"deleteCustomProvider","tags":["Custom providers"],"summary":"Delete a custom provider","security":[{"sessionCookie":[]}],"parameters":[{"schema":{"type":"string","description":"Path parameter `id`."},"required":true,"description":"Path parameter `id`.","name":"id","in":"path"},{"schema":{"type":"string","description":"Path parameter `providerId`."},"required":true,"description":"Path parameter `providerId`.","name":"providerId","in":"path"}],"responses":{"200":{"description":"Acknowledged.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OkResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/v1/echo":{"get":{"operationId":"echo","tags":["Ops"],"summary":"Key-auth echo","security":[{"bearerAuth":[]}],"description":"Proves API-key auth + the versioned config cache end-to-end. Requires API-key scope: gateway:invoke.","responses":{"200":{"description":"The echoed key identity.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EchoResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/healthz":{"get":{"operationId":"healthz","tags":["Ops"],"summary":"Liveness probe","security":[],"description":"The process is up and serving; never touches dependencies.","responses":{"200":{"description":"Alive.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/readyz":{"get":{"operationId":"readyz","tags":["Ops"],"summary":"Readiness probe","security":[],"description":"Dependencies are usable (DB reachable + migrations current). 503 when not ready.","responses":{"200":{"description":"Ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}},"default":{"description":"Normalized error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}}}