feat(#2002): self-healing runtime build for plugin-marketplace installs (#2036)

The compiled gsd-core/bin/lib/*.cjs modules are gitignored build artifacts
(ADR-457) shipped prebuilt in the npm tarball. A Claude Code plugin-marketplace
/ git-clone install materializes the repo tree directly and never runs
`npm run build:lib`, so those ~148 files are absent and every CLI command dies
at load with `Cannot find module './lib/cli-exit.cjs'`.

gsd-tools.cjs now calls ensureRuntimeBuild() before its ./lib requires: a new
committed bin helper that compiles the tree once on demand (lock-guarded,
incremental-cache-cleared, portable `node <tsc>` invocation) when the sentinel
cli-exit.cjs is missing, and surfaces an actionable error when TypeScript is
unavailable. The already-built npm path is a single fs.existsSync no-op.
ADR-457 (gitignored, build-at-publish) is preserved; no release-pipeline change.

Verified against a simulated marketplace checkout (148 build outputs removed):
the CLI self-heals and the result is byte-identical to `npm run build:lib`.

Closes #2002

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-07-05 20:56:12 -04:00
committed by GitHub
parent 76556f715c
commit 19fd9343f6
20 changed files with 642 additions and 15 deletions

View File

@@ -0,0 +1,6 @@
---
type: Changed
pr: 2036
---
**The GSD CLI now self-heals a missing runtime build.** The compiled `gsd-core/bin/lib/*.cjs` modules are gitignored build artifacts (ADR-457) that ship prebuilt in the npm tarball but are absent on a Claude Code plugin-marketplace / git-clone install, which never runs `npm run build:lib`. Previously every command died at load with `Cannot find module './lib/cli-exit.cjs'`. The `gsd-tools` entrypoint now detects the missing output and compiles it once, on demand (lock-guarded so parallel invocations don't race), then proceeds — a single no-op check on the already-built npm path. When TypeScript is genuinely unavailable it prints an actionable `npm install && npm run build:lib` message instead of crashing.