diff --git a/skills/beadboard-driver/scripts/lib/driver-lib.mjs b/skills/beadboard-driver/scripts/lib/driver-lib.mjs index 2bb2a19..86dd95a 100644 --- a/skills/beadboard-driver/scripts/lib/driver-lib.mjs +++ b/skills/beadboard-driver/scripts/lib/driver-lib.mjs @@ -77,6 +77,13 @@ async function validateRepoPath(repoPath) { return { ok: true, bbPath }; } +function installerRemediation() { + if (process.platform === 'win32') { + return 'Primary: npm i -g beadboard. Fallback: powershell -ExecutionPolicy Bypass -File .\\install\\install.ps1'; + } + return 'Primary: npm i -g beadboard. Fallback: bash ./install/install.sh'; +} + async function discoverBbPath() { const configuredRoots = splitPathVariable(process.env.BB_SEARCH_ROOTS || ''); const roots = configuredRoots.length > 0 ? configuredRoots : [process.cwd(), path.join(homeRoot(), 'codex'), homeRoot()]; @@ -126,7 +133,7 @@ async function resolveBbPath() { source: 'env', resolved_path: null, reason: validated.reason, - remediation: 'Set BB_REPO to your BeadBoard repo root, e.g. `$env:BB_REPO="C:\\path\\to\\beadboard"`.', + remediation: `Set BB_REPO to your BeadBoard repo root, e.g. \`$env:BB_REPO="C:\\path\\to\\beadboard"\`. ${installerRemediation()}`, }; } @@ -177,8 +184,7 @@ async function resolveBbPath() { source: 'none', resolved_path: null, reason: 'Unable to find bb command or bb.ps1.', - remediation: - 'Set BB_REPO to your BeadBoard repo root, or install a global bb command, then retry.', + remediation: `Set BB_REPO to your BeadBoard repo root, or install a global bb command, then retry. ${installerRemediation()}`, }; } diff --git a/skills/beadboard-driver/scripts/session-preflight.mjs b/skills/beadboard-driver/scripts/session-preflight.mjs index 2bb3e54..bb916a4 100644 --- a/skills/beadboard-driver/scripts/session-preflight.mjs +++ b/skills/beadboard-driver/scripts/session-preflight.mjs @@ -12,7 +12,10 @@ async function main() { ok: false, error_code: 'BD_NOT_FOUND', reason: 'Could not find bd in PATH.', - remediation: 'Install beads CLI or add bd executable to PATH.', + remediation: + process.platform === 'win32' + ? 'Primary: npm i -g beadboard. Fallback: powershell -ExecutionPolicy Bypass -File .\\install\\install.ps1. Then ensure bd is available in PATH.' + : 'Primary: npm i -g beadboard. Fallback: bash ./install/install.sh. Then ensure bd is available in PATH.', tools: { bd: { available: false, path: null }, }, diff --git a/tests/skills/beadboard-driver/resolve-bb.test.ts b/tests/skills/beadboard-driver/resolve-bb.test.ts index c480d6a..0451ef8 100644 --- a/tests/skills/beadboard-driver/resolve-bb.test.ts +++ b/tests/skills/beadboard-driver/resolve-bb.test.ts @@ -55,6 +55,12 @@ test('resolve-bb fails with remediation when BB_REPO is invalid', async () => { assert.equal(result.source, 'env'); assert.match(result.reason, /BB_REPO/i); assert.match(result.remediation, /Set BB_REPO/i); + assert.match(result.remediation, /npm i -g beadboard/i); + if (process.platform === 'win32') { + assert.match(result.remediation, /install\.ps1/i); + } else { + assert.match(result.remediation, /install\.sh/i); + } }); }); diff --git a/tests/skills/beadboard-driver/session-preflight.test.ts b/tests/skills/beadboard-driver/session-preflight.test.ts index 7f174a4..e41ecd6 100644 --- a/tests/skills/beadboard-driver/session-preflight.test.ts +++ b/tests/skills/beadboard-driver/session-preflight.test.ts @@ -32,18 +32,30 @@ test('session-preflight fails when bd is unavailable', async () => { assert.equal(result.ok, false); assert.equal(result.error_code, 'BD_NOT_FOUND'); + assert.match(result.remediation, /npm i -g beadboard/i); + if (process.platform === 'win32') { + assert.match(result.remediation, /install\.ps1/i); + } else { + assert.match(result.remediation, /install\.sh/i); + } }); test('session-preflight succeeds with fake bd and BB_REPO', async () => { await withTempDir(async (root) => { const repo = path.join(root, 'beadboard'); const toolsDir = path.join(root, 'tools'); - const bdCmd = path.join(toolsDir, 'bd.cmd'); + const bdExecutable = process.platform === 'win32' ? 'bd.cmd' : 'bd'; + const bdCmd = path.join(toolsDir, bdExecutable); await fs.mkdir(path.join(repo, 'tools'), { recursive: true }); await fs.mkdir(toolsDir, { recursive: true }); await fs.writeFile(path.join(repo, 'bb.ps1'), 'echo ok', 'utf8'); - await fs.writeFile(bdCmd, '@echo off\r\necho beads\r\n', 'utf8'); + if (process.platform === 'win32') { + await fs.writeFile(bdCmd, '@echo off\r\necho beads\r\n', 'utf8'); + } else { + await fs.writeFile(bdCmd, '#!/usr/bin/env sh\necho beads\n', 'utf8'); + await fs.chmod(bdCmd, 0o755); + } const result = await runPreflight({ PATH: toolsDir,