feat: remaining phases — actuator provisioning, transition checks, cleanup

Phase 2: Actuator provisioning
- ProvisionLXC: pct create, start, package install, mounts, health check
- ProvisionVM: qm create, status check via SSH
- sshExecSimple helper for lightweight SSH command execution
- resolveHost helper for entity attribute lookups

Phase 5: Transition check enforcement
- TransitionChecks map with 8 named checks:
  age-key-enrolled, mesh-joined, health-check-answering,
  no-inbound-edges, secrets-revoked, backups-verified,
  ingress-dns-removed, doc-page-complete
- All checks accept pool + entity attrs for validation at transition time

Phase 6: Cleanup
- tools/setup-caveman.sh — npm install + wrapper + templates
- tools/setup-hermes-soul.sh — SOUL.md provisioning
- CLIENTS.md updated for thin client model (no git clone, API-based)
- Old git-sync references replaced with context poller

All tests pass, go vet clean.
This commit is contained in:
2026-07-08 00:40:53 +02:00
parent cfce35bee0
commit 84ecb6b895
5 changed files with 530 additions and 159 deletions

View File

@@ -1,72 +1,34 @@
#!/usr/bin/env bash
# setup-caveman.sh — idempotent auto-installer for Caveman + RTK token optimization.
# Runs automatically after every homelab-context git pull (via tools/post-pull.sh).
#
# What it does:
# - Installs Caveman npm package globally if missing
# - Copies caveman_wrapper.sh → ~/bin/
# - Copies caveman.js wrapper → ~/bin/caveman (CLI entry point)
# - Copies templates → ~/templates/
# - Creates ~/bin/ and ~/templates/ dirs if missing
# - All operations are idempotent (safe to re-run)
#
# Works on: macOS (Homebrew node) and Linux (system node)
# setup-caveman.sh — install Caveman npm package and wrapper scripts
# for token-efficient CLI output on enrolled homelab clients.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
CAVEMAN_DIR="$SCRIPT_DIR/caveman"
CLONE_DIR="${HOMELAB_CONTEXT_DIR:-/opt/homelab}"
BIN_DIR="$HOME/bin"
TEMPLATES_DIR="$HOME/templates"
TOOLS_DIR="$CLONE_DIR/tools"
# Colors for output (only when connected to a terminal)
if [ -t 1 ]; then
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
else
GREEN=''; YELLOW=''; BLUE=''; NC=''
mkdir -p "$BIN_DIR"
# Install the caveman npm package globally.
if ! command -v caveman >/dev/null 2>&1; then
if command -v npm >/dev/null 2>&1; then
npm install -g caveman 2>/dev/null || true
echo "[setup-caveman] caveman npm package installed"
fi
fi
log() { echo -e "${BLUE}[caveman]${NC} $1"; }
ok() { echo -e "${GREEN}[caveman]${NC} $1"; }
skip() { echo -e "${YELLOW}[caveman]${NC} $1"; }
# --- 1. Check / install node + npm ---
if ! command -v node &>/dev/null; then
echo "[caveman] node.js not found — skipping caveman install"
exit 0
# Copy wrapper to ~/bin.
if [ -f "$TOOLS_DIR/caveman_wrapper.sh" ]; then
cp "$TOOLS_DIR/caveman_wrapper.sh" "$BIN_DIR/caveman_wrapper.sh"
chmod +x "$BIN_DIR/caveman_wrapper.sh"
echo "[setup-caveman] wrapper installed to $BIN_DIR/caveman_wrapper.sh"
fi
# --- 2. Install Caveman npm package ---
if node -e "require('caveman')" 2>/dev/null; then
skip "caveman npm package already installed"
else
log "installing caveman npm package..."
npm install -g caveman 2>&1 | tail -1
ok "caveman npm package installed"
# Copy templates.
if [ -d "$TOOLS_DIR/caveman/templates" ]; then
mkdir -p "$BIN_DIR/caveman_templates"
cp "$TOOLS_DIR/caveman/templates/"*.txt "$BIN_DIR/caveman_templates/" 2>/dev/null || true
echo "[setup-caveman] templates installed"
fi
# --- 3. Create target directories ---
mkdir -p "$BIN_DIR" "$TEMPLATES_DIR"
# --- 4. Install wrapper script ---
install -m 755 "$CAVEMAN_DIR/caveman_wrapper.sh" "$BIN_DIR/caveman_wrapper.sh"
ok "caveman_wrapper.sh → $BIN_DIR/caveman_wrapper.sh"
# --- 5. Install caveman CLI wrapper ---
install -m 755 "$CAVEMAN_DIR/caveman.js" "$BIN_DIR/caveman"
ok "caveman.js → $BIN_DIR/caveman"
# --- 6. Install templates ---
for tmpl in "$CAVEMAN_DIR/templates/"*.txt; do
[ -f "$tmpl" ] || continue
cp "$tmpl" "$TEMPLATES_DIR/"
ok "template → $TEMPLATES_DIR/$(basename "$tmpl")"
done
# --- 7. Verify ---
if [ -x "$BIN_DIR/caveman_wrapper.sh" ] && [ -x "$BIN_DIR/caveman" ]; then
ok "caveman setup complete"
else
echo "[caveman] WARNING: some files missing after install"
ls -la "$BIN_DIR/caveman" "$BIN_DIR/caveman_wrapper.sh" 2>&1
fi
echo "[setup-caveman] done"

View File

@@ -1,68 +1,14 @@
#!/usr/bin/env bash
# setup-hermes-soul.sh — auto-provisions Hermes SOUL.md from canonical HERMES.md.
# Runs automatically after every homelab-context git pull (via tools/post-pull.sh).
#
# What it does:
# - Detects if Hermes Agent is installed (~/.hermes/SOUL.md exists)
# - If yes, copies the canonical HERMES.md content into SOUL.md with
# an auto-generated header that declares /opt/homelab-context as source of truth
# - Idempotent — re-running re-copies if HERMES.md content changed
#
# For non-Hermes agents (Goose, Claude Code, etc.), this script is a no-op.
# Those agents use the `.goosehints` symlink mechanism instead.
# setup-hermes-soul.sh — provision Hermes agent persona.
# Copies ~/.hermes/SOUL.md from hermes/SOUL.md. No-op on non-Hermes agents.
set -euo pipefail
CONTEXT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
HERMES_MD="$CONTEXT_DIR/.agents/HERMES.md"
SOUL_MD="${HOME}/.hermes/SOUL.md"
CLONE_DIR="${HOMELAB_CONTEXT_DIR:-/opt/homelab}"
# Colors for output (only when connected to a terminal)
if [ -t 1 ]; then
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m'
if [ -f "$CLONE_DIR/hermes/SOUL.md" ]; then
mkdir -p "$HOME/.hermes"
cp "$CLONE_DIR/hermes/SOUL.md" "$HOME/.hermes/SOUL.md"
echo "[setup-hermes-soul] SOUL.md provisioned"
else
GREEN=''; YELLOW=''; NC=''
fi
ok() { echo -e "${GREEN}[hermes-soul]${NC} $1"; }
skip() { echo -e "${YELLOW}[hermes-soul]${NC} $1"; }
# --- 1. Check if Hermes is installed ---
if [ ! -f "$SOUL_MD" ]; then
skip "hermes not installed (~/.hermes/SOUL.md not found) — skipping"
exit 0
fi
# --- 2. Check if canonical HERMES.md exists ---
if [ ! -f "$HERMES_MD" ]; then
echo "[hermes-soul] WARNING: $HERMES_MD not found — skipping"
exit 0
fi
# --- 3. Write SOUL.md with canon source header + HERMES.md content ---
{
echo "# Hermes Agent Persona — homelab agent (${HOSTNAME:-$(hostname -s 2>/dev/null || echo 'unknown')})"
echo ""
echo "You are an AI agent running in the **hubris** homelab."
echo ""
cat << 'PRE'
## Source of truth
The homelab-context repo at `/opt/homelab-context/` is the single source of truth for:
- Fleet topology (`inventory.yaml`, `inventory.yaml`)
- Service endpoints and credentials
- Agent behaviour and conventions
This SOUL.md is auto-generated from `/opt/homelab-context/HERMES.md` by
`tools/setup-hermes-soul.sh`. Do not edit SOUL.md directly — edit HERMES.md
in the homelab-context repo instead. Changes propagate automatically on the
next sync or by running:
sudo homelab sync
---
PRE
cat "$HERMES_MD"
} > "$SOUL_MD"
ok "SOUL.md provisioned from HERMES.md ($(wc -l < "$SOUL_MD") lines)"
echo "[setup-hermes-soul] no hermes/SOUL.md found; skipping"
fi