Reference

Execution Receipt

The machine-readable record of what ota actually executed.

referenceautomation buildersintermediatestable2026-05-30

What a receipt is for

Read the receipt after a command runs if you need to audit what happened.

Use it when you want to compare runs, debug failures, or prove which backend and env values were used.

  • the receipt is the machine-readable record of execution, not diagnosis
  • the receipt tells you what ota chose, what ran, what succeeded, and what was blocked
  • the receipt is what automation should read after execution, not before it
  • the receipt makes the execution trail reviewable while failure output keeps Why and Next before the trailing RUN SUMMARY block, and the compact summary now leads with Status for faster scanning
  • repo receipts can include a Policy: section when policy-backed provisioning selected a source or backend-specific config
  • receipts can also include host_service_cleanup when ota attempted host-managed service shutdown during interrupt cleanup
  • receipts can also include execution_conflict.reasons[] when active execution ownership blocked the run path

Receipt fields

  • ok tells you whether the command completed successfully
  • path tells you which repo or workspace file ota resolved for the run
  • scope tells you whether the receipt came from a repo command or a workspace command
  • contract tells you which contract governed the execution
  • evaluated_inputs carries captured replay inputs while ota authored the receipt; a matching input can only support the named trust class, never broader ambient state
  • a consumed replay authority appears as evaluated_inputs[].kind: promoted_replay_baseline; its artifact_lineage.replay_authority binds the receipt to the portable authority manifest, SCM-review trust root, selected attestation, declared consumption posture, and promotion identity rather than claiming its producer ran during replay
  • a baseline producer receipt carries its attested recording reference in witnessed_observations.replay_baseline_recordings[]; this is historical regeneration evidence, while a later replay receipt carries only the separately selected authority
  • evaluated_inputs[*].hydration_provenance records the declared and runner-resolved source posture for a selected structured hydration lane, so a later config-file read cannot rewrite what that execution used
  • witnessed_observations carries attested execution evidence separately from evaluated inputs, so observed query variation cannot be mistaken for a current-run decision input
  • backend tells you where the work ran, such as native, container, or remote
  • lifecycle tells you whether container execution was persistent or ephemeral
  • steps shows the ordered execution steps and their status
  • summary gives the roll-up counts for errors, warnings, info, and steps
  • next gives the safest follow-up action when ota can suggest one
  • next_steps gives that same follow-up lane as an ordered machine-readable array when ota can break it into explicit steps
  • env_sources shows which env values won and where they came from
  • native_prerequisites shows the selected native prerequisite evidence for the executed native path, including additive check, activation, provisioning, and note detail when present
  • native_prerequisites[*].activation.applied tells you whether ota actually ran inside that activation for this command or only reported the declared activation shape
  • policy shows which effective approved provisioning source ota resolved for the run and any backend-specific source config
  • host_service_cleanup shows first-class host-managed service cleanup evidence when ota owned the stop path
  • execution_conflict.reasons[] shows typed active-execution conflict ownership such as host_service, compose_project, write_path, runtime_listener, or conservative unresolved service_task ownership
  • a single fixed runtime_listener collision keeps the machine reason stable while receipt follow-up points to --host-port <free port> only when the selected lane admits that override; explicit ports are refused rather than silently remapped
  • a live legacy service_task record without runtime_owners[] stays fail-closed because Ota cannot prove its endpoint from old evidence; restart that service once with the current Ota binary to record precise listener ownership

How to read it

  • Check ok first to see whether execution succeeded
  • Then check scope and contract to confirm what ota ran against
  • Then check backend and lifecycle to understand the execution model
  • Then read steps to see what actually ran and where the run stopped
  • Then read summary, next, and optional next_steps for the roll-up and safest follow-up
  • Then inspect env_sources if you need provenance for the values that won
  • Then inspect native_prerequisites when the selected path depended on host-native build tooling or task-scoped shell activation
  • Then inspect policy if you need the approved provisioning source or source config
  • Then inspect host_service_cleanup when the run was interrupted and ota owned host-managed service shutdown
  • Then inspect execution_conflict.reasons[] and optional owner runtime_owners[] when another active execution claimed an overlapping listener, write namespace, or unresolved service boundary
  • If the owner reports legacy_or_unresolved runtime ownership, restart that active service once with the current Ota binary before retrying cross-mode execution
  • If a step failed, the receipt should let you tell whether the failure was from setup, the task body, or the backend itself

Repo example

A repo receipt should be enough to tell you what happened in that repo run without opening the terminal output again.

Repo task runjson
{  ok: true,  path: "/workspace/acme/app/ota.yaml",  scope: "repo",  contract: "/workspace/acme/app/ota.yaml",  backend: "container",  lifecycle: "ephemeral",  steps: [    { "order": 1, "label": "setup", "status": "ok" },    { "order": 2, "label": "test", "status": "ok" }  ],  summary: { "error_count": 0, "warn_count": 0, "info_count": 0, "step_count": 2 },  next: "run `ota run test` again after your code changes",  env_sources: [    { "name": "NODE_ENV", "source": "task.env", "value": "test" }  ],  policy: [    "tool node (package: nodejs) 22 via choco (source_config: feed=internal-choco)"  ]}

Workspace example

A workspace receipt should tell you which member blocked the rollout and which members finished cleanly.

Workspace runjson
{  ok: false,  path: "/workspace/acme/ota.workspace.yaml",  scope: "workspace",  contract: "/workspace/acme/ota.workspace.yaml",  backend: "native",  lifecycle: "persistent",  steps: [    { "order": 1, "label": "api", "status": "ok" },    { "order": 2, "label": "web", "status": "blocked" }  ],  summary: { "error_count": 1, "warn_count": 0, "info_count": 0, "step_count": 2 },  next: "run `ota workspace doctor` to inspect the blocked member"}

How to use it

  • use ota execution plan --json when you need to inspect backend, lifecycle, image, or target selection without running setup or tasks
  • workflow-aware planning follows the selected workflow run path first and only falls back to setup when the workflow has no run phase
  • prepare.task stays additive workflow context rather than the concrete execution task
  • use ota execution plan --json --mode container or --mode remote when you want the same backend-configuration gate that ota run and ota up would enforce before execution starts
  • use ota workspace execution plan --json when you need the same read-only execution decision across selected workspace repos instead of one repo at a time, including workspace-pinned or repo-default workflow paths
  • use ota workspace execution plan --json --repo <name> when the decision boundary is the selected repo set, not the full required/optional workspace roll-up
  • use ota receipt --json when you want the same repo readiness scan as an archive-ready receipt artifact without provisioning, setup, or writes
  • repo receipts can now include additive receipt.toolchains[] evidence for the selected provider-backed ecosystem path, alongside the existing readiness findings and execution identity
  • when ota actually runs provider fulfillment commands on the recorded execution path, the same toolchain entry can also include additive fulfilled and commands[] evidence
  • every successful repo receipt now includes a normalized receipt.contract_snapshot_hash, and --archive also materializes that normalized contract JSON under .ota/contracts so the receipt can point at the exact semantic contract truth it used
  • every successful repo receipt now also includes additive receipt.assumption_set_hash, derived from the canonical extracted semantic path/value map instead of the raw snapshot blob
  • when a selected task or workflow closure declares tasks.<name>.replay_inputs, receipt.evaluated_inputs[] captures each static file SHA-256 identity before execution begins; those identities narrow only the named file input, never ambient runtime or external state. Use kind: static_file for generic immutable repo files, kind: presentation_profile for declared output-shaping or normalization policy files, and kind: comparator_profile for declared equivalence or tolerance policy files. The same field also captures lockfile-strict Node hydration and selected static Compose image evidence; compare all of them only through archived baseline versus current receipt, never through a later filesystem read
  • use policies.replay_inputs.identity.tasks|workflows when selected replay-sensitive closures must refuse unless every declared replay input has a matching immutable pin. Agent safety, claim assurance, replay admission, Doctor/provisioning findings, proof, CI projection, and receipt evidence reuse one command-scoped loaded policy snapshot and replay-input observation set; each task-qualified input is observed once for command admission, and aggregate monorepo Doctor JSON retains each member policy record. Runtime proof pins that admitted authority for its detached child and includes post-readiness seam observers plus its selected negative-control task before proof artifacts or child runtime spawn. Lifecycle proof admits the exact prerequisite-plus-assertion closure before tasks or service transitions. Recursive outcome hooks are part of admission and the projected CI execution closure, so a governed or mismatched hook blocks before its parent starts and cannot disappear from provider evidence. Hard-pin refusals retain the active policy record, while generic readiness receipts do not reconstruct policy after execution. Both deny and review refuse before native provisioning, dependency hydration, proof side effects, or task startup. Missing, unreadable, or mismatched declared hard pins always refuse and cannot be weakened to review; unavailable observations and active policy load failures also fail closed. Mutating ota doctor --fix applies the same admission before repo-hygiene or native tool-activation mutation, while ota doctor --fix --dry-run remains a non-mutating preview. CI projection carries requirements, not render-host observations, so provider checkouts recompute observed identities
  • use artifacts.<name>.replay for generated fixtures or model baselines. Keep kind: generated_source when the same outputs already have generated-source lineage; replay authority is additive and must not duplicate output ownership. A generated_source consumer with the producer in top-level depends_on is ordinary generated-source execution; without that unconditional dependency, it uses promoted replay authority. A dedicated replay_baseline always consumes promoted authority. ota baseline record --artifact <name> requires a clean Git source identity before it creates a receipt-bound recording, then ota baseline promote --artifact <name> --attestation <path> explicitly selects it through a committed manifest. That manifest embeds the selected attestation and declares SCM review as its external trust root; Ota does not verify reviewer inclusion or signer provenance. Doctor reports OTA_REPLAY_BASELINE_UNAVAILABLE before a selected replay consumer starts when that authority is unavailable or drifted. consumption: read_only mounts a runner-owned snapshot outside the writable workspace across the selected ephemeral-container closure and projects command-capable typed preparation through that same boundary; consumption: verify_unchanged keeps native replay available but reports replay_artifact_mutation_detected if the baseline changes after the task. It does not upgrade that detection posture to read-only enforcement. Replay-baseline symlinks must remain inside declared artifact outputs. Neither path regenerates the baseline or auto-promotes the newest recording
  • when a selected closure declares tasks.<name>.witnessed_observations.query_traces, receipt.witnessed_observations.query_traces[] carries attested per-subject/per-run query identity records, source path and SHA-256 identity, and a divergent-subject summary separately from evaluated_inputs[]; it reports observed query variation without claiming model causality or treating historical output as a current-run input
  • add --archive to persist the JSON receipt under .ota/receipts (keeps the newest 50), including its normalized snapshot reference and matching identity; authority-bearing execution archives also carry a canonical selected-invocation scope, so history re-derives the exact governed closure instead of trusting a lane label or the current worktree contract
  • use ota receipt --json --history when you need the archived repo receipt index without rerunning diagnosis
  • on a protected Linux systemd Launcher deployment, use ota receipt --json --history --source systemd_protected_launcher; the fixed history service selects the administrator-bound repository catalog, returns the exact archive, immutable contract snapshot, and finalization sidecar, and Core applies the same semantic archive verifier without local fallback
  • add --archive-identity <sha256:...> to select one exact protected archive; protected history rejects repository paths, --file, OTA_FILE, malformed or incomplete manifests, and any object or semantic verification mismatch
  • history reads valid archives newest first and surfaces malformed files as skipped entries. Snapshot-less older archives remain inspectable as legacy_unverified, but cannot be selected as baselines, proof inputs, or crossing-authority evidence
  • use ota receipt --json --baseline latest when you need introduced, resolved, unchanged, and semantic contract-drift evidence against the newest valid archived receipt for the same contract
  • use ota receipt --json --baseline <file> when the baseline should come from an explicit repo receipt JSON artifact instead of .ota/receipts
  • when that baseline carries receipt.contract_snapshot_ref, read summary.comparison.contract_snapshot_changed, contract_changes[], and likely_related_changes[] to connect new blockers to contract drift
  • read summary.comparison.correlation first for the top-level advisory posture; possibly_related is reserved for coarse same-family overlap, while unrelated drift stays no_clear_correlation
  • use ota receipt --json --snapshot latest or --snapshot promoted when you need the archived normalized semantic contract JSON itself rather than just drift evidence
  • --snapshot <file> accepts either an archived receipt JSON artifact or an archived .ota/contracts/... snapshot JSON file and reports the resolved selection_kind, snapshot_hash, assumption_set_hash, summary.assumption_count, and snapshot_path
  • receipt diff stays read-only and exits 0 when the comparison succeeds, even if the current or baseline receipt is blocked
  • use ota run <task> --dry-run --json for task-level execution previews without starting the run path; the published schema is run-preview.json, and blocked previews still stay on the same stdout preview envelope so automation can read summary.primary_blocker directly
  • use ota up --json for readiness roll-ups and receipts
  • use ota workspace run --json, ota workspace up --json, ota workspace refresh --json, and ota workspace status --json for workspace records; refresh stays read-only in preview mode and can also reflect stricter sync choices when those flags are used
  • use ota workspace receipt --json when you want the same workspace scan as an archive-ready receipt artifact
  • read receipts after execution, not before it
  • compare receipts across runs when you need to prove what changed
  • use receipts when you need the execution trail, not the readiness diagnosis

What it is not

  • not live logs
  • not a diagnosis report
  • not a contract inference result
  • not a replacement for doctor
  • not a replacement for detect
  • not the place to discover new contract fields

Use cases

  • confirm what ota actually executed after a successful ota run
  • debug a failed ota up without guessing which backend or lifecycle was used
  • inspect which steps were blocked before a task could finish
  • compare a native run and a container-backed run
  • feed a machine-readable execution trail into CI or agent workflows
  • review workspace roll-ups after multi-repo bootstrap or execution