# BeadBoard Global Install Runtime Manager Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Replace repo-path shim install behavior with a robust global install model where `beadboard` runs from managed runtime home and works from any directory. **Architecture:** Keep a hybrid install strategy with npm-global as primary and script bootstrap as fallback, but unify both paths behind one runtime manager contract (`~/.beadboard/runtime/` + stable shims). Preserve backward compatibility by detecting legacy repo-bound shims and offering migration. Implement with strict TDD and explicit installer smoke tests. **Tech Stack:** Node.js (ESM), TypeScript/tsx for CLI code, PowerShell + POSIX shell wrappers, GitHub Actions, Node test runner. --- ## Pre-Implementation Checklist ### Task 0: Baseline and Safety Snapshot **Files:** - Modify: `beadboard/.beads/issues.jsonl` via `bd` commands only - Read: `beadboard/AGENTS.md` - Read: `beadboard/NEXT_SESSION_PROMPT.md` **Step 1: Claim/track implementation bead(s)** Run: ```bash cd beadboard bd create --title="Global installer runtime manager implementation" --description="Implement npm-global-first runtime manager with migration from repo-path shims" --type=task --priority=1 --label="installation,cli,runtime" bd update --status in_progress --assignee ``` **Step 2: Capture baseline gate status** Run: ```bash npm run typecheck npm run lint npm run test ``` Expected: existing known unrelated failures may appear; record exact failing files/tests in bead notes. **Step 3: Commit checkpoint** No code changes yet. Do not commit. --- ## Phase 1: Define Runtime Manager Contract ### Task 1: Add runtime manager ADR and package contract **Files:** - Create: `docs/adr/2026-03-03-runtime-manager-global-install.md` - Modify: `docs/adr/2026-03-03-global-installer-contract-and-manifest.md` **Step 1: Write failing docs contract test** Create: - `tests/docs/runtime-manager-adr-contract.test.ts` ```ts import test from 'node:test'; import assert from 'node:assert/strict'; import fs from 'node:fs/promises'; import path from 'node:path'; test('runtime manager ADR exists and declares runtime home strategy', async () => { const raw = await fs.readFile(path.resolve('docs/adr/2026-03-03-runtime-manager-global-install.md'), 'utf8'); assert.match(raw, /~\/\.beadboard\/runtime/i); assert.match(raw, /npm i -g beadboard/i); assert.match(raw, /legacy repo-bound shim migration/i); }); ``` **Step 2: Run test to verify it fails** Run: ```bash node --import tsx --test tests/docs/runtime-manager-adr-contract.test.ts ``` Expected: FAIL (`ENOENT` for missing ADR file). **Step 3: Write minimal implementation** Add ADR with: - runtime directory layout - shim strategy - update/uninstall model - compatibility migration model - failure modes and rollback **Step 4: Run test to verify it passes** Run: ```bash node --import tsx --test tests/docs/runtime-manager-adr-contract.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add tests/docs/runtime-manager-adr-contract.test.ts docs/adr/2026-03-03-runtime-manager-global-install.md docs/adr/2026-03-03-global-installer-contract-and-manifest.md git commit -m "docs: define runtime manager global install contract" ``` --- ## Phase 2: Implement Runtime Manager Library ### Task 2: Add runtime manager core module with strict validation **Files:** - Create: `src/lib/runtime-manager.ts` - Create: `tests/lib/runtime-manager.test.ts` **Step 1: Write failing test** ```ts import test from 'node:test'; import assert from 'node:assert/strict'; import { getRuntimePaths, normalizeVersion } from '../../src/lib/runtime-manager'; test('normalizeVersion supports semver and rejects empty', () => { assert.equal(normalizeVersion('1.2.3'), '1.2.3'); assert.throws(() => normalizeVersion('')); }); test('getRuntimePaths builds ~/.beadboard/runtime/ layout', () => { const p = getRuntimePaths('/tmp/home', '1.2.3'); assert.match(p.runtimeRoot, /runtime\/1\.2\.3$/); assert.match(p.shimDir, /\.beadboard\/bin$/); }); ``` **Step 2: Run test to verify it fails** Run: ```bash node --import tsx --test tests/lib/runtime-manager.test.ts ``` Expected: FAIL (`Cannot find module '../../src/lib/runtime-manager'`). **Step 3: Write minimal implementation** Implement exports: - `normalizeVersion(version: string): string` - `getRuntimePaths(home: string, version: string)` - `resolveInstallHome(env)` Keep pure and side-effect free. **Step 4: Run test to verify it passes** Run: ```bash node --import tsx --test tests/lib/runtime-manager.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add src/lib/runtime-manager.ts tests/lib/runtime-manager.test.ts git commit -m "feat(installer): add runtime manager core library" ``` --- ## Phase 3: Move Launcher to Runtime-Aware Execution ### Task 3: Update launcher to run from managed runtime root **Files:** - Modify: `install/beadboard.mjs` - Modify: `tests/scripts/beadboard-launcher.test.ts` - Create: `tests/scripts/beadboard-launcher-runtime.test.ts` **Step 1: Write failing test** ```ts import test from 'node:test'; import assert from 'node:assert/strict'; import { execFile } from 'node:child_process'; import { promisify } from 'node:util'; import path from 'node:path'; const execFileAsync = promisify(execFile); const launcherPath = path.resolve('install/beadboard.mjs'); test('status --json reports runtime root and install mode', async () => { const { stdout } = await execFileAsync(process.execPath, [launcherPath, 'status', '--json']); const payload = JSON.parse(stdout); assert.ok(payload.runtimeRoot); assert.ok(payload.installMode); }); ``` **Step 2: Run test to verify it fails** Run: ```bash node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts ``` Expected: FAIL (missing fields). **Step 3: Write minimal implementation** In launcher: - derive runtime home/version - include `runtimeRoot`, `installMode`, `shimTarget` in JSON status - preserve existing `start/open/status` behavior **Step 4: Run tests to verify pass** Run: ```bash node --import tsx --test tests/scripts/beadboard-launcher.test.ts node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add install/beadboard.mjs tests/scripts/beadboard-launcher.test.ts tests/scripts/beadboard-launcher-runtime.test.ts git commit -m "feat(launcher): add runtime-aware status metadata" ``` --- ## Phase 4: Replace Repo-Bound Shim Targets ### Task 4: Make install wrappers point at runtime-managed target **Files:** - Modify: `install/install.sh` - Modify: `install/install.ps1` - Modify: `tests/scripts/install-wrappers-contract.test.ts` - Modify: `tests/scripts/install-sh-smoke.test.ts` - Create: `tests/scripts/install-legacy-migration.test.ts` **Step 1: Write failing migration test** ```ts import test from 'node:test'; import assert from 'node:assert/strict'; // simulate legacy shim text and verify installer rewrites to runtime target test('installer migrates legacy repo-bound shim to runtime-managed shim', async () => { assert.fail('implement'); }); ``` **Step 2: Run test to verify it fails** Run: ```bash node --import tsx --test tests/scripts/install-legacy-migration.test.ts ``` Expected: FAIL. **Step 3: Write minimal implementation** In both wrappers: - install runtime metadata file (`~/.beadboard/runtime/current.json`) - rewrite `bb`/`beadboard` shims to resolve runtime target first - detect old shim signatures and replace atomically **Step 4: Run wrapper tests** Run: ```bash node --import tsx --test tests/scripts/install-wrappers-contract.test.ts node --import tsx --test tests/scripts/install-sh-smoke.test.ts node --import tsx --test tests/scripts/install-legacy-migration.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add install/install.sh install/install.ps1 tests/scripts/install-wrappers-contract.test.ts tests/scripts/install-sh-smoke.test.ts tests/scripts/install-legacy-migration.test.ts git commit -m "feat(installer): migrate shims to runtime-managed targets" ``` --- ## Phase 5: Add npm-Global Entry and Self-Management Commands ### Task 5: Add CLI entrypoint commands (`self-update`, `uninstall`, `doctor`) **Files:** - Modify: `package.json` - Create: `bin/beadboard.js` - Create: `src/cli/beadboard-cli.ts` - Create: `tests/cli/beadboard-cli.test.ts` **Step 1: Write failing CLI tests** ```ts import test from 'node:test'; import assert from 'node:assert/strict'; import { runCli } from '../../src/cli/beadboard-cli'; test('doctor returns structured install diagnostics', async () => { const out = await runCli(['doctor', '--json']); assert.equal(out.ok, true); assert.ok(out.installMode); }); ``` **Step 2: Run test to verify it fails** Run: ```bash node --import tsx --test tests/cli/beadboard-cli.test.ts ``` Expected: FAIL (missing module/command). **Step 3: Write minimal implementation** Add commands: - `beadboard doctor --json` - `beadboard self-update` (placeholder behavior with explicit output if publish not configured) - `beadboard uninstall` (remove shims/runtime with `--yes` guard) Add `bin` mapping in `package.json`. **Step 4: Run test to verify pass** Run: ```bash node --import tsx --test tests/cli/beadboard-cli.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add package.json bin/beadboard.js src/cli/beadboard-cli.ts tests/cli/beadboard-cli.test.ts git commit -m "feat(cli): add global entrypoint with doctor/update/uninstall commands" ``` --- ## Phase 6: Driver Alignment + Remediation UX Finalization ### Task 6: Update driver preflight/remediation copy for npm-global-first flow **Files:** - Modify: `skills/beadboard-driver/scripts/lib/driver-lib.mjs` - Modify: `skills/beadboard-driver/scripts/session-preflight.mjs` - Modify: `tests/skills/beadboard-driver/resolve-bb.test.ts` - Modify: `tests/skills/beadboard-driver/session-preflight.test.ts` **Step 1: Write failing test assertion** Add expectation: - remediation mentions `npm i -g beadboard` as primary - install script remains fallback **Step 2: Run test to verify it fails** Run: ```bash node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts ``` Expected: FAIL (copy mismatch). **Step 3: Write minimal implementation** Update remediation strings to: 1. npm-global install 2. fallback installer wrapper 3. BB_REPO override guidance **Step 4: Re-run tests** Run: ```bash node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts node --import tsx --test tests/skills/beadboard-driver/session-preflight.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add skills/beadboard-driver/scripts/lib/driver-lib.mjs skills/beadboard-driver/scripts/session-preflight.mjs tests/skills/beadboard-driver/resolve-bb.test.ts tests/skills/beadboard-driver/session-preflight.test.ts git commit -m "feat(driver): prefer npm-global remediation with installer fallback" ``` --- ## Phase 7: CI, Docs, and Release Readiness ### Task 7: Expand CI smoke and operator docs for global model **Files:** - Modify: `.github/workflows/installer-smoke.yml` - Modify: `README.md` - Modify: `docs/adr/2026-03-03-runtime-manager-global-install.md` - Create: `docs/ops/global-install-rollout.md` - Modify: `tests/scripts/installer-ci-contract.test.ts` - Modify: `tests/docs/installer-quickstart-contract.test.ts` **Step 1: Write failing test updates** Add assertions for: - npm-global command in docs - runtime home path mentions - CI step validating `beadboard doctor --json` **Step 2: Run tests to verify fail** Run: ```bash node --import tsx --test tests/scripts/installer-ci-contract.test.ts node --import tsx --test tests/docs/installer-quickstart-contract.test.ts ``` Expected: FAIL. **Step 3: Write minimal implementation** Update docs and workflow: - install paths - migration notes - recovery playbook - supported platforms matrix **Step 4: Re-run tests** Run: ```bash node --import tsx --test tests/scripts/installer-ci-contract.test.ts node --import tsx --test tests/docs/installer-quickstart-contract.test.ts ``` Expected: PASS. **Step 5: Commit** ```bash git add .github/workflows/installer-smoke.yml README.md docs/adr/2026-03-03-runtime-manager-global-install.md docs/ops/global-install-rollout.md tests/scripts/installer-ci-contract.test.ts tests/docs/installer-quickstart-contract.test.ts git commit -m "docs(ci): finalize global install runtime docs and smoke coverage" ``` --- ## Phase 8: Final Verification + Bead Closeout ### Task 8: Full-gate verification and close **Files:** - Modify: `beadboard` issue notes via `bd update` - Modify: `NEXT_SESSION_PROMPT.md` **Step 1: Run full gates** Run: ```bash npm run typecheck npm run lint npm run test ``` Expected: PASS; if unrelated failures exist, capture exact files/tests. **Step 2: Run targeted installer acceptance checks** Run: ```bash node --import tsx --test tests/lib/runtime-manager.test.ts node --import tsx --test tests/scripts/beadboard-launcher-runtime.test.ts node --import tsx --test tests/scripts/install-legacy-migration.test.ts node --import tsx --test tests/skills/beadboard-driver/resolve-bb.test.ts ``` Expected: PASS. **Step 3: Update beads with evidence** Run: ```bash bd update --notes "" bd close --reason "" ``` **Step 4: Update handoff** Modify: - `NEXT_SESSION_PROMPT.md` with shipped state + residual risks + next bead. **Step 5: Commit** ```bash git add NEXT_SESSION_PROMPT.md git commit -m "chore: close runtime-manager rollout with verification evidence" ``` --- ## References and Required Skills During Execution 1. `@test-driven-development` 2. `@verification-before-completion` 3. `@linus-beads-discipline` 4. `@beadboard-driver` 5. `@executing-plans` (required for implementation phase) --- Plan complete and saved to `docs/plans/2026-03-03-global-install-runtime-manager.md`. Two execution options: **1. Subagent-Driven (this session)** - I dispatch fresh subagent per task, review between tasks, fast iteration **2. Parallel Session (separate)** - Open new session with executing-plans, batch execution with checkpoints Which approach?