From c62bbd3d7e542e318b9225ed8aeba7123ba9feab Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Fri, 19 Jun 2026 21:48:48 +0200 Subject: [PATCH] =?UTF-8?q?feat(mother):=20draft=20genesis=20skill=20?= =?UTF-8?q?=E2=80=94=20join-the-hive=20sequence?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Resolve identity: hostname, OS, capability probe - Verify vault: .env exists + contains API key - Register agent: idempotent, safe to re-run - Heartbeat + poll loop: stay alive on the board Platform-specific paths for FreeBSD jail vs Linux container, security invariant documented, cross-linked with HIVE-ONBOARDING and CAPABILITY-ROUTING. --- skills/mother/SKILL.md | 163 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 skills/mother/SKILL.md diff --git a/skills/mother/SKILL.md b/skills/mother/SKILL.md new file mode 100644 index 0000000..f19d009 --- /dev/null +++ b/skills/mother/SKILL.md @@ -0,0 +1,163 @@ +--- +name: mother +description: Genesis sequence for a new agent joining the Clawdie hive — resolve identity, verify vault provision, register capabilities on the Colibri board, and start the heartbeat/poll loop. Idempotent — safe to re-run on an already-provisioned agent. +triggers: + - "join the hive" + - "mother skill" + - "genesis sequence" + - "onboard this agent" + - "register with colibri" + - "first boot" + - "new agent setup" + - "provision agent" +--- + +# Mother Skill — Agent Genesis + +Trigger: the agent wakes up in a freshly-provisioned jail (or container) and needs +to join the hive. The vault has already written a `.env` into the jail root by the +time this skill runs — the agent's job is to verify, register, and start polling. + +## Prerequisites (must already exist before this skill runs) + +- `.env` file present in the agent's home directory (written by `colibri-vault`) +- `colibri-daemon` reachable — either on a local Unix socket (osa) or via the TCP + bridge over Tailscale (remote hosts) +- `colibri` binary in PATH (or at a known location) +- The agent knows its own hostname and OS (`hostname`, `uname`) + +## Genesis Sequence + +Run these steps in order. The skill is **idempotent** — if an agent already has an +agent_id and is registered, skip the registration step and go straight to polling. + +### 1. Resolve identity + +Determine what this agent IS before registering: + +```bash +HOST=$(hostname) +OS=$(uname -s | tr '[:upper:]' '[:lower:]') +``` + +Capability tags are derived from what's actually installed and reachable on this +host. Use the Host Matrix as reference (`docs/HOST-MATRIX.md` in layered-soul), but +the ground truth is `scripts/verify_facts_probe.py`. + +Minimum base tags every agent should carry: + +| Tag | Source | +|-----|--------| +| `freebsd` or `linux` | `uname -s` | +| `shell` | always present | +| `hermes` | if Hermes Agent is installed | +| `tailscale` | if `tailscale status` succeeds | + +Additional tags per the Capability Vocabulary in `docs/CAPABILITY-ROUTING.md`: +jail isolation (`freebsd-jail`), hardware (`zfs`, `gpu`), runtimes (`python3.12`, +`rust`, `node24`), media (`ffmpeg`, `image-render`). + +### 2. Verify vault provision + +Confirm the vault did its job — the `.env` must contain at least one valid API key: + +```bash +test -f ~/.env && grep -q '_API_KEY=' ~/.env && echo "vault: provisioned" || echo "vault: MISSING — .env absent or empty" +``` + +If missing, this agent cannot authenticate to any provider. Report the error and +halt — a human operator must re-run `colibri-vault provision`. + +### 3. Register with Colibri + +Check if already registered (by name, not UUID — the daemon enforces UNIQUE on names): + +```bash +# Check if agent already exists +colibri --socket $COLIBRI_SOCKET list-agents | grep -q "\"$AGENT_NAME\"" +``` + +If NOT registered, register with capabilities derived from Step 1: + +```bash +colibri --socket $COLIBRI_SOCKET register-agent "$AGENT_NAME" \ + --capabilities freebsd,shell,hermes,tailscale,rc.d,pf,zfs +``` + +The `COLIBRI_SOCKET` path depends on the host: + +| Host | Socket path | +|------|-------------| +| osa (FreeBSD, local daemon) | `/var/run/colibri/colibri.sock` | +| Remote hosts (via socat bridge) | `/tmp/osa-colibri.sock` | + +If registration fails (e.g., name collision), log the error and continue — the agent +may already be registered under a different name, or the board may be unreachable. +The poller will surface this on its next tick. + +### 4. Start heartbeat and poll loop + +The agent is now a member of the hive. Two recurring jobs keep it alive: + +**Heartbeat** (every 5 min): update agent status on the board so the scheduler knows +this agent is still alive and can receive tasks. + +```bash +colibri --socket $COLIBRI_SOCKET set-agent-status "$AGENT_NAME" active +``` + +**Poll loop** (every 2 min): check the board for tasks assigned to this agent. +On osa and debby, this runs inside Hermes' internal scheduler — see +`colibri/packaging/freebsd/colibri-agent-loop.md` for the Hermes cronjob setup. + +For a bare agent without Hermes cron, a minimal poll loop: + +```bash +while true; do + colibri --socket $COLIBRI_SOCKET list-tasks --status started \ + | colibri_poll.py # filters by agent UUID, outputs JSON + sleep 120 +done +``` + +## Platform-specific notes + +### FreeBSD jail (osa) + +- The vault writes `.env` to `/home/clawdie/.env` inside the jail +- The daemon socket is at `/var/run/colibri/colibri.sock` (mounted or shared) +- Capabilities include `freebsd-jail`, `zfs` (if zpool is visible), `rc.d` +- The jail's `/var/run` is tmpfs — `mkdir -p /var/run/colibri` before connecting + +### Linux container (debby, domedog) + +- The vault writes `.env` to `~/.env` +- The socket is a socat bridge at `/tmp/osa-colibri.sock` pointing to osa:9190 +- Capabilities include `docker` (if Docker socket is mounted), `image-render` + (if Pillow/FFmpeg are installed) +- Start the socat shim before the poll loop: + ```bash + socat UNIX-LISTEN:/tmp/osa-colibri.sock,fork TCP:${OSA_TS_IP}:9190 & + ``` + +## Idempotency contract + +This skill can be re-run at any time without breaking a live agent: + +| Step | Re-run behavior | +|------|-----------------| +| Resolve identity | Safe — hostname and OS don't change | +| Verify vault | Safe — checks file existence, no side effects | +| Register agent | Name collision = benign error (already registered) | +| Heartbeat/poll | Safe — daemon ignores duplicate status updates | + +## Security invariant + +The `.env` file is `0600` (written by `colibri-vault` with `Permissions::from_mode(0o600)`). +It contains the agent's ONE provider key — never the Vaultwarden org service-account +credential. A compromised jail can use its own key but cannot reach another tenant's +collection or the vault bootstrap credential. + +_See `docs/HIVE-ONBOARDING.md` for the full onboarding vision, +`docs/CAPABILITY-ROUTING.md` for the routing layer, and +`colibri/packaging/freebsd/colibri-agent-loop.md` for the Hermes cronjob setup._