bootstrap
Adom Hydrogen (platform base)
Public Made by Adomby adom
Layer Hydrogen's workspace onto a standard Adom workstation.
← Commit history
Publish 0.3.16
4 files changed
+159−2
migrate-retired-slugs.shadded+152@@ -0,0 +1,152 @@+#!/usr/bin/env bash+# migrate-retired-slugs.sh — adom/hydrogen-bootstrap+#+# Heal lockfile roots left behind by slug renames (John 2026-08-13). This is a+# PREREQUISITE for deleting the old wiki pages: the rename redirects are going+# away entirely, so every container must be moved off retired slugs while they+# still resolve. Containers provisioned before the consolidations carry the OLD+# slug as a separate pinned root in adom_modules/.lock.json (live example:+# adom/adom-desktop pinned 1.9.211 next to adom/adom-bridge 2.0.30).+#+# WHY THE PURGE PHASE EXISTS (verified live 2026-08-13): `adom-wiki pkg+# uninstall` removes the entry from `packages` but leaves it in the lockfile's+# `resolved` + `order` arrays; the NEXT `pkg install` re-syncs `packages` from+# that closure and RESURRECTS the removed entry as a ghost that uninstall then+# refuses ("not installed") while `packages` still lists it. Until the CLI bug+# is fixed, this script phases all installs BEFORE all uninstalls, then purges+# retired refs from packages/resolved/order directly (lockfile-only removal:+# uninstall itself is registry-independent, so this is safe offline too).+#+# Idempotent: a clean container matches nothing and exits in <1s.+# Best-effort: NEVER fails the bootstrap install (no set -e).+set -u+mlog() { echo "[slug-migration] $*"; }++WIKI="${ADOM_WIKI_BIN:-$HOME/.local/bin/adom-wiki}"+command -v "$WIKI" >/dev/null 2>&1 || WIKI="adom-wiki"+command -v "$WIKI" >/dev/null 2>&1 || { mlog "adom-wiki not found; skipping"; exit 0; }++MOD=""+for c in "$HOME/project/adom_modules" "$HOME/adom_modules"; do+ [ -f "$c/.lock.json" ] && MOD="$c" && break+done+[ -n "$MOD" ] || { mlog "no adom_modules lockfile found; skipping"; exit 0; }+LOCK="$MOD/.lock.json"++# ── The migration table (bootstraps first: [email protected] carries the dep+# edge on adom/adom-desktop; migrating it drops that edge before we prune).+# retired-ref:successor-ref (empty successor = absorbed, hub re-delivers).+TABLE="adom/hd-bootstrap:adom/hydrogen-bootstrap+adom/hd-windows-bootstrap:adom/hydrogen-windows-bootstrap+adom/hd-mac-bootstrap:adom/hydrogen-mac-bootstrap+adom/adom-desktop:adom/adom-bridge+adom/step2glb:adom/adom-step2glb+adom/adom-theme-system:adom/adom-theme+adom/adom-workspace-control:"++has_pkg() {+ python3 - "$LOCK" "$1" <<'PY'+import json, sys+d = json.load(open(sys.argv[1]))+sys.exit(0 if sys.argv[2] in (d.get("packages") or {}) else 1)+PY+}++PRESENT=""+while IFS=: read -r old new; do+ [ -n "$old" ] && has_pkg "$old" && PRESENT="$PRESENT$old:$new+"+done <<< "$TABLE"++if [ -z "$PRESENT" ]; then+ mlog "clean: no retired slugs present"+ exit 0+fi++# ── Phase 1: install every successor (ALL installs happen before ANY removal,+# so the resurrect-on-install bug can't undo phase 2/3).+while IFS=: read -r old new; do+ [ -n "$old" ] || continue+ mlog "MIGRATING $old -> ${new:-'(absorbed into adom/adom)'}"+ if [ -n "$new" ]; then+ "$WIKI" pkg install "$new" >/dev/null 2>&1 \+ && mlog " installed successor $new" \+ || mlog " ⚠ could not install $new (will still remove $old; re-run heals)"+ fi+done <<< "$PRESENT"+# The absorbed-skill case: adom/adom (the hub) owns adom-workspace-control's+# skill now — re-install it so the shared skill file survives phase 2's prune.+if echo "$PRESENT" | grep -q "adom/adom-workspace-control" && has_pkg "adom/adom"; then+ "$WIKI" pkg install "adom/adom" >/dev/null 2>&1 \+ && mlog " re-installed adom/adom (owns the absorbed workspace-control skill)"+fi++# ── Phase 2: uninstall the retired refs (registry-independent; may fail on+# ghosts — phase 3 purges whatever this leaves).+while IFS=: read -r old new; do+ [ -n "$old" ] || continue+ "$WIKI" pkg uninstall "$old" >/dev/null 2>&1 \+ && mlog " removed $old" \+ || mlog " (uninstall of $old refused; purging from lockfile directly)"+done <<< "$PRESENT"++# ── Phase 3: purge residue from packages/resolved/order so no later install+# can resurrect the retired refs.+python3 - "$LOCK" <<'PY'+import json, sys+RETIRED = {"adom/hd-bootstrap","adom/hd-windows-bootstrap","adom/hd-mac-bootstrap",+ "adom/adom-desktop","adom/step2glb","adom/adom-theme-system",+ "adom/adom-workspace-control"}+path = sys.argv[1]+d = json.load(open(path))+removed = []+pk = d.get("packages") or {}+for r in list(pk):+ if r in RETIRED:+ del pk[r]; removed.append(r)+def ref_of(entry):+ if not isinstance(entry, dict): return ""+ o, s = entry.get("owner"), entry.get("slug")+ return f"{o}/{s}" if o else (s or "")+d["resolved"] = [e for e in (d.get("resolved") or []) if ref_of(e) not in RETIRED]+d["order"] = [o for o in (d.get("order") or []) if o not in RETIRED]+if removed:+ json.dump(d, open(path, "w"), indent=2)+ print("[slug-migration] purged from lockfile:", ", ".join(sorted(removed)))+else:+ print("[slug-migration] no lockfile residue to purge")+PY++# Module-dir leftovers of purged refs (uninstall removes these when it works;+# the ghost path doesn't). Delivered ~/.claude/skills files are deliberately+# LEFT alone: deleting by name could hit a file the successor now owns — the+# successor installs above already overwrote every shared name.+while IFS=: read -r old new; do+ [ -n "$old" ] || continue+ [ -d "$MOD/$old" ] && rm -rf "$MOD/$old" 2>/dev/null && mlog " removed module dir $old"+done <<< "$PRESENT"++# ── Phase 4: verify every successor's delivered skills exist on disk; one+# re-install heals a collateral prune (safe now: retired refs are purged, so+# installs can no longer resurrect them).+for ref in adom/hydrogen-bootstrap adom/hydrogen-windows-bootstrap adom/hydrogen-mac-bootstrap \+ adom/adom-bridge adom/adom-step2glb adom/adom-theme adom/adom; do+ pkgdir="$MOD/$ref"+ [ -d "$pkgdir/skills" ] || continue+ missing=0+ for dsk in "$pkgdir"/skills/*/; do+ [ -d "$dsk" ] || continue+ n=$(basename "$dsk")+ [ -f "$HOME/.claude/skills/$n/SKILL.md" ] || { mlog " ⚠ $ref skill '$n' missing on disk"; missing=1; }+ done+ if [ "$missing" = "1" ]; then+ mlog " re-installing $ref to re-deliver missing skills"+ "$WIKI" pkg install "$ref" >/dev/null 2>&1 || mlog " ⚠ re-install of $ref failed"+ fi+done++N=$(echo "$PRESENT" | grep -c ":" || true)+mkdir -p "$HOME/.adom" 2>/dev/null+echo "{\"version\":1,\"migrated\":$N,\"at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" > "$HOME/.adom/slug-migration.json" 2>/dev/null+mlog "DONE: $N retired slug(s) migrated"+exit 0
package.json+1−1@@ -4,7 +4,7 @@ "type": "bootstrap", "title": "Adom Hydrogen (platform base)", "brief": "Layer Hydrogen's workspace onto a standard Adom workstation.",- "version": "0.3.15",+ "version": "0.3.16", "description": "Hydrogen's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen on ANY platform: the runtime-neutral hydrogen-* skills and the generic editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hydrogen-windows-bootstrap (WSL2), adom/hydrogen-mac-bootstrap, adom/hydrogen-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.", "org": "adom", "platform": "any",
page.json+1−1@@ -4,7 +4,7 @@ "type": "bootstrap", "title": "Adom Hydrogen (platform base)", "brief": "Layer Hydrogen's workspace onto a standard Adom workstation.",- "version": "0.3.15",+ "version": "0.3.16", "description": "Hydrogen's PLATFORM-GENERIC workspace layer on top of adom/core. Installs adom/core for the full Adom ecosystem, then adds everything common to running inside Hydrogen on ANY platform: the runtime-neutral hydrogen-* skills and the generic editor configuration (Claude Code CLI + extension, VS Code settings, trusted domains). Platform-specific layers depend on THIS: adom/hydrogen-windows-bootstrap (WSL2), adom/hydrogen-mac-bootstrap, adom/hydrogen-ubuntu-bootstrap. The reference design other orgs copy to build their own bootstrap on adom/core.", "org": "adom", "tags": [
postinstall.sh+5@@ -175,3 +175,8 @@ C /run/adom/api-key 0644 root root - /home/adom/.adom/api-key # 7. tidy — install.mjs / tooling leave an empty ~/project/.mcp.json; remove it. rm -f "$HOME/project/.mcp.json" 2>/dev/null || true log "done"++# ── Retired-slug migration (John 2026-08-13) ─────────────────────────────────+# Heals pre-rename lockfile roots (hd-bootstrap, adom-desktop, ...) so the old+# wiki pages/redirects can be deleted. Idempotent, best-effort, never fatal.+bash "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/migrate-retired-slugs.sh" || true