* feat(#2492): add gates ensuring discuss-phase decisions are translated and verified
Two gates close the loop between CONTEXT.md `<decisions>` and downstream
work, fixing #2492:
- Plan-phase **translation gate** (BLOCKING). After requirements
coverage, refuses to mark a phase planned when a trackable decision
is not cited (by id `D-NN` or by 6+-word phrase) in any plan's
`must_haves`, `truths`, or body. Failure message names each missed
decision with id, category, text, and remediation paths.
- Verify-phase **validation gate** (NON-BLOCKING). Searches plans,
SUMMARY.md, files modified, and recent commit subjects for each
trackable decision. Misses are written to VERIFICATION.md as a
warning section but do not change verification status. Asymmetry is
deliberate — fuzzy-match miss should not fail an otherwise green
phase.
Shared helper `parseDecisions()` lives in `sdk/src/query/decisions.ts`
so #2493 can consume the same parser.
Decisions opt out of both gates via `### Claude's Discretion` heading
or `[informational]` / `[folded]` / `[deferred]` tags.
Both gates skip silently when `workflow.context_coverage_gate=false`
(default `true`).
Closes#2492
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(#2492): make plan-phase decision gate actually block (review F1, F8, F9, F10, F15)
- F1: replace `${context_path}` with `${CONTEXT_PATH}` in the plan-phase
gate snippet so the BLOCKING gate receives a non-empty path. The
variable was defined in Step 4 (`CONTEXT_PATH=$(_gsd_field "$INIT" ...)`)
and the gate snippet referenced the lowercase form, leaving the gate to
run with an empty path argument and silently skip.
- F15: wrap the SDK call with `jq -e '.data.passed == true' || exit 1` so
failure halts the workflow instead of being printed and ignored. The
verify-phase counterpart deliberately keeps no exit-1 (non-blocking by
design) and now carries an inline note documenting the asymmetry.
- F10: tag the JSON example fence as `json` and the options-list fence as
`text` (MD040).
- F8/F9: anchor the heading-presence test regexes to `^## 13[a-z]?\\.` so
prose substrings like "Requirements Coverage Gate" mentioned in body
text cannot satisfy the assertion. Added two new regression tests
(variable-name match, exit-1 guard) so a future revert is caught.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(#2492): tighten decision-coverage gates against false positives and config drift (review F3,F4,F5,F6,F7,F16,F18,F19)
- F3: forward `workstream` arg through both gate handlers so workstream-scoped
`workflow.context_coverage_gate=false` actually skips. Added negative test
that creates a workstream config disabling the gate while the root config
has it enabled and asserts the workstream call is skipped.
- F4: restrict the plan-phase haystack to designated sections — front-matter
`must_haves` / `truths` / `objective` plus body sections under headings
matching `must_haves|truths|tasks|objective`. HTML comments and fenced
code blocks are stripped before extraction so a commented-out citation or
a literal example never counts as coverage. Verify-phase keeps the broader
artifact-wide haystack by design (non-blocking).
- F5: reject decisions with fewer than 6 normalized words from soft-matching
(previously only rejected when the resulting phrase was under 12 chars
AFTER slicing — too lenient). Short decisions now require an explicit
`D-NN` citation, with regression tests for the boundary.
- F6: walk every `*-SUMMARY.md` independently and use `matchAll` with the
`/g` flag so multiple `files_modified:` blocks across multiple summaries
are all aggregated. Previously only the first block in the concatenated
string was parsed, silently dropping later plans' files.
- F7: validate every `files_modified` path stays inside `projectDir` after
resolution (rejects absolute paths, `../` traversal). Cap each file read
at 256 KB. Skipped paths emit a stderr warning naming the entry.
- F16: validate `workflow.context_coverage_gate` is boolean in
`loadGateConfig`; warn loudly on numeric or other-shaped values and
default to ON. Mirrors the schema-vs-loadConfig validation gap from
#2609.
- F18: bump verify-phase `git log -n` cap from 50 to 200 so longer-running
phases are not undercounted. Documented as a precision-vs-recall tradeoff
appropriate for a non-blocking gate.
- F19: tighten `QueryResult` / `QueryHandler` to be parameterized
(`<T = unknown>`). Drops the `as unknown as Record<string, unknown>`
casts in the gate handlers and surfaces shape mismatches at compile time
for callers that pass a typed `data` value.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(#2492): harden decisions parser and verify-phase glob (review F11,F12,F13,F14,F17,F20)
- F11: strip fenced code blocks from CONTEXT.md before searching for
`<decisions>` so an example block inside ``` ``` is not mis-parsed.
- F12: accept tab-indented continuation lines (previously required a leading
space) so decisions split with `\t` continue cleanly.
- F13: parse EVERY `<decisions>` block in the file via `matchAll`, not just
the first. CONTEXT.md may legitimately carry more than one block.
- F14: `decisions.parse` handler now resolves a relative path against
`projectDir` — symmetric with the gate handlers — and still accepts
absolute paths.
- F17: replace `ls "${PHASE_DIR}"/*-CONTEXT.md | head -1` in verify-phase.md
with a glob loop (ShellCheck SC2012 fix). Also avoids spawning an extra
subprocess and survives filenames with whitespace.
- F20: extend the unicode quote-stripping in the discretion-heading match
to cover U+2018/2019/201A/201B and the U+201C-F double-quote variants
plus backtick, so any rendering of "Claude's Discretion" collapses to
the same key.
Each fix has a regression test in `decisions.test.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#2388 (plan-phase silently renames feature branch): add explicit Git
Branch Invariant section to plan-phase.md prohibiting branch
creation/rename/switch during planning; phase slug changes are
plan-level only and must not affect the git branch.
#2431 (worktree teardown silently swallows errors): replace
`git worktree remove --force 2>/dev/null || true` with a lock-aware
block in quick.md and execute-phase.md that detects locked worktrees,
attempts unlock+retry, and surfaces a user-visible recovery message
when removal still fails.
#2396 (hardcoded test commands bypass Makefile): add a three-tier
test command resolver (project config → Makefile/Justfile → language
sniff) in execute-phase.md, verify-phase.md, and audit-fix.md.
Makefile with a `test:` target now takes priority over npm/cargo/go.
#2376 (OpenCode @$HOME not mapped on Windows): add platform guard in
bin/install.js so OpenCode on win32 uses the absolute path instead of
`$HOME/...`, which OpenCode does not expand in @file references on
Windows.
Tests: 29 new assertions across 4 regression test files (all passing).
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: harness engineering improvements — post-merge test gate, shared file isolation, behavioral verification
Three improvements inspired by Anthropic's harness engineering research
(March 2026) and real-world pain points from parallel worktree execution:
1. Post-merge test gate (execute-phase.md)
- Run project test suite after merging each wave's worktrees
- Catches cross-plan integration failures that individual Self-Checks miss
- Addresses the Generator self-evaluation blind spot (agents praise own work)
2. Shared file isolation (execute-phase.md)
- Executors no longer modify STATE.md or ROADMAP.md in parallel mode
- Orchestrator updates tracking files centrally after merge
- Eliminates the #1 source of merge conflicts in parallel execution
3. Behavioral verification (verify-phase.md)
- Verifier runs project test suite and CLI commands, not just grep
- Follows Anthropic's Generator/Evaluator separation principle
- Tests actual behavior against success criteria, not just file existence
Real-world evidence: In a session executing 37 plans across 8 phases with
parallel worktrees, we observed:
- 4 test failures after merge that all Self-Checks missed (models.py type loss)
- STATE.md/ROADMAP.md conflicts on every single parallel merge
- Verifier reporting PASSED while merged code had broken imports
References:
- Anthropic Engineering Blog: Harness Design for Long-Running Apps (2026-03-24)
- Issue #1451: Massive git worktree problem
- Issue #1413: Autonomous execution without manual context clearing
* fix: address review feedback — test runner detection, parallel isolation, edge cases
- Replace hardcoded jest/vitest with `npm test` (reads project's scripts.test)
- Add Go detection to post-merge test gate (was only in verify-phase)
- Add 5-minute timeout to post-merge test gate to prevent pipeline stalls
- Track cumulative wave failures via WAVE_FAILURE_COUNT for cross-wave awareness
- Guard orchestrator tracking commit against unchanged files (prevent empty commits)
- Align execute-plan.md with parallel isolation model (skip STATE.md/ROADMAP.md
updates when running in parallel mode, orchestrator handles centrally)
- Scope behavioral verification CLI checks: skip when no fixtures/test data exist,
mark as NEEDS HUMAN instead of inventing inputs
* fix: pass PARALLEL_MODE to executor agents to activate shared file isolation
The executor spawn prompt in execute-phase.md instructed agents not to
modify STATE.md/ROADMAP.md, but execute-plan.md gates this behavior on
PARALLEL_MODE which was never defined in the executor context. This adds
the variable to the spawn prompt and wraps all three shared-file steps
(update_current_position, update_roadmap, git_commit_metadata) with
explicit conditional guards.
* fix: replace unreliable PARALLEL_MODE env var with git worktree auto-detection
Address PR #1486 review feedback (trek-e):
1. PARALLEL_MODE was never reliably set — the <env> block instructed the LLM
to export a bash variable, but each Bash tool call runs in a fresh shell
so the variable never persisted. Replace with self-contained worktree
detection: `[ -f .git ]` returns true in worktrees (.git is a file) and
false in main repos (.git is a directory). Each bash block detects
independently with no external state dependency.
2. TEST_EXIT only checked for timeout (124) — test failures (non-zero,
non-124) were silently ignored, making the "If tests fail" prose
unreachable. Add full if/elif/else handling: 0=pass, 124=timeout,
else=fail with WAVE_FAILURE_COUNT increment.
3. Add Go detection to regression_gate (was missing go.mod check).
Replace hardcoded npx jest/vitest with npm test for consistency.
4. Renumber steps from 4/4b/4c/5/5/5b to 4a/4b/4c/4d/5/6/7/8/9.
* fix: address remaining review blockers — timeout, tracking guard, shell safety
- verify-phase.md: wrap behavioral_verification test suite in timeout 300
- execute-phase.md: gate tracking update on TEST_EXIT=0, skip on failure/timeout
- Quote all TEST_EXIT variables, add default initialization
- Add else branch for unrecognized project types
- Renumber steps to align with upstream (5.x series)
* fix: rephrase worktree success_criteria to satisfy substring test guard
The worktree mode success_criteria line literally contained "STATE.md"
and "ROADMAP.md" inside a prohibition ("No modifications to..."), but
the test guard in execute-phase-worktree-artifacts.test.cjs uses a
substring check and cannot distinguish prohibition from requirement.
Rephrase to "shared orchestrator artifacts" so the substring check
passes while preserving the same intent.
The gsd-verifier was reporting false-positive gaps for items explicitly
scheduled in later phases of the milestone (e.g., reporting a Phase 5
item as a gap during Phase 1 verification). This adds Step 9b to
cross-reference gaps against later phases using `roadmap analyze` and
move matched items to a `deferred` list that does not affect status.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a new `audit_test_quality` step between `scan_antipatterns` and
`identify_human_verification` that catches test-level deceptions:
- Disabled tests (it.skip/xit/test.todo) covering phase requirements
- Circular tests (system generating its own expected values)
- Weak assertions (existence-only when value-level proof needed)
- Expected value provenance tracking for parity/migration phases
Any blocker from this audit forces `gaps_found` status, preventing
phases from being marked complete with inadequate test evidence.
Fixes#1457
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The verifier agent could set status: passed even when the report contained
a non-empty "Human Verification Required" section. This bypassed the
human_needed → HUMAN-UAT.md → user approval gate, allowing phases to be
marked complete without human testing.
Replace the advisory status descriptions with an ordered decision tree
(most restrictive first): gaps_found → human_needed → passed. The passed
status is now only valid when zero human verification items exist.
Synced the same decision tree in the verify-phase workflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Address 4 root causes of Windows + Claude Code reliability issues:
1. Workflow shell robustness: add || true guards to informational commands
(ls, grep, find, cat) that return non-zero on "no results", preventing
workflow step failures under strict execution models. Guard glob loops
with [ -e "$var" ] || continue to handle empty glob expansion.
2. Hook stdin handling: replace readFileSync('/dev/stdin') with async
process.stdin + timeout in agent templates (gsd-verifier.md). Existing
JS hooks already have timeout guards.
3. project_root detection: fix isInsideGitRepo() to check .git at the
candidate parent level (not just below it), enabling correct detection
when .git and .planning/ are siblings at the same directory level —
the common single-repo case from a subdirectory.
4. @file: handoff: add missing @file: handlers to autonomous.md and
manager.md workflows that call gsd-tools init but lacked the handler
for large output payloads.
Fixes#1343
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three additive quality improvements to the execution pipeline:
1. Pre-wave dependency check (execute-phase): Before spawning wave N+1,
verify key-links from prior wave artifacts. Catches cross-plan wiring
gaps before they cascade into downstream failures.
2. Cross-Plan Data Contracts dimension (plan-checker): New Dimension 9
checks that plans sharing data pipelines have compatible transformations.
Flags when one plan strips data another plan needs in original form.
3. Export-level spot check (verify-phase): After Level 3 wiring passes,
spot-check individual exports for actual usage. Catches dead stores
that exist in wired files but are never called.
When gsd-tools init output exceeds 50KB, core.cjs writes to a temp file
and outputs @file:<path>. No workflow handled this prefix, causing agents
to hallucinate /tmp paths that fail on Windows (C:\tmp doesn't exist).
Add @file: resolution line after every INIT=$(node ...) call across all
32 workflow, agent, and reference files.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Claude Code subagents sometimes rewrite ~/. paths to relative paths,
causing MODULE_NOT_FOUND when CWD is the project directory. $HOME is a
shell variable resolved at runtime, immune to model path rewriting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Projects with "type": "module" in package.json cause Node to treat
gsd-tools.js as ESM, crashing on require(). The .cjs extension forces
CommonJS regardless of the host project's module configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The verifier was deriving verification truths from the vague one-line Goal
field, allowing partial implementations to pass. Now extracts Success Criteria
as a structured array from `roadmap get-phase` and uses them directly as truths,
with Goal derivation as fallback for older ROADMAPs without Success Criteria.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(gsd-tools): add frontmatter CRUD, verification suite, template fill, and state progression
Four new command groups that delegate deterministic operations from AI agents to code:
- frontmatter get/set/merge/validate: Safe YAML frontmatter manipulation with schema validation
- verify plan-structure/phase-completeness/references/commits/artifacts/key-links: Structural checks agents previously burned context on
- template fill summary/plan/verification: Pre-filled document skeletons so agents only fill creative content
- state advance-plan/record-metric/update-progress/add-decision/add-blocker/resolve-blocker/record-session: Automate arithmetic and formatting in STATE.md
Adds reconstructFrontmatter() + spliceFrontmatter() helpers for safe frontmatter roundtripping,
and parseMustHavesBlock() for 3-level YAML parsing of must_haves structures.
20 new functions, ~1037 new lines.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: wire gsd-tools commands into agents and workflows
- gsd-verifier: use `verify artifacts` and `verify key-links` instead of
manual grep patterns for stub detection and wiring verification
- gsd-executor: use `state advance-plan`, `state update-progress`,
`state record-metric`, `state add-decision`, `state record-session`
instead of manual STATE.md manipulation
- gsd-plan-checker: use `verify plan-structure` and `frontmatter get`
for structural validation and must_haves extraction
- gsd-planner: add validation step using `frontmatter validate` and
`verify plan-structure` after writing PLAN.md
- execute-plan.md: use gsd-tools state commands for position/progress updates
- verify-phase.md: use gsd-tools for must_haves extraction and artifact/link verification
This makes the gsd-tools commands from PR #485 actually used by the system.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Add proper @-references to three reference files that existed
but were never loaded:
- git-integration.md -> execute-plan.md
- continuation-format.md -> resume-project.md
- verification-patterns.md -> verify-phase.md
- Support both zero-padded (05-*) and unpadded (5-*) phase folders
- Delete orphaned research-subagent-prompt.md template
- Update resume-project.md to use Task tool resume parameter
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Commands load agent expertise directly via Task tool spawning.
Thin orchestrator pattern — agents have methodology baked in.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>