{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://raw.githubusercontent.com/BourbonDog/amicus/main/schemas/council-run-live.schema.json",
  "title": "Amicus composed live council-run doc (amicus_status/buildCouncilStatusPayload, view:'live')",
  "type": "object",
  "required": ["taskId", "type", "runId", "runDir", "status", "currentStage", "stages", "legsTotal", "legsComplete", "elapsed", "exitCode", "version"],
  "properties": {
    "type": { "const": "council-run" },
    "view": { "const": "live" },
    "runId": { "type": "string" },
    "runDir": { "type": "string" },
    "status": { "type": "string" },
    "currentStage": { "type": ["string", "null"] },
    "stages": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["name", "status"],
        "properties": {
          "name": { "type": "string" },
          "status": { "type": "string" },
          "waveId": { "type": ["string", "null"] }
        }
      }
    },
    "legsTotal": { "type": ["number", "null"] },
    "legsComplete": { "type": ["number", "null"] },
    "elapsed": { "type": "string" },
    "exitCode": { "type": ["number", "null"] },
    "usage": { "type": "object" },
    "legs": {
      "description": "One row per active-stage leg id (DE-ROT Task 0.5 / F01), present unconditionally — a just-started leg with no usage flushed yet still gets a row.",
      "type": "array",
      "items": {
        "type": "object",
        "required": ["taskId", "model", "status"],
        "properties": {
          "taskId": { "type": "string" },
          "model": { "type": ["string", "null"], "description": "Resolved executable id (metadata.model)." },
          "modelInput": { "type": ["string", "null"], "description": "Council alias (run.json bench/chair/critic/lenses are keyed on this, not `model`); null when the leg's metadata.json has not been patched with it yet (F36)." },
          "role": { "type": ["string", "null"], "description": "'seat' | 'critic' | 'lens:<slug>' | 'chair', derived via roleFor keyed on modelInput (chair via the owning stage's name instead, F34); null when modelInput is unknown." },
          "seat": { "type": ["string", "null"], "description": "v4.8 R5, optional. This leg's seat id (`alias#N`) when the bench repeats an alias, else null. Written at launch by src/sidecar/fanout-leg.js :: runSingleAttempt from the per-wave roster and read back by src/observe/council-legs.js :: buildLegRow. Present on every leg row, including a truthful null — unlike metadata.json's own `seat` key, which is absent (not null) on a unique-alias bench: `buildLegRow`'s base row literal is unconditional and already emits nulls the same way for `model`/`modelInput`, so this field matches that literal rather than the absent-when-unset convention `usageError` above uses. The leg-row `items` object declares no `additionalProperties: false`, so an additive field was already accepted here — this documents the shape rather than changing what is accepted." },
          "status": { "type": "string" },
          "messages": { "type": "number" },
          "stage": { "type": "string" },
          "latestPreview": { "type": ["string", "null"] },
          "lastActivityAt": { "type": ["string", "null"] },
          "stalled": { "type": "boolean" },
          "usage": { "type": "object" },
          "usageError": { "type": "string", "description": "Council review C3: set when enrichLegUsage (pricing resolution) throws for this leg's progress usage, so the failure is distinguishable from a leg that simply has not billed yet (no `usage` key, no `usageError` key either). Additive; absent on every leg that priced cleanly or has no usage yet." }
        }
      }
    },
    "stalled": { "type": "boolean" },
    "stalledForSeconds": { "type": "number" }
  },
  "additionalProperties": true
}
