Reference

JSON Output

Stable machine-readable payloads for commands, workspace flows, and CI adapters.

referenceautomation buildersintermediatestable2026-05-30ota/docs/spec/json-output-reference.md

When to use JSON

Use JSON when automation needs stable contract data instead of reading terminal prose.

The JSON surface is the integration contract for CI, editors, AI agents, and scripts.

  • CI, editors, and agents should read JSON rather than scrape terminal text
  • human text output can change without breaking machine consumers
  • the same payload shapes are reused across repo and workspace flows
  • JSON mode is the right choice when you need stable parsing, not terminal polish

Common payload fields

  • ok tells you whether ota completed the command successfully
  • path tells you which contract or workspace file ota resolved
  • semver, version, source_build, commit, and dirty identify the current ota binary when you call ota --version --json
  • schema_version is the coarse contract-generation marker; contract_capabilities is the additive feature-support catalog for compatibility-aware automation
  • contract_capabilities now calls out high-signal task features such as tasks.effects.writes, tasks.effects.adapter_state, tasks.effects.network, tasks.effects.external_state, first-class bootstrap actions like tasks.action.ensure_git_checkout, tasks.action.ensure_git_template, tasks.action.ensure_container_network, and tasks.action.reset_compose_service_volume, bootstrap orchestration (tasks.action.ensure_bundle), and execution guards (tasks.when.checks) when the binary supports them
  • minimum-version compatibility failures should point back to ota --version --json after install or rebuild so operators can confirm the new binary identity and capability surface
  • mode tells you which command path or execution context ota used, such as preview, write, merge, rewrite, native, or container
  • written tells you whether ota actually wrote a file or applied changes
  • operation, subject, assumptions, changes, and validation are the stable reviewed-mutation fields for ota assist payloads
  • summary gives you the roll-up counts that hosted gates care about first
  • next, reason, and details carry structured recovery guidance when ota can classify a failure
  • engine, resource_kind, and resource_name identify the failing cleanup or backend resource when that context exists
  • generic repo-state failures still fall back to stable summary plus error
  • findings carries readiness, policy, and validation issues in a stable list; findings may also include human-readable provenance plus stable provenance_key when ota can trace the diagnosis back to repo contract, org policy, or repo signals
  • native runtime and tool probe findings can add evidence.command and evidence.path when ota resolved an executable and attempted a concrete version probe
  • env carries read-only environment inspection output from ota env --json
  • sources carries declared env-source status such as loaded, missing, parse-failed, or invalid structured source files
  • finding_groups adds grouped remediation summaries without changing findings; each summary carries a stable semantic action_key for the grouped action class
  • receipt records what ota actually executed and what context it used
  • receipt.host_service_cleanup records first-class host-managed service cleanup attempts when ota owned shutdown, including the service, action, status, trigger, and any captured detail
  • config is the generated or detected contract content when ota is previewing or writing
  • pack appears on ota init --json when an explicit starter pack seeded the contract instead of detector-led init
  • pack_options carries selected pack overrides such as Node package manager or Python test runner
  • pack_advisory appears when strong detected repo signals disagree with the selected pack without auto-switching it
  • mode: "catalog" plus packs appears on ota init --packs --json when ota lists the built-in starter-pack catalog instead of previewing one contract
  • comparison is the detected-versus-existing diff for init and detect flows; detect comparison entries now include stable machine ownership plus owner_kind so automation can tell detected adds, hand-authored fields, and ota-managed fields apart without scraping prose
  • inferred explains what ota learned from repo signals and how confident it was
  • inferred[].type and inferred[].signal classify the detected signal without forcing automation to parse prose
  • task-shaped inference entries can also add agent_safe and agent_signal when ota can justify agent-safety metadata
  • provenance is the per-field source map when ota is generating explainable contract content, such as ota init --json starter output or ota workspace init --json scaffold output
  • errors or error appears when validation or loading fails before the normal payload can be produced

Canonical source

  • the canonical machine-readable contract lives in the ota repo spec and the published JSON schemas, not in this summary page alone
  • treat docs/spec/json-output-reference.md in the ota repo and the published schema artifacts as source of truth when this site page is lagging
  • use this page as the public guide, but use the repo spec and schemas when automation needs exact field truth

What to use

  • version for machine-readable ota build identity and contract capability support
  • agents for repo-local AGENTS.md export preview or sync reports, including approved ota bootstrap guidance when the contract declares it
  • services for declared managed-service inventory, including manager shape, readiness declaration, endpoint projections, and dependencies
  • tasks for repo task inventory and AI-agent-safe task hints
  • for the newer contract-owned env/config surfaces, keep env.profiles, render.dotenv, render.dotenv.template, render.files, tasks.<name>.env_files, ensure_env_file, checks[].kind: env, and services.<name>.manager.env_file / services.<name>.manager.profiles on the public docs path instead of teaching shell glue as the default
  • validate and check for contract gating
  • assist declare-readiness, assist declare-service, assist bind-task, assist wire-setup, assist declare-env, assist add-task, and assist normalize for deterministic reviewed mutation output, including machine-readable assumptions, exact field changes, and follow-up validation guidance
  • init for starter-contract preview or write output, including per-field provenance, starter defaults, pack metadata, pack options, and pack advisories
  • ota init --packs --json for pack discovery across Node, Python, Ruby, Go, Rust, .NET, PHP Composer, and Java starter packs
  • detect for contract comparison, merge, and write decisions; ota records detect-managed fields under metadata.ota.detect.field_ownership, records detect-write admission under metadata.ota.detect.field_admission, records additive detector source governance under metadata.ota.detect.field_source_class, and treats existing fields without that metadata as manual by default
  • doctor and workspace doctor for readiness diagnosis and blockers; workspace doctor/check payloads can also carry workspace-level summary.primary_blocker, repo-owned primary_blocker, and additive blocker code when the blocker came from explicit stable finding identity, and policy-backed provisioning entries can add normalized_requirement, resolved_version, and policy_match when ota made a semver-aware authorization decision
  • proof runtime when CI, an agent, or a reviewer needs end-to-end evidence that one selected workflow really started and reached readiness on a clean boundary; it captures the canonical topology, doctor, up-log, and proof metadata artifacts for that runtime path, with cleanup scoped to the selected workflow/runtime boundary
  • policy init for conservative org-policy scaffolding preview or write output, including explicit starter presets
  • receipt for a read-only repo receipt artifact from the current readiness scan
  • workspace tasks and workspace list for workspace inventory and availability
  • up, workspace up, and workspace refresh for preparation, readiness roll-up, and receipts
  • workspace diff for read-only drift inspection before refresh
  • workspace status for the operational readiness-and-drift scan
  • workspace lifecycle payloads may add next, next_steps, drift_kind, and target_source when ota can name the safer follow-up lane directly
  • workspace receipt for the same scan packaged as an archive-ready receipt artifact
  • run and workspace run for execution receipts and repo-owned execution follow-up lanes
  • diff and explain for change impact and remediation planning
  • workspace init and workspace detect for workspace scaffolding and comparison, including per-field provenance for workspace-derived repo entries, preserved merge fields, and scaffold defaults

Canonical schema URLs

These are the live schema URLs behind the public machine-readable reference, including the published repo contract schema.

The ota release gate publishes them as generated artifacts and now checks them against both authored examples and Rust-owned authoring projections before release.

Click a card to open the schema in a new tab. Use the command example when you want to inspect the payload locally.

Workspace schema URLs

Use these when the workspace contract coordinates multiple repos and you need either the workspace contract schema itself or workspace-level machine output.

The published workspace schema is release-gated alongside the repo contract schema and is checked against both authored examples and Rust-owned authoring projections.

Change and remediation URLs

Use these when you are comparing contracts or turning findings into step-by-step fixes.

Read the payload in the right order

  • Check ok first to see whether the command completed cleanly
  • Then read path to confirm which contract or workspace ota resolved
  • Then read summary or findings depending on whether you are gating, diagnosing, or annotating
  • Then read receipt when you need to know what ota actually executed
  • Then read comparison or inferred when you are reviewing writes or previewing inference

Repo and workspace surfaces

  • ota validate --json for contract gating
  • ota workflows --json for workflow inventory and selected-path discovery
  • ota tasks --json for task inventory and safe-agent hints
  • ota tasks --json and ota workspace tasks --json also carry additive structured prepare summaries, including nested steps[] when a task uses prepare.kind: sequence instead of shell setup
  • ota tasks --json and ota workflows --json now carry structured launch additively when the selected task path uses launch instead of shell run or script
  • ota tasks --json and ota workspace tasks --json also carry additive task effects so automation can see declared repo writes, network dependence, and out-of-repo state mutation without scraping notes
  • ota doctor --json for readiness diagnosis and blockers
  • ota doctor --json --fix --dry-run when automation needs the same readiness diagnosis plus the planned contract-aware safe fix set; today that fix surface is .gitignore protection for .ota/state/ on repos with a valid ota.yaml
  • ota execution plan --json for a read-only execution decision with declared contract intent plus resolved backend, lifecycle, image, and target strategy; when the repo declares workflows, planning follows the canonical workflow run path first instead of guessing from repo-wide setup fallback
  • ota execution plan --json fails when the selected container or remote path is not actually runnable from the current contract, instead of inventing a resolved plan
  • ota policy init --json for conservative org-policy scaffold preview or write output, including the selected starter preset when one is used
  • ota receipt --json for a read-only repo receipt artifact from the current readiness scan
  • ota receipt --json now also emits a normalized receipt.contract_snapshot_hash so automation can tie a receipt back to the exact semantic contract truth that produced it
  • ota receipt --json also emits additive receipt.assumption_set_hash so automation can fingerprint the canonical extracted semantic assumption map separately from whole-snapshot identity
  • ota receipt --json, ota proof runtime --json, ota up --json, ota up --dry-run --json, and the workspace receipt/status/up/run/refresh JSON lanes now publish additive artifact_routing[] so automation can follow the same typed next-artifact path without scraping human follow-up text
  • ota execution topology --json for declared launch sources, surfaces, normalized listeners, and attached runtime publication intent without starting anything
  • ota proof runtime --json when automation needs machine-readable proof that a selected workflow actually booted and reached readiness, plus the artifact paths for the captured topology, doctor, and runtime logs; proof cleanup is scoped to the selected runtime path and non-blocking informational findings are preserved without forcing ok: false by themselves; when the selected run task is a successful launcher such as docker compose up -d, proof keeps probing until the declared readiness budget expires instead of collapsing the launcher exit into an immediate failure; timeout lanes normalize to phase: timeout / failure_class: readiness_timeout, signal-terminated lanes normalize to phase: interrupted / failure_class: interrupted, cleanup-classified proof failures now publish additive structured cleanup_failure evidence, high-confidence runtime target mismatches can now publish failure_class: readiness_target_mismatch with structured declared/observed target evidence, high-confidence dns/service-name resolution failures can now publish failure_class: dns_service_name_resolution_failure, high-confidence auth/credential failures can now publish failure_class: auth_credential_failure, high-confidence runtime config drift can normalize to failure_class: config_drift, bind/address-in-use collisions can normalize to failure_class: bind_conflict, missing-config failures can now publish structured likely_cause_evidence.kind: missing_env, install/toolchain breaks can now publish structured likely_cause_evidence.kind: install_or_toolchain_failure, and likely_cause_evidence publishes the structured root-cause signal behind any advisory likely_cause text.
  • ota receipt --json --baseline latest for receipt-to-receipt comparison against the newest valid archived baseline for the same contract
  • ota receipt --json --baseline <file> for comparison against an explicit repo receipt JSON artifact
  • when the selected baseline receipt carries receipt.contract_snapshot_ref, receipt diff JSON also adds semantic contract_changes[], correlated likely_related_changes[], and summary.comparison.contract_snapshot_changed so automation can connect new blockers to contract drift instead of only seeing finding deltas
  • receipt diff JSON now also carries summary.comparison.correlation so automation can distinguish likely_related, coarse same-family possibly_related, and unrelated-drift no_clear_correlation without reverse-engineering correlation posture from array emptiness
  • ota receipt --json --snapshot latest when automation needs the archived normalized contract truth directly instead of only seeing it indirectly through diff or receipt correlation
  • ota receipt --json --snapshot <file> accepts either an archived repo receipt JSON artifact or an archived .ota/contracts/... snapshot JSON artifact and reports which archive-backed lane was selected
  • snapshot JSON now also publishes additive assumption_set_hash plus summary.assumption_count, so automation can read semantic snapshot identity directly instead of deriving it from the raw normalized JSON payload
  • ota receipt --json emits the shared ValidateFailure JSON on stdout when contract load or validation fails before the receipt can be built
  • ota up --dry-run --json for read-only preparation previews
  • ota up --json for preparation and readiness receipts on repo targets; monorepo aggregate output keeps grouped member results instead of inventing a top-level aggregate receipt
  • ota clean --json for repo, member, and workspace cleanup counters on success, for classified cleanup failures that name either the engine/resource lane or the active-execution barrier lane, and for generic repo-state failures that still stay machine-readable through summary plus error
  • ota clean --stale --json for contract-free stale container cleanup results; classified stale cleanup failures use the same clean.json schema and expose stale engine-query failures without scraping text
  • ota diff --json for semantic contract comparison
  • ota explain --json for remediation planning
  • ota workspace doctor --json for workspace readiness and roll-ups, including summary.verdict, summary.agent_verdict, and additive summary.primary_blocker when ota can name the current workspace headline blocker
  • ota workspace check --json for checks-only workspace readiness; add --progress-json when you also need live NDJSON workspace progress on stderr while the final JSON roll-up stays on stdout, including additive phase and stage_family on each progress event
  • ota workspace execution plan --json for per-repo execution resolution across a workspace without running setup or tasks; when workflow-aware planning selects a canonical repo path, the output now carries both the effective workflow and task
  • ota workspace execution plan --json fails when any selected repo cannot actually produce a runnable execution plan, even if that repo is optional in the full workspace contract
  • ota workspace up --json for workspace preparation and receipts; add --progress-json when you also need live NDJSON workspace progress on stderr, including additive phase and stage_family on each event
  • ota workspace refresh --json for workspace re-sync and receipt output; add --progress-json when you also need live NDJSON workspace progress on stderr, including additive phase and stage_family on each event
  • ota workspace diff --json for read-only workspace drift inspection, including additive lifecycle next / next_steps and per-repo drift_kind / target_source when ota can name the safer follow-up lane directly; add --progress-json when you also need live NDJSON workspace progress on stderr, with additive phase / stage_family, the repo diff verdict in status, and machine drift_kind in tail
  • ota workspace status --json for the operational readiness-and-drift roll-up, including additive lifecycle next / next_steps and per-repo drift_kind / target_source when ota can name the safer follow-up lane directly; add --progress-json when you also need live NDJSON workspace progress on stderr, with additive phase / stage_family and repo drift state carried in tail
  • ota workspace receipt --json for the same scan as an archive-ready receipt artifact; add --progress-json when you also need live NDJSON workspace progress on stderr, with additive phase / stage_family and repo drift state carried in tail because receipt reuses the same scan as workspace status
  • ota workspace run --json for coordinated multi-repo execution; add --progress-json when you also need live NDJSON workspace progress on stderr, including additive phase / stage_family plus task and resolved repo_task on both dispatch and terminal repo-task events when workspace bindings rewrite the local task name

Example payloads

Task inventory with sequence preparejson
{  ok: true,  path: "/workspace/acme/ota.yaml",  tasks: [    {      name: "setup",      kind: "sequence",      description: "Prepare mixed repo dependencies",      prepare: {        kind: "sequence",        steps: [          {            kind: "dependency_hydration",            medium: "package_dependencies",            source_kind: "node_package_manager",            cwd: ".",            manager: "pnpm",            mode: "install",            frozen_lockfile: true          },          {            kind: "dependency_hydration",            medium: "package_dependencies",            source_kind: "uv",            cwd: "api",            manager: "uv",            mode: "sync"          }        ]      },      effects: {        writes: ["node_modules", ".venv"],        network: true,        network_kind: "dependency_hydration"      },      depends_on: [],      requires_services: [],      safe_for_agent: false    }  ]}
Doctor outputjson
{  ok: false,  path: "/workspace/acme/ota.yaml",  mode: "container",  summary: {    error_count: 1,    warn_count: 1,    info_count: 0  },  findings: [    {      code: "OTA_TASKS_MISSING",      category: "contract",      owner: "repo_contract",      severity: "error",      summary: "No tasks defined in contract",      why: "The repo is not runnable until it declares at least one task.",      next: "Add a setup or test task to ota.yaml.",      evidence: {        path: "/workspace/acme/ota.yaml"      }    }  ]}
Clean failure outputjson
{  ok: false,  path: "./ota.yaml",  summary: "Container engine unavailable",  error: "cleanup `list` failed for dependency-isolation volume state `dev.ota.repo=repo-1` using podman",  why: "`ota clean` needs Podman to remove dependency-isolation repo state for `dev.ota.repo=repo-1`, but Podman is not reachable.",  next: [    "start Podman and rerun `ota clean`",    "run `podman system connection list`",    "if needed, run `podman machine init` and `podman machine start`"  ],  reason: "engine_unavailable",  engine: "podman",  action: "list",  resource_kind: "dependency_isolation_volume",  resource_name: "dev.ota.repo=repo-1",  details: "unable to connect to Podman socket: dial tcp 127.0.0.1:57990: connect: connection refused"}
Workspace receiptjson
{  ok: true,  mode: "receipt",  path: "/workspace/acme/ota.workspace.yaml",  summary: {    error_count: 0,    warn_count: 0,    info_count: 0,    step_count: 2,    repo_count: 2,    ready_count: 2,    not_ready_count: 0  },  receipt: {    ok: true,    path: "/workspace/acme/ota.workspace.yaml",    scope: "workspace",    contract: "/workspace/acme/ota.workspace.yaml",    workspace: "acme-dev"  },  repos: [    {      name: "api",      ok: true,      status: "READY",      readiness_status: "READY",      drift_status: "MATCH"    },    {      name: "web",      ok: true,      status: "READY",      readiness_status: "READY",      drift_status: "MATCH"    }  ]}

What JSON is not

  • not live logs
  • not a replacement for the human status line
  • not a text parsing target
  • not the only output mode ota provides

Use cases

  • a CI job runs ota doctor --json, fails on errors, and posts warnings as annotations
  • an editor shows the primary finding without parsing text output
  • an agent reads the receipt to see what ota actually did
  • a workspace gate surfaces per-repo readiness instead of flattening everything into one string
  • a release pipeline compares contract changes through ota diff --json before writing updates
  • a repo author previews a new AGENTS.md with ota agents --json before writing it