@opengsd/gsd-core 1.10.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/agents/gsd-debug-session-manager.md +11 -0
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +5 -5
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +37 -0
- package/agents/gsd-planner.md +44 -46
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +12 -3
- package/bin/install.js +841 -971
- package/bin/lib/ui-safety-gate.cjs +2 -0
- package/commands/gsd/code-review.md +1 -1
- package/commands/gsd/execute-phase.md +1 -1
- package/commands/gsd/map-codebase.md +1 -1
- package/commands/gsd/mempalace-capture.md +1 -1
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +1 -1
- package/commands/gsd/quick.md +1 -1
- package/commands/gsd/review-backlog.md +2 -1
- package/commands/gsd/verify-work.md +1 -1
- package/gsd-core/bin/gsd-tools.cjs +469 -88
- package/gsd-core/bin/lib/active-workstream-store.cjs +138 -22
- package/gsd-core/bin/lib/agent-install-check.cjs +230 -32
- package/gsd-core/bin/lib/api-coverage.cjs +3 -5
- package/gsd-core/bin/lib/artifacts.cjs +3 -0
- package/gsd-core/bin/lib/assumption-delta.cjs +2 -4
- package/gsd-core/bin/lib/audit-command-router.cjs +9 -2
- package/gsd-core/bin/lib/audit.cjs +876 -240
- package/gsd-core/bin/lib/broken-windows.cjs +1 -1
- package/gsd-core/bin/lib/capability-consent.cjs +149 -15
- package/gsd-core/bin/lib/capability-lifecycle.cjs +45 -0
- package/gsd-core/bin/lib/capability-registry.cjs +575 -101
- package/gsd-core/bin/lib/capability-source.cjs +92 -0
- package/gsd-core/bin/lib/capability-trust.cjs +444 -25
- package/gsd-core/bin/lib/capability-validator.cjs +495 -22
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +71 -37
- package/gsd-core/bin/lib/claude-orchestration.cjs +56 -3
- package/gsd-core/bin/lib/codex-agent-toml.cjs +329 -0
- package/gsd-core/bin/lib/command-aliases.cjs +22 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +651 -86
- package/gsd-core/bin/lib/commonjs-marker.cjs +12 -6
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +75 -0
- package/gsd-core/bin/lib/config.cjs +10 -1
- package/gsd-core/bin/lib/core-utils.cjs +127 -29
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +155 -20
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/git-base-branch.cjs +102 -0
- package/gsd-core/bin/lib/gsd2-import.cjs +10 -1
- package/gsd-core/bin/lib/health-diagnostic-rules/agent-install.cjs +101 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/config-validation.cjs +348 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/consistency.cjs +145 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/install-surface-shadowing.cjs +98 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/milestone-archive-hygiene.cjs +100 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/phase-structure.cjs +222 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/roadmap-disk-consistency.cjs +265 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/root-existence.cjs +161 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/state-consistency.cjs +303 -0
- package/gsd-core/bin/lib/health-diagnostic-rules/worktree-health.cjs +173 -0
- package/gsd-core/bin/lib/health-diagnostic-types.cjs +68 -0
- package/gsd-core/bin/lib/health-diagnostic.cjs +431 -0
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init.cjs +321 -129
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +745 -258
- package/gsd-core/bin/lib/install-fs-adapter.cjs +262 -0
- package/gsd-core/bin/lib/install-model-override-resolver.cjs +203 -0
- package/gsd-core/bin/lib/install-profiles.cjs +134 -57
- package/gsd-core/bin/lib/install-scope.cjs +270 -0
- package/gsd-core/bin/lib/install-shadow-report.cjs +385 -0
- package/gsd-core/bin/lib/installed-surface-resolver.cjs +381 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +138 -31
- package/gsd-core/bin/lib/io.cjs +10 -0
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +2 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +754 -70
- package/gsd-core/bin/lib/model-catalog.cjs +59 -1
- package/gsd-core/bin/lib/model-resolver.cjs +183 -40
- package/gsd-core/bin/lib/normalize-test-command.cjs +1 -1
- package/gsd-core/bin/lib/pattern.cjs +122 -0
- package/gsd-core/bin/lib/phase-estimation.cjs +1 -1
- package/gsd-core/bin/lib/phase-id.cjs +444 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +125 -18
- package/gsd-core/bin/lib/phase.cjs +646 -143
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +72 -1
- package/gsd-core/bin/lib/plan-drift-guard.cjs +120 -0
- package/gsd-core/bin/lib/plan-scan.cjs +86 -2
- package/gsd-core/bin/lib/planning-scope.cjs +31 -0
- package/gsd-core/bin/lib/planning-snapshot.cjs +890 -0
- package/gsd-core/bin/lib/planning-workspace.cjs +56 -6
- package/gsd-core/bin/lib/probe-core.cjs +1 -1
- package/gsd-core/bin/lib/profile-output.cjs +1 -1
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +11 -6
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +13 -4
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +421 -66
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +34 -0
- package/gsd-core/bin/lib/roadmap-parser.cjs +943 -184
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +385 -94
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +608 -46
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +426 -55
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +69 -3
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +115 -3
- package/gsd-core/bin/lib/runtime-name-policy.cjs +3 -1
- package/gsd-core/bin/lib/runtime-slash.cjs +27 -9
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +275 -3
- package/gsd-core/bin/lib/smart-entry.cjs +142 -22
- package/gsd-core/bin/lib/state-command-router.cjs +5 -1
- package/gsd-core/bin/lib/state-document.cjs +152 -8
- package/gsd-core/bin/lib/state-transition.cjs +371 -117
- package/gsd-core/bin/lib/state.cjs +1794 -357
- package/gsd-core/bin/lib/surface.cjs +23 -9
- package/gsd-core/bin/lib/text-lines.cjs +80 -0
- package/gsd-core/bin/lib/token-scanner.cjs +76 -0
- package/gsd-core/bin/lib/uat-predicate.cjs +9 -3
- package/gsd-core/bin/lib/uat.cjs +399 -56
- package/gsd-core/bin/lib/ui-frontend-evidence.cjs +157 -0
- package/gsd-core/bin/lib/ui-safety-gate.cjs +14 -5
- package/gsd-core/bin/lib/unusable-input.cjs +24 -0
- package/gsd-core/bin/lib/update-context.cjs +8 -2
- package/gsd-core/bin/lib/user-artifact-staging.cjs +705 -0
- package/gsd-core/bin/lib/validate.cjs +20 -6
- package/gsd-core/bin/lib/vendor/README.md +37 -0
- package/gsd-core/bin/lib/vendor/re2js.cjs +6480 -0
- package/gsd-core/bin/lib/vendor/re2js.d.cts +938 -0
- package/gsd-core/bin/lib/verification-command-router.cjs +2 -1
- package/gsd-core/bin/lib/verification.cjs +258 -8
- package/gsd-core/bin/lib/verify.cjs +368 -888
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +53 -32
- package/gsd-core/bin/lib/workstream-inventory.cjs +63 -10
- package/gsd-core/bin/lib/workstream.cjs +2 -2
- package/gsd-core/bin/lib/worktree-safety.cjs +176 -9
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +7 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/dispatch-isolation-gate.md +138 -0
- package/gsd-core/references/doc-conflict-engine.md +1 -1
- package/gsd-core/references/execute-mvp-tdd.md +3 -3
- package/gsd-core/references/execute-phase-between-wave-reset.md +6 -2
- package/gsd-core/references/execute-phase-context-guard.md +1 -1
- package/gsd-core/references/execute-phase-response-language.md +1 -1
- package/gsd-core/references/execute-phase-wave-guard.md +6 -2
- package/gsd-core/references/gate-prompts.md +1 -1
- package/gsd-core/references/git-planning-commit.md +2 -1
- package/gsd-core/references/loop-hook-dispatch.md +39 -2
- package/gsd-core/references/model-profiles.md +12 -4
- package/gsd-core/references/mvp-concepts.md +9 -9
- package/gsd-core/references/planner-guidance.md +3 -9
- package/gsd-core/references/planner-preconditions.md +1 -1
- package/gsd-core/references/planner-reviews.md +1 -1
- package/gsd-core/references/planning-config.md +8 -6
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +1 -1
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/templates/discussion-log.md +1 -1
- package/gsd-core/templates/phase-prompt.md +2 -4
- package/gsd-core/templates/state.md +4 -4
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/autonomous.md +1 -1
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +13 -3
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +38 -12
- package/gsd-core/workflows/complete-milestone.md +141 -18
- package/gsd-core/workflows/debug.md +7 -5
- package/gsd-core/workflows/diagnose-issues.md +35 -9
- package/gsd-core/workflows/discuss-phase/modes/chain.md +2 -1
- package/gsd-core/workflows/discuss-phase/modes/default.md +1 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +2 -1
- package/gsd-core/workflows/edit-phase.md +26 -1
- package/gsd-core/workflows/eval-review.md +3 -5
- package/gsd-core/workflows/execute-phase/steps/executor-isolation-dispatch.md +31 -6
- package/gsd-core/workflows/execute-phase/steps/per-plan-executor-routing.md +77 -0
- package/gsd-core/workflows/execute-phase/steps/per-plan-worktree-gate.md +2 -0
- package/gsd-core/workflows/execute-phase.md +38 -50
- package/gsd-core/workflows/execute-plan.md +36 -4
- package/gsd-core/workflows/explore.md +131 -4
- package/gsd-core/workflows/fast.md +10 -2
- package/gsd-core/workflows/health.md +73 -4
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +5 -5
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone.md +14 -9
- package/gsd-core/workflows/new-project.md +14 -14
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase.md +41 -17
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress.md +34 -6
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +4 -4
- package/gsd-core/workflows/quick/steps/quick-verification.md +27 -6
- package/gsd-core/workflows/quick/steps/research-phase.md +2 -2
- package/gsd-core/workflows/quick.md +35 -15
- package/gsd-core/workflows/review.md +26 -5
- package/gsd-core/workflows/secure-phase.md +1 -1
- package/gsd-core/workflows/session-report.md +2 -1
- package/gsd-core/workflows/settings.md +66 -2
- package/gsd-core/workflows/ship.md +104 -44
- package/gsd-core/workflows/spec-phase.md +30 -12
- package/gsd-core/workflows/sync-skills.md +63 -8
- package/gsd-core/workflows/transition.md +46 -11
- package/gsd-core/workflows/ui-phase.md +5 -5
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update.md +1 -1
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work.md +9 -7
- package/hooks/dist/gsd-agent-isolation-guard.js +103 -14
- package/hooks/dist/gsd-check-update-worker.js +56 -13
- package/hooks/dist/gsd-check-update.js +19 -1
- package/hooks/dist/gsd-cursor-pre-tool.js +0 -3
- package/hooks/dist/gsd-cursor-subagent-start.js +77 -2
- package/hooks/dist/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/dist/gsd-prompt-guard.js +21 -20
- package/hooks/dist/gsd-read-injection-scanner.js +38 -24
- package/hooks/dist/gsd-statusline.js +18 -0
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/lib/git-cmd.js +92 -59
- package/hooks/dist/lib/injection-patterns.js +45 -0
- package/hooks/dist/lib/isolation-deny-reason.js +39 -0
- package/hooks/dist/lib/isolation-sentinel.js +9 -0
- package/hooks/gsd-agent-isolation-guard.js +103 -14
- package/hooks/gsd-check-update-worker.js +56 -13
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +77 -2
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +38 -24
- package/hooks/gsd-statusline.js +18 -0
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/lib/git-cmd.js +92 -59
- package/hooks/lib/injection-patterns.js +45 -0
- package/hooks/lib/isolation-deny-reason.js +39 -0
- package/hooks/lib/isolation-sentinel.js +9 -0
- package/package.json +21 -9
- package/pi/gsd.cjs +19 -5
- package/scripts/baselines/planning-prompt-drift-baseline.json +4 -0
- package/scripts/baselines/planning-snapshot-bypass-baseline.json +12 -0
- package/scripts/baselines/unreachable-guard-drift-baseline.json +4 -0
- package/scripts/changeset/lint.cjs +60 -5
- package/scripts/check-alias-drift.cjs +7 -43
- package/scripts/check-contract-drift.cjs +297 -0
- package/scripts/ci-test-scope.cjs +19 -2
- package/scripts/command-contract-helpers.cjs +903 -1
- package/scripts/gen-adr-index.cjs +728 -38
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +2 -11
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +50 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/lib/alias-drift-families.cjs +46 -0
- package/scripts/lib/drift-scan.cjs +278 -0
- package/scripts/lint-allow-test-rule-refs.allowlist.json +1 -26
- package/scripts/lint-allow-test-rule-refs.effective-ceiling.json +4 -0
- package/scripts/lint-allow-test-rule-refs.unverified-ceiling.json +3 -0
- package/scripts/lint-canary-version-leak.cjs +73 -0
- package/scripts/lint-command-contract.cjs +96 -13
- package/scripts/lint-completion-predicate-drift.cjs +933 -0
- package/scripts/lint-completion-ratio-drift.cjs +214 -0
- package/scripts/lint-default-flip-documentation.cjs +193 -0
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-frontmatter-scalar-broad-grep.cjs +237 -0
- package/scripts/lint-health-diagnostic-rule-table.cjs +404 -0
- package/scripts/lint-hooks-runtime-build-seam.cjs +262 -0
- package/scripts/lint-milestone-window-drift.cjs +468 -0
- package/scripts/lint-phase-enumeration-drift.cjs +479 -0
- package/scripts/lint-plan-count-drift.cjs +318 -0
- package/scripts/lint-planning-artifact-writer-drift.cjs +398 -0
- package/scripts/lint-planning-prompt-drift.cjs +434 -0
- package/scripts/lint-planning-snapshot-bypass-drift.cjs +544 -0
- package/scripts/lint-regression-test-names.cjs +15 -13
- package/scripts/lint-removed-but-needed.cjs +320 -0
- package/scripts/lint-state-field-drift.cjs +805 -0
- package/scripts/lint-state-write-path-drift.cjs +1045 -0
- package/scripts/lint-test-file-count.allowlist.json +21 -10
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +25 -0
- package/scripts/require-issue-link-policy.cjs +192 -0
- package/scripts/state-write-path-drift-baseline.json +19 -0
- package/scripts/sync-runtime-launcher.cjs +2 -4
- package/skills/gsd-autonomous/SKILL.md +0 -1
- package/skills/gsd-code-review/SKILL.md +1 -1
- package/skills/gsd-execute-phase/SKILL.md +1 -2
- package/skills/gsd-map-codebase/SKILL.md +1 -1
- package/skills/gsd-mempalace-capture/SKILL.md +1 -1
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +1 -1
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +0 -1
- package/skills/gsd-progress/SKILL.md +0 -1
- package/skills/gsd-quick/SKILL.md +1 -1
- package/skills/gsd-review-backlog/SKILL.md +2 -1
- package/skills/gsd-stats/SKILL.md +0 -1
- package/skills/gsd-verify-work/SKILL.md +1 -1
- package/vscode/package.json +1 -1
- package/gsd-core/workflows/discovery-phase.md +0 -298
- package/gsd-core/workflows/plan-milestone-gaps.md +0 -281
- package/gsd-core/workflows/verify-phase.md +0 -574
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1051
|
@@ -48,7 +48,7 @@ INIT_EARLY=$(gsd_run query init.new-milestone)
|
|
|
48
48
|
if [[ "$INIT_EARLY" == @file:* ]]; then INIT_EARLY=$(cat "${INIT_EARLY#@file:}"); fi
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
`GSD_WS` must chain to every downstream routing suggestion in this workflow (Step 4's shared-file guard, and the `/gsd:discuss-phase`/`/gsd:plan-phase` routing hints below) per the routing-propagation contract in `references/workstream-flag.md` — never let it silently drop.
|
|
51
|
+
`GSD_WS` must chain to every downstream routing suggestion in this workflow (Step 4's shared-file guard, and the `/gsd:discuss-phase`/`/gsd:plan-phase` routing hints below) per the routing-propagation contract in `gsd-core/references/workstream-flag.md` — never let it silently drop.
|
|
52
52
|
|
|
53
53
|
**If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow (including the "What do you want to build next?" prompt and seed-selection questions below) MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated.
|
|
54
54
|
|
|
@@ -160,7 +160,7 @@ AskUserQuestion:
|
|
|
160
160
|
|
|
161
161
|
## 4. Update PROJECT.md
|
|
162
162
|
|
|
163
|
-
PROJECT.md is shared across workstreams (`references/workstream-flag.md` marks it `# Shared` in the directory diagram). This step has two independently-scoped parts — only Part A is workstream-guarded.
|
|
163
|
+
PROJECT.md is shared across workstreams (`gsd-core/references/workstream-flag.md` marks it `# Shared` in the directory diagram). This step has two independently-scoped parts — only Part A is workstream-guarded.
|
|
164
164
|
|
|
165
165
|
<!-- gsd:section id="project-md-milestone-write" when="state:flat-mode" -->
|
|
166
166
|
If `section_manifest` (from `INIT_EARLY`) is `null` or `"project-md-milestone-write"` is in its `included` list: read and execute `gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md`. Otherwise (a workstream is active) skip — do not read the file; Part B below still runs regardless of `GSD_WS`.
|
|
@@ -259,9 +259,14 @@ rejects any `--archive-version` value that is not a plain version token (no path
|
|
|
259
259
|
Stage the phase archive move + source removal so they land in the same commit as the milestone start (atomic — no orphaned uncommitted deletions, no un-archived dirs carried forward). `phases.clear` archives each non-999 dir to `milestones/<version>-phases/`; staging both dirs captures the new archive and the removals together (#1871).
|
|
260
260
|
|
|
261
261
|
```bash
|
|
262
|
-
|
|
262
|
+
COMMIT_DOCS=$(gsd_run query config-get commit_docs 2>/dev/null || echo "true")
|
|
263
|
+
if [ "$COMMIT_DOCS" != "false" ]; then
|
|
264
|
+
git add .planning/milestones/ .planning/phases/ 2>/dev/null || true
|
|
265
|
+
fi
|
|
263
266
|
```
|
|
264
267
|
|
|
268
|
+
When `commit_docs` is false, the archive move and phase removals are deliberately left unstaged here — not a bug — since Step 6's commit is skipped too.
|
|
269
|
+
|
|
265
270
|
Stage PROJECT.md in both modes. Step 4's Part A guard — not this commit — is what protects the shared `## Current Milestone` heading (#2308): when a workstream is active Part A never writes it, so the only change PROJECT.md can carry here is Part B's idempotent `## Evolution` backfill, which must be committed rather than stranded as a dangling edit. Do NOT reintroduce a `[ -n "$GSD_WS" ]` branch around this commit: `GSD_WS` is set in Step 1's shell and each step's bash block runs in its own shell (the same reason Step 5 round-trips `OUTGOING_MILESTONE` through a file), so such a guard reads an unset variable, always takes the flat-mode branch, and only appears to work.
|
|
266
271
|
|
|
267
272
|
```bash
|
|
@@ -351,9 +356,9 @@ Focus ONLY on what's needed for the NEW features.
|
|
|
351
356
|
|
|
352
357
|
<question>{QUESTION}</question>
|
|
353
358
|
|
|
354
|
-
<
|
|
359
|
+
<required_reading>
|
|
355
360
|
- {project_path} (Project context)
|
|
356
|
-
</
|
|
361
|
+
</required_reading>
|
|
357
362
|
|
|
358
363
|
${AGENT_SKILLS_RESEARCHER}
|
|
359
364
|
|
|
@@ -390,12 +395,12 @@ After all 4 complete, spawn synthesizer:
|
|
|
390
395
|
Agent(prompt="
|
|
391
396
|
Synthesize research outputs into SUMMARY.md.
|
|
392
397
|
|
|
393
|
-
<
|
|
398
|
+
<required_reading>
|
|
394
399
|
- {research_dir}/STACK.md
|
|
395
400
|
- {research_dir}/FEATURES.md
|
|
396
401
|
- {research_dir}/ARCHITECTURE.md
|
|
397
402
|
- {research_dir}/PITFALLS.md
|
|
398
|
-
</
|
|
403
|
+
</required_reading>
|
|
399
404
|
|
|
400
405
|
${AGENT_SKILLS_SYNTHESIZER}
|
|
401
406
|
|
|
@@ -518,13 +523,13 @@ gsd_run query commit "docs: define milestone v[X.Y] requirements" --files .plann
|
|
|
518
523
|
```text
|
|
519
524
|
Agent(prompt="
|
|
520
525
|
<planning_context>
|
|
521
|
-
<
|
|
526
|
+
<required_reading>
|
|
522
527
|
- {project_path}
|
|
523
528
|
- {requirements_path}
|
|
524
529
|
- {research_dir}/SUMMARY.md (if exists)
|
|
525
530
|
- {config_path}
|
|
526
531
|
- {milestones_path}
|
|
527
|
-
</
|
|
532
|
+
</required_reading>
|
|
528
533
|
|
|
529
534
|
${AGENT_SKILLS_ROADMAPPER}
|
|
530
535
|
|
|
@@ -752,9 +752,9 @@ Subsequent: Research what's needed to add [target features] to an existing [doma
|
|
|
752
752
|
What's the standard 2025 stack for [domain]?
|
|
753
753
|
</question>
|
|
754
754
|
|
|
755
|
-
<
|
|
755
|
+
<required_reading>
|
|
756
756
|
- {project_path} (Project context and goals)
|
|
757
|
-
</
|
|
757
|
+
</required_reading>
|
|
758
758
|
|
|
759
759
|
${AGENT_SKILLS_RESEARCHER}
|
|
760
760
|
|
|
@@ -796,9 +796,9 @@ Subsequent: How do [target features] typically work? What's expected behavior?
|
|
|
796
796
|
What features do [domain] products have? What's table stakes vs differentiating?
|
|
797
797
|
</question>
|
|
798
798
|
|
|
799
|
-
<
|
|
799
|
+
<required_reading>
|
|
800
800
|
- {project_path} (Project context)
|
|
801
|
-
</
|
|
801
|
+
</required_reading>
|
|
802
802
|
|
|
803
803
|
${AGENT_SKILLS_RESEARCHER}
|
|
804
804
|
|
|
@@ -836,9 +836,9 @@ Subsequent: How do [target features] integrate with existing [domain] architectu
|
|
|
836
836
|
How are [domain] systems typically structured? What are major components?
|
|
837
837
|
</question>
|
|
838
838
|
|
|
839
|
-
<
|
|
839
|
+
<required_reading>
|
|
840
840
|
- {project_path} (Project context)
|
|
841
|
-
</
|
|
841
|
+
</required_reading>
|
|
842
842
|
|
|
843
843
|
${AGENT_SKILLS_RESEARCHER}
|
|
844
844
|
|
|
@@ -876,9 +876,9 @@ Subsequent: What are common mistakes when adding [target features] to [domain]?
|
|
|
876
876
|
What do [domain] projects commonly get wrong? Critical mistakes?
|
|
877
877
|
</question>
|
|
878
878
|
|
|
879
|
-
<
|
|
879
|
+
<required_reading>
|
|
880
880
|
- {project_path} (Project context)
|
|
881
|
-
</
|
|
881
|
+
</required_reading>
|
|
882
882
|
|
|
883
883
|
${AGENT_SKILLS_RESEARCHER}
|
|
884
884
|
|
|
@@ -912,12 +912,12 @@ Agent(prompt="
|
|
|
912
912
|
Synthesize research outputs into SUMMARY.md.
|
|
913
913
|
</task>
|
|
914
914
|
|
|
915
|
-
<
|
|
915
|
+
<required_reading>
|
|
916
916
|
- {research_dir}/STACK.md
|
|
917
917
|
- {research_dir}/FEATURES.md
|
|
918
918
|
- {research_dir}/ARCHITECTURE.md
|
|
919
919
|
- {research_dir}/PITFALLS.md
|
|
920
|
-
</
|
|
920
|
+
</required_reading>
|
|
921
921
|
|
|
922
922
|
${AGENT_SKILLS_SYNTHESIZER}
|
|
923
923
|
|
|
@@ -1161,12 +1161,12 @@ Spawn gsd-roadmapper agent with path references:
|
|
|
1161
1161
|
Agent(prompt="
|
|
1162
1162
|
<planning_context>
|
|
1163
1163
|
|
|
1164
|
-
<
|
|
1164
|
+
<required_reading>
|
|
1165
1165
|
- {project_path} (Project context)
|
|
1166
1166
|
- {requirements_path} (v1 Requirements)
|
|
1167
1167
|
- {research_dir}/SUMMARY.md (Research findings - if exists)
|
|
1168
1168
|
- {config_path} (Granularity and mode settings)
|
|
1169
|
-
</
|
|
1169
|
+
</required_reading>
|
|
1170
1170
|
|
|
1171
1171
|
${AGENT_SKILLS_ROADMAPPER}
|
|
1172
1172
|
|
|
@@ -1262,9 +1262,9 @@ Use AskUserQuestion:
|
|
|
1262
1262
|
User feedback on roadmap:
|
|
1263
1263
|
[user's notes]
|
|
1264
1264
|
|
|
1265
|
-
<
|
|
1265
|
+
<required_reading>
|
|
1266
1266
|
- {roadmap_path} (Current roadmap to revise)
|
|
1267
|
-
</
|
|
1267
|
+
</required_reading>
|
|
1268
1268
|
|
|
1269
1269
|
${AGENT_SKILLS_ROADMAPPER}
|
|
1270
1270
|
|
|
@@ -104,11 +104,22 @@ Illustrative bash:
|
|
|
104
104
|
```bash
|
|
105
105
|
INCOMPLETE_PHASE=""
|
|
106
106
|
ROADMAP_JSON=$(gsd_run query roadmap.analyze)
|
|
107
|
+
ROADMAP_SCOPE=$(echo "$ROADMAP_JSON" | jq -r '.scope // "complete"')
|
|
107
108
|
if [ $? -ne 0 ] || [ -z "$ROADMAP_JSON" ]; then
|
|
108
109
|
echo "⚠ WARNING: resume-incomplete-phase scan could not run (roadmap.analyze failed)." >&2
|
|
109
110
|
echo " The incomplete-phase invariant (#160) could not be verified." >&2
|
|
110
111
|
echo " Proceeding to prior-phase completeness check — review project state carefully." >&2
|
|
111
112
|
# Fall through to prior_phase_completeness rather than silently skipping
|
|
113
|
+
elif [ "$ROADMAP_SCOPE" != "complete" ]; then
|
|
114
|
+
# #3184/#3165: roadmap.analyze succeeded and returned a well-formed document,
|
|
115
|
+
# but its milestone window did not see all of its input, so `.phases[]` is a
|
|
116
|
+
# NON-answer rather than a real empty. Looping it would run the invariant over
|
|
117
|
+
# a phase list the scan could not populate and report "clean" — the silent
|
|
118
|
+
# disarm #3165 reports. Treated as scan-failed, same as an outright failure.
|
|
119
|
+
echo "⚠ WARNING: resume-incomplete-phase scan could not be scoped (roadmap.analyze scope: $ROADMAP_SCOPE)." >&2
|
|
120
|
+
echo " The milestone window did not cover the whole ROADMAP, so the phase list is incomplete." >&2
|
|
121
|
+
echo " The incomplete-phase invariant (#160) could not be verified — review project state carefully." >&2
|
|
122
|
+
# Fall through to prior_phase_completeness rather than silently passing
|
|
112
123
|
else
|
|
113
124
|
for PHASE_NUM in $(echo "$ROADMAP_JSON" | jq -r '.phases[] | (.number // .phase_number // empty)'); do
|
|
114
125
|
PHASE_JSON=$(gsd_run query find-phase "$PHASE_NUM")
|
|
@@ -338,6 +349,7 @@ Resume with: `/gsd:progress --next --auto` once resolved.
|
|
|
338
349
|
- [ ] `--no-resume`: Route 0 skipped, prior_phase_completeness defer prompt runs as before
|
|
339
350
|
- [ ] `--force`: everything skipped (Gates, Route 0, prior_phase_completeness) → straight to `determine_next_action`
|
|
340
351
|
- [ ] Scan uses `gsd_run` (canonical resolver form); errors are surfaced rather than suppressed
|
|
352
|
+
- [ ] A `roadmap.analyze` result whose `scope` is not `complete` is treated as scan-failed (warn + fall through), never as a clean empty scan (#3184/#3165)
|
|
341
353
|
- [ ] Predicate is plans-without-summaries (`plans.length > summaries.length`) — consistent with `determine_next_action` Route 4
|
|
342
354
|
- [ ] Next action correctly determined from routing rules
|
|
343
355
|
- [ ] Command invoked immediately without user confirmation
|
|
@@ -73,6 +73,14 @@ INGEST_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--ingest[[:space:]]+([^[:s
|
|
|
73
73
|
RESEARCH_PHASE_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--research-phase[[:space:]]+([^[:space:]-][^[:space:]]*) ]]; then RESEARCH_PHASE_PARAM="--research-phase ${BASH_REMATCH[2]}"; fi
|
|
74
74
|
REVIEWS_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--reviews([[:space:]]|$) ]]; then REVIEWS_PARAM="--reviews"; fi
|
|
75
75
|
CHUNKED_PARAM=""; if [[ "$ARGUMENTS" =~ (^|[[:space:]])--chunked([[:space:]]|$) ]]; then CHUNKED_PARAM="--chunked"; fi
|
|
76
|
+
# Project the just-completed planning mode onto the execute-phase follow-up (#3297):
|
|
77
|
+
# a --gaps run creates gap_closure plans, so the Next Up handoff must point at
|
|
78
|
+
# execute-phase's matching --gaps-only scope rather than the whole-phase run.
|
|
79
|
+
# Standard and --reviews runs leave GAPS_EXEC_FLAG empty → their Next Up is unchanged.
|
|
80
|
+
GAPS_MODE=false
|
|
81
|
+
if [[ "$ARGUMENTS" =~ (^|[[:space:]])--gaps([[:space:]]|$) ]]; then GAPS_MODE=true; fi
|
|
82
|
+
GAPS_EXEC_FLAG=""
|
|
83
|
+
if [ "$GAPS_MODE" = "true" ]; then GAPS_EXEC_FLAG="--gaps-only"; fi
|
|
76
84
|
INIT=$(gsd_run query init.plan-phase "$PHASE" $GRAN_PARAM $PRD_PARAM $INGEST_PARAM $RESEARCH_PHASE_PARAM $REVIEWS_PARAM $CHUNKED_PARAM)
|
|
77
85
|
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
|
|
78
86
|
AGENT_SKILLS_RESEARCHER=$(gsd_run query agent-skills gsd-phase-researcher)
|
|
@@ -82,7 +90,7 @@ CONTEXT_WINDOW=$(gsd_run query config-get context_window 2>/dev/null || echo "20
|
|
|
82
90
|
MVP_MODE_CFG=$(gsd_run query config-get workflow.mvp_mode 2>/dev/null || echo "false")
|
|
83
91
|
```
|
|
84
92
|
|
|
85
|
-
When the tdd capability's `workflow.tdd_mode` is active (resolved via the plan:pre render-hooks), the planner agent is instructed to apply `type: tdd` to eligible tasks using heuristics from `references/tdd.md`. The TDD guidance is injected via the tdd capability's contribution hook at §5.6; no inline config-get is needed.
|
|
93
|
+
When the tdd capability's `workflow.tdd_mode` is active (resolved via the plan:pre render-hooks), the planner agent is instructed to apply `type: tdd` to eligible tasks using heuristics from `gsd-core/references/tdd.md`. The TDD guidance is injected via the tdd capability's contribution hook at §5.6; no inline config-get is needed.
|
|
86
94
|
|
|
87
95
|
When `CONTEXT_WINDOW >= 500000`, the planner prompt includes the 3 most recent prior-phase CONTEXT.md/SUMMARY.md files plus any phases in the current phase's `Depends on:` field (explicit deps load regardless of recency).
|
|
88
96
|
|
|
@@ -92,7 +100,7 @@ Parse JSON for: `researcher_model`, `planner_model`, `checker_model`, `research_
|
|
|
92
100
|
|
|
93
101
|
**If `response_language` is set:** All user-facing orchestrator output MUST be in `{response_language}`; technical terms, code, paths, and subagent prompts stay in English. Pass `response_language: {value}` into every spawned subagent prompt.
|
|
94
102
|
|
|
95
|
-
**File paths (for <
|
|
103
|
+
**File paths (for <required_reading> blocks):** `state_path`, `roadmap_path`, `requirements_path`, `context_path`, `research_path`, `verification_path`, `uat_path`, `reviews_path`. These are null if files don't exist.
|
|
96
104
|
|
|
97
105
|
**If `planning_exists` is false:** Error — run `/gsd:new-project` first.
|
|
98
106
|
|
|
@@ -151,7 +159,7 @@ Defer the `phase.mvp-mode` query until `PHASE` is finalized (after explicit argu
|
|
|
151
159
|
```bash
|
|
152
160
|
WALKING_SKELETON=false
|
|
153
161
|
if [ "$MVP_MODE" = "true" ] && [ "$padded_phase" = "01" ]; then
|
|
154
|
-
PRIOR_SUMMARIES=$(gsd_run query phases.list --pick
|
|
162
|
+
PRIOR_SUMMARIES=$(gsd_run query phases.list --type summaries --pick count 2>/dev/null)
|
|
155
163
|
if [ "$PRIOR_SUMMARIES" = "0" ]; then WALKING_SKELETON=true; fi
|
|
156
164
|
fi
|
|
157
165
|
```
|
|
@@ -160,7 +168,7 @@ When `WALKING_SKELETON=true`:
|
|
|
160
168
|
- Planner is instructed to produce `SKELETON.md` in the phase directory alongside `PLAN.md`. The template lives at `~/.claude/gsd-core/references/skeleton-template.md` — the planner reads it when producing SKELETON.md (lazy; not loaded on non-skeleton runs).
|
|
161
169
|
- The plan must scaffold project + routing + one real DB read/write + one real UI interaction + dev deployment — the thinnest possible end-to-end working slice.
|
|
162
170
|
|
|
163
|
-
**Interaction with `--prd <filepath>`.** `--mvp` and `--prd` compose. The PRD express path (Step 3.5) creates `CONTEXT.md` from the PRD file and continues to research; the Walking Skeleton gate fires independently from the conditions above. When both are active on Phase 1 of a new project, the planner receives `WALKING_SKELETON=true` and PRD-derived context simultaneously — the PRD informs *what the skeleton should prove*. No precedence is needed; the two signals are orthogonal. See [`references/mvp-concepts.md`](../references/mvp-concepts.md) for the broader interaction map.
|
|
171
|
+
**Interaction with `--prd <filepath>`.** `--mvp` and `--prd` compose. The PRD express path (Step 3.5) creates `CONTEXT.md` from the PRD file and continues to research; the Walking Skeleton gate fires independently from the conditions above. When both are active on Phase 1 of a new project, the planner receives `WALKING_SKELETON=true` and PRD-derived context simultaneously — the PRD informs *what the skeleton should prove*. No precedence is needed; the two signals are orthogonal. See [`gsd-core/references/mvp-concepts.md`](../references/mvp-concepts.md) for the broader interaction map.
|
|
164
172
|
|
|
165
173
|
Extract express-path args from $ARGUMENTS: `PRD_FILE` (`--prd <filepath>`), `INGEST_PATH` (`--ingest <path-or-glob>`), and optional `INGEST_FORMAT` (`--ingest-format <auto|nygard|madr|narrative>`, default `auto`).
|
|
166
174
|
|
|
@@ -453,7 +461,7 @@ Read the `activeHooks` array directly from `PLAN_PRE_HOOKS_JSON` / `HOOKS_JSON`
|
|
|
453
461
|
- If `ref.agent` is set, dispatch with `Agent(prompt=filled_hook_fragment, subagent_type=ref.agent, model="{researcher_model}")`. Use the hook's `fragment.inline` as the prompt body and fill phase fields before spawning.
|
|
454
462
|
- The `research` hook is handled by §5.1's research decision. The `pattern-mapper` hook is handled by §7.8 after `RESEARCH_PATH` is known. Future plan:pre agent hooks use the same `ref.agent` fragment contract.
|
|
455
463
|
|
|
456
|
-
**AI integration capability:** If the active `ai-integration` step hook is present, `AI_SPEC_PATH` is empty, and the phase goal contains AI keywords (`agent`, `llm`, `rag`, `chatbot`, `embedding`, `langchain`, `llamaindex`, `crewai`, `langgraph`, `openai`, `anthropic`, `vector`, `eval
|
|
464
|
+
**AI integration capability:** If the active `ai-integration` step hook is present, `AI_SPEC_PATH` is empty, and the phase goal contains AI keywords (`agent`, `llm`, `rag`, `chatbot`, `embedding`, `langchain`, `llamaindex`, `crewai`, `langgraph`, `openai`, `anthropic`, `vector`, `llm eval`), then:
|
|
457
465
|
- In pipeline / `--auto` mode, invoke the hook's `ref.skill` via `Skill(skill="gsd-${ref.skill}", args="${PHASE} --auto ${GSD_WS}")`.
|
|
458
466
|
- In manual mode, display the existing non-blocking `/gsd:ai-integration-phase {N}` recommendation and let the user continue planning without AI-SPEC or stop to run the capability workflow first.
|
|
459
467
|
|
|
@@ -483,7 +491,8 @@ Display: `Using UI design contract: ${UI_SPEC_PATH}`. Continue to step 6.
|
|
|
483
491
|
Read the ephemeral auto-chain flag:
|
|
484
492
|
|
|
485
493
|
```bash
|
|
486
|
-
AUTO_CHAIN=$(gsd_run query check auto-mode --pick auto_chain_active 2>/dev/null
|
|
494
|
+
AUTO_CHAIN=$(gsd_run query check auto-mode --pick auto_chain_active 2>/dev/null)
|
|
495
|
+
AUTO_CHAIN="${AUTO_CHAIN:-false}"
|
|
487
496
|
```
|
|
488
497
|
|
|
489
498
|
**Branch 5 — `AUTO_CHAIN` is `true` (pipeline / `--auto`):** Fire each active UI **step** hook — runs independently of whether a gate is active (covers `{ui_phase:true,ui_safety_gate:false}`). For each entry in `activeHooks` (in array order) where `kind == "step"` and `ref.skill` is set:
|
|
@@ -691,7 +700,7 @@ Planner prompt:
|
|
|
691
700
|
**Phase:** {phase_number}
|
|
692
701
|
**Mode:** {standard | gap_closure | reviews}
|
|
693
702
|
|
|
694
|
-
<
|
|
703
|
+
<required_reading>
|
|
695
704
|
- {state_path} (Project State)
|
|
696
705
|
- {roadmap_path} (Roadmap)
|
|
697
706
|
- {requirements_path} (Requirements)
|
|
@@ -715,7 +724,7 @@ ${CONTEXT_WINDOW >= 500000 ? `
|
|
|
715
724
|
- CONTEXT.md, SUMMARY.md, and LEARNINGS.md from any phases listed in the current phase's "Depends on:" field in ROADMAP.md (regardless of recency — explicit dependencies always load, deduplicated against the 3 most recent)
|
|
716
725
|
- Skip all other prior phases to stay within context budget
|
|
717
726
|
` : ''}
|
|
718
|
-
</
|
|
727
|
+
</required_reading>
|
|
719
728
|
${API_SURFACE_PATH ? `
|
|
720
729
|
<intel_surface_hint>
|
|
721
730
|
**API Surface (HINT — may be incomplete):** When \`intel.enabled\` is true, \`${API_SURFACE_PATH}\` lists symbols extracted from the codebase by regex/JS analysis. Prefer symbols listed there when referencing existing code. This surface is regex/JS-derived and MAY BE INCOMPLETE — a symbol's absence means *unknown*, not *nonexistent*. Never treat the surface as exhaustive. If you reference a symbol that is not in the surface and this phase creates it, list it under "Artifacts this phase produces".
|
|
@@ -775,7 +784,7 @@ Output consumed by /gsd:execute-phase. Plans need:
|
|
|
775
784
|
- Tasks in XML format with read_first and acceptance_criteria fields (MANDATORY on every task)
|
|
776
785
|
- Verification criteria
|
|
777
786
|
- must_haves for goal-backward verification
|
|
778
|
-
- If the SPEC has an `## Edge Coverage` section, lift every resolved (verification: explicit) edge's acceptance criterion into `must_haves.truths` as a plain string, and every resolved (verification: backstop) edge **as a structured flat-scalar marker** — an object item `{ statement: <the check>, verification: backstop }`, NOT a prose note (the verifier branches deterministically on the `verification: backstop` field; a parenthetical is unparseable — the #1110 fragility). Use a flat scalar `verification:` continuation key, never a nested object (ADR-550 #1278). At verify time a `backstop` truth the verifier cannot confirm with explicit evidence abstains → `human_needed` (reason `insufficient_spec`), never a silent pass (#1154; see `references/honest-verifier.md`). `unresolved` edges are explicit assumptions — surface them in the plan, do not silently drop them. **Otherwise** (`EDGE_ABSENT`): apply the SAME lift to the fallback report `{COVERAGE}` (per §C of `references/specless-probe-fallback.md`); a SPEC-supplied section is never re-run.
|
|
787
|
+
- If the SPEC has an `## Edge Coverage` section, lift every resolved (verification: explicit) edge's acceptance criterion into `must_haves.truths` as a plain string, and every resolved (verification: backstop) edge **as a structured flat-scalar marker** — an object item `{ statement: <the check>, verification: backstop }`, NOT a prose note (the verifier branches deterministically on the `verification: backstop` field; a parenthetical is unparseable — the #1110 fragility). Use a flat scalar `verification:` continuation key, never a nested object (ADR-550 #1278). At verify time a `backstop` truth the verifier cannot confirm with explicit evidence abstains → `human_needed` (reason `insufficient_spec`), never a silent pass (#1154; see `gsd-core/references/honest-verifier.md`). `unresolved` edges are explicit assumptions — surface them in the plan, do not silently drop them. **Otherwise** (`EDGE_ABSENT`): apply the SAME lift to the fallback report `{COVERAGE}` (per §C of `gsd-core/references/specless-probe-fallback.md`); a SPEC-supplied section is never re-run.
|
|
779
788
|
- If the SPEC has a `## Prohibitions` section, lift every resolved prohibition into the `must_haves.prohibitions:` sibling block (NOT `truths` — ADR-550 D3) with `statement`+`status`+`verification`, via the single `projectProhibitions` serializer (Hyrum — no second serializer); unresolved -> flagged assumptions, don't drop; never put a must-NOT under `truths`. **Otherwise** (`PROHIB_ABSENT`), author the recalled prohibitions into the SAME block via the SAME `projectProhibitions` contract but **descriptor-less** (no `check_*`) so each disposes flagged-unverified; never auto-dismiss. Section-level precedence + no-silent-drop equality apply (§C).
|
|
780
789
|
- If a `-UI-SPEC.md` exists (resolved above as `UI_SPEC_PATH`) with a `## UI Considerations` section, lift it by the **identical rule** as `## Edge Coverage` above — resolved (explicit) → `must_haves.truths` string, resolved (backstop) → flat scalar `{ statement, verification: backstop }`, `unresolved` → explicit planner assumption (no new verb — ADR-550 #1278/#1154; #1867). Read it from `UI_SPEC_PATH` (the SPEC glob excludes `-UI-SPEC.md`).
|
|
781
790
|
- **"Artifacts this phase produces" section (MANDATORY)** — list every symbol this phase creates: decorators, classes, functions, CLI flags, struct/dataclass fields, new file paths. The plan-review-convergence source-grounding pass reads this section to exclude newly-created symbols from drift verification; omitting it causes new symbols to be flagged for acknowledgement.
|
|
@@ -863,7 +872,12 @@ If `section_manifest` is `null` or `"chunked-planning-mode"` is in its `included
|
|
|
863
872
|
**Triggered when:** Agent() returns but the return contains no recognized marker (`## PLANNING COMPLETE`, `## PHASE SPLIT RECOMMENDED`, `## ⚠ Source Audit`, `## CHECKPOINT REACHED`, `## PLANNING INCONCLUSIVE`).
|
|
864
873
|
|
|
865
874
|
```bash
|
|
866
|
-
|
|
875
|
+
# #3218: this asks "did the planner write files to disk at all" — a
|
|
876
|
+
# planner-produced-nothing check, not outstanding-work counting — so it
|
|
877
|
+
# takes the PHYSICAL set (`plan_count_all`, status:superseded INCLUDED): a
|
|
878
|
+
# superseded plan is still a file the planner wrote, and this check must not
|
|
879
|
+
# read "nothing written" just because every plan happens to be superseded.
|
|
880
|
+
DISK_PLANS=$(gsd_run query find-phase "${PHASE_NUMBER}" | jq -r '.plan_count_all // 0')
|
|
867
881
|
```
|
|
868
882
|
|
|
869
883
|
**If `DISK_PLANS` > 0:** The planner wrote plans to disk but the Agent() return was empty or
|
|
@@ -965,14 +979,14 @@ Checker prompt:
|
|
|
965
979
|
**Phase Goal:** {goal from ROADMAP}
|
|
966
980
|
**Mode:** {standard | gap_closure | reviews}
|
|
967
981
|
|
|
968
|
-
<
|
|
982
|
+
<required_reading>
|
|
969
983
|
- {PHASE_DIR}/*-PLAN.md (Plans to verify)
|
|
970
984
|
- {roadmap_path} (Roadmap)
|
|
971
985
|
- {requirements_path} (Requirements)
|
|
972
986
|
- {context_path} (USER DECISIONS from /gsd:discuss-phase)
|
|
973
987
|
- {research_path} (Technical Research — includes Validation Architecture)
|
|
974
988
|
- {reviews_path} (Cross-AI Review Feedback - if --reviews; verify actionable findings are represented in PLAN.md)
|
|
975
|
-
</
|
|
989
|
+
</required_reading>
|
|
976
990
|
|
|
977
991
|
${AGENT_SKILLS_CHECKER}
|
|
978
992
|
|
|
@@ -1037,7 +1051,12 @@ If thinking_partner disabled: skip this block entirely.
|
|
|
1037
1051
|
**Triggered when:** Checker Agent() returns but the return contains neither `## VERIFICATION PASSED` nor `## ISSUES FOUND`.
|
|
1038
1052
|
|
|
1039
1053
|
```bash
|
|
1040
|
-
|
|
1054
|
+
# #3218: this asks "did the planner write files to disk at all" — a
|
|
1055
|
+
# planner-produced-nothing check, not outstanding-work counting — so it
|
|
1056
|
+
# takes the PHYSICAL set (`plan_count_all`, status:superseded INCLUDED): a
|
|
1057
|
+
# superseded plan is still a file the planner wrote, and this check must not
|
|
1058
|
+
# read "nothing written" just because every plan happens to be superseded.
|
|
1059
|
+
DISK_PLANS=$(gsd_run query find-phase "${PHASE_NUMBER}" | jq -r '.plan_count_all // 0')
|
|
1041
1060
|
```
|
|
1042
1061
|
|
|
1043
1062
|
**If `DISK_PLANS` > 0:** Plans exist on disk; the checker return was empty or truncated (the
|
|
@@ -1094,10 +1113,10 @@ Revision prompt:
|
|
|
1094
1113
|
**Phase:** {phase_number}
|
|
1095
1114
|
**Mode:** revision
|
|
1096
1115
|
|
|
1097
|
-
<
|
|
1116
|
+
<required_reading>
|
|
1098
1117
|
- {PHASE_DIR}/*-PLAN.md (Existing plans)
|
|
1099
1118
|
- {context_path} (USER DECISIONS from /gsd:discuss-phase)
|
|
1100
|
-
</
|
|
1119
|
+
</required_reading>
|
|
1101
1120
|
|
|
1102
1121
|
${AGENT_SKILLS_PLANNER}
|
|
1103
1122
|
|
|
@@ -1358,12 +1377,15 @@ Proactive, non-blocking coverage report gated on `workflow.post_planning_gaps`
|
|
|
1358
1377
|
|
|
1359
1378
|
```bash
|
|
1360
1379
|
PLAN_POST_HOOKS_JSON=$(gsd_run loop render-hooks plan:post --raw)
|
|
1361
|
-
PHASE_REQ_IDS=$(gsd_run query init.plan-phase "$PHASE" --pick phase_req_ids 2>/dev/null
|
|
1380
|
+
PHASE_REQ_IDS=$(gsd_run query init.plan-phase "$PHASE" --pick phase_req_ids 2>/dev/null)
|
|
1381
|
+
PHASE_REQ_IDS="${PHASE_REQ_IDS:-TBD}"
|
|
1362
1382
|
```
|
|
1363
1383
|
|
|
1364
1384
|
Read the `activeHooks` array from `PLAN_POST_HOOKS_JSON` in-context. If the
|
|
1365
1385
|
`gap-analysis` gate hook is absent (capability inactive), skip this step.
|
|
1366
1386
|
|
|
1387
|
+
⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`.
|
|
1388
|
+
|
|
1367
1389
|
**For each active entry where `kind == "gate"`** (process in array order). **Dispatch by check shape** (the registry validates exactly one of `query`/`predicate`/`agentVerdict`):
|
|
1368
1390
|
|
|
1369
1391
|
```bash
|
|
@@ -1462,6 +1484,8 @@ Route to `<offer_next>` (existing behavior).
|
|
|
1462
1484
|
<offer_next>
|
|
1463
1485
|
Output this markdown directly (not as a code block):
|
|
1464
1486
|
|
|
1487
|
+
`${GAPS_EXEC_FLAG}` projects the just-completed planning mode onto the follow-up execute command (#3297): it expands to `--gaps-only` for a `--gaps` planning run (so the handoff points at execute-phase's gap-closure scope — only the newly created `gap_closure: true` plans — not the whole phase) and to empty for a standard or `--reviews` run (whole-phase scope, unchanged). Substitute it verbatim; when empty, collapse the extra space.
|
|
1488
|
+
|
|
1465
1489
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1466
1490
|
GSD ► PHASE {X} PLANNED ✓
|
|
1467
1491
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
@@ -1484,7 +1508,7 @@ Verification: {Passed | Passed with override | Skipped}
|
|
|
1484
1508
|
|
|
1485
1509
|
/clear then:
|
|
1486
1510
|
|
|
1487
|
-
/gsd:execute-phase {X} ${GSD_WS}
|
|
1511
|
+
/gsd:execute-phase {X} ${GAPS_EXEC_FLAG} ${GSD_WS}
|
|
1488
1512
|
|
|
1489
1513
|
───────────────────────────────────────────────────────────────
|
|
1490
1514
|
|
|
@@ -156,9 +156,12 @@ Skill(skill="gsd-plan-phase", args="{PHASE} {GSD_WS}")
|
|
|
156
156
|
|
|
157
157
|
Run plan-phase **inline** (do NOT wrap it in Agent()). The convergence orchestrator runs at depth 0 with Agent available, so inline plan-phase can spawn gsd-planner and gsd-plan-checker at depth 1 — the one level of nesting that works on Claude Code. Wrapping plan-phase in Agent() would push it to depth 1 where the Agent tool is absent, preventing it from spawning any sub-agents. Wait until plan-phase completes and PLAN.md files are committed before continuing.
|
|
158
158
|
|
|
159
|
-
After plan-phase completes, verify plans were created
|
|
159
|
+
After plan-phase completes, verify plans were created. This asks "did initial
|
|
160
|
+
planning write files to disk" — a planner-produced-nothing check, not
|
|
161
|
+
outstanding-work counting — so it takes the PHYSICAL set (`plan_count_all`,
|
|
162
|
+
`status: superseded` INCLUDED, #3218):
|
|
160
163
|
```bash
|
|
161
|
-
PLAN_COUNT=$(
|
|
164
|
+
PLAN_COUNT=$(gsd_run query find-phase "${PHASE}" | jq -r '.plan_count_all // 0')
|
|
162
165
|
```
|
|
163
166
|
|
|
164
167
|
If PLAN_COUNT == 0: Error — initial planning failed. Exit.
|
|
@@ -254,6 +257,51 @@ Run this pass unless `plan_review.source_grounding` is `false`. It verifies ever
|
|
|
254
257
|
- Signature mismatches cannot be asserted under `grep`/`intel`; report the signature as UNCHECKABLE.
|
|
255
258
|
5. **Coverage block.** Append a "Verification coverage" section to `REVIEWS.md` listing every UNCHECKABLE/skipped symbol and why — a clean review must never silently mean "nothing was checked."
|
|
256
259
|
|
|
260
|
+
### Cross-artifact fact-drift pass (same gate: `plan_review.source_grounding`)
|
|
261
|
+
|
|
262
|
+
Run this pass whenever the source-grounding pass ran — it is the second axis of the same drift guard, gated by the same `plan_review.source_grounding` key and adding no config surface of its own. Where source-grounding asks *"does this symbol exist in the source?"*, this asks *"does the project state the same fact in two planning artifacts, and do the two disagree?"* Because each phase runs in a fresh context, an agent typically reads only one artifact and trusts it, so a stale duplicate silently steers it wrong.
|
|
263
|
+
|
|
264
|
+
**Key on knowledge, not on similar text.** DRY is about a single authoritative representation of a piece of *knowledge*. Two passages that merely read alike, or that restate one fact at different levels of detail, are NOT drift. Only a contradiction is.
|
|
265
|
+
|
|
266
|
+
1. **Phase status — decided by the seam, not by judgment.** Do not eyeball this axis:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
DRIFT=$(gsd_run drift-guard phase-status --phase "${PHASE}")
|
|
270
|
+
# $DRIFT is JSON: {"verdict":"consistent|lag|drifted|uncheckable","stateStatus":…,"roadmapStatus":…}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
- `drifted` — STATE.md and ROADMAP.md contradict each other. Report it; the authority is STATE.md.
|
|
274
|
+
- `lag` — one lifecycle step apart between non-terminal statuses. NOT a finding.
|
|
275
|
+
- `consistent` — nothing to report.
|
|
276
|
+
- `uncheckable` — a document was absent or carried a status outside both vocabularies. Record it in the coverage block; never read it as consistent.
|
|
277
|
+
|
|
278
|
+
Completeness is terminal: when exactly one side says the phase is complete, the verdict is `drifted` and never `lag`, however few steps apart the two words look.
|
|
279
|
+
|
|
280
|
+
2. **Pair up the remaining facts by judgment.** The authority column names the source of truth, so a finding can say which side to keep:
|
|
281
|
+
|
|
282
|
+
| Fact class | Artifact pair | Authority | Decided by |
|
|
283
|
+
|---|---|---|---|
|
|
284
|
+
| Success criteria / must-have truths | ROADMAP.md Success Criteria ↔ PLAN.md `must_haves.truths` | ROADMAP.md | judgment |
|
|
285
|
+
| Requirement IDs | ROADMAP.md `**Requirements:**` ↔ PLAN.md task requirement refs | ROADMAP.md | judgment |
|
|
286
|
+
| Phase status | STATE.md status ↔ ROADMAP.md phase state | STATE.md | step 1 (deterministic) |
|
|
287
|
+
| Glossary / domain term | CONTEXT.md `Decisions` ↔ PLAN.md usage of the term | CONTEXT.md | judgment |
|
|
288
|
+
|
|
289
|
+
3. **Judge each judgment pair.** FLAG only when ALL THREE hold:
|
|
290
|
+
|
|
291
|
+
1. both sides name the *same* fact — same requirement ID, same success criterion, or the same defined term; and
|
|
292
|
+
2. the two representations *contradict*, one asserting what the other denies, rather than differing in wording or in level of detail; and
|
|
293
|
+
3. the pair is one of the judgment pairs above.
|
|
294
|
+
|
|
295
|
+
4. **Record.** Emit each finding into `REVIEWS.md` beside the source-grounding coverage block, quoting both locations and naming the divergence and the authority, so the author can collapse the two copies to a single source of truth.
|
|
296
|
+
|
|
297
|
+
**Do NOT flag:** a wording-only difference that asserts the same thing; a fact that appears in one artifact only — single-source is the target state, not a finding; a PLAN that ADDS a truth beyond the roadmap Success Criteria, which is sanctioned (plans may add, never subtract); a `lag` verdict from step 1 — two non-terminal statuses a single lifecycle step apart, in either direction, since STATE.md is written at planning time independently of ROADMAP.md and can lead as readily as trail (a disagreement about *completion* is never lag, and step 1 already reports it as `drifted`); anything under CONTEXT.md's `Claude's Discretion` or `Deferred Ideas`, which are non-authoritative by design.
|
|
298
|
+
|
|
299
|
+
**Report once, not twice — these belong to `gsd-plan-checker`:** a PLAN that omits a roadmap Success Criterion is scope reduction (Dimension 7b); a requirement ID the ROADMAP never defines is requirement coverage (Dimension 1); two PLAN.md files in one phase disagreeing is cross-plan data contracts (Dimension 9).
|
|
300
|
+
|
|
301
|
+
**Severity: advisory, never a blocker.** This pass never sets `hardBlock`, and its findings contribute to neither `HIGH_COUNT` nor `ACTIONABLE_COUNT` — a project carrying pre-existing drift must still be able to converge, or an advisory check becomes an endless replan loop.
|
|
302
|
+
|
|
303
|
+
**Coverage, never silence.** If STATE.md or CONTEXT.md is absent, that axis is skipped and the skip is recorded in the same "Verification coverage" block. A clean pass must never mean "nothing was compared."
|
|
304
|
+
|
|
257
305
|
After agent returns, verify REVIEWS.md exists:
|
|
258
306
|
```bash
|
|
259
307
|
REVIEWS_FILE=$(ls ${phase_dir}/${padded_phase}-REVIEWS.md 2>/dev/null)
|
|
@@ -181,8 +181,14 @@ if [ -z "$ROADMAP" ]; then
|
|
|
181
181
|
else
|
|
182
182
|
for PHASE_NUM in $(echo "$ROADMAP" | jq -r '.phases[] | (.number // .phase_number)'); do
|
|
183
183
|
PHASE_DATA=$(echo "$ROADMAP" | jq --arg n "$PHASE_NUM" '.phases[] | select((.number // .phase_number) == ($n | tonumber))')
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
# #3218: $PHASE_DATA is a `.phases[]` entry from `roadmap.analyze`, which
|
|
185
|
+
# emits `plan_count`/`summary_count` SCALARS (src/roadmap.cts) — it has
|
|
186
|
+
# never emitted `.plans`/`.summaries` ARRAYS. Reading those absent keys
|
|
187
|
+
# (even with a `// []` fallback) always produced 0, permanently disabling
|
|
188
|
+
# this resume-incomplete-phase check. Read the scalars the producer
|
|
189
|
+
# actually emits.
|
|
190
|
+
PLAN_COUNT=$(echo "$PHASE_DATA" | jq '.plan_count // 0')
|
|
191
|
+
SUMMARY_COUNT=$(echo "$PHASE_DATA" | jq '.summary_count // 0')
|
|
186
192
|
if [ "${PLAN_COUNT:-0}" -gt "${SUMMARY_COUNT:-0}" ]; then
|
|
187
193
|
INCOMPLETE_PHASE="$PHASE_NUM"
|
|
188
194
|
break
|
|
@@ -213,11 +219,13 @@ Then exit the route step. Do NOT run Steps 1 through Routes A-F.
|
|
|
213
219
|
|
|
214
220
|
**Step 1: Count plans, summaries, and issues in current phase**
|
|
215
221
|
|
|
216
|
-
|
|
222
|
+
Get plan/summary counts for the current phase from the single owner (#3218 — LIVE
|
|
223
|
+
counts, i.e. `status: superseded` plans excluded, matching "outstanding work"):
|
|
217
224
|
|
|
218
225
|
```bash
|
|
219
|
-
(
|
|
220
|
-
(
|
|
226
|
+
PHASE_COUNTS=$(gsd_run query find-phase "${CURRENT_PHASE}")
|
|
227
|
+
X=$(echo "$PHASE_COUNTS" | jq -r '.plan_count // 0')
|
|
228
|
+
Y=$(echo "$PHASE_COUNTS" | jq -r '.summary_count // 0')
|
|
221
229
|
(ls -1 .planning/phases/[current-phase-dir]/*-UAT.md 2>/dev/null || true) | wc -l
|
|
222
230
|
```
|
|
223
231
|
|
|
@@ -450,7 +458,17 @@ UAT.md exists with `status: partial` — testing session ended before all items
|
|
|
450
458
|
All plans have summaries, but canonical verification has not passed. The phase is implementation-complete, not phase-complete.
|
|
451
459
|
|
|
452
460
|
```
|
|
453
|
-
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Verification Report Missing
|
|
464
|
+
|
|
465
|
+
**Phase {phase}** has all plans summarized, but no canonical `*-VERIFICATION.md` exists yet. ${VERIFICATION_NEXT_ACTION}
|
|
466
|
+
|
|
467
|
+
`/clear` then:
|
|
468
|
+
|
|
469
|
+
`/gsd:execute-phase {phase} ${GSD_WS}` — resumes at the verification gates
|
|
470
|
+
|
|
471
|
+
---
|
|
454
472
|
```
|
|
455
473
|
|
|
456
474
|
---
|
|
@@ -460,7 +478,17 @@ All plans have summaries, but canonical verification has not passed. The phase i
|
|
|
460
478
|
VERIFICATION.md has an unexpected status. The phase is implementation-complete, not phase-complete.
|
|
461
479
|
|
|
462
480
|
```
|
|
481
|
+
---
|
|
482
|
+
|
|
483
|
+
## Verification Status Unexpected
|
|
484
|
+
|
|
485
|
+
**Phase {phase}** has all plans summarized, but its `*-VERIFICATION.md` reports an unexpected status. ${VERIFICATION_NEXT_ACTION}
|
|
486
|
+
|
|
487
|
+
`/clear` then:
|
|
488
|
+
|
|
463
489
|
`/gsd:execute-phase {phase} ${GSD_WS}` — regenerate verification
|
|
490
|
+
|
|
491
|
+
---
|
|
464
492
|
```
|
|
465
493
|
|
|
466
494
|
---
|
|
@@ -18,9 +18,9 @@ Checker prompt:
|
|
|
18
18
|
**Mode:** quick-full
|
|
19
19
|
**Task Description:** ${DESCRIPTION}
|
|
20
20
|
|
|
21
|
-
<
|
|
21
|
+
<required_reading>
|
|
22
22
|
- ${QUICK_DIR}/${quick_id}-PLAN.md (Plan to verify)
|
|
23
|
-
</
|
|
23
|
+
</required_reading>
|
|
24
24
|
|
|
25
25
|
${AGENT_SKILLS_CHECKER}
|
|
26
26
|
|
|
@@ -74,9 +74,9 @@ Revision prompt:
|
|
|
74
74
|
<revision_context>
|
|
75
75
|
**Mode:** quick-full (revision)
|
|
76
76
|
|
|
77
|
-
<
|
|
77
|
+
<required_reading>
|
|
78
78
|
- ${QUICK_DIR}/${quick_id}-PLAN.md (Existing plan)
|
|
79
|
-
</
|
|
79
|
+
</required_reading>
|
|
80
80
|
|
|
81
81
|
${AGENT_SKILLS_PLANNER}
|
|
82
82
|
|
|
@@ -17,9 +17,9 @@ Agent(
|
|
|
17
17
|
Task directory: ${QUICK_DIR}
|
|
18
18
|
Task goal: ${DESCRIPTION}
|
|
19
19
|
|
|
20
|
-
<
|
|
20
|
+
<required_reading>
|
|
21
21
|
- ${QUICK_DIR}/${quick_id}-PLAN.md (Plan)
|
|
22
|
-
</
|
|
22
|
+
</required_reading>
|
|
23
23
|
|
|
24
24
|
${AGENT_SKILLS_VERIFIER}
|
|
25
25
|
|
|
@@ -32,15 +32,36 @@ Check must_haves against actual codebase. Create VERIFICATION.md at ${QUICK_DIR}
|
|
|
32
32
|
|
|
33
33
|
> **ORCHESTRATOR RULE — CODEX RUNTIME**: After calling Agent() above, stop working on this task immediately. Do not read more files, edit code, or run tests related to this task while the subagent is active. Wait for the subagent to return its result. This prevents duplicate work, conflicting edits, and wasted context. Only resume when the subagent result is available.
|
|
34
34
|
|
|
35
|
-
Read verification status:
|
|
35
|
+
Read verification status via the canonical query (frontmatter-anchored, and total over its input space):
|
|
36
36
|
```bash
|
|
37
|
-
|
|
37
|
+
_GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; if [ -f "$GSD_TOOLS" ]; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif command -v gsd-tools >/dev/null 2>&1; then GSD_TOOLS="$(command -v gsd-tools)"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif [ -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; elif [ -f "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}" ]; then GSD_TOOLS="${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd-tools is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi
|
|
38
|
+
STATUS=$(gsd_run query verification.status "${QUICK_DIR}" --pick status 2>/dev/null)
|
|
38
39
|
```
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
`--pick status` returns the bare value, so this path needs **no `jq`**. That is deliberate: #2589
|
|
42
|
+
established that a `| jq -r '.field'` pipe yields an **empty** variable with no diagnostic on any
|
|
43
|
+
machine without jq — the default on Windows/Git-Bash — which here would route a perfectly good
|
|
44
|
+
`passed` verification into the recovery arm below.
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
Route on `$STATUS` and store the display string as `$VERIFICATION_STATUS` (consumed by the quick index row and the completion banner).
|
|
47
|
+
|
|
48
|
+
The query is **total**: beyond the verifier's own statuses it can also return `missing` (no `*-VERIFICATION.md`, or no `status` in its frontmatter), `unknown` (a value outside the verifier's schema) or `stale` (a summary newer than the verification file). Which one wins when more than one applies is the query's own precedence, not this table's concern — all three land in the same arm here. That arm is reachable in normal operation and must never be dropped.
|
|
49
|
+
|
|
50
|
+
| `$STATUS` | Action |
|
|
43
51
|
|--------|--------|
|
|
44
52
|
| `passed` | Store `$VERIFICATION_STATUS = "Verified"`, continue to step 7 |
|
|
45
53
|
| `human_needed` | Display items needing manual check, store `$VERIFICATION_STATUS = "Needs Review"`, continue |
|
|
46
54
|
| `gaps_found` | Display gap summary, offer: 1) Re-run executor to fix gaps, 2) Accept as-is. Store `$VERIFICATION_STATUS = "Gaps"` |
|
|
55
|
+
| anything else — `missing`, `unknown`, `stale`, or empty | Do **not** improvise a result. Report that verification produced no usable status, naming `$STATUS`, then offer: 1) Re-run the verifier, 2) Accept as-is without verification. Store `$VERIFICATION_STATUS = "Unverified (${STATUS:-no result})"` |
|
|
56
|
+
|
|
57
|
+
> **Why the status only, and not `next_action` / `next_command`.** The query projects those two for
|
|
58
|
+
> the phase pipeline — they name `execute-phase`, `plan-phase --gaps` and `verify-work`, and they
|
|
59
|
+
> append a phase-number argument taken from the directory basename. A quick task directory is named
|
|
60
|
+
> `${quick_id}-${slug}` with a date-derived `quick_id`, so that argument resolves to the date: for
|
|
61
|
+
> `260808-abc-some-slug` the projected recovery command carries `260808` as its phase argument — a
|
|
62
|
+
> date posing as a phase number.
|
|
63
|
+
> Quick therefore supplies its own recovery actions above. The split is the point:
|
|
64
|
+
> `readVerificationStatus` *discovers and parses* shape-agnostically — it scans whatever directory
|
|
65
|
+
> it is given for `*-VERIFICATION.md` — which is what makes the status half correct for
|
|
66
|
+
> `${QUICK_DIR}`; but it also reads that directory's basename as a phase token to build the
|
|
67
|
+
> projected commands, and that is the half quick must not use.
|