9e2ef2c94dea3f1267deba570c9a423fb38c2f85
13 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
463cffd894 |
chore(#604): rename get-shit-done/ runtime directory to gsd-core/ (#615)
* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
91f5bd7cb1 |
feat(#607): rebuild get-shit-done-cc → gsd-core migration (per-package cache + installer auto-cleanup + --dry-run) (#611)
* feat(#607): rebuild get-shit-done-cc → gsd-core migration Leftover get-shit-done-cc installs poisoned the shared update cache, causing a permanent false "update available". Rebuild the migration so a stale old install is both harmless and actively removed. - Per-package update cache filename (gsd-update-check-<slug>.json) in the shared ~/.cache/gsd dir, single-sourced via package-identity; writers stamp package_name and readers reject foreign/absent lineage. Multi- runtime visibility preserved (same shared dir + filename across runtimes). - New get-shit-done/bin/lib/legacy-cleanup.cjs seam: detects code-file references to the old package + the legacy fixed-name cache across home runtime dirs; installer auto-cleans on every install; --dry-run previews and mutates nothing. User hooks and dev-preferences are never touched. - update.md cache-clear globs gsd-update-check*.json across ALL supported runtimes (adds cursor/windsurf/augment/trae/qwen/hermes/codebuddy/cline). - Fix worker MODULE_NOT_FOUND post-install (ship managed-hooks-registry.cjs + degrade gracefully) so the per-package cache is always written. - Diataxis how-to: docs/cleanup-get-shit-done-cc.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#607): add changeset for PR #611 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#607): set USERPROFILE alongside HOME in dry-run install test for Windows os.homedir() reads USERPROFILE on win32, so HOME-only isolation let the spawned installer scan the real runner home on windows-latest. Set both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
6f2520786d |
feat(#498): single Package Identity seam for /gsd:update + fix runtime undefined-name bug (#499)
* feat(#498): generated package-identity seam derived from package.json Introduce a single source for GSD's published-package coordinates: scripts/generate-package-identity.cjs (pure deriveIdentity + formatManualInstall + render) emits the generated get-shit-done/bin/lib/package-identity.cjs with values baked from package.json at build time. Baking is required because the installed tree carries only a synthetic {"type":"commonjs"} package.json, so a runtime require('package.json').name resolves to undefined (#378). Reconciles Wired into npm run build; a parity test fails CI if the committed file drifts from package.json. Refs #498 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#498): repoint update worker + check-latest-version at the seam - check-latest-version.cjs sources PACKAGE_NAME from the package-identity seam instead of a re-typed literal (single source; #2992's constant guarantee is preserved since the seam bakes from package.json). - gsd-check-update-worker.js no longer does require('../package.json').name (resolved to undefined in the installed tree → background update check silently broken, #378). It now delegates the latest-version lookup to checkLatestVersion(), collapsing the duplicated npm-view call onto the single deterministic adapter and inheriting its typed {ok,version,reason} surface. - Move the PR #3102 Windows shell-gate contract test onto execNpm (where the spawn now lives) and assert the worker no longer spawns npm directly. - Rewrite the #378 contract: worker must NOT use require(package.json).name and must delegate; check-latest-version PACKAGE_NAME is single-sourced from the seam. Fixes #378-class runtime breakage. Refs #498 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#498): changeset for package-identity seam + update-check fix Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#498): drift-guard lint — value-check GSD coordinate literals against the seam scripts/lint-package-identity-drift.cjs scans the runtime/code surface (bin/, hooks/, scripts/, get-shit-done/) and asserts every GSD package name and GitHub repo slug literal equals the Package Identity seam's current value. Passes today; fails the moment a repoint isn't propagated (rename package.json, regenerate the seam, and stale literals are reported until updated). This is the second adapter that makes the seam real and a repoint mechanically safe. Enforced via tests/issue-498-identity-drift-lint.test.cjs (scanRepo === []) under npm test; also exposed as `npm run check:identity-drift`. Refs #498 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#498): update-context projection — port update.md resolution to a tested seam Add get-shit-done/bin/lib/update-context.cjs: a pure, injected-fs port of update.md's ~280-line get_installed_version bash. resolveUpdateContext() reproduces the full precedence cascade (preferred fast-path -> local probe -> global probe via env overrides then $HOME -> LOCAL-if-distinct -> scope cascade -> UNKNOWN) and returns the 4-field contract { installedVersion, scope, runtime, gsdDir }. The fs is injected so every branch is finally testable without a live multi-runtime install. Expose it as `gsd-tools update-context [--config-dir <d>] [--runtime <r>] --json`. Purely additive — update.md is unchanged in this commit; the workflow swap follows separately. Refs #498 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#498): swap update.md resolution to the update-context projection Replace ~280 lines of inline runtime/scope/config-dir bash in update.md's get_installed_version step with a call to `gsd-tools update-context --json` (60 lines: derive PREFERRED_* from execution_context, resolve gsd-tools.cjs, parse the 4-field JSON). Behavior is unchanged — the projection reproduces the same cascade — but the logic is now tested in update-context.cjs instead of untestable bash-in-markdown. Relocate the #3608 antigravity-first-class contract onto the projection (RUNTIME_DIRS order, inferPreferredRuntime, envRuntimeDirs) plus a behavioral test; keep the execution_context path-classification assertion on update.md. Re-point install.test's custom-config-dir assertion (kilo.jsonc/KILO_CONFIG) to update-context.cjs where that detection now lives. Full root suite: 2022 pass / 0 fail. Refs #498 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(#498): record Update Context Module in CONTEXT.md Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#498): CI — avoid bare gsd-tools in update.md; register new CLI modules - update.md update-context invocation: resolve the PATH gsd-tools shim into a variable and call "$GSD_TOOLS" (never a bare `gsd-tools` command) — satisfies the #2851 workflow-bare-gsd-tools guard. - Register package-identity.cjs and update-context.cjs in docs/INVENTORY.md (CLI Modules 76 -> 78 + rows) and regenerate docs/INVENTORY-MANIFEST.json, fixing inventory-counts and inventory-manifest-sync. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(#498): make update-context + parity tests OS-agnostic (Windows CI) Two Windows-only test failures, both test-portability (production code is fine — the real-fs CLI integration test passed on Windows): - update-context resolver tests + bug-3608 behavioral test used POSIX path-string keys in their fake fs, but the resolver builds lookups via path.join/resolve (backslash + drive letter on Windows) → keys never matched → everything resolved to UNKNOWN/claude. Normalize fake-fs keys and gsdDir comparisons through path.resolve so they match on both platforms. - package-identity parity test compared render() (LF) to the committed file, which Windows git checks out as CRLF (no .gitattributes eol rule). Normalize line endings before comparing, matching the repo convention (autonomous-decomposition, bug-3707). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#498): update.md backup must use GSD_DIR (adversarial-review finding) The get_installed_version rewrite emits GSD_DIR but dropped the probe-loop variables LOCAL_DIR/GLOBAL_DIR. The backup_custom_files step still read those, so RUNTIME_DIR went empty for every LOCAL/GLOBAL install and detect-custom-files was skipped — and since the update then runs a clean install that wipes managed dirs (commands/gsd, get-shit-done), user-added files could be deleted without the intended backup. Set RUNTIME_DIR="$GSD_DIR" directly (the resolved config dir; empty for UNKNOWN scope, which still skips the backup). Add a structural regression (tests/issue-498-update-backup-runtime-dir.test.cjs). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * test(#503): re-point Antigravity .agent detection at the #498 projection #499 moves the runtime/scope detection cascade out of update.md inline bash into get-shit-done/bin/lib/update-context.cjs. The #503 regression test asserted on the inline RUNTIME_DIRS array, which no longer exists, so it would fail against the projected update.md even though the .agent guarantee is preserved. Rewrite it to verify the surviving surfaces: - behavioral: resolveUpdateContext resolves a LOCAL ./.agent install to the antigravity runtime (the original root cause, now covered by adding ['antigravity', '.agent'] to the projection RUNTIME_DIRS table) - update.md prose classifier still maps /.agent/ -> antigravity - the post-update cache-clear for-dir loop still includes .agent Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#498): finish de-hardcoding consumers + close adversarial-review parity gaps Restore the consumer de-hardcoding that is the point of the seam, and close the parity gaps an adversarial review (codex) found in the update-context projection. De-hardcode the repo slug + install command in the changeset tooling — #516 only single-sourced the package NAME, leaving 'open-gsd/get-shit-done-redux' hardcoded in scripts/changeset/cli.cjs and github-release-notes.cjs. Route both through the seam's repoSlug/packageName so a rename is a regenerate, not a hand edit. The drift-lint real scan now reports zero divergent coordinate literals. Projection parity vs the old inline bash, as ONE consistent rule (trustedVersionAt) applied on every path: - expand a leading ~/ in preferredConfigDir before the fast path (the bash ran expand_home first; a custom --config-dir ~/foo otherwise fell to UNKNOWN) - trust a version only when BOTH VERSION and the update.md marker exist — fast path AND LOCAL/GLOBAL cascade; a partial dir falls to 0.0.0 keeping scope - apply the same same-path dedup to the 0.0.0 fallback so a partial install probed from cwd===home is not misdetected as LOCAL Adds regression tests for tilde expansion, VERSION-only (cascade + fast path), and the cwd===home partial-install dedup. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
b8c33647d8 |
refactor(tests): retire output-grep & source-grep via typed surfaces (finish #2974) (#462)
* refactor(#455): implement typed surfaces to retire grep tests Production surfaces added: - hooks/managed-hooks-registry.cjs: new CJS module exporting MANAGED_HOOKS as a typed array; gsd-check-update-worker.js now requires it instead of declaring an inline array - bin/install.js: elevate inline gsdHooks to module-level GSD_UNINSTALL_HOOKS, export it alongside runtimeMap/allRuntimes (already exported) - scripts/build-hooks.js: export HOOKS_TO_COPY; guard build() behind require.main===module so tests can require the file without triggering a build - get-shit-done/bin/lib/init.cjs: add --json mode to agent-skills command, emitting typed IR { agent_type, block, skills_count } for test assertions - get-shit-done/bin/gsd-tools.cjs: wire --json flag for agent-skills dispatch Category-B source-grep migrations: - tests/managed-hooks.test.cjs: require MANAGED_HOOKS from registry, drop fs.readFileSync+regex - tests/orphaned-hooks.test.cjs: require MANAGED_HOOKS+HOOKS_TO_COPY as typed exports - tests/hooks-opt-in.test.cjs: replace gsdHooks regex-parse with GSD_UNINSTALL_HOOKS import - tests/install-minimal-hooks.test.cjs: replace gsdHooks regex-parse with GSD_UNINSTALL_HOOKS - tests/copilot-install.test.cjs: replace src.includes() checks with typed assertions on runtimeMap, allRuntimes, parseRuntimeInput, buildRuntimePromptText - tests/agent-skills.test.cjs: migrate to --json typed IR assertions pending-migration-to-typed-ir token cleared (87 of 87 files): - 78 files already had source-text-is-the-product; removed duplicate token - 5 files already used typed assertions; reclassified or annotated - 4 files required individual reclassification to source-text-is-the-product or architectural-invariant Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(#455): update workflow-guard test to typed GSD_UNINSTALL_HOOKS import; isolate HOME in runtime-launcher (D) test Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(#455): guard install.js main() behind require.main===module so the typed export is require-safe Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(#455): document --json typed surfaces for agent-skills, progress, validate context Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(#455): add changeset fragment for new --json surfaces Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(#455): complete grep migration for files flagged by lint-tests The branch commit 4e630d99 stripped `allow-test-rule: pending-migration-to-typed-ir` from ~80 test files without replacing their assertions or adding the correct exemption annotation. The files were NOT source-grep tests — they read .md workflow/agent/command/reference files (source-text-is-the-product) or hook source files for structural invariants (structural-regression-guard). No assertion logic was changed; only the correct allow-test-rule annotation was added to each file per CONTRIBUTING.md exception matrix. 73 files: `source-text-is-the-product` — workflow/agent/command/reference .md 7 files: `structural-regression-guard` — hook .js / bin/install.js structural checks Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: CI Rebase Check <ci@gsd-redux> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7ea6a06645 |
fix(#378): poll scoped package name in update check (#414)
The update worker queried the unscoped 'get-shit-done-redux' via
`npm view`, which returns E404 — so `latest` stayed null and
`update_available` could never become true. Now derives the name from
package.json (`require('../package.json').name`) so it always matches
the actual published scoped name (@opengsd/get-shit-done-redux).
Fixes #378.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
6913dbcdb1 | fix(10): centralize semver comparison policy across hooks and changeset | ||
|
|
dff176bfd2 |
chore: rebrand to GSD-redux/get-shit-done-redux
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) |
||
|
|
088fc204ee |
fix(3347): clear CI gates raised by initial commit
- 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> |
||
|
|
ad0747ccac |
fix(hooks): scope shell:true to Windows + add changeset
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 |
||
|
|
6664190888 |
fix(hooks): execFileSync 'npm' needs shell:true on Windows
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",...}
|
||
|
|
95d2bc20f8 |
feat(hooks): opt-in SessionStart update banner for non-statusline users (#2795) (#3035)
* 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> |
||
|
|
c35997fb0b |
feat(hooks): add gsd-read-injection-scanner PostToolUse hook (#2201) (#2328)
* 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> |
||
|
|
50f61bfd9a |
fix(hooks): complete stale-hooks false-positive fix — stamp .sh version headers + fix detector regex (#2224)
* 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> |