Commit graph

463 commits

Author SHA1 Message Date
Sam & Claude
7b245d6f65 feat(iso): ship kitty.conf + tmux.conf defaults and xterm rescue fallback
Closes the OOTB config gaps from the kitty swap (b4c86b6). Kitty installed but
shipped with bare defaults and no tmux passthrough; rescue path lost its
headless fallback when xfce4-terminal was removed.

Changes:
- panel-skel/.config/kitty/kitty.conf: font 13pt (Hack, from hack-font pkg),
  quiet-dark theme + full 16-color palette, scrollback, tab bar, beam cursor.
  Lands at ~/.config/kitty/kitty.conf for the clawdie user via existing
  panel-skel staging (no build.sh change).
- panel-skel/.config/tmux/tmux.conf: extended-keys on + csi-u so modifier
  keys (Shift-Enter, Ctrl-Arrow, Alt-Enter) reach TUIs (pi, zot, colibri-tui)
  run inside tmux. XDG path (~/.config/tmux/tmux.conf), read natively by the
  live USB's tmux 3.5a. Plus escape-time 0, focus-events, mouse, sane indexing.
- clawdie-xfce-session-inner: rescue terminal now falls back kitty -> xterm.
  Kitty is GPU-only; without a GL surface (bhyve no-GPU VMs) it can fail to
  start, leaving the operator with no rescue shell. xterm stays installed.

No build.sh change needed: both configs ride the existing
`cp -R panel-skel/.config/.` into /etc/skel/.config and /home/clawdie/.config
(build.sh:2087, :2095).

Pre-merge: confirm `pkg search kitty` on the FreeBSD build host (couldn't
reach the network from the dev sandbox).

(Sam & Claude)
2026-06-25 20:24:55 +02:00
b4c86b68f4 feat(iso): replace xfce4-terminal with kitty
Kitty: GPU-accelerated, keyboard-driven, respects terminal color themes,
supports modern escape codes ratatui uses (REVERSED, italic, true color).

Changes:
- pkg-list-xfce.txt: kitty replaces xfce4-terminal
- 3 desktop launchers: Exec=kitty with -T (title) + -o window size
- Panel indicator: kitty for colibri status
- Session rescue: kitty for desktop rescue terminal
- Panel config: kitty.desktop in launcher-4
- BUILD.md: docs updated
2026-06-25 20:03:39 +02:00
c76345cd29 Merge pull request 'fix: atomic write of provider.env in enable-mother' (#144) from fix/atomic-provider-env into main
Reviewed-on: #144
2026-06-25 14:07:38 +02:00
adb8cd1725 fix: atomic write of provider.env in enable-mother
Step 4 of clawdie-enable-mother.sh rewrote provider.env in place with
`cat "$tmp" >"$f"`, which truncates the live secrets file before
streaming the new content. A crash, signal, disk-full, or concurrent
read during that window leaves provider.env empty or partial — and the
colibri_daemon prestart sources it for the provider key + BW_* creds.

Switch to the write-temp-then-rename pattern already used for
external-mcp.json in step 3: mktemp in provider.env's own directory (so
the rename stays on one filesystem and is atomic), chmod 0600 before the
swap, then mv. A reader now always sees a complete file, old or new.

Also add jq to the disk-install extras so disk-deployed hosts can run
the script post-deploy (step 3 hard-requires jq; the live image already
ships it).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:02:46 +02:00
4e244274c0 Merge pull request 'build: bump FreeBSD to 15.1-RELEASE (override-friendly, de-versioned docs)' (#143) from bump-freebsd-15.1 into main
Reviewed-on: #143
2026-06-25 13:18:42 +02:00
bfc9748052 Merge pull request 'refactor(build): clearer skip-fetch flag names (--skip-fetch / -pkg / -memstick)' (#142) from clearer-skip-fetch-flags into main
Reviewed-on: #142
2026-06-25 13:18:08 +02:00
3589cd1e53 build: bump FreeBSD to 15.1-RELEASE, make it override-friendly, de-version docs
- build.cfg: FREEBSD_VERSION -> ${FREEBSD_VERSION:-15.1-RELEASE}. The memstick
  URL, checksum URL, cache path, and build-manifest all derive from it, so the
  live-USB build bumps from this one line. The :- form also lets an operator
  override at build time (FREEBSD_VERSION=15.2-RELEASE ./build.sh) without
  editing git — previously a plain assignment clobbered any env value.
- docs: de-version README/BUILD/REQUIREMENTS + iso-build skill from '15.0' to
  '15.x' so they stop drifting on every point release.

Verified: default derives the 15.1 memstick URL (HTTP 200, dated 12.jun.2026);
env override cascades to 15.2. ABI stays FreeBSD:15:amd64 (same major — no
package rebuild needed). build-vps.sh (mfsbsd) and poudriere keep their own
version knobs and are intentionally untouched (ABI-compatible, separate paths).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:35:30 +02:00
ed4d03f201 refactor(build): clearer skip-fetch flag names
Rename the fetch-skip flags to a consistent, descriptive scheme:
  --skip-fetch            skip BOTH fetches (packages + memstick) — assemble from cache
  --skip-fetch-pkg        skip only the package + Clawdie-AI fetch (new granular)
  --skip-fetch-memstick   skip only the FreeBSD memstick fetch (was --skip-memstick-fetch)

Internals split SKIP_FETCH into SKIP_PKG_FETCH + SKIP_MEMSTICK_FETCH; the umbrella
--skip-fetch sets both. The memstick step collapses to a clean skip-or-fetch (the
old three-branch form only existed to couple the pkg-skip flag to memstick reuse,
which the split removes). No legacy alias kept — the flag names state the current
way directly.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 09:05:16 +02:00
1987531960 Merge pull request 'feat/combined-0.12' (#140) from feat/combined-0.12 into main
Reviewed-on: #140
2026-06-25 07:24:54 +02:00
0f9980c44c Merge pull request 'fix(seed): add TELEGRAM_BOT_TOKEN to seed key extraction (lost in #139 merge)' (#141) from fix/telegram-seed into main
Reviewed-on: #141
2026-06-25 07:24:21 +02:00
6998480cad fix(seed): add TELEGRAM_BOT_TOKEN to seed key extraction (lost in #139 merge) 2026-06-25 07:23:41 +02:00
a29afa4b14 Merge pull request 'feat(firstboot): force root + operator password on first boot (console gate)' (#139) from force-root-password-on-first-boot into main
Reviewed-on: #139
2026-06-25 07:21:31 +02:00
c940c51c51 feat(seed): include TELEGRAM_BOT_TOKEN in seed key extraction 2026-06-25 07:19:33 +02:00
ea045261e9 merge: firstboot root-password gate + seed infrastructure 2026-06-25 07:14:17 +02:00
2fa7825f12 fix(iso): bind colibri_daemon_require_secured=YES to complete the interlock
The rc.conf.sample on the live USB now sets require_secured=YES.
Together with the paired colibri change, this ensures the daemon
disables autospawn until the console gate writes .secured.
2026-06-25 07:05:16 +02:00
73b603d995 feat(firstboot): opt-in require-secured knob + 'will not' skip message
clawdie-iso half of the .secured interlock:
- build.sh writes colibri_daemon_require_secured="YES" to the operator image's
  rc.conf. Opt-in so DEPLOYED colibri hosts (shared colibri_daemon.in via the
  FreeBSD port, no firstboot gate) are unaffected — they never set this knob.
- gate skip message upgraded to 'agent will NOT start or register until secured'.

Depends on the colibri-side consumer (colibri_daemon.in prestart): when
colibri_daemon_require_secured is YES and /var/db/colibri/.secured is absent,
export COLIBRI_AUTOSPAWN=NO (after the provider.env source block). Tracked as the
colibri follow-up; both must ship in the same 0.12 image for the message to hold.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:16:34 +02:00
e135c305a4 docs(firstboot): make the skip message honest about unsecured state
The '.secured' marker is written but not yet consumed by colibri, so the gate
must not imply colibri/zot are blocked. Reword the skip message to state the
node is UNSECURED and the agent SHOULD NOT register/run while unsecured — true
as a policy statement, without claiming enforcement we haven't built. Upgrade to
'will not' once the colibri .secured interlock lands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:08:14 +02:00
f428bc7fcb feat(firstboot): visible 'Continuing in 3s 2s 1s' countdown before boot resumes
Replace the silent trailing sleeps with a counting-down message so the operator
sees the result (secured / skipped) and a clear cue before clawdie_live_gpu
repaints the screen. Same ~3s pause, now visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 06:02:01 +02:00
70731cddda fix(firstboot): run the password gate before the GPU/KMS switch
Reorder the gate to REQUIRE: FILESYSTEMS devfs / BEFORE: clawdie_live_gpu LOGIN
so it runs on the plain early boot text console, before clawdie_live_gpu does its
KMS/framebuffer mode-switch. That removes the console-flush race entirely, so the
sleep 1 + screen-clear workaround is gone. Still before LOGIN, hence before sddm
and colibri_daemon (race-free property preserved).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 05:59:05 +02:00
0cd59efa6d feat(firstboot): force root + operator password on first boot (console gate)
Adds clawdie_firstboot_rootpw, an rc.d gate ordered BEFORE sddm and
colibri_daemon. On the text console (operator present at first boot) it runs a
15s countdown to engage; if engaged it forces a root AND operator (clawdie)
password, echo-off, applied via 'pw usermod -h 0' over stdin (secret never in
argv/ps, never near the agent). Idempotent via a persistent success marker
/var/db/colibri/.secured (/var persists: varmfs=NO). Skipping leaves the node
open and re-prompts next boot — never bricks an unattended/headless boot.

Running before the daemon means the security decision is always made before any
agent can autospawn/node_register, so no cross-component interlock is needed
(rc ordering replaces it). The .secured marker is also the signal a future
colibri change can read to label an unsecured node to mother.

Tests: tests/firstboot-rootpw-test.sh proves marker skip, password validation,
and that the secret is delivered on stdin and NEVER appears in argv (10/10).

Console interactivity (read -t countdown, stty echo-off on /dev/console) must be
verified by booting on osa/bhyve before merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 05:54:13 +02:00
1a67d8a45c Merge pull request 'feat(seed): OOTB zot seed — AGENTS.md→ZOT_HOME, content + staging, regression tests' (#137) from feat/seed-population into main
Reviewed-on: #137
2026-06-25 05:09:31 +02:00
2beaf89ff8 Merge pull request 'feat(seed): install AGENTS.md from seed to zot's ZOT_HOME global slot' (#138) from feat/seed-agents-md into main
Reviewed-on: #138
2026-06-25 05:09:00 +02:00
5df307aaf4 test(seed): add Layer 0 importer + Layer 2 MCP-boundary regression tests
Layer 0 (seed-import-test.sh): runs the real clawdie-live-seed importer in a
sandbox (CLAWDIE_SEED_TEST=1, all paths overridden) and asserts the seed->runtime
propagation contract — env split, provider.env, dual-home ssh, soul staging, and
AGENTS.md -> $ZOT_HOME (the global slot the autospawned zot reads). Idempotent
re-import is checked. REQUIRE_AGENTS_MD=1 enforces the AGENTS.md install added on
this branch; it passes 23/23 here.

Layer 2 (mcp-boundary-test.sh): exercises the mother MCP-over-SSH boundary on
Linux — colibri-mcp-ssh forced-command allowlist (""/"tools" route, everything
else rejected) and the MCP tools/list handshake, including a real loopback sshd
with command=. Skips cleanly when colibri isn't a sibling checkout.

Verified end to end on Linux before merge: importer target path and the ZOT_HOME
pin in colibri (fix/zot-home) both resolve to /var/db/colibri/.local/state/zot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 05:03:23 +02:00
85ac1ceec5 fix(seed): close three OOTB gaps before merge
A. ZOT_VERSION drift: build.cfg defaulted to v0.2.42 while build.sh
   preflight hint said v0.2.47. Now both default to v0.2.47.

B. AGENTS.md hw-probe phrasing: told zot to run clawdie-hw-probe,
   but the daemon already collects it into CLAWDIE_HW_PROFILE at
   autospawn time. zot should read the env var, not shell out.

C. RPC_PROMPT missing: COLIBRI_AUTOSPAWN=YES starts zot in RPC mode,
   but without RPC_PROMPT, zot blocks on stdin and idles. Added
   a prompt telling zot to read CLAWDIE_HW_PROFILE, call node_register
   on mother, and report its assigned capabilities.
2026-06-25 04:38:06 +02:00
1a85f17733 feat(seed): populate CLAWDIESEED partition with agent operational files
Adds seed/ directory with:
- AGENTS.md: zot operational rules (mother, verbs, capabilities)
- harness.toml: harness="zot", model="deepseek-v4-pro"
- env.placeholder: template for API key injection

build.sh seed population step reads provider keys from the build host's
/usr/local/etc/colibri/provider.env and writes them to the seed partition's
env file. Also installs AGENTS.md, harness.toml, and the layered-soul backup.

Keys are NEVER committed — only placeholders. Real keys are injected at build
time from the build host's provider.env (DEEPSEEK_API_KEY, OPENROUTER_API_KEY).
2026-06-25 04:30:17 +02:00
06e8f4b77c feat(seed): install AGENTS.md from seed to zot's ZOT_HOME global slot
The seed importer already dual-writes SSH material to the daemon home.
Adds an AGENTS.md install block targeting /var/db/colibri/.local/state/zot/ —
the path pinned by colibri_daemon.in's ZOT_HOME export. Zot reads this as
its first AGENTS.md source, giving the autospawned agent operational rules
(mother, verbs, capabilities) on first boot.
2026-06-25 04:29:26 +02:00
62264e2aa4 Merge pull request 'build: pin zot agent to v0.2.47 in preflight hint' (#136) from pin-zot-v0.2.47 into main
Reviewed-on: #136
2026-06-24 19:13:25 +02:00
e3ccd7fa46 build: pin zot agent to v0.2.47 in preflight hint
The preflight checkout hint defaulted to v0.2.42 while the FreeBSD
build-lane handoff still named v0.2.29. Pin both to the current latest
zot tag (v0.2.47) so every reference the FreeBSD agent follows agrees,
and a release build targets one fixed agent version.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 19:11:19 +02:00
81e7259693 Merge pull request 'docs: remove superseded USB-mother plan and 0.11.0 handoff' (#135) from cleanup/iso-stale-docs into main
Reviewed-on: #135
2026-06-24 17:38:59 +02:00
Sam & Claude
02f719ff73 docs: remove stale USB-mother plan and 0.11.0 handoff 2026-06-24 17:28:52 +02:00
0336578ea4 Merge pull request 'docs: normalize prose dates to DD.mon.YYYY (iso)' (#134) from dates-eu-sweep into main 2026-06-24 16:45:37 +02:00
61683eeb42 docs: normalize prose dates to DD.mon.YYYY (AGENTS.md rule)
Convert US/ISO prose dates to EU format across iso docs (CHANGELOG, plans,
handoffs, wiki-linked docs). Left as-is (data, not prose): the sample log lines
in FIRSTBOOT.md and the ADMIN-PANEL.md UI mockup (timestamps/snapshot names);
ISO is correct for machine output.

Markdown format gate clean.
2026-06-24 16:44:37 +02:00
ae36b9f896 Merge pull request 'fix/ootb-mother-mcp' (#133) from fix/ootb-mother-mcp into main
Reviewed-on: #133
2026-06-24 11:32:03 +02:00
14dd2baa98 fix(iso): remove remaining real IPs, add -F robustness, prettier format, known_hosts note 2026-06-24 11:25:18 +02:00
dee76991de fix(iso): remove real IPs from image, install mother key for daemon user, de-obfuscate docs
Three blockers fixed from review of fix/ootb-mother-mcp:

1. Real Tailscale IP removed from image/repo.
   - external-mcp.json uses "mother" host alias (resolved by SSH config).
   - Key path: /var/db/colibri/.ssh/mother-mcp (daemon user home).
   - The real IP lives only on the offline seed (ssh/config), never in
     the repo or the shipped image.

2. Cross-user key access fixed.
   - The daemon runs as colibri (home /var/db/colibri), not clawdie.
   - Seed importer now installs SSH material to both clawdie AND
     colibri homes (same seed material, same key, separate ~/.ssh).
   - build.sh dev convenience also copies to both homes.
   - clawdie-live-seed.README.txt already documents the seed layout.

3. Doc fully de-obfuscated.
   - All m0th3r/c0l1br1/n0d3_r3g1st3r → mother/colibri/node_register.
   - All real IPs → <mother-tailscale-ip> placeholder.
   - Removed Step 2 (manual external MCP) + Step 3 (register) — both
     are now baked into the ISO.
   - Removed trailing "colibri-mcp" remote command from examples
     (hardened wrapper rejects non-allowlisted commands).
2026-06-24 11:19:21 +02:00
3fd3bc7560 fix(iso): pre-configure mother MCP OOTB + fix docs
Two changes so the USB connects to mother on first boot with no manual steps:

1. stage-colibri-iso.sh: external-mcp.json is now pre-configured with the
   mother server entry (colibri@100.72.229.63, no remote command — the
   hardened wrapper starts colibri-mcp in stdio MCP mode). Previously
   staged as empty {}; the operator had to create it manually or run
   clawdie-enable-mother.

2. provider.env now includes COLIBRI_MCP_EXTERNAL_CALL=1 by default
   (already set on osa; missing from the ISO defaults).

3. SETUP-USB-TO-MOTHER.md: removed Step 3 (manual external-mcp.json),
   fixed the diagram to match the hardened wrapper (no remote command),
   corrected the server name from "m0th3r"/"c0l1br1" to the real names.

The SSH key, config, and known_hosts still come from the CLAWDIESEED
seed partition — the image carries no secrets. Without the seed the
connection fails gracefully.
2026-06-24 11:04:36 +02:00
ca5a89b8ea Merge pull request 'docs: reconcile FEATURE_COLIBRI wording (internal flag, not 'no flag')' (#130) from residue-feature-colibri-doc into main
Reviewed-on: #130
2026-06-24 10:49:19 +02:00
22c678d40c Merge pull request 'fix(build): point agent-harness reference to AGENTS.md' (#131) from fix/adr-agent-harness-ref into main
Reviewed-on: #131
2026-06-24 10:48:50 +02:00
790bd45601 fix(build): point agent-harness reference to AGENTS.md 2026-06-24 10:47:29 +02:00
638e7c0c71 docs: reconcile FEATURE_COLIBRI wording (it is a flag, just internal)
README said 'no separate feature flag', but the build keeps FEATURE_COLIBRI
(build.cfg default YES) as an internal escape hatch (e.g. building without a
colibri checkout). Clarify: colibri is staged by default; FEATURE_COLIBRI=NO is
an internal build-time hatch, not a user-facing option. Resolves a wiki-ledger
residue item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 10:40:14 +02:00
6bd82eab26 Merge pull request 'mother: drop duplicate scripts from iso (canonical = colibri) + docs → hive_nodes' (#129) from iso-drop-mother-dup into main
Reviewed-on: #129
2026-06-24 10:18:42 +02:00
4298389f13 mother: drop duplicate scripts from iso; canonical = colibri; docs → hive_nodes
The mother MCP scripts were copied into clawdie-iso (packaging/mother/) AND
colibri. The iso copies drifted: node-register-mcp on iso main was the old,
SQL-injectable version (E'${HOST_ESCAPED}' string interpolation) using
usb_nodes — while colibri #161 carries the reviewed, parameterized (psql -v
:'var') hive_nodes version.

One canonical home: colibri. Remove packaging/mother/ from the iso (nothing in
the iso build references it), redirect the two doc path references to the colibri
repo, and align the docs to hive_nodes (matching the colibri schema rename).

Supersedes #127 (which only renamed docs and conflicted after the iso copies
landed). Doc-only + file removals; markdown gate green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 10:10:09 +02:00
eac844e239 Merge pull request 'feat/tailscale-vault-autojoin' (#128) from feat/tailscale-vault-autojoin into main
Reviewed-on: #128
2026-06-24 10:02:10 +02:00
a03c4a6b54 fix(build): rename osa-mother-2026 → mother-mcp in key paths 2026-06-24 09:18:12 +02:00
d001b46b34 feat(mother): add node-register MCP tool for USB hw-probe registration
New packaging/mother/node-register-mcp accepts JSON-RPC tools/call,
inserts hw_profile into mother_hive.usb_nodes, and returns the row
with auto-derived capabilities (derive_capabilities trigger fires).

Requires one-time PostgreSQL setup on mother:
  CREATE ROLE colibri WITH LOGIN;
  GRANT CONNECT ON DATABASE mother_hive TO colibri;
  GRANT INSERT, UPDATE ON usb_nodes TO colibri;
  GRANT USAGE ON SEQUENCE usb_nodes_id_seq TO colibri;

Also updates docs to reflect 0.12 daemon behavior: hw-probe is
collected by the daemon (not the agent) and passed via CLAWDIE_HW_PROFILE
env var. COLIBRI_AUTOSPAWN_ARGS default is binary-dependent (zot->rpc,
others->--mode json).
2026-06-24 09:07:48 +02:00
7c4975cfcf Merge pull request 'build: track Pi @latest + record resolved pi_version in manifest' (#126) from pi-latest-tracking into main
Reviewed-on: #126
2026-06-24 02:01:02 +02:00
fdbd6b152f build: track Pi @latest, record resolved version in build-manifest
The image shipped a hard pin (@earendil-works/pi-coding-agent@0.78.0) while
'pi upgrade' on hosts had moved to 0.80.2, so builds lagged. Switch Pi to the
@latest dist-tag so every image bundles the newest Pi.

To keep the floating spec traceable, record the version that actually got
fetched in build-manifest.json as pi_version, derived from the bundled tarball
name (earendil-works-pi-coding-agent-<version>.tgz) after fetch+install.
fetch-npm-globals.sh now also echoes the resolved tarball so the build log
shows the version a dist-tag resolved to.

Other globals (bw) stay pinned. Image is node24, compatible with current Pi
(the legacy-node20 dist-tag is for node20 only).

Verified: fetch resolves @latest → 0.80.2; version extraction matches npm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 01:59:29 +02:00
f3a719ab2c Merge pull request 'docs: rename 'fake-agent' → 'sample-agent'' (#125) from rename-sample-agent into main 2026-06-24 00:38:06 +02:00
52200c88c5 Merge pull request 'docs: harness-neutral cleanup + restore green markdown gate' (#124) from docs-harness-neutral-cleanup into main 2026-06-24 00:37:58 +02:00
da3f06f7da docs: rename 'fake-agent' → 'sample-agent' (matches colibri test rename)
Harness-neutral, lighter wording for the optional local test-double agent
(colibri-test-agent), matching the colibri-side fake→sample rename. Only the
two references that named it 'fake-agent' (build.cfg comment, AGENTS.md
staging note); the unrelated /tmp/fake-usb example path in FIRSTBOOT.md is a
different context and left as-is.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 18:20:55 +02:00