Mirror of code, issues, and PRs from the upstream gsd-build/get-shit-done,
which appears compromised or abandoned (maintainer unreachable since
2026-04-01; $GSD token linked to rug-pull).
- Adds rebrand notice block at top of English README
- Removes $GSD token badge and @gsd_foundation X badge (keeps Discord)
- Renames npm packages: get-shit-done-cc -> get-shit-done-redux,
@gsd-build/sdk -> @gsd-redux/sdk
- Updates all repo URLs across docs, workflows, package.json, bin/
- Updates ci@gsd-build -> ci@gsd-redux in workflow git identities
- Leaves CHANGELOG and .changeset/* alone (historical, time-stamped)
- docs/CONFIGURATION.md: document graphify.auto_update key (config-schema-docs-parity)
- hooks/gsd-check-update-worker.js: add gsd-graphify-update.sh to MANAGED_HOOKS (managed-hooks)
- agents/gsd-planner.md + gsd-phase-researcher.md: slim auto-update awareness block to
a one-line @-reference; extract full instructions to a new reference file
- get-shit-done/references/planner-graphify-auto-update.md: new reference with the
status-file schema, the four annotation cases (running/failed/ok-current/ok-stale),
and interaction with the existing stale-mtime annotation
- docs/INVENTORY.md: References (60 → 61 shipped) + row for new reference; regenerate
docs/INVENTORY-MANIFEST.json via gen-inventory-manifest.cjs
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Address adversarial review feedback on PR #3102:
1. shell:true is now conditional (process.platform === 'win32')
- POSIX path unchanged: no shell spawn, no overhead, original
signal/exit-code semantics and windowsHide effect preserved
- Windows path: still routes through cmd.exe to resolve npm.cmd
via PATHEXT (the actual fix for ENOENT)
2. Added .changeset/windows-npm-shell-fix.md (Fixed type)
Reviewed feedback resolved:
- Cross-platform regression risk → shell now Windows-only
- Missing changeset → added
Without shell:true, execFileSync('npm', ...) on Windows fails with
ENOENT because npm is distributed as npm.cmd, not as a literal 'npm'
binary. The silent try/catch swallows the error, latest stays null,
update_available becomes null, and the statusline never shows
"⬆ /gsd-update" — Windows users miss every release.
Adding shell:true makes execFileSync route through cmd.exe which
resolves npm.cmd via PATHEXT, identical behavior on POSIX.
Repro on Windows:
$env:GSD_CACHE_FILE = "$env:USERPROFILE\.cache\gsd\gsd-update-check.json"
node ~\.claude\hooks\gsd-check-update-worker.js
Get-Content "$env:USERPROFILE\.cache\gsd\gsd-update-check.json"
Before: {"update_available":null,"installed":"1.40.0","latest":"unknown",...}
After: {"update_available":false,"installed":"1.40.0","latest":"1.40.0",...}
* feat(hooks): opt-in SessionStart update banner for non-statusline users (#2795)
When a user declines (or keeps a non-GSD) statusline at install time, the
installer now offers an opt-in SessionStart banner that surfaces GSD update
availability. The banner reads the existing
~/.cache/gsd/gsd-update-check.json cache (written by
gsd-check-update-worker.js) and emits a single systemMessage line only when
update_available is true:
GSD update available: <installed> → <latest>. Run /gsd-update.
It is silent when up-to-date and rate-limits "check failed" diagnostics to
once per 24h via a sentinel file so a corrupt cache doesn't nag every
session. Removed cleanly by `npx get-shit-done-cc --uninstall` which strips
both the script and the SessionStart entry. The banner is never offered when
GSD's statusline is being installed (statusline already surfaces update
info, so re-prompting would be noise).
Implementation:
- hooks/gsd-update-banner.js — pure functions buildBannerOutput,
shouldSuppressFailureWarning, readCache; thin main() wires them.
- bin/install.js — handleUpdateBanner() prompt, parseUpdateBannerInput(),
buildUpdateBannerHookEntry(), buildUpdateBannerPromptText(); chained into
installAllRuntimes() so finalize() receives both flags. updateBannerCommand
computed alongside the other JS-hook commands; finishInstall() registers
the SessionStart entry only when shouldInstallBanner === true and the
hook file is present at the target.
- Hook ships in scripts/build-hooks.js HOOKS_TO_COPY, listed in
MANAGED_HOOKS for stale-detection in gsd-check-update-worker.js, in the
uninstall hook-removal lists in install.js, and in the
rewriteLegacyManagedNodeHookCommands allowlist.
Tests:
- tests/feat-2795-update-banner.test.cjs — 22 tests, structural-IR
assertions on parsed JSON envelopes (no raw-text matching). Covers
pure-function branches (cache present/absent, parseError, rate-limit
suppression, missing version fields), end-to-end hook invocation against
fixture cache states, and install.js wiring (prompt text, input parsing,
hook entry shape).
- tests/trae-install.test.cjs — updated install() return-shape assertion to
include updateBannerCommand: null for the no-settings runtime.
- 6881/6881 tests pass.
Docs (bundled in same commit per the bundle-docs-with-code skill):
- docs/USER-GUIDE.md — new "Surface GSD Update Notifications Without GSD's
Statusline" task section with opt-in/opt-out instructions.
- docs/FEATURES.md — REQ-HOOK-08 added; "Update Banner" subsection under
the Hook System feature with cache flow + removal path.
- docs/INVENTORY.md — hook count 11 → 12, new row for gsd-update-banner.js.
- docs/INVENTORY-MANIFEST.json — regenerated.
Closes#2795
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(install): gate banner prompt on actual installability (CR #3035)
CodeRabbit findings on PR #3035:
- bin/install.js (Major): continueAfterStatusline gated banner prompt on
the raw `shouldInstallStatusline` flag from handleStatusline. But
finishInstall later silently skips the statusline write on local
installs unless --force-statusline is set (#2248). Two consequences:
1. Interactive local Claude/Gemini installs got neither a statusline
nor a banner offer.
2. Codex/Cursor/Copilot/Windsurf/Trae/Cline-only installs (where
every result.updateBannerCommand is null) still got prompted even
though the choice was silently ignored.
Fix: derive willInstallStatusline = shouldInstallStatusline &&
(isGlobal || forceStatusline), and gate the banner prompt on a
canInstallBanner precondition computed from results[].updateBannerCommand.
Pass the raw shouldInstallStatusline through to finalize unchanged so
per-runtime statusline gating in finishInstall is unaffected.
- tests/feat-2795-update-banner.test.cjs (Minor): rate-limit suppression
test parsed r1.stdout without first asserting r1.status === 0. Other
e2e tests in this file (lines 210, 241) do this. A non-zero exit would
surface as a cryptic SyntaxError instead of a status assertion failure.
Fix applied verbatim.
6881/6881 tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* feat: add /gsd-spec-phase — Socratic spec refinement with ambiguity scoring (#2213)
Introduces `/gsd-spec-phase <phase>` as an optional pre-step before discuss-phase.
Clarifies WHAT a phase delivers (requirements, boundaries, acceptance criteria) with
quantitative ambiguity scoring before discuss-phase handles HOW to implement.
- `commands/gsd/spec-phase.md` — slash command routing to workflow
- `get-shit-done/workflows/spec-phase.md` — full Socratic interview loop (up to 6
rounds, 5 rotating perspectives: Researcher, Simplifier, Boundary Keeper, Failure
Analyst, Seed Closer) with weighted 4-dimension ambiguity gate (≤ 0.20 to write SPEC.md)
- `get-shit-done/templates/spec.md` — SPEC.md template with falsifiable requirements
(Current/Target/Acceptance per requirement), Boundaries, Acceptance Criteria,
Ambiguity Report, and Interview Log; includes two full worked examples
- `get-shit-done/workflows/discuss-phase.md` — new `check_spec` step detects
`{padded_phase}-SPEC.md` at startup; displays "Found SPEC.md — N requirements
locked. Focusing on implementation decisions."; `analyze_phase` respects `spec_loaded`
flag to skip "what/why" gray areas; `write_context` emits `<spec_lock>` section
with boundary summary and canonical ref to SPEC.md
- `docs/ARCHITECTURE.md` — update command/workflow counts (74→75, 71→72)
Closes#2213
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(hooks): add gsd-read-injection-scanner PostToolUse hook (#2201)
Adds a new PostToolUse hook that scans content returned by the Read tool
for prompt injection patterns, including four summarisation-specific patterns
(retention-directive, permanence-claim, etc.) that survive context compression.
Defense-in-depth for long GSD sessions where the context summariser cannot
distinguish user instructions from content read from external files.
- Advisory-only (warns without blocking), consistent with gsd-prompt-guard.js
- LOW severity for 1-2 patterns, HIGH for 3+
- Inlined pattern library (hook independence)
- Exclusion list: .planning/, REVIEW.md, CHECKPOINT, security docs, hook sources
- Wired in install.js as PostToolUse matcher: Read, timeout: 5s
- Added to MANAGED_HOOKS for staleness detection
- 19 tests covering all 13 acceptance criteria (SCAN-01–07, EXCL-01–06, EDGE-01–06)
Closes#2201
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ci): add read-injection-scanner files to prompt-injection-scan allowlist
Test payloads in tests/read-injection-scanner.test.cjs and inlined patterns
in hooks/gsd-read-injection-scanner.js legitimately contain injection strings.
Add both to the CI script allowlist to prevent false-positive failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(test): assert exitCode, stdout, and signal explicitly in EDGE-05
Addresses CodeRabbit feedback: the success path discarded the return
value so a malformed-JSON input that produced stdout would still pass.
Now captures and asserts all three observable properties.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(hooks): stamp gsd-hook-version in .sh hooks and fix stale detection regex (#2136, #2206)
Three-part fix for the persistent "⚠ stale hooks — run /gsd-update" false
positive that appeared on every session after a fresh install.
Root cause: the stale-hook detector (gsd-check-update.js) could only match
the JS comment syntax // in its version regex — never the bash # syntax used
in .sh hooks. And the bash hooks had no version header at all, so they always
landed in the "unknown / stale" branch regardless.
Neither partial fix (PR #2207 regex only, PR #2215 install stamping only) was
sufficient alone:
- Regex fix without install stamping: hooks install with literal
"{{GSD_VERSION}}", the {{-guard silently skips them, bash hook staleness
permanently undetectable after future updates.
- Install stamping without regex fix: hooks are stamped correctly with
"# gsd-hook-version: 1.36.0" but the detector's // regex can't read it;
still falls to the unknown/stale branch on every session.
Fix:
1. Add "# gsd-hook-version: {{GSD_VERSION}}" header to
gsd-phase-boundary.sh, gsd-session-state.sh, gsd-validate-commit.sh
2. Extend install.js (both bundled and Codex paths) to substitute
{{GSD_VERSION}} in .sh files at install time (same as .js hooks)
3. Extend gsd-check-update.js versionMatch regex to handle bash "#"
comment syntax: /(?:\/\/|#) gsd-hook-version:\s*(.+)/
Tests: 11 new assertions across 5 describe blocks covering all three fix
parts independently plus an E2E install+detect round-trip. 3885/3885 pass.
Approach credit: PR #2207 (j2h4u / Maxim Brashenko) for the regex fix;
PR #2215 (nitsan2dots) for the install.js substitution approach.
Closes#2136, #2206, #2209, #2210, #2212
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(hooks): extract check-update worker to dedicated file, eliminating template-literal regex escaping
Move stale-hook detection logic from inline `node -e '<template literal>'` subprocess
to a standalone gsd-check-update-worker.js. Benefits:
- Regex is plain JS with no double-escaping (root cause of the (?:\\/\\/|#) confusion)
- Worker is independently testable and can be read directly by tests
- Uses execFileSync (array args) to satisfy security hook that blocks execSync
- MANAGED_HOOKS now includes gsd-check-update-worker.js itself
Update tests to read worker file instead of main hook for regex/configDir assertions.
All 3886 tests pass.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>