2026-06-14 15:29:09 +02:00
|
|
|
# FreeBSD Build Lane — ISO Validation Handoff
|
|
|
|
|
|
|
|
|
|
**For:** Codex (FreeBSD 15 host) · **Goal:** produce a Colibri-backed ISO
|
|
|
|
|
candidate and prove ISO Gate 1 (passive service) on real FreeBSD.
|
|
|
|
|
|
|
|
|
|
This is the runtime-proof step for **Priority 1** of
|
|
|
|
|
`PRIORITY-HANDOFF-ISO-SPAWN-COST.md`. The build-side wiring is already done on
|
|
|
|
|
Linux — `clawdie-iso build.sh` stages the Colibri binaries, installs the rc.d
|
|
|
|
|
script, creates the `colibri` user, and enables the service. What remains is
|
|
|
|
|
work only a FreeBSD host can do: build the FreeBSD binaries, run the image
|
|
|
|
|
build, boot it, and run the acceptance checks.
|
|
|
|
|
|
|
|
|
|
Linux agents cannot cross-compile the `x86_64-unknown-freebsd` binaries, so
|
|
|
|
|
this lane belongs to the FreeBSD agent end to end.
|
|
|
|
|
|
|
|
|
|
## 0. Host evidence to report
|
|
|
|
|
|
|
|
|
|
Run once and paste into the validation report:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
freebsd-version
|
|
|
|
|
uname -a
|
|
|
|
|
rustc --version
|
|
|
|
|
cargo --version
|
|
|
|
|
go version
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 1. Sources
|
|
|
|
|
|
|
|
|
|
Three repos must sit side by side (the ISO build defaults to `../colibri`):
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
# expected layout
|
|
|
|
|
# <work>/clawdie-iso
|
|
|
|
|
# <work>/colibri
|
|
|
|
|
# <work>/zot
|
|
|
|
|
git -C colibri pull --ff-only # or: git reset --hard origin/main
|
|
|
|
|
git -C clawdie-iso pull --ff-only
|
|
|
|
|
git -C zot pull --ff-only
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`colibri` main tip for this handoff includes the staged-env tests and the
|
|
|
|
|
ISO Priority 1 re-scope; `zot` provides the agent binary that the ISO version
|
|
|
|
|
auto-tracks.
|
|
|
|
|
|
|
|
|
|
## 2. Build the FreeBSD artifacts (host toolchains, not on the image)
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
# Colibri release binaries — staged by the ISO build, never compiled by it
|
|
|
|
|
cd colibri
|
|
|
|
|
cargo build --workspace --release
|
|
|
|
|
cargo test --workspace # confirm green on real FreeBSD; report output
|
|
|
|
|
cargo clippy --workspace --all-targets -- -D warnings
|
|
|
|
|
|
2026-06-14 15:45:57 +02:00
|
|
|
# zot agent binary (Go) — the agent has no FreeBSD release, so build it.
|
|
|
|
|
# This is the exact command clawdie-iso's preflight prints; ZOT_VERSION
|
|
|
|
|
# defaults to v0.2.29. Output must land at bin/zot (the ISO default artifact
|
|
|
|
|
# path). Check out the tag you intend to ship: ISO_VERSION auto-tracks the
|
|
|
|
|
# zot checkout via `git describe`, so the checked-out ref becomes the ISO
|
|
|
|
|
# version.
|
2026-06-14 15:29:09 +02:00
|
|
|
cd ../zot
|
2026-06-14 15:45:57 +02:00
|
|
|
git checkout v0.2.29
|
|
|
|
|
GOOS=freebsd GOARCH=amd64 go build -trimpath -o bin/zot ./cmd/zot
|
2026-06-14 15:29:09 +02:00
|
|
|
```
|
|
|
|
|
|
2026-06-14 15:45:57 +02:00
|
|
|
After both builds, these must exist (the ISO preflight checks each):
|
2026-06-14 15:29:09 +02:00
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
ls -l colibri/target/release/colibri-daemon \
|
|
|
|
|
colibri/target/release/colibri \
|
2026-06-15 07:35:44 +02:00
|
|
|
colibri/target/release/colibri-test-agent
|
2026-06-14 15:45:57 +02:00
|
|
|
ls -l zot/bin/zot
|
2026-06-14 15:29:09 +02:00
|
|
|
# colibri-tui is optional (staged if present)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 3. Build the image
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
cd clawdie-iso
|
|
|
|
|
sudo ./build.sh # FEATURE_COLIBRI defaults to YES
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`build.sh` will:
|
|
|
|
|
|
|
|
|
|
- `preflight_colibri_artifacts` — fail early if any of the three binaries above
|
|
|
|
|
are missing (it prints the exact `cargo build` command to fix it).
|
|
|
|
|
- `install_colibri_service` — run `scripts/stage-colibri-iso.sh` against the
|
|
|
|
|
image root, then `pw -R <root> useradd colibri` and write
|
|
|
|
|
`colibri_daemon_enable=YES` into the image.
|
|
|
|
|
|
|
|
|
|
Useful overrides (defaults are fine for a standard run):
|
|
|
|
|
|
|
|
|
|
- `COLIBRI_REPO=/path/to/colibri` if not at `../colibri`.
|
|
|
|
|
- `COLIBRI_ARTIFACT_DIR=...` if binaries live outside `target/release`.
|
|
|
|
|
- `COLIBRI_COST_MODE=smart|fast|max` (default `smart`).
|
2026-06-14 15:45:57 +02:00
|
|
|
- `ZOT_REPO=/path/to/zot` if not at `../zot`; `ZOT_ARTIFACT_DIR=...` if the
|
|
|
|
|
binary is not at `<zot>/bin/zot`.
|
|
|
|
|
- `COLIBRI_STAGE_AGENT=NO` to skip the zot agent (default `YES`, needs the
|
|
|
|
|
prebuilt `zot`); `FEATURE_COLIBRI=NO` to skip Colibri entirely (not for this
|
|
|
|
|
lane).
|
2026-06-14 15:29:09 +02:00
|
|
|
|
|
|
|
|
Output image name encodes the zot version, e.g. `clawdie-quindecim-<ver>.img`.
|
|
|
|
|
|
|
|
|
|
## 4. Boot and validate Colibri (ISO Gate 1)
|
|
|
|
|
|
|
|
|
|
Boot the image in a bhyve VM or on hardware, then run the full
|
|
|
|
|
`docs/ISO-ACCEPTANCE-RUNBOOK.md`. Minimum pass set:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
# pre-flight
|
|
|
|
|
id colibri
|
|
|
|
|
ls -l /usr/local/bin/colibri /usr/local/bin/colibri-daemon
|
|
|
|
|
ls -l /usr/local/etc/rc.d/colibri_daemon
|
|
|
|
|
sysrc colibri_daemon_enable
|
|
|
|
|
|
2026-06-15 07:35:44 +02:00
|
|
|
# lifecycle + checks
|
2026-06-14 15:29:09 +02:00
|
|
|
service colibri_daemon start
|
|
|
|
|
colibri status # paths, cost.mode, scheduler, tasks
|
2026-06-15 07:35:44 +02:00
|
|
|
colibri create-task --title "iso check"
|
|
|
|
|
colibri list-tasks --status queued # contains "iso check"
|
|
|
|
|
colibri intake-task --title "iso intake check" --capability freebsd
|
2026-06-14 15:29:09 +02:00
|
|
|
sleep 35 # one scheduler tick (~30s)
|
2026-06-15 07:35:44 +02:00
|
|
|
colibri list-tasks --status queued # contains "iso intake check"
|
2026-06-14 15:29:09 +02:00
|
|
|
service colibri_daemon stop # socket gone, SQLite remains
|
|
|
|
|
service colibri_daemon start && colibri list-tasks --status queued # persistence
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Confirm `cost.mode` matches the `COLIBRI_COST_MODE` baked at build time.
|
|
|
|
|
|
|
|
|
|
## 5. Validate the Hermes rc.d service
|
|
|
|
|
|
|
|
|
|
`hermes_daemon` is **not** staged by the clawdie-iso build (only Colibri is) —
|
|
|
|
|
install it manually from the `hermes-bsd` repo on the booted image (or any
|
|
|
|
|
FreeBSD host) per `hermes-bsd/README-FreeBSD.md`:
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
# one-time setup (from hermes-bsd checkout)
|
|
|
|
|
sudo pw groupadd hermes
|
|
|
|
|
sudo pw useradd hermes -g hermes -d /var/db/hermes -s /usr/sbin/nologin
|
|
|
|
|
sudo cp packaging/freebsd/hermes_daemon.in /usr/local/etc/rc.d/hermes_daemon
|
|
|
|
|
sudo chmod 555 /usr/local/etc/rc.d/hermes_daemon
|
|
|
|
|
sudo sysrc hermes_daemon_enable=YES
|
|
|
|
|
|
|
|
|
|
# missing-config abort: must fail cleanly, NOT crash-loop under daemon(8) -r
|
|
|
|
|
sudo service hermes_daemon start # expect exit 1 + clear "config not found"
|
|
|
|
|
|
|
|
|
|
# after `hermes setup` + `hermes model` write /var/db/hermes/config.yaml:
|
|
|
|
|
sudo service hermes_daemon start
|
|
|
|
|
sudo service hermes_daemon health # "healthy (pid N alive)"
|
|
|
|
|
sudo service hermes_daemon stop # supervisor exits, child does not respawn
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Confirm both the supervisor and child pidfiles under `/var/run/hermes/` are
|
|
|
|
|
removed on stop.
|
|
|
|
|
|
|
|
|
|
## 6. Report + acceptance
|
|
|
|
|
|
|
|
|
|
Report back: host evidence (§0), full `cargo test` output, the runbook results,
|
|
|
|
|
and the Hermes checks. File any FreeBSD-specific differences from Linux-built
|
|
|
|
|
behavior as a PR, not a silent local fix.
|
|
|
|
|
|
|
|
|
|
Delete this doc when all are true:
|
|
|
|
|
|
|
|
|
|
- [ ] `cargo test --workspace` passes on FreeBSD 15 (output + versions reported).
|
|
|
|
|
- [ ] `sudo ./build.sh` produces an image with Colibri staged (preflight passed,
|
|
|
|
|
`colibri` user present, service enabled).
|
|
|
|
|
- [ ] Booted image passes the Colibri acceptance runbook (start/status/task/
|
|
|
|
|
intake/stop/restart-persistence).
|
|
|
|
|
- [ ] Hermes rc.d: missing-config start aborts (no crash loop); configured
|
|
|
|
|
start/health/stop work and pidfiles are cleaned up.
|
|
|
|
|
- [ ] Any platform differences are filed as a PR and reported.
|
|
|
|
|
|
|
|
|
|
## Notes
|
|
|
|
|
|
|
|
|
|
- The build host needs Go + Rust; the image does not (binaries are staged, not
|
|
|
|
|
compiled on device). See `clawdie-iso/REQUIREMENTS.md`.
|
|
|
|
|
- `/var/run` is tmpfs on FreeBSD — both rc.d scripts recreate their run dirs in
|
|
|
|
|
prestart, so a fresh boot is the correct test.
|
|
|
|
|
- Cost-mode _enforcement_ wiring is Priority 3 (Linux-doable, separate lane);
|
|
|
|
|
this lane only confirms the baked `cost.mode` is surfaced by `colibri status`.
|