Commit Graph

8 Commits

Author SHA1 Message Date
Tom Boucher
77b16993f8 fix(3584): address coderabbit findings on PR #3606
CodeRabbit surfaced one outstanding inline finding plus an outside-diff
finding and a finer point on two already-remediated sites; all addressed:

1. (inline, Minor) runtime-slash.cjs:31 — a degenerate input like `/gsd:`,
   `gsd:`, or `gsd-` normalizes to empty and the previous fallback returned
   the original colon-form input, reintroducing the deprecated shape the
   module exists to suppress. Now returns `''` (empty string) so callers
   see "no command" instead of an unroutable string. Also catches
   whitespace-only inputs the same way. New unit tests pin the contract.

2. (inline, Major) drift.cjs library purity — the earlier remediation
   passed `projectDir` into `detectDrift` and re-resolved runtime inside the
   library. CodeRabbit (correctly) flagged this as breaking the module's
   pure-library contract. detectDrift now accepts `input.runtime` directly;
   verify.cmdVerifyCodebaseDrift resolves the runtime once and passes the
   literal name in. drift.cjs no longer reads env or config at all.

3. (duplicate inline, Minor) gsd2-import.cjs:475 — when
   `gsd2-import --path <dir>` targets a project that isn't the process
   cwd, the preview command was formatted for the wrong runtime.
   buildPreview now receives the resolved `projectDir` (the same one
   used to find the .gsd/ root) instead of the raw `cwd`.

4. (outside-diff, Minor) tests/copilot-install.test.cjs:1-5 — the
   `allow-test-rule: integration-test-input` rationale block specifically
   named verify.cjs as the fixture, but #3584 changed that test to use a
   synthetic input. Comment now describes the real shape of the file's
   readFileSync usage (commands/, agents/, install.js source inputs to
   the installer/converter functions under test) and notes the synthetic
   substitution for the bin/lib path.

Full suite: 9366/9366 pass (+1 new test). Lint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 19:52:17 -04:00
Tom Boucher
bdf06c04b0 fix(3584): address codex-review findings on PR #3606
Codex review surfaced five issues in the initial slash-formatter PR — three MED
and two LOW. All five are addressed:

1. (MED) formatter corrupted argument tails under codex runtime. Splitting on
   the first whitespace and lowercasing only the command token preserves
   path-like arguments (`Map-Codebase --paths C:\\Users\\Me\\Project`) and
   case-sensitive flag values. (`runtime-slash.cjs`)

2. (MED) profile-output `cmdGenerateDevPreferences` emitted a hardcoded
   `command_name: '/gsd-dev-preferences'`. Replaced with
   `formatGsdSlash('dev-preferences', resolveRuntime(cwd))` so the structured
   result honors codex/skills runtime distinction. (`profile-output.cjs`)

3. (MED) `drift.detectDrift` → `buildMessage` called `resolveRuntime(null)`,
   ignoring a project's `.planning/config.json` `runtime` setting when
   `GSD_RUNTIME` env var was absent. Threaded `projectDir` through
   `detectDrift({projectDir})` → `buildMessage(..., projectDir)` →
   `resolveRuntime(projectDir)`. `verify.cmdVerifyCodebaseDrift` now passes
   `cwd` into the detect call. (`drift.cjs`, `verify.cjs`)

4. (LOW) `gsd2-import.buildPreview` had the same env-vs-config issue. Threaded
   `cwd` through `buildPreview(..., projectDir)` for parity. (`gsd2-import.cjs`)

5. (LOW) The codex emitter test only asserted absence of `/gsd:` — a regression
   to `/gsd-` (skills) form in codex output would have passed undetected.
   Added positive assertions that every gsd-referencing fix string under
   `GSD_RUNTIME=codex` contains `$gsd-` and contains neither `/gsd-` nor
   `/gsd:`. Also added formatter unit tests pinning the argument-tail
   preservation contract for both hyphen and codex runtimes.

Full suite: 9365/9365 pass (+2 new). Lint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 19:42:48 -04:00
Tom Boucher
034b47c8d0 fix(3584): runtime-aware slash formatter for user-facing emissions
Introduce `runtime-slash.cjs` as the single source of truth for emitting
GSD slash-command references in user-facing runtime output and persisted
artifacts. `formatGsdSlash(commandName, runtime)` produces `/gsd-<cmd>`
for skills-based runtimes (Claude/Cursor/OpenCode/Kilo/etc.) and
`$gsd-<cmd>` for Codex. The deprecated `/gsd:<cmd>` colon form is never
emitted — pasting a recommended-action command into Claude Code now
routes correctly instead of failing with `Unknown command`.

Wired into the high-impact emitters identified in #3584:

- `init.cjs` `cmdInitManager` recommended_actions[].command (the
  original failure path in the bug report) plus the no-ROADMAP /
  no-STATE error hints.
- `phase.cjs` `cmdPhaseAdd`, `cmdPhaseAddBatch`, `cmdPhaseInsert` —
  ROADMAP.md `Plans:` references now persist the routable form
  instead of the legacy colon form.
- `verify.cjs` `cmdValidateHealth` — every fix-hint addIssue() call
  (E001/E002/E003/E004/E005, W002/W003/W008/W009/W011/W016/W018) and
  the persisted STATE.md regenerate / MILESTONES.md backfill notes.
- `milestone.cjs` `cmdMilestoneComplete` — Operator Next Steps tail
  rewrite.
- `validate-command-router.cjs` — `validate context` recommendation
  strings for WARNING/CRITICAL utilization bands.
- `workstream.cjs` — missing .planning hint.
- `profile-output.cjs` — `generate-claude-md` workflow enforcement
  block, project/skills fallbacks, profile placeholder, and the
  dev-preferences refresh hints.
- `drift.cjs`, `gsd2-import.cjs`, `commands.cjs scaffold context` —
  remaining one-off persisted references.

Runtime detection: `resolveRuntime(projectDir)` reads
`process.env.GSD_RUNTIME` first, then a side-effect-free direct read of
`.planning/config.json` (NOT `loadConfig`, which would normalize legacy
keys and re-write the file just to read the runtime name).

Tests:
- `tests/bug-3584-runtime-slash-formatter.test.cjs` — 22 unit tests
  covering the pure formatter and resolver (hyphen vs codex, prefix
  normalization, defensive returns, env/config/default chain).
- `tests/bug-3584-runtime-slash-emitters.test.cjs` — 6 integration
  tests exercising `init manager`, `phase add` (via the structured
  `roadmap get-phase` payload to avoid raw-text matching on the
  on-disk artifact), `validate health`, `validate context`, and the
  codex variant.
- Existing tests updated to assert the new contract: validate-context
  recommendations, claude-md workflow block, milestone complete
  Operator Next Steps. Copilot-install engine-conversion test now
  asserts against a synthetic input since bin/lib/*.cjs no longer
  contains literal `/gsd:` references for the install-time converter
  to rewrite.

INVENTORY.md and INVENTORY-MANIFEST.json updated for the new module
(64 CLI modules shipped, +1).

Fixes #3584

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 19:32:02 -04:00
Tom Boucher
1e091d2bcb refactor(shell-projection): remove deprecated wrappers + finalize ADRs (Phase 4, #3468) (#3484)
* refactor(shell-projection): remove deprecated wrappers + finalize ADRs (Phase 4, #3468)

Final phase of the shell-command-projection expansion. Removes the legacy
core.cjs wrappers (`atomicWriteFileSync`, `safeReadFile`, `normalizeMd`)
now that every call site lives behind the seam, plus three Phase-3
stragglers (`graphify.cjs`, `template.cjs`, dead import in
`profile-pipeline.cjs`).

Documentation:
- ADR-0009: addendum noting Phase 1–4 scope expansion (subprocess +
  file I/O ownership), supersession of "does not execute" constraint,
  and resolution of open Q4.
- ADR-0010: status changed to Superseded by ADR-0009 with explanation.
- CONTEXT.md "Shell Command Projection Module" entry already current
  from Phase 1 — no edit needed.

Tests:
- `tests/atomic-write.test.cjs` deleted — wrapper it tested is gone;
  `atomic-write-coverage.test.cjs` (Phase 3) covers platformWriteSync.
- `tests/core.test.cjs::safeReadFile` + `::normalizeMd` describes
  deleted — wrappers are gone.
- `tests/concurrency-safety.test.cjs` normalizeMd suite (behavioral /
  perf / snapshot) repointed via 2-line shim at the seam's
  `normalizeContent` — full regression coverage preserved.

Test result: 9059/9041/18 — exact pre-Phase-4 baseline. All 18
failures are pre-existing path-with-spaces local-env issues.

Closes #3468

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

* refactor(shell-projection): migrate remaining raw fs.writeFileSync sites (Phase 4, #3468)

Sweeps the 7 raw fs.writeFileSync call sites that bypassed the seam through Phase 3,
folding them into platformWriteSync. Net -14 lines: deletes the local writeFileAtomicSync
helper in installer-migrations.cjs and collapses surface.cjs's manual tmp+rename into a
single seam call.

Sites migrated:
- drift.cjs (1) — frontmatter write
- learnings.cjs (1) — learning record JSON write
- install-profiles.cjs (1) — profile marker write (collapsed redundant mkdir)
- gsd2-import.cjs (1) — imported file write (collapsed redundant mkdir)
- surface.cjs (1) — surface state write (replaced manual tmp+rename block)
- installer-migrations.cjs (3) — journal init/finalize + rewrite-json action;
  deleted private writeFileAtomicSync helper and its three call sites

Two sites intentionally retained outside the seam:
- planning-workspace.cjs:241 — workspace lock (wx-flag atomic-create; previously excluded by Phase 3)
- installer-migrations.cjs:220 — install migration lock (fd write into wx-opened handle)
- writeInstallState (installer-migrations.cjs) — strict atomic contract for install state;
  the seam's fallback-to-direct-write on rename failure would silently violate the
  invariant that install state must never be left half-written. Inline tmp+rename with
  rethrow keeps the original guarantee.

Tests: 9059 / 9041 / 18 — exactly the pre-Phase-4 baseline; 18 failures are the
pre-existing path-with-spaces local-env issues, identical files as before.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(installer-migrations): use strict atomic write for rollback install-state restore

The rollback path was restoring INSTALL_STATE via platformWriteSync, which falls
back to a direct write on rename failure and would silently violate the
half-written invariant that the install-state contract guarantees elsewhere.

Extracts the strict tmp+rename logic from writeInstallState into a shared
atomicWriteInstallState(configDir, content) helper and routes both
writeInstallState and rollbackAppliedMigrationResult through it. Preserves the
existing null-handling (rmSync when previousInstallStateBytes === null) and
existing failure-collection (failures.push on caught errors).

Byte-faithful restore: previousInstallStateBytes is written as-is (no JSON
parse round-trip), preserving the exact prior file contents on restore.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-13 20:46:02 -04:00
Tom Boucher
a60e05c714 fix(claude): restore namespaced /gsd:<command> references (#3452)
* fix(claude): restore namespaced /gsd:<command> references

* test(claude): align slash-command expectations to /gsd: form

* test(claude): align generated command references to /gsd:

* test(claude): finish /gsd: namespace expectation updates
2026-05-12 21:53:24 -04:00
Tom Boucher
b1a670e662 fix(#2697): replace retired /gsd: prefix with /gsd- in all user-facing text (#2699)
All workflow, command, reference, template, and tool-output files that
surfaced /gsd:<cmd> as a user-typed slash command have been updated to
use /gsd-<cmd>, matching the Claude Code skill directory name.

Closes #2697

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-25 10:59:33 -04:00
Tom Boucher
73c1af5168 fix(#2543): replace legacy /gsd-<cmd> syntax with /gsd:<cmd> across all source files (#2595)
Commands are now installed as commands/gsd/<name>.md and invoked as
/gsd:<name> in Claude Code. The old hyphen form /gsd-<name> was still
hardcoded in hundreds of places across workflows, references, templates,
lib modules, and command files — causing "Unknown command" errors
whenever GSD suggested a command to the user.

Replace all /gsd-<cmd> occurrences where <cmd> is a known command name
(derived at runtime from commands/gsd/*.md) using a targeted Node.js
script. Agent names, tool names (gsd-sdk, gsd-tools), directory names,
and path fragments are not touched.

Adds regression test tests/bug-2543-gsd-slash-namespace.test.cjs that
enforces zero legacy occurrences going forward. Removes inverted
tests/stale-colon-refs.test.cjs (bug #1748) which enforced the now-obsolete
hyphen form; the new bug-2543 test supersedes it. Updates 5 assertion
tests that hardcoded the old hyphen form to accept the new colon form.

Closes #2543

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 12:04:25 -04:00
Tom Boucher
96eef85c40 feat(import): add /gsd-from-gsd2 reverse migration from GSD-2 to v1 (#2072)
Adds a new command and CLI subcommand that converts a GSD-2 `.gsd/`
project back to GSD v1 `.planning/` format — the reverse of the forward
migration GSD-2 ships.

Closes #2069

Maps GSD-2's Milestone → Slice → Task hierarchy to v1's flat
Milestone sections → Phase → Plan structure. Slices are numbered
sequentially across all milestones; tasks become numbered plans within
their phase. Completion state, research files, and summaries are
preserved.

New files:
- `get-shit-done/bin/lib/gsd2-import.cjs` — parser, transformer, writer
- `commands/gsd/from-gsd2.md` — slash command definition
- `tests/gsd2-import.test.cjs` — 41 tests, 99.21% statement coverage

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 21:30:13 -04:00