From 4298389f13f7758296b3631a2a5fc966b9ae987c Mon Sep 17 00:00:00 2001 From: Sam & Claude Date: Wed, 24 Jun 2026 10:10:09 +0200 Subject: [PATCH] =?UTF-8?q?mother:=20drop=20duplicate=20scripts=20from=20i?= =?UTF-8?q?so;=20canonical=20=3D=20colibri;=20docs=20=E2=86=92=20hive=5Fno?= =?UTF-8?q?des?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- docs/DOME-GEOMETRY-CAPABILITY.md | 2 +- docs/SETUP-USB-TO-MOTHER.md | 8 ++-- docs/USB-MOTHER-MCP-CONNECTION.md | 6 +-- packaging/mother/build-colibri.sh | 68 ------------------------------ packaging/mother/colibri-mcp-ssh | 6 --- packaging/mother/node-register-mcp | 66 ----------------------------- 6 files changed, 8 insertions(+), 148 deletions(-) delete mode 100755 packaging/mother/build-colibri.sh delete mode 100755 packaging/mother/colibri-mcp-ssh delete mode 100755 packaging/mother/node-register-mcp diff --git a/docs/DOME-GEOMETRY-CAPABILITY.md b/docs/DOME-GEOMETRY-CAPABILITY.md index 180ce72..2a83de2 100644 --- a/docs/DOME-GEOMETRY-CAPABILITY.md +++ b/docs/DOME-GEOMETRY-CAPABILITY.md @@ -44,7 +44,7 @@ bill-of-materials calculation. The obvious answer was Blender — it has ## Registering capabilities -This comparison feeds into the mother node's PostgreSQL `usb_nodes` table. +This comparison feeds into the mother node's PostgreSQL `hive_nodes` table. When a node registers its hardware profile, the capability derivation trigger marks nodes that can run `geodesic-dome-mcp` (all of them — numpy + Pillow are universal). Nodes that have Blender installed get an additional diff --git a/docs/SETUP-USB-TO-MOTHER.md b/docs/SETUP-USB-TO-MOTHER.md index 036a04c..a7f5fa2 100644 --- a/docs/SETUP-USB-TO-MOTHER.md +++ b/docs/SETUP-USB-TO-MOTHER.md @@ -4,7 +4,7 @@ Connects a booted Clawdie USB to the mother node (OSA) via MCP over SSH. After setup, `clawdie-hw-probe` runs on the USB, the hardware profile is -sent to mother, and stored in PostgreSQL `mother_hive.usb_nodes`. +sent to mother, and stored in PostgreSQL `mother_hive.hive_nodes`. ## Hosts used in this guide @@ -48,7 +48,7 @@ sent to mother, and stored in PostgreSQL `mother_hive.usb_nodes`. │ colibri-mcp-ssh → strips forced-command wrapper │ │ → passes "tools" subcommand to colibri-mcp │ │ │ -│ PostgreSQL mother_hive.usb_nodes ← hw-probe JSON stored │ +│ PostgreSQL mother_hive.hive_nodes ← hw-probe JSON stored │ │ │ └───────────────────────────────────────────────────────────────┘ ``` @@ -200,7 +200,7 @@ HW_JSON=$(sudo clawdie-hw-probe 2>/dev/null) # 2. View what would be sent to mother echo "$HW_JSON" | python3.11 -m json.tool | head -15 -# 3. Send to mother via MCP (node_register tool: packaging/mother/node-register-mcp) +# 3. Send to mother via MCP (node_register tool lives in the colibri repo: packaging/mother/node-register-mcp) # The 0.12 daemon collects hw-probe at autospawn time and passes it to agents # via CLAWDIE_HW_PROFILE env var. For manual testing, pipe JSON-RPC directly: printf '{"jsonrpc":"2.0","method":"tools/call","id":1,"params":{"name":"node_register","arguments":{"hostname":"%s","hw_profile":%s}}}\n' \ @@ -208,7 +208,7 @@ printf '{"jsonrpc":"2.0","method":"tools/call","id":1,"params":{"name":"node_reg # 4. Verify on mother ssh m0th3r 'sudo -u postgres psql -d mother_hive \ - -c "SELECT hostname, status, capabilities FROM usb_nodes;"' + -c "SELECT hostname, status, capabilities FROM hive_nodes;"' # Expected: both osa.smilepowered.org and clawdie-usb listed ``` diff --git a/docs/USB-MOTHER-MCP-CONNECTION.md b/docs/USB-MOTHER-MCP-CONNECTION.md index 32dfcee..4f8efdd 100644 --- a/docs/USB-MOTHER-MCP-CONNECTION.md +++ b/docs/USB-MOTHER-MCP-CONNECTION.md @@ -7,7 +7,7 @@ Boot the live USB, and the colibri-daemon automatically connects to mother (OSA) via MCP over SSH. The first action on autospawn: `clawdie-hw-probe` runs, hardware profile is sent to mother via `colibri_external_mcp_call_tool`, and -mother stores it in PostgreSQL `mother_hive.usb_nodes`. +mother stores it in PostgreSQL `mother_hive.hive_nodes`. ## Current state @@ -135,7 +135,7 @@ HW_JSON=$(sudo clawdie-hw-probe 2>/dev/null) # with the mother server registered) # 3. Verify on mother: -sudo -u postgres psql -d mother_hive -c "SELECT hostname, status, capabilities FROM usb_nodes;" +sudo -u postgres psql -d mother_hive -c "SELECT hostname, status, capabilities FROM hive_nodes;" ``` Expected: the USB node appears in PostgreSQL with hardware profile and @@ -154,7 +154,7 @@ derived capabilities (`has_gpu`, `ram_gb`, `cpu_cores`, etc.). The agent's first action should read that env var and call `colibri_external_mcp_call_tool(server="mother", tool="node_register")`. The `node_register` MCP tool is now implemented at - `packaging/mother/node-register-mcp`. + the **colibri** repo (`packaging/mother/node-register-mcp`). 3. **Tailscale dependency**: The USB needs Tailscale to be up before MCP works. This is already the case — Tailscale auth is part of the bootstrap flow. diff --git a/packaging/mother/build-colibri.sh b/packaging/mother/build-colibri.sh deleted file mode 100755 index 36097f6..0000000 --- a/packaging/mother/build-colibri.sh +++ /dev/null @@ -1,68 +0,0 @@ -#!/bin/sh -# build-colibri MCP tool — build a colibri crate from any git branch. -# -# Accepts a JSON-RPC tools/call request on stdin, builds the requested -# crate, and returns the result as a JSON content block to stdout. -# -# Expected input (MCP tools/call): -# {"jsonrpc":"2.0","method":"tools/call","id":1,"params":{"name":"build_colibri","arguments":{"crate":"colibri-daemon","branch":"main","features":"","release":"true"}}} -# -# Parameters: -# crate — workspace member to build (default: colibri-daemon) -# branch — git branch/ref to check out (default: main) -# features — optional comma-separated features -# release — "true" for --release, anything else for debug (default: true) -# -# Output: MCP JSON-RPC response with text content block -# {"success":true,"binary":"/home/clawdie/ai/colibri/target/release/colibri-daemon","duration_s":25.4,"branch":"main","commit":"abc1234"} -# or -# {"success":false,"error":"build failed: ..."} -set -eu - -REPO="/home/clawdie/ai/colibri" -CRATE_DEFAULT="colibri-daemon" -BRANCH_DEFAULT="main" - -# Read JSON from stdin, extract arguments -INPUT=$(cat) -CRATE=$(echo "$INPUT" | jq -r '.params.arguments.crate // "'"$CRATE_DEFAULT"'"') -BRANCH=$(echo "$INPUT" | jq -r '.params.arguments.branch // "'"$BRANCH_DEFAULT"'"') -FEATURES=$(echo "$INPUT" | jq -r '.params.arguments.features // ""') -RELEASE=$(echo "$INPUT" | jq -r '.params.arguments.release // "true"') -ID=$(echo "$INPUT" | jq -r '.id // "1"') - -# Build flags -CARGO_FLAGS="" -if [ "$RELEASE" = "true" ]; then - CARGO_FLAGS="--release" -fi -if [ -n "$FEATURES" ]; then - CARGO_FLAGS="$CARGO_FLAGS --features $FEATURES" -fi - -START_TS=$(date +%s) - -# Fetch and checkout -cd "$REPO" -git fetch origin 2>&1 || true -if ! git checkout "$BRANCH" 2>&1; then - printf '{"jsonrpc":"2.0","id":%s,"error":{"code":-1,"message":"git checkout failed: %s"}}\n' "$ID" "$BRANCH" - exit 1 -fi -COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") - -# Build -BUILD_LOG=$(mktemp) -if cargo build $CARGO_FLAGS -p "$CRATE" >"$BUILD_LOG" 2>&1; then - DURATION=$(( $(date +%s) - START_TS )) - BINARY=$(find target -maxdepth 3 -type f -name "$CRATE" -perm -111 | grep -v deps | head -1) - SIZE=$(stat -f '%z' "$BINARY" 2>/dev/null || echo "0") - cat "$BUILD_LOG" | tail -5 >&2 # send tail to stderr for logging - printf '{"jsonrpc":"2.0","id":%s,"result":{"content":[{"type":"text","text":"{\\"success\\":true,\\"binary\\":\\"%s\\",\\"duration_s\\":%s,\\"branch\\":\\"%s\\",\\"commit\\":\\"%s\\",\\"size_bytes\\":%s}"}]}}\n' \ - "$ID" "$BINARY" "$DURATION" "$BRANCH" "$COMMIT" "$SIZE" -else - DURATION=$(( $(date +%s) - START_TS )) - ERROR=$(tail -20 "$BUILD_LOG" | head -10 | tr '\n' ' ' | sed 's/"/\\"/g') - printf '{"jsonrpc":"2.0","id":%s,"error":{"code":-1,"message":"build failed in %ss: %s"}}\n' "$ID" "$DURATION" "$ERROR" -fi -rm -f "$BUILD_LOG" diff --git a/packaging/mother/colibri-mcp-ssh b/packaging/mother/colibri-mcp-ssh deleted file mode 100755 index 5a96f86..0000000 --- a/packaging/mother/colibri-mcp-ssh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# Wrapper for SSH forced-command MCP entrypoint. -# SSH's command="..." restriction replaces the client's command with -# this script and stores the original in $SSH_ORIGINAL_COMMAND. -# Pass it through to colibri-mcp so `ssh colibri@mother tools` works. -exec /usr/local/bin/colibri-mcp ${SSH_ORIGINAL_COMMAND} diff --git a/packaging/mother/node-register-mcp b/packaging/mother/node-register-mcp deleted file mode 100755 index 1903244..0000000 --- a/packaging/mother/node-register-mcp +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -# node-register MCP tool — register a USB node's hardware profile in PostgreSQL. -# -# Accepts a JSON-RPC tools/call request on stdin, inserts the hw_profile into -# mother_hive.usb_nodes, and returns the result to stdout. The -# derive_capabilities() trigger auto-computes has_gpu, gpu_vendor, -# can_run_local_llm, has_wifi, etc. on INSERT. -# -# Expected input: -# {"jsonrpc":"2.0","method":"tools/call","id":1,"params":{"name":"node_register","arguments":{"hostname":"clawdie-usb","hw_profile":{...}}}} -# -# Output on success: -# {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"{\"registered\":true,\"hostname\":\"clawdie-usb\",\"capabilities\":{...}}"}]}} -# -# PostgreSQL access: peer auth for the 'colibri' OS user. The operator must run -# once on mother (as postgres): -# 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; -set -eu - -DB="mother_hive" - -# Read JSON-RPC from stdin -INPUT=$(cat) -ID=$(echo "$INPUT" | jq -r '.id // "1"') -HOSTNAME=$(echo "$INPUT" | jq -r '.params.arguments.hostname // ""') -HW_PROFILE=$(echo "$INPUT" | jq -c '.params.arguments.hw_profile // {}') - -if [ -z "$HOSTNAME" ]; then - printf '{"jsonrpc":"2.0","id":%s,"error":{"code":-1,"message":"missing required argument: hostname"}}\n' "$ID" - exit 1 -fi - -if [ "$HW_PROFILE" = "{}" ]; then - printf '{"jsonrpc":"2.0","id":%s,"error":{"code":-1,"message":"missing required argument: hw_profile"}}\n' "$ID" - exit 1 -fi - -# Escape for psql string literal: double any single quotes, wrap in E'...' -HW_ESCAPED=$(printf '%s' "$HW_PROFILE" | sed "s/'/''/g") -HOST_ESCAPED=$(printf '%s' "$HOSTNAME" | sed "s/'/''/g") - -# Insert/update. The derive_capabilities() trigger fires on INSERT and -# UPDATE OF hw_profile, so capabilities are always fresh. -SQL="INSERT INTO usb_nodes (hostname, hw_profile, status, last_seen) -VALUES (E'${HOST_ESCAPED}', E'${HW_ESCAPED}'::jsonb, 'online', now()) -ON CONFLICT (hostname) DO UPDATE -SET hw_profile = EXCLUDED.hw_profile, - status = 'online', - last_seen = now()" - -RESULT=$(psql -d "$DB" -tAc "BEGIN; $SQL; SELECT json_build_object( - 'registered', true, - 'hostname', hostname, - 'capabilities', capabilities -) FROM usb_nodes WHERE hostname = E'${HOST_ESCAPED}'; COMMIT;" 2>&1) || { - printf '{"jsonrpc":"2.0","id":%s,"error":{"code":-1,"message":"psql failed: %s"}}\n' \ - "$ID" "$(printf '%s' "$RESULT" | sed 's/"/\\"/g' | tr '\n' ' ')" - exit 1 -} - -# RESULT is the JSON object from json_build_object -printf '{"jsonrpc":"2.0","id":%s,"result":{"content":[{"type":"text","text":"%s"}]}}\n' \ - "$ID" "$(printf '%s' "$RESULT" | sed 's/"/\\"/g')" -- 2.45.3