Reference
Ownership Layers
The canonical ownership model for ecosystem capability truth, repo-level orchestration, simple runtimes, standalone commands, and native prerequisites.
Recommended next
Purpose
Use this page to decide where prerequisite truth belongs.
The canonical split is capability-first for toolchains and mediation-first for orchestrators.
The goal is one owner per capability and one explicit repo execution story.
toolchainsown required ecosystem capability truth.orchestratorsown repo-level trust, prepare, and mediated task execution.runtimesown simple unmanaged runtime checks.toolsown standalone commands on PATH.native_prerequisitesown host-native build bundles and shell activation.
Ownership rule
Pick the highest useful owner and do not repeat the same capability below it.
toolchainsare capability-first:versionsays what the repo needs, whilefulfillmentsays how ota may fulfill it on the selected path.orchestratorsdo not replacetoolchains; they model repo-level trust, install, and selected task execution.- Current shipped toolchain names are
toolchains.rust,toolchains.node,toolchains.java,toolchains.python,toolchains.go,toolchains.ruby, andtoolchains.dotnet. - Current shipped canonical fulfillment sources are
rustup,corepack,sdkman,uv,go,ruby, anddotnet. - Legacy toolchain
provideris still accepted for compatibility, but it is not the canonical public model. - If a declared toolchain owns the capability, do not also declare it under
runtimesortools.
Command behavior
ota doctordiagnoses selected toolchains and orchestrators without mutation.ota doctor --jsonandota check --jsonexpose additive selected-pathtoolchains[]evidence so automation can see the chosen fulfillment source, backend, target OS, fulfillment mode, and owned capabilities.ota up --dry-runshows selected toolchains before execution.fulfillment.mode: nonemeans diagnose only;fulfillment.mode: runmeans ota may provision the selected toolchain on the selected run path.tasks.<name>.execution.orchestratormakes mediated execution first-class instead of burying repo truth inrun: mise ...shell strings.
toolchains: rust: fulfillment: source: rustup node: fulfillment: source: corepack java: fulfillment: source: sdkman python: fulfillment: source: uv go: fulfillment: source: go ruby: fulfillment: source: ruby dotnet: fulfillment: source: dotnetWhen to use each layer
Toolchain
A managed ecosystem capability such as Rust, Node, Java, Python, Go, Ruby, or .NET.
Example
Orchestrator
A repo-level manager such as mise that mediates trust, install, and selected task execution.
Example
Runtime
A simple language/runtime version requirement with no managed ecosystem ownership.
Example
Tool
A standalone command on PATH.
Example
Before and after
Without the canonical model, repo truth often disappears into setup shell strings.
tools: mise: "*" tasks: setup: run: mise trust && mise install server:verify: run: mise run //server:ci-unittoolchains: node: version: "24.15.0" package_managers: pnpm: "10.33.4" fulfillment: source: mise mode: run orchestrators: mise: kind: mise required: true config_files: - mise.toml activation: trust: true prepare: install: true tasks: server:verify: run: //server:ci-unit execution: orchestrator: ref: mise mode: taskTask requirement examples
Task requirements should select the owner that actually applies to the selected path.
tasks: setup: requirements: toolchains: - nodetasks: start: requirements: runtimes: node: ">=24"tasks: docker:proof: requirements: tools: docker: ">=27"tasks: install: requirements: native: - node-native-build-toolsDuplication boundaries
Duplicate ownership is invalid contract drift, not extra safety.
- Reject
toolchains.nodeplusruntimes.nodeortools.nodeon the same contract. - Reject
toolchains.pythonplusruntimes.pythonon the same contract, and rejecttoolchains.python.package_managers.poetryplustools.poetrywhen Poetry ownership is explicit. - Reject toolchain-provided components such as
rustfmtwhen they are also modeled as standalone tools. - Keep one owner for the selected capability and remove the duplicate location instead of carrying parallel truth.
Fulfillment behavior
Capability truth and fulfillment truth are separate on purpose.
ota validatevalidates contract shape only.ota doctordiagnoses missing or mismatched toolchains without mutation.ota up --dry-runshows the exact fulfillment action before execution.- Supported
fulfillment.modevalues today are onlynoneandrun. - Use
fulfillment.mode: nonewhen ota should only diagnose/check the toolchain truth and never provision it on the selected path. ota upand selectedota runmay provision only whenfulfillment.mode: runis declared and policy permits it.- Use
fulfillment.mode: runonly when the selected repo path should let ota own fulfillment through the declared source. - Default fulfillment should be
mode: none, so inspection commands never silently download or mutate.
toolchains: rust: version: "1.94.0" components: - rustfmt fulfillment: mode: nonetoolchains: rust: version: "1.94.0" components: - rustfmt fulfillment: source: rustup mode: runCurrent shipped examples
These examples use only the canonical public model.
toolchains: rust: version: "1.94.0" profile: minimal components: - rustfmt - clippy targets: - x86_64-unknown-linux-musltoolchains: node: version: "24.15.0" package_managers: pnpm: "10.33.4" fulfillment: source: corepack mode: runtoolchains: java: version: "21" fulfillment: source: sdkman mode: run tools: maven: "*"toolchains: python: version: "3.12" package_managers: uv: "*" fulfillment: source: uv mode: runtoolchains: go: version: "1.24" fulfillment: source: go mode: runtoolchains: ruby: version: "3.3.11" package_managers: bundler: "2.5" fulfillment: source: ruby mode: runtoolchains: dotnet: version: "9.0" fulfillment: source: dotnet mode: runorchestrators: mise: kind: mise required: true config_files: - mise.toml activation: trust: true prepare: install: trueWhat this is not
- not a second task language
- not a place for arbitrary setup commands
- not a replacement for services or launch sources
- not the right home for Docker itself
- not the right home for OS-native build-tool bundles
Current shipped slice
- top-level
toolchains, top-levelorchestrators, and task-scopedrequirements.toolchainsare supported - Rust, Node, Java, Python, Go, Ruby, and .NET are the shipped toolchain names today
ota doctordiagnoses missing toolchains and orchestrators without mutation, and Ruby can govern Bundler throughtoolchains.ruby.package_managers.bundler- for
toolchains.rubywithfulfillment.mode: run, ota currently uses the selected Ruby to hydrate the declared Bundler lane structurally instead of treatingbundle installas shell glue - selected
ota run/ workflowota uppaths can provision shipped fulfillment sources plusfulfillment.source: misewhenfulfillment.mode: runis declared and policy allows it - duplicate ownership is invalid and fails validation
- Ota's own contract now uses this model instead of shell-based managed-surface setup