clawdie-iso/docs/RELEASE-BUILD-RUNBOOK.md
Sam & Claude 14248b6a20 feat(colibri): gate test-agent staging by build mode (Sam & Pi)
Add COLIBRI_STAGE_TEST_AGENT with dev/release defaults so validation builds can include colibri-test-agent while production/release operator USB images omit it by default. Keep poudriere guidance test-friendly and document binary roles in BUILD.md.\n\nValidation: sh -n build.sh scripts/stage-colibri-iso.sh live/operator-session/colibri-live-rebuild; ./scripts/check-format.sh; ./scripts/test-release-gate.sh; build.cfg default/override checks.
2026-06-21 07:55:24 +02:00

7.6 KiB

Release Build Runbook

Current target: 0.10.0 ("Operator Image") · Channel: release

How to cut a reproducible, publishable operator image from merged sources. This is the BUILD_CHANNEL=release path — distinct from the everyday BUILD_CHANNEL=dev integration build. Run it on the FreeBSD 15 build host; Linux can't produce the FreeBSD binaries.

For a throwaway integration image (current main, no clean-tree requirement), use BUILD_CHANNEL=dev and skip the pinning discipline below.


0. What a release build guarantees

  • Reproducible by record. The release gate refuses to build unless every staged source repo (clawdie-iso, clawdie-ai, colibri, zot) is a clean, committed tree (git status --porcelain — untracked files count). The exact commits are then written to build-manifest.json, so the image can be rebuilt from that record.
  • Own product version. ISO_VERSION is an explicit product number (0.10.0), not a component's. Component versions are provenance, not identity.
  • Fits the stick. The build aborts before shipping if the live filesystem has less than IMAGE_MIN_FREE_MB (default 1024) free.

Output: tmp/output/clawdie-quindecim-0.10.0.img (quindecim = FreeBSD 15).


1. Host prerequisites

  • FreeBSD 15 build host (root for the build; it mounts/loops the image).

  • Toolchains: Rust (cargo, rustc) for Colibri, Go for zot. See REQUIREMENTS.md.

  • Repos checked out side by side (the defaults assume ../colibri, ../zot, ../clawdie-ai relative to clawdie-iso, or /home/clawdie/ai/<repo>):

    <work>/clawdie-iso
    <work>/colibri
    <work>/zot
    <work>/clawdie-ai
    

Report host evidence in the release notes:

freebsd-version ; uname -a ; rustc --version ; cargo --version ; go version

2. Sync clean, merged heads

The gate requires every repo clean and on its intended commit. Do this for all four repos:

for r in clawdie-iso colibri zot clawdie-ai; do
  git -C "../$r" fetch --prune origin
  git -C "../$r" switch main && git -C "../$r" pull --ff-only   # or checkout the release ref
  git -C "../$r" status --porcelain   # MUST be empty
done

Any output from status --porcelain (modified or untracked) will fail the release gate. Clean it before continuing — do not .gitignore your way past it.

zot ships at a pinned tag. Check out the tag you intend to release (ZOT_VERSION, default v0.2.29) so the recorded commit is the tag's commit.


3. Build the artifacts (the ISO stages, never compiles)

# Colibri release binaries
cd ../colibri
cargo build --workspace --release
cargo test --workspace                       # green before release
cargo clippy --workspace --all-targets -- -D warnings

# zot agent binary (native FreeBSD build)
cd ../zot
git checkout v0.2.29                          # the release tag
ZOT_BUILD_VERSION="${ZOT_VERSION:-v0.2.29}"
VERSION="${ZOT_BUILD_VERSION#v}" make build
./bin/zot --version                            # expect: zot 0.2.29

cd ../clawdie-iso

build.sh preflight will hard-fail if any of these are missing:

ls -l ../colibri/target/release/colibri-daemon \
      ../colibri/target/release/colibri \
      ../colibri/target/release/colibri-mcp \
      ../zot/bin/zot

# Development/validation helper only; default release/prod images omit it.
[ "${COLIBRI_STAGE_TEST_AGENT:-NO}" != "YES" ] || \
  ls -l ../colibri/target/release/colibri-test-agent
# colibri-tui is optional (staged if present)

Building binaries does not dirty the repos (target/ and bin/zot are gitignored). If git status --porcelain is non-empty after building, something else changed — investigate, don't suppress.


4. Run the release build

cd ../clawdie-iso
sudo env BUILD_CHANNEL=release ISO_VERSION=0.10.0 \
  ./build.sh --clawdie-ref main
  • ISO_VERSION=0.10.0 — also the build.cfg default; an empty/auto value fails fast.
  • --clawdie-ref main bundles current clawdie-ai main (its commit is recorded as provenance). Use --clawdie-version X.Y.Z instead to pin a clawdie-ai tag. The gate does not require a tag — a recorded commit is enough.
  • Defaults that matter: FEATURE_COLIBRI=YES, COLIBRI_STAGE_AGENT=YES, COLIBRI_COST_MODE=smart. Override only with reason.

What you should see, in order:

  1. BannerISO : 0.10.0-release (zot v0.2.29).
  2. Release gate — silent on success; on failure it lists each modified repo and exits. (Fix the tree; don't switch to dev for a real release.)
  3. Preflight — confirms the colibri binaries and zot/bin/zot exist.
  4. Image space reportdf/du of the live filesystem, then Free space OK (… MB, floor 1024 MB) — or an abort if it won't fit.
  5. OutputDone : tmp/output/clawdie-quindecim-0.10.0.img.

5. Verify provenance

cat tmp/output/build-manifest.json        # or USB_SHARE copy

Confirm:

  • "iso_version": "0.10.0", "version_scheme": "product", "build_channel": "release".
  • zot_commit, colibri_commit, clawdie_ai_commit, iso_repo_commit are all real SHAs (not unknown).
  • Every *_modified flag is false (zot_modified, colibri_modified, clawdie_ai_modified, iso_repo_modified). A true here on a release means a tree was modified — the gate should have caught it; investigate.

6. Boot proof (the actual acceptance)

Boot the image in bhyve or on hardware and run docs/ISO-ACCEPTANCE-RUNBOOK.md. Minimum pass set for the milestone:

id colibri
service colibri_daemon status            # running, socket ready
colibri status                           # paths, cost.mode=smart, scheduler
colibri create-task --title "rc check"
colibri list-tasks --status queued       # contains "rc check"
service colibri_daemon stop              # socket + pidfiles cleaned up (SIGTERM path)
service colibri_daemon start             # restart works; no stale-socket clobber

XFCE: confirm the desktop comes up and is usable (the milestone's headline).

If anything fails out of the box, this is not the cut — fix, rebuild, and the rc1rc2 style iteration is the version number doing its job.


7. Publish

Follow skills/iso-publish/SKILL.md: compress to .xz, write the .sha256, and the publish manifest, then scripts/publish.sh to the CMS downloads jail. FLASHING.md is the operator-facing flashing guide (already references the 0.10.0 artifact name).


Acceptance checklist

  • All four repos clean (git status --porcelain empty) and on the release ref.
  • cargo test --workspace + cargo clippy -D warnings green on colibri.
  • BUILD_CHANNEL=release ISO_VERSION=0.10.0 ./build.sh completes; gate passed, preflight passed, free-space check passed.
  • build-manifest.json: channel release, all commits real, all *_modified false.
  • Booted image: colibri_daemon start/status/task/stop/restart clean; XFCE usable.
  • Published .xz + .sha256 + manifest; FLASHING.md accurate.

Notes / gotchas

  • Future cuts: bump ISO_VERSION in build.cfg (e.g. 0.10.1, 1.0.0). Everything else here is unchanged.
  • dev vs release: dev skips the clean-tree gate — fine for proving a change, never for a published artifact.
  • Live field repair: to rebuild Colibri on an already-booted USB without a full image rebuild, use colibri-live-rebuild (see docs/LIVE-COLIBRI-REBUILD.md). That is for validation, not release artifacts.
  • BUILD_CHANNEL is not the package channel. It marks artifact provenance; the future poudriere pkg repo's channel (latest/quarterly/signed) is a separate axis — don't conflate them.