From cea9bdaaa930e909361cb0edb5fdae6c0e4b17ac Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Sun, 24 May 2026 20:12:27 +0200 Subject: [PATCH 01/15] Pin ISO npm global CLI versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use packages/npm-globals.txt as the source of truth for offline npm CLI tarballs, update Pi to 0.75.5, and keep Claude Code out of the XFCE USB path. --- Build: not run — ISO build not requested Tests: pass — sh -n fetch-npm-globals and shell-npm-globals; pinned npm pack smoke passed --- build.sh | 4 ++-- firstboot/MODULE-MANIFEST.md | 2 +- firstboot/firstboot.sh | 2 +- firstboot/shell-npm-globals.sh | 4 ++-- packages/npm-globals.txt | 8 ++++++++ scripts/fetch-npm-globals.sh | 29 ++++++++++++++++++----------- 6 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 packages/npm-globals.txt diff --git a/build.sh b/build.sh index 55ee93a6..883359b1 100755 --- a/build.sh +++ b/build.sh @@ -531,8 +531,8 @@ EOF echo " Fetch complete." - # Fetch npm-global CLI tarballs (claude-code, gemini-cli, pi) - echo "==> [2b/7] Fetching npm-global CLI tarballs..." + # Fetch pinned npm-global CLI tarballs (pi, gemini-cli) + echo "==> [2b/7] Fetching pinned npm-global CLI tarballs..." OUT_DIR="$NPM_GLOBALS_DIR" "${SCRIPT_DIR}/scripts/fetch-npm-globals.sh" || { echo " ERROR: fetch-npm-globals.sh failed" exit 1 diff --git a/firstboot/MODULE-MANIFEST.md b/firstboot/MODULE-MANIFEST.md index 73fe8232..d1d4a2d8 100644 --- a/firstboot/MODULE-MANIFEST.md +++ b/firstboot/MODULE-MANIFEST.md @@ -436,7 +436,7 @@ ### **1.5.1: shell-npm-globals.sh** -**Purpose:** Install bundled npm CLI tools (claude, gemini, pi) from ISO cache +**Purpose:** Install pinned bundled npm CLI tools (pi, gemini) from ISO cache **Wizard Inputs:** None (automatic) diff --git a/firstboot/firstboot.sh b/firstboot/firstboot.sh index 382d850e..98cbc1a7 100644 --- a/firstboot/firstboot.sh +++ b/firstboot/firstboot.sh @@ -317,7 +317,7 @@ run_step_if "install" "system" clawdie_shell_system_config "H run_step_if "install" "desktop" clawdie_shell_desktop_detect "Desktop enablement" 7 run_step_if "install" "pf" clawdie_shell_pf "PF firewall + jail NAT" 8 run_step_if "install" "tailscale" clawdie_shell_tailscale_setup "Tailscale remote access" 8 -run_step_if "install upgrade" "npm-globals" clawdie_shell_npm_globals_install "Install bundled npm CLIs (claude/gemini/pi)" 8 +run_step_if "install upgrade" "npm-globals" clawdie_shell_npm_globals_install "Install pinned bundled npm CLIs (pi/gemini)" 8 run_step_if "install upgrade" "deploy" clawdie_shell_deploy "Extract tarball + just install" 8 log_msg "[firstboot] Complete." diff --git a/firstboot/shell-npm-globals.sh b/firstboot/shell-npm-globals.sh index 036d61f5..d57c0da6 100755 --- a/firstboot/shell-npm-globals.sh +++ b/firstboot/shell-npm-globals.sh @@ -1,11 +1,11 @@ #!/bin/sh # Clawdie Shell — NPM Globals Module -# Purpose: Install bundled npm-global CLI tools (claude-code, gemini-cli, pi) +# Purpose: Install pinned bundled npm-global CLI tools (pi, gemini-cli) # from local tarballs shipped on the install media. Fully offline. # POSIX-compliant (no bash-isms) # # Runs after shell-pkg.sh (so node24 + npm exist) and before shell-deploy.sh -# (so the agent runtime can find `claude`, `gemini`, `pi` on PATH at first run). +# (so the agent runtime can find `pi` and `gemini` on PATH at first run). set -eu diff --git a/packages/npm-globals.txt b/packages/npm-globals.txt new file mode 100644 index 00000000..951e8f05 --- /dev/null +++ b/packages/npm-globals.txt @@ -0,0 +1,8 @@ +# Bundled npm global CLIs for offline firstboot/live operator use. +# Pin exact versions to prevent build-to-build drift. +# +# Keep Pi current through coordinated version-sync work; do not rely on +# npm's moving latest dist-tag during ISO builds. + +@earendil-works/pi-coding-agent@0.75.5 +@google/gemini-cli@0.43.0 diff --git a/scripts/fetch-npm-globals.sh b/scripts/fetch-npm-globals.sh index d10c42a8..f8b20540 100755 --- a/scripts/fetch-npm-globals.sh +++ b/scripts/fetch-npm-globals.sh @@ -1,36 +1,39 @@ #!/bin/sh # Fetch npm-global CLIs as .tgz tarballs for offline install on the ISO target. # -# These three packages are agent runtimes the firstboot installer will -# `npm install -g` from local tarballs (no network needed): -# -# @anthropic-ai/claude-code — Claude Code CLI (agent harness) -# @google/gemini-cli — Gemini CLI (alt agent) -# @earendil-works/pi-coding-agent — pi CLI (used by Clawdie-AI + paperclip adapters) +# These packages are installed by firstboot with `npm install -g` from local +# tarballs (no network needed on the target). Exact versions are pinned in +# packages/npm-globals.txt to prevent build-to-build drift. # # Notes: # - Codex is shipped via the FreeBSD `codex` pkg (see pkg-list-host.txt), # not via npm — kept out of this bundle on purpose. +# - Claude Code is intentionally not bundled in the XFCE USB image path. # - opencode + cursor have no working FreeBSD distribution (upstream gap). # - Output is dual-purpose: bundled into the ISO and used by firstboot. # # Usage: # ./scripts/fetch-npm-globals.sh # fetch into tmp/npm-globals/ # OUT_DIR=/some/path ./scripts/fetch-npm-globals.sh +# NPM_GLOBALS_LIST=/path/to/list ./scripts/fetch-npm-globals.sh set -eu SCRIPT_DIR="$(dirname "$(realpath "$0")")" ROOT_DIR="$(dirname "$SCRIPT_DIR")" OUT_DIR="${OUT_DIR:-${ROOT_DIR}/tmp/npm-globals}" - -PACKAGES="@anthropic-ai/claude-code @google/gemini-cli @earendil-works/pi-coding-agent" +NPM_GLOBALS_LIST="${NPM_GLOBALS_LIST:-${ROOT_DIR}/packages/npm-globals.txt}" if ! command -v npm >/dev/null 2>&1; then echo "ERROR: npm not found in PATH (install www/npm-node24)" >&2 exit 1 fi +if [ ! -f "$NPM_GLOBALS_LIST" ]; then + echo "ERROR: npm globals list not found: $NPM_GLOBALS_LIST" >&2 + exit 1 +fi + mkdir -p "$OUT_DIR" cd "$OUT_DIR" @@ -40,13 +43,17 @@ cd "$OUT_DIR" rm -f ./*.tgz echo "==> Fetching npm-global tarballs into ${OUT_DIR}" -for pkg in $PACKAGES; do +echo "==> Package list: ${NPM_GLOBALS_LIST}" +while IFS= read -r pkg || [ -n "$pkg" ]; do + case "$pkg" in + ''|'#'*) continue ;; + esac echo " npm pack ${pkg}" - # `npm pack ` downloads the latest published tarball without + # `npm pack @` downloads the pinned published tarball without # installing it. Output is `-.tgz` (scoped names get # their slash flattened to a dash). npm pack "$pkg" >/dev/null -done +done < "$NPM_GLOBALS_LIST" echo "" echo "==> Bundle contents:" -- 2.45.3 From ad96541828982172a0d9bdeef7d6c0f3735a5934 Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Sun, 24 May 2026 20:24:40 +0200 Subject: [PATCH 02/15] Point AGENTS at INSTALLER-PLAN on main (Sam & Codex) --- AGENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index cf5ab6ff..46d624de 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -5,7 +5,7 @@ `clawdie-iso` is the **single canonical repo** for all Clawdie installation targets. The `clawdie-shell` repo is being **archived** (read-only). Do not make new commits there. -All work goes into `clawdie-iso`. See `PLAN-UNIFY.md` for the active implementation plan. +All work goes into `clawdie-iso`. See `INSTALLER-PLAN.md` for the active implementation plan. --- -- 2.45.3 From bfe1b7e782916af1f97b350f99868ef0abdabd49 Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Sun, 24 May 2026 23:22:14 +0200 Subject: [PATCH 03/15] Add platform x harness matrix: FreeBSD/Linux x 5 LLM providers (Opencode) --- doc/LLM-PROVIDER-HARNESS.md | 46 +++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/doc/LLM-PROVIDER-HARNESS.md b/doc/LLM-PROVIDER-HARNESS.md index 291435a2..4391500f 100644 --- a/doc/LLM-PROVIDER-HARNESS.md +++ b/doc/LLM-PROVIDER-HARNESS.md @@ -87,3 +87,49 @@ When a key needs rotation: 2. Update `~/.pi/agent/auth.json` or your shell profile. 3. Re-run the smoke to confirm. 4. Delete the old key at the provider dashboard. + +--- + +## Platform × Harness Matrix + +Level 1 is the **platform** (FreeBSD main, Linux auxiliary). +Level 2 is the **harness** — which agent runtime lives where and which +LLM providers each can reach. + +### Level 1: Platform + +| Platform | Role | Primary harness | Herdr | Notes | +| --------------------- | ----------------------------- | --------------- | ----- | -------------------------- | +| **FreeBSD (main)** | ISO build, live USB, validate | pi + codex | no | Authoritative build host | +| **Linux (auxiliary)** | Review, deploy, Colibri, UX | pi + herdr | yes | Opencode + Claude sessions | + +### Level 2: Harness × LLM Provider Combos + +Each cell shows: agent / provider / model / smoke status. + +| Harness / Agent | DeepSeek v4 | GLM-4.7 (z.ai) | Claude (Anthropic) | Gemini (Google) | Codex (OpenAI) | +| --------------- | --------------------------------- | -------------------------- | ------------------------- | ---------------------- | --------------- | +| **pi** | `deepseek/deepseek-v4-flash` PASS | `zai/` TRANSPORT OK | `anthropic/claude-*` TODO | `google/gemini-*` TODO | n/a (codex pkg) | +| **codex** | n/a | n/a | n/a | n/a | built-in OpenAI | +| **claude-code** | DeepSeek via OpenAI compat TODO | n/a | native PASS | n/a | n/a | +| **opencode** | n/a (no DeepSeek config yet) | native PASS (this session) | n/a | n/a | n/a | +| **gemini-cli** | n/a | n/a | n/a | native TODO | n/a | + +### What populates the matrix + +- **FreeBSD live USB**: ships `pi` + `codex` only (per live CLI policy) +- **Linux with herdr**: runs `pi`, `claude-code`, `codex`, `gemini-cli`, + and `opencode` — all visible in herdr panes +- **Opencode** (this session): currently GLM-4.7 via z.ai; other + providers can be wired via opencode's config +- **pi**: supports all providers via `--provider` flag; key in env or + `auth.json` + +### How to add a combo + +1. Pick an empty cell above. +2. Configure the agent for that provider (key, model). +3. Run the smoke (see Quick Start). +4. Update the cell with the exact `provider/model` string and PASS/FAIL. +5. Create a smoke doc if one doesn't exist. +6. Commit and push. -- 2.45.3 From 116787b9e62c7c3f34087977f33cbb6df3dde70c Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Sun, 24 May 2026 23:26:49 +0200 Subject: [PATCH 04/15] Add key revocation verification and error reference table (Opencode) --- doc/DEEPSEEK-V4-SMOKE.md | 67 +++++++++++++++++++++++++++++++++++++ doc/LLM-PROVIDER-HARNESS.md | 20 +++++++++++ 2 files changed, 87 insertions(+) diff --git a/doc/DEEPSEEK-V4-SMOKE.md b/doc/DEEPSEEK-V4-SMOKE.md index e71d0e88..6a11e8dd 100644 --- a/doc/DEEPSEEK-V4-SMOKE.md +++ b/doc/DEEPSEEK-V4-SMOKE.md @@ -108,6 +108,73 @@ Or export in your shell profile: export DEEPSEEK_API_KEY="" ``` +## Verifying Key Deletion / Revocation + +### 1. Confirm the key is gone from pi + +```sh +cat ~/.pi/agent/auth.json +``` + +If empty `{}`, no stored key. If it contains a `deepseek` entry, remove +it: + +```sh +# Back up first +cp ~/.pi/agent/auth.json ~/.pi/agent/auth.json.bak +# Edit to remove the deepseek entry, or wipe entirely: +echo '{}' > ~/.pi/agent/auth.json +``` + +### 2. Confirm the env var is unset + +```sh +echo "DEEPSEEK_API_KEY is set: ${DEEPSEEK_API_KEY:+yes}" +``` + +If blank, no env key. If still set: + +```sh +unset DEEPSEEK_API_KEY +``` + +### 3. Confirm the revoked key is rejected by the API + +```sh +DEEPSEEK_API_KEY="" pi --provider deepseek --model deepseek-v4-flash -p "test" 2>&1 +``` + +Expected error: + +``` +401 Authentication Fails, Your api key: ****XXXX is invalid +``` + +If you see `401`, the key is properly revoked at DeepSeek's side. + +### 4. Confirm clean "no key" state + +```sh +pi --provider deepseek --model deepseek-v4-flash -p "test" 2>&1 +``` + +Expected error: + +``` +No API key found for deepseek. +``` + +If you see this, pi has no stored or env key for DeepSeek — fully clean. + +### Error Reference + +| Scenario | Error message | +| ---------------------------- | ------------------------------------------------------------- | +| No key at all | `No API key found for deepseek.` | +| Revoked / invalid key | `401 Authentication Fails, Your api key: ****XXXX is invalid` | +| Rate limited (too many reqs) | `429 Rate limit reached...` | +| Quota exhausted | `402 Insufficient balance` | + ## Deletion Criteria - Lane confirmed in agent capability table diff --git a/doc/LLM-PROVIDER-HARNESS.md b/doc/LLM-PROVIDER-HARNESS.md index 291435a2..3e4fcdcf 100644 --- a/doc/LLM-PROVIDER-HARNESS.md +++ b/doc/LLM-PROVIDER-HARNESS.md @@ -87,3 +87,23 @@ When a key needs rotation: 2. Update `~/.pi/agent/auth.json` or your shell profile. 3. Re-run the smoke to confirm. 4. Delete the old key at the provider dashboard. + +## Verifying Key Cleanup + +After revoking a key, confirm it's fully removed: + +```sh +# 1. No stored key +cat ~/.pi/agent/auth.json # should be {} + +# 2. No env var +echo "Key set: ${DEEPSEEK_API_KEY:+yes}" # should be blank + +# 3. Revoked key is rejected +DEEPSEEK_API_KEY="" pi --provider deepseek --model deepseek-v4-flash -p "test" 2>&1 +# Expected: "401 Authentication Fails, Your api key: ****XXXX is invalid" + +# 4. Clean "no key" state confirmed +pi --provider deepseek --model deepseek-v4-flash -p "test" 2>&1 +# Expected: "No API key found for deepseek." +``` -- 2.45.3 From 1036e8d6ef96db29527d65b3d362be9cb7e9ef36 Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Mon, 25 May 2026 00:23:34 +0200 Subject: [PATCH 05/15] Add GPT-5.5 lane, restore platform x harness matrix with 5 providers --- doc/LLM-PROVIDER-HARNESS.md | 57 ++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/doc/LLM-PROVIDER-HARNESS.md b/doc/LLM-PROVIDER-HARNESS.md index 3e4fcdcf..1644eff4 100644 --- a/doc/LLM-PROVIDER-HARNESS.md +++ b/doc/LLM-PROVIDER-HARNESS.md @@ -8,10 +8,11 @@ can use. Each row links to its smoke doc with full setup commands. ## Provider Status -| Provider | pi flag | Smoke status | API docs | Key env var | Key file | Model IDs | Notes | -| --------------- | --------------------- | ------------ | ------------------------------------------------------- | ------------------ | ----------------------- | -------------------------------------- | ---------------------------- | -| **DeepSeek v4** | `--provider deepseek` | PASS | [api-docs.deepseek.com](https://api-docs.deepseek.com/) | `DEEPSEEK_API_KEY` | `~/.pi/agent/auth.json` | `deepseek-v4-flash`, `deepseek-v4-pro` | Direct API; Sam holds key | -| **GLM-4.7** | `--provider zai` | TRANSPORT OK | z.ai (internal) | `ZAI_API_KEY` | opencode config | TBD (`--list-models` needed) | Powers this Opencode session | +| Provider | pi flag | Smoke status | API docs | Key env var | Key file | Model IDs | Notes | +| --------------- | ---------------------- | ------------ | ------------------------------------------------------- | ------------------ | ----------------------- | -------------------------------------- | -------------------------------------------- | +| **DeepSeek v4** | `--provider deepseek` | PASS | [api-docs.deepseek.com](https://api-docs.deepseek.com/) | `DEEPSEEK_API_KEY` | `~/.pi/agent/auth.json` | `deepseek-v4-flash`, `deepseek-v4-pro` | Direct API; Sam holds key | +| **GLM-4.7** | `--provider zai` | TRANSPORT OK | z.ai (internal) | `ZAI_API_KEY` | opencode config | TBD (`--list-models` needed) | Powers this Opencode session | +| **GPT-5.5** | `openai-codex/gpt-5.5` | ACTIVE | OpenAI (via Codex app) | `PI_TUI_*` env | `~/.pi/agent/auth.json` | `gpt-5.5` | Pi TUI on FreeBSD host; Colibri review/fixes | ## Quick Start for New Agents @@ -68,6 +69,7 @@ pi --model deepseek/deepseek-v4-flash -p "hello" | ----------- | ---------------------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------- | | DeepSeek v4 | [DEEPSEEK-V4-SMOKE.md](./DEEPSEEK-V4-SMOKE.md) | [platform.deepseek.com/api_keys](https://platform.deepseek.com/api_keys) | [Pricing page](https://api-docs.deepseek.com/quick_start/pricing) | | GLM-4.7 | [GLM-4.7-SMOKE.md](./GLM-4.7-SMOKE.md) | z.ai internal | TBD | +| GPT-5.5 | (Codex app; no separate smoke doc) | OpenAI via Codex app | OpenAI standard | ## Adding a New Provider @@ -107,3 +109,50 @@ DEEPSEEK_API_KEY="" pi --provider deepseek --model deepseek-v4-flash -p pi --provider deepseek --model deepseek-v4-flash -p "test" 2>&1 # Expected: "No API key found for deepseek." ``` + +--- + +## Platform × Harness Matrix + +Level 1 is the **platform** (FreeBSD main, Linux auxiliary). +Level 2 is the **harness** — which agent runtime lives where and which +LLM providers each can reach. + +### Level 1: Platform + +| Platform | Role | Primary harness | Herdr | Notes | +| --------------------- | ----------------------------- | --------------- | ----- | -------------------------- | +| **FreeBSD (main)** | ISO build, live USB, validate | pi + codex | no | Authoritative build host | +| **Linux (auxiliary)** | Review, deploy, Colibri, UX | pi + herdr | yes | Opencode + Claude sessions | + +### Level 2: Harness × LLM Provider Combos + +Each cell shows: provider/model — smoke status. + +| Harness / Agent | DeepSeek v4 | GLM-4.7 (z.ai) | GPT-5.5 (OpenAI/Codex) | Claude (Anthropic) | Gemini (Google) | +| --------------- | ------------------------------- | -------------------------- | ----------------------------- | ------------------------- | ---------------------- | +| **pi** | `deepseek/v4-flash` PASS | `zai/` TRANSPORT OK | `openai-codex/gpt-5.5` ACTIVE | `anthropic/claude-*` TODO | `google/gemini-*` TODO | +| **codex** | n/a | n/a | built-in PASS | n/a | n/a | +| **claude-code** | DeepSeek via OpenAI compat TODO | n/a | n/a | native PASS | n/a | +| **opencode** | n/a (no DeepSeek config yet) | native PASS (this session) | n/a | n/a | n/a | +| **gemini-cli** | n/a | n/a | n/a | n/a | native TODO | + +### What populates the matrix + +- **FreeBSD live USB**: ships `pi` + `codex` only (per live CLI policy) +- **FreeBSD build host**: `pi` with `openai-codex/gpt-5.5` for Colibri review/fixes +- **Linux with herdr**: runs `pi`, `claude-code`, `codex`, `gemini-cli`, + and `opencode` — all visible in herdr panes +- **Opencode** (this session): currently GLM-4.7 via z.ai; other + providers can be wired via opencode's config +- **pi**: supports all providers via `--provider` flag; key in env or + `auth.json` + +### How to add a combo + +1. Pick an empty cell above. +2. Configure the agent for that provider (key, model). +3. Run the smoke (see Quick Start). +4. Update the cell with the exact `provider/model` string and PASS/FAIL. +5. Create a smoke doc if one doesn't exist. +6. Commit and push. -- 2.45.3 From f3cd46b247052457d41d0bd22f2e59e9ee68e6e8 Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Tue, 26 May 2026 18:53:00 +0200 Subject: [PATCH 06/15] XFCE handoff: visual-polish lane complete, awaiting ISO rebuild + hardware boot (Sam & Claude) Pass 1 + Pass 2 panel polish is on main and build-ready (XML valid, build.sh install paths + Whisker icon verified). Baton passes from the Claude/Linux config lane to the FreeBSD build host (osa) for an ISO rebuild + a boot on the AMD/ASUS box to check the verification items. No domedog config work remains. Co-Authored-By: Claude Opus 4.7 --- doc/XFCE-PANEL-BUGS-HANDOFF.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/XFCE-PANEL-BUGS-HANDOFF.md b/doc/XFCE-PANEL-BUGS-HANDOFF.md index 44785b40..c194c009 100644 --- a/doc/XFCE-PANEL-BUGS-HANDOFF.md +++ b/doc/XFCE-PANEL-BUGS-HANDOFF.md @@ -2,7 +2,7 @@ **From:** Claude Reviewer / XFCE Tweaker (Linux) **Date:** 24.maj.2026 -**Status:** OPEN — hand off to Claude for XFCE visual-polish lane; base hardware collection is closed +**Status:** Visual-polish lane COMPLETE (Pass 1 + Pass 2, on `main`, build-ready: panel XML valid, `build.sh` install paths + Whisker icon verified). → **Awaiting ISO rebuild on the FreeBSD build host (osa) + a boot on the AMD/ASUS box** to check the verification items below. No domedog/config work remains. ## Pre-build changes applied (2026-05-24) -- 2.45.3 From bac53516bd3157b278c7e4a9c3858118038ca470 Mon Sep 17 00:00:00 2001 From: 123kupola <123kupola@gmail.com> Date: Wed, 27 May 2026 02:25:40 +0200 Subject: [PATCH 07/15] AGENTS.md: anchor FreeBSD 15; add Colibri dependency section Co-authored-by: Sam & Hermes --- AGENTS.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 778ea1a3..563f0610 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,7 +9,7 @@ load-bearing responsibility. | Role name | Identity | Owns | Restrictions | | ---------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | | **Pi ISO Developer** | Pi harness (this dev agent) | Source changes, docs, static checks, commits, pushes | Does not start ISO builds or flash media unless explicitly assigned | -| **Codex ISO Builder** | codex pkg on the FreeBSD build host | `./build.sh`, mounted-image inspection, publishing, hardware validation | Should avoid broad source refactors; reports exact logs/output back through git or handoff notes | +| **Codex ISO Builder** | codex pkg on the FreeBSD 15 build host | `./build.sh`, mounted-image inspection, publishing, hardware validation | Should avoid broad source refactors; reports exact logs/output back through git or handoff notes | | **Hermes USB/IMG Deployer** | Hermes on Debian/Linux | Downloading verified published artifacts, USB target identification, flashing | Does not need Codeberg; never flashes unverified artifacts or partition paths | | **Claude Reviewer / XFCE Tweaker** | Claude (Linux) | Review/plans plus Track E XFCE GUI polish | Cannot build ISO, cannot run FreeBSD-only validation, should mark speculative runtime claims as such | | **Opencode / Z.ai Integrator** | Opencode CLI on Linux | Linux-side Herdr/dashboard experiments plus Pi/DeepSeek v4 provider-lane smoke wiring | Cannot claim FreeBSD runtime proof; uses Sam-provided API keys only for provider validation | @@ -69,14 +69,21 @@ surface should expose for report collection and review. ### Linux Agent Constraints Linux agents MUST NOT attempt to build the ISO (`./build.sh`, `./build-vps.sh`). -ISO builds require FreeBSD system tools (`mdconfig`, `mount_msdosfs`, `pkg`). -Instead, guide Codex ISO Builder with exact commands to run on the FreeBSD +ISO builds require FreeBSD 15 system tools (`mdconfig`, `mount_msdosfs`, `pkg`). +Instead, guide Codex ISO Builder with exact commands to run on the FreeBSD 15 system. Agents on any platform MUST NOT start a new ISO build unless explicitly assigned. Builds are long-running, mutate repo-local caches, and can leave mounted md(4) devices that require cleanup. +### Colibri Dependency + +The ISO build may eventually depend on artifacts from `Clawdie/Colibri` (the +cross-platform Rust control plane). Linux agents building Colibri should push to +Codeberg for FreeBSD 15 validation. Do not assume `cargo test` on Linux produces +identical results to FreeBSD 15. + --- ## Current XFCE Operator USB Baseline @@ -93,7 +100,7 @@ inspection as final proof that SDDM/XFCE works. **Privilege model:** distinguish build-host administration from live-USB runtime. -- On the FreeBSD build host, operator-facing commands may use `sudo`. +- On the FreeBSD 15 build host, operator-facing commands may use `sudo`. - Inside the live USB, `sudo` is intentionally absent. - Live privileged actions use FreeBSD `mac_do` via `mdo -u root `. - Agent runtime code must not shell out to `sudo` for privileged host changes. @@ -136,14 +143,15 @@ retrying. ## Cross-Repo Coordination -Clawdie spans two repos. Changes often require coordinated updates. +Clawdie spans three repos. Changes often require coordinated updates. | Repo | Purpose | Remote | | ------------- | ---------------------------------------- | ------------------------------------------ | | `Clawdie-AI` | Agent runtime, control plane, channels | `git@codeberg.org:Clawdie/Clawdie-AI.git` | | `clawdie-iso` | ISO builder, firstboot wizard, installer | `git@codeberg.org:Clawdie/Clawdie-ISO.git` | +| `Colibri` | Cross-platform Rust control plane core | `git@codeberg.org:Clawdie/Colibri.git` | -When changes span both repos, create a handoff doc in the secondary repo +When changes span repos, create a handoff doc in the secondary repo listing what needs updating. See `Clawdie-AI/AGENTS.md` for full protocol. --- -- 2.45.3 From bef252b057d1d757988e995b9f1bb87f86bb12a5 Mon Sep 17 00:00:00 2001 From: 123kupola <123kupola@gmail.com> Date: Wed, 27 May 2026 15:23:17 +0200 Subject: [PATCH 08/15] feat: seed SSH agent config in firstboot (Sam & Hermes) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit shell-ssh.sh now seeds ~/.ssh/config (AddKeysToAgent yes) and ~/.tmux.conf (SSH_AUTH_SOCK persistence) after SSH key install. Idempotent — appends to existing configs if already present. Fixes agent-dead-after-tmux-restart for every fresh Clawdie install. --- .graphifyignore | 20 ++++++++++++++++ firstboot/shell-ssh.sh | 54 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 .graphifyignore diff --git a/.graphifyignore b/.graphifyignore new file mode 100644 index 00000000..09063b63 --- /dev/null +++ b/.graphifyignore @@ -0,0 +1,20 @@ +.git/ +tmp/ +node_modules/ +dist/ +build/ +.cache/ +.env +*.key +*.pem +*.sqlite +*.db +*.img +*.img.gz +*.iso +*.sha256 +packages/ +downloads/ +html/ +webroot/ +graphify-out/cache/ diff --git a/firstboot/shell-ssh.sh b/firstboot/shell-ssh.sh index 25995748..9cbac444 100644 --- a/firstboot/shell-ssh.sh +++ b/firstboot/shell-ssh.sh @@ -25,6 +25,7 @@ clawdie_shell_ssh_setup() { # 1. Configure SSH keys (if provided) # 2. Set system passwords (if provided or auto-generate) # 3. Configure SSH auth methods (key-only or key+password) + # 4. Seed SSH agent persistence (~/.ssh/config + ~/.tmux.conf) log_msg "[ssh] Starting SSH and password setup" @@ -42,7 +43,8 @@ clawdie_shell_ssh_setup() { if [ -n "${SSH_PUBLIC_KEY:-}" ]; then clawdie_shell_ssh_install_pubkey clawdie_shell_ssh_disable_password_auth - log_msg "[ssh] SSH public key installed, password auth disabled" + clawdie_shell_ssh_seed_agent_config + log_msg "[ssh] SSH public key installed, password auth disabled, agent config seeded" else clawdie_shell_ssh_enable_password_auth log_msg "[ssh] No SSH key provided, password auth enabled (less secure)" @@ -102,6 +104,56 @@ clawdie_shell_ssh_install_pubkey() { return 0 } +# ============================================================================ +# SSH AGENT PERSISTENCE (seed ~/.ssh/config + ~/.tmux.conf) +# ============================================================================ + +clawdie_shell_ssh_seed_agent_config() { + # Seed SSH agent auto-load and tmux persistence for the clawdie user. + # Run after clawdie_shell_ssh_install_pubkey (requires user to exist). + + local ssh_config="/home/clawdie/.ssh/config" + local tmux_conf="/home/clawdie/.tmux.conf" + + # --- ~/.ssh/config: AddKeysToAgent yes, no agent forwarding --- + if [ ! -f "$ssh_config" ]; then + cat > "$ssh_config" <<'SSHEOF' +Host * + AddKeysToAgent yes + ForwardAgent no +SSHEOF + chmod 600 "$ssh_config" + chown clawdie:clawdie "$ssh_config" 2>/dev/null || true + log_msg "[ssh] Seeded ~/.ssh/config with AddKeysToAgent yes" + else + # Append only if not already present (idempotent) + if ! grep -q 'AddKeysToAgent' "$ssh_config" 2>/dev/null; then + printf '\nHost *\n AddKeysToAgent yes\n ForwardAgent no\n' >> "$ssh_config" + log_msg "[ssh] Appended AddKeysToAgent to existing ~/.ssh/config" + fi + fi + + # --- ~/.tmux.conf: persist agent socket across windows --- + if [ ! -f "$tmux_conf" ]; then + cat > "$tmux_conf" <<'TMUXEOF' +set -g base-index 1 +setw -g pane-base-index 1 +set -g mouse on +set-option -g update-environment "SSH_AUTH_SOCK SSH_AGENT_PID" +TMUXEOF + chmod 644 "$tmux_conf" + chown clawdie:clawdie "$tmux_conf" 2>/dev/null || true + log_msg "[ssh] Seeded ~/.tmux.conf with agent persistence" + else + if ! grep -q 'SSH_AUTH_SOCK' "$tmux_conf" 2>/dev/null; then + printf '\nset-option -g update-environment "SSH_AUTH_SOCK SSH_AGENT_PID"\n' >> "$tmux_conf" + log_msg "[ssh] Appended agent persistence to existing ~/.tmux.conf" + fi + fi + + return 0 +} + # ============================================================================ # SSH AUTH METHOD CONFIGURATION # ============================================================================ -- 2.45.3 From 4b76e0a9e5f28ac2f0374984e0f92d7953a10f71 Mon Sep 17 00:00:00 2001 From: 123kupola <123kupola@gmail.com> Date: Wed, 27 May 2026 15:32:58 +0200 Subject: [PATCH 09/15] fix: add agent launcher, drop harmful update-environment (Sam & Hermes) - Tier 1: seed ~/.profile with eval $(ssh-agent -s) launcher (FreeBSD, no systemd). AddKeysToAgent alone does not start an agent; without a launcher headless/SSH-in shells still get "Could not open connection". - Tier 3: drop set-option -g update-environment from tmux.conf seed. tmux default already includes SSH_AUTH_SOCK + DISPLAY/XAUTHORITY. set -g replaces the entire list, breaking X11 GUI apps on XFCE. - Remove .graphifyignore per project policy (graph artifacts not committed, tool not integrated into ISO repo). --- .graphifyignore | 20 ------------------ firstboot/shell-ssh.sh | 47 +++++++++++++++++++++++++++++++----------- 2 files changed, 35 insertions(+), 32 deletions(-) delete mode 100644 .graphifyignore diff --git a/.graphifyignore b/.graphifyignore deleted file mode 100644 index 09063b63..00000000 --- a/.graphifyignore +++ /dev/null @@ -1,20 +0,0 @@ -.git/ -tmp/ -node_modules/ -dist/ -build/ -.cache/ -.env -*.key -*.pem -*.sqlite -*.db -*.img -*.img.gz -*.iso -*.sha256 -packages/ -downloads/ -html/ -webroot/ -graphify-out/cache/ diff --git a/firstboot/shell-ssh.sh b/firstboot/shell-ssh.sh index 9cbac444..b9bf68ed 100644 --- a/firstboot/shell-ssh.sh +++ b/firstboot/shell-ssh.sh @@ -105,17 +105,45 @@ clawdie_shell_ssh_install_pubkey() { } # ============================================================================ -# SSH AGENT PERSISTENCE (seed ~/.ssh/config + ~/.tmux.conf) +# SSH AGENT PERSISTENCE (seed ~/.profile, ~/.ssh/config, ~/.tmux.conf) # ============================================================================ clawdie_shell_ssh_seed_agent_config() { - # Seed SSH agent auto-load and tmux persistence for the clawdie user. + # Seed SSH agent launcher, auto-load, and terminal preferences. + # FreeBSD: no systemd — use ~/.profile to start the agent on login. + # tmux's default update-environment already includes SSH_AUTH_SOCK; + # do NOT override it (would drop DISPLAY, XAUTHORITY, etc.). # Run after clawdie_shell_ssh_install_pubkey (requires user to exist). + local profile="/home/clawdie/.profile" local ssh_config="/home/clawdie/.ssh/config" local tmux_conf="/home/clawdie/.tmux.conf" - # --- ~/.ssh/config: AddKeysToAgent yes, no agent forwarding --- + # --- Tier 1: ~/.profile — start agent on every login (FreeBSD, no systemd) --- + if [ ! -f "$profile" ]; then + cat > "$profile" <<'PROFEOF' +# Start SSH agent if not already running +if [ -z "$SSH_AUTH_SOCK" ]; then + eval $(ssh-agent -s) > /dev/null 2>&1 +fi +PROFEOF + chmod 644 "$profile" + chown clawdie:clawdie "$profile" 2>/dev/null || true + log_msg "[ssh] Seeded ~/.profile with SSH agent launcher" + else + if ! grep -q 'ssh-agent -s' "$profile" 2>/dev/null; then + cat >> "$profile" <<'PROFEOF' + +# Start SSH agent if not already running +if [ -z "$SSH_AUTH_SOCK" ]; then + eval $(ssh-agent -s) > /dev/null 2>&1 +fi +PROFEOF + log_msg "[ssh] Appended SSH agent launcher to existing ~/.profile" + fi + fi + + # --- Tier 2: ~/.ssh/config — auto-load key on first use --- if [ ! -f "$ssh_config" ]; then cat > "$ssh_config" <<'SSHEOF' Host * @@ -126,29 +154,24 @@ SSHEOF chown clawdie:clawdie "$ssh_config" 2>/dev/null || true log_msg "[ssh] Seeded ~/.ssh/config with AddKeysToAgent yes" else - # Append only if not already present (idempotent) if ! grep -q 'AddKeysToAgent' "$ssh_config" 2>/dev/null; then printf '\nHost *\n AddKeysToAgent yes\n ForwardAgent no\n' >> "$ssh_config" log_msg "[ssh] Appended AddKeysToAgent to existing ~/.ssh/config" fi fi - # --- ~/.tmux.conf: persist agent socket across windows --- + # --- Tier 3: ~/.tmux.conf — UI preferences only (agent socket is default) --- + # tmux update-environment already includes SSH_AUTH_SOCK + DISPLAY. + # Seed mouse + indexing; do NOT override update-environment. if [ ! -f "$tmux_conf" ]; then cat > "$tmux_conf" <<'TMUXEOF' set -g base-index 1 setw -g pane-base-index 1 set -g mouse on -set-option -g update-environment "SSH_AUTH_SOCK SSH_AGENT_PID" TMUXEOF chmod 644 "$tmux_conf" chown clawdie:clawdie "$tmux_conf" 2>/dev/null || true - log_msg "[ssh] Seeded ~/.tmux.conf with agent persistence" - else - if ! grep -q 'SSH_AUTH_SOCK' "$tmux_conf" 2>/dev/null; then - printf '\nset-option -g update-environment "SSH_AUTH_SOCK SSH_AGENT_PID"\n' >> "$tmux_conf" - log_msg "[ssh] Appended agent persistence to existing ~/.tmux.conf" - fi + log_msg "[ssh] Seeded ~/.tmux.conf (base-index 1, mouse on)" fi return 0 -- 2.45.3 From 3bbbd9b500994bea2b17f55cb5822428e186f20f Mon Sep 17 00:00:00 2001 From: 123kupola <123kupola@gmail.com> Date: Wed, 27 May 2026 15:48:31 +0200 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20ground-up=20.bashrc=20rewrite=20?= =?UTF-8?q?=E2=80=94=20sudo=E2=86=92mdo=20alias,=20ZFS=20safety=20(Sam=20&?= =?UTF-8?q?=20Hermes)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - shell-system.sh (runs last, step 6): rewrite .profile with agent launcher, full .bashrc with sudo() shell function that fire-and-forget snapshots zroot@cli- before mdo -u root. PATH, prompt, history, aliases (ll/la/lt). Agent fallback for non-login shells via ~/.ssh-agent-env. - shell-ssh.sh (step 4): strip to ~/.ssh/config only. Agent/profile/tmux seeding moved to shell-system.sh so it is not overwritten. - AGENTS.md: document sudo→mdo decision with rationale table (ISO size, audit surface, single privilege path, ZFS rollback safety). --- AGENTS.md | 22 ++++++++++++++- firstboot/shell-ssh.sh | 59 ++++++--------------------------------- firstboot/shell-system.sh | 54 +++++++++++++++++++++++++++++++---- 3 files changed, 78 insertions(+), 57 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 563f0610..02937c1a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -101,11 +101,31 @@ inspection as final proof that SDDM/XFCE works. **Privilege model:** distinguish build-host administration from live-USB runtime. - On the FreeBSD 15 build host, operator-facing commands may use `sudo`. -- Inside the live USB, `sudo` is intentionally absent. +- Inside the live USB, `sudo` is intentionally absent (deleted via `pkg delete -f sudo`). - Live privileged actions use FreeBSD `mac_do` via `mdo -u root `. +- `~/.bashrc` aliases `sudo` → `mdo -u root` for muscle-memory compatibility. + The shell function wraps `mdo` with a fire-and-forget ZFS snapshot + (`zroot@cli-`) before each privileged invocation, so rollback + is always available without confirmation prompts or warning popups. - Agent runtime code must not shell out to `sudo` for privileged host changes. - Privileged Clawdie-AI host operations go through the hostd RPC layer. +**Why `sudo` as alias, not as pkg:** + +| Approach | Install sudo pkg | Alias to mdo | +|----------|-----------------|--------------| +| Extra package | Yes (sudo + deps) | No | +| Two privilege paths | `sudo` AND `mdo` coexist | Single path (`mdo`) | +| Audit surface | Two tools to audit | One kernel-enforced MAC | +| ZFS safety net | Requires sudoers hooks | Built into bash function | +| Agent confusion | Agents try both paths | Agents use `sudo`, get `mdo` | +| ISO size | Larger | Zero bytes | + +The alias approach keeps the ISO lean, eliminates dual-privilege-path +confusion, and bakes ZFS rollback safety directly into the operator shell. +`mac_do` is FreeBSD base system — no package dependency, kernel-enforced, +auditable via MAC framework. + --- ## Installer Temp Files diff --git a/firstboot/shell-ssh.sh b/firstboot/shell-ssh.sh index b9bf68ed..c6e834c3 100644 --- a/firstboot/shell-ssh.sh +++ b/firstboot/shell-ssh.sh @@ -25,7 +25,7 @@ clawdie_shell_ssh_setup() { # 1. Configure SSH keys (if provided) # 2. Set system passwords (if provided or auto-generate) # 3. Configure SSH auth methods (key-only or key+password) - # 4. Seed SSH agent persistence (~/.ssh/config + ~/.tmux.conf) + # 4. Seed SSH client defaults (~/.ssh/config) log_msg "[ssh] Starting SSH and password setup" @@ -43,8 +43,8 @@ clawdie_shell_ssh_setup() { if [ -n "${SSH_PUBLIC_KEY:-}" ]; then clawdie_shell_ssh_install_pubkey clawdie_shell_ssh_disable_password_auth - clawdie_shell_ssh_seed_agent_config - log_msg "[ssh] SSH public key installed, password auth disabled, agent config seeded" + clawdie_shell_ssh_seed_client_config + log_msg "[ssh] SSH public key installed, password auth disabled, client config seeded" else clawdie_shell_ssh_enable_password_auth log_msg "[ssh] No SSH key provided, password auth enabled (less secure)" @@ -105,45 +105,18 @@ clawdie_shell_ssh_install_pubkey() { } # ============================================================================ -# SSH AGENT PERSISTENCE (seed ~/.profile, ~/.ssh/config, ~/.tmux.conf) +# SSH CLIENT CONFIGURATION (seed ~/.ssh/config) # ============================================================================ -clawdie_shell_ssh_seed_agent_config() { - # Seed SSH agent launcher, auto-load, and terminal preferences. - # FreeBSD: no systemd — use ~/.profile to start the agent on login. - # tmux's default update-environment already includes SSH_AUTH_SOCK; - # do NOT override it (would drop DISPLAY, XAUTHORITY, etc.). +clawdie_shell_ssh_seed_client_config() { + # Seed SSH client defaults for the clawdie user. + # .profile / .bashrc / .tmux.conf are handled by shell-system.sh + # (which runs after this module). # Run after clawdie_shell_ssh_install_pubkey (requires user to exist). - local profile="/home/clawdie/.profile" local ssh_config="/home/clawdie/.ssh/config" - local tmux_conf="/home/clawdie/.tmux.conf" - # --- Tier 1: ~/.profile — start agent on every login (FreeBSD, no systemd) --- - if [ ! -f "$profile" ]; then - cat > "$profile" <<'PROFEOF' -# Start SSH agent if not already running -if [ -z "$SSH_AUTH_SOCK" ]; then - eval $(ssh-agent -s) > /dev/null 2>&1 -fi -PROFEOF - chmod 644 "$profile" - chown clawdie:clawdie "$profile" 2>/dev/null || true - log_msg "[ssh] Seeded ~/.profile with SSH agent launcher" - else - if ! grep -q 'ssh-agent -s' "$profile" 2>/dev/null; then - cat >> "$profile" <<'PROFEOF' - -# Start SSH agent if not already running -if [ -z "$SSH_AUTH_SOCK" ]; then - eval $(ssh-agent -s) > /dev/null 2>&1 -fi -PROFEOF - log_msg "[ssh] Appended SSH agent launcher to existing ~/.profile" - fi - fi - - # --- Tier 2: ~/.ssh/config — auto-load key on first use --- + # --- ~/.ssh/config: auto-load key on first use, no agent forwarding --- if [ ! -f "$ssh_config" ]; then cat > "$ssh_config" <<'SSHEOF' Host * @@ -160,20 +133,6 @@ SSHEOF fi fi - # --- Tier 3: ~/.tmux.conf — UI preferences only (agent socket is default) --- - # tmux update-environment already includes SSH_AUTH_SOCK + DISPLAY. - # Seed mouse + indexing; do NOT override update-environment. - if [ ! -f "$tmux_conf" ]; then - cat > "$tmux_conf" <<'TMUXEOF' -set -g base-index 1 -setw -g pane-base-index 1 -set -g mouse on -TMUXEOF - chmod 644 "$tmux_conf" - chown clawdie:clawdie "$tmux_conf" 2>/dev/null || true - log_msg "[ssh] Seeded ~/.tmux.conf (base-index 1, mouse on)" - fi - return 0 } diff --git a/firstboot/shell-system.sh b/firstboot/shell-system.sh index 2c61c9ca..7c12ad49 100755 --- a/firstboot/shell-system.sh +++ b/firstboot/shell-system.sh @@ -354,6 +354,12 @@ EOF cat > /home/clawdie/.profile <<'EOF' # Clawdie operator POSIX shell profile. [ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh + +# Start SSH agent on login (FreeBSD: no systemd, no X11 agent launcher). +# Non-login shells (tmux windows) use ~/.bashrc fallback instead. +if [ -z "$SSH_AUTH_SOCK" ]; then + eval $(ssh-agent -s) > /dev/null 2>&1 +fi EOF cat > /home/clawdie/.bash_profile <<'EOF' # Clawdie operator bash login profile. @@ -365,14 +371,50 @@ EOF } [ -r "${HOME}/.bashrc" ] && . "${HOME}/.bashrc" EOF - cat > /home/clawdie/.bashrc <<'EOF' -# Clawdie operator interactive bash profile. + cat > /home/clawdie/.bashrc <<'BASHRC' +# Clawdie operator interactive bash shell. +# Non-interactive shells stop here. +case $- in *i*) ;; *) return ;; esac + +# ── PATH (FreeBSD: /usr/local first) ────────────────────────── +export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" [ -r /etc/profile.d/clawdie.sh ] && . /etc/profile.d/clawdie.sh -if [ -n "${PS1:-}" ]; then - export HISTFILE="${HISTFILE:-/tmp/clawdie/bash_history}" - mkdir -p /tmp/clawdie 2>/dev/null || true + +# ── Privilege escalation ────────────────────────────────────── +# Clawdie ISO: no sudo pkg. Use FreeBSD mac_do instead. +# mac_do rules (gid=0>uid=0) allow wheel→root transitions. +# ZFS auto-snapshot provides safety net — no confirmation prompts. +sudo() { + local pool + pool=$(zpool list -H -o name 2>/dev/null | head -1) + if [ -n "$pool" ]; then + (zfs snapshot "${pool}@cli-$(date +%s)" 2>/dev/null &) + fi + mdo -u root "$@" +} + +# ── SSH agent (fallback for non-login shells) ───────────────── +# .profile starts the agent for login shells; tmux windows +# (non-login) inherit via SSH_AUTH_SOCK if the parent had one, +# but if not, try a stored env file from a prior login. +if [ -z "$SSH_AUTH_SOCK" ] && [ -f ~/.ssh-agent-env ]; then + . ~/.ssh-agent-env 2>/dev/null || true fi -EOF + +# ── Prompt ──────────────────────────────────────────────────── +PS1='\h:\w\$ ' + +# ── History ─────────────────────────────────────────────────── +export HISTFILE="${HISTFILE:-/tmp/clawdie/bash_history}" +export HISTSIZE=5000 +export HISTFILESIZE=10000 +mkdir -p /tmp/clawdie 2>/dev/null || true + +# ── Aliases ─────────────────────────────────────────────────── +alias ll='ls -lah' +alias la='ls -A' +alias lt='ls -laht' +BASHRC cat > /home/clawdie/.zprofile <<'EOF' # Clawdie operator zsh login profile. [ -r /etc/profile ] && . /etc/profile -- 2.45.3 From ef286770330dd2ed20795e23cc9705acb30e14f8 Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Thu, 28 May 2026 09:42:04 +0200 Subject: [PATCH 11/15] chore: harden ignores against pkg cache blobs --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index 9ab181be..4199344c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Never commit FreeBSD/pkg cache blobs anywhere in the repo. +**/*.pkg +**/*.txz + # Build artifacts (generated by build.sh) *.img *.img.sha256 -- 2.45.3 From 4a60cd3ca19e272e993c3e6c47c68c08796aace4 Mon Sep 17 00:00:00 2001 From: Sam & Hermes Date: Fri, 29 May 2026 11:43:19 +0200 Subject: [PATCH 12/15] docs: replace Codeberg refs with Forgejo (Sam & Hermes) --- AGENTS.md | 435 +++++++++++++++++++++++++++--------------------------- 1 file changed, 218 insertions(+), 217 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6f7bf9cb..c52785dc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,217 +1,218 @@ -# Clawdie ISO Agent Guidelines - -## Agent Identity and Current Role Split - -The XFCE operator USB work now uses a git-coordinated split. Agents may review -or suggest across boundaries, but should not silently take over another role's -load-bearing responsibility. - -| Role name | Identity | Owns | Restrictions | -| ---------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | -| **Pi ISO Developer** | Pi harness (this dev agent) | Source changes, docs, static checks, commits, pushes | Does not start ISO builds or flash media unless explicitly assigned | -| **Codex ISO Builder** | codex pkg on the FreeBSD 15 build host | `./build.sh`, mounted-image inspection, publishing, hardware validation | Should avoid broad source refactors; reports exact logs/output back through git or handoff notes | -| **Hermes USB/IMG Deployer** | Hermes on Debian/Linux | Downloading verified published artifacts, USB target identification, flashing | Does not need Codeberg; never flashes unverified artifacts or partition paths | -| **Claude Reviewer / XFCE Tweaker** | Claude (Linux) | Review/plans plus Track E XFCE GUI polish | Cannot build ISO, cannot run FreeBSD-only validation, should mark speculative runtime claims as such | -| **Opencode / Z.ai Integrator** | Opencode CLI on Linux | Linux-side Herdr/dashboard experiments plus Pi/DeepSeek v4 provider-lane smoke wiring | Cannot claim FreeBSD runtime proof; uses Sam-provided API keys only for provider validation | -| **Operator (Sam)** | Human operator | Product, hardware, acceptance, release judgment | Human approval required for release/tagging decisions | - -### Git Coordination Rules - -- Coordinate through git: fetch before commenting on remote state, push small - reviewable commits, and include test/build status in commit messages. -- Claude may push critique/suggestion commits, but Pi ISO Developer should - re-check and adjust implementation details before the next build target is - treated as final. -- Codex ISO Builder consumes pushed build targets, builds/publishes artifacts, - and reports hardware findings with exact commands and output. -- Hermes USB/IMG Deployer consumes published artifact URLs/manifests, verifies - checksums on Linux, identifies the USB target, and owns the final image-to-USB - deployment handoff. -- Opencode / Z.ai Integrator owns Linux-side Herdr/dashboard experiments and - the Pi/DeepSeek v4 smoke lane when Sam provides a `ZAI_API_KEY`; findings - should come back as exact commands, output, provider/version notes, and small - manifests/summaries that Colibri can ingest. -- If a change needs a long ISO build, USB flash, or real hardware proof, hand it - to the owning role instead of running it opportunistically. - -### Markdown Formatting Gate - -Markdown formatting is tool-owned, not taste-owned. Before pushing any commit -that edits `*.md`, run: - -```sh -./scripts/check-format.sh -``` - -If it fails, format only the touched markdown files, then rerun the check: - -```sh -npx --yes prettier@3 --write path/to/file.md -``` - -Do not hand-align Markdown tables or reflow prose manually. `.prettierrc` uses -`proseWrap: preserve` so existing prose line breaks stay intentional, while -Prettier still catches table padding, list spacing, and emphasis drift. - -### Private Planning Workspace - -`private/` is gitignored and may contain operator-private strategy notes or PRDs. -Agents on this host may read files there only when directly relevant to the -assigned work. Do not commit, quote, summarize publicly, or copy private content -to Codeberg unless the operator explicitly approves it. - -If working on custom ISO / hardware-report monetization, check -`private/PRD-CUSTOM-ISO.md` when present. Codex ISO Builder should focus first -on the local-only `hw-report` feasibility path and, after analysis, -return concise action notes for Claude Reviewer / XFCE Tweaker on what GUI -surface should expose for report collection and review. - -### Linux Agent Constraints - -Linux agents MUST NOT attempt to build the ISO (`./build.sh`, `./build-vps.sh`). -ISO builds require FreeBSD 15 system tools (`mdconfig`, `mount_msdosfs`, `pkg`). -Instead, guide Codex ISO Builder with exact commands to run on the FreeBSD 15 -system. - -Agents on any platform MUST NOT start a new ISO build unless explicitly assigned. -Builds are long-running, mutate repo-local caches, and can leave mounted md(4) -devices that require cleanup. - -### Colibri Dependency - -The ISO build stages FreeBSD-native Colibri control-plane artifacts from the -adjacent `../colibri` checkout (`FEATURE_COLIBRI=YES` is the default lane). The -staging is wired into `build.sh` and `scripts/stage-colibri-iso.sh`; the ISO -does **not** build Rust while the image is mounted. - -- Build Colibri release artifacts on the FreeBSD/OSA host, not on Debian/Linux. -- Build order, binary verification, and cleanup timing live in the `iso-build` - skill (§Colibri artifact preflight). -- Staging layout (installed paths, rc.d, directory ownership) is owned by - Colibri `docs/ISO-INTEGRATION-PLAN.md`. -- Required by ISO preflight: `colibri-daemon`, `colibri`, `colibri-smoke-agent`. - `colibri-tui` is optional in staging code but desired for this USB target and - should be verified alongside the other three. - -**Invariant:** do not `cargo clean` the Colibri checkout until the ISO -preflight/build has consumed `../colibri/target/release`. - ---- - -## Current XFCE Operator USB Baseline - -The active branch target is the XFCE live operator USB. Authoritative state -lives in `packages/` (what ships) and `PLAN-OPERATOR-USB-NEXT.md` (round-scope -decisions and any "for now" retention notes). Final graphical validation -requires real hardware — do not treat bhyve, nested VMs, or static image -inspection as final proof that SDDM/XFCE works. - ---- - -## System Configuration - -**Privilege model:** distinguish build-host administration from live-USB runtime. - -- On the FreeBSD 15 build host, operator-facing commands may use `sudo`. -- Inside the live USB, `sudo` is intentionally absent (deleted via `pkg delete -f sudo`). -- Live privileged actions use FreeBSD `mac_do` via `mdo -u root `. -- `~/.bashrc` aliases `sudo` → `mdo -u root` for muscle-memory compatibility. - The shell function wraps `mdo` with a fire-and-forget ZFS snapshot - (`zroot@cli-`) before each privileged invocation, so rollback - is always available without confirmation prompts or warning popups. -- Agent runtime code must not shell out to `sudo` for privileged host changes. -- Privileged Clawdie-AI host operations go through the hostd RPC layer. - -**Why `sudo` as alias, not as pkg:** - -| Approach | Install sudo pkg | Alias to mdo | -| ------------------- | ------------------------ | ---------------------------- | -| Extra package | Yes (sudo + deps) | No | -| Two privilege paths | `sudo` AND `mdo` coexist | Single path (`mdo`) | -| Audit surface | Two tools to audit | One kernel-enforced MAC | -| ZFS safety net | Requires sudoers hooks | Built into bash function | -| Agent confusion | Agents try both paths | Agents use `sudo`, get `mdo` | -| ISO size | Larger | Zero bytes | - -The alias approach keeps the ISO lean, eliminates dual-privilege-path -confusion, and bakes ZFS rollback safety directly into the operator shell. -`mac_do` is FreeBSD base system — no package dependency, kernel-enforced, -auditable via MAC framework. - ---- - -## Installer Temp Files - -The GUI installer uses `/tmp/clawdie-install.conf` to pass wizard values to -`firstboot.sh`. This is an exemption from the project-local `tmp/` rule. - -**Rationale:** - -- Live ISO has no project root -- Single-user install phase (no other users on the system) -- File is consumed once by `firstboot.sh` then deleted on reboot -- PF firewall is not yet running during install - -**Applies to:** - -- `/tmp/clawdie-install.conf` — GUI wizard config output -- `/tmp/clawdie-firstboot.*` — firstboot progress and log (written by rc.d) - -## Repo-local ISO Build Workspace - -ISO builds use repo-local `tmp/` for large caches and output artifacts: - -- `tmp/cache` — build cache -- `tmp/cache/mnt` — temporary md(4) work-image mountpoint -- `tmp/output` — generated `.img.gz` artifacts and checksums -- `tmp/packages` — fetched package archives - -`tmp/cache/mnt` is an ISO-builder-specific mountpoint exception. Do not mount -unrelated datasets, recovery filesystems, or scratch filesystems elsewhere under -repo `tmp/`. If a build is interrupted, use the `iso-build-cleanup` skill before -retrying. - ---- - -## Cross-Repo Coordination - -Clawdie spans three repos. Changes often require coordinated updates. - -| Repo | Purpose | Remote | -| ------------- | ---------------------------------------- | ------------------------------------------ | -| `Clawdie-AI` | Agent runtime, control plane, channels | `git@codeberg.org:Clawdie/Clawdie-AI.git` | -| `clawdie-iso` | ISO builder, firstboot wizard, installer | `git@codeberg.org:Clawdie/Clawdie-ISO.git` | -| `Colibri` | Cross-platform Rust control plane core | `git@codeberg.org:Clawdie/Colibri.git` | - -When changes span repos, create a handoff doc in the secondary repo -listing what needs updating. See `Clawdie-AI/AGENTS.md` for full protocol. - ---- - -## Agent Handoff Documents - -Use ephemeral handoff files to transfer context between agents. - -- **Name:** `doc/-HANDOFF.md` or `-HANDOFF.md` (repo root) -- **Lifecycle:** Create when handing off, delete when complete -- **Structure:** Must include task checklist, deletion criteria, results section - -See `Clawdie-AI/AGENTS.md` for the full handoff template and protocol. - ---- - -## Attribution in Commit History - -Use attribution in commit messages, not in code comments. - -Labels: - -- `Sam & Codex` — changes made by Sam and Codex -- `Sam & Claude` — changes made by Sam and Claude -- `C&C` — joint change with equal credit for Claude and Codex - -Add the label to the commit subject or body. Example: - -``` -Fix bhyve preflight checks (C&C) -``` + 1|# Clawdie ISO Agent Guidelines + 2| + 3|## Agent Identity and Current Role Split + 4| + 5|The XFCE operator USB work now uses a git-coordinated split. Agents may review + 6|or suggest across boundaries, but should not silently take over another role's + 7|load-bearing responsibility. + 8| + 9|| Role name | Identity | Owns | Restrictions | + 10|| ---------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | + 11|| **Pi ISO Developer** | Pi harness (this dev agent) | Source changes, docs, static checks, commits, pushes | Does not start ISO builds or flash media unless explicitly assigned | + 12|| **Codex ISO Builder** | codex pkg on the FreeBSD 15 build host | `./build.sh`, mounted-image inspection, publishing, hardware validation | Should avoid broad source refactors; reports exact logs/output back through git or handoff notes | + 13|| **Hermes USB/IMG Deployer** | Hermes on Debian/Linux | Downloading verified published artifacts, USB target identification, flashing | Does not need Codeberg (mirror only); pushes to Forgejo exclusively | + 14|| **Claude Reviewer / XFCE Tweaker** | Claude (Linux) | Review/plans plus Track E XFCE GUI polish | Cannot build ISO, cannot run FreeBSD-only validation, should mark speculative runtime claims as such | + 15|| **Opencode / Z.ai Integrator** | Opencode CLI on Linux | Linux-side Herdr/dashboard experiments plus Pi/DeepSeek v4 provider-lane smoke wiring | Cannot claim FreeBSD runtime proof; uses Sam-provided API keys only for provider validation | + 16|| **Operator (Sam)** | Human operator | Product, hardware, acceptance, release judgment | Human approval required for release/tagging decisions | + 17| + 18|### Git Coordination Rules + 19| + 20|- Coordinate through git: fetch before commenting on remote state, push small + 21| reviewable commits, and include test/build status in commit messages. + 22|- Claude may push critique/suggestion commits, but Pi ISO Developer should + 23| re-check and adjust implementation details before the next build target is + 24| treated as final. + 25|- Codex ISO Builder consumes pushed build targets, builds/publishes artifacts, + 26| and reports hardware findings with exact commands and output. + 27|- Hermes USB/IMG Deployer consumes published artifact URLs/manifests, verifies + 28| checksums on Linux, identifies the USB target, and owns the final image-to-USB + 29| deployment handoff. + 30|- Opencode / Z.ai Integrator owns Linux-side Herdr/dashboard experiments and + 31| the Pi/DeepSeek v4 smoke lane when Sam provides a `ZAI_API_KEY`; findings + 32| should come back as exact commands, output, provider/version notes, and small + 33| manifests/summaries that Colibri can ingest. + 34|- If a change needs a long ISO build, USB flash, or real hardware proof, hand it + 35| to the owning role instead of running it opportunistically. + 36| + 37|### Markdown Formatting Gate + 38| + 39|Markdown formatting is tool-owned, not taste-owned. Before pushing any commit + 40|that edits `*.md`, run: + 41| + 42|```sh + 43|./scripts/check-format.sh + 44|``` + 45| + 46|If it fails, format only the touched markdown files, then rerun the check: + 47| + 48|```sh + 49|npx --yes prettier@3 --write path/to/file.md + 50|``` + 51| + 52|Do not hand-align Markdown tables or reflow prose manually. `.prettierrc` uses + 53|`proseWrap: preserve` so existing prose line breaks stay intentional, while + 54|Prettier still catches table padding, list spacing, and emphasis drift. + 55| + 56|### Private Planning Workspace + 57| + 58|`private/` is gitignored and may contain operator-private strategy notes or PRDs. + 59|Agents on this host may read files there only when directly relevant to the + 60|assigned work. Do not commit, quote, summarize publicly, or copy private content + 61|to Forgejo unless the operator explicitly approves it. + 62| + 63|If working on custom ISO / hardware-report monetization, check + 64|`private/PRD-CUSTOM-ISO.md` when present. Codex ISO Builder should focus first + 65|on the local-only `hw-report` feasibility path and, after analysis, + 66|return concise action notes for Claude Reviewer / XFCE Tweaker on what GUI + 67|surface should expose for report collection and review. + 68| + 69|### Linux Agent Constraints + 70| + 71|Linux agents MUST NOT attempt to build the ISO (`./build.sh`, `./build-vps.sh`). + 72|ISO builds require FreeBSD 15 system tools (`mdconfig`, `mount_msdosfs`, `pkg`). + 73|Instead, guide Codex ISO Builder with exact commands to run on the FreeBSD 15 + 74|system. + 75| + 76|Agents on any platform MUST NOT start a new ISO build unless explicitly assigned. + 77|Builds are long-running, mutate repo-local caches, and can leave mounted md(4) + 78|devices that require cleanup. + 79| + 80|### Colibri Dependency + 81| + 82|The ISO build stages FreeBSD-native Colibri control-plane artifacts from the + 83|adjacent `../colibri` checkout (`FEATURE_COLIBRI=YES` is the default lane). The + 84|staging is wired into `build.sh` and `scripts/stage-colibri-iso.sh`; the ISO + 85|does **not** build Rust while the image is mounted. + 86| + 87|- Build Colibri release artifacts on the FreeBSD/OSA host, not on Debian/Linux. + 88|- Build order, binary verification, and cleanup timing live in the `iso-build` + 89| skill (§Colibri artifact preflight). + 90|- Staging layout (installed paths, rc.d, directory ownership) is owned by + 91| Colibri `docs/ISO-INTEGRATION-PLAN.md`. + 92|- Required by ISO preflight: `colibri-daemon`, `colibri`, `colibri-smoke-agent`. + 93| `colibri-tui` is optional in staging code but desired for this USB target and + 94| should be verified alongside the other three. + 95| + 96|**Invariant:** do not `cargo clean` the Colibri checkout until the ISO + 97|preflight/build has consumed `../colibri/target/release`. + 98| + 99|--- + 100| + 101|## Current XFCE Operator USB Baseline + 102| + 103|The active branch target is the XFCE live operator USB. Authoritative state + 104|lives in `packages/` (what ships) and `PLAN-OPERATOR-USB-NEXT.md` (round-scope + 105|decisions and any "for now" retention notes). Final graphical validation + 106|requires real hardware — do not treat bhyve, nested VMs, or static image + 107|inspection as final proof that SDDM/XFCE works. + 108| + 109|--- + 110| + 111|## System Configuration + 112| + 113|**Privilege model:** distinguish build-host administration from live-USB runtime. + 114| + 115|- On the FreeBSD 15 build host, operator-facing commands may use `sudo`. + 116|- Inside the live USB, `sudo` is intentionally absent (deleted via `pkg delete -f sudo`). + 117|- Live privileged actions use FreeBSD `mac_do` via `mdo -u root `. + 118|- `~/.bashrc` aliases `sudo` → `mdo -u root` for muscle-memory compatibility. + 119| The shell function wraps `mdo` with a fire-and-forget ZFS snapshot + 120| (`zroot@cli-`) before each privileged invocation, so rollback + 121| is always available without confirmation prompts or warning popups. + 122|- Agent runtime code must not shell out to `sudo` for privileged host changes. + 123|- Privileged Clawdie-AI host operations go through the hostd RPC layer. + 124| + 125|**Why `sudo` as alias, not as pkg:** + 126| + 127|| Approach | Install sudo pkg | Alias to mdo | + 128|| ------------------- | ------------------------ | ---------------------------- | + 129|| Extra package | Yes (sudo + deps) | No | + 130|| Two privilege paths | `sudo` AND `mdo` coexist | Single path (`mdo`) | + 131|| Audit surface | Two tools to audit | One kernel-enforced MAC | + 132|| ZFS safety net | Requires sudoers hooks | Built into bash function | + 133|| Agent confusion | Agents try both paths | Agents use `sudo`, get `mdo` | + 134|| ISO size | Larger | Zero bytes | + 135| + 136|The alias approach keeps the ISO lean, eliminates dual-privilege-path + 137|confusion, and bakes ZFS rollback safety directly into the operator shell. + 138|`mac_do` is FreeBSD base system — no package dependency, kernel-enforced, + 139|auditable via MAC framework. + 140| + 141|--- + 142| + 143|## Installer Temp Files + 144| + 145|The GUI installer uses `/tmp/clawdie-install.conf` to pass wizard values to + 146|`firstboot.sh`. This is an exemption from the project-local `tmp/` rule. + 147| + 148|**Rationale:** + 149| + 150|- Live ISO has no project root + 151|- Single-user install phase (no other users on the system) + 152|- File is consumed once by `firstboot.sh` then deleted on reboot + 153|- PF firewall is not yet running during install + 154| + 155|**Applies to:** + 156| + 157|- `/tmp/clawdie-install.conf` — GUI wizard config output + 158|- `/tmp/clawdie-firstboot.*` — firstboot progress and log (written by rc.d) + 159| + 160|## Repo-local ISO Build Workspace + 161| + 162|ISO builds use repo-local `tmp/` for large caches and output artifacts: + 163| + 164|- `tmp/cache` — build cache + 165|- `tmp/cache/mnt` — temporary md(4) work-image mountpoint + 166|- `tmp/output` — generated `.img.gz` artifacts and checksums + 167|- `tmp/packages` — fetched package archives + 168| + 169|`tmp/cache/mnt` is an ISO-builder-specific mountpoint exception. Do not mount + 170|unrelated datasets, recovery filesystems, or scratch filesystems elsewhere under + 171|repo `tmp/`. If a build is interrupted, use the `iso-build-cleanup` skill before + 172|retrying. + 173| + 174|--- + 175| + 176|## Cross-Repo Coordination + 177| + 178|Clawdie spans three repos. Changes often require coordinated updates. + 179| + 180|| Repo | Purpose | Remote | + 181|| ------------- | ---------------------------------------- | ------------------------------------------ | + 182|| `Clawdie-AI` | Agent runtime, control plane, channels | `git@codeberg.org:Clawdie/Clawdie-AI.git` | + 183|| `clawdie-iso` | ISO builder, firstboot wizard, installer | `git@codeberg.org:Clawdie/Clawdie-ISO.git` | + 184|| `Colibri` | Cross-platform Rust control plane core | `git@codeberg.org:Clawdie/Colibri.git` | + 185| + 186|When changes span repos, create a handoff doc in the secondary repo + 187|listing what needs updating. See `Clawdie-AI/AGENTS.md` for full protocol. + 188| + 189|--- + 190| + 191|## Agent Handoff Documents + 192| + 193|Use ephemeral handoff files to transfer context between agents. + 194| + 195|- **Name:** `doc/-HANDOFF.md` or `-HANDOFF.md` (repo root) + 196|- **Lifecycle:** Create when handing off, delete when complete + 197|- **Structure:** Must include task checklist, deletion criteria, results section + 198| + 199|See `Clawdie-AI/AGENTS.md` for the full handoff template and protocol. + 200| + 201|--- + 202| + 203|## Attribution in Commit History + 204| + 205|Use attribution in commit messages, not in code comments. + 206| + 207|Labels: + 208| + 209|- `Sam & Codex` — changes made by Sam and Codex + 210|- `Sam & Claude` — changes made by Sam and Claude + 211|- `C&C` — joint change with equal credit for Claude and Codex + 212| + 213|Add the label to the commit subject or body. Example: + 214| + 215|``` + 216|Fix bhyve preflight checks (C&C) + 217|``` + 218| \ No newline at end of file -- 2.45.3 From a2b6f6f1d3a53fc9a6e9737b9eaaa59fcbd16960 Mon Sep 17 00:00:00 2001 From: Sam & Hermes Date: Fri, 29 May 2026 11:58:19 +0200 Subject: [PATCH 13/15] docs: fix cross-repo table still pointing to Codeberg (Sam & Hermes) --- AGENTS.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c52785dc..e8cf6a2c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -177,11 +177,11 @@ 177| 178|Clawdie spans three repos. Changes often require coordinated updates. 179| - 180|| Repo | Purpose | Remote | - 181|| ------------- | ---------------------------------------- | ------------------------------------------ | - 182|| `Clawdie-AI` | Agent runtime, control plane, channels | `git@codeberg.org:Clawdie/Clawdie-AI.git` | - 183|| `clawdie-iso` | ISO builder, firstboot wizard, installer | `git@codeberg.org:Clawdie/Clawdie-ISO.git` | - 184|| `Colibri` | Cross-platform Rust control plane core | `git@codeberg.org:Clawdie/Colibri.git` | + | Repo | Purpose | Remote | + | ------------- | ---------------------------------------- | -------------------------------------------------- | + | `clawdie-ai` | Agent runtime, control plane, channels | `git@code.smilepowered.org:clawdie/clawdie-ai.git` | + | `clawdie-iso` | ISO builder, firstboot wizard, installer | `git@code.smilepowered.org:clawdie/clawdie-iso.git`| + | `Colibri` | Cross-platform Rust control plane core | `git@code.smilepowered.org:clawdie/colibri.git` | 185| 186|When changes span repos, create a handoff doc in the secondary repo 187|listing what needs updating. See `Clawdie-AI/AGENTS.md` for full protocol. -- 2.45.3 From 17379e484137669c401ed07b80885235016389a1 Mon Sep 17 00:00:00 2001 From: Sam & Hermes Date: Mon, 1 Jun 2026 06:22:18 +0200 Subject: [PATCH 14/15] fix: regenerate all icon caches, not just 4 hardcoded themes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced hardcoded icon theme list (hicolor/Adwaita/AdwaitaLegacy/Papirus) with a dynamic directory scan of /usr/local/share/icons/. Applications like pcmanfm and xfce4-terminal install into hicolor but were missed when the cache wasn't regenerated for all themes, causing broken launcher icons (blank/missing glyphs) on the panel and in the Whisker menu. Root cause: gtk-update-icon-cache was only run for the 4 known themes, but FreeBSD packages install icons into additional directories that weren't covered. The Clawdie visual assets (clawdie-operator-bg.png background + clawdie-start.png triangle icon) are already committed and referenced correctly in xfce4-desktop.xml and xfce4-panel.xml — no changes needed. --- build.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/build.sh b/build.sh index 9d127254..51c8c7b5 100755 --- a/build.sh +++ b/build.sh @@ -542,10 +542,13 @@ refresh_live_desktop_caches() { run_live_chroot /usr/local/bin/update-desktop-database /usr/local/share/applications fi if [ -x "${MOUNT_POINT}/usr/local/bin/gtk-update-icon-cache" ]; then - for _icon_theme in hicolor Adwaita AdwaitaLegacy Papirus; do - if [ -d "${MOUNT_POINT}/usr/local/share/icons/${_icon_theme}" ]; then - run_live_chroot /usr/local/bin/gtk-update-icon-cache -f -t "/usr/local/share/icons/${_icon_theme}" || true - fi + # Regenerate ALL installed icon theme caches, not just the four + # commonly expected ones. Applications install icons into hicolor + # and their own theme directories; missing caches cause broken + # launcher icons (pcmanfm, xfce4-terminal, firefox, etc.). + for _icon_theme_dir in "${MOUNT_POINT}/usr/local/share/icons"/*/; do + _theme_name=$(basename "$_icon_theme_dir") + run_live_chroot /usr/local/bin/gtk-update-icon-cache -f -t "/usr/local/share/icons/${_theme_name}" || true done fi -- 2.45.3 From 88c36118cddc956b0a951b4357c3b2b623f2e1ec Mon Sep 17 00:00:00 2001 From: Sam & Hermes Date: Mon, 1 Jun 2026 23:34:52 +0200 Subject: [PATCH 15/15] fix: install brand icons into hicolor, use themed name, add visual guard MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three root causes for missing XFCE icons found via live-USB hardware test: 1. XFCE plugins do not reliably load absolute icon paths — the Whisker Start button had button-icon=/usr/local/share/clawdie-iso/icons/... which silently failed to resolve. Changed to themed name "clawdie-start" and install the icon files into hicolor/48x48/apps/, 64x64/apps/, and scalable/apps/ where the icon theme lookup can find them. 2. Brand icons were only installed to /usr/local/share/clawdie-iso/icons/ but XFCE resolves themed icon names by scanning the icon theme directories. Now install clawdie-start.png/svg into hicolor as well. 3. XFCE creates monitor-specific desktop keys only after xfdesktop starts, which can override the skeleton wallpaper. Add a post-login visual guard that re-applies theme, panel, and wallpaper settings at 3/7/15 seconds. The dynamic icon-cache regeneration (all directories under icons/) is retained from the previous commit. Checks: sh -n build.sh clawdie-xfce-visuals-guard.sh clawdie-xfce-session-inner --- build.sh | 29 ++++++- .../clawdie-xfce-visuals-guard.desktop | 7 ++ .../clawdie-xfce-visuals-guard.sh | 87 +++++++++++++++++++ .../xfce-perchannel-xml/xfce4-panel.xml | 2 +- 4 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 live/operator-session/autostart/clawdie-xfce-visuals-guard.desktop create mode 100644 live/operator-session/clawdie-xfce-visuals-guard.sh diff --git a/build.sh b/build.sh index 51c8c7b5..046d743a 100755 --- a/build.sh +++ b/build.sh @@ -775,6 +775,8 @@ configure_live_operator_session() { "${MOUNT_POINT}/usr/local/bin/clawdie-bootstrap-launch.sh" install -m 0755 "${LIVE_SESSION_DIR}/clawdie-noblank-guard.sh" \ "${MOUNT_POINT}/usr/local/bin/clawdie-noblank-guard.sh" + install -m 0755 "${LIVE_SESSION_DIR}/clawdie-xfce-visuals-guard.sh" \ + "${MOUNT_POINT}/usr/local/bin/clawdie-xfce-visuals-guard.sh" install -m 0755 "${LIVE_SESSION_DIR}/hw-report" \ "${MOUNT_POINT}/usr/local/bin/hw-report" @@ -833,6 +835,8 @@ EOF "${MOUNT_POINT}/usr/local/etc/xdg/autostart/clawdie-bootstrap.desktop" install -m 0644 "${LIVE_SESSION_DIR}/autostart/clawdie-noblank-guard.desktop" \ "${MOUNT_POINT}/usr/local/etc/xdg/autostart/clawdie-noblank-guard.desktop" + install -m 0644 "${LIVE_SESSION_DIR}/autostart/clawdie-xfce-visuals-guard.desktop" \ + "${MOUNT_POINT}/usr/local/etc/xdg/autostart/clawdie-xfce-visuals-guard.desktop" mkdir -p "${MOUNT_POINT}/usr/local/etc/X11/xorg.conf.d" install -m 0644 "${LIVE_SESSION_DIR}/xorg.conf.d/30-keyboard.conf" \ "${MOUNT_POINT}/usr/local/etc/X11/xorg.conf.d/30-keyboard.conf" @@ -1381,14 +1385,31 @@ EOF cp "${_wallpapers_dir}"/* "${MOUNT_POINT}/usr/local/share/clawdie-iso/wallpapers/" 2>/dev/null || true fi - # Brand icons (e.g. the Whisker Start-button triangle). Referenced by - # absolute path from xfce4-panel.xml so the button never depends on an - # icon-theme cache being current at first login. + # Brand icons (e.g. the Whisker Start-button triangle). Install both the + # raw files for direct diagnostics and hicolor theme names for XFCE plugins + # that do not reliably load absolute icon paths. _icons_dir="${LIVE_SESSION_DIR}/icons" if [ -d "$_icons_dir" ]; then echo " Installing brand icons..." - mkdir -p "${MOUNT_POINT}/usr/local/share/clawdie-iso/icons" + mkdir -p \ + "${MOUNT_POINT}/usr/local/share/clawdie-iso/icons" \ + "${MOUNT_POINT}/usr/local/share/icons/hicolor/48x48/apps" \ + "${MOUNT_POINT}/usr/local/share/icons/hicolor/64x64/apps" \ + "${MOUNT_POINT}/usr/local/share/icons/hicolor/scalable/apps" cp "${_icons_dir}"/* "${MOUNT_POINT}/usr/local/share/clawdie-iso/icons/" 2>/dev/null || true + if [ -f "${_icons_dir}/clawdie-start.png" ]; then + install -m 0644 "${_icons_dir}/clawdie-start.png" \ + "${MOUNT_POINT}/usr/local/share/icons/hicolor/48x48/apps/clawdie-start.png" + install -m 0644 "${_icons_dir}/clawdie-start.png" \ + "${MOUNT_POINT}/usr/local/share/icons/hicolor/64x64/apps/clawdie-start.png" + fi + if [ -f "${_icons_dir}/clawdie-start.svg" ]; then + install -m 0644 "${_icons_dir}/clawdie-start.svg" \ + "${MOUNT_POINT}/usr/local/share/icons/hicolor/scalable/apps/clawdie-start.svg" + fi + if [ -x "${MOUNT_POINT}/usr/local/bin/gtk-update-icon-cache" ]; then + run_live_chroot /usr/local/bin/gtk-update-icon-cache -f -t /usr/local/share/icons/hicolor || true + fi fi rm -rf "${MOUNT_POINT}/home/clawdie/.cache" "${MOUNT_POINT}/etc/skel/.cache" diff --git a/live/operator-session/autostart/clawdie-xfce-visuals-guard.desktop b/live/operator-session/autostart/clawdie-xfce-visuals-guard.desktop new file mode 100644 index 00000000..f817d6b2 --- /dev/null +++ b/live/operator-session/autostart/clawdie-xfce-visuals-guard.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Type=Application +Name=Clawdie XFCE Visuals Guard +Comment=Re-assert wallpaper, theme, and panel settings after XFCE creates monitor-specific state +Exec=/usr/local/bin/clawdie-xfce-visuals-guard.sh +X-GNOME-Autostart-enabled=true +NoDisplay=true diff --git a/live/operator-session/clawdie-xfce-visuals-guard.sh b/live/operator-session/clawdie-xfce-visuals-guard.sh new file mode 100644 index 00000000..97a38e26 --- /dev/null +++ b/live/operator-session/clawdie-xfce-visuals-guard.sh @@ -0,0 +1,87 @@ +#!/bin/sh +# Best-effort live-session visual guard for XFCE. +# +# XFCE may create monitor-specific desktop keys only after xfdesktop starts, and +# some panel plugins are stricter about themed icon names than absolute paths. +# Re-assert the operator USB visual contract after login without failing the +# session if a component is missing. + +LOG="${HOME}/.clawdie-xfce-visuals-guard.log" +WALLPAPER="/usr/local/share/clawdie-iso/wallpapers/clawdie-operator-bg.png" +START_ICON="clawdie-start" + +log() { + printf '%s %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "$*" >>"$LOG" 2>/dev/null || true +} + +set_xfconf() { + _channel="$1" + _property="$2" + _type="$3" + _value="$4" + + command -v xfconf-query >/dev/null 2>&1 || return 0 + xfconf-query -c "$_channel" -p "$_property" -s "$_value" >/dev/null 2>&1 || \ + xfconf-query -c "$_channel" -p "$_property" -n -t "$_type" -s "$_value" >/dev/null 2>&1 || true +} + +apply_theme() { + set_xfconf xsettings /Net/ThemeName string Greybird + set_xfconf xsettings /Net/IconThemeName string Papirus + set_xfconf xsettings /Net/CursorTheme string DMZ-White + set_xfconf xsettings /Net/CursorSize int 24 + set_xfconf xsettings /Gtk/FontName string "Noto Sans 11" + set_xfconf xsettings /Gtk/MonospaceFontName string "Hack 11" +} + +apply_panel() { + set_xfconf xfce4-panel /plugins/plugin-1/button-icon string "$START_ICON" + set_xfconf xfce4-panel /plugins/plugin-1/show-button-icon bool true + set_xfconf xfce4-panel /plugins/plugin-1/show-button-title bool true + set_xfconf xfce4-panel /panels/panel-1/size uint 40 + set_xfconf xfce4-panel /panels/panel-1/icon-size uint 2 + set_xfconf xfce4-panel /plugins/plugin-8/square-icons bool true +} + +apply_wallpaper() { + [ -f "$WALLPAPER" ] || { + log "wallpaper missing: $WALLPAPER" + return 0 + } + command -v xfconf-query >/dev/null 2>&1 || return 0 + + _bases="$(xfconf-query -c xfce4-desktop -l 2>/dev/null | awk '/\/last-image$/ { sub(/\/last-image$/, ""); print }')" + if [ -z "$_bases" ]; then + _bases='/backdrop/screen0/monitor0/workspace0 +/backdrop/screen0/monitorDefault/workspace0' + fi + + printf '%s\n' "$_bases" | while IFS= read -r _base; do + [ -n "$_base" ] || continue + set_xfconf xfce4-desktop "${_base}/last-image" string "$WALLPAPER" + set_xfconf xfce4-desktop "${_base}/image-path" string "$WALLPAPER" + set_xfconf xfce4-desktop "${_base}/image-style" int 5 + set_xfconf xfce4-desktop "${_base}/image-show" bool true + set_xfconf xfce4-desktop "${_base}/color-style" int 0 + done + + if command -v xfdesktop >/dev/null 2>&1; then + xfdesktop --reload >/dev/null 2>&1 || true + fi +} + +run_once() { + log "applying XFCE visual guard" + apply_theme + apply_panel + apply_wallpaper +} + +# Run more than once because xfdesktop/panel may create monitor/plugin state +# after XDG autostart begins. +sleep 3 +run_once +sleep 7 +run_once +sleep 15 +run_once diff --git a/live/operator-session/panel-skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml b/live/operator-session/panel-skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml index 1c021c56..8acfbbc2 100644 --- a/live/operator-session/panel-skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml +++ b/live/operator-session/panel-skel/.config/xfce4/xfconf/xfce-perchannel-xml/xfce4-panel.xml @@ -44,7 +44,7 @@ - + -- 2.45.3