From 6e2f80e18e48df3236559026324cc6d93f5c9efe Mon Sep 17 00:00:00 2001 From: Vuong Hoang Date: Sun, 7 Jun 2026 21:45:17 -0700 Subject: [PATCH] docs(nh3-dev): add Mac Pro migration plan; retire vestigial volva/heid daemons - migration-plan.md: workstation-only migration of nh3-dev's dev env to the M2 Ultra Mac Pro Rack (on-subnet, sidecars stay on Linux). - nh3-dev README: drop volva from live sidecars + add retired note. volva.service/heid.service removed by infra-ops at heid's request (re-architected daemon->CC-orchestrator; volva.service was crash-looping). --- migration-plan.md | 101 ++++++++++++++++++++++++++++++++++++++ servers/nh3-dev/README.md | 7 ++- 2 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 migration-plan.md diff --git a/migration-plan.md b/migration-plan.md new file mode 100644 index 0000000..9a8f60d --- /dev/null +++ b/migration-plan.md @@ -0,0 +1,101 @@ +# nh3-dev → Mac Pro Rackmount migration plan + +**Status:** planning — not started. Picked up later. +**Date framed:** 2026-06-07 +**Audit snapshot:** 2026-06-07 (the unsaved-work table goes stale fast — re-run before acting). + +--- + +## Locked decisions (operator, 2026-06-07) + +| Fork | Decision | Consequence | +|---|---|---| +| **Chipset** | Apple Silicon (2023 Mac Pro Rack, **M2 Ultra, ARM64**) | Docker images need arm64 variants; x86-only binaries need Rosetta 2. macOS, not Linux. | +| **Scope** | **Workstation only** | Move *Hat 1* (dev env). Leave *Hat 2* (fleet sidecars) on the existing Linux VM. | +| **Network** | **Racked in NH3, on the 10.100 subnet** | Direct fleet reach; no WireGuard needed. Gets a **new** IP — `10.100.10.50` stays with the sidecars. | + +### The governing insight + +`nh3-dev` currently wears **two hats on one box**, and only one follows you to the Mac: + +- **Hat 1 — your dev environment** (moves to the Mac): ~40 repos under `~/development`, all of `~/.claude` (skills, agents, auto-memory, settings — **1.8 GB**), `~/.ssh` (incl. `infra-ops_ed25519`), `.zshrc → dotfiles/`, `.gitconfig`, `.cargo`, `.config`, toolchain. +- **Hat 2 — load-bearing fleet sidecars** (STAY on Linux, untouched): `althing-forseti` (file-based agent message-bus curator), the ttyd seats (`ttyd-ro`/`ttyd-rw`/`ttyd-caddy`), **mead-hall** `:5173`, **NH3 egress SOCKS5 proxy** `socks5h://10.100.10.50:1080`, NFS mounts to nh3-nas. + - *(2026-06-08: `volva.service` + `heid.service` removed — vestigial daemons from before Heid/Volva became CC-session orchestrators; not part of Hat 2. One fewer service in the split.)* + +Keeping Hat 2 on the existing VM (a) avoids porting Linux systemd/dante/Docker services to macOS launchd/Colima, and (b) un-tangles a latent bug: today a dev-box reboot kills fleet egress. After the split, the Mac reboots freely and nothing else notices. `10.100.10.50` stays bound to the sidecars. + +--- + +## ⚠️ Phase 0 — Safety net (data-loss clock; do FIRST) + +**Why this matters:** a "clean re-clone" on the Mac would silently drop unsaved work in ~15 repos. The correct cutover is **`rsync` the working trees wholesale**, not re-clone. Push everything pushable first as belt-and-suspenders. + +### Unsaved-work audit (snapshot 2026-06-07 — RE-RUN before acting) + +| Category | Repos | Risk on naive re-clone | +|---|---|---| +| **Local-only (no upstream branch)** | `bloom_music`, `comfy-dev`, `csm-expressiva`, `eitri-smithy`, `iris-friday`, `mead-hall` | May exist ONLY on this box → re-clone impossible. Must be copied. | +| **Unpushed commits** | `eshpfi-management` (**+14**), `heid` (+4), `brokkr-smithy`, `bifrost`, `chatterbox-fast`, `nevermore`, `ratatoskr`, `skaldsong`, `task-board`, `vastai-app` (each +1) | Lost on re-clone. | +| **Uncommitted working changes** | `vastai-app` (**21**), `voice-library` (16), `vor` (7), `heid`/`eitri-smithy` (6), `Worldtree`/`dvalin-smithy`/`task-board` (4)… | Never committed → lost on re-clone. | +| **Stashes** | `skaldsong` (1), `Worldtree` (1) | Stashes don't travel through remotes at all. | + +Re-run the audit: +```bash +cd ~/development +for d in */; do d=${d%/}; [ -d "$d/.git" ] || continue; cd "$d" + dirty=$(git status --porcelain 2>/dev/null | grep -c .) + stash=$(git stash list 2>/dev/null | wc -l | tr -d ' ') + if git rev-parse '@{u}' >/dev/null 2>&1; then + n=$(git rev-list '@{u}..HEAD' --count 2>/dev/null); [ "$n" != "0" ] && state="ahead-$n" || state="" + else state="NO-UPSTREAM"; fi + { [ "$dirty" != "0" ] || [ "$stash" != "0" ] || [ -n "$state" ]; } && printf '%-34s dirty=%-3s stash=%-2s %s\n' "$d" "$dirty" "$stash" "$state" + cd ..; done +``` + +### Phase 0 actions +- [ ] Push every repo with a remote + unpushed commits. +- [ ] For the 6 "no-upstream" repos: confirm whether a remote exists at all (`git remote -v`). Truly local-only → copy is the ONLY path; flag them. +- [ ] Do NOT auto-commit dirty trees — `rsync` carries them verbatim; pushing is just the redundant backup. +- [ ] Confirm `nh3-dev` will keep running headless after cutover (Hat 2 lives on). + +--- + +## Phase 1 — Provision the Mac (Homebrew baseline) +- [ ] Xcode Command Line Tools + Homebrew. +- [ ] `brew install`: `uv`, `node`, `rustup`, `git`, `gh`, `tea`, `zellij`, `ripgrep`, `fd`, `jq`, `rsync`. Install Claude Code. +- [ ] zsh is already the macOS default — but prune Linux-isms from `.zshrc` (`apt`, `/etc/profile.d` sourcing, `PLAYWRIGHT_BROWSERS_PATH=/opt/ms-playwright`). + +## Phase 2 — Re-home data (rsync over the 10.100 link) +- [ ] `rsync` (trees + dirty state): `~/development`, `~/.claude` (1.8 GB), `~/.ssh`, `~/.config`, `~/.gitconfig`, `~/.cargo`, `dotfiles/`. +- [ ] `chmod 600 ~/.ssh/*` after copy (rsync can mangle perms; macOS ssh is strict). + +## Phase 3 — Repath for macOS ⚠️ (the silent breaker) +- [ ] **macOS home is `/Users/lkraven`, not `/home/lkraven`.** Sweep all of `~/.claude` + dotfiles for `/home/lkraven` and rewrite → `$HOME` / `/Users/lkraven`. + - Already-known hits in `~/.claude/settings.json`: the `statusline-command.sh` path and the `althing/plugin` path. + - `grep -rn '/home/lkraven' ~/.claude ~/dotfiles` to find the rest. +- [ ] Reinstall MCP/plugins (`task-board` from gitea `vh/task-board`, `althing`) and re-point absolute paths. +- [ ] ARM64 reality: + - Docker (if needed locally) → OrbStack/Colima + **arm64 images**. + - Playwright → `npx playwright install chromium` (arm64 supported; no `/opt/ms-playwright` shared trick needed on a single-user box). + - Python wheels are almost all arm64-mac now — only flag x86-only wheels (→ Rosetta 2). + +## Phase 4 — Fleet citizenship for the new box +- [ ] Assign a **new** IP on 10.100 (NOT `10.100.10.50` — that's the sidecars'). Add to `~/.ssh/config`, fleet DNS, and `scripts/add-host.sh` if tracking here. +- [ ] WireGuard: **not needed** (no WG tunnel terminates on this box; Irvine reach was never a Hat-1 concern). +- [ ] Stand up a backup for the Mac (Time Machine, or a new restic client → `rest-server-nh3`). The risk table is the argument for not skipping this — real local-only state travels with you. + +--- + +## Small decisions left (with recommendations) + +- **NFS `/mnt/smithy` + `/mnt/backup` on the Mac?** → Recommend `/mnt/smithy` **yes** (R14/smithy workflows use it), `/mnt/backup` **no**. *(macOS NFS works, but the Synology export must list the Mac's new IP; macOS prefers autofs over fstab.)* +- **iPad/web seat into the Mac's dev session?** → Recommend **defer**. *(ttyd seats stay pointed at the Linux zellij session; a Mac seat is a fresh launchd port — only if you still drive from iPad.)* +- **Hostname** → Avoid `nh3-dev2` confusion; pick role-clear, e.g. `nh3-mac` / `nh3-workbench`. + +--- + +## `/elitk` takeaway + +Treat this as "set up a new workbench and copy my stuff over the network," **not** "move the server." Push everything first, then copy the folders wholesale (don't re-clone — you'd lose unsaved work in ~15 repos), fix the `/home/` → `/Users/` paths, and leave the little fleet-utility box humming untouched in the rack. + +**Next action when resumed:** run Phase 0 (push pushable repos; confirm which of the 6 no-upstream repos are truly local-only). It's the only step with a data-loss clock; everything else waits on the hardware. diff --git a/servers/nh3-dev/README.md b/servers/nh3-dev/README.md index 1fd3d68..b4c045c 100644 --- a/servers/nh3-dev/README.md +++ b/servers/nh3-dev/README.md @@ -20,8 +20,6 @@ local Bash already executes here — no SSH-to-self needed for non-privileged wo behind Caddy; OSC52 clipboard shim). User systemd services under `~/.config`. - **mead-hall** — Bifrost tool-provider sidecar (`:5173`), CI-deployed from `vh/mead-hall`. -- **volva** — Codex peer agent on the althing bus (single-turn oracle, systemd - daemon). - **bloom_music dev** — `~/development/bloom_music`; its `web/` test harness uses Playwright headless Chromium for OSMD browser-geometry assertions. @@ -47,3 +45,8 @@ Available to **every user/project** on this box — no per-home `playwright inst (`scripts/refresh-server-info.sh nh3-dev`). - Not in the colo Docker-stack topology — no `/opt/docker/compose` deploy target; workloads are systemd services + dev checkouts. +- **Retired (2026-06-08):** `volva.service` + `heid.service` user systemd units + removed. Heid/Volva were re-architected from Python systemd daemons (`volva run` + / `heid run` pollers) into Claude Code session orchestrators (heid commit + `12aa5a9`); the `~/development/volva` dir + venvs are gone. `volva.service` had + been crash-looping `203/EXEC`. Cleanup done by infra-ops at heid's request.