feat(iso): live-rebuild lane covers zot + version-model cleanup #56

Merged
clawdie merged 3 commits from live-rebuild-zot-and-version-cleanup into main 2026-06-15 09:24:52 +02:00
9 changed files with 101 additions and 47 deletions

View file

@ -21,7 +21,7 @@ On `xfce-operator-usb`, builds a bootable FreeBSD 15.0 operator USB image with:
The ISO version is independent from the bundled Clawdie-AI ref:
```sh
ISO_VERSION="0.1.0"
ISO_VERSION="auto" # default: git describe, then ZOT_VERSION fallback
BUILD_CHANNEL="dev" # dev | release
CLAWDIE_REF="main" # validation default
```
@ -92,7 +92,7 @@ Colibri-backed. The image includes:
```
The build also creates the `colibri` service user/group and writes rc.conf
values for `colibri_daemon_enable`, paths, and `colibri_cost_mode`. Operator USB
values for `colibri_daemon_enable`, paths, and `colibri_daemon_cost_mode`. Operator USB
validation builds enable `colibri_daemon_enable=YES`; the service starts after
the login milestone and is the lightweight control plane for the live USB.
@ -396,7 +396,7 @@ boolean `tailscale_auth_key_baked: true|false` is recorded in the manifest.
The build header shows:
```text
ISO : 0.1.0-dev
ISO : <iso-version>-dev
FreeBSD : 15.0-RELEASE amd64
Clawdie : main
Clawdie commit: <resolved-sha>
@ -428,7 +428,7 @@ The final size output distinguishes:
Edit `build.cfg` for persistent defaults:
```sh
ISO_VERSION="0.1.0"
ISO_VERSION="${ISO_VERSION:-auto}"
BUILD_CHANNEL="${BUILD_CHANNEL:-dev}"
IMAGE_SIZE="28G"
CLAWDIE_REF="${CLAWDIE_REF:-main}"

View file

@ -7,12 +7,16 @@ All notable changes to Clawdie-ISO are documented here.
## [Unreleased]
### Added
- Live rebuild lane now covers the **whole agent stack**: `go` added to the live-operator package list and the `zot` source seeded at `/home/clawdie/ai/zot`, so a booted USB can rebuild zot (Go) as well as Colibri (Rust). See `docs/LIVE-COLIBRI-REBUILD.md`.
- Aider+Pi harness venv provisioning — `firstboot/shell-deploy.sh` now creates `/opt/clawdie/venv/aider` with pinned deps: `aider-chat==0.86.2`, `litellm==1.81.10`, `tree_sitter==0.20.4`
- Aider availability check in post-install verification (logs `aider` version at end of deployment)
### Improvements
- Updated firstboot completion messages to highlight Aider and Pi as primary harnesses (Codex listed as optional alternative)
### Versioning
- The image version tracks the `zot` release it is built on (resolved via `git describe`, falling back to `ZOT_VERSION`); the output is named `clawdie-<freebsd-codename>-<version>.img`. No separately invented ISO number.
---
## [0.9.0] — 2026-04-06
@ -54,9 +58,14 @@ All notable changes to Clawdie-ISO are documented here.
## Repository Status
| Repo | Status | Latest |
|------|--------|--------|
| clawdie-ai | Active | v0.9.0 |
| clawdie-iso | Active | v0.9.0 + Phase 0 |
| clawdie-shell | **Archived** | — |
| pi | Independent | v0.56.3 |
The agent stack is **zot (Go agent) + Colibri (Rust control plane)**; "Clawdie"
is the product name for the two together. The image version tracks zot.
| Repo | Status | Version source |
| ------------- | ----------------------------------- | ------------------------------- |
| zot | Active — the agent (front door) | pinned tag (`ZOT_VERSION`) |
| colibri | Active — control plane + installer | workspace `Cargo.toml` |
| clawdie-iso | Active — image builder | tracks zot (`git describe`) |
| clawdie-ai | Being pruned (features → zot/Colibri) | — |
| pi | Demoted — spawnable backend, not default | upstream npm |
| clawdie-shell | **Archived** (merged into clawdie-iso) | — |

View file

@ -229,7 +229,7 @@ contract between agents.
| ------------------ | ------------------------------ | ---------------------------------- | ----------------------------------------------------- |
| Build result | `iso-build` | `clawdie.iso.build.v1` | Commit, flags, log path, output files, static checks |
| Publish result | `iso-publish` | `clawdie.iso.publish.v1` | Public URLs, checksums, manifest path, symlink state |
| Flash verification | `iso-flash-verify` | `clawdie.iso.flash.v1` | Download, checksum, xz test, target disk fit, flash |
| Flash verification | `iso-flash-verify` | `clawdie.iso.flash.v1` | Download, checksum, xz test, target disk fit, flash |
| Mounted validation | `iso-validate-image` | `clawdie.iso.validation.v1` | SDDM, CLIs, `mdo`, seed slice, no-blank, panel assets |
| Hardware report | `iso-hardware-report-ingest` | `clawdie.iso.hardware.v1` | GPU/KMS, GL renderer, input, audio, Wi-Fi, SDDM/XFCE |
| Package audit | `iso-package-audit` | `clawdie.iso.package-audit.v1` | Category, size, flat size, reason kept, deferral risk |

View file

@ -155,7 +155,7 @@ BUILD_CHANNEL=release sudo ./build.sh --clawdie-version 0.10.0
The build prints provenance similar to:
```text
ISO : 0.1.0-dev
ISO : <iso-version>-dev
FreeBSD : 15.0-RELEASE amd64
Clawdie : main
Clawdie commit: <sha>

View file

@ -820,7 +820,7 @@ install_colibri_service() {
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'colibri_daemon_logfile="/var/log/colibri/daemon.log"'
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'colibri_daemon_provider_env="/usr/local/etc/colibri/provider.env"'
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'colibri_daemon_host="$(hostname)"'
set_config_line "${MOUNT_POINT}/etc/rc.conf" "colibri_cost_mode=\"${COLIBRI_COST_MODE:-smart}\""
set_config_line "${MOUNT_POINT}/etc/rc.conf" "colibri_daemon_cost_mode=\"${COLIBRI_COST_MODE:-smart}\""
if [ ! -x "${MOUNT_POINT}/usr/local/bin/colibri-daemon" ] || \
[ ! -x "${MOUNT_POINT}/usr/local/bin/colibri" ] || \
@ -1055,14 +1055,22 @@ seed_live_ai_source_repo() {
return 0
fi
echo " Seeding AI source snapshot: ${_repo_name}"
rm -rf "${_repo_dest}"
mkdir -p "${_repo_dest}"
git -C "${_repo_src}" archive --format=tar HEAD | tar -C "${_repo_dest}" -xf -
_repo_branch=$(git -C "${_repo_src}" symbolic-ref --short -q HEAD 2>/dev/null || echo detached)
_repo_commit=$(git -C "${_repo_src}" rev-parse HEAD 2>/dev/null || echo unknown)
_repo_origin=$(git -C "${_repo_src}" remote get-url origin 2>/dev/null || echo unknown)
_repo_src_real=$(cd "${_repo_src}" && pwd -P)
echo " Seeding AI source checkout: ${_repo_name} (${_repo_commit})"
rm -rf "${_repo_dest}"
if [ "${_repo_branch}" != "detached" ]; then
git clone --quiet --depth 1 --branch "${_repo_branch}" "file://${_repo_src_real}" "${_repo_dest}"
else
git clone --quiet "file://${_repo_src_real}" "${_repo_dest}"
git -C "${_repo_dest}" checkout --quiet --detach "${_repo_commit}"
fi
git -C "${_repo_dest}" remote set-url origin "${_repo_origin}" 2>/dev/null || true
printf '%s\n' '.clawdie-source.json' >> "${_repo_dest}/.git/info/exclude"
_repo_dirty=false
if ! git -C "${_repo_src}" diff --quiet 2>/dev/null || ! git -C "${_repo_src}" diff --cached --quiet 2>/dev/null; then
_repo_dirty=true
@ -1076,31 +1084,39 @@ seed_live_ai_source_repo() {
"branch": "$(json_escape "${_repo_branch}")",
"commit": "$(json_escape "${_repo_commit}")",
"dirty_at_build": ${_repo_dirty},
"snapshot_note": "git archive of HEAD; uncommitted changes and ignored/private files are not included"
"iso_version": "$(json_escape "${ISO_VERSION}")",
"build_channel": "$(json_escape "${BUILD_CHANNEL}")",
"snapshot_kind": "shallow git checkout",
"snapshot_note": "shallow git checkout of HEAD; uncommitted changes and ignored/private files are not included"
}
EOF
}
install_live_ai_source_snapshots() {
echo " Installing live AI source snapshots..."
echo " Installing live AI source checkouts..."
resolve_clawdie_ai_repo
resolve_colibri_paths
mkdir -p "${MOUNT_POINT}/home/clawdie/ai"
cat > "${MOUNT_POINT}/home/clawdie/ai/README.txt" <<'EOF'
Clawdie live AI source snapshots
Clawdie live AI source checkouts
These directories are included so the operator can start a local provider-backed
Pi session from the live XFCE desktop and inspect the shipped source beside the
running system.
Pi session from the live XFCE desktop, inspect the shipped source beside the
running system, and fetch follow-up commits from Forgejo when network access is
available.
No API keys, .env files, SSH private keys, build caches, package caches, tmp/
directories, or uncommitted worktree changes are included. Each snapshot has a
.clawdie-source.json file recording the source remote, branch, commit, and dirty
state at image build time.
directories, or uncommitted worktree changes are included. Each checkout keeps a
.git directory plus a .clawdie-source.json file recording the source remote,
branch, commit, dirty state, ISO version, and build channel at image build time.
EOF
seed_live_ai_source_repo "${SCRIPT_DIR}" "clawdie-iso"
seed_live_ai_source_repo "${_resolved_clawdie_ai_repo}" "clawdie-ai"
seed_live_ai_source_repo "${_resolved_colibri_repo}" "colibri"
# zot source so the live rebuild lane can rebuild the agent (Go) too, not
# just Colibri (Rust). Skipped automatically if the zot checkout is absent.
resolve_zot_paths
seed_live_ai_source_repo "${_resolved_zot_repo}" "zot"
chroot "${MOUNT_POINT}" chown -R clawdie:clawdie /home/clawdie/ai
}

View file

@ -10,18 +10,11 @@ the next image is rebuilt.
## Why this exists
The live USB currently stages `/home/clawdie/ai/colibri` as a source snapshot
from `git archive`. That snapshot is useful for inspection, but it is not a real
git checkout and has no `.git` directory:
```sh
cd /home/clawdie/ai/colibri
git remote -v
# fatal: not a git repository (or any of the parent directories): .git
```
For rebuilds, clone a fresh working checkout into a separate directory such as
`/home/clawdie/ai/colibri-build` or `/var/tmp/colibri-build`.
New live USB builds stage `/home/clawdie/ai/colibri` as a shallow git checkout
with a `.git` directory and a `.clawdie-source.json` provenance file. You can
rebuild directly from that checkout, or clone a separate working checkout such
as `/home/clawdie/ai/colibri-build` if you want to keep the shipped source
untouched while testing a branch.
## Required live packages
@ -32,10 +25,12 @@ box:
rust
pkgconf
git
go
```
`git` is already in the live operator package list. `rust` provides `cargo` on
FreeBSD. `pkgconf` is needed by common Rust native dependency build scripts.
`go` builds the zot agent (see "Rebuild zot" below).
Optional if future dependencies need them:
@ -56,7 +51,8 @@ pkgconf --version
```
If `rustc` or `cargo` is missing, the current USB cannot rebuild Colibri from
source without installing packages first or using a newer ISO.
source without installing packages first or using a newer ISO. Likewise check
`go version` before attempting a zot rebuild.
## Clone or update Colibri
@ -181,6 +177,36 @@ mdo -u root install -m 0644 /tmp/colibri-live-rebuild.sha256 /var/db/colibri/liv
Report both files with validation notes when handing findings back through git.
## Rebuild zot (agent)
zot is the Go agent staged as a prebuilt binary at `/usr/local/bin/zot`. New
live USB builds seed `/home/clawdie/ai/zot` as a shallow git checkout with
`.clawdie-source.json` provenance, so you can rebuild there or clone a separate
`zot-build` checkout for branch testing.
```sh
mkdir -p /home/clawdie/ai
cd /home/clawdie/ai
if [ ! -d zot-build/.git ]; then
git clone https://code.smilepowered.org/clawdie/zot.git zot-build
fi
cd zot-build
git fetch --prune origin
git checkout v0.2.29 # ship the tag the ISO version tracks
go build -trimpath -o bin/zot ./cmd/zot
```
Install into the running USB (privileged steps via `mdo`):
```sh
mdo -u root install -m 0555 bin/zot /usr/local/bin/zot
zot --version
```
zot has no rc.d service of its own — Colibri spawns it — so no service restart
is needed. Validate with `zot --version` and a Colibri spawn check.
## Fast rc.d-only repair
If only the service script is broken and no binary rebuild is needed, fetch the

View file

@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Clawdie Operator USB — v0.9.1</title>
<title>Clawdie Operator USB</title>
<style>
:root {
--bg: #f3f1ea;
@ -84,7 +84,7 @@
</p>
<div class="card">
<strong>Included now (v0.9.1):</strong>
<strong>Included in this build:</strong>
<ul>
<li>XFCE desktop — dual-monitor, panel, wallpaper</li>
<li><code>colibri-daemon</code> — agent supervisor, skills catalog, Glasspane state machine</li>

View file

@ -21,10 +21,13 @@ bash
zsh
ohmyzsh
git
# Live Colibri rebuild lane: lets the running USB rebuild and redeploy Colibri
# Live rebuild lane: lets the running USB rebuild and redeploy the agent stack
# without a full ISO rebuild for every small service/runtime iteration.
# rust + pkgconf -> Colibri (Rust control plane)
# go -> zot (Go agent)
rust
pkgconf
go
tailscale
avahi-app
nss_mdns

View file

@ -73,9 +73,9 @@ install -m 0644 "${NEWSYSLOG_SOURCE}" "${NEWSYSLOG_DIR}/colibri.conf"
if ! grep -q '^command="/usr/sbin/daemon"' "${RC_DIR}/colibri_daemon" || \
! grep -q -- '-o .*colibri_daemon_binary' "${RC_DIR}/colibri_daemon" || \
! grep -q 'colibri_daemon_provider_env' "${RC_DIR}/colibri_daemon" || \
! grep -q 'rm -f "${colibri_daemon_socket}" "${pidfile}" "${supervisor_pidfile}"' "${RC_DIR}/colibri_daemon" || \
! grep -q 'chmod 644 "${pidfile}"' "${RC_DIR}/colibri_daemon" || \
! grep -q 'chmod 660 "${colibri_daemon_socket}"' "${RC_DIR}/colibri_daemon"; then
! grep -q 'colibri_daemon_cost_mode' "${RC_DIR}/colibri_daemon" || \
! grep -q 'rm -f "${pidfile}" "${supervisor_pidfile}"' "${RC_DIR}/colibri_daemon" || \
! grep -q 'export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"' "${RC_DIR}/colibri_daemon"; then
echo "ERROR: staged colibri_daemon rc.d script is missing required live USB supervision hooks" >&2
echo " Update COLIBRI_REPO (${COLIBRI_REPO}) before building." >&2
exit 66
@ -99,8 +99,8 @@ colibri_daemon_socket="/var/run/colibri/colibri.sock"
colibri_daemon_db_path="/var/db/colibri/colibri.sqlite"
colibri_daemon_logfile="/var/log/colibri/daemon.log"
colibri_daemon_provider_env="/usr/local/etc/colibri/provider.env"
colibri_daemon_host="\$(hostname)"
colibri_cost_mode="${COLIBRI_COST_MODE}"
colibri_daemon_host="\$(/bin/hostname)"
colibri_daemon_cost_mode="${COLIBRI_COST_MODE}"
EOF
cat > "${ETC_DIR}/provider.env.sample" <<'EOF'