@opengsd/gsd-core 1.9.1 → 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 +2 -3
- package/.opencode/plugins/gsd-core.js +8 -1
- package/agents/gsd-code-fixer.md +27 -3
- package/agents/gsd-debug-session-manager.md +11 -0
- package/agents/gsd-debugger.md +12 -246
- package/agents/gsd-doc-synthesizer.md +2 -4
- package/agents/gsd-executor.md +12 -10
- package/agents/gsd-integration-checker.md +3 -0
- package/agents/gsd-mempalace-curator.md +5 -2
- package/agents/gsd-phase-researcher.md +20 -1
- package/agents/gsd-plan-checker.md +46 -0
- package/agents/gsd-planner.md +49 -54
- package/agents/gsd-roadmapper.md +21 -3
- package/agents/gsd-user-profiler.md +3 -0
- package/agents/gsd-verifier.md +26 -73
- package/bin/install.js +1272 -1238
- 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 +2 -2
- package/commands/gsd/mempalace-recall.md +1 -1
- package/commands/gsd/new-milestone.md +2 -2
- package/commands/gsd/plan-phase.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 +1009 -115
- package/gsd-core/bin/lib/active-workstream-store.cjs +153 -12
- package/gsd-core/bin/lib/agent-install-check.cjs +268 -38
- package/gsd-core/bin/lib/api-coverage.cjs +123 -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 +926 -202
- package/gsd-core/bin/lib/broken-windows.cjs +36 -6
- 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 +608 -148
- 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 +507 -24
- package/gsd-core/bin/lib/capability-writer.cjs +3 -2
- package/gsd-core/bin/lib/check-command-router.cjs +114 -38
- 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 +94 -0
- package/gsd-core/bin/lib/command-roster.cjs +44 -1
- package/gsd-core/bin/lib/commands.cjs +665 -99
- package/gsd-core/bin/lib/commonjs-marker.cjs +142 -0
- package/gsd-core/bin/lib/complexity-trigger.cjs +1172 -0
- package/gsd-core/bin/lib/config-loader.cjs +76 -0
- package/gsd-core/bin/lib/config.cjs +22 -2
- package/gsd-core/bin/lib/context-composer.cjs +278 -0
- package/gsd-core/bin/lib/context-predicates.cjs +506 -0
- package/gsd-core/bin/lib/core-utils.cjs +217 -40
- package/gsd-core/bin/lib/decisions.cjs +23 -0
- package/gsd-core/bin/lib/docs.cjs +3 -2
- package/gsd-core/bin/lib/external-job.cjs +19 -4
- package/gsd-core/bin/lib/fallow-runner.cjs +20 -44
- package/gsd-core/bin/lib/frontmatter.cjs +239 -32
- package/gsd-core/bin/lib/gap-checker.cjs +68 -7
- package/gsd-core/bin/lib/gate-predicate-evaluator.cjs +57 -6
- package/gsd-core/bin/lib/git-base-branch.cjs +160 -15
- package/gsd-core/bin/lib/graphify.cjs +142 -27
- package/gsd-core/bin/lib/gsd2-import.cjs +37 -5
- 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-integration.cjs +13 -1
- package/gsd-core/bin/lib/host-runtime-detection.cjs +134 -0
- package/gsd-core/bin/lib/init-command-router.cjs +83 -8
- package/gsd-core/bin/lib/init.cjs +1325 -169
- package/gsd-core/bin/lib/install-effort-resolver.cjs +73 -30
- package/gsd-core/bin/lib/install-engine.cjs +805 -264
- 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 +160 -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-migration-authoring.cjs +3 -1
- package/gsd-core/bin/lib/installer-migration-report.cjs +4 -0
- package/gsd-core/bin/lib/installer-migrations/007-retire-config-root-commonjs-marker.cjs +149 -0
- package/gsd-core/bin/lib/installer-migrations/008-cursor-retire-commands-surface.cjs +55 -0
- package/gsd-core/bin/lib/installer-migrations/009-pi-retire-reserved-hooks-dir.cjs +199 -0
- package/gsd-core/bin/lib/installer-migrations.cjs +206 -13
- package/gsd-core/bin/lib/io.cjs +38 -3
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +8 -1
- package/gsd-core/bin/lib/markdown-table.cjs +133 -20
- package/gsd-core/bin/lib/mcp-catalog.cjs +518 -0
- package/gsd-core/bin/lib/mcp-server.cjs +135 -3
- package/gsd-core/bin/lib/milestone-lock.cjs +248 -0
- package/gsd-core/bin/lib/milestone.cjs +821 -109
- 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 +507 -36
- package/gsd-core/bin/lib/phase-lifecycle.cjs +28 -3
- package/gsd-core/bin/lib/phase-locator.cjs +258 -58
- package/gsd-core/bin/lib/phase.cjs +891 -156
- package/gsd-core/bin/lib/plan-dependency-graph.cjs +303 -0
- 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 +60 -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/prompt-budget.cjs +128 -165
- package/gsd-core/bin/lib/refactor-trigger-command-router.cjs +740 -0
- package/gsd-core/bin/lib/retired-artifact-cleanup.cjs +85 -0
- package/gsd-core/bin/lib/review-lane-descriptor.cjs +108 -0
- package/gsd-core/bin/lib/review-lane-invocation.cjs +30 -0
- package/gsd-core/bin/lib/review-lane-runner.cjs +447 -68
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +13 -18
- package/gsd-core/bin/lib/roadmap-command-router.cjs +76 -9
- package/gsd-core/bin/lib/roadmap-parser.cjs +1035 -194
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +37 -10
- package/gsd-core/bin/lib/roadmap.cjs +405 -84
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +795 -100
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +14 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +440 -57
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +3 -2
- package/gsd-core/bin/lib/runtime-homes.cjs +220 -41
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +220 -44
- 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/section-manifest.cjs +209 -0
- package/gsd-core/bin/lib/security.cjs +104 -5
- package/gsd-core/bin/lib/shell-command-projection.cjs +388 -30
- package/gsd-core/bin/lib/smart-entry.cjs +154 -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 +424 -105
- package/gsd-core/bin/lib/state.cjs +1927 -401
- package/gsd-core/bin/lib/surface.cjs +35 -10
- 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 +20 -4
- package/gsd-core/bin/lib/uat.cjs +706 -64
- 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 +33 -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 +287 -20
- package/gsd-core/bin/lib/verify.cjs +368 -880
- package/gsd-core/bin/lib/workflow-fragments.cjs +557 -0
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +203 -19
- package/gsd-core/bin/lib/workstream-inventory.cjs +576 -31
- package/gsd-core/bin/lib/workstream.cjs +8 -2
- package/gsd-core/bin/lib/worktree-base-ref.cjs +50 -6
- package/gsd-core/bin/lib/worktree-safety.cjs +450 -125
- package/gsd-core/bin/shared/config-defaults.manifest.json +1 -0
- package/gsd-core/bin/shared/config-schema.manifest.json +9 -1
- package/gsd-core/references/agent-contracts.md +43 -26
- package/gsd-core/references/artifact-types.md +10 -3
- package/gsd-core/references/autonomous-ui-design-contract.md +42 -0
- package/gsd-core/references/checkpoints.md +2 -2
- package/gsd-core/references/context-budget.md +1 -1
- package/gsd-core/references/debugger-techniques.md +255 -0
- 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/research-documentation-lookup.md +5 -3
- package/gsd-core/references/revision-loop.md +1 -1
- package/gsd-core/references/specless-probe-fallback.md +8 -7
- package/gsd-core/references/universal-anti-patterns.md +3 -3
- package/gsd-core/references/verifier-phase-gates.md +192 -0
- package/gsd-core/references/verifier-wiring-patterns.md +100 -0
- package/gsd-core/references/verify-mvp-mode.md +1 -1
- package/gsd-core/references/workstream-flag.md +22 -6
- package/gsd-core/references/worktree-branch-check.md +2 -2
- 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/summary-complex.md +2 -0
- package/gsd-core/templates/summary-minimal.md +2 -0
- package/gsd-core/templates/summary-standard.md +2 -0
- package/gsd-core/templates/summary.md +2 -0
- package/gsd-core/templates/verification-report.md +9 -1
- package/gsd-core/workflows/ai-integration-phase.md +9 -11
- package/gsd-core/workflows/audit-milestone.md +3 -0
- package/gsd-core/workflows/autonomous/steps/converge-banner.md +1 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-bg.md +11 -0
- package/gsd-core/workflows/autonomous/steps/converge-dispatch-inline.md +7 -0
- package/gsd-core/workflows/autonomous/steps/converge-fail-fast.md +21 -0
- package/gsd-core/workflows/autonomous/steps/converge-loop.md +7 -0
- package/gsd-core/workflows/autonomous.md +33 -70
- package/gsd-core/workflows/cleanup.md +62 -3
- package/gsd-core/workflows/code-review/steps/dispatch-fix.md +39 -0
- package/gsd-core/workflows/code-review/steps/structural-pre-pass.md +93 -0
- package/gsd-core/workflows/code-review-fix.md +37 -10
- package/gsd-core/workflows/code-review.md +74 -166
- package/gsd-core/workflows/complete-milestone/steps/git-tag.md +29 -0
- package/gsd-core/workflows/complete-milestone.md +160 -95
- package/gsd-core/workflows/debug.md +16 -17
- package/gsd-core/workflows/diagnose-issues.md +56 -8
- 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/steps/auto-advance-dispatch.md +15 -0
- package/gsd-core/workflows/discuss-phase-assumptions.md +7 -17
- package/gsd-core/workflows/docs-update/steps/dispatch-monorepo-packages.md +51 -0
- package/gsd-core/workflows/docs-update.md +8 -51
- 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 +64 -7
- package/gsd-core/workflows/execute-phase/steps/gap-closure-artifacts.md +50 -0
- package/gsd-core/workflows/execute-phase/steps/partial-wave.md +31 -0
- 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 +21 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate-run.md +42 -0
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +43 -37
- package/gsd-core/workflows/execute-phase.md +103 -187
- 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/help/modes/full.md +6 -1
- package/gsd-core/workflows/import.md +4 -4
- package/gsd-core/workflows/ingest-docs.md +7 -6
- package/gsd-core/workflows/mvp-phase.md +6 -3
- package/gsd-core/workflows/new-milestone/steps/project-md-milestone-write.md +16 -0
- package/gsd-core/workflows/new-milestone/steps/reset-phase-safety.md +19 -0
- package/gsd-core/workflows/new-milestone.md +35 -47
- package/gsd-core/workflows/new-project/steps/auto-mode-config.md +176 -0
- package/gsd-core/workflows/new-project/steps/auto-mode-detection.md +32 -0
- package/gsd-core/workflows/new-project/steps/codebase-map-offer.md +18 -0
- package/gsd-core/workflows/new-project.md +27 -240
- package/gsd-core/workflows/next.md +12 -0
- package/gsd-core/workflows/plan-phase/steps/adr-ingest-express-path.md +15 -0
- package/gsd-core/workflows/plan-phase/steps/chunked-planning-mode.md +110 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-gate.md +8 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-early-exit.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/research-only-modifiers.md +16 -0
- package/gsd-core/workflows/plan-phase/steps/reviews-prerequisite.md +17 -0
- package/gsd-core/workflows/plan-phase/steps/stall-detection-helpers.md +149 -0
- package/gsd-core/workflows/plan-phase.md +89 -209
- package/gsd-core/workflows/plan-review-convergence.md +50 -2
- package/gsd-core/workflows/progress/steps/forensic-audit.md +125 -0
- package/gsd-core/workflows/progress/steps/mvp-display.md +18 -0
- package/gsd-core/workflows/progress.md +45 -159
- package/gsd-core/workflows/quick/steps/discussion-phase.md +124 -0
- package/gsd-core/workflows/quick/steps/plan-checker-loop.md +111 -0
- package/gsd-core/workflows/quick/steps/quick-verification.md +67 -0
- package/gsd-core/workflows/quick/steps/research-phase.md +72 -0
- package/gsd-core/workflows/quick/steps/worktree-pre-dispatch-commit.md +37 -0
- package/gsd-core/workflows/quick.md +55 -405
- package/gsd-core/workflows/resume-project.md +3 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-1.md +4 -0
- package/gsd-core/workflows/review/steps/reviewer-instances-note-2.md +3 -0
- package/gsd-core/workflows/review.md +41 -13
- package/gsd-core/workflows/section-manifest.json +219 -0
- 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/sketch.md +1 -1
- package/gsd-core/workflows/spec-phase.md +41 -20
- package/gsd-core/workflows/spike-wrap-up.md +20 -5
- package/gsd-core/workflows/spike.md +50 -16
- package/gsd-core/workflows/sync-skills.md +106 -13
- package/gsd-core/workflows/transition/steps/workstream-collision-check.md +17 -0
- package/gsd-core/workflows/transition.md +53 -31
- package/gsd-core/workflows/ui-phase.md +13 -12
- package/gsd-core/workflows/ui-review.md +2 -2
- package/gsd-core/workflows/update/steps/channel-banner.md +7 -0
- package/gsd-core/workflows/update.md +19 -8
- package/gsd-core/workflows/validate-phase.md +1 -1
- package/gsd-core/workflows/verify-work/steps/automated-ui-verification.md +36 -0
- package/gsd-core/workflows/verify-work/steps/mvp-uat-framing.md +21 -0
- package/gsd-core/workflows/verify-work.md +17 -65
- package/hooks/dist/gsd-agent-isolation-guard.js +517 -0
- package/hooks/dist/gsd-check-update-worker.js +64 -12
- 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 +607 -26
- 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 +45 -24
- package/hooks/dist/gsd-statusline.js +90 -6
- package/hooks/dist/gsd-update-banner.js +22 -1
- package/hooks/dist/gsd-workflow-guard.js +134 -36
- package/hooks/dist/gsd-worktree-path-guard.js +2 -1
- package/hooks/dist/gsd-write-guard.js +359 -0
- 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 +277 -0
- package/hooks/dist/managed-hooks-registry.cjs +2 -0
- package/hooks/gsd-agent-isolation-guard.js +517 -0
- package/hooks/gsd-check-update-worker.js +64 -12
- package/hooks/gsd-check-update.js +19 -1
- package/hooks/gsd-cursor-pre-tool.js +0 -3
- package/hooks/gsd-cursor-subagent-start.js +607 -26
- package/hooks/gsd-cursor-subagent-stop.js +3 -2
- package/hooks/gsd-prompt-guard.js +21 -20
- package/hooks/gsd-read-injection-scanner.js +45 -24
- package/hooks/gsd-statusline.js +90 -6
- package/hooks/gsd-update-banner.js +22 -1
- package/hooks/gsd-workflow-guard.js +134 -36
- package/hooks/gsd-worktree-path-guard.js +2 -1
- package/hooks/gsd-write-guard.js +359 -0
- package/hooks/hooks.json +12 -0
- 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 +277 -0
- package/hooks/managed-hooks-registry.cjs +2 -0
- package/package.json +31 -10
- package/pi/gsd.cjs +71 -12
- 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/build-hooks.js +9 -0
- package/scripts/changeset/lint.cjs +68 -6
- package/scripts/changeset/serialize.cjs +5 -1
- 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-matrix.cjs +1 -1
- package/scripts/gen-capability-registry.cjs +3 -15
- package/scripts/gen-context-index.cjs +439 -0
- package/scripts/gen-health-docs.cjs +390 -0
- package/scripts/gen-inventory-manifest.cjs +150 -4
- package/scripts/gen-loop-host-contract.cjs +4 -24
- package/scripts/gen-prompt-budget-parity-corpus.cjs +645 -0
- package/scripts/gen-registry.cjs +3 -14
- package/scripts/gen-section-manifest.cjs +638 -0
- package/scripts/generate-package-identity.cjs +4 -2
- 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 +15 -54
- 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-compiled-artifact-sync.cjs +6 -1
- 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-docs-command-form.cjs +195 -0
- package/scripts/lint-docs-required.cjs +9 -1
- package/scripts/lint-emitted-drift-ack.cjs +215 -20
- package/scripts/lint-eslint-glob-coverage.allowlist.json +34 -0
- package/scripts/lint-eslint-glob-coverage.cjs +340 -0
- package/scripts/lint-example-parser-parity.cjs +395 -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 +40 -3
- package/scripts/lint-unreachable-guard-drift.cjs +843 -0
- package/scripts/lint-vendored-deps.cjs +124 -0
- package/scripts/mutation-matrix.cjs +13 -0
- package/scripts/pr-changed-files.cjs +63 -0
- package/scripts/pr-template-policy.cjs +14 -4
- package/scripts/prompt-injection-scan.sh +52 -6
- 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 +2 -2
- package/skills/gsd-mempalace-recall/SKILL.md +1 -1
- package/skills/gsd-new-milestone/SKILL.md +2 -2
- package/skills/gsd-next/SKILL.md +0 -1
- package/skills/gsd-plan-phase/SKILL.md +1 -2
- 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 -577
- package/scripts/affected-tests-lib.cjs +0 -554
- package/scripts/gen-emitted-baseline.cjs +0 -145
- package/scripts/lint-allow-test-rule-refs.cjs +0 -162
- package/scripts/run-affected-tests.cjs +0 -7
- package/scripts/run-tests.cjs +0 -1050
|
@@ -55,14 +55,14 @@ Verify the work is ready to ship:
|
|
|
55
55
|
# The gate decides on ONE read. --pick takes a single field, so the two
|
|
56
56
|
# human-facing fields are read only on the blocking path below — never on the
|
|
57
57
|
# passing path — rather than issuing three queries up front (#2589).
|
|
58
|
-
STATUS=$(gsd_run query verification.status "${PHASE_DIR}" --pick status 2>/dev/null
|
|
58
|
+
STATUS=$(gsd_run query verification.status "${PHASE_DIR}" --pick status 2>/dev/null)
|
|
59
59
|
```
|
|
60
60
|
Only `passed` may ship. If `$STATUS` is `passed`, verification is complete — continue to the next preflight check; do not read any further verification field.
|
|
61
61
|
|
|
62
62
|
Any other value (including `gaps_found`, `human_needed`, `missing`, and `unknown`) blocks with `PHASE_VERIFICATION_INCOMPLETE`. Only then, read the two message fields:
|
|
63
63
|
```bash
|
|
64
|
-
NEXT_ACTION=$(gsd_run query verification.status "${PHASE_DIR}" --pick next_action 2>/dev/null
|
|
65
|
-
NEXT_COMMAND=$(gsd_run query verification.status "${PHASE_DIR}" --pick next_command 2>/dev/null
|
|
64
|
+
NEXT_ACTION=$(gsd_run query verification.status "${PHASE_DIR}" --pick next_action 2>/dev/null)
|
|
65
|
+
NEXT_COMMAND=$(gsd_run query verification.status "${PHASE_DIR}" --pick next_command 2>/dev/null)
|
|
66
66
|
```
|
|
67
67
|
Present `$NEXT_ACTION` to the user and, when `$NEXT_COMMAND` is non-empty, show it as the command to run next. These two are message text only — the block/allow decision has already been made from `$STATUS`, so a concurrent write between the reads cannot change the gate's verdict. The query already handles missing files and unexpected values, so no per-status arm is needed.
|
|
68
68
|
|
|
@@ -91,9 +91,9 @@ Verify the work is ready to ship:
|
|
|
91
91
|
```
|
|
92
92
|
If `gh` not found or not authenticated: provide setup instructions and exit.
|
|
93
93
|
|
|
94
|
-
6. **
|
|
94
|
+
6. **Capability ship gates (generic dispatch).**
|
|
95
95
|
|
|
96
|
-
Resolve active `ship:pre` gate hooks from the capability registry — the registry evaluates each hook's `when` condition, so do **not** read `workflow.security_enforcement` directly:
|
|
96
|
+
Resolve active `ship:pre` gate hooks from the capability registry — the registry evaluates each hook's `when` condition, so do **not** read `workflow.security_enforcement` or `workflow.windows_enforce` directly:
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
SHIP_PRE_HOOKS_JSON=$(gsd_run loop render-hooks ship:pre --raw)
|
|
@@ -102,57 +102,83 @@ Verify the work is ready to ship:
|
|
|
102
102
|
|
|
103
103
|
Read the `activeHooks` array from `SHIP_PRE_HOOKS_JSON` in-context (do NOT pipe it through a shell parser).
|
|
104
104
|
|
|
105
|
-
If
|
|
105
|
+
**If `activeHooks` is empty or absent:** skip this check silently and continue to the next preflight step. A capability whose `when` is off contributes no entry, and one that failed to load fails OPEN with its own warning from the resolver — neither is a block.
|
|
106
106
|
|
|
107
|
-
-
|
|
108
|
-
```
|
|
109
|
-
⚠ Security enforcement is enabled but no SECURITY.md exists for this phase.
|
|
110
|
-
Run /gsd:secure-phase {phase} and resolve findings before shipping.
|
|
111
|
-
```
|
|
112
|
-
- **`SECURITY_FILE` exists** → read its frontmatter `threats_open`. The gate passes **only** when `threats_open` is exactly `0`. For any other value — `threats_open` > 0, or a missing / non-numeric / unparsable field — **fail closed and block** with `SECURITY_SHIP_GATE_OPEN_THREATS` (the predicate is strict equality to `0`; never ship on an ambiguous value):
|
|
113
|
-
```
|
|
114
|
-
⚠ Security ship gate: SECURITY.md does not assert threats_open == 0 (found: {threats_open|unset}).
|
|
115
|
-
Resolve open threats (or re-run /gsd:secure-phase {phase}) before shipping.
|
|
116
|
-
```
|
|
107
|
+
**For each active entry where `kind == "gate"`** (process in array order), following `gsd-core/references/loop-hook-dispatch.md`. Entries of any other `kind` are not gates and are not enforced here. Every gate is visited exactly once by this loop — the named branches below are specializations *within* it, never a separate pass, so no gate is evaluated twice.
|
|
117
108
|
|
|
118
|
-
|
|
109
|
+
**Step 1 — evaluate the gate's `check`.** Dispatch by check shape; read the hook's `check` object in-context to pick the branch (the registry validates exactly one of `query`/`predicate`/`agentVerdict`). Two capability IDs carry a bespoke evaluation whose fail-closed semantics the declared predicate alone does not reproduce — take their branch, then rejoin at step 2:
|
|
119
110
|
|
|
120
|
-
|
|
111
|
+
- **`capId == "security"`** — enforce against `SECURITY_FILE`:
|
|
112
|
+
- **`SECURITY_FILE` is empty** → `block: true`, `SECURITY_SHIP_GATE_NO_REVIEW`:
|
|
113
|
+
```
|
|
114
|
+
⚠ Security enforcement is enabled but no SECURITY.md exists for this phase.
|
|
115
|
+
Run /gsd:secure-phase {phase} and resolve findings before shipping.
|
|
116
|
+
```
|
|
117
|
+
- **`SECURITY_FILE` exists** → read its frontmatter `threats_open`. The gate passes **only** when `threats_open` is exactly `0`. For any other value — `threats_open` > 0, or a missing / non-numeric / unparsable field — **fail closed** with `block: true` and `SECURITY_SHIP_GATE_OPEN_THREATS` (the predicate is strict equality to `0`; never ship on an ambiguous value):
|
|
118
|
+
```
|
|
119
|
+
⚠ Security ship gate: SECURITY.md does not assert threats_open == 0 (found: {threats_open|unset}).
|
|
120
|
+
Resolve open threats (or re-run /gsd:secure-phase {phase}) before shipping.
|
|
121
|
+
```
|
|
121
122
|
|
|
122
|
-
|
|
123
|
+
- **`capId == "broken-windows"`** (issue #1950) — enforce against the ledger's typed status. The ledger lives at the **project root** (cross-phase, not phase-scoped):
|
|
123
124
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
'
|
|
127
|
-
|
|
128
|
-
```
|
|
125
|
+
```bash
|
|
126
|
+
WINDOWS_STATUS_JSON=$(gsd_run windows status --raw 2>/dev/null || echo '')
|
|
127
|
+
WINDOWS_OPEN_COUNT=$(printf '%s' "$WINDOWS_STATUS_JSON" | jq -r '.ledger.open_count // "?"' 2>/dev/null || echo '?')
|
|
128
|
+
```
|
|
129
129
|
|
|
130
|
-
|
|
130
|
+
- **`WINDOWS_OPEN_COUNT == "0"`** → `block: false`; the gate passes.
|
|
131
|
+
- **`WINDOWS_OPEN_COUNT` is a positive integer** → `block: true`, `WINDOWS_SHIP_GATE_OPEN`:
|
|
132
|
+
```
|
|
133
|
+
⚠ Broken-windows ship gate: WINDOWS.md has {WINDOWS_OPEN_COUNT} open window(s).
|
|
134
|
+
Resolve each entry before shipping, or explicitly waive with a recorded reason:
|
|
135
|
+
gsd_run windows fixed <id> # defect resolved
|
|
136
|
+
gsd_run windows waive <id> "<reason>" # justified deferral (reason required)
|
|
137
|
+
Then re-run /gsd:ship.
|
|
138
|
+
```
|
|
139
|
+
- **`WINDOWS_OPEN_COUNT` is `"?"`, empty, or non-numeric** → **fail closed** with `block: true` and `WINDOWS_SHIP_GATE_READ_FAILED` (the gate is strict equality to `0`; never ship on an unreadable ledger):
|
|
140
|
+
```
|
|
141
|
+
⚠ Broken-windows ship gate: could not read open_count from .planning/WINDOWS.md.
|
|
142
|
+
Inspect the file or run `gsd_run windows status --raw` to diagnose. The ledger
|
|
143
|
+
may be malformed; fix it before shipping (an unparseable ledger is a broken window).
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
The ledger is **optional and backward-compatible**: on a project where `gsd_run windows status` returns `open_count: 0` (no `.planning/WINDOWS.md` yet, or an empty ledger), the gate passes silently. It only blocks when at least one entry is `open`.
|
|
147
|
+
|
|
148
|
+
- **Every other `capId`** — run the gate's own declared check through the generic evaluator. This arm is what makes a third-party capability's declared gate enforceable at all (#3559); before it existed, a gate whose `capId` was not named above was resolved and then silently dropped.
|
|
149
|
+
|
|
150
|
+
⚠ **Validate `check` before shell use** (third-party manifest input) — `loop-hook-dispatch.md` § `gate`.
|
|
151
|
+
|
|
152
|
+
For a named-query gate (only a value that has passed validation is run):
|
|
153
|
+
```bash
|
|
154
|
+
GATE_RESULT=$(gsd_run check ${hook.check.query} "${PHASE_DIR}" --raw)
|
|
155
|
+
CHECK_EXIT=$?
|
|
156
|
+
```
|
|
131
157
|
|
|
132
|
-
|
|
133
|
-
WINDOWS_STATUS_JSON=$(gsd_run windows status --raw 2>/dev/null || echo '')
|
|
134
|
-
WINDOWS_OPEN_COUNT=$(printf '%s' "$WINDOWS_STATUS_JSON" | jq -r '.ledger.open_count // "?"' 2>/dev/null || echo '?')
|
|
135
|
-
```
|
|
158
|
+
(The named-query argument convention — a single `"${PHASE_DIR}"` positional — mirrors `verify-work.md`'s `verify:pre` arm verbatim. No capability declares a `check.query` gate at `ship:pre` today; the arm exists so the documented check contract is complete rather than half-implemented.)
|
|
136
159
|
|
|
137
|
-
|
|
138
|
-
|
|
160
|
+
For a `predicate` gate (ADR-2008 / #2008), serialize `hook.check.predicate` to compact JSON and pass it as a **single argv element**:
|
|
161
|
+
```bash
|
|
162
|
+
GATE_RESULT=$(gsd_run check predicate --predicate '<hook.check.predicate as JSON>' --phase-dir "${PHASE_DIR}" --phase-number "${PHASE_NUMBER}" --raw)
|
|
163
|
+
CHECK_EXIT=$?
|
|
139
164
|
```
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
165
|
+
A gate carrying neither — including an `agentVerdict` check, which has no runner at `ship:pre` — cannot be evaluated here. Record a warning naming the `capId` and treat it as a check-command failure routed per step 1a, **never** as a silent pass.
|
|
166
|
+
|
|
167
|
+
**Step 1a — did the CHECK COMMAND itself fail?** (non-zero `CHECK_EXIT`, empty output, or unparseable JSON). The two named branches above cannot reach this state — their failure modes are already folded into a fail-closed `block: true`.
|
|
168
|
+
- **`onError == "halt"`** → stop the ship. Do NOT push, do NOT create a PR. Surface: `⚠ Gate check command failed ({hook.capId}): command error. Resolve before shipping.`
|
|
169
|
+
- **`onError == "skip"`** → record a warning naming the `capId`, then continue to the next gate. Do NOT read `GATE_RESULT.block`.
|
|
170
|
+
|
|
171
|
+
**Step 2 — read the gate's `block` decision.** Only reached when the check produced a verdict.
|
|
172
|
+
|
|
173
|
+
- **`blocking == true` and `block == true`** → HALT the ship — do NOT push, do NOT create a PR — surfacing that gate's own message:
|
|
147
174
|
```
|
|
148
|
-
⚠
|
|
149
|
-
Inspect the file or run `gsd_run windows status --raw` to diagnose. The ledger
|
|
150
|
-
may be malformed; fix it before shipping (an unparseable ledger is a broken window).
|
|
175
|
+
⚠ Ship blocked by capability gate ({hook.capId}): {message}
|
|
151
176
|
```
|
|
177
|
+
This halt is **not** bypassed by `onError` — `onError` covers check-command failure (step 1a), never the gate's block decision.
|
|
178
|
+
- **`blocking == false`** (advisory) → never halts. If `block == true` or the result carries a non-empty message, print `⚠ {hook.capId} advisory: {message}`, then continue.
|
|
179
|
+
- **`blocking == true` and `block == false`** → continue silently.
|
|
152
180
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
If no active `broken-windows` `ship:pre` gate hook is present (gate disabled via `workflow.windows_enforce=false`, the default — tracking continues but the gate is opt-in), skip this check silently.
|
|
181
|
+
**When every active gate has been processed without a halt:** continue to the next preflight check.
|
|
156
182
|
</step>
|
|
157
183
|
|
|
158
184
|
<step name="push_branch">
|
|
@@ -455,7 +481,41 @@ would otherwise trigger (GitHub honors `[ci skip]` / `[skip ci]`):
|
|
|
455
481
|
|
|
456
482
|
```bash
|
|
457
483
|
gsd_run query commit "docs(${padded_phase}): ship phase ${PHASE_NUMBER} — PR #${PR_NUMBER} [ci skip]" --files .planning/STATE.md
|
|
484
|
+
SHIP_NOTE_SHA=$(git rev-parse HEAD)
|
|
458
485
|
git push origin ${CURRENT_BRANCH} 2>&1 || echo "⚠ track_shipping: ship-note push failed — it is local-only; rerun: git push origin ${CURRENT_BRANCH}"
|
|
486
|
+
|
|
487
|
+
# Preserve the skip-token optimization for repositories without a required-check
|
|
488
|
+
# wedge; only synthesize a second CI-triggering commit when GitHub reports one (#2783).
|
|
489
|
+
# Poll mergeStateStatus with backoff to avoid racing GitHub's async state computation.
|
|
490
|
+
# Note: Skip tokens recognized by GitHub Actions are [skip ci], [ci skip], [no ci], [skip actions], [actions skip], and skip-checks:true.
|
|
491
|
+
# The recovery commit message MUST NOT contain any of these tokens.
|
|
492
|
+
|
|
493
|
+
STATUS="UNKNOWN"
|
|
494
|
+
CHECKS=0
|
|
495
|
+
REVIEW_DECISION=""
|
|
496
|
+
for i in {1..5}; do
|
|
497
|
+
PR_STATE=$(gh pr view ${PR_NUMBER} --json headRefOid,mergeStateStatus,statusCheckRollup,reviewDecision -q '{head: .headRefOid, status: .mergeStateStatus, checks: ((.statusCheckRollup // []) | length), review: (.reviewDecision // "")}' 2>/dev/null || echo '{"head":"","status":"UNKNOWN","checks":0,"review":""}')
|
|
498
|
+
HEAD_OID=$(echo "$PR_STATE" | jq -r .head)
|
|
499
|
+
if [ "$HEAD_OID" = "$SHIP_NOTE_SHA" ]; then
|
|
500
|
+
STATUS=$(echo "$PR_STATE" | jq -r .status)
|
|
501
|
+
CHECKS=$(echo "$PR_STATE" | jq -r .checks)
|
|
502
|
+
REVIEW_DECISION=$(echo "$PR_STATE" | jq -r .review)
|
|
503
|
+
fi
|
|
504
|
+
if [ "$HEAD_OID" = "$SHIP_NOTE_SHA" ] && [ "$STATUS" != "UNKNOWN" ]; then
|
|
505
|
+
break
|
|
506
|
+
fi
|
|
507
|
+
sleep 3
|
|
508
|
+
done
|
|
509
|
+
|
|
510
|
+
if [ "$STATUS" = "BLOCKED" ] && [ "$CHECKS" = "0" ] && [ "$REVIEW_DECISION" != "REVIEW_REQUIRED" ] && [ "$REVIEW_DECISION" != "CHANGES_REQUESTED" ] && git log -1 --format=%B "$SHIP_NOTE_SHA" | grep -q '\[ci skip\]'; then
|
|
511
|
+
echo "⚠ PR is BLOCKED with zero checks. The [ci skip] trailer wedged the PR due to required checks."
|
|
512
|
+
echo "Pushing an empty commit to trigger the required pipelines..."
|
|
513
|
+
# gsd_run query commit requires a file list; use git directly for this intentionally empty commit.
|
|
514
|
+
git commit --allow-empty -m "chore: trigger CI (recover from ship-note skip-token)"
|
|
515
|
+
git push origin ${CURRENT_BRANCH} 2>&1 || echo "⚠ track_shipping: recovery push failed — rerun: git push origin ${CURRENT_BRANCH}"
|
|
516
|
+
elif [ "$STATUS" = "UNKNOWN" ]; then
|
|
517
|
+
echo "⚠ track_shipping: PR mergeStateStatus is UNKNOWN after polling; PR may require manual check re-trigger."
|
|
518
|
+
fi
|
|
459
519
|
```
|
|
460
520
|
</step>
|
|
461
521
|
|
|
@@ -134,7 +134,7 @@ If spikes exist for this project, read them to ground the sketches in reality. M
|
|
|
134
134
|
|
|
135
135
|
**a.** Glob for `./.claude/skills/spike-findings-*/SKILL.md` and read any that exist, plus their `references/*.md`. These contain validated patterns and requirements.
|
|
136
136
|
|
|
137
|
-
**b.** Read `.planning/spikes/MANIFEST.md` if it exists —
|
|
137
|
+
**b.** Read `.planning/spikes/MANIFEST.md` if it exists — it may hold separate `### {idea-key}` sections for several unrelated ideas. Check the Requirements list of the idea key relevant to this sketch's design direction (or all of them if none clearly matches) for non-negotiable design constraints (e.g., "must support streaming", "must render markdown"). These requirements should be visible in the mockup even though the mockup doesn't implement them for real.
|
|
138
138
|
|
|
139
139
|
**c.** Read `.planning/spikes/CONVENTIONS.md` if it exists — the established stack informs what's buildable and what interaction patterns are idiomatic.
|
|
140
140
|
|
|
@@ -126,7 +126,7 @@ Acceptance Criteria:[score 0.0–1.0]
|
|
|
126
126
|
Ambiguity: [score] ([calculate])
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
**If `--auto` and initial ambiguity already ≤ 0.20 with all minimums met:** Skip interview — derive SPEC.md directly from roadmap + requirements. Log: `[auto] Phase requirements are already sufficiently clear — generating SPEC.md from existing context.` Jump to Step
|
|
129
|
+
**If `--auto` and initial ambiguity already ≤ 0.20 with all minimums met:** Skip interview — derive SPEC.md directly from roadmap + requirements. Log: `[auto] Phase requirements are already sufficiently clear — generating SPEC.md from existing context.` Jump to Step 5.5.
|
|
130
130
|
|
|
131
131
|
**Otherwise:** Continue to Step 4.
|
|
132
132
|
|
|
@@ -159,15 +159,15 @@ After round [N]:
|
|
|
159
159
|
|
|
160
160
|
If gate passes (ambiguity ≤ 0.20 AND all minimums met):
|
|
161
161
|
|
|
162
|
-
**If `--auto`:** Jump to Step
|
|
162
|
+
**If `--auto`:** Jump to Step 5.5.
|
|
163
163
|
|
|
164
164
|
**Otherwise:** AskUserQuestion:
|
|
165
165
|
- header: "Spec Gate Passed"
|
|
166
166
|
- question: "Ambiguity is [score] — requirements are clear enough to write SPEC.md. Proceed?"
|
|
167
167
|
- options:
|
|
168
|
-
- "Yes — write SPEC.md" → Jump to Step
|
|
168
|
+
- "Yes — write SPEC.md" → Jump to Step 5.5
|
|
169
169
|
- "One more round" → Continue interview
|
|
170
|
-
- "Done talking — write it" → Jump to Step
|
|
170
|
+
- "Done talking — write it" → Jump to Step 5.5
|
|
171
171
|
|
|
172
172
|
**If max rounds reached (6) and gate not passed:**
|
|
173
173
|
|
|
@@ -251,8 +251,11 @@ if ! node -e 'const a=require(process.argv[1]);if(!Array.isArray(a)||a.length===
|
|
|
251
251
|
exit 1
|
|
252
252
|
fi
|
|
253
253
|
# Invoke the compiled engine and CAPTURE its report — it computes which categories apply per
|
|
254
|
-
# requirement. The
|
|
255
|
-
#
|
|
254
|
+
# requirement. The report is RENDERED into context below (#3102); its resolved/dismissed/
|
|
255
|
+
# unresolved rows (resolved items carry verification: explicit|backstop) are the deterministic
|
|
256
|
+
# FLOOR the resolution loop consumes and unions with its own classification — the loop no longer
|
|
257
|
+
# re-derives the taxonomy from prose unaided. Floor, never ceiling: the classifier has a measured
|
|
258
|
+
# recall gap (ADR-857 §98 / ADR-550 D7b), so the model still ADDS any category the engine missed.
|
|
256
259
|
# The engine FAILS CLOSED (exit 2) on an invalid authored shape or bad input — so the capture
|
|
257
260
|
# MUST be exit-checked. A bare `COVERAGE=$(node …)` swallows that exit code, leaves $COVERAGE
|
|
258
261
|
# empty, and lets the workflow fall through to prose re-derivation: fail-OPEN at the boundary
|
|
@@ -269,6 +272,16 @@ if ! printf '%s' "$COVERAGE" | node -e 'let s="";process.stdin.on("data",d=>s+=d
|
|
|
269
272
|
echo "ERROR: edge-probe produced an unparseable or malformed coverage report — refusing to proceed with the resolution loop." >&2
|
|
270
273
|
exit 1
|
|
271
274
|
fi
|
|
275
|
+
# Render the validated report into the model's visible context (#3102). Until here $COVERAGE was
|
|
276
|
+
# captured, shape-checked, and reduced to coverage.applicable — the engine's per-requirement
|
|
277
|
+
# items[] never reached the model, so the resolution loop below re-derived edge categories from
|
|
278
|
+
# requirement PROSE (the data-flow twin of #2733's control-flow discard). These rows are the
|
|
279
|
+
# deterministic FLOOR the resolution loop consumes. Printed RAW (not a bespoke table) so this
|
|
280
|
+
# step holds NO knowledge of the item schema: an ADR-550 D7a-style re-cut of the item/coverage
|
|
281
|
+
# shape cannot silently desync a hand-rolled renderer here — the engine stays the single source.
|
|
282
|
+
echo "### Edge-probe coverage report (deterministic proposals — the FLOOR for the resolution loop below):"
|
|
283
|
+
printf '%s\n' "$COVERAGE"
|
|
284
|
+
echo "### (end edge-probe coverage report)"
|
|
272
285
|
# Zero-applicable guard: a report where the engine proposed NO applicable edge across ANY
|
|
273
286
|
# requirement is far more likely a shape-classification miss (or malformed requirements) than
|
|
274
287
|
# a genuinely edge-free spec — the same fail-open shape as an invalid shape yielding
|
|
@@ -286,23 +299,29 @@ edge-free spec, or should we revisit the requirement wording / authored shapes?"
|
|
|
286
299
|
an empty `## Edge Coverage` section after explicit confirmation.
|
|
287
300
|
|
|
288
301
|
For each Requirement gathered so far:
|
|
289
|
-
1.
|
|
290
|
-
|
|
291
|
-
|
|
302
|
+
1. Start from the edge-probe rows RENDERED above — the deterministic `items[]` are the FLOOR:
|
|
303
|
+
every proposed `(requirement_id, category)` MUST be resolved below (Specify / Dismiss-with-
|
|
304
|
+
reason / Backstop / Defer), none silently dropped. Then raise any applicable category the
|
|
305
|
+
engine MISSED — the rows are a floor, never a ceiling: the classifier has a measured recall
|
|
306
|
+
gap on terse prose (ADR-857 §98 / ADR-550 D7b), e.g. a CSV-export requirement whose
|
|
307
|
+
`encoding` edge the shape cue under-fires. Union the engine's rows with your own
|
|
308
|
+
classification (relevance filter — see the taxonomy in the reference); do not narrow to them.
|
|
309
|
+
Reuse any edges the Round-4 Failure Analyst already surfaced as pre-resolved.
|
|
292
310
|
2. For each raised category, propose a CONCRETE candidate edge (not "consider
|
|
293
311
|
boundaries" — e.g. "R2 merges intervals; what about `[[1,2],[2,3]]` that only touch?").
|
|
294
312
|
3. Resolve each with the user (AskUserQuestion; text mode → numbered list):
|
|
295
313
|
- **Specify it** → write a new pass/fail line into Acceptance Criteria AND mark the
|
|
296
|
-
edge `
|
|
314
|
+
edge `resolved` with `verification: explicit`.
|
|
297
315
|
- **Dismiss (reason)** → mark `dismissed` with a required non-empty reason.
|
|
298
|
-
- **Backstop with a test** → mark `backstop`; note
|
|
316
|
+
- **Backstop with a test** → mark `resolved` with `verification: backstop`; note
|
|
317
|
+
"held-out edge test" for plan-phase.
|
|
299
318
|
- **Defer** → leave `unresolved`.
|
|
300
319
|
- An `unclassified` row (probe `unclassified — review manually`) means the requirement's
|
|
301
320
|
prose matched no shape cue (#1110) — treat it like any other candidate (**Specify**,
|
|
302
321
|
**Dismiss (reason)**, or **Defer**). A manual-review nudge, not a hard block.
|
|
303
322
|
|
|
304
323
|
**Soft gate (after resolving):**
|
|
305
|
-
- All applicable edges resolved → proceed to Step 6.
|
|
324
|
+
- All applicable edges resolved → proceed to Step 5.6.
|
|
306
325
|
- Any `unresolved` → AskUserQuestion:
|
|
307
326
|
- header: "Edge Coverage"
|
|
308
327
|
- question: "[N] edge(s) are unresolved: [list]. What do you want to do?"
|
|
@@ -311,13 +330,16 @@ For each Requirement gathered so far:
|
|
|
311
330
|
- On "anyway": write SPEC.md with those rows marked `⚠ Edge unresolved — planner must
|
|
312
331
|
treat as assumption`.
|
|
313
332
|
|
|
314
|
-
**`--auto` mode:**
|
|
315
|
-
|
|
316
|
-
|
|
333
|
+
**`--auto` mode:** resolve over the **same rendered floor** (#3102) — every engine-proposed row
|
|
334
|
+
from Step 5.5's report (step 1) plus any category the classifier missed, never a narrower set.
|
|
335
|
+
For each: auto-`resolved` (verification: explicit) where a defensible acceptance criterion can be
|
|
336
|
+
written; otherwise auto-`resolved` (verification: backstop) (never auto-dismiss — a wrong
|
|
337
|
+
dismissal is the exact silent failure being eliminated). Log:
|
|
338
|
+
`[auto] edge coverage: E explicit, B backstop, U unresolved`.
|
|
317
339
|
|
|
318
340
|
**`unclassified` exception (#1110):** `--auto` leaves an `unclassified` candidate
|
|
319
341
|
**`unresolved`** (the soft gate surfaces it as a flagged planner assumption) — it never
|
|
320
|
-
auto
|
|
342
|
+
auto-resolves it with `verification: backstop`. A missing shape is not evidence an edge exists, so minting a held-out
|
|
321
343
|
edge obligation on a requirement that may be genuinely edge-free would be a false claim and
|
|
322
344
|
risks a vacuous edge test. Leaving it `unresolved` keeps the zero-cue requirement visible
|
|
323
345
|
(never a silent drop) without fabricating an edge — which is exactly #1110's purpose: surface
|
|
@@ -425,7 +447,7 @@ downstream rather than blocking authoring.
|
|
|
425
447
|
|
|
426
448
|
Use the SPEC.md template from @~/.claude/gsd-core/templates/spec.md.
|
|
427
449
|
|
|
428
|
-
- Populate the **Edge Coverage** section from Step 5.5 (
|
|
450
|
+
- Populate the **Edge Coverage** section from Step 5.5 (resolved/dismissed/unresolved rows; resolved items carry `verification: explicit|backstop`).
|
|
429
451
|
- Populate the **Prohibitions** section from Step 5.6 (resolved/dismissed/unresolved rows with the test|judgment tier).
|
|
430
452
|
|
|
431
453
|
**Requirements for every requirement entry:**
|
|
@@ -455,11 +477,10 @@ Write to: `{phase_dir}/{padded_phase}-SPEC.md`
|
|
|
455
477
|
## Step 7: Commit
|
|
456
478
|
|
|
457
479
|
```bash
|
|
458
|
-
|
|
459
|
-
git commit -m "spec(phase-${phase_number}): add SPEC.md for ${phase_name} — ${requirement_count} requirements (#2213)" -- "${phase_dir}/${padded_phase}-SPEC.md"
|
|
480
|
+
gsd_run query commit "spec(phase-${phase_number}): add SPEC.md for ${phase_name} — ${requirement_count} requirements (#2213)" --files "${phase_dir}/${padded_phase}-SPEC.md"
|
|
460
481
|
```
|
|
461
482
|
|
|
462
|
-
If `commit_docs` is false
|
|
483
|
+
If `commit_docs` is false the CLI returns `skipped`; SPEC.md is written, not committed.
|
|
463
484
|
|
|
464
485
|
## Step 8: Wrap Up
|
|
465
486
|
|
|
@@ -22,8 +22,12 @@ Read all files referenced by the invoking prompt's execution_context before star
|
|
|
22
22
|
<step name="gather">
|
|
23
23
|
## Gather Spike Inventory
|
|
24
24
|
|
|
25
|
-
1. Read `.planning/spikes/MANIFEST.md` for the
|
|
26
|
-
|
|
25
|
+
1. Read `.planning/spikes/MANIFEST.md` for the `## Ideas` sections (each idea's paragraph and
|
|
26
|
+
its own scoped Requirements list) and the `## Spikes` table (its Idea column tells you which
|
|
27
|
+
idea key each spike row belongs to).
|
|
28
|
+
2. Glob `.planning/spikes/*/README.md` and parse YAML frontmatter from each — each spike's
|
|
29
|
+
`idea:` field is the idea key that owns it. If a README predates #1700 and has no `idea:`
|
|
30
|
+
field, resolve its idea key from the matching `## Spikes` table row's Idea column instead.
|
|
27
31
|
3. Check if `./.claude/skills/spike-findings-*/SKILL.md` exists for this project
|
|
28
32
|
- If yes: read its `processed_spikes` list from the metadata section and filter those out
|
|
29
33
|
- If no: all spikes are candidates
|
|
@@ -101,7 +105,12 @@ For each feature-area group, write a reference file at `references/[feature-area
|
|
|
101
105
|
|
|
102
106
|
## Requirements
|
|
103
107
|
|
|
104
|
-
[Non-negotiable design decisions from
|
|
108
|
+
[Non-negotiable design decisions pulled ONLY from the Requirements list of the idea key(s) that
|
|
109
|
+
own the spikes in this feature-area group — match each spike's `idea:` frontmatter (or Idea
|
|
110
|
+
column) to its `### {idea-key}` Requirements list in MANIFEST.md. These MUST be honored in the
|
|
111
|
+
real build. E.g., "Must use streaming JSON output", "Must support reconnection".
|
|
112
|
+
|
|
113
|
+
Never include a requirement from an idea key that has no spike in this group.]
|
|
105
114
|
|
|
106
115
|
## How to Build It
|
|
107
116
|
|
|
@@ -136,7 +145,8 @@ description: Implementation blueprint from spike experiments. Requirements, prov
|
|
|
136
145
|
<context>
|
|
137
146
|
## Project: [project-dir-name]
|
|
138
147
|
|
|
139
|
-
[One paragraph
|
|
148
|
+
[One paragraph per idea key represented among the wrapped spikes, taken from that idea's
|
|
149
|
+
`### {idea-key}` section in MANIFEST.md — not the whole MANIFEST.md if it holds unrelated ideas.]
|
|
140
150
|
|
|
141
151
|
Spike sessions wrapped: [date(s)]
|
|
142
152
|
</context>
|
|
@@ -144,7 +154,11 @@ Spike sessions wrapped: [date(s)]
|
|
|
144
154
|
<requirements>
|
|
145
155
|
## Requirements
|
|
146
156
|
|
|
147
|
-
[
|
|
157
|
+
[Union of the Requirements lists for every idea key represented among the spikes being wrapped
|
|
158
|
+
in this session — never the whole MANIFEST.md. These are non-negotiable design decisions that
|
|
159
|
+
emerged from the user's choices while spiking those specific idea(s). Every feature area
|
|
160
|
+
reference must honor these. If this wrap-up spans more than one idea key, group the list by
|
|
161
|
+
idea key so a future reader can tell which requirement belongs to which idea.]
|
|
148
162
|
|
|
149
163
|
- [requirement 1]
|
|
150
164
|
- [requirement 2]
|
|
@@ -299,6 +313,7 @@ After the summary, present next-step options:
|
|
|
299
313
|
- [ ] Spikes grouped by feature area
|
|
300
314
|
- [ ] Spike-findings skill exists at `./.claude/skills/` with SKILL.md (including requirements), references/, sources/
|
|
301
315
|
- [ ] Reference files are implementation blueprints with Requirements, How to Build It, What to Avoid, Constraints
|
|
316
|
+
- [ ] Requirements in each reference file and in SKILL.md are scoped to the idea key(s) actually represented among the wrapped spikes — never blended with an unrelated idea's requirements
|
|
302
317
|
- [ ] `.planning/spikes/CONVENTIONS.md` created or updated with recurring stack/structure/pattern choices
|
|
303
318
|
- [ ] `.planning/spikes/WRAP-UP-SUMMARY.md` written for project history
|
|
304
319
|
- [ ] Project CLAUDE.md has auto-load routing line
|
|
@@ -53,7 +53,8 @@ If no `.planning/spikes/` directory exists, tell the user there's nothing to ana
|
|
|
53
53
|
|
|
54
54
|
Otherwise, load in this order:
|
|
55
55
|
|
|
56
|
-
**a. MANIFEST.md** —
|
|
56
|
+
**a. MANIFEST.md** — every idea section under `## Ideas` (each idea's paragraph and its own
|
|
57
|
+
scoped Requirements) and the `## Spikes` table with verdicts (each row tagged by idea).
|
|
57
58
|
|
|
58
59
|
**b. Findings skills** — glob `./.claude/skills/spike-findings-*/SKILL.md` and read any that exist, plus their `references/*.md`. These contain curated knowledge from prior wrap-ups.
|
|
59
60
|
|
|
@@ -74,7 +75,8 @@ If integration risks exist, present them as concrete proposed spikes with names
|
|
|
74
75
|
|
|
75
76
|
### Analyze for Frontier Spikes
|
|
76
77
|
|
|
77
|
-
Think laterally about
|
|
78
|
+
Think laterally about every idea section from MANIFEST.md and what's been proven so far for
|
|
79
|
+
each. Consider:
|
|
78
80
|
|
|
79
81
|
- **Gaps in the vision:** Capabilities assumed but unproven.
|
|
80
82
|
- **Discovered dependencies:** Findings that reveal new questions.
|
|
@@ -86,7 +88,7 @@ Present frontier spikes as concrete proposals numbered from the highest existing
|
|
|
86
88
|
|
|
87
89
|
### Get Alignment and Execute
|
|
88
90
|
|
|
89
|
-
Present all integration and frontier candidates, then ask which to run. When the user picks spikes, write definitions into `.planning/spikes/MANIFEST.md` (appending to existing table) and proceed directly to building them starting at `research`.
|
|
91
|
+
Present all integration and frontier candidates, then ask which to run. When the user picks spikes, write definitions into `.planning/spikes/MANIFEST.md` (appending to the existing table, with each row's Idea column set to the idea key(s) it extends or validates) and proceed directly to building them starting at `research`.
|
|
90
92
|
</step>
|
|
91
93
|
|
|
92
94
|
<step name="setup_directory">
|
|
@@ -212,33 +214,63 @@ If 2+ credible approaches exist, plan to build quick variants within the spike a
|
|
|
212
214
|
</step>
|
|
213
215
|
|
|
214
216
|
<step name="create_manifest">
|
|
215
|
-
Create or update `.planning/spikes/MANIFEST.md
|
|
217
|
+
Create or update `.planning/spikes/MANIFEST.md`.
|
|
218
|
+
|
|
219
|
+
**Assign an idea key.** Derive a short, stable, kebab-case slug (2-4 words) summarizing the
|
|
220
|
+
idea being spiked right now, e.g. `realtime-llm-streaming`. Reuse the exact same idea key for
|
|
221
|
+
every spike in this session and any later session that continues the same idea. Only mint a
|
|
222
|
+
new idea key when the current idea is not a continuation of one already indexed in
|
|
223
|
+
MANIFEST.md — never reuse an existing idea key for an unrelated idea, and never merge two
|
|
224
|
+
different ideas under one key.
|
|
225
|
+
|
|
226
|
+
If `.planning/spikes/MANIFEST.md` doesn't exist, create it:
|
|
216
227
|
|
|
217
228
|
```markdown
|
|
218
229
|
# Spike Manifest
|
|
219
230
|
|
|
220
|
-
##
|
|
221
|
-
|
|
231
|
+
## Ideas
|
|
232
|
+
|
|
233
|
+
### {idea-key}
|
|
234
|
+
[One paragraph describing this idea]
|
|
222
235
|
|
|
223
|
-
|
|
224
|
-
[Design decisions that emerged from the user's choices
|
|
236
|
+
**Requirements:**
|
|
237
|
+
[Design decisions that emerged from the user's choices while spiking THIS idea. Non-negotiable
|
|
238
|
+
for the real build of this idea. Updated as spikes progress. Never copy or merge requirements
|
|
239
|
+
from a different idea key into this list.]
|
|
225
240
|
|
|
226
241
|
- [e.g., "Must use streaming JSON output, not single-response"]
|
|
227
242
|
- [e.g., "Must support reconnection on network failure"]
|
|
228
243
|
|
|
229
244
|
## Spikes
|
|
230
245
|
|
|
231
|
-
| # | Name | Type | Validates | Verdict | Tags |
|
|
232
|
-
|
|
246
|
+
| # | Idea | Name | Type | Validates | Verdict | Tags |
|
|
247
|
+
|---|------|------|------|-----------|---------|------|
|
|
233
248
|
```
|
|
234
249
|
|
|
235
|
-
|
|
250
|
+
If `.planning/spikes/MANIFEST.md` already exists:
|
|
251
|
+
|
|
252
|
+
- **Same idea key already has a `### {idea-key}` section under `## Ideas`:** append to that
|
|
253
|
+
section's Requirements list as new requirements emerge. Never overwrite or rewrite its
|
|
254
|
+
`## Idea` paragraph.
|
|
255
|
+
- **New idea key, not yet present:** append a new `### {idea-key}` subsection under `## Ideas`,
|
|
256
|
+
after any existing idea sections. Never touch, merge into, or delete another idea's section.
|
|
257
|
+
- **A pre-#1700 MANIFEST.md with the old flat shape** (a single top-level `## Idea` / `##
|
|
258
|
+
Requirements` pair, no `## Ideas` heading): treat its existing content as one implicit idea.
|
|
259
|
+
Derive an idea key from its `## Idea` paragraph, migrate it in place to `## Ideas` >
|
|
260
|
+
`### {idea-key}` — preserving the paragraph and every existing Requirements bullet and
|
|
261
|
+
Spikes row verbatim — then continue as above. Do this migration once; do not repeat it once
|
|
262
|
+
`## Ideas` exists.
|
|
263
|
+
|
|
264
|
+
Every row appended to `## Spikes` carries an **Idea** column set to the idea key it belongs to.
|
|
265
|
+
|
|
266
|
+
**Track requirements as they emerge.** When the user expresses a preference during spiking, add
|
|
267
|
+
it to the current idea's Requirements list immediately — never to a different idea's list.
|
|
236
268
|
</step>
|
|
237
269
|
|
|
238
270
|
<step name="reground">
|
|
239
271
|
## Re-Ground Before Each Spike
|
|
240
272
|
|
|
241
|
-
Before starting each spike (not just the first), re-read `.planning/spikes/MANIFEST.md` and `.planning/spikes/CONVENTIONS.md` to prevent drift within long sessions. Check the Requirements
|
|
273
|
+
Before starting each spike (not just the first), re-read `.planning/spikes/MANIFEST.md` and `.planning/spikes/CONVENTIONS.md` to prevent drift within long sessions. Check the current idea's `### {idea-key}` Requirements list — make sure the spike doesn't contradict any established requirement for this idea. Do not apply another idea's requirements.
|
|
242
274
|
</step>
|
|
243
275
|
|
|
244
276
|
<step name="build_spikes">
|
|
@@ -287,6 +319,7 @@ Multiple files per spike are expected for complex questions (e.g., `test-basic.j
|
|
|
287
319
|
```markdown
|
|
288
320
|
---
|
|
289
321
|
spike: NNN
|
|
322
|
+
idea: {idea-key}
|
|
290
323
|
name: descriptive-name
|
|
291
324
|
type: standard
|
|
292
325
|
validates: "Given [precondition], when [action], then [expected outcome]"
|
|
@@ -337,7 +370,8 @@ tags: [tag1, tag2]
|
|
|
337
370
|
→ Does this match what you expected? Describe what you see.
|
|
338
371
|
──────────────────────────────────────────────────────────────
|
|
339
372
|
|
|
340
|
-
**h.** Update `.planning/spikes/MANIFEST.md` with the spike's row
|
|
373
|
+
**h.** Update `.planning/spikes/MANIFEST.md` with the spike's row, setting the Idea column to
|
|
374
|
+
this spike's idea key.
|
|
341
375
|
|
|
342
376
|
**i.** Commit (if `COMMIT_DOCS` is true):
|
|
343
377
|
```bash
|
|
@@ -450,10 +484,10 @@ gsd_run query commit "docs(spikes): update conventions" --files .planning/spikes
|
|
|
450
484
|
- [ ] Depth over speed — edge cases tested, surprising findings followed, investigation trail documented
|
|
451
485
|
- [ ] Comparison spikes built back-to-back with head-to-head verdict
|
|
452
486
|
- [ ] Spikes needing human interaction have forensic log layer
|
|
453
|
-
- [ ] Requirements tracked in MANIFEST.md as they emerge from user choices
|
|
487
|
+
- [ ] Requirements tracked in MANIFEST.md, scoped to the idea key that produced them, as they emerge from user choices
|
|
454
488
|
- [ ] CONVENTIONS.md created or updated with patterns that emerged
|
|
455
|
-
- [ ] Each spike README has complete frontmatter, Investigation Trail, and Results
|
|
456
|
-
- [ ] MANIFEST.md is current (with Type
|
|
489
|
+
- [ ] Each spike README has complete frontmatter (including its idea key), Investigation Trail, and Results
|
|
490
|
+
- [ ] MANIFEST.md is current (with Idea and Type columns, and each idea's own scoped Requirements section)
|
|
457
491
|
- [ ] Commits use `docs(spike-NNN): [VERDICT]` format
|
|
458
492
|
- [ ] Consolidated report presented with next-step routing
|
|
459
493
|
</success_criteria>
|