Commit Graph

2504 Commits

Author SHA1 Message Date
Tom Boucher
f1960fad67 fix(install): eliminate Claude reference leaks in Qwen install paths (#2112)
Three install code paths were leaking Claude-specific references into
Qwen installs: copyCommandsAsClaudeSkills lacked runtime-aware content
replacement, the agents copy loop had no isQwen branch, and the hooks
template loop only replaced the quoted '.claude' form. Added CLAUDE.md,
Claude Code, and .claude/ replacements across all three paths plus
copyWithPathReplacement's Qwen .md branch. Includes regression test
that walks the full .qwen/ tree after install and asserts zero Claude
references outside CHANGELOG.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 11:19:47 -04:00
Tom Boucher
898dbf03e6 Merge pull request #2113 from gsd-build/docs/undocumented-features-v1.36
docs: add v1.36.0 feature documentation for PRs #2100-#2111
2026-04-11 10:42:28 -04:00
Tom Boucher
362e5ac36c fix(docs): correct plan_bounce_passes default from 1 to 2
The actual code default in config.cjs and config.json template is 2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 10:39:31 -04:00
Tom Boucher
3865afd254 Merge branch 'main' into docs/undocumented-features-v1.36 2026-04-11 10:39:23 -04:00
Tom Boucher
091793d2c6 Merge pull request #2111 from gsd-build/feat/1978-prompt-thinning
feat(agents): context-window-aware prompt thinning for sub-200K models
2026-04-11 10:38:18 -04:00
Tom Boucher
06daaf4c68 Merge pull request #2110 from gsd-build/feat/1884-sdk-ws-flag
feat(sdk): add --ws flag for workstream-aware execution
2026-04-11 10:38:07 -04:00
Tom Boucher
4ad7ecc6c6 Merge pull request #2109 from gsd-build/feat/1873-extract-learnings
feat(workflow): add extract-learnings command (#1873)
2026-04-11 10:37:57 -04:00
Tom Boucher
9d5d7d76e7 Merge pull request #2108 from gsd-build/fix/1988-phase-researcher-app-aware
feat(agents): add Architectural Responsibility Mapping to phase-researcher pipeline
2026-04-11 10:37:45 -04:00
Tom Boucher
bae220c5ad Merge pull request #2107 from gsd-build/feat/1875-cross-ai-execution
feat(executor): add cross-AI execution hook in execute-phase
2026-04-11 10:37:39 -04:00
Tom Boucher
8961322141 merge: resolve config.json conflict with main (add all new workflow keys)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 10:36:17 -04:00
Tom Boucher
3c2cc7189a Merge pull request #2106 from gsd-build/feat/1960-cursor-cli-reviewer
feat(review): add Cursor CLI as peer reviewer in /gsd-review
2026-04-11 10:35:20 -04:00
Tom Boucher
9ff6ca20cf Merge pull request #2105 from gsd-build/feat/1876-code-review-command-hook
feat(ship): add external code review command hook
2026-04-11 10:35:05 -04:00
Tom Boucher
73be20215e merge: resolve conflicts with main (plan_bounce + code_review_command)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 10:32:20 -04:00
Tom Boucher
ae17848ef1 Merge pull request #2104 from gsd-build/feat/1874-plan-bounce
feat(plan-phase): add plan bounce hook (step 12.5)
2026-04-11 10:31:04 -04:00
Tom Boucher
f425bf9142 enhancement(planner): replace time-based reasoning with context-cost sizing and add multi-source coverage audit (#2091) (#2092) (#2114)
Replace minutes-based task sizing with context-window percentage sizing.
Add planner_authority_limits section prohibiting difficulty-based scope
decisions. Expand decision coverage matrix to multi-source audit covering
GOAL, REQ, RESEARCH, and CONTEXT artifacts. Add Source Audit gap handling
to plan-phase orchestrator (step 9c). Update plan-checker to detect
time/complexity language in scope reduction scans. Add 374 CI regression
tests preventing prohibited language from leaking back into artifacts.

Closes #2091
Closes #2092

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 10:26:27 -04:00
Tom Boucher
4553d356d2 docs: add v1.36.0 feature documentation for PRs #2100-#2111
Document 8 new features (108-115) in FEATURES.md, add --bounce/--cross-ai
flags to COMMANDS.md, new /gsd-extract-learnings command, 8 new config keys
in CONFIGURATION.md, and skill-manifest + --ws flag in CLI-TOOLS.md.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 09:54:21 -04:00
Tom Boucher
319663deb7 feat(agents): add context-window-aware prompt thinning for sub-200K models (#1978)
When CONTEXT_WINDOW < 200000, executor and planner agent prompts strip
extended examples and anti-pattern lists into reference files for
on-demand @ loading, reducing static overhead by ~40% while preserving
behavioral correctness for standard (200K-500K) and enriched (500K+) tiers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:34:29 -04:00
Tom Boucher
868e3d488f feat(sdk): add --ws flag for workstream-aware execution (#1884)
Add a --ws <name> CLI flag that routes all .planning/ paths to
.planning/workstreams/<name>/, enabling multi-workstream projects
without directory conflicts.

Changes:
- workstream-utils.ts: validateWorkstreamName() and relPlanningPath() helpers
- cli.ts: Parse --ws flag with input validation
- types.ts: Add workstream? to GSDOptions
- gsd-tools.ts: Inject --ws <name> into all gsd-tools.cjs invocations
- config.ts: Resolve workstream-aware config path with root fallback
- context-engine.ts: Constructor accepts workstream via positional param
- index.ts: GSD class propagates workstream to all subsystems
- ws-flag.test.ts: 22 tests covering all workstream functionality

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:33:34 -04:00
Tom Boucher
3f3fd0a723 feat(workflow): add extract-learnings command for phase knowledge capture (#1873)
Add /gsd:extract-learnings command and backing workflow that extracts
decisions, lessons, patterns, and surprises from completed phase artifacts
into a structured LEARNINGS.md file with YAML frontmatter metadata.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:28:16 -04:00
Tom Boucher
21ebeb8713 feat(executor): add cross-AI execution hook (step 2.5) in execute-phase (#1875)
Add optional cross-AI delegation step that lets execute-phase delegate
plans to external AI runtimes via stdin-based prompt delivery. Activated
by --cross-ai flag, plan frontmatter cross_ai: true, or config key
workflow.cross_ai_execution. Adds 3 config keys, template defaults,
and 18 tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:20:27 -04:00
Tom Boucher
53995faa8f feat(ship): add external code review command hook to ship workflow
Adds workflow.code_review_command config key that allows solo devs to
plug external AI review tools into the ship flow. When configured, the
ship workflow generates a diff, builds a review prompt with stats and
phase context, pipes it to the command via stdin, and parses JSON output
with verdict/confidence/issues. Handles timeout (120s) and failures
gracefully by falling through to the existing manual review flow.

Closes #1876

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:19:32 -04:00
Tom Boucher
9ac7b7f579 feat(plan-phase): add optional plan bounce hook for external refinement (step 12.5)
Add plan bounce feature that allows plans to be refined through an external
script between plan-checker approval and requirements coverage gate. Activated
via --bounce flag or workflow.plan_bounce config. Includes backup/restore
safety (pre-bounce.md), YAML frontmatter validation, and checker re-run on
bounced plans.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:19:01 -04:00
Tom Boucher
ff0b06b43a feat(review): add Cursor CLI self-detection and complete REVIEWS.md template (#1960)
Add CURSOR_SESSION_ID env var detection in review.md so Cursor skips
itself as a reviewer (matching the CLAUDE_CODE_ENTRYPOINT pattern).
Add Qwen Review and Cursor Review sections to the REVIEWS.md template.
Update ja-JP and ko-KR FEATURES.md to include --opencode, --qwen, and
--cursor flags in the /gsd-review command signature.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:18:49 -04:00
Tom Boucher
72e789432e feat(agents): add Architectural Responsibility Mapping to phase-researcher pipeline (#1988) (#2103)
Before framework-specific research, phase-researcher now maps each
capability to its architectural tier owner (browser, frontend server,
API, database, CDN). The planner sanity-checks task assignments against
this map, and plan-checker enforces tier compliance as Dimension 7c.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:16:11 -04:00
Tom Boucher
23763f920b feat(config): add configurable claude_md_path setting (#2010) (#2102)
Allow users to control where GSD writes its managed CLAUDE.md sections
via a `claude_md_path` setting in .planning/config.json, enabling
separation of GSD content from team-shared CLAUDE.md in shared repos.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:15:36 -04:00
Tom Boucher
9435c4dd38 feat(init): add skill-manifest command to pre-compute skill discovery (#2101)
Adds `skill-manifest` command that scans a skills directory, extracts
frontmatter and trigger conditions from each SKILL.md, and outputs a
compact JSON manifest. This reduces per-agent skill discovery from 36
Read operations (~6,000 tokens) to a single manifest read (~1,000 tokens).

Closes #1976

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:15:18 -04:00
Tom Boucher
f34dc66fa9 fix(core): use dedicated temp subdirectory for GSD temp files (#1975) (#2100)
Move GSD temp file writes from os.tmpdir() root to os.tmpdir()/gsd
subdirectory. This limits reapStaleTempFiles() scan to only GSD files
instead of scanning the entire system temp directory.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:15:00 -04:00
Tom Boucher
1f7ca6b9e8 feat(agents): add Architectural Responsibility Mapping to phase-researcher pipeline (#1988)
Before framework-specific research, phase-researcher now maps each
capability to its architectural tier owner (browser, frontend server,
API, database, CDN). The planner sanity-checks task assignments against
this map, and plan-checker enforces tier compliance as Dimension 7c.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:14:28 -04:00
Tom Boucher
6b0e3904c2 enhancement(workflow): replace consecutive-call counter with prior-phase completeness scan in /gsd-next (#2097)
Removes the .next-call-count counter file guard (which fired on clean usage and missed
real incomplete work) and replaces it with a scan of all prior phases for plans without
summaries, unoverridden VERIFICATION.md failures, and phases with CONTEXT.md but no plans.
When gaps are found, shows a structured report with Continue/Stop/Force options; the
Continue path writes a formal 999.x backlog entry and commits it before routing. Clean
projects route silently with no interruption.

Closes #2089

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:02:30 -04:00
Tom Boucher
aa4532b820 fix(workflow): quote path variables in workspace next-step examples (#2096)
Display examples showing 'cd $TARGET_PATH' and 'cd $WORKSPACE_PATH/repo1'
were unquoted, causing path splitting when project paths contain spaces
(e.g. Windows paths like C:\Users\First Last\...).

Quote all path variable references in user-facing guidance blocks so
the examples shown to users are safe to copy-paste directly.

The actual bash execution blocks (git worktree add, rm -rf, etc.) were
already correctly quoted — this fixes only the display examples.

Fixes #2088

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:02:18 -04:00
Tom Boucher
0e1711b460 fix(workflow): carve out Other+empty exception from answer_validation retry loop (#2093)
When a user selects "Other" in AskUserQuestion with no text body, the
answer_validation block was treating the empty result as a generic empty
response and retrying the question — causing 2-3 cascading question rounds
instead of pausing for freeform user input as intended by the Other handling
on line 795.

Add an explicit exception in answer_validation: "Other" + empty text signals
freeform intent, not a missing answer. The workflow must output one prompt line
and stop rather than retry or generate more questions.

Fixes #2085

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 09:02:01 -04:00
Tom Boucher
b84dfd4c9b fix(tests): add before() hook to bug-1736 test to prevent hooks/dist race condition (#2099)
With --test-concurrency=4, bug-1834 and bug-1924 run build-hooks.js concurrently
with bug-1736. build-hooks.js creates hooks/dist/ empty first then copies files,
creating a window where bug-1736 sees an empty directory, install() fails with
"directory is empty", and process.exit(1) kills the test process.

Added the same before() pattern used by all other install tests.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 08:50:44 -04:00
Carlos Cativo
5a302f477a fix: add Qwen Code dedicated path replacement branches and finishInstall labels (#2082)
- Add isQwen branch in copyWithPathReplacement for .md files converting
  CLAUDE.md to QWEN.md and 'Claude Code' to 'Qwen Code'
- Add isQwen branch in copyWithPathReplacement for .js/.cjs files
  converting .claude paths to .qwen equivalents
- Add Qwen Code program and command labels in finishInstall() so the
  post-install message shows 'Qwen Code' instead of 'Claude Code'

Closes #2081

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-04-11 08:36:35 -04:00
Tibsfox
01f0b4b540 feat(state): add --dry-run mode and resolved blocker pruning (#1970)
Review feedback from @trek-e — address scope gaps:

1. **--dry-run mode** — New flag that computes what would be pruned
   without modifying STATE.md. Returns structured output showing
   per-section counts so users can verify before committing.

2. **Resolved blocker pruning** — In addition to decisions and
   recently-completed entries, now prunes entries in the Blockers
   section that are marked resolved (~~strikethrough~~ or [RESOLVED]
   prefix) AND reference a phase older than the cutoff. Unresolved
   blockers are preserved regardless of age.

3. **Tests** — Added tests/state-prune.test.cjs (4 cases):
   - Prunes decisions older than cutoff, keeps recent
   - --dry-run reports changes without modifying STATE.md
   - Prunes resolved blockers, keeps unresolved regardless of age
   - Returns pruned:false when nothing exceeds cutoff

Scope items still deferred (to be filed as follow-up):
- Performance Metrics "By Phase" table row pruning — needs different
  regex handling than prose lines
- Auto-prune via workflow.auto_prune_state at phase completion — needs
  integration into cmdPhaseComplete

Also: the pre-existing test failure (2918/2919) is
tests/stale-colon-refs.test.cjs:83:3 "No stale /gsd: colon references
(#1748)". Verified failing on main, not introduced by this PR.
2026-04-11 03:43:46 -07:00
Tibsfox
f1b3702be8 feat(state): add state prune command for unbounded section growth (#1970)
Add `gsd-tools state prune --keep-recent N` that moves old decisions
and recently-completed entries to STATE-ARCHIVE.md. Entries from phases
older than (current - N) are archived; the N most recent are kept.

STATE.md sections grow unboundedly in long-lived projects. A 20+ phase
project accumulates hundreds of historical decisions that every agent
loads into context. Pruning removes stale entries from the hot path
while preserving them in a recoverable archive.

Usage: gsd-tools state prune --keep-recent 3
Default: keeps 3 most recent phases

Closes #1970

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:39:57 -07:00
Tibsfox
0a18fc3464 fix(config): global skill symlink guard, tests, and empty-name handling (#1992)
Review feedback from @trek-e — three blocking issues and one style fix:

1. **Symlink escape guard** — Added validatePath() call on the resolved
   global skill path with allowAbsolute: true. This routes the path
   through the existing symlink-resolution and containment logic in
   security.cjs, preventing a skill directory symlinked to an arbitrary
   location from being injected. The name regex alone prevented
   traversal in the literal name but not in the underlying directory.

2. **5 new tests** covering the global: code path:
   - global:valid-skill resolves and appears in output
   - global:invalid!name rejected by regex, skipped without crash
   - global:missing-skill (directory absent) skipped gracefully
   - Mix of global: and project-relative paths both resolve
   - global: with empty name produces clear warning and skips

3. **Explicit empty-name guard** — Added before the regex check so
   "global:" produces "empty skill name" instead of the confusing
   'Invalid global skill name ""'.

4. **Style fix** — Hoisted require('os') and globalSkillsBase
   calculation out of the loop, alongside the existing validatePath
   import at the top of buildAgentSkillsBlock.

All 16 agent-skills tests pass.
2026-04-11 03:39:29 -07:00
Tibsfox
7752234e75 feat(config): support global skills from ~/.claude/skills/ in agent_skills (#1992)
Add global: prefix for agent_skills config entries that resolve to
~/.claude/skills/<name>/SKILL.md instead of the project root. This
allows injecting globally-installed skills (e.g., shadcn, supabase)
into GSD sub-agents without duplicating them into every project.

Example config:
  "agent_skills": {
    "gsd-executor": ["global:shadcn", "global:supabase-postgres"]
  }

Security: skill names are validated against /^[a-zA-Z0-9_-]+$/ to
prevent path traversal. The ~/.claude/skills/ directory is a trusted
runtime-controlled location. Project-relative paths continue to use
validatePath() containment checks as before.

Closes #1992

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:37:56 -07:00
Tibsfox
7be9affea2 fix(hooks): address three blocking defects in context exhaustion record (#1974)
Review feedback from @trek-e — three blocking fixes:

1. **Sentinel prevents repeated firing**
   Added warnData.criticalRecorded flag persisted to the warn state file.
   Previously the subprocess fired on every DEBOUNCE_CALLS cycle (5 tool
   uses) for the rest of the session, overwriting the "crash moment"
   record with a new timestamp each time. Now fires exactly once per
   CRITICAL session.

2. **Runtime-agnostic path via __dirname**
   Replaced hardcoded `path.join(process.env.HOME, '.claude', ...)` with
   `path.join(__dirname, '..', 'get-shit-done', 'bin', 'gsd-tools.cjs')`.
   The hook lives at <runtime-config>/hooks/ and gsd-tools.cjs at
   <runtime-config>/get-shit-done/bin/ — __dirname resolves correctly on
   all runtimes (Claude Code, OpenCode, Gemini, Kilo) without assuming
   ~/.claude/.

3. **Correct subcommand: state record-session**
   Switched from `state update "Stopped At" ...` to
   `state record-session --stopped-at ...`. The dedicated command
   updates Last session, Last Date, Stopped At, and Resume File
   atomically under the state lock.

Also:
- Hoisted `const { spawn } = require('child_process')` to top of file
  to match existing require() style.
- Coerced usedPct to Number(usedPct) || 0 to sanitize the bridge file
  in case it's malformed or adversarially crafted.

Tests (tests/bug-1974-context-exhaustion-record.test.cjs, 4 cases):
- Subprocess spawns and writes "context exhaustion" on CRITICAL
- Subprocess does NOT spawn when .planning/STATE.md is absent
- Sentinel guard prevents second fire within same session
- Hook source uses __dirname-based path (not hardcoded ~/.claude/)
2026-04-11 03:37:34 -07:00
Tibsfox
42ad3fe853 feat(hooks): auto-record session state on context exhaustion (#1974)
When the context monitor detects CRITICAL threshold (25% remaining)
and a GSD project is active, spawn a fire-and-forget subprocess to
record "Stopped At: context exhaustion at N%" in STATE.md.

This provides automatic breadcrumbs for /gsd-resume-work when sessions
crash from context exhaustion — the most common unrecoverable scenario.
Previously, session state was only saved via voluntary /gsd-pause-work.

The subprocess is detached and unref'd so it doesn't block the hook
or the agent. The advisory warning to the agent is unchanged.

Closes #1974

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:35:20 -07:00
Tibsfox
67aeb049c2 fix(state): invalidate disk scan cache in writeStateMd (#1967)
Add _diskScanCache.delete(cwd) at the start of writeStateMd before
buildStateFrontmatter is called. This prevents stale reads if multiple
state-mutating operations occur within the same Node process — the
write may create new PLAN/SUMMARY files that the next frontmatter
computation must see.

Matters for:
- SDK callers that require() gsd-tools.cjs as a module
- Future dispatcher extensions handling compound operations
- Tests that import state.cjs directly

Adds tests/bug-1967-cache-invalidation.test.cjs which exercises two
sequential writes in the same process with a new phase directory
created between them, asserting the second write sees the new disk
state (total_phases: 2, completed_phases: 1) instead of the cached
pre-write snapshot (total_phases: 1, completed_phases: 0).

Review feedback on #2054 from @trek-e.
2026-04-11 03:35:00 -07:00
Tibsfox
5638448296 perf(state): cache buildStateFrontmatter disk scan per process (#1967)
buildStateFrontmatter performs N+1 readdirSync calls (phases dir + each
phase subdirectory) every time it's called. Multiple state writes within
a single gsd-tools invocation repeat the same scan unnecessarily.

Add a module-level Map cache keyed by cwd that stores the disk scan
results. The cache auto-clears when the process exits since each
gsd-tools CLI invocation is a short-lived process running one command.

Closes #1967

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:33:48 -07:00
Tibsfox
e5cc0bb48b fix(workflow): correct grep anchor and add threshold=0 guard (#1979)
Two correctness bugs from @trek-e review:

1. Grep pattern `^<task` only matched unindented task tags, missing
   indented tasks in PLAN.md templates that use indentation. Fixed to
   `^\s*<task[[:space:]>]` which matches at any indentation level and
   avoids false positives on <tasks> or </task>.

2. Threshold=0 was documented to disable inline routing but the
   condition `TASK_COUNT <= INLINE_THRESHOLD` evaluated 0<=0 as true,
   routing empty plans inline even when the feature was disabled.
   Fixed by guarding with `INLINE_THRESHOLD > 0`.

Added tests/inline-plan-threshold.test.cjs (8 tests) covering:
- config-set accepts the key and threshold=0
- VALID_CONFIG_KEYS and planning-config.md contain the entry
- Routing pattern matches indented tasks and rejects <tasks>/</task>
- Inline routing is guarded by INLINE_THRESHOLD > 0

Review feedback on #2061 from @trek-e.
2026-04-11 03:33:29 -07:00
Tibsfox
bd7048985d perf(workflow): default to inline execution for small plans (#1979)
Plans with 1-2 tasks now execute inline (Pattern C) instead of spawning
a subagent (Pattern A). This avoids ~14K token subagent spawn overhead
and preserves the orchestrator's prompt cache for small plans.

The threshold is configurable via workflow.inline_plan_threshold
(default: 2). Set to 0 to always spawn subagents. Plans above the
threshold continue to use checkpoint-based routing as before.

Closes #1979

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:31:27 -07:00
Tibsfox
e0b766a08b perf(workflow): include Depends on phases in prior-phase context (#1969)
Per approved spec in #1969, the planner must include CONTEXT.md and
SUMMARY.md from any phases listed in the current phase's 'Depends on:'
field in ROADMAP.md, in addition to the 3 most recent completed phases.

This ensures explicit dependencies are always visible to the planner
regardless of recency — e.g., Phase 7 declaring 'Depends on: Phase 2'
always sees Phase 2's context, not just when Phase 2 is among the 3
most recent.

Review feedback on #2058 from @trek-e.
2026-04-11 03:31:09 -07:00
Tibsfox
2efce9fd2a perf(workflow): limit prior-phase context to 3 most recent phases (#1969)
When CONTEXT_WINDOW >= 500000 (1M models), the planner loaded ALL prior
phase CONTEXT.md and SUMMARY.md files for cross-phase consistency. On
projects with 20+ phases, this consumed significant context budget with
diminishing returns — decisions from phase 2 are rarely relevant to
phase 22.

Limit to the 3 most recent completed phases, which provides enough
cross-phase context for consistency while keeping the planner's context
budget focused on the current phase's plans.

Closes #1969

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:30:32 -07:00
Tibsfox
2cd0e0d8f0 test(core): add atomic write coverage structural regression guard (#1972)
Per CONTRIBUTING.md, enhancements require tests covering the enhanced
behavior. This test structurally verifies that milestone.cjs, phase.cjs,
and frontmatter.cjs do not contain bare fs.writeFileSync calls targeting
.planning/ files. All such writes must route through atomicWriteFileSync.

Allowed exceptions: .gitkeep writes (empty files) and archive directory
writes (new files, not read-modify-write).

This complements atomic-write.test.cjs which tests the helper itself.
If someone later adds a bare writeFileSync to these files without using
the atomic helper, this test will catch it.

Review feedback on #2056 from @trek-e.
2026-04-11 03:30:05 -07:00
Tibsfox
cad40fff8b fix(core): extend atomicWriteFileSync to milestone, phase, and frontmatter (#1972)
Replace 11 fs.writeFileSync calls with atomicWriteFileSync in three
files that write to .planning/ artifacts (ROADMAP.md, REQUIREMENTS.md,
MILESTONES.md, and frontmatter updates). This prevents partial writes
from corrupting planning files on crash or power loss.

Skipped low-risk writes: .gitkeep (empty files) and archive directory
writes (new files, not read-modify-write).

Files changed:
- milestone.cjs: 5 sites (REQUIREMENTS.md, MILESTONES.md)
- phase.cjs: 5 sites (ROADMAP.md, REQUIREMENTS.md)
- frontmatter.cjs: 2 sites (arbitrary .planning/ files)

Closes #1972

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:25:06 -07:00
Tibsfox
053269823b test(health): add degradation test for missing phasesDir (#1973)
Covers the behavior change from independent per-check degradation to
coupled degradation when the hoisted readdirSync throws. Asserts that
cmdValidateHealth completes without throwing and emits zero phase
directory warnings (W005, W006, W007, W009, I001) when phasesDir
doesn't exist.

Review feedback on #2053 from @trek-e.
2026-04-11 03:24:49 -07:00
Tibsfox
08d1767a1b perf(health): merge four readdirSync passes into one in cmdValidateHealth (#1973)
cmdValidateHealth read the phases directory four separate times for
checks 6 (naming), 7 (orphaned plans), 7b (validation artifacts), and
8 (roadmap cross-reference). Hoist the directory listing into a single
readdirSync call with a shared Map of per-phase file lists.

Reduces syscalls from ~3N+1 to N+1 where N is the number of phase
directories.

Closes #1973

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 03:23:56 -07:00
Tom Boucher
6c2795598a docs: release notes and documentation updates for v1.35.0 (#2079)
Closes #2080
2026-04-10 22:29:06 -04:00