Add support for workspaces with multiple independent git repositories.
When configured, GSD routes commits to the correct sub-repo and ensures
.planning/ stays at the project root.
Core features:
- detectSubRepos(): scans child directories for .git to discover repos
- findProjectRoot(): walks up from CWD to find the project root that
owns .planning/, preventing orphaned .planning/ in sub-repos
- loadConfig auto-syncs sub_repos when repos are added or removed
- Migrates legacy "multiRepo: true" to sub_repos array automatically
- All init commands include project_root in output
- cmdCommitToSubrepo: groups files by sub-repo prefix, commits independently
Zero impact on single-repo workflows — sub_repos defaults to empty array.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Refactoring:
- Extract stateReplaceFieldWithFallback() to state.cjs as single source of truth
for the try-primary-then-fallback pattern that was duplicated inline across
phase.cjs, milestone.cjs, and state.cjs
- Replace all inline bold-only regex patterns in cmdPhaseComplete with shared
stateReplaceField/stateExtractField helpers — now supports both **Bold:**
and plain Field: STATE.md formats (fixes the same bug as #924)
- Replace inline bold-only regex patterns in cmdMilestoneComplete with shared helpers
- Replace inline bold-only regex for Completed Phases/Total Phases/Progress
counters in cmdPhaseComplete with stateExtractField/stateReplaceField
- Replace inline bold-only Total Phases regex in cmdPhaseRemove with shared helpers
Security:
- Fix command injection surface in isGitIgnored (core.cjs): replace execSync with
string concatenation with execFileSync using array arguments — prevents shell
interpretation of special characters in file paths
Tests (7 new):
- 5 tests for stateReplaceFieldWithFallback: primary field, fallback, neither,
preference, and plain format
- 1 regression test: phase complete with plain-format STATE.md fields
- 1 regression test: milestone complete with plain-format STATE.md fields
854 tests pass (was 847). No behavioral regressions.
- Add resolveWorktreeRoot() that detects linked worktrees via
git rev-parse --git-common-dir and resolves to the main worktree
where .planning/ lives
- Add withPlanningLock() file-based locking mechanism to prevent
concurrent worktrees from corrupting shared planning files
- Wire worktree root resolution into gsd-tools.cjs main entry point
- Add regression tests for resolveWorktreeRoot (non-git, normal repo)
and withPlanningLock (normal execution, error cleanup, stale lock
recovery)
When check-todos moves a file from pending/ to done/, the commit only
staged the new destination. The deletion of the source was never staged
because `git add` on a non-existent path is a no-op. Now we detect
missing files and use `git rm --cached` to stage the deletion.
Closes#1228
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The regex-based table parser captured a fixed number of columns,
so 5-column tables (Phase | Milestone | Plans | Status | Completed)
had the Milestone column eaten and Status/Date written to wrong cells.
Replaced regex with cell-based `split('|')` parsing that detects
column count (4 or 5) and updates the correct cells by index.
Affects both `cmdRoadmapUpdatePlanProgress` and `cmdPhaseComplete`.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The summary template puts the one-liner as a `**bold**` line after the
`# Phase N` heading, but `cmdSummaryExtract` and `cmdMilestoneComplete`
only checked frontmatter `one-liner` field — which is often empty.
Adds `extractOneLinerFromBody()` to core.cjs as a fallback that parses
the first `**...**` line after the heading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`cmdStateAdvancePlan` expected separate `Current Plan` and
`Total Plans in Phase` fields, but the current STATE.md template
uses a single compound field: `Plan: X of Y in current phase`.
Now tries legacy separate fields first, then falls back to parsing
the compound format. Preserves the compound format when writing back
(replaces only the plan number). Also handles `Last activity`
(lowercase) field name from current template.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Generate {phase_num}-DISCUSSION-LOG.md alongside CONTEXT.md during
discuss-phase sessions
- Log captures all options presented per gray area (not just the
selected one), user's choice, notes, Claude's discretion items,
and deferred ideas
- File is explicitly marked as audit-only — not for agent consumption
- Add discussion-log.md template with format specification
- Track Q&A data accumulation instruction in discuss_areas step
- Commit discussion log alongside CONTEXT.md in same git commit
- Add regression tests for workflow reference and template existence
- Add workflow.text_mode config option (default: false) that replaces
AskUserQuestion TUI menus with plain-text numbered lists
- Document --text flag and config-set workflow.text_mode true as the
fix for /rc remote sessions where the Claude App cannot forward TUI
menu selections
- Update discuss-phase.md with text mode parsing and answer_validation
fallback documentation
- Add text_mode to loadConfig defaults and VALID_CONFIG_KEYS
- Add regression tests for config-set and loadConfig
The summary template writes task count as `**Tasks:** N` in the
Performance section, but `cmdMilestoneComplete` only counted
`## Task N` markdown headers — which don't exist in that format.
Now checks three patterns in order: `**Tasks:** N` field (primary),
`<task` XML tags, then `## Task N` headers (legacy fallback).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
`cmdRoadmapUpdatePlanProgress` only marked phase-level checkboxes
(e.g. `- [ ] Phase 50: Build`) but skipped plan-level entries
(e.g. `- [ ] 50-01-PLAN.md`). Now iterates phase summaries and
marks matching plan checkboxes as complete.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevent silent loss of UAT/verification items when projects advance.
Surfaces outstanding items across all prior phases so nothing is forgotten.
New command:
- /gsd:audit-uat — cross-phase audit with categorized report and test plan
New capabilities:
- Cross-phase health check in /gsd:progress (Step 1.6)
- status: partial for incomplete UAT sessions
- result: blocked with blocked_by tag for dependency-gated tests
- human_needed items persisted as trackable HUMAN-UAT.md files
- Phase completion and transition warnings for verification debt
Files: 4 new, 14 modified (9 feature + 5 docs)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three commands reimplemented from positively-received community PRs:
1. /gsd:review (#925) — Cross-AI peer review
Invoke external AI CLIs (Gemini, Claude, Codex) to independently
review phase plans. Produces REVIEWS.md with per-reviewer feedback
and consensus summary. Feed back into planning via --reviews flag.
Multiple users praised the adversarial review concept.
2. /gsd:plant-seed (#456) — Forward-looking idea capture
Capture ideas with trigger conditions that auto-surface during
/gsd:new-milestone. Seeds preserve WHY, WHEN to surface, and
breadcrumbs to related code. Better than deferred items because
triggers are checked, not forgotten.
3. /gsd:pr-branch (#470) — Clean PR branches
Create a branch for pull requests by filtering out .planning/
commits. Classifies commits as code-only, planning-only, or mixed,
then cherry-picks only code changes. Reviewers see clean diffs.
All three are standalone command+workflow additions with no core code
changes. Help workflow updated. Test skill counts updated.
797/797 tests pass.
Consolidates repeated path.join(cwd, '.planning', ...) patterns into
calls to the shared planningPaths() helper from core.cjs.
Modules updated:
- state.cjs: 16 → planningPaths() (2 remain for non-standard paths)
- commands.cjs: 8 → planningPaths() (4 remain for todos dir)
- milestone.cjs: 5 → planningPaths() (3 remain for archive/milestones)
- roadmap.cjs: 4 → planningPaths()
Benefits:
- Single source of truth for .planning/ directory structure
- Easier to change planning dir location in the future
- Consistent path construction across the codebase
- No behavioral changes — pure refactor
797/797 tests pass.
Adds workflow.research_questions config toggle (default: false) that
enables web research before asking questions during /gsd:new-project
and /gsd:discuss-phase.
When enabled:
- discuss-phase: searches best practices for each gray area before
presenting questions, showing 2-3 bullet points of findings
- new-project: researches the user's described domain before asking
follow-up questions, weaving findings into the conversation
Added to /gsd:settings as a toggle ('Research Qs' section).
Closes#1186
New opt-in PreToolUse hook that warns when Claude edits files outside
a GSD workflow context (no active /gsd: command or subagent).
Soft guard — advises, does not block. The edit proceeds but Claude
sees a reminder to use /gsd:fast or /gsd:quick for state tracking.
Enable: set hooks.workflow_guard: true in .planning/config.json
Default: disabled (false)
Allows without warning:
- .planning/ files (GSD state management)
- Config files (.gitignore, .env, CLAUDE.md, settings.json)
- Subagent contexts (executor, planner, etc.)
Includes 3s stdin timeout guard and silent fail-safe.
Closes#678
Code review fixes from codebase pattern analysis:
1. state.cjs: Remove duplicate stateExtractField() definition (lines 12 vs 184).
The second definition shadowed the first with identical logic. Keeps the
original that uses escapeRegex() from core.cjs.
2. init.cjs: Replace Unix-only 'find' pipe with cross-platform fs.readdirSync
recursive walk for code file detection. The execSync('find ... | grep ...')
command fails on Windows where these Unix utilities aren't available.
Removes unused child_process import.
3. state.cjs: Add lockfile-based mutual exclusion to writeStateMd() to prevent
parallel executor agents from overwriting each other's STATE.md changes.
Uses O_EXCL atomic file creation for lock acquisition, stale lock detection
(10s timeout), and spin-wait with jitter. Ensures data integrity during
wave-based parallel execution where multiple agents update STATE.md
concurrently.
All 755 existing tests pass.
New lightweight command for tasks too small to justify planning overhead:
typo fixes, config changes, forgotten commits, simple additions.
- Runs inline in current context (no subagent spawn)
- No PLAN.md or SUMMARY.md generated
- Scope guard: redirects to /gsd:quick if task needs >3 file edits
- Atomic commit with conventional commit format
- Logs to STATE.md quick tasks table if present
Complements /gsd:quick (which spawns planner+executor) for cases where
the planning overhead exceeds the actual work.
Closes#609
Windows users experience plan-phase freezes due to Claude Code stdio
deadlocks with MCP servers. When a subagent hangs, the orchestrator
blocks indefinitely with no timeout or error.
Adds:
- Windows troubleshooting section to plan-phase.md with:
- Orphaned process cleanup (PowerShell commands)
- Stale task directory cleanup (~/.claude/tasks/)
- MCP server reduction advice
- --skip-research fallback to reduce agent chain
- Stale task directory detection to health.md (I002 diagnostic)
- Reports count of stale dirs on --repair
- Safe cleanup guidance
Closes#732
Adds --analyze flag to /gsd:discuss-phase that provides a trade-off
analysis before each question (or question group in --batch mode).
When active, each question is preceded by:
- 2-3 options with pros/cons based on codebase context
- A recommended approach with reasoning
- Known pitfalls or constraints from prior phases
Composable with existing flags: --batch --analyze gives grouped
questions each with trade-off tables.
Closes#833