feat(iso): product version 0.10.0 + colibri provenance (milestone cut) #58

Merged
clawdie merged 1 commit from versioning-product-0.10.0 into main 2026-06-15 17:09:53 +02:00
9 changed files with 103 additions and 63 deletions
Showing only changes of commit 67b6477119 - Show all commits

View file

@ -18,10 +18,11 @@ On `xfce-operator-usb`, builds a bootable FreeBSD 15.0 operator USB image with:
- Colibri Rust control-plane service for the live USB
- deployed-system `clawdie` service lane for future disk/server installs
The ISO version is independent from the bundled Clawdie-AI ref:
The ISO carries its own product version, independent of any component (zot,
Colibri, Clawdie-AI). Component versions are recorded in `build-manifest.json`.
```sh
ISO_VERSION="auto" # default: git describe, then ZOT_VERSION fallback
ISO_VERSION="0.10.0" # explicit product version (required; no zot-tracking)
BUILD_CHANNEL="dev" # dev | release
CLAWDIE_REF="main" # validation default
```
@ -137,14 +138,14 @@ sudo ./build.sh
Output:
```text
tmp/output/clawdie-quindecim-0.2.29.img
tmp/output/clawdie-quindecim-0.10.0.img
```
Published/downloaded artifacts are compressed as `.img.xz`. Stream the
compressed image directly into `dd`:
```sh
xz -dc clawdie-quindecim-0.2.29.img.xz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
xz -dc clawdie-quindecim-0.10.0.img.xz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
sync
```
@ -153,15 +154,15 @@ For Linux or FreeBSD downloads from the published HTTPS path, prefer resumable
```sh
curl -fL --continue-at - --retry 5 --retry-delay 5 --progress-bar -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz
curl -fL --retry 5 --retry-delay 5 -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz.sha256
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz.sha256
```
For a build-local uncompressed image, plain `dd` is also fine:
```sh
sudo dd if=tmp/output/clawdie-quindecim-0.2.29.img of=/dev/daX bs=1M status=progress conv=fsync
sudo dd if=tmp/output/clawdie-quindecim-0.10.0.img of=/dev/daX bs=1M status=progress conv=fsync
sync
```
@ -428,7 +429,7 @@ The final size output distinguishes:
Edit `build.cfg` for persistent defaults:
```sh
ISO_VERSION="${ISO_VERSION:-auto}"
ISO_VERSION="${ISO_VERSION:-0.10.0}"
BUILD_CHANNEL="${BUILD_CHANNEL:-dev}"
IMAGE_SIZE="28G"
CLAWDIE_REF="${CLAWDIE_REF:-main}"

View file

@ -6,17 +6,34 @@ All notable changes to Clawdie-ISO are documented here.
## [Unreleased]
_Nothing yet._
---
## [0.10.0] — 2026-06-15
**Codename:** Operator Image
First numbered milestone since the architecture settled on **zot (agent) +
Colibri (control plane)**. Not production, but a real, flashable operator image:
the XFCE live experience is stable and the Colibri service bugs are fixed, so the
image is meant to work out of the box. Work continues from here toward `1.0.0`.
### Versioning
- The ISO now carries its **own product version** and no longer borrows zot's number. `ISO_VERSION` is explicit (set in `build.cfg`); `auto`/zot-tracking is gone and a build with no version fails fast. Component versions (zot, colibri, clawdie-ai, clawdie-iso) are recorded as provenance in `build-manifest.json`.
- `build-manifest.json` now records `colibri_commit`/`colibri_dirty` — the image stages adjacent colibri binaries, so the commit that produced them is captured for reproducibility.
### 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)
### Fixed
- Colibri daemon now handles SIGTERM (graceful socket cleanup + agent reaping on `service stop`), refuses to steal a live socket, and fails closed if it cannot bind a control socket (colibri PR #75).
### 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
@ -59,13 +76,14 @@ All notable changes to Clawdie-ISO are documented here.
## Repository Status
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.
is the product name for the two together. The image carries its own product
version; component versions are recorded as provenance in `build-manifest.json`.
| 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-iso | Active — image builder | product version (`ISO_VERSION`) |
| clawdie-ai | Being pruned (features → zot/Colibri) | — |
| pi | Demoted — spawnable backend, not default | upstream npm |
| clawdie-shell | **Archived** (merged into clawdie-iso) | — |

View file

@ -3,7 +3,7 @@
Published Clawdie operator USB artifacts are compressed:
```text
clawdie-quindecim-0.2.29.img.xz
clawdie-quindecim-0.10.0.img.xz
```
Default policy:
@ -47,15 +47,15 @@ Download with resume and retries:
```sh
curl -fL --continue-at - --retry 5 --retry-delay 5 --progress-bar -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz
curl -fL --retry 5 --retry-delay 5 -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz.sha256
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz.sha256
```
Verify the downloaded artifact:
```sh
sha256sum -c clawdie-quindecim-0.2.29.img.xz.sha256
sha256sum -c clawdie-quindecim-0.10.0.img.xz.sha256
```
Unmount mounted USB partitions if needed:
@ -68,7 +68,7 @@ Flash by streaming xz into `dd`:
```sh
set -o pipefail 2>/dev/null || true
xz -dc clawdie-quindecim-0.2.29.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
xz -dc clawdie-quindecim-0.10.0.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
sync
```
@ -89,22 +89,22 @@ Download with resume and retries:
```sh
curl -fL --continue-at - --retry 5 --retry-delay 5 --progress-bar -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz
curl -fL --retry 5 --retry-delay 5 -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz.sha256
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz.sha256
```
Verify the downloaded artifact:
```sh
HASH=$(awk '{print $1}' clawdie-quindecim-0.2.29.img.xz.sha256)
sha256 -c "$HASH" clawdie-quindecim-0.2.29.img.xz
HASH=$(awk '{print $1}' clawdie-quindecim-0.10.0.img.xz.sha256)
sha256 -c "$HASH" clawdie-quindecim-0.10.0.img.xz
```
If `sha256sum` is installed, this GNU-style form is also OK:
```sh
sha256sum -c clawdie-quindecim-0.2.29.img.xz.sha256
sha256sum -c clawdie-quindecim-0.10.0.img.xz.sha256
```
Unmount mounted USB partitions if needed:
@ -116,7 +116,7 @@ sudo umount /dev/daXs* 2>/dev/null
Flash by streaming xz into `dd`:
```sh
xz -dc clawdie-quindecim-0.2.29.img.xz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
xz -dc clawdie-quindecim-0.10.0.img.xz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
sync
```
@ -129,11 +129,11 @@ Replace `/dev/daX` with the actual whole USB disk.
No decompression step needed — both tools read `.img.xz` directly.
1. Download both files (same folder):
- `clawdie-quindecim-0.2.29.img.xz`
- `clawdie-quindecim-0.2.29.img.xz.sha256`
- `clawdie-quindecim-0.10.0.img.xz`
- `clawdie-quindecim-0.10.0.img.xz.sha256`
2. (Recommended) verify the checksum in PowerShell:
```powershell
(Get-FileHash .\clawdie-quindecim-0.2.29.img.xz -Algorithm SHA256).Hash.ToLower()
(Get-FileHash .\clawdie-quindecim-0.10.0.img.xz -Algorithm SHA256).Hash.ToLower()
# compare against the value in the .sha256 file
```
3. **Rufus:** open Rufus → **SELECT** the `.img.xz` → choose the USB drive under "Device" → **START**. Rufus decompresses and writes in one step. (Use "DD Image" mode if prompted.)
@ -152,21 +152,21 @@ For a local build artifact that already exists as a raw image:
### Linux
```sh
sudo dd if=clawdie-quindecim-0.2.29.img of=/dev/sdX bs=4M status=progress conv=fsync
sudo dd if=clawdie-quindecim-0.10.0.img of=/dev/sdX bs=4M status=progress conv=fsync
sync
```
### FreeBSD
```sh
sudo dd if=clawdie-quindecim-0.2.29.img of=/dev/daX bs=1M status=progress conv=fsync
sudo dd if=clawdie-quindecim-0.10.0.img of=/dev/daX bs=1M status=progress conv=fsync
sync
```
Only unxz first if you specifically need the raw file for inspection or reuse:
```sh
unxz -k clawdie-quindecim-0.2.29.img.xz
unxz -k clawdie-quindecim-0.10.0.img.xz
```
---

View file

@ -170,17 +170,17 @@ Artifact names use a short Latin codename for the FreeBSD major line they were
built on. For FreeBSD `15`, that codename is `quindecim`, so:
```text
clawdie-quindecim-0.2.29.img
clawdie-quindecim-0.10.0.img
```
means:
- `clawdie` — project name
- `quindecim` — Latin for `15`, matching the FreeBSD 15 build line
- `0.2.29` — version, tracking the zot release the image is built upon
- `0.10.0` — the ISO product version (set in `build.cfg`)
Per-build provenance (build date, `clawdie-iso` commit, zot commit) lives in
`build-manifest.json`, not the filename.
Per-build provenance (build date and the `clawdie-iso`, `colibri`, `zot`, and
`clawdie-ai` commits) lives in `build-manifest.json`, not the filename.
Small reference for the current naming convention:
@ -233,26 +233,26 @@ Download on Linux or FreeBSD with resume and retries:
```sh
curl -fL --continue-at - --retry 5 --retry-delay 5 --progress-bar -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz
curl -fL --retry 5 --retry-delay 5 -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz.sha256
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz.sha256
```
Linux:
```sh
sha256sum -c clawdie-quindecim-0.2.29.img.xz.sha256
sha256sum -c clawdie-quindecim-0.10.0.img.xz.sha256
set -o pipefail 2>/dev/null || true
xz -dc clawdie-quindecim-0.2.29.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
xz -dc clawdie-quindecim-0.10.0.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
sync
```
FreeBSD:
```sh
HASH=$(awk '{print $1}' clawdie-quindecim-0.2.29.img.xz.sha256)
sha256 -c "$HASH" clawdie-quindecim-0.2.29.img.xz
xz -dc clawdie-quindecim-0.2.29.img.xz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
HASH=$(awk '{print $1}' clawdie-quindecim-0.10.0.img.xz.sha256)
sha256 -c "$HASH" clawdie-quindecim-0.10.0.img.xz
xz -dc clawdie-quindecim-0.10.0.img.xz | sudo dd of=/dev/daX bs=1M status=progress conv=fsync
sync
```

View file

@ -1,7 +1,7 @@
# Clawdie Operator USB Testing Guide
**Branch:** `xfce-operator-usb`
**Target artifact:** `clawdie-quindecim-0.2.29.img`
**Target artifact:** `clawdie-quindecim-0.10.0.img`
**Current desktop path:** XFCE via SDDM, interactive login as `clawdie`
---
@ -105,7 +105,7 @@ Run this on the FreeBSD build host after `build.sh` finishes.
### Useful verification commands
```sh
sudo mdconfig -a -t vnode -f tmp/output/clawdie-quindecim-0.2.29.img
sudo mdconfig -a -t vnode -f tmp/output/clawdie-quindecim-0.10.0.img
sudo mount -o ro /dev/md0s2a /mnt
egrep 'hostname|root_rw_mount|tmpmfs|varmfs|sshd|avahi|powerd|powerdxx|pf_enable|sddm|display_manager|clawdie_live_gpu|clawdie_tailscale_up|linux_enable|zfs_enable|kld_list' /mnt/etc/rc.conf
@ -426,12 +426,12 @@ FreeBSD. For a published compressed image on Linux, the default path is:
```sh
curl -fL --continue-at - --retry 5 --retry-delay 5 --progress-bar -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz
curl -fL --retry 5 --retry-delay 5 -O \
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.2.29.img.xz.sha256
sha256sum -c clawdie-quindecim-0.2.29.img.xz.sha256
https://osa.smilepowered.org/downloads/iso/clawdie-quindecim-0.10.0.img.xz.sha256
sha256sum -c clawdie-quindecim-0.10.0.img.xz.sha256
set -o pipefail 2>/dev/null || true
xz -dc clawdie-quindecim-0.2.29.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
xz -dc clawdie-quindecim-0.10.0.img.xz | sudo dd of=/dev/sdX bs=4M status=progress conv=fsync
sync
```

View file

@ -10,10 +10,10 @@ FREEBSD_MEMSTICK_URL="${FREEBSD_ISO_BASE_URL}/FreeBSD-${FREEBSD_VERSION}-${FREEB
FREEBSD_MEMSTICK_SHA256_URL="${FREEBSD_ISO_BASE_URL}/CHECKSUM.SHA256-FreeBSD-${FREEBSD_VERSION}-${FREEBSD_ARCH}"
# ISO version metadata.
# The ISO version tracks the zot release the image is built upon — no separately
# invented number. "auto" resolves it at build time from the zot checkout
# (git describe), falling back to ZOT_VERSION. Set ISO_VERSION=x.y.z to override.
ISO_VERSION="${ISO_VERSION:-auto}"
# The ISO carries its own product version — it does NOT borrow a component's
# number. Component versions (zot, colibri, clawdie-ai, clawdie-iso) are recorded
# as provenance in build-manifest.json. Bump this for each milestone image.
ISO_VERSION="${ISO_VERSION:-0.10.0}"
BUILD_CHANNEL="${BUILD_CHANNEL:-dev}" # dev | release
# Output image

View file

@ -112,8 +112,14 @@ if [ "${BUILD_CHANNEL}" = "release" ]; then
esac
fi
# ISO version tracks the zot release built upon — no separately invented number.
# "auto" resolves from the zot checkout (git describe); else the pinned ZOT_VERSION.
# The ISO carries its own product version (ISO_VERSION in build.cfg). It does not
# track any single component. Component versions are resolved below purely for
# provenance in build-manifest.json. A milestone build must declare a version.
if [ -z "${ISO_VERSION:-}" ] || [ "${ISO_VERSION}" = "auto" ]; then
echo "ERROR: ISO_VERSION must be an explicit product version (e.g. 0.10.0)."
echo " The image no longer tracks zot — set ISO_VERSION in build.cfg."
exit 1
fi
_iso_zot_repo="${ZOT_REPO:-${SCRIPT_DIR}/../zot}"
case "${_iso_zot_repo}" in /*) ;; *) _iso_zot_repo="${SCRIPT_DIR}/${_iso_zot_repo}" ;; esac
ZOT_RESOLVED_VERSION=""
@ -123,12 +129,9 @@ if [ -d "${_iso_zot_repo}/.git" ]; then
ZOT_RESOLVED_COMMIT="$(git -C "${_iso_zot_repo}" rev-parse --short=12 HEAD 2>/dev/null || true)"
fi
[ -n "${ZOT_RESOLVED_VERSION}" ] || ZOT_RESOLVED_VERSION="${ZOT_VERSION}"
if [ -z "${ISO_VERSION:-}" ] || [ "${ISO_VERSION}" = "auto" ]; then
ISO_VERSION="${ZOT_RESOLVED_VERSION#v}"
fi
echo "==> clawdie-iso build"
echo " ISO : ${ISO_VERSION}-${BUILD_CHANNEL} (tracks zot ${ZOT_RESOLVED_VERSION})"
echo " ISO : ${ISO_VERSION}-${BUILD_CHANNEL} (zot ${ZOT_RESOLVED_VERSION})"
echo " FreeBSD : ${FREEBSD_VERSION} ${FREEBSD_ARCH}"
echo " Clawdie : ${CLAWDIE_REF}"
echo " Desktop : ${DEFAULT_DESKTOP}"
@ -139,9 +142,9 @@ echo " Target : ${TARGET:-baremetal}"
echo " Colibri : ${FEATURE_COLIBRI:-NO} (agent ${ZOT_VERSION:-} / stage ${COLIBRI_STAGE_AGENT:-YES})"
echo ""
# Name the output: clawdie-<freebsd-codename>-<version>.img, where the version
# tracks zot (see ISO_VERSION above). Per-build provenance — date, clawdie-iso
# commit, zot commit — lives in build-manifest.json, not the filename.
# Name the output: clawdie-<freebsd-codename>-<version>.img, where the version is
# the ISO product version (see ISO_VERSION above). Per-build provenance — date,
# clawdie-iso/colibri/zot/clawdie-ai commits — lives in build-manifest.json.
BUILD_FREEBSD_MAJOR="${FREEBSD_RELEASE_SERIES%%.*}"
BUILD_FREEBSD_STAMP="$(printf '%s' "${FREEBSD_RELEASE_SERIES}" | tr 'A-Z' 'a-z')"
case "${BUILD_FREEBSD_MAJOR}" in
@ -481,13 +484,31 @@ write_build_manifest() {
if [ -n "${LIVE_SSH_PUBKEY_FP:-}" ]; then
_live_ssh_pubkey_fp_json="\"$(json_escape "${LIVE_SSH_PUBKEY_FP}")\""
fi
# Colibri provenance: the image stages adjacent colibri binaries, so record
# which commit produced them (the biggest gap for a reproducible release).
_colibri_commit="unknown"
_colibri_dirty="null"
if [ "${FEATURE_COLIBRI:-NO}" = "YES" ]; then
resolve_colibri_paths
if git -C "${_resolved_colibri_repo}" rev-parse --git-dir >/dev/null 2>&1; then
_colibri_commit=$(git -C "${_resolved_colibri_repo}" rev-parse HEAD 2>/dev/null || echo unknown)
if git -C "${_resolved_colibri_repo}" diff --quiet 2>/dev/null && \
git -C "${_resolved_colibri_repo}" diff --cached --quiet 2>/dev/null; then
_colibri_dirty="false"
else
_colibri_dirty="true"
fi
fi
fi
mkdir -p "$(dirname "$_manifest_path")"
cat > "$_manifest_path" <<EOF
{
"iso_version": "$(json_escape "${ISO_VERSION}")",
"iso_version_tracks": "zot",
"version_scheme": "product",
"zot_version": "$(json_escape "${ZOT_RESOLVED_VERSION:-${ZOT_VERSION}}")",
"zot_commit": "$(json_escape "${ZOT_RESOLVED_COMMIT:-unknown}")",
"colibri_commit": "$(json_escape "${_colibri_commit:-unknown}")",
"colibri_dirty": ${_colibri_dirty:-null},
"build_channel": "$(json_escape "${BUILD_CHANNEL}")",
"freebsd_version": "$(json_escape "${FREEBSD_VERSION}")",
"freebsd_arch": "$(json_escape "${FREEBSD_ARCH}")",

View file

@ -192,7 +192,7 @@ if [ ! -d zot-build/.git ]; then
fi
cd zot-build
git fetch --prune origin
git checkout v0.2.29 # ship the tag the ISO version tracks
git checkout v0.2.29 # the zot tag this image ships (see build-manifest.json)
go build -trimpath -o bin/zot ./cmd/zot
```

View file

@ -61,7 +61,7 @@ steps that write beside the artifact, or use the `sudo` variants shown below.
Set `IMG` to the raw image produced by the current build. Example:
```sh
IMG="tmp/output/clawdie-quindecim-0.2.29.img"
IMG="tmp/output/clawdie-quindecim-0.10.0.img"
```
```sh