checkpoint: pre-split branch cleanup
This commit is contained in:
parent
4c2ae2e5b7
commit
b5db7a7753
276 changed files with 35912 additions and 60119 deletions
533
docs/plans/2026-03-03-global-install-runtime-manager.md
Normal file
533
docs/plans/2026-03-03-global-install-runtime-manager.md
Normal file
|
|
@ -0,0 +1,533 @@
|
|||
# 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/<version>` + 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: `/mnt/c/Users/Zenchant/codex/beadboard/AGENTS.md`
|
||||
- Read: `/mnt/c/Users/Zenchant/codex/beadboard/NEXT_SESSION_PROMPT.md`
|
||||
|
||||
**Step 1: Claim/track implementation bead(s)**
|
||||
|
||||
Run:
|
||||
```bash
|
||||
cd /mnt/c/Users/Zenchant/codex/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 <new-bead-id> --status in_progress --assignee <agent-bead-id>
|
||||
```
|
||||
|
||||
**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/<version> 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 <bead-id> --notes "<commands run + pass/fail details>"
|
||||
bd close <bead-id> --reason "<completed outcome>"
|
||||
```
|
||||
|
||||
**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?
|
||||
Loading…
Add table
Add a link
Reference in a new issue