From 0fbe1d899e986dc38823547c712a5b3d39d342de Mon Sep 17 00:00:00 2001 From: Tom Boucher Date: Sat, 30 May 2026 19:19:14 -0400 Subject: [PATCH] =?UTF-8?q?chore(#191):=20retire=20the=20gsd-sdk=20shim=20?= =?UTF-8?q?=E2=80=94=20route=20everything=20at=20gsd-tools=20(#522)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(#191): migrate gsd-sdk query call sites to gsd-tools query Retiring the gsd-sdk shim. gsd-tools.cjs already accepts `query` as a meta-prefix (gsd-tools query ), so this is a behavior-preserving 1:1 swap across the runtime reference prompts, the graphify hook's commit-detection gate, and two bin/lib comment/message references. Co-Authored-By: Claude Opus 4.8 * chore(#191): remove vestigial gsd-sdk shim code from installer + projection The gsd-sdk shim was already not wired up (no gsd-sdk bin in package.json; buildWindowsShimTriple had zero call sites). Remove the dead code: - shell-command-projection.cjs: buildWindowsShimTriple + formatSdkPathDiagnostic (+ their now-unused PACKAGE_NAME import) and exports - install.js: the re-export wrappers + imports, the #3406 stale-standalone-sdk detection (detectStaleStandaloneSdk/formatStaleStandaloneSdkWarning + its global-install call site), and the exports Preserved (retained, not gsd-sdk): buildCodexHookWindowsShimIR (#3426) — only its comments referenced the gsd-sdk pattern; reworded. Also kept the homePathCoveredByRc 'reopen your shell' branch in maybeSuggestPathExport — its logic is bin-dir-agnostic, only the message mentioned gsd-sdk; reworded to use the actual bin dir. Co-Authored-By: Claude Opus 4.8 * test(#191): update tests for retired gsd-sdk shim - bug-3441/bug-3442: drop the formatSdkPathDiagnostic / buildWindowsShimTriple assertions (functions removed); retained PATH-action + drift-guard tests stay - bug-505: remove the 'still exported' assertions for detectStaleStandaloneSdk / formatStaleStandaloneSdkWarning / the shim contract surface (#505 kept them; #191 removes them) - graphify-auto-update: migrate the hook-dispatch inputs gsd-sdk query commit -> gsd-tools query commit to match the migrated commit hook Co-Authored-By: Claude Opus 4.8 * docs(#191): point active docs at gsd-tools query (gsd-sdk shim retired) Update the user/agent-facing docs (AGENTS, COMMANDS, CONFIGURATION, USER-GUIDE, ship-pr-body-sections) that presented gsd-sdk query as a current command to gsd-tools query. Historical docs (ADRs, PRDs, release notes) left untouched. Co-Authored-By: Claude Opus 4.8 * docs(#191): correct state.load vs state.json description for gsd-tools query Adversarial-review (codex) finding: the migrated USER-GUIDE line claimed both 'gsd-tools query state.json' and 'state.load' resolve to the frontmatter-rebuild handler. Verified they don't — state.load returns the CJS load shape (config + state_raw + flags), state.json returns the frontmatter shape. Both are available via gsd-tools query; corrected the text to say so. Co-Authored-By: Claude Opus 4.8 * chore(#191): add changeset for gsd-sdk shim retirement Co-Authored-By: Claude Opus 4.8 --------- Co-authored-by: Claude Opus 4.8 --- .changeset/plucky-pumas-tumble.md | 5 + bin/install.js | 149 ++---------------- docs/AGENTS.md | 4 +- docs/COMMANDS.md | 4 +- docs/CONFIGURATION.md | 10 +- docs/USER-GUIDE.md | 6 +- docs/ship-pr-body-sections.md | 4 +- get-shit-done/bin/lib/code-review-flags.cjs | 2 +- .../bin/lib/shell-command-projection.cjs | 53 ------- .../bin/lib/state-command-router.cjs | 2 +- .../references/autonomous-smart-discuss.md | 6 +- .../references/decimal-phase-calculation.md | 10 +- get-shit-done/references/git-integration.md | 8 +- .../references/git-planning-commit.md | 6 +- .../references/phase-argument-parsing.md | 6 +- get-shit-done/references/planner-revision.md | 2 +- get-shit-done/references/planning-config.md | 14 +- .../references/universal-anti-patterns.md | 4 +- get-shit-done/references/verify-mvp-mode.md | 2 +- get-shit-done/references/workstream-flag.md | 22 +-- hooks/gsd-graphify-update.sh | 6 +- .../bug-3441-path-action-projection.test.cjs | 19 +-- ...-3442-shim-projection-drift-guard.test.cjs | 17 +- ...-505-remove-dead-sdk-verification.test.cjs | 33 +--- tests/graphify-auto-update.test.cjs | 16 +- 25 files changed, 91 insertions(+), 319 deletions(-) create mode 100644 .changeset/plucky-pumas-tumble.md diff --git a/.changeset/plucky-pumas-tumble.md b/.changeset/plucky-pumas-tumble.md new file mode 100644 index 000000000..05a26395d --- /dev/null +++ b/.changeset/plucky-pumas-tumble.md @@ -0,0 +1,5 @@ +--- +type: Removed +pr: 522 +--- +Retire the gsd-sdk shim/command. GSD now invokes gsd-tools query (behaviorally identical via gsd-tools' query meta-prefix) everywhere; the vestigial gsd-sdk shim builder, installer wiring, and the #3406 stale-standalone-sdk shadow warning are removed. diff --git a/bin/install.js b/bin/install.js index 918da634d..fec39755a 100755 --- a/bin/install.js +++ b/bin/install.js @@ -6,8 +6,6 @@ const os = require('os'); const readline = require('readline'); const crypto = require('crypto'); const { - buildWindowsShimTriple: buildWindowsShimTripleFromProjection, - formatSdkPathDiagnostic: formatSdkPathDiagnosticFromProjection, isManagedHookBasename, isManagedHookCommand, projectLocalHookPrefix, @@ -1070,8 +1068,8 @@ function reconcileCodexHooksJsonSessionStart(targetDir, opts = {}) { * (a Windows PE binary) via execvp(), which fails with ENOEXEC on Windows PE * binaries that the MSYS layer doesn't know how to fork-exec natively. * - * Fix: write a .cmd shim (same IR pattern as buildWindowsShimTriple for - * gsd-sdk.cmd) whose content is `@ECHO OFF / @SETLOCAL / @"node.exe" "script.js" %*`. + * Fix: write a .cmd shim (using the same CRLF .cmd shim pattern) whose + * content is `@ECHO OFF / @SETLOCAL / @"node.exe" "script.js" %*`. * cmd.exe executes * .cmd natively via CreateProcess — no POSIX exec layer, no MSYS shebang * walk, no PE binary fork-exec failure. @@ -1117,9 +1115,8 @@ function buildCodexHookWindowsShimIR(scriptAbsPath, absoluteRunnerToken) { eol: { cmd: '\r\n' }, // CRLF — canonical for cmd.exe .cmd files passthroughArgs: true, // the shim forwards all args via %* render: { - // Mirror buildWindowsShimTriple's CRLF line endings for strict - // cmd.exe compatibility (LF-only .cmd files work in modern Windows but - // CRLF is canonical and what the existing gsd-sdk.cmd triple emits). + // Use CRLF line endings for strict cmd.exe compatibility (LF-only + // .cmd files work in modern Windows but CRLF is the canonical format). cmd: () => `@ECHO OFF\r\n@SETLOCAL\r\n@${runnerQuoted} ${scriptQuoted} %*\r\n`, }, }; @@ -8275,45 +8272,6 @@ function install(isGlobal, runtime = 'claude', options = {}) { ? targetDir.replace(os.homedir(), '~') : targetDir.replace(process.cwd(), '.'); - // #3406: warn if a stale standalone `@opengsd/gsd-sdk` is globally installed - // and shadows the `gsd-sdk` shim this installer wires up. Only meaningful - // for global installs (the shim collision lives in the global node_modules - // bin dir). Guarded by GSD_SKIP_STALE_SDK_CHECK so CI/tests can silence it. - // #3406 CR: opt-out only on explicit "1" / "true" / "yes" rather than any - // non-empty value. Without this guard `GSD_SKIP_STALE_SDK_CHECK=0` and - // `GSD_SKIP_STALE_SDK_CHECK=false` would silently disable the check. - const skipRaw = process.env.GSD_SKIP_STALE_SDK_CHECK; - const skipStaleCheck = skipRaw === '1' || skipRaw === 'true' || skipRaw === 'yes'; - if (isGlobal && !skipStaleCheck) { - try { - const { execFileSync } = require('child_process'); - const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm'; - const staleInfo = detectStaleStandaloneSdk(() => { - try { - return execFileSync( - npmCmd, - ['ls', '-g', '@opengsd/gsd-sdk', '--json', '--depth=0'], - { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 10_000 } - ); - } catch (e) { - // `npm ls -g ` exits 1 with the JSON still on stdout when - // the package is absent. execFileSync throws on non-zero exit but - // attaches stdout to the error. Recover the JSON in that case so - // the detector classifies "absent" correctly. - if (e && typeof e.stdout !== 'undefined') { - return Buffer.isBuffer(e.stdout) ? e.stdout.toString('utf-8') : String(e.stdout); - } - throw e; - } - }); - if (staleInfo.stale) { - console.warn(`\n${yellow}${formatStaleStandaloneSdkWarning(staleInfo)}${reset}\n`); - } - } catch { - // Detection is best-effort; never block install on its failure. - } - } - // Path prefix for file references in markdown content (e.g. gsd-tools.cjs). // Replaces $HOME/.claude/ or ~/.claude/ so the result is get-shit-done/bin/... // For global installs: use $HOME/ so paths expand correctly inside double-quoted @@ -10673,8 +10631,13 @@ function maybeSuggestPathExport(globalBin, homeDir) { }); if (onPath) return; + // Already added to PATH via an rc file, but the current shell predates that + // edit — tell the user to reopen rather than (wrongly) suggesting they add it + // again. Applies to whatever bin dir we install into (retained shim-agnostic). if (homePathCoveredByRc(globalBin, homeDir)) { - console.log(` ${yellow}⚠${reset} ${bold}gsd-sdk${reset}'s directory is already on your PATH via an rc file entry — try reopening your shell (or ${cyan}source ~/.zshrc${reset}).`); + console.log(''); + console.log(` ${yellow}⚠${reset} ${bold}${globalBin}${reset}'s directory is already on your PATH via an rc file entry — try reopening your shell (or ${cyan}source ~/.zshrc${reset}).`); + console.log(''); return; } @@ -10692,94 +10655,6 @@ function maybeSuggestPathExport(globalBin, homeDir) { console.log(''); } -/** - * #3406 helper: detect a stale globally-installed `@opengsd/gsd-sdk` package - * shadowing the `gsd-sdk` shim that `@opengsd/gsd-core` installs. - * - * Background: `@opengsd/gsd-sdk@0.1.0` was published once and never updated - * (the SDK now ships embedded in `@opengsd/gsd-core`). When a user has the - * 0.1.0 standalone package installed globally, its `gsd-sdk` bin shadows - * the one `@opengsd/gsd-core` provides — and the 0.1.0 binary only knows - * `run | auto | init` (no `query`), so every `gsd-sdk query ` - * call from skills/hooks fails until the user runs - * `npm uninstall -g @opengsd/gsd-sdk`. - * - * Pure function: takes an injected `runNpmLs` executor that returns - * `npm ls -g @opengsd/gsd-sdk --json --depth=0` stdout. Returns: - * `{ stale: true, version }` when the package is present. - * `{ stale: false }` for every other input — including: - * - executor throws (npm missing / EACCES / network), - * - executor returns null/undefined/non-string, - * - stdout is not parseable JSON, - * - the JSON has no `.dependencies['@opengsd/gsd-sdk']` field. - * - * Fail-closed conservative: we'd rather miss a detection than fire a - * false-positive warning that confuses users who have a fine install. - */ -function detectStaleStandaloneSdk(runNpmLs) { - if (typeof runNpmLs !== 'function') return { stale: false }; - let out; - try { - out = runNpmLs(); - } catch { - return { stale: false }; - } - if (typeof out !== 'string' || out.length === 0) return { stale: false }; - let parsed; - try { - parsed = JSON.parse(out); - } catch { - return { stale: false }; - } - const deps = parsed && typeof parsed === 'object' ? parsed.dependencies : null; - if (!deps || typeof deps !== 'object') return { stale: false }; - const entry = deps['@opengsd/gsd-sdk']; - if (!entry || typeof entry !== 'object') return { stale: false }; - const version = typeof entry.version === 'string' ? entry.version : '(unknown)'; - // #3406 CR: scope stale detection to the known-bad version (0.1.0). Any - // newer @opengsd/gsd-sdk version is an intentional install (or a future - // republish) and should not be flagged as a shim shadow. Without this - // narrowing, a maintainer's local-link or a legitimate future publish - // would trigger a misleading "stale shadow" warning on every install. - if (version !== '0.1.0') return { stale: false }; - return { stale: true, version }; -} - -/** - * #3406 helper: format the install-time warning emitted when - * `detectStaleStandaloneSdk` reports a stale shadow. Separated from the - * detection so the message contract is testable independently of npm. - */ -function formatStaleStandaloneSdkWarning(info) { - const version = info && info.version ? info.version : '(unknown)'; - return [ - '⚠ A stale globally-installed @opengsd/gsd-sdk@' + version + ' is shadowing the', - ' `gsd-sdk` shim that ' + pkg.name + ' provides. The standalone package', - ' only knows `run | auto | init` — every `gsd-sdk query ` call from', - ' skills and hooks will fail until you remove it.', - '', - ' Remediation:', - ' npm uninstall -g @opengsd/gsd-sdk', - ' npx -y ' + pkg.name + '@latest -- --global', - '', - ' Tracking: #3406 — https://github.com/open-gsd/gsd-core/issues/3406', - ].join('\n'); -} - -// Projection-contract surfaces (drift guards: tests/bug-3441, tests/bug-3442). -// These have no production caller after the #505 dead-SDK-verification removal, -// but they are the install.js side of the shell-command projection contract: -// the drift-guard tests assert install.js delegates to -// shell-command-projection.cjs rather than hand-rolling the projection. Kept -// exported so that contract stays verifiable. -function buildWindowsShimTriple(shimSrc) { - return buildWindowsShimTripleFromProjection(shimSrc); -} - -function formatSdkPathDiagnostic({ shimDir, platform, runDir }) { - return formatSdkPathDiagnosticFromProjection({ shimDir, platform, runDir }); -} - /** * Install GSD for all selected runtimes */ @@ -10931,10 +10806,6 @@ module.exports = { install, installAllRuntimes, uninstall, - detectStaleStandaloneSdk, - formatStaleStandaloneSdkWarning, - buildWindowsShimTriple, - formatSdkPathDiagnostic, convertClaudeCommandToCodexSkill, convertClaudeToOpencodeFrontmatter, convertClaudeToKiloFrontmatter, diff --git a/docs/AGENTS.md b/docs/AGENTS.md index 96d1cec3d..c625dc6ea 100644 --- a/docs/AGENTS.md +++ b/docs/AGENTS.md @@ -674,11 +674,11 @@ Twelve additional agents ship under `agents/gsd-*.md` and are used by specialty | **Tools** | Read, Write, Bash, Glob, Grep | | **Model (balanced)** | Sonnet | | **Color** | Cyan | -| **Produces** | `.planning/intel/*.json` (and companion Markdown) consumed by `gsd-sdk query intel` | +| **Produces** | `.planning/intel/*.json` (and companion Markdown) consumed by `gsd-tools query intel` | **Key behaviors:** - Writes current state only — no temporal language, every claim references an actual file path -- Uses Glob / Read / Grep for cross-platform correctness; Bash is reserved for `gsd-sdk query intel` CLI calls +- Uses Glob / Read / Grep for cross-platform correctness; Bash is reserved for `gsd-tools query intel` CLI calls --- diff --git a/docs/COMMANDS.md b/docs/COMMANDS.md index 1dd4bdf09..f7e40d5af 100644 --- a/docs/COMMANDS.md +++ b/docs/COMMANDS.md @@ -932,7 +932,7 @@ Interactive configuration of workflow toggles and model profile. Questions are g - **Model & Pipeline** — Model Profile, Auto-Advance, Branching - **Misc** — Context Warnings, Research Qs -All answers are merged via `gsd-sdk query config-set` into the resolved project config path (`.planning/config.json` for a standard install, or `.planning/workstreams//config.json` when a workstream is active), preserving unrelated keys. After confirmation, the user may save the full settings object to `~/.gsd/defaults.json` so future `/gsd-new-project` runs start from the same baseline. +All answers are merged via `gsd-tools query config-set` into the resolved project config path (`.planning/config.json` for a standard install, or `.planning/workstreams//config.json` when a workstream is active), preserving unrelated keys. After confirmation, the user may save the full settings object to `~/.gsd/defaults.json` so future `/gsd-new-project` runs start from the same baseline. ```bash /gsd-settings # Interactive config @@ -960,7 +960,7 @@ Configure GSD settings interactively — workflow toggles, advanced knobs, integ | Git Customization | `git.base_branch`, `git.phase_branch_template`, `git.milestone_branch_template` | | Runtime / Output | `response_language`, `context_window`, `search_gitignored`, `graphify.build_timeout` | -All answers merge via `gsd-sdk query config-set`, preserving unrelated keys. API keys are masked (`****`) in all output. +All answers merge via `gsd-tools query config-set`, preserving unrelated keys. API keys are masked (`****`) in all output. ```bash /gsd-config # Common-case interactive config diff --git a/docs/CONFIGURATION.md b/docs/CONFIGURATION.md index 55820adb1..699e497ab 100644 --- a/docs/CONFIGURATION.md +++ b/docs/CONFIGURATION.md @@ -344,7 +344,7 @@ Example: ### Project-Root Resolution in Multi-Repo Workspaces -When `sub_repos` is set and `gsd-tools.cjs` or `gsd-sdk query` is invoked from inside a listed child repo, both CLIs walk up to the parent workspace that owns `.planning/` before dispatching handlers. Resolution order (checked at each ancestor up to 10 levels, never above `$HOME`): +When `sub_repos` is set and `gsd-tools.cjs` or `gsd-tools query` is invoked from inside a listed child repo, both CLIs walk up to the parent workspace that owns `.planning/` before dispatching handlers. Resolution order (checked at each ancestor up to 10 levels, never above `$HOME`): 1. If the starting directory already has its own `.planning/`, it is the project root (no walk-up). 2. Parent has `.planning/config.json` listing the starting directory's top-level segment in `sub_repos` (or the legacy `planning.sub_repos` shape). @@ -424,7 +424,7 @@ Any GSD agent type can receive skills. Common types: ### How It Works -At spawn time, workflows call `gsd-sdk query agent-skills ` (or legacy `node gsd-tools.cjs agent-skills `) to load configured skills. If skills exist for the agent type, they are injected as an `` block in the Task() prompt: +At spawn time, workflows call `gsd-tools query agent-skills ` (or legacy `node gsd-tools.cjs agent-skills `) to load configured skills. If skills exist for the agent type, they are injected as an `` block in the Task() prompt: ```xml @@ -441,7 +441,7 @@ If no skills are configured, the block is omitted (zero overhead). Set skills via the CLI: ```bash -gsd-sdk query config-set agent_skills.gsd-executor '["skills/my-skill"]' +gsd-tools query config-set agent_skills.gsd-executor '["skills/my-skill"]' ``` --- @@ -512,10 +512,10 @@ architecture questions. ```bash # Enable a feature -gsd-sdk query config-set features.global_learnings true +gsd-tools query config-set features.global_learnings true # Disable a feature -gsd-sdk query config-set features.thinking_partner false +gsd-tools query config-set features.thinking_partner false ``` The `features.*` namespace is a dynamic key pattern — new feature flags can be added without modifying `VALID_CONFIG_KEYS`. Any key matching `features.` is accepted by the config system. diff --git a/docs/USER-GUIDE.md b/docs/USER-GUIDE.md index af33e4c25..03dd832f1 100644 --- a/docs/USER-GUIDE.md +++ b/docs/USER-GUIDE.md @@ -1095,11 +1095,11 @@ Each workspace gets: ## Troubleshooting -### Programmatic CLI (`gsd-sdk query` vs `gsd-tools.cjs`) +### Programmatic CLI (`gsd-tools query` vs `gsd-tools.cjs`) -For automation and copy-paste from docs, prefer **`gsd-sdk query`** with a registered subcommand (see [CLI-TOOLS.md — SDK and programmatic access](CLI-TOOLS.md#sdk-and-programmatic-access) and [QUERY-HANDLERS.md](../sdk/src/query/QUERY-HANDLERS.md)). The legacy `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs` CLI remains supported for dual-mode operation. +For automation and copy-paste from docs, prefer **`gsd-tools query`** with a registered subcommand (see [CLI-TOOLS.md — SDK and programmatic access](CLI-TOOLS.md#sdk-and-programmatic-access) and [QUERY-HANDLERS.md](../sdk/src/query/QUERY-HANDLERS.md)). The legacy `node $HOME/.claude/get-shit-done/bin/gsd-tools.cjs` CLI remains supported for dual-mode operation. -**CLI-only (not in the query registry):** **graphify**, **from-gsd2** / **gsd2-import** — call `gsd-tools.cjs` (see [QUERY-HANDLERS.md](../sdk/src/query/QUERY-HANDLERS.md)). **Two different `state` JSON shapes in the legacy CLI:** `state json` (frontmatter rebuild) vs `state load` (`config` + `state_raw` + flags). **`gsd-sdk query` today:** both `state.json` and `state.load` resolve to the frontmatter-rebuild handler — use `node …/gsd-tools.cjs state load` when you need the CJS `state load` shape. See [CLI-TOOLS.md](CLI-TOOLS.md#sdk-and-programmatic-access) and QUERY-HANDLERS. +**CLI-only (not in the query registry):** **graphify**, **from-gsd2** / **gsd2-import** — call `gsd-tools.cjs` (see [QUERY-HANDLERS.md](../sdk/src/query/QUERY-HANDLERS.md)). **Two distinct `state` JSON shapes, both available via `gsd-tools query`:** `state.json` (frontmatter rebuild) vs `state.load` (`config` + `state_raw` + flags) — they resolve to different handlers, so pick the one whose shape you need. The legacy `gsd-tools.cjs state json` / `state load` forms produce the same two shapes. See [CLI-TOOLS.md](CLI-TOOLS.md#sdk-and-programmatic-access) and QUERY-HANDLERS. ### STATE.md Out of Sync diff --git a/docs/ship-pr-body-sections.md b/docs/ship-pr-body-sections.md index 64be67838..16795b9a6 100644 --- a/docs/ship-pr-body-sections.md +++ b/docs/ship-pr-body-sections.md @@ -31,10 +31,10 @@ Selected sections are written with `"enabled": true`. Seeded but unselected sect ## Configure Sections Manually -Set `ship.pr_body_sections` with `gsd-sdk query config-set`: +Set `ship.pr_body_sections` with `gsd-tools query config-set`: ```bash -gsd-sdk query config-set ship.pr_body_sections '[{"heading":"Risks & Dependencies","enabled":true,"source":"PLAN.md ## Risks || PLAN.md ## Dependencies","fallback":"- No known high-risk rollout dependencies."}]' +gsd-tools query config-set ship.pr_body_sections '[{"heading":"Risks & Dependencies","enabled":true,"source":"PLAN.md ## Risks || PLAN.md ## Dependencies","fallback":"- No known high-risk rollout dependencies."}]' ``` You can also edit `.planning/config.json` directly: diff --git a/get-shit-done/bin/lib/code-review-flags.cjs b/get-shit-done/bin/lib/code-review-flags.cjs index a0bba0167..b8396e3e3 100644 --- a/get-shit-done/bin/lib/code-review-flags.cjs +++ b/get-shit-done/bin/lib/code-review-flags.cjs @@ -20,7 +20,7 @@ * Parse code-review flags from an argv array. * * The first positional argument (phase number) is ignored by this function — - * phase validation is handled by `gsd-sdk query init.phase-op`. + * phase validation is handled by `gsd-tools query init.phase-op`. * * @param {string[]} argv - Array of argument strings, e.g. ['2', '--fix', '--all'] * @returns {CodeReviewFlags} diff --git a/get-shit-done/bin/lib/shell-command-projection.cjs b/get-shit-done/bin/lib/shell-command-projection.cjs index 38ac0a87c..576263d58 100644 --- a/get-shit-done/bin/lib/shell-command-projection.cjs +++ b/get-shit-done/bin/lib/shell-command-projection.cjs @@ -2,7 +2,6 @@ const path = require('path'); const fs = require('fs'); -const { PACKAGE_NAME } = require('./package-identity.cjs'); // Use non-destructured access so test-time mock.method(childProcess, 'spawnSync') // can intercept calls from this seam — destructured imports capture references // at load time and become un-mockable. @@ -311,56 +310,6 @@ function projectPersistentPathExportActions({ targetDir, platform = process.plat return { shellActions: projected.shellActions }; } -function buildWindowsShimTriple(shimSrc) { - const shimAbs = path.resolve(shimSrc); - const shimQuoted = JSON.stringify(shimAbs); - const invocation = { - interpreter: 'node', - target: shimAbs, - }; - const renderCmd = () => - '@ECHO OFF\r\n@SETLOCAL\r\n@node ' + shimQuoted + ' %*\r\n'; - const renderPs1 = () => - '#!/usr/bin/env pwsh\n& node ' + shimQuoted + ' $args\nexit $LASTEXITCODE\n'; - const renderSh = () => - '#!/usr/bin/env sh\nexec node ' + shimQuoted + ' "$@"\n'; - return { - invocation, - eol: { cmd: '\r\n', ps1: '\n', sh: '\n' }, - fileNames: { cmd: 'gsd-sdk.cmd', ps1: 'gsd-sdk.ps1', sh: 'gsd-sdk' }, - render: { cmd: renderCmd, ps1: renderPs1, sh: renderSh }, - }; -} - -function formatSdkPathDiagnostic({ shimDir, platform, runDir }) { - const isWin32 = platform === 'win32'; - const isNpx = typeof runDir === 'string' && - (runDir.includes('/_npx/') || runDir.includes('\\_npx\\')); - const shimLocationLine = shimDir ? `Shim written to: ${shimDir}` : ''; - const actionLines = []; - let shellActions = []; - if (shimDir) { - const projected = projectPathActionProjection({ - mode: 'repair', - targetDir: shimDir, - platform, - }); - shellActions = projected.shellActions; - actionLines.push('Add that directory to your PATH and restart your shell.'); - actionLines.push(...projected.actionLines); - } else { - actionLines.push('Could not locate a writable PATH directory to install the shim.'); - actionLines.push('Install globally to materialize the bin symlink:'); - actionLines.push(`npm install -g ${PACKAGE_NAME}`); - } - const npxNoteLines = isNpx - ? [ - "Note: you're running via npx. For a persistent shim,", - `install globally instead: npm install -g ${PACKAGE_NAME}`, - ] - : []; - return { shimLocationLine, actionLines, shellActions, npxNoteLines, isNpx, isWin32 }; -} // ─── Subprocess dispatch ────────────────────────────────────────────────────── @@ -540,8 +489,6 @@ module.exports = { projectPathActionProjection, renderShellActionLines, projectPersistentPathExportActions, - buildWindowsShimTriple, - formatSdkPathDiagnostic, execGit, execNpm, execTool, diff --git a/get-shit-done/bin/lib/state-command-router.cjs b/get-shit-done/bin/lib/state-command-router.cjs index ef4b404f9..16e10c22a 100644 --- a/get-shit-done/bin/lib/state-command-router.cjs +++ b/get-shit-done/bin/lib/state-command-router.cjs @@ -31,7 +31,7 @@ function routeStateCommand({ state, args, cwd, raw, error }) { subcommands: ['load', 'complete-phase', ...STATE_SUBCOMMANDS.filter((s) => s !== 'load')], defaultSubcommand: 'load', unsupported: { - 'add-roadmap-evolution': 'state add-roadmap-evolution is SDK-only. Use: gsd-sdk query state.add-roadmap-evolution ...', + 'add-roadmap-evolution': 'state add-roadmap-evolution is SDK-only. Use: gsd-tools query state.add-roadmap-evolution ...', }, error, cwd, diff --git a/get-shit-done/references/autonomous-smart-discuss.md b/get-shit-done/references/autonomous-smart-discuss.md index 62156d278..1e5554df7 100644 --- a/get-shit-done/references/autonomous-smart-discuss.md +++ b/get-shit-done/references/autonomous-smart-discuss.md @@ -5,7 +5,7 @@ Smart discuss is the autonomous-optimized variant of `gsd-discuss-phase`. It pro **Inputs:** `PHASE_NUM` from execute_phase. Run init to get phase paths: ```bash -PHASE_STATE=$(gsd-sdk query init.phase-op ${PHASE_NUM}) +PHASE_STATE=$(gsd-tools query init.phase-op ${PHASE_NUM}) ``` Parse from JSON: `phase_dir`, `phase_slug`, `padded_phase`, `phase_name`. @@ -94,7 +94,7 @@ Read the 3-5 most relevant files to understand existing patterns. **Get phase details:** ```bash -DETAIL=$(gsd-sdk query roadmap.get-phase ${PHASE_NUM}) +DETAIL=$(gsd-tools query roadmap.get-phase ${PHASE_NUM}) ``` Extract `goal`, `requirements`, `success_criteria` from the JSON response. @@ -266,7 +266,7 @@ Write the file. **Commit:** ```bash -gsd-sdk query commit "docs(${PADDED_PHASE}): smart discuss context" --files "${phase_dir}/${padded_phase}-CONTEXT.md" +gsd-tools query commit "docs(${PADDED_PHASE}): smart discuss context" --files "${phase_dir}/${padded_phase}-CONTEXT.md" ``` Display confirmation: diff --git a/get-shit-done/references/decimal-phase-calculation.md b/get-shit-done/references/decimal-phase-calculation.md index 44f88f748..995475c1a 100644 --- a/get-shit-done/references/decimal-phase-calculation.md +++ b/get-shit-done/references/decimal-phase-calculation.md @@ -6,7 +6,7 @@ Calculate the next decimal phase number for urgent insertions. ```bash # Get next decimal phase after phase 6 -gsd-sdk query phase.next-decimal 6 +gsd-tools query phase.next-decimal 6 ``` Output: @@ -32,13 +32,13 @@ With existing decimals: ## Extract Values ```bash -DECIMAL_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --pick next) -BASE_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --pick base_phase) +DECIMAL_PHASE=$(gsd-tools query phase.next-decimal "${AFTER_PHASE}" --pick next) +BASE_PHASE=$(gsd-tools query phase.next-decimal "${AFTER_PHASE}" --pick base_phase) ``` Or with --raw flag: ```bash -DECIMAL_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --raw) +DECIMAL_PHASE=$(gsd-tools query phase.next-decimal "${AFTER_PHASE}" --raw) # Returns just: 06.1 ``` @@ -56,7 +56,7 @@ DECIMAL_PHASE=$(gsd-sdk query phase.next-decimal "${AFTER_PHASE}" --raw) Decimal phase directories use the full decimal number: ```bash -SLUG=$(gsd-sdk query generate-slug "$DESCRIPTION" --raw) +SLUG=$(gsd-tools query generate-slug "$DESCRIPTION" --raw) PHASE_DIR=".planning/phases/${DECIMAL_PHASE}-${SLUG}" mkdir -p "$PHASE_DIR" ``` diff --git a/get-shit-done/references/git-integration.md b/get-shit-done/references/git-integration.md index 628f24f12..846ffc06a 100644 --- a/get-shit-done/references/git-integration.md +++ b/get-shit-done/references/git-integration.md @@ -51,7 +51,7 @@ Phases: What to commit: ```bash -gsd-sdk query commit "docs: initialize [project-name] ([N] phases)" --files .planning/ +gsd-tools query commit "docs: initialize [project-name] ([N] phases)" --files .planning/ ``` @@ -136,7 +136,7 @@ SUMMARY: .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md What to commit: ```bash -gsd-sdk query commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md +gsd-tools query commit "docs({phase}-{plan}): complete [plan-name] plan" --files .planning/phases/XX-name/{phase}-{plan}-PLAN.md .planning/phases/XX-name/{phase}-{plan}-SUMMARY.md .planning/STATE.md .planning/ROADMAP.md ``` **Note:** Code files NOT included - already committed per-task. @@ -156,7 +156,7 @@ Current: [task name] What to commit: ```bash -gsd-sdk query commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/ +gsd-tools query commit "wip: [phase-name] paused at task [X]/[Y]" --files .planning/ ``` @@ -287,7 +287,7 @@ Set `commit_docs: false` so planning docs stay local and are not committed to an Instead of the standard `commit` command, use `commit-to-subrepo` when `sub_repos` is configured: ```bash -gsd-sdk query commit-to-subrepo "feat(02-01): add user API" \ +gsd-tools query commit-to-subrepo "feat(02-01): add user API" \ --files backend/src/api/users.ts backend/src/types/user.ts frontend/src/components/UserForm.tsx ``` diff --git a/get-shit-done/references/git-planning-commit.md b/get-shit-done/references/git-planning-commit.md index 7082bfede..79e6cfa6b 100644 --- a/get-shit-done/references/git-planning-commit.md +++ b/get-shit-done/references/git-planning-commit.md @@ -1,6 +1,6 @@ # Git Planning Commit -Commit planning artifacts via `gsd-sdk query commit`, which checks `commit_docs` config and gitignore status (same behavior as legacy `gsd-tools.cjs commit`). +Commit planning artifacts via `gsd-tools query commit`, which checks `commit_docs` config and gitignore status (same behavior as legacy `gsd-tools.cjs commit`). ## Commit via CLI @@ -9,7 +9,7 @@ Pass the message first, then file paths via `--files`. Both `commit` and `commit Always use this for `.planning/` files — it handles `commit_docs` and gitignore checks automatically: ```bash -gsd-sdk query commit "docs({scope}): {description}" --files .planning/STATE.md .planning/ROADMAP.md +gsd-tools query commit "docs({scope}): {description}" --files .planning/STATE.md .planning/ROADMAP.md ``` The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.planning/` is gitignored. No manual conditional checks needed. @@ -19,7 +19,7 @@ The CLI will return `skipped` (with reason) if `commit_docs` is `false` or `.pla To fold `.planning/` file changes into the previous commit: ```bash -gsd-sdk query commit "" --files .planning/codebase/*.md --amend +gsd-tools query commit "" --files .planning/codebase/*.md --amend ``` ## Commit Message Patterns diff --git a/get-shit-done/references/phase-argument-parsing.md b/get-shit-done/references/phase-argument-parsing.md index d0081ed5f..4d6c60e71 100644 --- a/get-shit-done/references/phase-argument-parsing.md +++ b/get-shit-done/references/phase-argument-parsing.md @@ -14,7 +14,7 @@ From `$ARGUMENTS`: The `find-phase` command handles normalization and validation in one step: ```bash -PHASE_INFO=$(gsd-sdk query find-phase "${PHASE}") +PHASE_INFO=$(gsd-tools query find-phase "${PHASE}") ``` Returns JSON with: @@ -45,7 +45,7 @@ fi Use `roadmap get-phase` to validate phase exists: ```bash -PHASE_CHECK=$(gsd-sdk query roadmap.get-phase "${PHASE}" --pick found) +PHASE_CHECK=$(gsd-tools query roadmap.get-phase "${PHASE}" --pick found) if [ "$PHASE_CHECK" = "false" ]; then echo "ERROR: Phase ${PHASE} not found in roadmap" exit 1 @@ -57,5 +57,5 @@ fi Use `find-phase` for directory lookup: ```bash -PHASE_DIR=$(gsd-sdk query find-phase "${PHASE}" --raw) +PHASE_DIR=$(gsd-tools query find-phase "${PHASE}" --raw) ``` diff --git a/get-shit-done/references/planner-revision.md b/get-shit-done/references/planner-revision.md index c37ea3663..d1066f45b 100644 --- a/get-shit-done/references/planner-revision.md +++ b/get-shit-done/references/planner-revision.md @@ -55,7 +55,7 @@ Group by plan, dimension, severity. ### Step 6: Commit ```bash -gsd-sdk query commit "fix($PHASE): revise plans based on checker feedback" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md +gsd-tools query commit "fix($PHASE): revise plans based on checker feedback" --files .planning/phases/$PHASE-*/$PHASE-*-PLAN.md ``` ### Step 7: Return Revision Summary diff --git a/get-shit-done/references/planning-config.md b/get-shit-done/references/planning-config.md index 1c972b893..3de0bb514 100644 --- a/get-shit-done/references/planning-config.md +++ b/get-shit-done/references/planning-config.md @@ -55,19 +55,19 @@ Configuration options for `.planning/` directory behavior. - User must add `.planning/` to `.gitignore` - Useful for: OSS contributions, client projects, keeping planning private -**Using `gsd-sdk query` (preferred):** +**Using `gsd-tools query` (preferred):** ```bash # Commit with automatic commit_docs + gitignore checks: -gsd-sdk query commit "docs: update state" --files .planning/STATE.md +gsd-tools query commit "docs: update state" --files .planning/STATE.md # Load config via state load (returns JSON): -INIT=$(gsd-sdk query state.load) +INIT=$(gsd-tools query state.load) if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi # commit_docs is available in the JSON output # Or use init commands which include commit_docs: -INIT=$(gsd-sdk query init.execute-phase "1") +INIT=$(gsd-tools query init.execute-phase "1") if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi # commit_docs is included in all init command outputs ``` @@ -77,7 +77,7 @@ if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi **Commit via CLI (handles checks automatically):** ```bash -gsd-sdk query commit "docs: update state" --files .planning/STATE.md +gsd-tools query commit "docs: update state" --files .planning/STATE.md ``` The CLI checks `commit_docs` config and gitignore status internally — no manual conditionals needed. @@ -165,14 +165,14 @@ To use uncommitted mode: Use `init execute-phase` which returns all config as JSON: ```bash -INIT=$(gsd-sdk query init.execute-phase "1") +INIT=$(gsd-tools query init.execute-phase "1") if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi # JSON output includes: branching_strategy, phase_branch_template, milestone_branch_template ``` Or use `state load` for the config values: ```bash -INIT=$(gsd-sdk query state.load) +INIT=$(gsd-tools query state.load) if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi # Parse branching_strategy, phase_branch_template, milestone_branch_template from JSON ``` diff --git a/get-shit-done/references/universal-anti-patterns.md b/get-shit-done/references/universal-anti-patterns.md index dfa4fb161..7fde6e9cc 100644 --- a/get-shit-done/references/universal-anti-patterns.md +++ b/get-shit-done/references/universal-anti-patterns.md @@ -34,7 +34,7 @@ Reference: `references/questioning.md` for the full anti-pattern list. ## State Management Anti-Patterns -15. **No direct Write/Edit to STATE.md or ROADMAP.md for mutations.** Always use `gsd-sdk query` for registered state/roadmap handlers (e.g. `state.update`, `state.advance-plan`, `roadmap.update-plan-progress`), or legacy `node …/gsd-tools.cjs` for CLI-only commands. Direct Write tool usage bypasses safe update logic and is unsafe in multi-session environments. Exception: first-time creation of STATE.md from template is allowed. +15. **No direct Write/Edit to STATE.md or ROADMAP.md for mutations.** Always use `gsd-tools query` for registered state/roadmap handlers (e.g. `state.update`, `state.advance-plan`, `roadmap.update-plan-progress`), or legacy `node …/gsd-tools.cjs` for CLI-only commands. Direct Write tool usage bypasses safe update logic and is unsafe in multi-session environments. Exception: first-time creation of STATE.md from template is allowed. ## Behavioral Rules @@ -53,7 +53,7 @@ Reference: `references/questioning.md` for the full anti-pattern list. ## GSD-Specific Rules 24. **Do not** check for `mode === 'auto'` or `mode === 'autonomous'` -- GSD uses `yolo` config flag. Check `yolo: true` for autonomous mode, absence or `false` for interactive mode. -25. **Prefer `gsd-sdk query`** for orchestration when a handler exists; when shelling out to the legacy CLI, use **`gsd-tools.cjs`** (not `gsd-tools.js` or any other filename) — GSD ships the programmatic API as CommonJS for Node.js CLI compatibility. +25. **Prefer `gsd-tools query`** for orchestration when a handler exists; when shelling out to the legacy CLI, use **`gsd-tools.cjs`** (not `gsd-tools.js` or any other filename) — GSD ships the programmatic API as CommonJS for Node.js CLI compatibility. 26. **Plan files MUST follow `{padded_phase}-{NN}-PLAN.md` pattern** (e.g., `01-01-PLAN.md`). Never use `PLAN-01.md`, `plan-01.md`, or any other variation -- gsd-tools detection depends on this exact pattern. 27. **Do not start executing the next plan before writing the SUMMARY.md for the current plan** -- downstream plans may reference it via `@` includes. diff --git a/get-shit-done/references/verify-mvp-mode.md b/get-shit-done/references/verify-mvp-mode.md index 32999bdf2..f336b9271 100644 --- a/get-shit-done/references/verify-mvp-mode.md +++ b/get-shit-done/references/verify-mvp-mode.md @@ -14,7 +14,7 @@ The user-flow form mirrors what a real user does: open, fill, click, see. No HTT ## When this framing applies The framing fires when: -- The phase under verification has `**Mode:** mvp` in ROADMAP.md (parsed via `gsd-sdk query roadmap.get-phase --pick mode`). +- The phase under verification has `**Mode:** mvp` in ROADMAP.md (parsed via `gsd-tools query roadmap.get-phase --pick mode`). - AND the phase has a user-story-formatted goal (set by `/gsd mvp-phase` per Phase 2): "As a [user role], I want to [capability], so that [outcome]." If the phase has `mode: mvp` but the goal is NOT in user-story format, the verifier surfaces this as a discrepancy and asks the user to run `/gsd mvp-phase` to reformat the goal — same pattern as the planner agent under MVP_MODE (per `references/planner-mvp-mode.md`). diff --git a/get-shit-done/references/workstream-flag.md b/get-shit-done/references/workstream-flag.md index 99524423d..fab5ba2e6 100644 --- a/get-shit-done/references/workstream-flag.md +++ b/get-shit-done/references/workstream-flag.md @@ -93,19 +93,19 @@ This ensures workstream scope chains automatically through the workflow: ## CLI Usage ```bash -# All gsd-sdk query commands accept --ws -gsd-sdk query state.json --ws feature-a -gsd-sdk query find-phase 3 --ws feature-b +# All gsd-tools query commands accept --ws +gsd-tools query state.json --ws feature-a +gsd-tools query find-phase 3 --ws feature-b # Session-local switching without --ws on every command -GSD_SESSION_KEY=my-terminal-a gsd-sdk query workstream.set feature-a -GSD_SESSION_KEY=my-terminal-a gsd-sdk query state.json -GSD_SESSION_KEY=my-terminal-b gsd-sdk query workstream.set feature-b -GSD_SESSION_KEY=my-terminal-b gsd-sdk query state.json +GSD_SESSION_KEY=my-terminal-a gsd-tools query workstream.set feature-a +GSD_SESSION_KEY=my-terminal-a gsd-tools query state.json +GSD_SESSION_KEY=my-terminal-b gsd-tools query workstream.set feature-b +GSD_SESSION_KEY=my-terminal-b gsd-tools query state.json # Workstream CRUD -gsd-sdk query workstream.create -gsd-sdk query workstream.list -gsd-sdk query workstream.status -gsd-sdk query workstream.complete +gsd-tools query workstream.create +gsd-tools query workstream.list +gsd-tools query workstream.status +gsd-tools query workstream.complete ``` diff --git a/hooks/gsd-graphify-update.sh b/hooks/gsd-graphify-update.sh index ac5de6cb6..a62b51e6d 100755 --- a/hooks/gsd-graphify-update.sh +++ b/hooks/gsd-graphify-update.sh @@ -11,7 +11,7 @@ # Gates (in fast-fail order — each shaves work off the common non-dispatch path): # 1. Stdin payload present and tool_name == "Bash" # 2. tool_input.command matches a HEAD-advancing git op (shell-direct or -# the exact `gsd-sdk query commit` command shape; the SDK command invokes +# the exact `gsd-tools query commit` command shape; the SDK command invokes # git internally, so the literal "git commit" substring never appears — # see #3653) # 3. $CI is unset/empty @@ -49,10 +49,10 @@ COMMAND=$(printf '%s\n' "$TOOL_INFO" | sed -n '2p') [ "$TOOL_NAME" = "Bash" ] || exit 0 -# Gate 2 — HEAD-advancing git op (shell-direct or exact `gsd-sdk query commit`) +# Gate 2 — HEAD-advancing git op (shell-direct or exact `gsd-tools query commit`) case "$COMMAND" in *"git commit"*|*"git merge"*|*"git pull"*|*"git rebase --continue"*|*"git cherry-pick"*) ;; - *"gsd-sdk query commit"|*"gsd-sdk query commit "*) ;; + *"gsd-tools query commit"|*"gsd-tools query commit "*) ;; *) exit 0 ;; esac diff --git a/tests/bug-3441-path-action-projection.test.cjs b/tests/bug-3441-path-action-projection.test.cjs index c61115fe1..dcf010470 100644 --- a/tests/bug-3441-path-action-projection.test.cjs +++ b/tests/bug-3441-path-action-projection.test.cjs @@ -32,23 +32,8 @@ describe('bug #3441: PATH guidance is projected from typed shell action IR', () assert.equal(typeof projection.projectPathActionProjection, 'function'); }); - test('formatSdkPathDiagnostic exposes structured shellActions alongside rendered actionLines', () => { - const ir = install.formatSdkPathDiagnostic({ - shimDir: 'C:\\Users\\me\\AppData\\Roaming\\npm', - platform: 'win32', - runDir: 'C:\\some\\path', - }); - - assert.ok(Array.isArray(ir.shellActions), 'shellActions must be an array'); - assert.ok(ir.shellActions.length >= 3, `expected 3+ shell actions, got ${ir.shellActions.length}`); - assert.equal(ir.shellActions[0].label, 'PowerShell'); - assert.equal(typeof ir.shellActions[0].command, 'string'); - assert.equal( - ir.actionLines.some((line) => line.startsWith('PowerShell:')), - true, - `rendered action lines should include shell labels: ${JSON.stringify(ir.actionLines)}`, - ); - }); + // (formatSdkPathDiagnostic removed with the gsd-sdk shim, #191 — the PATH + // action projection it wrapped is still covered by the tests below.) test('persistent PATH export guidance is projected via the same seam', () => { const posix = projection.projectPathActionProjection({ diff --git a/tests/bug-3442-shim-projection-drift-guard.test.cjs b/tests/bug-3442-shim-projection-drift-guard.test.cjs index 731f1fa4c..78a8f09bd 100644 --- a/tests/bug-3442-shim-projection-drift-guard.test.cjs +++ b/tests/bug-3442-shim-projection-drift-guard.test.cjs @@ -10,8 +10,6 @@ const path = require('node:path'); const { spawnSync } = require('node:child_process'); const ROOT = path.resolve(__dirname, '..'); -const INSTALL = require(path.join(ROOT, 'bin', 'install.js')); -const PROJECTION = require(path.join(ROOT, 'get-shit-done', 'bin', 'lib', 'shell-command-projection.cjs')); const DRIFT_LINT = path.join(ROOT, 'scripts', 'lint-shell-command-projection-drift.cjs'); function runLint(targetFile) { @@ -21,19 +19,8 @@ function runLint(targetFile) { }); } -describe('bug #3442: shim/wrapper projection seam', () => { - test('buildWindowsShimTriple matches shared projection output', () => { - const shimSrc = path.join(ROOT, 'bin', 'gsd-sdk.js'); - const fromInstall = INSTALL.buildWindowsShimTriple(shimSrc); - const fromProjection = PROJECTION.buildWindowsShimTriple(shimSrc); - assert.deepEqual(fromInstall.invocation, fromProjection.invocation); - assert.deepEqual(fromInstall.eol, fromProjection.eol); - assert.deepEqual(fromInstall.fileNames, fromProjection.fileNames); - assert.equal(fromInstall.render.cmd(), fromProjection.render.cmd()); - assert.equal(fromInstall.render.ps1(), fromProjection.render.ps1()); - assert.equal(fromInstall.render.sh(), fromProjection.render.sh()); - }); -}); +// (The buildWindowsShimTriple parity test was removed with the gsd-sdk shim, +// #191. The serialized-command drift guard below is retained and unaffected.) describe('bug #3442: shim/wrapper serialized-command drift guard', () => { test('drift guard passes for current install.js', () => { diff --git a/tests/bug-505-remove-dead-sdk-verification.test.cjs b/tests/bug-505-remove-dead-sdk-verification.test.cjs index 2bc760c45..b3a0df922 100644 --- a/tests/bug-505-remove-dead-sdk-verification.test.cjs +++ b/tests/bug-505-remove-dead-sdk-verification.test.cjs @@ -54,33 +54,10 @@ describe('bug #505: dead SDK verification subsystem removed from bin/install.js' } // ---------------------------------------------------------------- - // Live symbols — MUST still be exported as functions + // The stale-standalone-SDK helpers (detectStaleStandaloneSdk, + // formatStaleStandaloneSdkWarning) and the gsd-sdk shim contract surface + // (buildWindowsShimTriple, formatSdkPathDiagnostic) that #505 kept were + // removed when the gsd-sdk shim itself was retired (#191). Their absence is + // covered by the dead-symbol assertions above. // ---------------------------------------------------------------- - test('live function detectStaleStandaloneSdk is still exported', () => { - assert.equal( - typeof inst.detectStaleStandaloneSdk, - 'function', - 'detectStaleStandaloneSdk handles real stale-SDK condition (#3406) and must not be removed', - ); - }); - - test('live function formatStaleStandaloneSdkWarning is still exported', () => { - assert.equal( - typeof inst.formatStaleStandaloneSdkWarning, - 'function', - 'formatStaleStandaloneSdkWarning handles real stale-SDK condition (#3406) and must not be removed', - ); - }); - - // buildWindowsShimTriple / formatSdkPathDiagnostic have no production caller - // after this removal, but they are the install.js side of a projection-contract - // drift guard (tests/bug-3441, tests/bug-3442) that assert install.js delegates - // to shell-command-projection.cjs. They are deliberately kept exported. - test('contract surface buildWindowsShimTriple is still exported', () => { - assert.equal(typeof inst.buildWindowsShimTriple, 'function'); - }); - - test('contract surface formatSdkPathDiagnostic is still exported', () => { - assert.equal(typeof inst.formatSdkPathDiagnostic, 'function'); - }); }); diff --git a/tests/graphify-auto-update.test.cjs b/tests/graphify-auto-update.test.cjs index 833e96b0c..f24da1b7b 100644 --- a/tests/graphify-auto-update.test.cjs +++ b/tests/graphify-auto-update.test.cjs @@ -571,11 +571,11 @@ describe('auto-update', () => { 'git pull --ff-only', 'git rebase --continue', 'git cherry-pick abc123', - // #3653 — `gsd-sdk query commit` invokes git via spawnSync('git', [...]), + // #3653 — `gsd-tools query commit` invokes git via spawnSync('git', [...]), // so the substring "git commit" never appears in tool_input.command. // The hook must match the user-facing SDK invocation directly. - 'gsd-sdk query commit "docs: probe" --files .planning/STATE.md', - 'npx gsd-sdk query commit "docs: probe" --files .planning/STATE.md', + 'gsd-tools query commit "docs: probe" --files .planning/STATE.md', + 'npx gsd-tools query commit "docs: probe" --files .planning/STATE.md', ]) { test(`dispatches on: ${cmd}`, (t) => { const tmpDir = createTempGitRepo({ @@ -610,7 +610,7 @@ describe('auto-update', () => { { tool_name: 'Bash', tool_input: { - command: 'gsd-sdk query commit-to-subrepo "msg" --files packages/foo', + command: 'gsd-tools query commit-to-subrepo "msg" --files packages/foo', }, }, { pathPrepend: mockBin }, @@ -623,13 +623,13 @@ describe('auto-update', () => { }); // #3653 — only the SDK `commit` verb invokes git internally. Other - // `gsd-sdk query` verbs (phase.complete, roadmap.update-plan-progress, + // `gsd-tools query` verbs (phase.complete, roadmap.update-plan-progress, // state.begin-phase) mutate .md files but do NOT advance HEAD; matching // them would cause a spurious rebuild per state mutation. for (const cmd of [ - 'gsd-sdk query phase.complete 109', - 'gsd-sdk query roadmap.update-plan-progress 109 W001', - 'gsd-sdk query state.begin-phase 110', + 'gsd-tools query phase.complete 109', + 'gsd-tools query roadmap.update-plan-progress 109 W001', + 'gsd-tools query state.begin-phase 110', ]) { test(`does NOT dispatch on non-HEAD-advancing SDK verb: ${cmd}`, (t) => { const tmpDir = createTempGitRepo({