diff --git a/AGENTS.md b/AGENTS.md index 9950626..ba20349 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -136,19 +136,47 @@ inspection as final proof that SDDM/XFCE works. --- -## Installer Temp Files +## Scratch / Temporary Files Policy + +Agents must use the project-local scratch workspace for repo work instead of +system-global `/tmp` paths. Treat the repo root as `$PROJECT_ROOT` and use: + +```sh +PROJECT_ROOT=$(git rev-parse --show-toplevel) +PROJECT_TMP="$PROJECT_ROOT/tmp" +mkdir -p "$PROJECT_TMP" +``` + +Use `$PROJECT_TMP/...` for generated checks, transient logs, extracted manifests, +image-inspection notes, helper-script test output, and other disposable files. +Do not create new `/tmp/clawdie-*`, `/tmp/colibri-*`, or ad-hoc `/tmp/...` paths +from agent work unless the operator explicitly asks for a host-global scratch +location. + +Live-USB runtime code usually has no git checkout/project root. In that case, +prefer an app-owned cache/state path such as `$XDG_CACHE_HOME/clawdie`, +`$HOME/.cache/clawdie`, `/var/cache/clawdie`, or `/var/db/clawdie` rather than +`/tmp`. If a runtime helper supports both modes, it should use `$PROJECT_ROOT/tmp` +when a project root is detectable and fall back to the app-owned live path. + +Known platform/tooling exceptions should stay narrow and documented: Xorg's +standard `/tmp/.X11-unix` / `/tmp/.X*-lock`, bsdinstall handoff files, and the +installer handoff below. + +### Installer Temp Files Exception 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. +`firstboot.sh`. This is the narrow historical exemption from the project-local +`tmp/` rule. **Rationale:** -- Live ISO has no project root +- Live ISO has no project root during the installer handoff - 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:** +**Applies only to:** - `/tmp/clawdie-install.conf` — GUI wizard config output - `/tmp/clawdie-firstboot.*` — firstboot progress and log (written by rc.d) diff --git a/live/operator-session/clawdie-join-hive.sh b/live/operator-session/clawdie-join-hive.sh index 1d0984d..e5cf347 100755 --- a/live/operator-session/clawdie-join-hive.sh +++ b/live/operator-session/clawdie-join-hive.sh @@ -127,12 +127,26 @@ fi echo "[4/4] Agent ${AGENT_NAME} is live on the Colibri board." echo "" -if have clawdie-wallpaper-gen; then +if have clawdie-wallpaper-gen && have xfconf-query; then echo " Setting identity wallpaper..." - if have xfconf-query; then - WP="/tmp/clawdie-wallpaper.png" - clawdie-wallpaper-gen "$WP" 2>/dev/null && \ - xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/workspace0/last-image -s "$WP" 2>/dev/null + # Let the generator pick a policy-compliant path (project-local tmp/ or an + # app-owned cache dir) and report it on stdout — no host-global /tmp here. + WP=$(clawdie-wallpaper-gen 2>/dev/null) + if [ -n "$WP" ] && [ -f "$WP" ]; then + # XFCE keys backdrops by connector name (monitorHDMI-1, monitoreDP-1, ...), + # not a fixed "monitor0". Set every existing last-image property so the + # change actually applies on real hardware. + _applied=0 + for _prop in $(xfconf-query -c xfce4-desktop -l 2>/dev/null | grep '/last-image$'); do + xfconf-query -c xfce4-desktop -p "$_prop" -s "$WP" 2>/dev/null && _applied=1 + done + # First boot / headless: no backdrop props exist yet — create the default. + if [ "$_applied" -eq 0 ]; then + xfconf-query -c xfce4-desktop \ + -p /backdrop/screen0/monitor0/workspace0/last-image \ + -n -t string -s "$WP" 2>/dev/null + fi + xfdesktop --reload >/dev/null 2>&1 || true fi fi diff --git a/live/operator-session/clawdie-noblank-guard.sh b/live/operator-session/clawdie-noblank-guard.sh index 64d6bf7..f56290d 100644 --- a/live/operator-session/clawdie-noblank-guard.sh +++ b/live/operator-session/clawdie-noblank-guard.sh @@ -5,7 +5,9 @@ # session startup. This guard makes the policy explicit at the desktop level. _uid="$(id -u 2>/dev/null || echo unknown)" -_lock="/tmp/clawdie-noblank-guard.${_uid}.lock" +_runtime_dir="${XDG_RUNTIME_DIR:-${HOME}/.cache/clawdie/runtime}" +mkdir -p "${_runtime_dir}" 2>/dev/null || true +_lock="${_runtime_dir}/clawdie-noblank-guard.${_uid}.lock" _log="${HOME}/.clawdie-noblank-guard.log" if ! mkdir "${_lock}" 2>/dev/null; then diff --git a/live/operator-session/clawdie-vault-fetch b/live/operator-session/clawdie-vault-fetch index 0a116f1..ccc8ac6 100644 --- a/live/operator-session/clawdie-vault-fetch +++ b/live/operator-session/clawdie-vault-fetch @@ -97,7 +97,10 @@ if [ -z "${BW_CLIENTID:-}" ] || [ -z "${BW_CLIENTSECRET:-}" ] || [ -z "${BW_PASS exit 1 fi -WORK="$(mktemp -d "${TMPDIR:-/tmp}/clawdie-vault.XXXXXX")" +RUNTIME_BASE="${XDG_RUNTIME_DIR:-${HOME}/.cache/clawdie/runtime}" +mkdir -p "$RUNTIME_BASE" +chmod 700 "$RUNTIME_BASE" 2>/dev/null || true +WORK="$(mktemp -d "${RUNTIME_BASE}/clawdie-vault.XXXXXX")" # Lock the vault on any exit; never leave an unlocked session behind. cleanup() { bw lock >/dev/null 2>&1 || true diff --git a/live/operator-session/clawdie-wallpaper-gen.sh b/live/operator-session/clawdie-wallpaper-gen.sh index bca2bdd..eb45c8e 100755 --- a/live/operator-session/clawdie-wallpaper-gen.sh +++ b/live/operator-session/clawdie-wallpaper-gen.sh @@ -1,33 +1,91 @@ #!/bin/sh # Generate a wallpaper with machine identity overlaid. -# Run once on first boot, caches result in /tmp/clawdie-wallpaper.png. -# Requires: ImageMagick (convert), tailscale, colibri socket. +# Safe to run on first boot; caches result in project-local tmp/ when a project +# root is available, otherwise in the live user's app-owned cache directory. +# Requires ImageMagick (magick or convert). Tailscale is optional. -set -e +CLAWDIE_BG="/usr/local/share/clawdie-iso/wallpapers/clawdie-operator-bg.png" +XFCE_BG="/usr/local/share/backgrounds/xfce/default.png" -OUT="${1:-/tmp/clawdie-wallpaper.png}" -BG="/usr/local/share/backgrounds/xfce/default.png" +have() { + command -v "$1" >/dev/null 2>&1 +} -HOST=$(hostname) -TS_IP=$(tailscale ip -4 2>/dev/null || echo "offline") -COLIBRI_SOCK="/var/run/colibri/colibri.sock" -COLIBRI_PORT="9190" -JAIL_RELEASE=$(freebsd-version 2>/dev/null || uname -r) +project_root() { + if [ -n "${CLAWDIE_PROJECT_ROOT:-}" ]; then + printf '%s\n' "$CLAWDIE_PROJECT_ROOT" + elif have git && git rev-parse --show-toplevel >/dev/null 2>&1; then + git rev-parse --show-toplevel + else + return 1 + fi +} -# Fall back to a solid colour if no background image exists -if [ ! -f "$BG" ]; then - convert -size 1920x1080 xc:'#1a1a2e' "$BG" 2>/dev/null || true +scratch_dir() { + if [ -n "${CLAWDIE_TMP:-}" ]; then + printf '%s\n' "$CLAWDIE_TMP" + elif _root=$(project_root); then + printf '%s/tmp\n' "$_root" + elif [ -n "${XDG_CACHE_HOME:-}" ]; then + printf '%s/clawdie\n' "$XDG_CACHE_HOME" + elif [ -n "${HOME:-}" ]; then + printf '%s/.cache/clawdie\n' "$HOME" + else + printf '%s\n' "/var/cache/clawdie" + fi +} + +if have magick; then + im() { magick "$@"; } +elif have convert; then + im() { convert "$@"; } +else + echo "ERROR: ImageMagick is not installed; expected magick or convert." >&2 + exit 1 fi -# One-liner draw: place identity text in the bottom-left corner -convert "$BG" \ - -font Helvetica -pointsize 18 -fill '#e0e0e0' \ +SCRATCH_DIR=$(scratch_dir) +mkdir -p "$SCRATCH_DIR" +OUT="${1:-${SCRATCH_DIR}/clawdie-wallpaper.png}" +FALLBACK_BG="${SCRATCH_DIR}/clawdie-wallpaper-base.png" + +HOST=$(hostname 2>/dev/null || echo "clawdie-live") +if have tailscale; then + TS_IP=$(tailscale ip -4 2>/dev/null | head -n 1) +fi +[ -n "${TS_IP:-}" ] || TS_IP="offline" +COLIBRI_SOCK="/var/run/colibri/colibri.sock" +COLIBRI_PORT="9190" +JAIL_RELEASE=$(freebsd-version 2>/dev/null || uname -r 2>/dev/null || echo "unknown") + +if [ -f "$CLAWDIE_BG" ]; then + BG="$CLAWDIE_BG" +elif [ -f "$XFCE_BG" ]; then + BG="$XFCE_BG" +else + BG="$FALLBACK_BG" + im -size 1920x1080 xc:'#1a1a2e' "$BG" +fi + +SOCK_STATUS="down" +[ -S "$COLIBRI_SOCK" ] && SOCK_STATUS="socket ${COLIBRI_PORT}" + +# Overlay identity text in the bottom-left corner. Do not require a specific +# font: ImageMagick's default font is more portable across FreeBSD package sets. +if ! im "$BG" \ + -pointsize 18 -fill '#e0e0e0' \ -annotate +40+900 "hostname ${HOST}" \ -annotate +40+930 "tailscale ${TS_IP}" \ - -annotate +40+960 "colibri ${COLIBRI_PORT}" \ + -annotate +40+960 "colibri ${SOCK_STATUS}" \ -annotate +40+990 "jail ${JAIL_RELEASE}" \ - -font Helvetica-Bold -pointsize 28 -fill '#8b5cf6' \ + -pointsize 28 -fill '#8b5cf6' \ -annotate +40+850 "Clawdie OS" \ - "$OUT" + "$OUT"; then + echo "WARNING: identity overlay failed; copying base wallpaper instead." >&2 + cp "$BG" "$OUT" +fi -echo "Wallpaper: ${OUT}" +# stdout is the bare output path (machine-readable for callers that capture it, +# e.g. `WP=$(clawdie-wallpaper-gen)`); human-facing note goes to stderr. +echo "Wallpaper: ${OUT}" >&2 +printf '%s\n' "$OUT" diff --git a/scripts/test-release-gate.sh b/scripts/test-release-gate.sh index aee0e2b..6bd8db2 100755 --- a/scripts/test-release-gate.sh +++ b/scripts/test-release-gate.sh @@ -14,7 +14,9 @@ set -eu SCRIPT_DIR=$(cd "$(dirname "$0")/.." && pwd) BUILD_SH="${SCRIPT_DIR}/build.sh" -TMP=$(mktemp -d "${TMPDIR:-/tmp}/release-gate-test.XXXXXX") +PROJECT_TMP="${SCRIPT_DIR}/tmp" +mkdir -p "${PROJECT_TMP}" +TMP=$(mktemp -d "${PROJECT_TMP}/release-gate-test.XXXXXX") trap 'rm -rf "${TMP}"' EXIT fail=0 check() { if [ "$1" = "$2" ]; then echo "ok - $3"; else echo "FAIL - $3 (want '$2', got '$1')"; fail=1; fi; } diff --git a/skills/iso-build/SKILL.md b/skills/iso-build/SKILL.md index ba88e90..38443c3 100644 --- a/skills/iso-build/SKILL.md +++ b/skills/iso-build/SKILL.md @@ -188,7 +188,8 @@ longer needed: ```sh cd /home/clawdie/ai/colibri cargo clean -rm -rf /tmp/colibri-* +mkdir -p tmp/iso-build +rm -rf tmp/iso-build/* ``` `colibri-mcp` is part of the out-of-the-box operator USB. `colibri-tui` is