Commit Graph

154 Commits

Author SHA1 Message Date
Tom Boucher
802092d8ff fix: add verification gate before writing PROJECT.md in new-milestone
After gathering milestone goals and determining version, the workflow
now presents a summary and asks for confirmation before writing any
files. Users can adjust until satisfied, preventing the previous
behavior where GSD would immediately write PROJECT.md without verifying
its understanding of the milestone scope.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 22:07:57 -04:00
Colin
81fa102b9c Merge branch 'main' into Solvely/execute-phase-active-flags 2026-03-20 13:52:26 -04:00
Tom Boucher
62db008570 security: add prompt injection guards, path traversal prevention, and input validation
Defense-in-depth security hardening for a codebase where markdown files become
LLM system prompts. Adds centralized security module, PreToolUse hook for
injection detection, and CI-ready codebase scan.

New files:
- security.cjs: path traversal prevention, prompt injection scanner/sanitizer,
  safe JSON parsing, field name validation, shell arg validation
- gsd-prompt-guard.js: PreToolUse hook scans .planning/ writes for injection
- security.test.cjs: 62 unit tests for all security functions
- prompt-injection-scan.test.cjs: CI scan of all agent/workflow/command files

Hardened code paths:
- readTextArgOrFile: path traversal guard (--prd, --text-file)
- cmdStateUpdate/Patch: field name validation prevents regex injection
- cmdCommit: sanitizeForPrompt strips invisible chars from commit messages
- gsd-tools --fields: safeJsonParse wraps unprotected JSON.parse
- cmdFrontmatterGet/Set: null byte rejection
- cmdVerifyPathExists: null byte rejection
- install.js: registers prompt guard hook, updates uninstaller

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 11:38:26 -04:00
Tom Boucher
5adbba81b2 Merge pull request #1211 from jecanore/feat/advisor-mode-v2
feat: add advisor mode with research-backed discussion
2026-03-20 11:07:56 -04:00
Tom Boucher
122bc0d7c3 Merge pull request #1181 from diegomarino/feat/materialize-new-project-config
feat: materialize full config on new-project initialization
2026-03-20 11:07:09 -04:00
Tom Boucher
b0e60e9bbd Merge pull request #1253 from gsd-build/fix/commit-docs-gitignore-autodetect-1250
fix(core): auto-detect commit_docs from gitignore in loadConfig
2026-03-20 11:02:51 -04:00
Diego Mariño
fb83ada838 merge: resolve conflicts with upstream main (firecrawl + exa_search)
ensureConfigFile(): keep our refactored version that delegates to
buildNewProjectConfig({}) instead of upstream's duplicated logic.

buildNewProjectConfig(): add firecrawl and exa_search API key
detection alongside existing brave_search, matching upstream's
new integrations.
2026-03-20 15:54:58 +01:00
Tom Boucher
28166e4839 fix(core): auto-detect commit_docs from gitignore in loadConfig (#1250)
loadConfig() defaulted commit_docs to true regardless of whether
.planning/ was gitignored. The documented auto-detection only existed
inside cmdCommit, so init commands returned commit_docs: true even
when .planning/ was in .gitignore. This caused LLM executors to
bypass the cmdCommit gate and re-commit planning files with raw git.

Now loadConfig() checks isGitIgnored(cwd, '.planning/') when no
explicit commit_docs value is set in config.json. If .planning/ is
gitignored, commit_docs defaults to false. An explicit commit_docs
value in config.json is always respected.

Added 5 regression tests covering auto-detection, explicit overrides,
and the no-config-file edge case.
2026-03-20 10:41:42 -04:00
Tom Boucher
1063fdf1ad fix(init): add ROADMAP fallback to plan-phase, execute-phase, and verify-work (#1238)
cmdInitPlanPhase, cmdInitExecutePhase, and cmdInitVerifyWork returned
phase_found: false when the phase existed in ROADMAP.md but no phase
directory had been created yet. This caused workflows to fail silently
after /gsd:new-project, producing directories named null-null.

cmdInitPhaseOp (used by discuss-phase) already had a ROADMAP fallback.
Applied the same pattern to the three missing commands: when
findPhaseInternal returns null, fall back to getRoadmapPhaseInternal
and construct phaseInfo from the ROADMAP entry.

Added 5 regression tests covering:
- plan-phase ROADMAP fallback
- execute-phase ROADMAP fallback
- verify-work ROADMAP fallback
- phase_found false when neither directory nor ROADMAP entry exists
- disk directory preferred over ROADMAP fallback
2026-03-20 10:38:57 -04:00
Tom Boucher
1d5233a21b Merge pull request #1237 from Disaster-Terminator/fix-codex-config-crlf-features
fix(codex-config): safely manage codex_hooks in existing configs
2026-03-20 10:18:59 -04:00
Diego Mariño
a1852fef33 fix(tests): add USERPROFILE override for Windows HOME sandboxing
On Windows, os.homedir() reads USERPROFILE instead of HOME. The 6
tests using { HOME: tmpDir } to sandbox ~/.gsd/ lookups failed on
windows-latest because the child process still resolved homedir to
the real user profile.

Pass USERPROFILE alongside HOME in all sandboxed test calls.
2026-03-20 14:56:28 +01:00
Disaster-Terminator
b6a49163ea fix(codex-config): preserve EOL when enabling codex hooks 2026-03-20 13:24:19 +08:00
jecanore
86c10b4cea test: update agent count for new gsd-advisor-researcher agent 2026-03-19 20:08:50 -05:00
Diego Mariño
fd2a80675a merge: resolve conflicts with upstream main
VALID_CONFIG_KEYS: merge our additions (workflow.auto_advance,
workflow.node_repair, workflow.node_repair_budget, hooks.context_warnings)
with upstream's additions (workflow.text_mode, git.quick_branch_template).

ensureConfigFile(): keep our refactored version that delegates to
buildNewProjectConfig({}) instead of upstream's duplicated logic.

buildNewProjectConfig(): add git.quick_branch_template: null and
workflow.text_mode: false to match upstream's new keys.

new-project.md: integrate upstream's Step 5.1 Sub-Repo Detection
after our commit block; drop upstream's duplicate Note (ours at
line 493 is more detailed).
2026-03-19 22:48:21 +01:00
Srinivas Koduri
d0aae7b63c fix: address PR review — nested path resolution, sub_repos in init, depth-1 detection
- findProjectRoot: use isInsideGitRepo() to walk up and find .git in
  ancestor dirs, fixing nested paths like backend/src/modules/
- Add sub_repos to cmdInitExecutePhase output so execute-plan.md and
  gsd-executor.md can route commits correctly
- Align new-project.md sub-repo detection to maxdepth 1 matching
  detectSubRepos() behavior
- Add 3 nested path tests for .git heuristic, sub_repos, and multiRepo

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:18:20 -07:00
Srinivas Koduri
21081dc821 feat: multi-repo workspace support with auto-detection and project root resolution
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>
2026-03-19 12:18:20 -07:00
Tom Boucher
3e2c85e6fd refactor: consolidate STATE.md field helpers, fix command injection in isGitIgnored
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.
2026-03-19 15:05:20 -04:00
Tom Boucher
0afffb15f5 feat(core): worktree-aware .planning/ resolution and file locking (#1215)
- 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)
2026-03-19 13:41:11 -04:00
Tom Boucher
78fa8f4052 Merge pull request #1224 from trek-e/feat/discussion-log-1209
feat(discuss-phase): auto-generate DISCUSSION-LOG.md audit trail
2026-03-19 13:00:13 -04:00
Tom Boucher
44e141c043 Merge pull request #1218 from j2h4u/fix/one-liner-extraction
fix(lifecycle): extract one-liner from summary body when not in frontmatter
2026-03-19 12:59:52 -04:00
Tom Boucher
aa29c46ca6 Merge pull request #947 from j2h4u/fix/state-advance-plan-compound
fix(state): parse compound Plan field in advance-plan command
2026-03-19 12:59:18 -04:00
Tom Boucher
6d7f9e35e5 Merge pull request #923 from j2h4u/fix/progress-table-columns
fix(roadmap): handle 5-column progress tables with Milestone column
2026-03-19 12:58:47 -04:00
j2h4u
e3bc614eb7 fix(roadmap): handle 5-column progress tables with Milestone column
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>
2026-03-19 21:30:41 +05:00
j2h4u
104a39e573 fix(lifecycle): extract one-liner from summary body when not in frontmatter
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>
2026-03-19 21:29:25 +05:00
j2h4u
85a65fd384 fix(state): parse compound Plan field in advance-plan command
`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>
2026-03-19 21:28:26 +05:00
Tom Boucher
61d82dc3c0 feat(discuss-phase): auto-generate DISCUSSION-LOG.md for audit trail (#1209)
- 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
2026-03-19 12:25:59 -04:00
Tom Boucher
342ca5929d fix(tests): update expected Copilot skill count from 47 to 50
Three new commands were added (add-backlog, review-backlog, thread)
but the Copilot install test counts were not updated.
2026-03-19 12:25:47 -04:00
Tom Boucher
efc398c554 Merge pull request #1223 from trek-e/fix/remote-session-menu-fallback-1214
fix(workflows): text_mode config for Claude Code remote session compatibility
2026-03-19 12:13:10 -04:00
Tom Boucher
0f9908ae77 Merge pull request #1222 from trek-e/fix/copilot-executor-completion-1128
fix(execute-phase): Copilot sequential fallback and spot-check completion detection
2026-03-19 12:12:54 -04:00
Tom Boucher
52f6c71bdf Merge pull request #1144 from ChaptersOfFloatingLife/fix/codex-agent-toml-metadata
fix(codex): include required agent metadata in TOML
2026-03-19 12:12:08 -04:00
Tom Boucher
1f2e17923a Merge pull request #1142 from medhatgalal/AI/fix-codex-markerless-gsd-merge
Fix duplicate Codex GSD agent blocks without marker
2026-03-19 12:11:48 -04:00
Tom Boucher
ea1797d362 Merge pull request #922 from j2h4u/fix/plan-checkboxes-progress
fix(roadmap): mark individual plan checkboxes when summaries exist
2026-03-19 12:09:03 -04:00
Tom Boucher
a44094018b Merge pull request #1177 from matteo-michele-bianchini/fix/windows-absolute-paths
fix: use ~/ instead of resolved absolute paths in global install
2026-03-19 12:08:34 -04:00
Tom Boucher
f9434f7ffc Merge pull request #1212 from jecanore/feat/audit-uat
feat: add verification debt tracking and /gsd:audit-uat command
2026-03-19 12:05:36 -04:00
Tom Boucher
86cbd5442b Merge pull request #1217 from j2h4u/fix/task-count-pattern
fix(milestone): read task count from **Tasks:** field in summary body
2026-03-19 12:04:37 -04:00
Tom Boucher
841da5a80d Merge pull request #1155 from gsd-build/Solvely/quick-task-branching
feat(quick): add quick-task branch support
2026-03-19 12:03:58 -04:00
Tom Boucher
37ae2bc936 Merge pull request #1154 from gsd-build/Solvely/soft-gsd-workflow-enforcement
feat(new-project): add soft GSD workflow enforcement
2026-03-19 12:03:31 -04:00
Tom Boucher
0342ce33c6 Merge pull request #1149 from Solvely-Colin/Solvely/health-non-destructive-state-repair
fix(health): preserve state on phase mismatch repair
2026-03-19 12:02:11 -04:00
Tom Boucher
b0523d6cbe Merge pull request #1148 from Solvely-Colin/Solvely/reset-milestone-phase-numbers
feat(milestones): support safe phase-number resets
2026-03-19 12:01:52 -04:00
Tom Boucher
0487151142 fix(workflows): add text_mode config for Claude Code remote session compatibility (#1214)
- 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
2026-03-19 09:19:01 -04:00
Tom Boucher
8a6cdf5f25 fix(execute-phase): add Copilot sequential fallback and spot-check completion detection (#1128)
- Default Copilot runtime to sequential inline execution instead of
  unreliable subagent spawning
- Add spot-check fallback in step 3 (SUMMARY.md exists + git commits
  found) so orchestrator never blocks indefinitely on missing completion
  signals
- Add runtime detection guidance in init step to force sequential mode
  under Copilot
- Add regression test verifying execute-phase contains Copilot fallback
  and spot-check documentation
2026-03-19 09:15:06 -04:00
j2h4u
b34bf532ef fix(milestone): read task count from **Tasks:** field in summary body
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>
2026-03-19 14:37:21 +05:00
j2h4u
459f7f3b64 fix(roadmap): mark individual plan checkboxes when summaries exist
`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>
2026-03-19 14:36:11 +05:00
jecanore
60a76ae06e feat: add verification debt tracking and /gsd:audit-uat command
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>
2026-03-19 00:05:05 -05:00
Tom Boucher
1192c0ae02 Merge pull request #1203 from trek-e/fix/stale-hooks-filter-1200
fix: filter stale hooks check to gsd-prefixed files only (#1200)
2026-03-18 23:56:33 -04:00
Tom Boucher
cd8c406a7c Merge pull request #1204 from trek-e/fix/codex-config-toml-1202
fix: prevent Codex config.toml corruption from non-boolean [features] keys (#1202)
2026-03-18 23:56:18 -04:00
Tom Boucher
b0c78fa9bc Merge pull request #1205 from trek-e/refactor/adopt-planning-paths
refactor: adopt planningPaths() across 4 modules, standardize test assertions
2026-03-18 23:56:05 -04:00
Tom Boucher
c41a9f5908 feat: community-requested commands — /gsd:review, /gsd:plant-seed, /gsd:pr-branch
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.
2026-03-18 23:53:13 -04:00
Tom Boucher
1d4deb0f8b refactor: adopt planningPaths() across 4 modules — eliminate 34 inline path constructions
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.
2026-03-18 23:39:47 -04:00
Tom Boucher
862f6b91ba fix: prevent Codex config.toml corruption from non-boolean [features] keys (#1202)
When GSD installs codex_hooks = true under [features], any non-boolean
keys already in that section (e.g. model = "gpt-5.4") cause Codex's
TOML parser to fail with 'invalid type: string, expected a boolean'.

Root cause: TOML sections extend until the next [section] header. If
the user placed model/model_reasoning_effort under [features] (common
since Codex's own config format encourages this), GSD's installer
didn't detect or correct the structural issue.

Fix: After injecting codex_hooks, scan the [features] section for
non-boolean values and move them above [features] to the top level.
This preserves the user's keys while keeping [features] clean for
Codex's strict boolean parser.

Includes 2 regression tests:
- Detects non-boolean keys under [features] (model, model_reasoning_effort)
- Confirms boolean keys (codex_hooks, multi_agent) are not flagged

Closes #1202
2026-03-18 23:32:05 -04:00