Use when working on anything Ota-specific: creating, refining, reviewing, or explaining Ota contracts (`ota.yaml`), modeling execution governance for humans and AI agents, working through `ota doctor` / `ota up` / `ota run`, handling agent safety surfaces, Ota Studio boundaries, or when deciding whether a problem belongs in the repo contract or in Ota itself.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
npx skills add https://github.com/nathfavour/threader --skill ota
La commande reste sur une seule ligne. Faites défiler horizontalement pour la vérifier avant de la copier.
Vous préférez une copie locale ? Téléchargez les fichiers actuellement disponibles dans SkillsMP.
Use when working on anything Ota-specific: creating, refining, reviewing, or explaining Ota contracts (`ota.yaml`), modeling execution governance for humans and AI agents, working through `ota doctor` / `ota up` / `ota run`, handling agent safety surfaces, Ota Studio boundaries, or when deciding whether a problem belongs in the repo contract or in Ota itself.
Ota
Use this skill when the task is about Ota-specific contract authoring, contract review, execution
governance for humans and AI agents, or Ota platform judgment.
Do not use this skill for generic YAML generation. It is for truthful execution governance, not
schema-only completion.
Core product posture
Doctor first, contract second.
ota.yaml is the canonical source of execution governance truth.
Prefer one explicit operational path over parallel scripts and tribal knowledge.
If the repo needs ugly glue because Ota lacks a product feature, call it out as an Ota
gap instead of normalizing the workaround.
Architecture loop
Keep the Ota mental model in this order:
contract truth
execution truth
proof and receipt truth
semantic diff and correlation
policy and governance truth
Use the matching surface for the real question:
contract truth: ota.yaml, ota.workspace.yaml, ota validate
execution truth: ota doctor, ota up, ota run, ota tasks, ota execution plan
proof and receipt truth: ota receipt
semantic diff and correlation: ota diff, ota receipt --snapshot, ota receipt --json --baseline ...
policy and governance truth: .ota/org-policy.yaml, ota policy, ota policy review
Do not collapse these into one artifact mentally or in guidance. The contract declares, execution
selects, proof records, diff compares semantic truth, and policy constrains approval.
For workspace contracts, keep one more boundary explicit:
use repos.<name>.tasks.<workspace_task>.task when one shared workspace verb should map to a
different repo-local task name
do not force mixed-name cross-repo flows back into shell wrappers just because the repos do not
share one literal task name
Source priority
Prefer sources in this order:
the repo you are actively working on
local canonical Ota references, when they exist in the checkout:
ota.yaml
examples/
docs/spec/contract-reference.md
docs/spec/json-output-reference.md
README.md
public references in references/official-sources.md
When the question is specifically about archived semantic truth, semantic diff, or receipt
correlation as a public operator surface, prefer the dedicated public page
https://ota.run/docs/reference/semantic-snapshots-and-correlation after checking the local repo
sources above.
When the question is broader than one command or one receipt and you need the public architecture
loop itself, prefer https://ota.run/docs/reference/execution-governance-loop after checking the
local repo sources above.
When the active repo is ota-run/ota, also prefer the local core spec
docs/spec/semantic-snapshots-and-correlation.md for the shipped contract details behind:
receipt.contract_snapshot_hash
receipt.assumption_set_hash
ota receipt --snapshot
contract_changes[]
likely_related_changes[]
summary.comparison.correlation
Do not jump straight to public docs if the local repository already contains the canonical
answer. If the active repo is not the Ota repo, treat local repo files as evidence about that
project, not as Ota product documentation.
When the active repo is ota-run/ota, also inspect adjacent first-party repos when the task
touches their ownership boundary:
inspect ota-site when the task affects public install docs, public contract docs, public
examples, onboarding guidance, or anything the docs site promises to operators
inspect ota-run/skills when the task affects first-party agent-skill guidance, contract
authoring behavior, or the public skill installation story
Do this only when the task really crosses that boundary. Do not turn routine Ota implementation
work into a mandatory three-repo read.
Bootstrap flow
Always prefer using the real Ota binary when it is available.
Check whether ota exists.
If it is missing, ask for approval before installing it.
Use the official install commands only:
macOS / Linux:
curl -fsSL https://dist.ota.run/install.sh | sh
Windows PowerShell:
irm https://dist.ota.run/install.ps1 | iex
when teaching repo-authored bootstrap truth, prefer structured agent.bootstrap.ota.source
over raw shell strings:
kind: version for released proof
kind: git_rev for deterministic unreleased proof
kind: branch only for active pressure testing
when a repo already declares agent.bootstrap.ota.source, apply the canonical mapping
directly instead of guessing:
kind: version
shell:
curl -fsSL https://dist.ota.run/install.sh | OTA_VERSION=<version> sh
when a GitHub Actions job needs direct ota commands and the repo already declares
agent.bootstrap.ota.source, prefer the first-party
ota-run/setup@v1 action with source: contract over duplicating OTA_VERSION,
OTA_GIT_REV, OTA_GIT_BRANCH, or --from-git in workflow YAML
when a repository declares contract-owned CI bootstrap or verification truth, add a dedicated
pull-request gate with ota-run/action@v1, command: doctor, , and
; it fails only on Ota-established CI bootstrap or verification drift,
not ordinary Doctor warnings. Keep it separate from general readiness reporting so the blocking
reason stays explicit.
Prefer the official install docs and repository references in
references/official-sources.md when you need canonical links.
Do not silently install Ota, install agent skills, modify shell profiles, or overwrite an existing
ota.yaml. Ask first unless the user explicitly requested that action.
Canonical command workflow
Use the smallest real Ota workflow that fits the task:
ota doctor
inspect readiness blockers, warnings, next actions, and agent guidance
use ota doctor --fix --dry-run to preview the currently shipped deterministic fix lane
use ota doctor --fix when the repo truth should allow safe deterministic repair such as
repo-hygiene cleanup or native command-acquired tool activation; plain ota doctor should
stay non-mutating
do not use mutating ota doctor --fix to route around replay-input admission. When an active
replay-input policy is unavailable, evaluates to deny or review, or a declared hard pin is
unavailable or mismatched, Ota refuses before repo-hygiene or tool-activation mutation.
ota doctor --fix --dry-run remains a non-mutating preview
ota init
create a starter contract only when the user wants Ota adoption or no contract exists
prefer the emitted starter shapes Ota now owns directly: toolchains.*,
prepare.kind: dependency_hydration for setup, and command for simple finite task bodies
ota detect
inspect deterministic repo evidence before broadening a contract
treat ota detect --write as the conservative first-write lane, not the full starter lane
when reviewing a detect-written contract, read metadata.ota.detect.field_ownership together
with metadata.ota.detect.field_admission so direct detector-owned writes are not confused
with conservative starter-policy promotions
for AGENTS.md / CLAUDE.md pressure, keep the boundary explicit:
structured external boundary lists may be admitted as detect evidence, narrow labeled command
sections and bounded structured command tables inside those command sections may be admitted
as low-authority task guidance, including exact | Task | Command | and adjacent
| Command | description | forms under headings such as Commands, Individual Commands,
Common Commands, Quick Reference Commands, Build/Test Commands, and
Build & Development Commands when ota can still recover a stable canonical task name from
the command itself or from a bounded task label such as , , or ; placeholder-heavy command templates like ,
, or obvious scaffolding should stay ignored because they are guidance,
not runnable task truth; prose should stay ignored, and Ota-generated agent docs from
should be treated as self-origin guidance and excluded from detect evidence,
including older generated docs that only say ./ota.yaml`.by ota agents` marker
If a contract already exists, start with ota doctor and ota validate before editing it.
If the repository has no contract yet:
inspect the smallest real operational surface
model the minimum truthful contract
validate it
only then broaden the contract if real repo truth requires it
For agent, Studio, CI, or other integration surfaces, prefer Ota JSON output (--json) or documented
schemas. Do not parse rich human output unless no machine-readable surface exists, and call that out
as an Ota platform gap.
When reading receipt/proof machine output, prefer explicit stage ownership over inferring from
labels:
receipt.steps[*].stage_family carries the broad governance family
ota proof runtime --json carries stage_family: "proof" alongside the finer proof phase
ok is execution/readiness success only. It is necessary but insufficient for proof breadth;
consumers must read proof_verdict with not_proved[].
use ota proof runtime --json --archive when a runtime proof must later support a governance
claim. Then read ota doctor --jsonclaim_assurance[]: proof breadth is supported only by a
content-addressed witness archive matching current semantic contract, clean source identity, and
resolved execution scope; a matching failed proof is contradicted and stale evidence is unknown.
use ota proof lifecycle --workflow <name> --json --archive only for a workflow that declares
proof.lifecycle over manager-owned services. The runner first executes the normal workflow
prerequisite closure, then either leases manager-observed inactive services or creates one
transaction-bound ephemeral container session for a declared boundary_terminated service.
It starts and readies the dependency closure, optionally runs one finite assertion, then
finalizes in reverse order even after a failed start, readiness failure, assertion failure, or
interrupted child.
When declared, the typed assertion record carries the terminal task state, exit code, and
bounded runner-captured output tails for diagnosis; it does not turn that output into broader
application proof. A manager-reported pre-existing or unknown-state service is never stopped.
The archive is local,
content-addressed evidence bound to the semantic contract snapshot, selected scope, transaction,
service records, and terminal verdict; it does not support claim assurance, CI projection, or a
broader runtime/application proof.
lifecycle proof reuses selected-workflow --agent, --mode, and --member admission. The
selected mode applies to prerequisite and assertion tasks. Replay-input admission evaluates the
exact workflow prerequisite-plus-assertion closure before any lifecycle task, service
transition, or assertion starts. Runtime proof similarly includes its post-readiness seam
observers and selected negative-control task, then admits before creating .ota/proof artifacts
or spawning its child runtime. A refused machine result carries
execution_started: false with the hard-pin and active policy evidence. A
boundary_terminated service requires structured
/ commands and resolving to an ephemeral
context; Ota runs those commands inside its session and attests removal of that exact session.
Machine consumers must require the same in archive scope and every isolated
service record. A failed removal is attested as incomplete cleanup, never promoted to
, host-manager inactivity, or application output. Native generic host
start/stop remains ineligible until it has a typed state observer.
Contract authoring workflow
When creating or refining a contract:
Identify the real operational truth with the minimum repo reading needed:
setup path
runtime dependencies
env sources and required vars
service and readiness ownership
canonical tasks
agent-safe boundaries
Model only what is actually true today.
Keep the contract minimal but complete enough that:
ota doctor is useful
ota up has a clear path
ota run executes named tasks honestly
Prefer contract fields over repo-local helper scripts when Ota already supports the
behavior cleanly.
Prefer these concrete shapes when repo truth matches them:
use aggregate for finite task grouping instead of fake run: "true" bodies
use command.cwd when the task truth is still one finite executable plus stable argv but it
should run from a repo subdirectory instead of hiding cd ... && ... in shell
use launch.kind: command for long-running service processes instead of opaque run
when a supported long-running server adapter would otherwise duplicate bind flags already owned
by explicit runtime.listeners, use launch.runtime_projection so ota projects bind argv from
canonical runtime listener truth instead of repeating --host / --port, -b / -p, or
Next.js --hostname / --port in launch.args; use the nextjs adapter with a direct
structured next dev invocation rather than a package-script wrapper that owns those flags
use tasks.<name>.compose when the repo truth is a finite docker|podman compose
lane ota should own directly, whether that is an in-service exec/run/attach command or a
staged compose up, compose build, compose restart, compose rm, compose logs, or
project-scoped compose down task; use
omitted compose.engine to use the default Docker Compose CLI, or set compose.engine: podman
when the same body should execute through Podman Compose; use
compose.detach: true only with compose.kind: exec or compose.kind: up, keep
compose.rm: true only with compose.kind: run, keep
compose.build: true only with compose.kind: run for one-off service shells that must
rebuild the selected service image before execution, keep
compose.service_ports: true only with compose.kind: run for one-off service shells that
must publish the service's declared ports, keep compose.force_recreate: true only with
compose.kind: up, keep only with , keep
only with , keep
only with for , keep
only with for , keep
for //, and use for staged
, , , ,
, , or
Before editing:
preserve existing user intent in ota.yaml
make the narrowest complete contract change
update docs/tests only when command behavior, schema shape, or published examples change
validate with ota validate and, when useful, ota doctor
Author from evidence, not vibes. Before writing or broadening a contract, inspect the smallest
set of repo files that reveal real behavior:
package/build manifests (package.json, workspace files, lockfiles, language manifests)
CI workflows that show canonical install, build, test, and smoke paths
compose/container files only when the workflow actually needs services or containers
existing scripts that users already run successfully
Keep scope honest. If the contract only models one slice of a large repo, say that in
project.description, workflow descriptions, and the final response. Do not make a partial
contract sound like full production readiness.
Default modeling areas:
project
execution.contexts
toolchains, runtimes, and tools
env.sources and env.vars
services and readiness
tasks
workflows
checks
agent
When deciding where something belongs, prefer:
toolchains for managed ecosystem ownership such as Node/Corepack/pnpm or Rust/rustup
runtimes for direct runtime presence/version checks not owned by a toolchain
tools for standalone command checks not owned by a toolchain
env for runtime config truth
services for declared managed services and readiness ownership
checks for operator-facing blockers and warnings
tasks for named execution paths
workflows for canonical user-facing paths through prepare/setup/run/readiness
agent for safety and automation boundaries
Do not duplicate ownership across toolchains, runtimes, and tools. If a package manager,
runtime, or command is owned by a declared toolchain, task requirements may select it, but top-level
runtime/tool ownership should not be duplicated.
Requirements should live at the narrowest truthful owner.
use context-level requirements only when every task in that context genuinely needs them
prefer task-level requirements for most tool/runtime ownership
keep pure action.kind:*, file-prep, env-prep, and other deterministic non-runtime tasks free of
heavyweight inherited requirements unless they actually execute that tool
when a file action, env action, or other finite host prep lane fails only because a context
inherited Docker, Node, Python, or another heavyweight tool, treat that as a contract issue first
and tighten the owner boundary before changing the workflow
Preferred modern contract shapes
When the repo truth supports them, push toward these shapes explicitly:
finite verification grouping:
aggregate.tasks for verify, ci, and other bounded parent tasks
long-running services:
launch.kind: command plus runtime.kind: service and surfaced readiness
package-manager truth:
Node package managers under toolchains.node.package_managers
Composer-backed PHP dependency hydration through prepare.source.kind: composer
uv under toolchains.python.package_managers.uv when uv owns Python dependency setup/run
uv-backed Python dependency hydration through prepare.source.kind: uv
Poetry under toolchains.python.package_managers.poetry
Bundler under toolchains.ruby.package_managers.bundler
deterministic setup:
prepare.kind: dependency_hydration instead of ad hoc install shell bodies where Ota already
owns the manager lane
prepare.kind: sequence when one setup task must compose multiple structural finite steps
action.kind: ensure_container_network when shared external Docker network ownership belongs
to one finite standalone setup task
action.kind: reset_compose_service_volume when one destructive local reset lane owns one
Compose-managed service volume reset and restart sequence
env and compose truth:
env.sources, env.vars, env_files, ensure_env_file, workflow-owned env rendering, and
adapter_inputs.overlays.compose.env_files / adapter_inputs.overlays.bake.files for adapter-owned input
truth before resorting to inline shell glue
OTA_HOST_WORKSPACE, OTA_HOST_UID, and OTA_HOST_GID when a native or compose task
truthfully needs the real host repo path or Unix user/group ids for deterministic env
interpolation; do not fall back to shell pwd, id -u, or id -g glue when ota already
owns that lane
adapter_inputs.overlays.compose.cwd / when compose or Bake truth lives in a
repo subdirectory and the task would otherwise need shell or
glue
Prefer the strongest truthful contract surface, not the broadest valid YAML surface.
When the contract could be modeled more than one way, choose by owner boundary:
use prepare.kind: sequence when the lane is still structural setup such as dependency or
image hydration and those steps share one honest setup owner
use action.kind: ensure_bundle when the lane is deterministic setup built from action
primitives such as env/file prep plus shared Docker network bootstrap
use action.kind: ensure_git_checkout when the lane is deterministic repo-local Git
materialization, including optional declared remote reconciliation, and should stay on the same
governed setup surface as file/env prep instead of shell bootstrap glue
use action.kind: ensure_container_network when the lane is deterministic external Docker
network bootstrap and should stay machine-readable as its own setup lane
use action.kind: reset_compose_service_volume when the lane is a destructive local
Compose-managed service-data reset and should stay explicit instead of disappearing into shell
use workflows.<name>.prepare.task when that bootstrap step deserves reuse or its own task
identity; use workflows.<name>.prepare.action when the workflow itself owns it directly
keep steps as separate finite tasks when they need distinct reuse, separate requirements/effects,
or independent operator entrypoints
For fuller holistic shapes, also use:
references/workflow-service-patterns.md for workflows, services, env modeling,
requires_services, context-bound execution, and post-run hooks
references/agent-and-governance-checklist.md for agent, checks, effects, proof posture,
and CI/version-floor governance
references/execution-governance-capability-map.md when you need the dedicated public
reference, evidence boundary, and copy-ready example for safe execution, CI projection,
sandboxing, proof, replay, claim assurance, crossings, or semantic snapshots
references/pressure-testing-protocol.md before selecting, modeling, or declaring a pressure
repo complete; it defines the required proof matrix, Ota-gap review, and first-party
propagation decision
the public examples repo when a compact copy-ready surface is better than prose alone:
reference/bake-adapter-inputs, reference/action-ensure-env-file,
reference/action-ensure-bundle, reference/action-ensure-git-checkout,
reference/action-ensure-container-network, and
reference/compose-adapter-inputs
Known regression traps
Watch for the concrete regressions we have repeatedly seen in pressure-test repos:
runtime.kind: service paired with opaque run instead of launch.kind: command
supported server launch adapters still duplicating bind flags in launch.args even though
explicit runtime.listeners already own the canonical bind host/port and
launch.runtime_projection should carry the translation
fake aggregate bodies such as run: "true" where aggregate should own the task shape
aggregate membership smuggled through depends_on instead of aggregate.tasks
Poetry declared under tools.poetry when it actually owns Python dependency truth
mixed-ecosystem setup script bodies where prepare.kind: sequence should own the lane instead
raw uv sync or uv pip install -r ... setup bodies in Python repos where first-class
prepare.source.kind: uv now exists
raw npm install or non-lockfile setup when the repo truth is npm plus package-lock.json
invalid generic native package fields where explicit manager-owned package fields should own
fulfillment or policy truth
public CI or proof workflows pinned to an older Ota build than the contract surface they execute
env-file ownership baked into shell commands when first-class env surfaces can own that truth
compose interpolation files modeled as process env_files instead of
tasks.<name>.adapter_inputs.overlays.compose.env_files
compose or Bake subdirectory truth still buried in shell cd ... && docker ... glue or
docker compose --project-directory ... instead of adapter_inputs.overlays.compose.cwd or
adapter_inputs.overlays.bake.cwd
fake host alias tasks such as typecheck:host or build:host where one task identity plus
execution.modes.<mode>.depends_on should own the plane-specific prerequisite truth
Bake file selection buried in shell docker buildx bake -f ... flags instead of
tasks.<name>.adapter_inputs.overlays.bake.files or
workflows.<name>.adapter_inputs.overlays.bake.files
missing metadata.ota.minimum_version on any contract, especially a published example; a
contract that uses newer Ota parsing or runtime behavior must not rely on an implicit version
floor
Production-readiness gates
When the user asks whether an Ota contract is solid, production-ready, PR-ready, or suitable for a
serious OSS repo, evaluate these gates explicitly:
Scope honesty: the contract description and workflow names match the repo slice actually modeled.
Deterministic setup: CI/proof install paths use lockfile-respecting commands where the repo
supports them.
Bounded agent defaults: agent.default_task, agent.safe_tasks, and verify_after_changes
prefer finite verification tasks over long-running dev loops.
Refusal controls: when a repo has an unsafe publish, deploy, or release lane, declare it under
agent.refusal_canaries and prove the real runner boundary with
ota run --agent --expect-refusal <task> or
ota up --agent --expect-refusal --workflow <workflow>. Do not model this as a shell test or
declare an expected reason: Ota must derive the refusal from the current closure.
Ce SKILL.md est tres volumineux, SkillsMP affiche donc ici seulement la premiere section.Voir sur GitHub
source: contract
fail-on-ci-drift: true
when a repository wants Ota to own the CI verification lane itself, generate a dedicated
provider-neutral contract lane with ota ci projection --workflow <name> --mode <mode> --target-os <linux|macos|windows> --json,
then generate the GitHub reusable workflow with ota ci github render --workflow <name> --mode <mode> --target-os <linux|macos|windows> and use
ota ci github check and explicit ota ci github sync against an Ota-owned output and a
human-owned caller. Keep triggers, permissions, runners, secrets, environments, deployment,
and non-Ota jobs in the caller; never duplicate Ota bootstrap or verification commands there.
Generated lanes retain full workflow agent admission across prepare, setup, run, and attach
roots. A workflow that declares proof still must be agent-admitted; proof breadth is not
execution authority, and proof-required lanes use the runtime-proof wrapper as their sole
real execution path. Finite verification lanes use a dry-run ota up admission preview,
then execute their selected dependency closure directly through ota run --agent;
service-runtime lanes retain their single
runtime-owned execution path. Every declared
agent.refusal_canaries control is projected as its own generated provider check and executed
through Ota's --expect-refusal boundary. GitHub qualifies the check name by target OS and
mode while retaining its canonical merge identity; do not replace those checks with provider
shell/JQ glue. Required selected-closure toolchains are projected from ota.yaml; GitHub
carries execution_scopes per selected toolchain and renders immutable Go setup for native
source: go, translating supported lower-bound ranges into Go release selectors, native Node
setup for toolchains.node with source: corepack, native Ruby setup for
toolchains.ruby with source: ruby, native Python plus uv setup for
toolchains.python with source: uv, and native .NET setup for toolchains.dotnet with
source: dotnet. Container and remote toolchains remain owned by their
declared runtime boundary. It refuses unsupported native sources instead of trusting a hosted
runner image.
Ota also refuses any target OS that the selected executable closure or resolved context does
not support. Omit --mode only when the contract default is intended; an explicit unavailable
mode must be treated as a projection refusal. Read JSON refusal projections rather than scraping error
text. The caller must bind both the exact projection identity and the projection target OS;
Ota verifies the identity without relying on a provider shell.
once agent.bootstrap.ota.source exists, treat explicit workflow-owned Ota install truth as
governance drift unless the lane is an intentional unreleased pressure path; ota doctor
should be allowed to call out that duplication or conflict
After install, use real Ota commands instead of hand-wavy advice.
Run all unit tests
Run type checking
Format code
<PROJECT>
<tests>
path/to/...
ota agents
Generated from \
without the newer
ota validate
verify structural and semantic contract correctness
ota diff
compare semantic contract truth, including archived receipt-backed snapshot inputs
ota receipt --snapshot ...
inspect archived normalized semantic contract truth directly
ota receipt --json --baseline ...
compare current receipt state against archived baseline truth and read contract-drift
correlation when the baseline carries snapshot identity
on repos with more than one declared workflow, keep archive, baseline, and snapshot selection
scoped with ota receipt --workflow <name> ... instead of relying on repo-global latest or
promoted receipt history
receipt history verifies the archived snapshot reference and identity, never the current
worktree. Authority-bearing execution archives also bind a canonical selected-invocation scope
that history re-derives before accepting crossing evidence. legacy_unverified entries remain inspectable but cannot become baselines, proof
inputs, or crossing-authority evidence
read summary.comparison.correlation first, then contract_changes[], then
likely_related_changes[]
read baseline.evaluated_inputs[], current.evaluated_inputs[], and
summary.comparison.artifact_trust[] only as receipt-authored evidence. A matching
typed Node lockfile currently acquits declared_dependency_resolution only. A static
digest-pinned Compose image for an explicitly selected service and its declared depends_on
closure in an explicitly declared file acquits only its selected_runtime_artifact. The paired
runtime:node version record only narrows selected_runtime_version; never replace any of
these with a later filesystem read or over-read them as environment or external-state proof
expect sharper declared owners such as reusable surfaces.<name> or
readiness.probes.<name> to outrank weaker adjacent workflow references when Ota can recover
them honestly
use tasks.<name>.replay_inputs only for immutable repo files a deterministic selected lane
actually consumes; Ota captures their identities before the full closure starts and treats a
match as narrowing evidence, never as proof that runtime or external state was unchanged
add expected_identity: sha256:<64 lowercase hex characters> only when that file must be
independently pinned. Ota blocks the selected closure before execution when the observed
content differs; never let Ota or an agent rewrite the pin automatically
use policies.replay_inputs.identity.tasks|workflows when an org policy must require complete
pins for selected replay-sensitive closures. Task rules follow reachable execution closure,
including recursive after_success, after_failure, and after_always hooks; workflow and
reachable task rules are cumulative. Both deny and review refuse before native
provisioning, dependency hydration, or task startup today. Unavailable observations, active
policy load failures, and missing, unreadable, or mismatched declared pins always fail closed
and cannot be weakened to review. Mutating ota doctor --fix applies the same refusal before
repo-hygiene or native tool-activation mutation. Read replay_input_policy from Doctor,
dry-run, and admission-produced run/up execution or refusal receipts; hard-pin refusals retain
the active policy record, while generic readiness receipts do not reconstruct policy after
execution. Each task-qualified replay input is observed once for command admission, and that
command-scoped observation set drives findings, policy evaluation, hard-pin validation, and
receipts. Agent safety, claim assurance, replay admission,
Doctor/provisioning findings, proof, CI projection, and receipt policy evidence reuse one
loaded policy snapshot per command. Runtime proof pins that admitted authority for its
detached child and reuses the command-scoped preflight across readiness diagnosis and its
embedded Doctor artifact. CI projection carries
requirements and the canonical execution closure including recursive hooks, not render-host
observations, so the provider checkout recomputes observed identities
use artifacts.<name>.replay when a generated fixture, store, model baseline, or existing
generated_source needs an explicit regeneration authority chain. Keep kind: generated_source
when that lineage already exists; do not duplicate output ownership. A generated_source
consumer with a top-level producer dependency remains ordinary generated-source execution;
omit that dependency only for an offline promoted-replay consumer. A dedicated
replay_baseline always consumes promoted authority. Run ota baseline record --artifact <name>
from a clean Git source tree to execute its declared producer through the explicit recording
boundary and issue a receipt-bound attestation. A dedicated replay_baseline producer is not
agent-safe; an additive generated_source producer keeps its ordinary task safety posture.
Review the generated output, then select that exact record with
ota baseline promote --artifact <name> --attestation <path>. The committed authority manifest
embeds the selected attestation and declares SCM review as its external trust root; Ota does not
verify reviewer inclusion or signer provenance. Never
hand-edit a digest or auto-promote the newest recording. Replay-baseline symlinks must resolve
within declared artifact outputs, never into the mutable worktree.
Use consumption: read_only only with an enforceable ephemeral container boundary for the
full selected closure; Ota mounts a run-scoped snapshot outside the writable workspace and
projects command-capable typed preparation through that same boundary without replacing it
with shell glue. Use
consumption: verify_unchanged when native replay must remain available: Ota detects a changed
baseline after the task and emits replay_artifact_mutation_detected, but does not claim it
refused the write or upgrade that posture to read-only enforcement.
replay consumers must not depend on the baseline producer. consumption: read_only requires
an enforceable runner-owned ephemeral container boundary; native or persistent execution is
refused rather than approximated with mutable worktree checks or file permissions
within tasks.<name>.replay_inputs, use kind: static_file for generic immutable repo files,
kind: presentation_profile for files that define output-shaping or normalization posture, and
kind: comparator_profile for files that define equivalence, tolerance, or comparison rules
use tasks.<name>.witnessed_observations.query_traces for prior-run JSONL query evidence;
Ota preserves these as attested observations in the receipt, never as current-run evaluated
inputs. A divergent identity names changed query shape only; it does not establish causality.
ota tasks
discover named task surfaces
prefer ota tasks --use when you need the runnable lane itself, including Human Run,
closure-aware Agent Run, Agent Policy, command preview, and modes in stable Container,
Native, then Remote order with the selected lane marked (Default), plus effect surface
plus required inputs and dry-run / receipt follow-up commands; use plain ota tasks for the
full declaration view. Unavailable Container or Native planes must be shown explicitly, and a
declared-safe task is agent-callable only when its full dependency closure is callable
for machine consumers, use ota tasks --json and read tasks[].use.modes[] as the canonical
per-mode human/agent capability matrix; use.human and use.agent remain compatibility
projections of the selected default mode, while availability: unavailable is contract
support truth rather than a substitute for environment readiness checks
prefer ota tasks --safe --use first for agent-oriented execution because it keeps the
routine runnable surface bounded before you decide whether any non-safe lane needs review
ota run <task>
execute canonical task flows
treat explicit mode, lifecycle, host-port, memory, and dependency overrides as capability
requests, not hints. If Ota refuses one, inspect ota tasks --use and the dry-run blocker;
never retry by assuming an unsupported override was approximately applied
native or remote task paths without a managed shared backend cannot honor --ephemeral or
--persistent; use the declared native/remote path or select an advertised container mode
ota up
prepare the repo into a ready state
task-backed workflow phases use the same execution-option admission as ota run and must
refuse unsupported overrides before prepare/setup/run execution starts
manager.start
manager.stop
--mode container
boundary_identity
boundary_terminated
use workflows.<name>.proof.claim: bounded for a real archive-backed verification lane that has
no declared dependency seam, such as an offline replay, build, or deterministic test gate. It
creates a bounded proof_breadth claim, not a repo-wide pass: Doctor remains unknown until a
matching archive exists. Do not invent seam_observations or negative controls merely to opt in.
proof_verdict is the terminal selected-lane result: treat
passed_with_unproven_boundaries as a qualified proof, never as repo-global completion; parse
or contract-load failures do not enter that proof carrier
proof_scope is the canonical machine-readable boundary for the selected runtime path; do not
read a green runtime proof as repo-global success
not_proved[] is relative to proof_scope: treat entries with source: contract_lane and
declared_by_workflows[] as contract-declared adjacent paths, matched through declared external
state, that were not exercised; source: proof_scope is the generic broader-repo remainder for
that narrow proof
For governance previews, a preflight refusal remains post_execution.state: not_run because
execution never began. Read post_execution.refusal_occurred, its refusal record, and
not_run_reason: preflight_refusal together; do not infer that no refusal happened from a
non-executed lane.
dependency_exercise_not_proved names a requires_services seam in the selected proof closure
that Ota did not independently observe crossing. It is not a service failure or unused-service
claim; do not upgrade it to exercised from reachability, a caller trace, or a green proof.
A marker-bound workflows.<name>.proof.seam_observations[] observer is the first honest path to
exercised: Ota gives the opaque marker to a declared producer in the selected closure, never
to the finite observer. The observer must recover it through the dependency and write the
runner-owned transaction attestation. Ota records exercised only after verifying that
attestation before teardown. Keep producer and observer prerequisites inside the normal workflow
closure; do not claim exercise from an unrun, inert, or prose-only observer.
A workflows.<name>.proof.negative_controls[] entry is the only path to fault_tested. It must
reference one observed seam obligation, stay outside the normal closure, and declare a typed
expected_failure. The finite control receives transaction and attestation coordinates, not a
caller-authored verdict; a generic non-zero exit is invalid until Ota verifies the matching
same-obligation failure attestation.
Every marker-bound seam retains dependency_output_shaping_not_proved, whether its evidence is
exercised or fault_tested; absence is reserved for a future explicit output-proof carrier.
The nested dependency-level negative-control object is a self-describing
evidence_class: derived projection of the canonical control record, not a second authority.
Use the public ota-run/examples/reference/runtime-proof-evidence example when authors need a
copy-ready producer, observer, and negative-control pattern. Keep that evidence on
ota proof runtime; generic readiness and receipt lanes did not execute the proof obligation.
artifact_routing[] points to the next receipt/proof artifact or capture command with typed
role, kind, and stage_family
receipt comparison summary.comparison.artifact_trust[] is runner-derived and scoped to the
named input class. A matching semantic_contract_snapshot is acquitting for
contract_truth only; it does not clear dependency, environment, runtime, or external-state
drift that the receipts did not capture
a matching receipt-authored typed Node lockfile is likewise acquitting only for
declared_dependency_resolution; it proves the declared lockfile identity matched between
receipts, not that ambient registry, runtime, env, or external-state inputs were unchanged
a matching receipt-authored static digest-pinned Compose image is acquitting only for its
named selected_runtime_artifact, including the selected service's declared depends_on
closure; mutable tags, interpolation, inferred Compose files, and unrelated stack services do
not produce this evidence
a matching receipt-authored runtime:node version is narrowing for
selected_runtime_version; it does not establish binary, image, host, environment, or
external-state identity
For ota run <task> --dry-run --json, prefer top-level provisioning and provisioning_request
when present instead of scraping plan.requirement_lines; that selected-path provisioning truth is
the machine-readable host-fulfillment surface for direct tool acquisition.
Full ota run --dry-run --json and ota up --dry-run --json previews carry
execution_started: false. On run override refusal, read overrides together with
summary.primary_blocker.code; on up refusal, read blockers[].code. Do not treat resolved
execution metadata as evidence that the requested backend or lifecycle actually started.
Also prefer the additive top-level governance block for the selected lane’s safety posture,
review requirement, runnable mode commands, effect surface, and receipt follow-up command instead
of reconstructing those facts from task text or from the raw requested_task payload by hand.
For harness-facing callable truth, prefer ota tasks --json or ota workflows --jsoncapability_profile over hand-built agent policy:
read preflight for the canonical callable vs refused decision
read environment_boundary for declared writable/protected path posture
read additive sandbox_policy for the first compiled runtime target, codex_local
treat sandbox_policy.filesystem.state: "compiled" as derived from declared
agent.writable_paths / agent.protected_paths
prefer canonical runtime_boundary truth when present on execution, workflows.<name>, or
tasks.<name>; sandbox_policy.filesystem.source / network.source tells you which selected
lane actually owns the compiled boundary
treat sandbox_policy.filesystem.state: "unavailable" as insufficient declared boundary truth,
not as an implicit allow
treat sandbox_policy.network.default: "deny" / scope: "none" and
default: "allow" / scope: "broad" as the current honest broad effect posture; do not invent
host or destination allowlists that the contract does not yet declare
when sandbox_policy.network.scope: "targeted", consume declared outbound_targets[] directly
and keep enforcement: "advisory_only" honest unless an identified provider can apply and attest
every authoritative target constraint
distinguish compiled posture from applied enforcement: codex_local remains advisory, while
ota run <task> --agent --sandbox-target oci_local and the matching ota up lane may enforce
the supported subset only for an explicit-platform ephemeral container selection
treat container.platform as canonical for every selected execution-backend container creation,
task variant, input, environment, service binding, and requirement, not as a sandbox-only
annotation; the current backend accepts Linux OCI targets only, and oci_local requires the
explicit pin instead of inferring it from the runner host
before recommending oci_local, verify the selected path needs only the shipped controls:
read-only repository root, existing writable carve-outs, protected-path write refusal, bounded
external IP-network denial, and cleanup of Ota's exact boundary; targeted egress, inherited
service networks, managed isolated paths, image-declared volumes, undeclared mounts,
runtime-control sockets, native execution, and unsupported path aliases refuse
require a finite run, script, or command body with no task requirements, required services,
or conditional checks. The first provider refuses typed prepare/action/Compose/launch/attach
bodies and other pre-boundary work rather than claiming that a later container covered it
read dry-run sandbox_admission for capability/refusal truth and executed
witnessed_observations.sandbox_application for runner-authored application, terminal inspection,
policy-authority/overlay linkage, and cleanup evidence; never infer enforcement from task success
or the compiled profile alone
do not expect dry-run to start a provider boundary merely to probe runtime/tool availability.
Real OCI execution performs provider-backed precondition probes only inside the registered
sandbox application transaction, binds each to the exact admitted segment that owns the
requirement, records it as a cleanup-confirmed precondition_probe invocation, and retains that
terminal evidence on a blocking refusal. Probe evidence never satisfies task-execution evidence
do not reuse one task identity as both a dependency and a hook or across separate workflow
phases in an enforced lane; give each invocation a distinct task identity so receipt segments
cannot collapse different execution phases
treat the automatically archived receipt as selected-lane evidence only. It does not prove
application output, repo-global safety, host-wide isolation, or raw-shell execution outside Ota
when a contract references governance.crossing_authority.authority_id, keep the authority
boundary outside the repository. Never add a public key, signed bundle, sequence state, or
caller-selectable trust path to ota.yaml; the first prebound_file carrier resolves those only
from fixed root-owned system state. That carrier is guarded from Ota's current unprivileged
process, not provider-attested privilege separation: authority_separation_posture: current_process_filesystem_guarded does not prove the invoking job lacks administrative
escalation. The provisioner owns the Linux trust store at
/etc/ota/crossing-authorities.json; its binding points to separately protected signed bundle
and sequence-state files, normally under /var/lib/ota/. See the
Prebound Crossing Authority
before proposing this bounded carrier. Never self-provision it from a GitHub-hosted workflow
before live grant pressure on a controlled runner, use ota authority inspect --json as the
canonical read-only hardening diagnostic. Require every required observation to be passed
and retain informational unknown capabilities as explicit boundaries. The command selects no
grant, writes no authority/high-water state or receipt, and proves only
current_process_filesystem_guarded; do not treat its matched profile as crossing authority or
provider/launcher attestation
for controlled GitHub Actions pressure, use a dedicated Linux/x64 VPS and register its
unprivileged ota-runner account as a repository-scoped self-hosted runner with one protected
scenario label. The administrator builds the exact reviewed Ota commit outside the job, keeps it
root-owned at an administrator-controlled absolute path, and publishes a root-owned manifest
binding the full commit and binary SHA-256. The workflow must invoke that absolute path rather
than inheriting PATH. Archive that manifest check, ota --version --json, and ota authority inspect --json.
Do not treat the version command's abbreviated commit as full source-identity proof or give
ota-runner sudo, Docker, signing keys, or authority-write access. The complete
sequence is in Prebound Crossing Authority
use crossing authority only for a derived heavier non-agent closure. prebound_file uses
ota run <task> --grant <id> or the matching ota up form. On Unix, authority_broker
automatically selects exactly one protected binding matching the contract's authority_id;
optional --grant <authority-id> is only a non-secret label check, never a lease. Broker dry-run
reports requires_live_authorization without launcher contact, while real run/up consumes one
exact lease after deterministic admission and before provisioning or work. If consume
acknowledgement is uncertain, Ota re-queries the exact durable intent only after
fresh launcher attestation, closes the abandoned transaction as incomplete for every verified status,
and never resumes its work; a new execution requires fresh authorization. Ordinary workflow
selected instance, ordered prerequisite-instance closure, readiness timeout, and runner-derived
closure/effect/resource breadth are authority-bound; public breadth uses counts, categories, and
hashed resource identities rather than raw values. Archives retain a public verification binding,
never the protected live launcher descriptor. Signed
protocol evidence permits only bounded non-secret invocation, principal, and mount labels.
Selected proof commands retain one proof-owned terminal transaction across their complete
invocation set. Proof invocation role and declaration order, lifecycle selected-service closure,
target platform, host-port, memory, dependency selection, and normalized runtime readiness
timeout are scope-bound. Runner-private authority travels only between immediate Ota processes
over a bounded Unix descriptor and is removed before selected code executes. Runtime and
lifecycle archives embed and re-derive terminal authority rather than inheriting an ordinary
workflow grant.
Routine lanes reject an inapplicable grant, and agent-unsafe lanes remain refused under --agent
even when a grant exists
on a production Linux systemd Launcher deployment, inspect independently retained execution
evidence with ota receipt --history --source systemd_protected_launcher --json. The fixed
protected service derives repository/catalog selection from the admitted operator peer and
administrator mapping, and returns the exact archive, immutable contract snapshot, and
finalization sidecar for Core semantic re-verification. Never add a path, --file, or OTA_FILE
override, never read protected blobs directly, and never fall back to local history after a
protected-source refusal. Use --archive-identity <sha256:...> only to select one exact archive
and use https://ota.run/docs/reference/broker-crossing-authority for the canonical operator
deployment, fixed-layout, ownership, and trust-boundary reference
read successful dry-run crossing_grant_admission and executed
receipt.crossing.authority as exact signed admission evidence. Real execution must also carry
a terminal receipt.crossing.authority.transaction created before selected-lane mutation;
refusal and dry-run create no crossing transaction or crossing record. Missing, stale, revoked,
rolled-back, or out-of-scope authority refuses before provider/setup/task mutation
inspect refused task dry-run crossing_grant_admission or workflow-refusal
receipt.refusal for typed prebound_file authority source, selected authority/grant, stable
reason, and execution_started: false. Both runner-derived scope carriers expose scope and
contract identities, boundary family, and classification for external issuance. The workflow
receipt keeps its refusal boundary separate through scope_boundary_family and
scope_classification; never reconstruct either semantic scope in CI glue or treat refusal
evidence as a crossing record
keep the local transaction claim bounded:
authentication_posture: runner_local_content_addressed means runner-authored, locked, and
internally reconciled; it does not authenticate the journal against same-user writes to
.ota/state
do not add free-form task inputs to a signed-file grant lane. The first carrier refuses that
unresolved identity rather than hashing or exposing potentially secret input values
keep carrier claims bounded. The signed-file carrier is short-lived offline authority under
current_process_filesystem_guarded. The Unix broker carrier verifies challenge-bound launcher
attestation and atomically consumed one-use authority. Immutable v1 evidence remains
launcher_attested_one_use. A strict v2 protected-launcher binding additionally requires one
exact protocol-published profile, every ordered required observation verified,
content-addressed launcher/configuration identities, and a separate attestor key authority
before it can emit protected_launcher_attested_one_use. The protected binding itself must carry
schema_version: 2; an unversioned binding remains v1. Neither posture invents provider,
human, CI, or host-isolation claims outside the signed evidence. V1 and v2 binding, payload,
domain, and archive branches are mutually exclusive; never upgrade v1 by defaulting v2 fields.
The additive Linux systemd V3 branch requires the exact closed launcher V3 and job-principal V2
profiles. Immutable Linux/x64 PID 1 pressure run
31664495937
proves completed, failed, interrupted, replay-refused, and crash-recovered selected execution.
Core completion remains separate from launcher cleanup: Core's archive binds admission, one-use
consumption, semantic scope, and the terminal crossing transaction. Protected post-cleanup
recovery adds producer signatures over cleanup and the exact archive
association. Signed launcher-owned transaction schema v3 requires broker-archive schema v2 and
portable finalization verification. Core publishes the archive atomically and durably; the root
launcher requires execution-principal-owned 0700 archive directories, verifies and publishes
the exact sidecar, and retains the exact terminal until its identity-bound acknowledgement. The
job principal never reads the private receipt directory.
Historical transaction v2 evidence is not upgraded. Immutable Linux/x64 PID 1 run
31758094819 proves the pressure-only portable-finalization and crash-recovery path, including
schema-v2 recovered child absence without false exit or reaping claims. Do not call the pressure
client a production operator attachment surface. Immutable Linux/x64 PID 1 run 31823037642
proves the separate installed production client and least-privilege protected-history source
against exact Protocol, Core, and Launcher revisions, with one valid and zero invalid protected
archive and no private signing material. Independently administered Linux/x64 PID 1 run
31939777636 separately proves the consumer-only positive path with a pre-provisioned protected
runner, one consumed work unit, exact terminal cleanup, one valid protected archive, and zero
invalid archives. Immutable Linux/x64 PID 1 run 31953535665 separately proves the
administrator-driven execution-completion, finalization-intent, and terminal-recorded reboot
matrix against exact Protocol, Core, and Launcher revisions, with three valid protected archives,
zero invalid or legacy archives, unchanged repository state, and complete terminal cleanup.
Provider attestation remains open.
Use the
Broker Crossing Authority
for its fixed binding and launcher boundary. Bounded protected-launcher v2, execution-disabled
systemd V3, selected execution, portable finalization, and production attachment/history pressure
are green. The independently administered positive hardened-launcher and administrator-driven
reboot/fault-recovery branches are also green and satisfy the bounded V11.7 OSS slice.
Provider-specific attestation remains optional stronger hardening rather than an implied systemd
property or V11.7 completion gate.
For dependency-plane truth, prefer preview plan.dependency_steps[], executed
receipt.dependency_steps[], and validate warning_details[].provenance instead of inferring
backend selection from task names or advisory prose.
For interactive workspace automation with ota workspace doctor --json --progress-json,
ota workspace check --json --progress-json, ota workspace diff --json --progress-json,
ota workspace status --json --progress-json, ota workspace receipt --json --progress-json,
ota workspace run --json --progress-json, ota workspace up --json --progress-json, or
ota workspace refresh --json --progress-json, keep one output contract boundary explicit: final
machine JSON stays on stdout, while live NDJSON workspace progress events stream on stderr. Do not
treat stderr progress as the final roll-up payload, and when workspace task bindings are in play
expect progress events that carry command plus, when relevant, both task and repo_task
before the final receipt or repo report lands. Prefer additive phase plus stage_family
instead of inferring operational meaning from status text alone. For ota workspace status and
ota workspace receipt, expect tail to carry the repo drift state, and for
ota workspace diff, expect status to carry the diff verdict while tail carries the machine
drift_kind.
compose.force: true
compose.kind: rm
compose.follow: true
compose.kind: logs
compose.remove_volumes: true
compose.kind: down
compose down -v
compose.timeout_seconds: <seconds>
compose.kind: down
compose down -t <seconds>
compose.service
exec
run
attach
compose.services[]
compose.kind: up
compose.kind: build
compose.kind: stop
compose.kind: restart
compose.kind: rm
compose.kind: logs
compose.kind: ps
use launch.kind: compose when the repo truth is a long-running docker|podman compose up
runtime start rather than a finite Compose lane; keep host-side Compose cwd, env-file, file,
profile, and project-name ownership under adapter_inputs.overlays.compose.*, then keep only
launch.engine, launch.action: up, optional launch.services[], and optional
launch.detach: true under launch
when a native structured Docker Compose lane owns one published host URL and operators may need
one-run --host-port overrides, keep the Docker command/task truthful and declare
runtime.listeners.<name>.project.publication.compose.service so ota can remap the published
host port without changing the internal bind port or editing compose YAML
for a direct native task with fixed bind and fixed projected host-port truth, a one-run
--host-port selection updates both the workload bind and projected host port; Ota reprojects
supported typed launch arguments and canonical runtime env rather than pretending native
execution has a separate publication boundary
use launch.cwd when the service-start truth is one executable plus stable argv rooted in a
repo subdirectory instead of hiding cd ... && ... in shell
use prepare.kind: dependency_hydration for dependency setup instead of raw package-manager
install commands when Ota can own the lane truthfully
when that typed setup lane must run inside a declared repo orchestrator such as devbox or
devenv, use execution.orchestrator.mode: exec on command-backed
prepare.kind: dependency_hydration or prepare.kind: tool_bootstrap; do not pretend mixed
native prepare.kind: sequence can be orchestrator-mediated until Ota has a step-level model
when prepare.source.kind: docker_compose owns image hydration, keep Compose file selection and
interpolation input on prepare.source.files / prepare.source.env_files instead of burying
docker compose -f ... --env-file ... pull ... in raw shell; declare
prepare.medium: container_images, explicit image targets, requirements.tools.docker,
effects.network: true, and effects.network_kind: container_image_hydration. Use the same
effect kind for a Compose up or launch.kind: compose lane that may pull declared images, and
keep immutable image receipt evidence separate from the registry-access declaration
when that typed dependency lane truthfully runs inside a declared Compose service, keep the
package-manager truth under prepare.source.kind: ... and add prepare.source.compose only as
the service wrapper; in that shape the host requirement stays requirements.tools.docker or
requirements.tools.podman, not a duplicate host language toolchain
if you need one concrete contract shape for that lane, point authors at the dedicated reference
example reference/task-prepare-compose-hydration instead of making them infer it from the
broader Compose adapter example
when the durable install state for that Compose-wrapped lane lives in a service volume instead
of a repo path, declare it under effects.adapter_state with a token such as
compose_volume:node_modules or compose_volume:bundle_data instead of faking repo writes
for source.kind: bundler, keep source.path only when the repo truth is a repo-local gem
lane such as vendor/bundle; omit it for compose-wrapped lanes that truthfully use the
container-default Bundler path and declare the durable state under effects.adapter_state
use source.kind: composer under prepare.kind: dependency_hydration for PHP dependency setup
instead of raw composer install; keep durable install state such as vendor under
effects.writes, or use effects.adapter_state when the lane is Compose-volume-backed
use source.kind: node_package_manager with manager: yarn, mode: install, and
inline_builds: true when the repo truth is yarn install --inline-builds instead of leaving
that lane as raw shell
use source.kind: node_package_manager with manager: npm, mode: install or mode: ci,
and force: true only when the repo truth is explicitly npm install --force or
npm ci --force; treat that as an exceptional override lane, not the normal npm default
treat typed dependency hydration as stronger governance, not weaker safety: it removes
replaceable install-shell drift, but the task still needs honest requirements, effects,
writable-path boundaries, and usually remains outside routine agent.safe_tasks because the
networked setup blast radius is still real
use prepare.kind: tool_bootstrap when the task truth is contract-owned tool installation
rather than repo dependency hydration; the shipped slices are bootstrapping uv through
source.kind: pip with explicit source.exe, plus Node package-manager browser bootstrap
through prepare.tool: playwright_browsers or prepare.tool: cypress_browsers
treat typed tool bootstrap the same way: it removes replaceable shell drift, but keep
effects.network_kind: tool_bootstrap explicit and do not pretend unattended tool installation
is automatically routine agent-safe execution
use effects.network_kind: integration_test for live, staging, or remote-backed verification
lanes that depend on real services or non-local credentials; keep requirements.env and any
real effects.external_state explicit, and do not treat those paths as routine agent.safe_tasks
use effects.network_kind: service_readiness for a finite assertion against one declared
repo-managed service endpoint; pair it with requires_services and do not over-read it as
external integration coverage
use prepare.kind: sequence when one honest finite setup lane needs more than one typed setup
step in order, including structural prepare steps (dependency_hydration, tool_bootstrap) and
deterministic bootstrap steps such as ensure_env_file, ensure_file, ensure_directory,
ensure_git_checkout, ensure_git_template, ensure_container_network, or reset_compose_service_volume
use action.kind: ensure_env_file when one honest setup lane is deterministic env-file
bootstrap or normalization
use action.kind: ensure_git_checkout when one honest setup lane owns clone-if-missing
materialization of a sibling or vendored repo checkout instead of hiding git clone plus
optional git checkout or deterministic remote-wiring shell glue in a helper script
use action.kind: ensure_git_template when one honest setup lane owns deterministic scaffold or
factory materialization from a Git-backed template instead of hiding git clone, inherited
.git removal, and fresh git init glue in a helper script
use action.kind: ensure_container_network when one honest setup lane owns shared external
Docker network readiness as a standalone lane instead of shell docker network inspect/create
glue
use action.kind: build_container_image when one direct task truthfully owns Dockerfile-backed
local image materialization for a declared container or Compose lane; keep file, context,
tag, Docker external state, and any network posture explicit instead of hiding docker build
in a shell command, and do not place image builds inside prepare.steps or ensure_bundle
use action.kind: reset_compose_service_volume when one destructive local recovery or reset
lane truthfully owns stopping a Compose-managed service, removing one declared volume, and
restarting the service instead of hiding docker compose stop/rm plus docker volume rm
shell glue in the task body
use action.kind: ensure_bundle when one honest setup lane owns more than one deterministic
setup action and would otherwise become shell orchestration glue
use workflows.<name>.prepare.action when the workflow itself honestly owns one finite
deterministic host bootstrap action or bundle and a reusable helper task would only be glue
use manager-specific native prerequisite package lanes (apt, brew, winget, choco,
scoop) when the repo wants Ota-owned host package fulfillment or org-policy approval
keep those manager lanes aligned to the OS platform entry they live under instead of mixing
likely wrong-OS package-manager lanes into the same native prerequisite platform
avoid mixing opaque install shell glue with manager-owned native package lanes on the same
platform entry when the shell command is only there for host package installation
use lockfile-strict npm hydration with manager: npm and mode: ci when the repo truth is npm
plus package-lock.json
use source.kind: maven or source.kind: gradle under
prepare.kind: dependency_hydration for Java setup instead of raw mvn ... or gradle ...
shell; set wrapper: true when the repo truth is mvnw or gradlew, and use
mode: go_offline plus skip_tests: true when the real setup lane is
mvn -q -DskipTests dependency:go-offline
use source.kind: cargo under prepare.kind: dependency_hydration for Rust setup instead of
raw run: cargo fetch
use source.kind: dotnet_restore under prepare.kind: dependency_hydration for .NET setup
instead of raw run: dotnet restore; when the repo owns NuGet feed selection in NuGet.Config,
declare source.config_file and let ota up --json recover resolved feed identities instead of
duplicating those URLs as source.sources[] command overrides. Read the resulting typed
receipt.evaluated_inputs[]hydration_provenance record rather than re-reading NuGet.Config
after the run. Treat resolution: unavailable as narrowing evidence, never a hermetic replay
anchor; when an ephemeral container
restore must feed later dotnet build --no-restore or dotnet test --no-restore tasks, declare
attachments.isolated_paths: [.nuget/packages] on that context so Ota owns one shared NuGet
package cache through derived NUGET_PACKAGES
use source.kind: helm under prepare.kind: dependency_hydration for Helm chart setup instead
of raw helm dependency build ... command or shell glue
use source.kind: composer under prepare.kind: dependency_hydration for PHP setup instead of
raw run: composer install
use tools.<name>.platforms.<os>.acquisition for standalone CLI ownership when the repo truth is
a host package-manager lane such as Helm via apt, brew, winget, choco, or scoop;
keep that CLI in tools instead of splitting it into native_prerequisites
use tools.<name>.acquisition.provider: release_asset when the truthful standalone CLI owner is
one exact downloadable binary artifact or release archive and ota should own that selected-path
source directly in the contract instead of hiding it in shell glue or org policy only
use tools.<name>.acquisition.source_config when that package-manager-backed or release-asset
standalone CLI also needs source truth such as a Brew tap, Winget source, Chocolatey feed, Scoop
bucket, apt sources list, asset_by_platform release URLs, or archive extraction metadata such
as archive.format: tar_gz / zip plus archive.executable_path
use source.kind: uv under prepare.kind: dependency_hydration for uv-backed Python setup
instead of raw run: uv sync or raw uv pip install -r requirements.txt shell
declare default_index, ordered indexes[], and offline: true when package-source or
cache-only posture materially affects replay or supply-chain trust; do not let user/global uv
configuration silently stand in for contract-owned source truth
use mode: pip_local_project with local_project.path, explicit editable, ordered
extras[] / groups[], and optional lockfile when the repo installs one checked-out Python
package; Ota records manifest, lockfile, and clean local-project source identity rather than
preserving those installs as opaque shell glue. Treat the record as replay-acquitting only when
resolved hydration posture, declared lockfile identity, and clean source identity all exist;
otherwise matching evidence is narrowing only.
use action.kind: ensure_virtualenv when the repo truthfully owns deterministic creation of one
repo-local Python virtualenv such as .venv, and keep dependency installation itself under
prepare.kind: dependency_hydration
use toolchains.python.package_managers.poetry instead of standalone tools.poetry when Poetry
owns Python dependency truth
use ${OTA_HOST_HOME} when truthful instance or runtime input ownership depends on one host-home
clone or cache root instead of shell echo $HOME / %USERPROFILE% glue
use first-class env ownership such as env_files, ensure_env_file, workflow-owned env
materialization, adapter_inputs.overlays.compose.env_files for compose interpolation truth, and
adapter_inputs.overlays.bake.files for Bake file selection truth instead of baking adapter flags and
shell rewrite glue into task commands
use checks[].kind: file instead of shell test -f ... / test -d ... glue for deterministic
filesystem assertions; keep the default repo-bound scope for in-repo paths and use
checks[].scope: workspace only when the real contract truth depends on a sibling relative input
such as ../task-sdk/schema.json
use canonical effects.external_state tokens when the task mutates out-of-repo systems;
prefer shipped vocabulary such as docker, postgres, redis, mysql, mariadb, kafka,
rabbitmq, elasticsearch, opensearch, s3, gcs, azure_blob, cloudflare,
kubernetes, or terraform instead of repo-local aliases like docker_compose,
postgresql, or k8s
use adapter_inputs.overlays.compose.cwd / adapter_inputs.overlays.bake.cwd when the truthful compose or Bake
working directory is a repo subdirectory instead of burying cd ... && docker ...,
cd ... && podman ..., docker compose --project-directory ..., or
podman compose --project-directory ... glue in task bodies
use services.<name>.manager.engine: podman plus command.exe: podman / launch.exe: podman
when the repo truth is podman compose rather than teaching Podman as a Docker-shaped shell
variant
use services.<name>.manager.kind: host with manager.host.kind: systemd plus
readiness.kind: systemd_active when the repo truth is a host-managed systemd unit rather than
shell systemctl start / stop / is-active glue
use canonical workflows.<name>.adapter_inputs.overlays.compose.* when one workflow should own the
adapter root, base compose file stack, compose profile set, or project naming across its
selected compose task closure, instead of repeating that truth in task-local adapter inputs
use tasks.<name>.variants.<i>.env, .env_files, .env_bindings, .inputs,
.requirements, or .adapter_inputs when one task keeps the same body but needs an
OS-scoped process, prerequisite, or adapter overlay such as Linux-only host uid/gid
interpolation, service-derived URLs, input defaults/allowed values, platform-specific tool
requirements, Compose files, env files, or profiles; do not clone the whole task body into
shell-only variants just to express input drift
use workflows.<name>.instances when one workflow is really a named runtime family such as
ws0, ws1, or preview; select it as workflow@instance instead of cloning pseudo-workflows
use workflows.<name>.instances.generated.<family> when that runtime family has a bounded
repeated selector range such as ws1..ws8 and the repeated overlays should stay on the
existing instance boundary instead of being duplicated across many explicit named instances
use workflows.<name>.instances.<instance>.topology.requires_instances when one selected
instance truthfully needs another instance up first, such as ws1+ requiring ws0
use workflows.<name>.instances.<instance>.env for selected-instance host-clone or cache roots,
and use workflows.<name>.instances.<instance>.tasks.<task>.adapter_inputs for instance-specific
compose project naming or other adapter-owned runtime inputs
use workflows.<name>.instances.<instance>.tasks.<task>.runtime when one selected service task
keeps the same runtime identity but needs instance-specific listener bind/project ports or
readiness listener selection; treat it as a strict overlay on the base task runtime instead of
inventing a workflow-local listener model
generated instance templates may interpolate ${OTA_WORKFLOW_INSTANCE} and
${OTA_WORKFLOW_INSTANCE_INDEX} in string-valued overlay fields, and may derive repeated
surface/runtime ports with port_stride / stride instead of falling back to shell math
use workflows.<name>.adapter_inputs.overlays.bake.* when one workflow should own the adapter root
or base Bake file stack across its selected docker buildx bake task closure instead of
repeating that truth in task-local adapter inputs
use adapter_inputs.overlays.helm.* or workflows.<name>.adapter_inputs.overlays.helm.* when one
task path or workflow owns Helm chart root, values-file selection, release naming, or namespace
truth instead of hard-coding Helm positionals or --namespace flags in argv
treat adapter_inputs.overlays.<family> as a generalized contract surface with a strict shipped
boundary: runtime semantics currently exist for compose, bake, and helm, and unsupported
families should be called out as not yet shipped rather than modeled as if they execute
every ota.yaml must declare metadata.ota.minimum_version, including all published and local
example contracts; set it to the lowest Ota release that can honestly parse and execute the
contract, not merely the version currently installed
adapter_inputs.overlays.bake.cwd
cd ... && docker ...
docker compose --project-directory ...
workflows.<name>.adapter_inputs.overlays.compose.* when compose file selection, compose profile
selection, project naming, or adapter-root ownership belongs to the workflow rather than one
isolated task body
workflows.<name>.adapter_inputs.overlays.bake.* when Bake file selection or adapter-root
ownership belongs to the workflow rather than one isolated task body
release/governance truth:
metadata.ota.minimum_version on every contract, with the lowest honest compatible release
pressure workflow truth:
separate contract/dry-run coverage lanes from real runtime proof lanes
execute heavyweight runtime paths once per meaningful proof lane instead of re-running the same
expensive task through task, aggregate, and workflow entrypoints in one job
only run setup or runtime tasks on matrix lanes that truthfully advertise the required host
capabilities
materialize declared file/env/setup prerequisites before broad task dry-run enumeration when the
task surface depends on those artifacts
context-level heavyweight requirements such as docker, node, or python that accidentally
make pure file/env/action tasks unrunnable on contract-only lanes
pressure workflows that dry-run or execute tasks before materializing declared file/env bootstrap
truth such as ensure_env_file, copy_if_missing, or other deterministic setup lanes
pressure workflows that prove the same heavyweight runtime lane multiple times in one job through
direct task execution, aggregate execution, and workflow execution without gaining new coverage