6.8 KiB
6.8 KiB
Distribution Contract for codex-controller-loop
v1 Contract
This document defines the first stable, versioned distribution contract for the Rust controller binary. It is the canonical compatibility and consumption reference for external projects.
1) Contract version and release identity
- Contract version:
distribution-contract@1.0 - Release artifact identity is immutable for a given tuple:
artifact_version(semver)git_rev(full SHA, immutable reference)toolchainandbuild_profiletargetdist_revision(incrementing revision when rebuilds occur for the same release tuple)
- Consumers must pin by immutable tuple, never by moving tags.
2) Canonical artifact entrypoint
- Primary entrypoint:
codex-controller-loopCLI. - Canonical binary names:
codex-controller-loop(single binary)
- Canonical distribution entrypoint index:
dist/index.json. - Deprecated compatibility entrypoint (removed after 2026-07-01):
dist/{distribution_contract_version}/index.json.
3) Canonical dist layout and naming
dist/is the only published artifact namespace.- Directory template (contract version stable):
dist/{distribution_contract_version}/{artifact_version}/{target}/{profile}/{toolchain}/{gitsha}/{dist_revision}/- Example:
dist/1.0.0/0.1.0/x86_64-unknown-linux-gnu/release/1.84.0/ab12cd34/r1/
- Canonical artifact filename:
codex-controller-loop-v{version}-{target}-{profile}-{rust}-{gitsha}-{dist_revision}.{ext}version= semver release (e.g.1.4.2)target= Rust target tripleprofile=releaseordebugrust= rustc version string used in buildgitsha= short git commit hash of source revisiondist_revision=r1,r2, ... for immutable re-build iterationsext= container format used by release pipeline (e.g.tar.gz)
- Canonical generator entrypoint:
scripts/release-orchestrator.py(single orchestrator)- Controlled by
scripts/release-orchestrator.config.json - Index manifest output:
dist/index.json
- Deterministic provenance snapshot in generated index:
- Each index artifact row is keyed by
version + target + profile + toolchain + gitsha + dist_revision artifact_file,manifest_file,checksums_file,artifact_sha256, andsource_date_epochare emitted
- Each index artifact row is keyed by
8) Consumer integration examples
Use the canonical index first, then fail fast if no rows match the requested immutable tuple. Optional legacy fallback is accepted only during migration.
VERSION=0.1.0
TARGET=x86_64-unknown-linux-gnu
PROFILE=release
TOOLCHAIN=1.84.0
GITSHA=ab12cd34
DIST_REVISION=r1
INDEX=dist/index.json
if [ ! -f "$INDEX" ]; then
INDEX=dist/1.0.0/index.json
echo "warning: using deprecated index path, remove by 2026-07-01"
fi
ARTIFACTS=$(jq -r --arg version "$VERSION" --arg target "$TARGET" --arg profile "$PROFILE" \
--arg toolchain "$TOOLCHAIN" --arg git "$GITSHA" --arg dist "$DIST_REVISION" \
'.releases[] | select(.version==$version) | .targets[] | select(.target==$target) | .profiles[] | select(.profile==$profile) | .artifacts[] | select(.toolchain|startswith($toolchain)) | select(.git_rev|startswith($git)) | select(.dist_revision==$dist) | .artifact_file' "$INDEX")
COUNT=$(printf "%s\n" "$ARTIFACTS" | awk 'NF {count += 1} END {print count + 0}')
if [ "$COUNT" -ne 1 ]; then
echo "expected exactly one artifact for immutable tuple" >&2
exit 1
fi
ARTIFACT_FILE=$(printf "%s" "$ARTIFACTS")
echo "resolved artifact: $ARTIFACT_FILE"
PACKAGE_DIR="${ARTIFACT_FILE%/*}/package"
CHECKSUMS="$PACKAGE_DIR/checksums.json"
python - <<PY
import hashlib, json, pathlib
artifact = pathlib.Path("${ARTIFACT_FILE}")
checksums = json.loads(pathlib.Path("${CHECKSUMS}").read_text())
actual = hashlib.sha256(artifact.read_bytes()).hexdigest()
if actual != checksums["artifact_sha256"]:
raise SystemExit("artifact checksum mismatch")
print(f"artifact sha256: {actual}")
PY
4) Release compatibility matrix
| Platform | OS | Arch | Binary compatibility | Runtime assumptions | Notes |
|---|---|---|---|---|---|
| Linux | Linux | x86_64 / aarch64 |
Recommended | UTF-8 locale and terminal (TTY) | Required for TUI rendering |
| macOS | Darwin | aarch64 / x86_64 |
Recommended | UTF-8 locale and terminal (TTY) | Build validation expected |
| Windows | Windows | x86_64 |
Planned / not guaranteed | UTF-8 locale and terminal (TTY) | Future support candidate |
- Rust compatibility: Release pipelines are required to document exact
rusttoolchain versions per artifact. - Source compatibility is guaranteed only for the same
distribution_contract_versionandartifact_versiontuple.
5) Checksums and integrity
- Every release artifact must include
checksums.json,manifest.json, andprovenance.json. - All checksums use SHA-256.
- Consumers treat a release as valid only if:
- Artifact checksum matches manifest entry.
- Manifest has reproducibility metadata matching expected tuple (version, target, profile, toolchain, git rev).
6) Retention and migration
- The canonical contract file is immutable once published for a release version.
- Backward compatibility matrix changes require a migration note in the contract changelog.
- Deprecated/removed platform support is announced via the changelog and removed only after a deprecation cycle.
- Contract index migration note:
dist/{distribution_contract_version}/index.jsonis a temporary compatibility alias and is retired on 2026-07-01.
7) Changelog and compatibility governance
- Compatibility assumption changes require a changelog entry in
docs/distribution-changelog.md. - Contract fields are first-class API: any consumer-facing contract change must update:
docs/distribution.mddocs/distribution-contract.jsondocs/distribution-changelog.md
8) Source-of-truth documents
Machine-readable contract file: docs/distribution-contract.json
The JSON contract is the machine-readable interface; this ADR should be treated as the human-readable interpretation.
9) Operational governance and release hygiene
- Release ownership handoff is explicit and bounded:
- The active release steward must own the distribution contract updates for the PR.
- Ownership is transferred only after
docs/distribution.md,docs/distribution-changelog.md, anddocs/distribution-contract.jsonare updated together. - Handoff requires at least one release cycle of overlap so downstream consumers have a recovery window.
- Deprecation workflow is fixed:
- Legacy index path support remains for the documented minimum notice period.
- Any compatibility assumption change requires a changelog entry and a migration step before sunset.
- Minimum retention window:
- Keep at least six release generations in the contract retention policy.
- Do not remove deprecated aliases before the contract's documented notice date and retention cleanup policy are both met.