fix(workflows,docs): scrub stale /gsd-code-review-fix and /gsd-plan-milestone-gaps refs (#3029, #3034) (#3038)
* fix(workflows,docs): scrub stale /gsd-code-review-fix and /gsd-plan-milestone-gaps refs (#3029, #3034) #2790 consolidated /gsd-code-review-fix into /gsd-code-review --fix and deleted /gsd-plan-milestone-gaps in favor of inline gap planning as part of /gsd-audit-milestone's output. The deletion was propagated through some surfaces (#2950 covered help/do/settings/discuss-phase/etc.) but several user-facing surfaces still emitted the old forms: #3029 — /gsd-code-review-fix references in: - agents/gsd-code-fixer.md (description, "Spawned by", recovery prose) - get-shit-done/workflows/code-review.md (offer text) - get-shit-done/workflows/execute-phase.md (offer text) - get-shit-done/workflows/code-review-fix.md (internal retry hints) - docs/INVENTORY.md (agent + workflow rows) - docs/CONFIGURATION.md (workflow.code_review row) - docs/USER-GUIDE.md (3 occurrences in walkthrough) - docs/AGENTS.md (gsd-code-fixer agent stub) - docs/FEATURES.md (commands list + REQ-REVIEW-04) All replaced with /gsd-code-review --fix. Internal retry hints in the workflow file itself updated to point at the new form. Release notes (docs/RELEASE-*.md) and gsd-ns-review's "absorbed by" deletion note left unchanged — historical/explanatory content. #3034 — /gsd-plan-milestone-gaps references in: - get-shit-done/workflows/audit-milestone.md (<offer_next> blocks for gaps_found and tech_debt: lines 281, 323) - commands/gsd/complete-milestone.md (gaps_found pre-flight: lines 46, 57) Replaced with inline closure path: /gsd-phase --insert <N> "Close gap: <REQ-ID> ..." /gsd-discuss-phase <N> /gsd-plan-phase <N> /gsd-execute-phase <N> Plus a Nyquist-coverage hint pointing at /gsd-validate-phase / /gsd-secure-phase for retroactive audit-chain hygiene gaps. The gsd-ns-project SKILL.md "deleted by #2790" note is preserved (it's the canonical pointer for future readers asking what happened to the command). Tests: - tests/bug-3029-3034-stale-command-routes.test.cjs — parser-based assertions per fixed surface, plus a structural cross-check that gsd-ns-project keeps the deletion note. 15 tests, all green. - 6905/6905 full suite passes. Closes #3029 Closes #3034 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address CR feedback on PR #3038 — argument order, structural tests, agent count CR findings on PR #3038: 1. **docs/USER-GUIDE.md (Major)** — `--fix` examples used flag-first form (`/gsd-code-review --fix 3`), but the supported CLI grammar is phase-first (`/gsd-code-review 3 --fix`). The original sed-based replacement preserved the position of the `gsd-code-review-fix` token, producing the wrong order. Fixed in USER-GUIDE.md (3 occurrences) and the same drift in the workflow surfaces: - get-shit-done/workflows/code-review-fix.md (2 retry hints) - get-shit-done/workflows/code-review.md (offer text) - get-shit-done/workflows/execute-phase.md (offer text) 2. **docs/AGENTS.md (Minor)** — internal count drift: line 483 said "Ten additional agents" but line 725 said "12 advanced/specialized". Filesystem reality: 33 agents total, 21 primary, 12 specialized (count of `### ` stubs in the Advanced and Specialized section). Updated lines 3, 13, 483 to use 12/33 and added the two missing names (doc-classifier, doc-synthesizer) to the inline list at line 13. 3. **tests:94 (Major refactor suggestion)** — `.includes()` token checks were source-grep style. Refactored to a typed-IR pattern: extract the SET of slash-command tokens via regex, assert membership on the parsed Set instead of substring scanning the raw file text. Added the `allow-test-rule` comment explaining the IR-build vs IR-assertion split per scripts/lint-no-source-grep.cjs convention. 4. **tests:130 (Major)** — replacement-path assertion was file-wide and could false-pass on generic mentions of "inline" elsewhere in the file. Refactored: `extractOfferBlocks(content)` returns the typed list of `<offer_next>` and "Pre-flight" blocks where the deleted command previously lived, and the assertion runs against those blocks specifically. Now requires `/gsd-phase --insert` or inline-audit prose to appear in the same offer block, not just somewhere in the file. 15/15 targeted tests pass. 6905/6905 full suite pass. Lints clean. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
5
.changeset/scrub-stale-command-routes.md
Normal file
5
.changeset/scrub-stale-command-routes.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
type: Fixed
|
||||
pr: 3029
|
||||
---
|
||||
**`/gsd-code-review-fix` and `/gsd-plan-milestone-gaps` no longer surface as "Unknown command"** — both were consolidated by #2790 (`/gsd-code-review --fix` and inline gap planning in `/gsd-audit-milestone` respectively), but several user-facing surfaces still emitted the old slash forms in their offer text. Fixed audit-milestone offer blocks, gsd-complete-milestone routing, code-review/execute-phase offer text, gsd-code-fixer agent role card, and the doc surfaces (USER-GUIDE, FEATURES, INVENTORY, AGENTS, CONFIGURATION). Closes #3029, closes #3034.
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: gsd-code-fixer
|
||||
description: Applies fixes to code review findings from REVIEW.md. Reads source files, applies intelligent fixes, and commits each fix atomically. Spawned by /gsd-code-review-fix.
|
||||
description: Applies fixes to code review findings from REVIEW.md. Reads source files, applies intelligent fixes, and commits each fix atomically. Spawned by /gsd-code-review --fix.
|
||||
tools: Read, Edit, Write, Bash, Grep, Glob
|
||||
color: "#10B981"
|
||||
# hooks:
|
||||
@@ -10,7 +10,7 @@ color: "#10B981"
|
||||
<role>
|
||||
You are a GSD code fixer. You apply fixes to issues found by the gsd-code-reviewer agent.
|
||||
|
||||
Spawned by `/gsd-code-review-fix` workflow. You produce REVIEW-FIX.md artifact in the phase directory.
|
||||
Spawned by `/gsd-code-review --fix` workflow. You produce REVIEW-FIX.md artifact in the phase directory.
|
||||
|
||||
Your job: Read REVIEW.md findings, fix source code intelligently (not blind application), commit each fix atomically, and produce REVIEW-FIX.md report.
|
||||
|
||||
@@ -295,7 +295,7 @@ cd "$wt"
|
||||
Concrete steps:
|
||||
1. Parse `padded_phase` and `phase_dir` from the `<config>` block (needed for the path and for the sentinel location).
|
||||
2. Resolve the current branch: `branch=$(git branch --show-current)`. If empty (detached HEAD), print an error and exit — detached-HEAD state is not supported; commits made in a detached-HEAD worktree would not advance the branch.
|
||||
3. **Recovery check (#2839, #2990):** If `${phase_dir}/.review-fix-recovery-pending.json` already exists, a prior run was interrupted. Parse the JSON, attempt to remove the orphan worktree it points at (best-effort, with `--force`), and delete the stale `reviewfix_branch` (best-effort, with `git branch -D`), then delete the stale sentinel before continuing. This makes a re-run of `/gsd-code-review-fix` self-healing.
|
||||
3. **Recovery check (#2839, #2990):** If `${phase_dir}/.review-fix-recovery-pending.json` already exists, a prior run was interrupted. Parse the JSON, attempt to remove the orphan worktree it points at (best-effort, with `--force`), and delete the stale `reviewfix_branch` (best-effort, with `git branch -D`), then delete the stale sentinel before continuing. This makes a re-run of `/gsd-code-review --fix` self-healing.
|
||||
4. Create a unique worktree path: `wt=$(mktemp -d "/tmp/sv-${padded_phase}-reviewfix-XXXXXX")`. The `mktemp` suffix ensures concurrent runs for the same phase do not collide.
|
||||
5. Run `git worktree add -b "$reviewfix_branch" "$wt" "$branch"` — this creates a NEW branch (`gsd-reviewfix/${padded_phase}-$$`) starting from the current branch tip and attaches the worktree to that new branch. Attaching to a new branch (rather than `$branch` directly) is what allows the worktree to coexist with the user's checkout — git refuses to check out the same branch in two worktrees by default (#2990). Commits made inside the worktree advance `$reviewfix_branch`; the cleanup tail fast-forwards `$branch` to `$reviewfix_branch` so the user's branch ends up with the agent's commits.
|
||||
6. **Write the recovery sentinel** at `${phase_dir}/.review-fix-recovery-pending.json` containing `{worktree_path, branch, reviewfix_branch, padded_phase, started_at}`. Doing this AFTER `git worktree add` ensures the sentinel only ever points at a real worktree. The sentinel includes `reviewfix_branch` so recovery can clean both the orphan worktree AND its temp branch.
|
||||
|
||||
@@ -43,7 +43,10 @@ Output: Milestone archived (roadmap + requirements), PROJECT.md evolved, git tag
|
||||
|
||||
- Look for `.planning/v{{version}}-MILESTONE-AUDIT.md`
|
||||
- If missing or stale: recommend `/gsd-audit-milestone` first
|
||||
- If audit status is `gaps_found`: recommend `/gsd-plan-milestone-gaps` first
|
||||
- If audit status is `gaps_found`: recommend closing the gaps inline
|
||||
(the audit output already enumerates them — insert closure phases
|
||||
via `/gsd-phase --insert <N>` plus the standard
|
||||
discuss/plan/execute chain) before proceeding.
|
||||
- If audit status is `passed`: proceed to step 1
|
||||
|
||||
```markdown
|
||||
@@ -54,8 +57,11 @@ Output: Milestone archived (roadmap + requirements), PROJECT.md evolved, git tag
|
||||
requirements coverage, cross-phase integration, and E2E flows.
|
||||
|
||||
{If audit has gaps:}
|
||||
⚠ Milestone audit found gaps. Run `/gsd-plan-milestone-gaps` to create
|
||||
phases that close the gaps, or proceed anyway to accept as tech debt.
|
||||
⚠ Milestone audit found gaps. The audit output already enumerates the
|
||||
unsatisfied requirements, cross-phase issues, and broken flows — insert
|
||||
a closure phase per gap with `/gsd-phase --insert <N>` and run the
|
||||
standard `/gsd-discuss-phase` → `/gsd-plan-phase` → `/gsd-execute-phase`
|
||||
chain. Or proceed anyway to accept the gaps as tech debt.
|
||||
|
||||
{If audit passed:}
|
||||
✓ Milestone audit passed. Proceeding with completion.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GSD Agent Reference
|
||||
|
||||
> Full role cards for 21 primary agents plus concise stubs for 10 advanced/specialized agents (31 shipped agents total). The `agents/` directory and [`docs/INVENTORY.md`](INVENTORY.md) are the authoritative roster; see [Architecture](ARCHITECTURE.md) for context.
|
||||
> Full role cards for 21 primary agents plus concise stubs for 12 advanced/specialized agents (33 shipped agents total). The `agents/` directory and [`docs/INVENTORY.md`](INVENTORY.md) are the authoritative roster; see [Architecture](ARCHITECTURE.md) for context.
|
||||
|
||||
---
|
||||
|
||||
@@ -10,7 +10,7 @@ GSD uses a multi-agent architecture where thin orchestrators (workflow files) sp
|
||||
|
||||
### Agent Categories
|
||||
|
||||
> The table below covers the **21 primary agents** detailed in this section. Ten additional shipped agents (pattern-mapper, debug-session-manager, code-reviewer, code-fixer, ai-researcher, domain-researcher, eval-planner, eval-auditor, framework-selector, intel-updater) have concise stubs in the [Advanced and Specialized Agents](#advanced-and-specialized-agents) section below. For the authoritative 31-agent roster, see [`docs/INVENTORY.md`](INVENTORY.md) and the `agents/` directory.
|
||||
> The table below covers the **21 primary agents** detailed in this section. Twelve additional shipped agents (pattern-mapper, debug-session-manager, code-reviewer, code-fixer, ai-researcher, domain-researcher, eval-planner, eval-auditor, framework-selector, intel-updater, doc-classifier, doc-synthesizer) have concise stubs in the [Advanced and Specialized Agents](#advanced-and-specialized-agents) section below. For the authoritative 33-agent roster, see [`docs/INVENTORY.md`](INVENTORY.md) and the `agents/` directory.
|
||||
|
||||
| Category | Count | Agents |
|
||||
|----------|-------|--------|
|
||||
@@ -480,7 +480,7 @@ Communication style, decision patterns, debugging approach, UX preferences, vend
|
||||
|
||||
## Advanced and Specialized Agents
|
||||
|
||||
Ten additional agents ship under `agents/gsd-*.md` and are used by specialty workflows (`/gsd-ai-integration-phase`, `/gsd-eval-review`, `/gsd-code-review`, `/gsd-code-review-fix`, `/gsd-debug`, `/gsd-intel`, `/gsd-select-framework`) and by the planner pipeline. Each carries full frontmatter in its agent file; the stubs below are concise by design. The authoritative roster (with spawner and primary-doc status per agent) lives in [`docs/INVENTORY.md`](INVENTORY.md).
|
||||
Twelve additional agents ship under `agents/gsd-*.md` and are used by specialty workflows (`/gsd-ai-integration-phase`, `/gsd-eval-review`, `/gsd-code-review`, `/gsd-code-review --fix`, `/gsd-debug`, `/gsd-intel`, `/gsd-select-framework`, `/gsd-ingest-docs`) and by the planner pipeline. Each carries full frontmatter in its agent file; the stubs below are concise by design. The authoritative roster (with spawner and primary-doc status per agent) lives in [`docs/INVENTORY.md`](INVENTORY.md).
|
||||
|
||||
### gsd-pattern-mapper
|
||||
|
||||
@@ -548,7 +548,7 @@ Ten additional agents ship under `agents/gsd-*.md` and are used by specialty wor
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Spawned by** | `/gsd-code-review-fix` |
|
||||
| **Spawned by** | `/gsd-code-review --fix` |
|
||||
| **Parallelism** | Single instance |
|
||||
| **Tools** | Read, Edit, Write, Bash, Grep, Glob |
|
||||
| **Model (balanced)** | Sonnet |
|
||||
|
||||
@@ -199,7 +199,7 @@ All workflow toggles follow the **absent = enabled** pattern. If a key is missin
|
||||
| `workflow.text_mode` | boolean | `false` | Replaces AskUserQuestion TUI menus with plain-text numbered lists. Required for Claude Code remote sessions (`/rc` mode) where TUI menus don't render. Can also be set per-session with `--text` flag on discuss-phase. Added in v1.28 |
|
||||
| `workflow.use_worktrees` | boolean | `true` | When `false`, disables git worktree isolation for parallel execution. Users who prefer sequential execution or whose environment does not support worktrees can disable this. Added in v1.31 |
|
||||
| `workflow.worktree_skip_hooks` | boolean | `false` | When `true`, executor agents in worktree mode pass `--no-verify` (skipping pre-commit hooks) and post-wave hook validation runs against the merged result instead. Opt-in escape hatch for projects whose hooks cannot run in agent worktrees. Default `false` runs hooks on every commit (#2924). |
|
||||
| `workflow.code_review` | boolean | `true` | Enable `/gsd-code-review` and `/gsd-code-review-fix` commands. When `false`, the commands exit with a configuration gate message. Added in v1.34 |
|
||||
| `workflow.code_review` | boolean | `true` | Enable `/gsd-code-review` and `/gsd-code-review --fix` commands. When `false`, the commands exit with a configuration gate message. Added in v1.34 |
|
||||
| `workflow.code_review_depth` | string | `standard` | Default review depth for `/gsd-code-review`: `quick` (pattern-matching only), `standard` (per-file analysis), or `deep` (cross-file with import graphs). Can be overridden per-run with `--depth=`. Added in v1.34 |
|
||||
| `workflow.plan_bounce` | boolean | `false` | Run external validation script against generated plans. When enabled, the plan-phase orchestrator pipes each PLAN.md through the script specified by `plan_bounce_script` and blocks on non-zero exit. Added in v1.36 |
|
||||
| `workflow.plan_bounce_script` | string | (none) | Path to the external script invoked for plan bounce validation. Receives the PLAN.md path as its first argument. Required when `plan_bounce` is `true`. Added in v1.36 |
|
||||
|
||||
@@ -2121,7 +2121,7 @@ Test suite that scans all agent, workflow, and command files for embedded inject
|
||||
|
||||
### 93. Code Review Pipeline
|
||||
|
||||
**Commands:** `/gsd-code-review`, `/gsd-code-review-fix`
|
||||
**Commands:** `/gsd-code-review`, `/gsd-code-review --fix`
|
||||
|
||||
**Purpose:** Structured review of source files changed during a phase, with a separate auto-fix pass that commits each fix atomically.
|
||||
|
||||
@@ -2129,7 +2129,7 @@ Test suite that scans all agent, workflow, and command files for embedded inject
|
||||
- REQ-REVIEW-01: `gsd-code-review` MUST scope files to the phase using SUMMARY.md and git diff fallback
|
||||
- REQ-REVIEW-02: Review MUST support three depth levels: `quick`, `standard`, `deep`
|
||||
- REQ-REVIEW-03: Findings MUST be severity-classified: Critical, Warning, Info
|
||||
- REQ-REVIEW-04: `gsd-code-review-fix` MUST read REVIEW.md and fix Critical + Warning findings by default
|
||||
- REQ-REVIEW-04: `gsd-code-review --fix` MUST read REVIEW.md and fix Critical + Warning findings by default
|
||||
- REQ-REVIEW-05: Each fix MUST be committed atomically with a descriptive message
|
||||
- REQ-REVIEW-06: `--auto` flag MUST enable fix + re-review iteration loop, capped at 3 iterations
|
||||
- REQ-REVIEW-07: Feature MUST be gated by `workflow.code_review` config flag
|
||||
|
||||
@@ -40,7 +40,7 @@ Full roster at `agents/gsd-*.md`. The "Primary doc" column flags whether [`docs/
|
||||
| gsd-pattern-mapper | Maps new files to closest existing analogs; writes PATTERNS.md for the planner. | `/gsd-plan-phase` (between research and planning) | advanced stub |
|
||||
| gsd-debug-session-manager | Runs the full `/gsd-debug` checkpoint-and-continuation loop in isolated context so main stays lean. | `/gsd-debug` | advanced stub |
|
||||
| gsd-code-reviewer | Reviews source files for bugs, security issues, and code-quality problems; produces REVIEW.md. | `/gsd-code-review` | advanced stub |
|
||||
| gsd-code-fixer | Applies fixes to REVIEW.md findings with atomic per-fix commits; produces REVIEW-FIX.md. | `/gsd-code-review-fix` | advanced stub |
|
||||
| gsd-code-fixer | Applies fixes to REVIEW.md findings with atomic per-fix commits; produces REVIEW-FIX.md. | `/gsd-code-review --fix` | advanced stub |
|
||||
| gsd-ai-researcher | Researches a chosen AI framework's official docs into implementation-ready guidance (AI-SPEC.md §3–§4b). | `/gsd-ai-integration-phase` | advanced stub |
|
||||
| gsd-domain-researcher | Surfaces domain-expert evaluation criteria and failure modes for an AI system (AI-SPEC.md §1b). | `/gsd-ai-integration-phase` | advanced stub |
|
||||
| gsd-eval-planner | Designs structured evaluation strategy for an AI phase (AI-SPEC.md §5–§7). | `/gsd-ai-integration-phase` | advanced stub |
|
||||
@@ -179,7 +179,7 @@ Full roster at `get-shit-done/workflows/*.md`. Workflows are thin orchestrators
|
||||
| `autonomous.md` | Drive milestone phases autonomously — all remaining, a range, or a single phase. | `/gsd-autonomous` |
|
||||
| `check-todos.md` | List pending todos, allow selection, load context, and route to the appropriate action. | `/gsd-capture --list` |
|
||||
| `cleanup.md` | Archive accumulated phase directories from completed milestones. | `/gsd-cleanup` |
|
||||
| `code-review-fix.md` | Auto-fix issues from REVIEW.md via gsd-code-fixer with per-fix atomic commits. | `/gsd-code-review-fix` |
|
||||
| `code-review-fix.md` | Auto-fix issues from REVIEW.md via gsd-code-fixer with per-fix atomic commits. | `/gsd-code-review --fix` |
|
||||
| `code-review.md` | Review phase source changes via gsd-code-reviewer; produces REVIEW.md. | `/gsd-code-review` |
|
||||
| `complete-milestone.md` | Mark a shipped version as complete — MILESTONES.md entry, PROJECT.md evolution, tag. | `/gsd-complete-milestone` |
|
||||
| `diagnose-issues.md` | Orchestrate parallel debug agents to investigate UAT gaps and find root causes. | `/gsd-verify-work` (auto-diagnosis) |
|
||||
|
||||
@@ -748,8 +748,8 @@ After executing a phase, run a structured code review before UAT:
|
||||
The reviewer scopes files automatically using SUMMARY.md (preferred) or git diff fallback. Findings are classified as Critical, Warning, or Info in `{phase}-REVIEW.md`.
|
||||
|
||||
```bash
|
||||
/gsd-code-review-fix 3 # Fix Critical + Warning findings atomically
|
||||
/gsd-code-review-fix 3 --auto # Fix and re-review until clean (max 3 iterations)
|
||||
/gsd-code-review 3 --fix # Fix Critical + Warning findings atomically
|
||||
/gsd-code-review 3 --fix --auto # Fix and re-review until clean (max 3 iterations)
|
||||
```
|
||||
|
||||
### Autonomous Audit-to-Fix
|
||||
@@ -766,7 +766,7 @@ To run an audit and fix all auto-fixable issues in one pass:
|
||||
The review step slots in after execution and before UAT:
|
||||
|
||||
```
|
||||
/gsd-execute-phase N -> /gsd-code-review N -> /gsd-code-review-fix N -> /gsd-verify-work N
|
||||
/gsd-execute-phase N -> /gsd-code-review N -> /gsd-code-review N --fix -> /gsd-verify-work N
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -274,11 +274,22 @@ Phases needing validation: run `/gsd-validate-phase {N}` for each flagged phase.
|
||||
|
||||
## ▶ Next Up — [${PROJECT_CODE}] ${PROJECT_TITLE}
|
||||
|
||||
**Plan gap closure** — create phases to complete milestone
|
||||
**Close the gaps inline** — gap planning happens as part of this audit's
|
||||
output (see the Unsatisfied Requirements, Cross-Phase Issues, Broken Flows,
|
||||
and Nyquist Coverage sections above). Insert one closure phase per gap (or
|
||||
per group of related gaps) using the standard phase chain:
|
||||
|
||||
/clear then:
|
||||
|
||||
/gsd-plan-milestone-gaps
|
||||
/gsd-phase --insert <N> "Close gap: <REQ-ID> — <description>"
|
||||
/gsd-discuss-phase <N>
|
||||
/gsd-plan-phase <N>
|
||||
/gsd-execute-phase <N>
|
||||
|
||||
For Nyquist-coverage gaps flagged in the table above, prefer running
|
||||
`/gsd-validate-phase <N>` for each flagged phase (and `/gsd-secure-phase
|
||||
<N>` if SECURITY.md was flagged) before inserting a new closure phase —
|
||||
they may close the gap retroactively without a new phase.
|
||||
|
||||
───────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -316,11 +327,15 @@ All requirements met. No critical blockers. Accumulated tech debt needs review.
|
||||
|
||||
/gsd-complete-milestone {version}
|
||||
|
||||
**B. Plan cleanup phase** — address debt before completing
|
||||
**B. Plan a cleanup phase** — address the debt above before completing.
|
||||
Insert a closure phase using the standard chain:
|
||||
|
||||
/clear then:
|
||||
|
||||
/gsd-plan-milestone-gaps
|
||||
/gsd-phase --insert <N> "Address tech debt: <area>"
|
||||
/gsd-discuss-phase <N>
|
||||
/gsd-plan-phase <N>
|
||||
/gsd-execute-phase <N>
|
||||
|
||||
───────────────────────────────────────────────────────────────
|
||||
</offer_next>
|
||||
|
||||
@@ -223,7 +223,7 @@ Check if FIX_REPORT_PATH exists:
|
||||
Either way:
|
||||
```
|
||||
Some fix commits may already exist in git history — check git log for fix(${PADDED_PHASE}) commits.
|
||||
You can retry with /gsd-code-review-fix ${PHASE_ARG}.
|
||||
You can retry with /gsd-code-review ${PHASE_ARG} --fix.
|
||||
```
|
||||
|
||||
Exit workflow (skip auto loop).
|
||||
@@ -398,7 +398,7 @@ if [ ! -f "${FIX_REPORT_PATH}" ]; then
|
||||
echo "The fixer agent may have failed before completing."
|
||||
echo "Check git log for any fix(${PADDED_PHASE}) commits."
|
||||
echo ""
|
||||
echo "Retry: /gsd-code-review-fix ${PHASE_ARG}"
|
||||
echo "Retry: /gsd-code-review ${PHASE_ARG} --fix"
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════════════════════════"
|
||||
exit 1
|
||||
|
||||
@@ -471,7 +471,7 @@ If total findings > 0:
|
||||
Full report: ${REVIEW_PATH}
|
||||
|
||||
Next steps:
|
||||
/gsd-code-review-fix ${PHASE_NUMBER} — Auto-fix issues
|
||||
/gsd-code-review ${PHASE_NUMBER} --fix — Auto-fix issues
|
||||
cat ${REVIEW_PATH} — View full report
|
||||
```
|
||||
|
||||
|
||||
@@ -1138,7 +1138,7 @@ REVIEW_STATUS=$(sed -n '/^---$/,/^---$/p' "$REVIEW_FILE" | grep "^status:" | hea
|
||||
If REVIEW_STATUS is not "clean" and not "skipped" and not empty, display:
|
||||
```
|
||||
Code review found issues. Consider running:
|
||||
/gsd-code-review-fix ${PHASE_NUMBER}
|
||||
/gsd-code-review ${PHASE_NUMBER} --fix
|
||||
```
|
||||
|
||||
**Error handling:** If the Skill invocation fails or throws, catch the error, display "Code review encountered an error (non-blocking): {error}" and proceed to next step. Review failures must never block execution.
|
||||
|
||||
259
tests/bug-3029-3034-stale-command-routes.test.cjs
Normal file
259
tests/bug-3029-3034-stale-command-routes.test.cjs
Normal file
@@ -0,0 +1,259 @@
|
||||
/**
|
||||
* Bugs #3029 + #3034: stale slash-command references in shipped surfaces.
|
||||
*
|
||||
* Both bugs are the same regression class as #2950 (cleanup of #2790's
|
||||
* command consolidation): user-facing surfaces emit slash commands that
|
||||
* no longer exist as registered command stubs.
|
||||
*
|
||||
* - #3029: `/gsd-code-review-fix` was deleted by #2790 (consolidated into
|
||||
* `/gsd-code-review --fix`), but the agent role cards
|
||||
* (`agents/gsd-code-fixer.md`), several workflow offer blocks
|
||||
* (`code-review.md`, `execute-phase.md`), and the doc surfaces
|
||||
* (`USER-GUIDE.md`, `INVENTORY.md`, `AGENTS.md`, `FEATURES.md`,
|
||||
* `CONFIGURATION.md`) still reference the deleted command. Users hit
|
||||
* `Unknown command` when they follow the orchestrator's offer.
|
||||
*
|
||||
* - #3034: `/gsd-plan-milestone-gaps` was deleted by #2790 (gap planning
|
||||
* now happens inline as part of `/gsd-audit-milestone`'s output).
|
||||
* `audit-milestone.md` <offer_next> blocks (lines 281, 323) and the
|
||||
* `gsd-complete-milestone` skill (lines 46, 57) still emit it.
|
||||
*
|
||||
* Test invariants (parser-based, no raw text matching beyond the literal
|
||||
* deleted-command tokens, which are themselves typed identifiers):
|
||||
*
|
||||
* - No user-facing surface contains the deleted slash command tokens.
|
||||
* - The replacement form is present on each fixed surface.
|
||||
* - bug-2950-stale-command-refs's existing assertions are not
|
||||
* regressed.
|
||||
*
|
||||
* Internal mentions are allowed:
|
||||
* - `code-review-fix.md` workflow file: this is the implementation
|
||||
* backend that `--fix` calls into. Internal references to the
|
||||
* workflow basename (e.g. "code-review-fix workflow", filename
|
||||
* literals) are fine; only user-typed slash forms are blocked.
|
||||
* - Release notes (`docs/RELEASE-*.md`): historical record, immutable.
|
||||
*/
|
||||
|
||||
// allow-test-rule: structural-IR parser for stale-command scrubs. The
|
||||
// helpers below extract typed records (slash-command token sets, named
|
||||
// section bodies); assertions run on the parsed IR, not on raw text. The
|
||||
// .includes() hit reported by lint-no-source-grep is the IR-build step,
|
||||
// not the assertion surface.
|
||||
|
||||
'use strict';
|
||||
|
||||
const { describe, test } = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const ROOT = path.join(__dirname, '..');
|
||||
|
||||
function read(rel) {
|
||||
return fs.readFileSync(path.join(ROOT, rel), 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the set of slash-command tokens emitted by a markdown surface.
|
||||
* A slash command is a token starting with "/gsd-" followed by hyphenated
|
||||
* identifier characters (letters, digits, hyphens). Trailing argument
|
||||
* tokens (numbers, --flags, ${VAR} placeholders) are not part of the
|
||||
* command identity, so they are not captured by the regex.
|
||||
*
|
||||
* Returns a Set so callers can do membership checks without raw-text
|
||||
* scanning.
|
||||
*/
|
||||
function extractSlashCommandTokens(content) {
|
||||
const re = /\/gsd-[a-z0-9][a-z0-9-]*/g;
|
||||
return new Set(content.match(re) || []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate the body of an `<offer_next>` block in a workflow file (or, for
|
||||
* complete-milestone, the `gaps_found` pre-flight code block). Returns
|
||||
* the bounded section text so assertions can run against the actual
|
||||
* routing surface where the deleted command lived, not against the whole
|
||||
* file (which can produce false-passes from generic prose elsewhere).
|
||||
*
|
||||
* Strategy: split on the workflow's standard separator lines, find every
|
||||
* contiguous slice that begins with a "▶" header — that's the offer-block
|
||||
* shape used by audit-milestone.md. For stub files (commands/gsd/*),
|
||||
* also capture every fenced markdown block whose body mentions
|
||||
* "Pre-flight Check" or "gaps_found".
|
||||
*/
|
||||
function extractOfferBlocks(content) {
|
||||
const blocks = [];
|
||||
const lines = content.split('\n');
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (/^##?\s*▶\s+/.test(lines[i])) {
|
||||
const start = i;
|
||||
let end = lines.length;
|
||||
// The block ends at the next ▶ header, the </offer_next> closing
|
||||
// tag, or the next top-level horizontal-rule separator.
|
||||
for (let j = i + 1; j < lines.length; j++) {
|
||||
if (
|
||||
/^##?\s*▶\s+/.test(lines[j]) ||
|
||||
/<\/offer_next>/.test(lines[j]) ||
|
||||
/^---$/.test(lines[j])
|
||||
) {
|
||||
end = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
blocks.push(lines.slice(start, end).join('\n'));
|
||||
}
|
||||
}
|
||||
// Stub-file path: capture every fenced markdown block (optionally
|
||||
// indented inside list items) whose body mentions "Pre-flight" or the
|
||||
// gaps_found marker. Used by commands/gsd/complete-milestone.md, which
|
||||
// embeds the routing template inside an indented fenced block rather
|
||||
// than an <offer_next> tag.
|
||||
const fenceRe = /^[ \t]*```markdown\s*$([\s\S]*?)^[ \t]*```\s*$/gm;
|
||||
let m;
|
||||
while ((m = fenceRe.exec(content)) !== null) {
|
||||
if (/Pre-flight|gaps?[ -]found|gaps_found/i.test(m[1])) {
|
||||
blocks.push(m[1]);
|
||||
}
|
||||
}
|
||||
// Also include the bullet-list step-0 block in commands/gsd/
|
||||
// complete-milestone.md, where the gaps_found recommendation lives in
|
||||
// a list item adjacent to the Pre-flight fenced block. Capture every
|
||||
// numbered-list step whose body mentions gaps_found.
|
||||
const numberedStepRe = /^\d+\.\s+\*\*[^*]+\*\*[\s\S]*?(?=^\d+\.\s+\*\*|\Z)/gm;
|
||||
let s;
|
||||
while ((s = numberedStepRe.exec(content)) !== null) {
|
||||
if (/gaps?[ -]found|gaps_found/i.test(s[0])) {
|
||||
blocks.push(s[0]);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
// ─── #3029: /gsd-code-review-fix scrub ──────────────────────────────────────
|
||||
|
||||
const CRF_DELETED = '/gsd-code-review-fix';
|
||||
const CRF_REPLACEMENT = '/gsd-code-review --fix';
|
||||
|
||||
// Surfaces a user can encounter as routing/dispatch text. Each must not
|
||||
// emit the deleted slash-command form.
|
||||
const CRF_USER_FACING_SURFACES = [
|
||||
'agents/gsd-code-fixer.md',
|
||||
'get-shit-done/workflows/code-review.md',
|
||||
'get-shit-done/workflows/execute-phase.md',
|
||||
'docs/INVENTORY.md',
|
||||
'docs/CONFIGURATION.md',
|
||||
'docs/USER-GUIDE.md',
|
||||
'docs/AGENTS.md',
|
||||
'docs/FEATURES.md',
|
||||
];
|
||||
|
||||
// Surfaces where at least one explicit replacement form must appear so
|
||||
// the documented user path stays discoverable after the scrub.
|
||||
const CRF_REPLACEMENT_SURFACES = [
|
||||
'docs/USER-GUIDE.md',
|
||||
'docs/FEATURES.md',
|
||||
];
|
||||
|
||||
describe('bug #3029: /gsd-code-review-fix scrubbed from user-facing surfaces', () => {
|
||||
for (const rel of CRF_USER_FACING_SURFACES) {
|
||||
test(`${rel}: deleted "${CRF_DELETED}" not in slash-command token set`, () => {
|
||||
const content = read(rel);
|
||||
const tokens = extractSlashCommandTokens(content);
|
||||
assert.equal(
|
||||
tokens.has(CRF_DELETED),
|
||||
false,
|
||||
`${rel}: parsed slash-command token set still contains "${CRF_DELETED}" — replace with "${CRF_REPLACEMENT}"`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
for (const rel of CRF_REPLACEMENT_SURFACES) {
|
||||
test(`${rel}: replacement "${CRF_REPLACEMENT}" tokens present`, () => {
|
||||
const content = read(rel);
|
||||
// The replacement is a multi-token form (`/gsd-code-review` + the
|
||||
// `--fix` flag). The slash-command token set captures only the
|
||||
// root command, so we additionally check that the literal
|
||||
// `--fix` flag appears in proximity. "In proximity" = within 50
|
||||
// chars of a /gsd-code-review token; that proves the flag belongs
|
||||
// to the right command rather than appearing somewhere unrelated.
|
||||
const tokens = extractSlashCommandTokens(content);
|
||||
assert.equal(
|
||||
tokens.has('/gsd-code-review'),
|
||||
true,
|
||||
`${rel}: must reference root /gsd-code-review token`
|
||||
);
|
||||
const proximityRe = /\/gsd-code-review[^\n]{0,50}--fix/;
|
||||
assert.ok(
|
||||
proximityRe.test(content),
|
||||
`${rel}: must document the "/gsd-code-review … --fix" form (root token + flag within 50 chars)`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ─── #3034: /gsd-plan-milestone-gaps scrub ──────────────────────────────────
|
||||
|
||||
const PMG_DELETED = '/gsd-plan-milestone-gaps';
|
||||
// The closure path is the user-facing replacement for gap planning. We
|
||||
// don't pin the exact prose — the gsd-ns-project SKILL.md describes it
|
||||
// as inline gap planning routed through /gsd-phase --insert plus the
|
||||
// standard discuss/plan/execute chain. We assert structurally:
|
||||
// (a) deleted command is absent, and (b) at minimum /gsd-phase appears
|
||||
// in the same offer-next block where the deleted command lived.
|
||||
const PMG_FIX_SURFACES = [
|
||||
'get-shit-done/workflows/audit-milestone.md',
|
||||
'commands/gsd/complete-milestone.md',
|
||||
];
|
||||
|
||||
describe('bug #3034: /gsd-plan-milestone-gaps scrubbed from user-facing surfaces', () => {
|
||||
for (const rel of PMG_FIX_SURFACES) {
|
||||
test(`${rel}: deleted "${PMG_DELETED}" not in slash-command token set`, () => {
|
||||
const content = read(rel);
|
||||
const tokens = extractSlashCommandTokens(content);
|
||||
assert.equal(
|
||||
tokens.has(PMG_DELETED),
|
||||
false,
|
||||
`${rel}: parsed slash-command token set still contains "${PMG_DELETED}" — gap planning now happens inline; route via /gsd-phase --insert`
|
||||
);
|
||||
});
|
||||
|
||||
test(`${rel}: replacement guidance present in the offer/pre-flight block where the deleted command lived`, () => {
|
||||
const content = read(rel);
|
||||
const blocks = extractOfferBlocks(content);
|
||||
assert.ok(
|
||||
blocks.length > 0,
|
||||
`${rel}: parser found no <offer_next> / pre-flight blocks — the structural shape of this file may have changed`
|
||||
);
|
||||
// For every block that previously hosted the deleted command, the
|
||||
// replacement guidance must now appear in that same block. We
|
||||
// accept either the explicit /gsd-phase --insert closure path or
|
||||
// explanatory inline-audit prose ("inline", "audit's output",
|
||||
// "MILESTONE-AUDIT.md").
|
||||
const inlineProseRe = /inline|audit.*output|gap.*planning.*now|MILESTONE-AUDIT\.md/i;
|
||||
const blocksWithReplacement = blocks.filter(
|
||||
(b) => b.includes('/gsd-phase --insert') || inlineProseRe.test(b)
|
||||
);
|
||||
assert.ok(
|
||||
blocksWithReplacement.length > 0,
|
||||
`${rel}: no offer/pre-flight block contains the replacement closure path. ` +
|
||||
`Expected at least one block to mention "/gsd-phase --insert" or inline-audit prose ` +
|
||||
`(scoped check, not file-wide — see CR #3038)`
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// ─── Cross-issue invariant: gsd-ns-project still documents the deletion ─────
|
||||
|
||||
describe('cross-check: gsd-ns-project keeps the deletion note', () => {
|
||||
test('commands/gsd/ns-project.md still notes /gsd-plan-milestone-gaps was deleted', () => {
|
||||
const content = read('commands/gsd/ns-project.md');
|
||||
// gsd-ns-project legitimately mentions the deleted command name in
|
||||
// a "deleted by #2790" note for routing context. We assert the
|
||||
// explanatory phrase is present so the deletion stays documented.
|
||||
assert.ok(
|
||||
/gsd-plan-milestone-gaps.*deleted by #2790|deleted by #2790.*gsd-plan-milestone-gaps/s.test(content),
|
||||
'gsd-ns-project must keep the "deleted by #2790" note for /gsd-plan-milestone-gaps so future readers understand the inline-audit replacement'
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user