Files
codex-controller-loop/docs/distribution.md
eric ebb6b488fe
Some checks failed
distribution-gate / distribution-gate (push) Failing after 1m56s
feat: 0.1.0
2026-04-04 18:41:34 +02:00

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)
    • toolchain and build_profile
    • target
    • dist_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-loop CLI.
  • 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 triple
      • profile = release or debug
      • rust = rustc version string used in build
      • gitsha = short git commit hash of source revision
      • dist_revision = r1, r2, ... for immutable re-build iterations
      • ext = 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, and source_date_epoch are emitted

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 rust toolchain versions per artifact.
  • Source compatibility is guaranteed only for the same distribution_contract_version and artifact_version tuple.

5) Checksums and integrity

  • Every release artifact must include checksums.json, manifest.json, and provenance.json.
  • All checksums use SHA-256.
  • Consumers treat a release as valid only if:
    1. Artifact checksum matches manifest entry.
    2. 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.json is 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.md
    • docs/distribution-contract.json
    • docs/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, and docs/distribution-contract.json are 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.