From 0992979c5a02089a64b2a31098153f40b3c16ab8 Mon Sep 17 00:00:00 2001 From: Koshkoshinsk Date: Sun, 19 Apr 2026 12:01:05 +0000 Subject: [PATCH] feat(new-setup): probe host-deps and skip bootstrap when already installed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Probe now emits HOST_DEPS (ok|missing) based on whether node_modules/better-sqlite3/build/Release/better_sqlite3.node exists — the canonical proof that `pnpm install` ran and the native build step succeeded. Step 1 (Node bootstrap) skips when HOST_DEPS=ok instead of always re-running setup.sh. Probe now genuinely routes step 1 the same way it routes every other step. Co-Authored-By: Claude Opus 4.7 (1M context) --- .claude/skills/new-setup/SKILL.md | 6 ++++-- setup/probe.mjs | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.claude/skills/new-setup/SKILL.md b/.claude/skills/new-setup/SKILL.md index ba62242..f08fd16 100644 --- a/.claude/skills/new-setup/SKILL.md +++ b/.claude/skills/new-setup/SKILL.md @@ -38,12 +38,14 @@ One permitted parallelism: ### 1. Node bootstrap -If the probe reported `STATUS: unavailable` (Node isn't installed yet), install Node 22 **before** running `bash setup.sh` — otherwise the first bootstrap run is guaranteed to fail and you'll pay for it twice: +Check probe results and skip if `HOST_DEPS=ok` — Node, pnpm, `node_modules`, and `better-sqlite3`'s native binding are already in place. + +If the probe reported `STATUS: unavailable` (Node isn't installed yet — probe itself couldn't run), install Node 22 **before** running `bash setup.sh`, otherwise the first bootstrap run is guaranteed to fail: - macOS: `brew install node@22` - Linux / WSL: `curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs` -Then run `bash setup.sh`. If the probe reported any other status, run `bash setup.sh` directly — it's idempotent and verifies host deps + native modules. +Then run `bash setup.sh`. If the probe succeeded but `HOST_DEPS=missing`, run `bash setup.sh` directly — Node is there, deps aren't. Parse the status block: diff --git a/setup/probe.mjs b/setup/probe.mjs index a28f759..5aea0d4 100644 --- a/setup/probe.mjs +++ b/setup/probe.mjs @@ -268,6 +268,22 @@ function probeInferredDisplayName() { return 'User'; } +function probeHostDeps() { + const nodeModules = path.resolve(process.cwd(), 'node_modules'); + if (!fs.existsSync(nodeModules)) return 'missing'; + // better-sqlite3's compiled native binding is the canonical proof that + // `pnpm install` ran AND the native build step succeeded. Cheaper than + // actually loading the module, and unambiguous on success. + const nativeBinding = path.join( + nodeModules, + 'better-sqlite3', + 'build', + 'Release', + 'better_sqlite3.node', + ); + return fs.existsSync(nativeBinding) ? 'ok' : 'missing'; +} + function probeTimezone() { const envTz = readEnvVar('TZ'); const systemTz = Intl.DateTimeFormat().resolvedOptions().timeZone || ''; @@ -309,6 +325,7 @@ export async function run() { const serviceStatus = probeServiceStatus(); const displayName = probeInferredDisplayName(); const tz = probeTimezone(); + const hostDeps = probeHostDeps(); const [onecliStatus, cliAgentWired] = await Promise.all([ probeOnecliStatus(oneCliUrl), @@ -323,6 +340,7 @@ export async function run() { emitStatus('PROBE', { OS: osLabel, SHELL: shell, + HOST_DEPS: hostDeps, DOCKER: docker.status, IMAGE_PRESENT: docker.imagePresent, ONECLI_STATUS: onecliStatus,