Commit Graph

4 Commits

Author SHA1 Message Date
Jeremy McSpadden
0a049149e1 fix(sdk): decouple from build-from-source install, close #2441 #2453 (#2457)
* fix(sdk): decouple SDK from build-from-source install path, close #2441 and #2453

Ship sdk/dist prebuilt in the tarball and replace the npm-install-g
sub-install with a parent-package bin shim (bin/gsd-sdk.js). npm chmods
bin entries from a packed tarball correctly, eliminating the mode-644
failure (#2453) and the full class of NPM_CONFIG_PREFIX/ignore-scripts/
corepack/air-gapped failure modes that caused #2439 and #2441.

Changes:
- sdk/package.json: prepublishOnly runs `rm -rf dist && tsc && chmod +x
  dist/cli.js` (stale-build guard + execute-bit fix at publish time)
- package.json: add "gsd-sdk": "bin/gsd-sdk.js" bin entry; add sdk/dist
  to files so the prebuilt CLI ships in the tarball
- bin/gsd-sdk.js: new back-compat shim — resolves sdk/dist/cli.js relative
  to the package root and delegates via `node`, so all existing PATH call
  sites (slash commands, agents, hooks) continue to work unchanged (S1 shim)
- bin/install.js: replace installSdkIfNeeded() build-from-source + global-
  install dance with a dist-verify + chmod-in-place guard; delete
  resolveGsdSdk(), detectShellRc(), emitSdkFatal() helpers now unused
- .github/workflows/install-smoke.yml: add smoke-unpacked job that strips
  execute bit from sdk/dist/cli.js before install to reproduce the exact
  #2453 failure mode
- tests/bug-2441-sdk-decouple.test.cjs: new regression tests asserting all
  invariants (no npm install -g from sdk/, shim exists, sdk/dist in files,
  prepublishOnly has rm -rf + chmod)
- tests/bugs-1656-1657.test.cjs: update stale assertions that required
  build-from-source behavior (now asserts new prebuilt-dist invariants)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* chore(release): bump to 1.38.2, wire release.yml to build SDK dist

- Bump version 1.38.1 -> 1.38.2 for the #2441/#2453 fix shipped in 0f6903d.
- Add `build:sdk` script (`cd sdk && npm ci && npm run build`).
- `prepublishOnly` now runs hooks + SDK builds as a safety net.
- release.yml (rc + finalize): build SDK dist before `npm publish` so the
  published tarball always ships fresh `sdk/dist/` (kept gitignored).
- CHANGELOG: document 1.38.2 entry and `--sdk` flag semantics change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ci: build SDK dist before tests and smoke jobs

sdk/dist/ is gitignored (built fresh at publish time via release.yml),
but both the test suite and install-smoke jobs run `bin/install.js`
or `npm pack` against the checked-out tree where dist doesn't exist yet.

- test.yml: `npm run build:sdk` before `npm run test:coverage`, so tests
  that spawn `bin/install.js` don't hit `installSdkIfNeeded()`'s fatal
  missing-dist check.
- install-smoke.yml (both smoke and smoke-unpacked): build SDK before
  pack/chmod so the published tarball contains dist and the unpacked
  install has a file to strip exec-bit from.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sdk): lift SDK runtime deps to parent so tarball install can resolve them

The SDK's runtime deps (ws, @anthropic-ai/claude-agent-sdk) live in
sdk/package.json, but sdk/node_modules is NOT shipped in the parent
tarball — only sdk/dist, sdk/src, sdk/prompts, and sdk/package.json are.
When a user runs `npm install -g get-shit-done-cc`, npm installs the
parent's node_modules but never runs `npm install` inside the nested
sdk/ directory.

Result: `node sdk/dist/cli.js` fails with ERR_MODULE_NOT_FOUND for 'ws'.
The smoke tarball job caught this; the unpacked variant masked it
because `npm install -g <dir>` copies the entire workspace including
sdk/node_modules (left over from `npm run build:sdk`).

Fix: declare the same deps in the parent package.json so they land in
<pkg>/node_modules, which Node's resolution walks up to from
<pkg>/sdk/dist/cli.js. Keep them declared in sdk/package.json too so
the SDK remains a self-contained package for standalone dev.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(lockfile): regenerate package-lock.json cleanly

The previous `npm install` run left the lockfile internally inconsistent
(resolved esbuild@0.27.7 referenced but not fully written), causing
`npm ci` to fail in CI with "Missing from lock file" errors.

Clean regen via rm + npm install fixes all three failed jobs
(test, smoke, smoke-unpacked), which were all hitting the same
`npm ci` sync check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(deps): remove unused esbuild + vitest from root devDependencies

Both were declared but never imported anywhere in the root package
(confirmed via grep of bin/, scripts/, tests/). They lived in sdk/
already, which is the only place they're actually used.

The transitive tree they pulled in (vitest → vite → esbuild 0.28 →
@esbuild/openharmony-arm64) was the root of the CI npm ci failures:
the openharmony platform package's `optional: true` flag was not being
applied correctly by npm 10 on Linux runners, causing EBADPLATFORM.

After removal: 800+ transitive packages → 155. Lockfile regenerated
cleanly. All 4170 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(sdk): pretest:coverage builds sdk; tighten shim test assertions

Add "pretest:coverage": "npm run build:sdk" so npm run test:coverage
works in clean checkouts where sdk/dist/ hasn't been built yet.

Tighten the two loose shim assertions in bug-2441-sdk-decouple.test.cjs:
- forwards-to test now asserts path.resolve() is called with the
  'sdk','dist','cli.js' path segments, not just substring presence
- node-invocation test now asserts spawnSync(process.execPath, [...])
  pattern, ruling out matches in comments or the shebang line

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: address PR review — pretest:coverage + tighten shim tests

Review feedback from trek-e on PR 2457:

1. pretest:coverage + pretest hooks now run `npm run build:sdk` so
   `npm run test[:coverage]` in a clean checkout produces the required
   sdk/dist/ artifacts before running the installer-dependent tests.
   CI already does this explicitly; local contributors benefit.

2. Shim tests in bug-2441-sdk-decouple.test.cjs tightened from loose
   substring matches (which would pass on comments/shebangs alone) to
   regex assertions on the actual path.resolve call, spawnSync with
   process.execPath, process.argv.slice(2), and process.exit pattern.
   These now provide real regression protection for #2453-class bugs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: correct CHANGELOG entry and add [1.38.2] reference link

Two issues in the 1.38.2 CHANGELOG entry:
- installSdkIfNeeded() was described as deleted but it still exists in
  bin/install.js (repurposed to verify sdk/dist/cli.js and fix execute bit).
  Corrected the description to say 'repurposes' rather than 'deletes'.
- The reference-link block at the bottom of the file was missing a [1.38.2]
  compare URL and [Unreleased] still pointed to v1.37.1...HEAD. Added the
  [1.38.2] link and updated [Unreleased] to compare/v1.38.2...HEAD.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(sdk): double-cast WorkflowConfig to Record for strict tsc build

TypeScript error on main (introduced in #2611) blocks `npm run build`
in sdk/, which now runs as part of this PR's tarball build path. Apply
the double-cast via `unknown` as the compiler suggests.

Same fix as #2622; can be dropped if that lands first.

* test: remove bug-2598 test obsoleted by SDK decoupling

The bug-2598 test guards the Windows CVE-2024-27980 fix in the old
build-from-source path (npm spawnSync with shell:true + formatSpawnFailure
diagnostics). This PR removes that entire code path — installSdkIfNeeded
no longer spawns npm, it just verifies the prebuilt sdk/dist/cli.js
shipped in the tarball.

The test asserts `installSdkIfNeeded.toString()` contains a
formatSpawnFailure helper. After decoupling, no such helper exists
(nothing to format — there's no spawn). Keeping the test would assert
invariants of the rejected architecture.

The original #2598 defect (silent failure of npm spawn on Windows) is
structurally impossible in the shim path: bin/gsd-sdk.js invokes
`node sdk/dist/cli.js` directly via child_process.spawn with an
explicit argv array. No .cmd wrapper, no shell delegation.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Tom Boucher <trekkie@nomorestars.com>
2026-04-23 08:36:03 -04:00
Tom Boucher
e3f40201dd fix(sdk): bump engines.node from >=20 to >=22.0.0 (#2465)
Node 20 reaches EOL April 30 2026. The root package already declares
>=22.0.0 and CI only runs Node 22 and 24. Align sdk/package.json so
`npm install` on Node 20 fails with a clear engines mismatch rather
than a silent install that breaks at runtime.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 23:02:57 -04:00
TÂCHES
89f95c43ba feat: auto --init flag, headless prompts, and prompt sanitizer (#1417)
* fix: Created 10 headless prompt files (5 workflows + 5 agents) in sdk/p…

- "sdk/prompts/workflows/execute-plan.md"
- "sdk/prompts/workflows/research-phase.md"
- "sdk/prompts/workflows/plan-phase.md"
- "sdk/prompts/workflows/verify-phase.md"
- "sdk/prompts/workflows/discuss-phase.md"
- "sdk/prompts/agents/gsd-executor.md"
- "sdk/prompts/agents/gsd-phase-researcher.md"
- "sdk/prompts/agents/gsd-planner.md"

GSD-Task: S01/T02

* feat: Created prompt-sanitizer.ts, wired headless prompt loading into P…

- "sdk/src/prompt-sanitizer.ts"
- "sdk/src/phase-prompt.ts"
- "sdk/src/gsd-tools.ts"
- "sdk/src/gsd-tools.test.ts"
- "sdk/src/phase-runner-types.test.ts"

GSD-Task: S01/T01

* test: Added 111 unit tests covering sanitizePrompt(), headless prompt l…

- "sdk/src/prompt-sanitizer.test.ts"
- "sdk/src/headless-prompts.test.ts"
- "sdk/src/phase-prompt.test.ts"

GSD-Task: S01/T03

* feat: Wired sdkPromptsDir preference and sanitizePrompt into InitRunner…

- "sdk/src/init-runner.ts"
- "sdk/package.json"

GSD-Task: S02/T01

* feat: add --init flag to auto command for single-command PRD-to-execution

gsd-sdk auto --init @path/to/prd.md now bootstraps the project (init)
then immediately runs the autonomous phase execution loop.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* chore: add remaining headless prompt files and templates

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: Extended init-runner.test.ts with 7 sdkPromptsDir preference and…

- "sdk/src/init-runner.test.ts"

GSD-Task: S02/T03

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 22:40:34 -06:00
TÂCHES
596ce2d252 feat: GSD SDK — headless CLI with init + auto commands (#1407)
* test: Bootstrapped sdk/ as TypeScript ESM package with full GSD-1 PLAN.…

- "sdk/package.json"
- "sdk/tsconfig.json"
- "sdk/vitest.config.ts"
- "sdk/src/types.ts"
- "sdk/src/plan-parser.ts"
- "sdk/src/plan-parser.test.ts"

GSD-Task: S01/T01

* test: Implemented config reader and gsd-tools bridge with 25 unit tests…

- "sdk/src/config.ts"
- "sdk/src/config.test.ts"
- "sdk/src/gsd-tools.ts"
- "sdk/src/gsd-tools.test.ts"

GSD-Task: S01/T02

* test: Built prompt-builder, session-runner, and GSD class — 85 total un…

- "sdk/src/prompt-builder.ts"
- "sdk/src/prompt-builder.test.ts"
- "sdk/src/session-runner.ts"
- "sdk/src/index.ts"
- "sdk/src/types.ts"

GSD-Task: S01/T03

* test: Created E2E integration test with fixtures proving full SDK pipel…

- "sdk/src/e2e.integration.test.ts"
- "sdk/test-fixtures/sample-plan.md"
- "sdk/test-fixtures/.planning/config.json"
- "sdk/test-fixtures/.planning/STATE.md"
- "vitest.config.ts"
- "tsconfig.json"

GSD-Task: S01/T04

* test: Added PhaseType/GSDEventType enums, 16-variant GSDEvent union, GS…

- "sdk/src/types.ts"
- "sdk/src/event-stream.ts"
- "sdk/src/logger.ts"
- "sdk/src/event-stream.test.ts"
- "sdk/src/logger.test.ts"

GSD-Task: S02/T01

* test: Built ContextEngine for phase-aware context file resolution, getT…

- "sdk/src/context-engine.ts"
- "sdk/src/tool-scoping.ts"
- "sdk/src/phase-prompt.ts"
- "sdk/src/context-engine.test.ts"
- "sdk/src/tool-scoping.test.ts"
- "sdk/src/phase-prompt.test.ts"

GSD-Task: S02/T02

* test: Wired event stream into session runner, added onEvent()/addTransp…

- "sdk/src/session-runner.ts"
- "sdk/src/index.ts"
- "sdk/src/e2e.integration.test.ts"

GSD-Task: S02/T03

* feat: Added PhaseStepType enum, PhaseOpInfo interface, phase lifecycle…

- "sdk/src/types.ts"
- "sdk/src/gsd-tools.ts"
- "sdk/src/session-runner.ts"
- "sdk/src/index.ts"
- "sdk/src/phase-runner-types.test.ts"

GSD-Task: S03/T01

* test: Implemented PhaseRunner state machine with 39 unit tests covering…

- "sdk/src/phase-runner.ts"
- "sdk/src/phase-runner.test.ts"

GSD-Task: S03/T02

* test: Wired PhaseRunner into GSD.runPhase() public API with full re-exp…

- "sdk/src/index.ts"
- "sdk/src/phase-runner.integration.test.ts"
- "sdk/src/phase-runner.ts"

GSD-Task: S03/T03

* test: Expanded runVerifyStep with full gap closure cycle (plan → execut…

- "sdk/src/types.ts"
- "sdk/src/phase-runner.ts"
- "sdk/src/phase-runner.test.ts"

GSD-Task: S04/T02

* fix: Added 3 integration tests proving phasePlanIndex returns correct t…

- "sdk/src/phase-runner.integration.test.ts"
- "sdk/src/index.ts"

GSD-Task: S04/T03

* test: Add milestone-level types, typed roadmapAnalyze(), GSD.run() orch…

- "sdk/src/types.ts"
- "sdk/src/gsd-tools.ts"
- "sdk/src/index.ts"
- "sdk/src/milestone-runner.test.ts"

GSD-Task: S05/T01

* test: Added CLITransport (structured stdout log lines) and WSTransport…

- "sdk/src/cli-transport.ts"
- "sdk/src/cli-transport.test.ts"
- "sdk/src/ws-transport.ts"
- "sdk/src/ws-transport.test.ts"
- "sdk/src/index.ts"
- "sdk/package.json"

GSD-Task: S05/T02

* test: Added gsd-sdk CLI entry point with argument parsing, bin field, p…

- "sdk/src/cli.ts"
- "sdk/src/cli.test.ts"
- "sdk/package.json"

GSD-Task: S05/T03

* feat: Add InitNewProjectInfo type, initNewProject()/configSet() GSDTool…

- "sdk/src/types.ts"
- "sdk/src/gsd-tools.ts"
- "sdk/src/cli.ts"
- "sdk/src/cli.test.ts"
- "sdk/src/gsd-tools.test.ts"

GSD-Task: S01/T01

* chore: Created InitRunner orchestrator with setup → config → PROJECT.md…

- "sdk/src/init-runner.ts"
- "sdk/src/types.ts"
- "sdk/src/index.ts"

GSD-Task: S01/T02

* test: Wired InitRunner into CLI main() for full gsd-sdk init dispatch a…

- "sdk/src/cli.ts"
- "sdk/src/init-runner.test.ts"
- "sdk/src/cli.test.ts"

GSD-Task: S01/T03

* test: Add PlanCheck step, AI self-discuss, and retryOnce wrapper to Pha…

- "sdk/src/types.ts"
- "sdk/src/phase-runner.ts"
- "sdk/src/session-runner.ts"
- "sdk/src/phase-runner.test.ts"
- "sdk/src/phase-runner-types.test.ts"

GSD-Task: S02/T01

* feat: Rewrite CLITransport with ANSI colors, phase banners, spawn indic…

- "sdk/src/cli-transport.ts"
- "sdk/src/cli-transport.test.ts"

GSD-Task: S02/T02

* test: Add `gsd-sdk auto` command with autoMode config override, USAGE t…

- "sdk/src/cli.ts"
- "sdk/src/cli.test.ts"
- "sdk/src/index.ts"
- "sdk/src/types.ts"

GSD-Task: S02/T03

* fix: CLI shebang + gsd-tools non-JSON output handling

Three bugs found during first real gsd-sdk run:

1. cli.ts shebang was commented out — shell executed JS as bash,
   triggering ImageMagick's import command instead of Node

2. configSet() called exec() which JSON.parse()d the output, but
   gsd-tools config-set returns 'key=value' text, not JSON.
   Added execRaw() method for commands that return plain text.

3. Same JSON parse bug affected commit() (returns git SHA),
   stateLoad(), verifySummary(), initExecutePhase(), stateBeginPhase(),
   and phaseComplete(). All switched to execRaw().

Tests updated to match real gsd-tools output format (plain text
instead of mocked JSON). 376/376 tests pass.
2026-03-26 20:27:51 -06:00