{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/mmerterden/multi-agent-pipeline/pipeline/schemas/runs-index.schema.json",
  "title": "Runs index",
  "description": "What `runs-index.mjs --json` prints: every run under the log root and the unattended log root (one record per task id), grouped per status/SKILL.md 3b. Fields are only ever added - a decoder ignores keys it does not know. `--redact` drops every x-sensitivity local field (and `logsRoot`) and scrubs the free text in the title, `now`, sub-step names, task subjects and the pending question.",
  "type": "object",
  "additionalProperties": false,
  "required": ["contractVersion", "count", "runs"],
  "properties": {
    "contractVersion": {
      "type": "string",
      "pattern": "^1\\.[0-9]+\\.[0-9]+$",
      "x-sensitivity": "none"
    },
    "logsRoot": {
      "type": "string",
      "x-sensitivity": "local",
      "description": "Absent under --redact."
    },
    "count": { "type": "integer", "minimum": 0, "x-sensitivity": "none" },
    "runs": {
      "type": "array",
      "x-sensitivity": "none",
      "items": { "$ref": "#/$defs/run" }
    }
  },
  "$defs": {
    "run": {
      "type": "object",
      "required": [
        "taskId",
        "project",
        "layout",
        "salvaged",
        "kind",
        "stateReadable",
        "status",
        "currentPhase",
        "branch",
        "baseBranch",
        "startedAt",
        "autopilot",
        "schemaVersion",
        "rev",
        "group",
        "phases",
        "tokens",
        "estUsd",
        "unlockedWrites"
      ],
      "properties": {
        "taskId": { "type": "string", "x-sensitivity": "none" },
        "project": { "type": ["string", "null"], "x-sensitivity": "none" },
        "dir": { "type": "string", "x-sensitivity": "local", "description": "The run directory." },
        "layout": { "enum": ["nested", "flat"], "x-sensitivity": "none" },
        "duplicateOf": {
          "type": ["string", "null"],
          "x-sensitivity": "local",
          "description": "The other layout's directory for the same task id, when both exist."
        },
        "salvaged": { "type": "boolean", "x-sensitivity": "none" },
        "kind": { "enum": ["pipeline", "tracker-only", "empty"], "x-sensitivity": "none" },
        "stateReadable": { "type": "boolean", "x-sensitivity": "none" },
        "status": { "type": ["string", "null"], "x-sensitivity": "none" },
        "currentPhase": { "type": ["integer", "null"], "x-sensitivity": "none" },
        "branch": { "type": ["string", "null"], "x-sensitivity": "none" },
        "baseBranch": { "type": ["string", "null"], "x-sensitivity": "none" },
        "startedAt": { "type": ["string", "null"], "x-sensitivity": "none" },
        "worktreePath": { "type": ["string", "null"], "x-sensitivity": "local" },
        "prUrl": {
          "type": ["string", "null"],
          "x-sensitivity": "local",
          "description": "Carries the host, so it stays on this machine."
        },
        "autopilot": { "type": "boolean", "x-sensitivity": "none" },
        "schemaVersion": {
          "type": ["string", "null"],
          "x-sensitivity": "none",
          "description": "The run's agent-state schemaVersion. Always a string; a number in a hand-edited state is printed as its string."
        },
        "rev": { "type": ["integer", "null"], "x-sensitivity": "none" },
        "sessionId": {
          "type": ["string", "null"],
          "x-sensitivity": "none",
          "description": "The session id the run was launched under (agent-state sessionId). A client that launched a run through launch.json finds it by this id. Added in 1.1.0."
        },
        "waitingFor": {
          "type": ["string", "null"],
          "x-sensitivity": "none",
          "description": "The step a paused run re-enters (agent-state waitingFor): maturity, user-channels-choice or question. Added in 1.1.0."
        },
        "pendingQuestion": {
          "x-sensitivity": "none",
          "description": "The question the run stopped on, present only with waitingFor question. Answer it with one of options[].id through `answer-question.mjs` or POST /v1/runs/{id}/answer. text and labels are scrubbed under --redact. Added in 1.1.0.",
          "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/question" }]
        },
        "group": { "enum": ["waiting", "stopped", "question", "unknown"], "x-sensitivity": "none" },
        "phases": {
          "type": "array",
          "x-sensitivity": "none",
          "items": { "$ref": "#/$defs/phase" }
        },
        "tokens": {
          "type": "object",
          "required": ["in", "out", "cached"],
          "x-sensitivity": "none",
          "properties": {
            "in": { "type": "integer", "minimum": 0 },
            "out": { "type": "integer", "minimum": 0 },
            "cached": { "type": "integer", "minimum": 0 }
          }
        },
        "estUsd": { "type": "number", "minimum": 0, "x-sensitivity": "none" },
        "unlockedWrites": { "type": "integer", "minimum": 0, "x-sensitivity": "none" },
        "runType": {
          "enum": ["analysis", "development", "autopilot"],
          "x-sensitivity": "none",
          "description": "autopilot when the run is in autopilot mode; analysis for an analysis-family run (agent-state mode analysis, or a tracker with no agent state); development otherwise. Added in 1.2.0."
        },
        "title": {
          "type": ["string", "null"],
          "x-sensitivity": "none",
          "description": "The issue summary Phase 0 recorded (agent-state title), else the input the run was launched with (launchRequest.input), else null. Scrubbed under --redact. Added in 1.2.0."
        },
        "progress": {
          "type": ["number", "null"],
          "minimum": 0,
          "maximum": 1,
          "x-sensitivity": "none",
          "description": "The mean of phases[].progress over the registered phases, a phase whose progress is null counting as 0. Null when no phase is registered. Added in 1.2.0."
        },
        "processAlive": {
          "type": ["boolean", "null"],
          "x-sensitivity": "none",
          "description": "Whether the session the run was launched under (sessionId) is alive per `claude agents --json`: true listed and working, false recorded and ended, null when no session is recorded or the list could not be read. Added in 1.2.0."
        },
        "currentTask": {
          "type": ["object", "null"],
          "additionalProperties": false,
          "required": ["subject", "activeForm"],
          "x-sensitivity": "none",
          "description": "The first in_progress task of the phase in progress, or null. Scrubbed under --redact. Added in 1.2.0.",
          "properties": {
            "subject": { "type": "string" },
            "activeForm": { "type": ["string", "null"] }
          }
        }
      }
    },
    "question": {
      "type": "object",
      "additionalProperties": false,
      "required": ["id", "stepId", "text", "kind", "options"],
      "properties": {
        "id": { "type": "string", "x-sensitivity": "none" },
        "stepId": { "type": "string", "x-sensitivity": "none" },
        "text": { "type": "string", "x-sensitivity": "none" },
        "kind": { "enum": ["single-select", "multi-select"], "x-sensitivity": "none" },
        "options": {
          "type": "array",
          "x-sensitivity": "none",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "label"],
            "properties": {
              "id": { "type": "string" },
              "label": { "type": "string" }
            }
          }
        }
      }
    },
    "phase": {
      "type": "object",
      "required": [
        "id",
        "name",
        "status",
        "model",
        "startedAt",
        "completedAt",
        "now",
        "subs",
        "subList"
      ],
      "properties": {
        "id": { "type": "string", "x-sensitivity": "none" },
        "name": { "type": "string", "x-sensitivity": "none" },
        "status": { "type": "string", "x-sensitivity": "none" },
        "model": { "type": ["string", "null"], "x-sensitivity": "none" },
        "startedAt": { "type": ["string", "null"], "x-sensitivity": "none" },
        "completedAt": { "type": ["string", "null"], "x-sensitivity": "none" },
        "now": {
          "type": ["string", "null"],
          "x-sensitivity": "none",
          "description": "The phase's one-line current activity: what `phase-tracker.sh now` recorded (meta.Now). Scrubbed under --redact."
        },
        "subs": {
          "type": "integer",
          "minimum": 0,
          "x-sensitivity": "none",
          "description": "How many sub-steps the phase has. Kept as a count for existing readers; the sub-steps are subList."
        },
        "subList": {
          "type": "array",
          "x-sensitivity": "none",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "name", "status"],
            "properties": {
              "id": { "type": "string" },
              "name": { "type": "string" },
              "status": { "type": "string" }
            }
          }
        },
        "progress": {
          "type": ["number", "null"],
          "minimum": 0,
          "maximum": 1,
          "x-sensitivity": "none",
          "description": "1 for a completed or skipped phase, 0 for a pending one; otherwise completed tasks over tasks, and null when the phase has no tasks. Added in 1.2.0."
        },
        "tasks": {
          "type": "array",
          "x-sensitivity": "none",
          "description": "The host's native task list for this phase (TaskCreate/TaskUpdate, update_plan steps, card rows) as `phase-tracker.sh task` mirrored it; empty when there are none. subject and activeForm are scrubbed under --redact. Added in 1.2.0.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "subject", "activeForm", "status"],
            "properties": {
              "id": { "type": "string" },
              "subject": { "type": "string" },
              "activeForm": { "type": ["string", "null"] },
              "status": { "enum": ["pending", "in_progress", "completed"] }
            }
          }
        }
      }
    }
  }
}
