@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.b1abb545
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/dist/cli-web-branch.d.ts +2 -0
- package/dist/cli-web-branch.js +9 -2
- package/dist/help-text.js +5 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
- package/dist/resources/extensions/github-sync/templates.js +3 -3
- package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
- package/dist/resources/extensions/gsd/auto/loop.js +74 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
- package/dist/resources/extensions/gsd/auto/phases.js +28 -3
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
- package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
- package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -23
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
- package/dist/resources/extensions/gsd/auto-verification.js +7 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
- package/dist/resources/extensions/gsd/auto.js +11 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
- package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
- package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
- package/dist/resources/extensions/gsd/db-workspace.js +103 -0
- package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
- package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/dist/resources/extensions/gsd/doctor.js +16 -9
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
- package/dist/resources/extensions/gsd/gsd-db.js +12 -0
- package/dist/resources/extensions/gsd/guided-flow.js +34 -468
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
- package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
- package/dist/resources/extensions/gsd/md-importer.js +4 -3
- package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
- package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
- package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
- package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
- package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +147 -29
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
- package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
- package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
- package/dist/resources/extensions/gsd/question-transport.js +86 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state.js +13 -5
- package/dist/resources/extensions/gsd/templates/plan.md +7 -0
- package/dist/resources/extensions/gsd/templates/project.md +1 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/dist/resources/extensions/gsd/templates/uat.md +5 -1
- package/dist/resources/extensions/gsd/tool-contract.js +52 -8
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
- package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/uat-policy.js +16 -10
- package/dist/resources/extensions/gsd/uat-run.js +9 -14
- package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
- package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
- package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
- package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
- package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
- package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
- package/dist/resources/extensions/shared/interview-ui.js +2 -2
- package/dist/resources/shared/claude-runtime-floor.js +182 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-cmd.js +20 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
- package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
- package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/package.json +2 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts +10 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +8 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +2 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +8 -93
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +35 -120
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/components/input.js +1 -1
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +39 -30
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +22 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
- package/src/resources/extensions/github-sync/templates.ts +3 -3
- package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
- package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
- package/src/resources/extensions/gsd/auto/phases.ts +35 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
- package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
- package/src/resources/extensions/gsd/auto-start.ts +17 -20
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
- package/src/resources/extensions/gsd/auto-verification.ts +7 -8
- package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
- package/src/resources/extensions/gsd/auto.ts +15 -8
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
- package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
- package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
- package/src/resources/extensions/gsd/db-workspace.ts +170 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
- package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/src/resources/extensions/gsd/doctor.ts +15 -5
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
- package/src/resources/extensions/gsd/gsd-db.ts +12 -0
- package/src/resources/extensions/gsd/guided-flow.ts +47 -558
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
- package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -3
- package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
- package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
- package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
- package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
- package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +173 -28
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
- package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
- package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
- package/src/resources/extensions/gsd/question-transport.ts +138 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state.ts +15 -5
- package/src/resources/extensions/gsd/templates/plan.md +7 -0
- package/src/resources/extensions/gsd/templates/project.md +1 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/src/resources/extensions/gsd/templates/uat.md +5 -1
- package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
- package/src/resources/extensions/gsd/tool-contract.ts +86 -8
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
- package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/uat-policy.ts +19 -10
- package/src/resources/extensions/gsd/uat-run.ts +10 -14
- package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
- package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
- package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
- package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
- package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
- package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
- package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
- package/src/resources/extensions/shared/interview-ui.ts +15 -2
- package/src/resources/shared/claude-runtime-floor.ts +248 -0
- package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
- package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Persist planned milestone roadmaps and their DB-backed projections.
|
|
3
|
+
|
|
4
|
+
import { clearParseCache } from "./files.js";
|
|
5
|
+
import { isClosedStatus } from "./status-guards.js";
|
|
6
|
+
import {
|
|
7
|
+
transaction,
|
|
8
|
+
getMilestone,
|
|
9
|
+
getMilestoneSlices,
|
|
10
|
+
getSlice,
|
|
11
|
+
insertMilestone,
|
|
12
|
+
insertSlice,
|
|
13
|
+
upsertMilestonePlanning,
|
|
14
|
+
upsertSlicePlanning,
|
|
15
|
+
} from "./gsd-db.js";
|
|
16
|
+
import { invalidateStateCache } from "./state.js";
|
|
17
|
+
import { renderRoadmapFromDb } from "./markdown-renderer.js";
|
|
18
|
+
import { renderAllProjections } from "./workflow-projections.js";
|
|
19
|
+
import { writeManifest } from "./workflow-manifest.js";
|
|
20
|
+
import { appendEvent } from "./workflow-events.js";
|
|
21
|
+
import { logWarning } from "./workflow-logger.js";
|
|
22
|
+
|
|
23
|
+
export interface PersistMilestonePlanSlice {
|
|
24
|
+
sliceId: string;
|
|
25
|
+
title: string;
|
|
26
|
+
risk: string;
|
|
27
|
+
depends: string[];
|
|
28
|
+
demo: string;
|
|
29
|
+
goal: string;
|
|
30
|
+
successCriteria: string;
|
|
31
|
+
proofLevel: string;
|
|
32
|
+
integrationClosure: string;
|
|
33
|
+
observabilityImpact: string;
|
|
34
|
+
isSketch?: boolean;
|
|
35
|
+
sketchScope?: string;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface PersistMilestonePlanParams {
|
|
39
|
+
milestoneId: string;
|
|
40
|
+
title: string;
|
|
41
|
+
vision: string;
|
|
42
|
+
slices: PersistMilestonePlanSlice[];
|
|
43
|
+
status?: string;
|
|
44
|
+
dependsOn?: string[];
|
|
45
|
+
actorName?: string;
|
|
46
|
+
triggerReason?: string;
|
|
47
|
+
successCriteria?: string[];
|
|
48
|
+
keyRisks?: Array<{ risk: string; whyItMatters: string }>;
|
|
49
|
+
proofStrategy?: Array<{ riskOrUnknown: string; retireIn: string; whatWillBeProven: string }>;
|
|
50
|
+
verificationContract?: string;
|
|
51
|
+
verificationIntegration?: string;
|
|
52
|
+
verificationOperational?: string;
|
|
53
|
+
verificationUat?: string;
|
|
54
|
+
definitionOfDone?: string[];
|
|
55
|
+
requirementCoverage?: string;
|
|
56
|
+
boundaryMapMarkdown?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface PersistMilestonePlanResult {
|
|
60
|
+
milestoneId: string;
|
|
61
|
+
roadmapPath: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function validatePlanPromotion(params: PersistMilestonePlanParams): string | null {
|
|
65
|
+
const existingMilestone = getMilestone(params.milestoneId);
|
|
66
|
+
if (existingMilestone && isClosedStatus(existingMilestone.status)) {
|
|
67
|
+
return `cannot re-plan milestone ${params.milestoneId}: it is already complete`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Guard: refuse to re-plan a milestone that would drop completed slices (#2960).
|
|
71
|
+
// Allow re-planning when all completed slices are still present in the
|
|
72
|
+
// incoming plan — their status is preserved below (#2558). Block only when
|
|
73
|
+
// the new plan omits a completed slice, which could shadow completed work.
|
|
74
|
+
const existingSlices = getMilestoneSlices(params.milestoneId);
|
|
75
|
+
const completedSlices = existingSlices.filter(s => isClosedStatus(s.status));
|
|
76
|
+
if (completedSlices.length > 0) {
|
|
77
|
+
const incomingSliceIds = new Set(params.slices.map(s => s.sliceId));
|
|
78
|
+
const droppedCompleted = completedSlices.filter(s => !incomingSliceIds.has(s.id));
|
|
79
|
+
if (droppedCompleted.length > 0) {
|
|
80
|
+
return `cannot re-plan milestone ${params.milestoneId}: ${droppedCompleted.length} completed slice(s) would be dropped (${droppedCompleted.map(s => s.id).join(", ")}). Use gsd_reassess_roadmap to modify the roadmap.`;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Validate depends_on: all dependencies must exist and be complete
|
|
85
|
+
if (params.dependsOn && params.dependsOn.length > 0) {
|
|
86
|
+
for (const depId of params.dependsOn) {
|
|
87
|
+
const dep = getMilestone(depId);
|
|
88
|
+
if (!dep) {
|
|
89
|
+
return `depends_on references unknown milestone: ${depId}`;
|
|
90
|
+
}
|
|
91
|
+
if (!isClosedStatus(dep.status)) {
|
|
92
|
+
return `depends_on milestone ${depId} is not yet complete (status: ${dep.status})`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function writePlanRows(params: PersistMilestonePlanParams): void {
|
|
101
|
+
insertMilestone({
|
|
102
|
+
id: params.milestoneId,
|
|
103
|
+
title: params.title,
|
|
104
|
+
status: params.status ?? "active",
|
|
105
|
+
depends_on: params.dependsOn ?? [],
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
upsertMilestonePlanning(params.milestoneId, {
|
|
109
|
+
title: params.title,
|
|
110
|
+
status: params.status ?? "active",
|
|
111
|
+
depends_on: params.dependsOn ?? [],
|
|
112
|
+
vision: params.vision,
|
|
113
|
+
successCriteria: params.successCriteria,
|
|
114
|
+
keyRisks: params.keyRisks,
|
|
115
|
+
proofStrategy: params.proofStrategy,
|
|
116
|
+
verificationContract: params.verificationContract,
|
|
117
|
+
verificationIntegration: params.verificationIntegration,
|
|
118
|
+
verificationOperational: params.verificationOperational,
|
|
119
|
+
verificationUat: params.verificationUat,
|
|
120
|
+
definitionOfDone: params.definitionOfDone,
|
|
121
|
+
requirementCoverage: params.requirementCoverage,
|
|
122
|
+
boundaryMapMarkdown: params.boundaryMapMarkdown,
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
for (let i = 0; i < params.slices.length; i++) {
|
|
126
|
+
const slice = params.slices[i]!;
|
|
127
|
+
// Preserve completed/done status on re-plan (#2558).
|
|
128
|
+
// Without this, a re-plan after milestone transition would reset
|
|
129
|
+
// already-completed slices back to "pending".
|
|
130
|
+
const existing = getSlice(params.milestoneId, slice.sliceId);
|
|
131
|
+
const status = existing && (existing.status === "complete" || existing.status === "done")
|
|
132
|
+
? existing.status
|
|
133
|
+
: "pending";
|
|
134
|
+
insertSlice({
|
|
135
|
+
id: slice.sliceId,
|
|
136
|
+
milestoneId: params.milestoneId,
|
|
137
|
+
title: slice.title,
|
|
138
|
+
status,
|
|
139
|
+
risk: slice.risk,
|
|
140
|
+
depends: slice.depends,
|
|
141
|
+
demo: slice.demo,
|
|
142
|
+
sequence: i + 1, // Preserve agent-ordered sequence (#3356)
|
|
143
|
+
// ADR-011: pass undefined through so ON CONFLICT preserves existing values
|
|
144
|
+
// when the caller omitted the fields on a re-plan.
|
|
145
|
+
isSketch: slice.isSketch,
|
|
146
|
+
sketchScope: slice.sketchScope,
|
|
147
|
+
});
|
|
148
|
+
upsertSlicePlanning(params.milestoneId, slice.sliceId, {
|
|
149
|
+
goal: slice.goal,
|
|
150
|
+
successCriteria: slice.successCriteria,
|
|
151
|
+
proofLevel: slice.proofLevel,
|
|
152
|
+
integrationClosure: slice.integrationClosure,
|
|
153
|
+
observabilityImpact: slice.observabilityImpact,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function renderPlanArtifacts(
|
|
159
|
+
basePath: string,
|
|
160
|
+
params: PersistMilestonePlanParams,
|
|
161
|
+
): Promise<string | { error: string }> {
|
|
162
|
+
try {
|
|
163
|
+
const renderResult = await renderRoadmapFromDb(basePath, params.milestoneId);
|
|
164
|
+
return renderResult.roadmapPath;
|
|
165
|
+
} catch (renderErr) {
|
|
166
|
+
logWarning("tool", `plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}`);
|
|
167
|
+
invalidateStateCache();
|
|
168
|
+
return { error: `render failed: ${(renderErr as Error).message}` };
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
async function runPostPlanHooks(basePath: string, params: PersistMilestonePlanParams): Promise<void> {
|
|
173
|
+
try {
|
|
174
|
+
await renderAllProjections(basePath, params.milestoneId);
|
|
175
|
+
writeManifest(basePath);
|
|
176
|
+
appendEvent(basePath, {
|
|
177
|
+
cmd: "plan-milestone",
|
|
178
|
+
params: { milestoneId: params.milestoneId },
|
|
179
|
+
ts: new Date().toISOString(),
|
|
180
|
+
actor: "agent",
|
|
181
|
+
actor_name: params.actorName,
|
|
182
|
+
trigger_reason: params.triggerReason,
|
|
183
|
+
});
|
|
184
|
+
} catch (hookErr) {
|
|
185
|
+
logWarning("tool", `plan-milestone post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export async function persistMilestonePlan(
|
|
190
|
+
params: PersistMilestonePlanParams,
|
|
191
|
+
basePath: string,
|
|
192
|
+
): Promise<PersistMilestonePlanResult | { error: string }> {
|
|
193
|
+
// ── Guards + DB writes inside a single transaction (prevents TOCTOU) ───
|
|
194
|
+
// Guards must be inside the transaction so the state they check cannot
|
|
195
|
+
// change between the read and the write (#2723).
|
|
196
|
+
let guardError: string | null = null;
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
transaction(() => {
|
|
200
|
+
guardError = validatePlanPromotion(params);
|
|
201
|
+
if (guardError) return;
|
|
202
|
+
writePlanRows(params);
|
|
203
|
+
});
|
|
204
|
+
} catch (err) {
|
|
205
|
+
return { error: `db write failed: ${(err as Error).message}` };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (guardError) {
|
|
209
|
+
return { error: guardError };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const roadmapPath = await renderPlanArtifacts(basePath, params);
|
|
213
|
+
if (typeof roadmapPath !== "string") return roadmapPath;
|
|
214
|
+
|
|
215
|
+
invalidateStateCache();
|
|
216
|
+
clearParseCache();
|
|
217
|
+
|
|
218
|
+
await runPostPlanHooks(basePath, params);
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
milestoneId: params.milestoneId,
|
|
222
|
+
roadmapPath,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Classify milestone readiness from DB status, slices, and artifacts.
|
|
3
|
+
|
|
4
|
+
import { readFileSync } from "node:fs";
|
|
5
|
+
import type { Phase } from "./types.js";
|
|
6
|
+
import { getMilestone, getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
|
|
7
|
+
import { parseRoadmapSlices } from "./roadmap-slices.js";
|
|
8
|
+
import { logWarning } from "./workflow-logger.js";
|
|
9
|
+
|
|
10
|
+
export type MilestoneReadinessKind =
|
|
11
|
+
| "queued-shell"
|
|
12
|
+
| "needs-discussion"
|
|
13
|
+
| "planning-pending"
|
|
14
|
+
| "executable-plan"
|
|
15
|
+
| "terminal";
|
|
16
|
+
|
|
17
|
+
export interface MilestoneReadiness {
|
|
18
|
+
kind: MilestoneReadinessKind;
|
|
19
|
+
hasContext: boolean;
|
|
20
|
+
hasDraftContext: boolean;
|
|
21
|
+
hasExecutablePlan: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface MilestoneReadinessInput {
|
|
25
|
+
status?: string | null;
|
|
26
|
+
hasContext?: boolean;
|
|
27
|
+
hasDraftContext?: boolean;
|
|
28
|
+
hasSummary?: boolean;
|
|
29
|
+
sliceCount?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface HandoffReadinessInput {
|
|
33
|
+
milestoneId: string;
|
|
34
|
+
contextFile: string | null;
|
|
35
|
+
roadmapFile: string | null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function classifyMilestoneReadiness(input: MilestoneReadinessInput): MilestoneReadiness {
|
|
39
|
+
const hasContext = input.hasContext === true;
|
|
40
|
+
const hasDraftContext = !hasContext && input.hasDraftContext === true;
|
|
41
|
+
const hasSummary = input.hasSummary === true;
|
|
42
|
+
const sliceCount = input.sliceCount ?? 0;
|
|
43
|
+
const hasExecutablePlan = sliceCount > 0;
|
|
44
|
+
const status = input.status ?? null;
|
|
45
|
+
|
|
46
|
+
if (status === "complete" || hasSummary) {
|
|
47
|
+
return { kind: "terminal", hasContext, hasDraftContext, hasExecutablePlan };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (status === "queued" && !hasContext && sliceCount === 0) {
|
|
51
|
+
return { kind: "queued-shell", hasContext, hasDraftContext, hasExecutablePlan };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if ((status === "needs-discussion" && !hasContext) || hasDraftContext) {
|
|
55
|
+
return { kind: "needs-discussion", hasContext, hasDraftContext, hasExecutablePlan };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (hasExecutablePlan) {
|
|
59
|
+
return { kind: "executable-plan", hasContext, hasDraftContext, hasExecutablePlan };
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return { kind: "planning-pending", hasContext, hasDraftContext, hasExecutablePlan };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function readinessNeedsDiscussion(readiness: MilestoneReadiness): boolean {
|
|
66
|
+
return readiness.kind === "needs-discussion" ||
|
|
67
|
+
(readiness.kind === "queued-shell" && readiness.hasDraftContext);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export function describeMilestoneReadinessPhase(
|
|
71
|
+
phase: Phase,
|
|
72
|
+
): { label: string; description: string } | null {
|
|
73
|
+
switch (phase) {
|
|
74
|
+
case "needs-discussion":
|
|
75
|
+
return {
|
|
76
|
+
label: "Discuss milestone draft",
|
|
77
|
+
description: "Milestone has a draft context — needs discussion before planning.",
|
|
78
|
+
};
|
|
79
|
+
case "pre-planning":
|
|
80
|
+
return {
|
|
81
|
+
label: "Research & plan milestone",
|
|
82
|
+
description: "Scout the landscape and create the roadmap.",
|
|
83
|
+
};
|
|
84
|
+
default:
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function executablePlanSliceCount(milestoneId: string, roadmapFile: string | null): number {
|
|
90
|
+
if (isDbAvailable()) {
|
|
91
|
+
return getMilestoneSlices(milestoneId).length;
|
|
92
|
+
}
|
|
93
|
+
if (!roadmapFile) return 0;
|
|
94
|
+
try {
|
|
95
|
+
return parseRoadmapSlices(readFileSync(roadmapFile, "utf-8")).length;
|
|
96
|
+
} catch (e) {
|
|
97
|
+
logWarning(
|
|
98
|
+
"guided",
|
|
99
|
+
`failed to parse roadmap slices for ${milestoneId}: ${(e as Error).message}`,
|
|
100
|
+
);
|
|
101
|
+
return 0;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function assessMilestoneHandoffReadiness(
|
|
106
|
+
input: HandoffReadinessInput,
|
|
107
|
+
): MilestoneReadiness {
|
|
108
|
+
const milestone = isDbAvailable() ? getMilestone(input.milestoneId) : null;
|
|
109
|
+
return classifyMilestoneReadiness({
|
|
110
|
+
status: milestone?.status,
|
|
111
|
+
hasContext: input.contextFile != null,
|
|
112
|
+
sliceCount: executablePlanSliceCount(input.milestoneId, input.roadmapFile),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function formatAcceptedDiscussHandoffMessage(
|
|
117
|
+
milestoneId: string,
|
|
118
|
+
readiness: MilestoneReadiness,
|
|
119
|
+
): string {
|
|
120
|
+
if (readiness.hasExecutablePlan) return `Milestone ${milestoneId} ready.`;
|
|
121
|
+
if (readiness.hasContext) {
|
|
122
|
+
return `Milestone ${milestoneId} context captured. Continuing the planning pipeline.`;
|
|
123
|
+
}
|
|
124
|
+
return `Milestone ${milestoneId} planning artifacts captured. Continuing the planning pipeline.`;
|
|
125
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Milestone closeout settlement state across DB proof, artifacts, merge, and cleanup.
|
|
3
|
+
|
|
4
|
+
import { isInAutoWorktree } from "./auto-worktree.js";
|
|
5
|
+
import {
|
|
6
|
+
formatCloseoutProofBlock,
|
|
7
|
+
proveMilestoneCloseout,
|
|
8
|
+
} from "./milestone-closeout-proof.js";
|
|
9
|
+
import { resolveCloseoutArtifactProjection } from "./artifact-projection.js";
|
|
10
|
+
|
|
11
|
+
export type MilestoneSettlementOutcome =
|
|
12
|
+
| { ok: true; reason: "settled" | "not-applicable" }
|
|
13
|
+
| {
|
|
14
|
+
ok: false;
|
|
15
|
+
reason: "closeout-blocked" | "merge-pending";
|
|
16
|
+
action: "pause";
|
|
17
|
+
message: string;
|
|
18
|
+
nextAction: string;
|
|
19
|
+
milestoneId: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface MilestoneSettlementInput {
|
|
23
|
+
milestoneId: string | null | undefined;
|
|
24
|
+
statePhase: string;
|
|
25
|
+
basePath: string;
|
|
26
|
+
originalBasePath: string;
|
|
27
|
+
milestoneMerged: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isActiveUnmergedWorktree(input: MilestoneSettlementInput): boolean {
|
|
31
|
+
if (!input.milestoneId || input.milestoneMerged) return false;
|
|
32
|
+
return isInAutoWorktree(input.basePath);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function evaluateAllCompleteSettlement(
|
|
36
|
+
input: MilestoneSettlementInput,
|
|
37
|
+
): MilestoneSettlementOutcome {
|
|
38
|
+
if (input.statePhase !== "complete") {
|
|
39
|
+
return { ok: true, reason: "not-applicable" };
|
|
40
|
+
}
|
|
41
|
+
if (!isActiveUnmergedWorktree(input)) {
|
|
42
|
+
return { ok: true, reason: "settled" };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const milestoneId = input.milestoneId;
|
|
46
|
+
if (!milestoneId) {
|
|
47
|
+
return { ok: true, reason: "settled" };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const projection = resolveCloseoutArtifactProjection({
|
|
51
|
+
milestoneId,
|
|
52
|
+
basePath: input.basePath,
|
|
53
|
+
originalBasePath: input.originalBasePath,
|
|
54
|
+
});
|
|
55
|
+
const proof = proveMilestoneCloseout(milestoneId, {
|
|
56
|
+
refreshFromDisk: true,
|
|
57
|
+
summaryArtifactBasePath: projection.summaryArtifactBasePath,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
if (!proof.ok) {
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
reason: "closeout-blocked",
|
|
64
|
+
action: "pause",
|
|
65
|
+
message: `${formatCloseoutProofBlock(proof)} The milestone branch has not been merged to main.`,
|
|
66
|
+
nextAction: `Resolve closeout blockers, then retry \`/gsd dispatch complete-milestone ${milestoneId}\`.`,
|
|
67
|
+
milestoneId,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
reason: "merge-pending",
|
|
74
|
+
action: "pause",
|
|
75
|
+
message:
|
|
76
|
+
`Milestone ${milestoneId} is complete, but its worktree branch has not been merged to main. ` +
|
|
77
|
+
`Retry with \`/gsd dispatch complete-milestone ${milestoneId}\` or merge manually.`,
|
|
78
|
+
nextAction: `Retry \`/gsd dispatch complete-milestone ${milestoneId}\` or merge manually.`,
|
|
79
|
+
milestoneId,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Forwarded validation evidence rules for milestone validation.
|
|
3
|
+
|
|
4
|
+
import { getArtifact, getMilestone, getMilestoneSlices } from "./gsd-db.js";
|
|
5
|
+
import { loadFile } from "./files.js";
|
|
6
|
+
import { resolveSliceFile } from "./paths.js";
|
|
7
|
+
import {
|
|
8
|
+
compactTextParts,
|
|
9
|
+
hasBrowserEvidenceText,
|
|
10
|
+
hasBrowserRequiredText,
|
|
11
|
+
} from "./browser-evidence.js";
|
|
12
|
+
|
|
13
|
+
export interface MilestoneValidationEvidenceParams {
|
|
14
|
+
milestoneId: string;
|
|
15
|
+
verdict: "pass" | "needs-attention" | "needs-remediation";
|
|
16
|
+
successCriteriaChecklist: string;
|
|
17
|
+
verificationClasses?: string;
|
|
18
|
+
verdictRationale: string;
|
|
19
|
+
remediationPlan?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function hasRuntimeExecutableUatEvidenceText(text: string): boolean {
|
|
23
|
+
if (!/\buatType:\s*runtime-executable\b/i.test(text)) return false;
|
|
24
|
+
if (!/\bverdict:\s*PASS\b/i.test(text)) return false;
|
|
25
|
+
return /^\|\s*[^|\n]+\s*\|\s*runtime\s*\|\s*PASS\s*\|[^|\n]*\bgsd_uat_exec\b/mi.test(text);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export async function browserEvidenceGateRequiresAttention(
|
|
29
|
+
params: MilestoneValidationEvidenceParams,
|
|
30
|
+
basePath: string,
|
|
31
|
+
): Promise<boolean> {
|
|
32
|
+
if (params.verdict !== "pass") return false;
|
|
33
|
+
|
|
34
|
+
const milestone = getMilestone(params.milestoneId);
|
|
35
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
36
|
+
const requirementText = compactTextParts([
|
|
37
|
+
milestone?.vision,
|
|
38
|
+
milestone?.success_criteria,
|
|
39
|
+
milestone?.verification_uat,
|
|
40
|
+
params.successCriteriaChecklist,
|
|
41
|
+
params.verificationClasses,
|
|
42
|
+
...slices.flatMap((slice) => [
|
|
43
|
+
slice.demo,
|
|
44
|
+
slice.goal,
|
|
45
|
+
slice.success_criteria,
|
|
46
|
+
]),
|
|
47
|
+
]);
|
|
48
|
+
if (!hasBrowserRequiredText(requirementText)) return false;
|
|
49
|
+
|
|
50
|
+
const sliceEvidencePairs: Array<{ sliceRequirementText: string; evidenceText: string }> = [];
|
|
51
|
+
for (const slice of slices) {
|
|
52
|
+
const chunks: string[] = [];
|
|
53
|
+
const artifactPath = `milestones/${params.milestoneId}/slices/${slice.id}/${slice.id}-ASSESSMENT.md`;
|
|
54
|
+
const artifact = getArtifact(artifactPath);
|
|
55
|
+
if (artifact?.full_content) chunks.push(artifact.full_content);
|
|
56
|
+
const assessmentPath = resolveSliceFile(basePath, params.milestoneId, slice.id, "ASSESSMENT");
|
|
57
|
+
const assessmentContent = assessmentPath ? await loadFile(assessmentPath) : null;
|
|
58
|
+
if (assessmentContent) chunks.push(assessmentContent);
|
|
59
|
+
sliceEvidencePairs.push({
|
|
60
|
+
sliceRequirementText: compactTextParts([slice.demo, slice.goal, slice.success_criteria]),
|
|
61
|
+
evidenceText: chunks.join("\n\n"),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const browserRequiringSlices = sliceEvidencePairs.filter((slice) =>
|
|
66
|
+
hasBrowserRequiredText(slice.sliceRequirementText),
|
|
67
|
+
);
|
|
68
|
+
const runtimeBypasses =
|
|
69
|
+
browserRequiringSlices.length > 0
|
|
70
|
+
? browserRequiringSlices.every((slice) => hasRuntimeExecutableUatEvidenceText(slice.evidenceText))
|
|
71
|
+
: sliceEvidencePairs.some((slice) => hasRuntimeExecutableUatEvidenceText(slice.evidenceText));
|
|
72
|
+
if (runtimeBypasses) return false;
|
|
73
|
+
|
|
74
|
+
const persistedEvidence = sliceEvidencePairs.map((slice) => slice.evidenceText).join("\n\n");
|
|
75
|
+
const validationEvidence = compactTextParts([
|
|
76
|
+
params.successCriteriaChecklist,
|
|
77
|
+
params.verificationClasses,
|
|
78
|
+
params.verdictRationale,
|
|
79
|
+
params.remediationPlan,
|
|
80
|
+
]);
|
|
81
|
+
return !hasBrowserEvidenceText(`${persistedEvidence}\n\n${validationEvidence}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function applyBrowserEvidenceGate<T extends MilestoneValidationEvidenceParams>(
|
|
85
|
+
params: T,
|
|
86
|
+
): Omit<T, "verdict" | "verdictRationale"> & { verdict: "needs-attention"; verdictRationale: string } {
|
|
87
|
+
const note = "Browser evidence gate: Browser-observable acceptance criteria were detected, but no persisted ASSESSMENT or validation evidence recorded browser actions with assertions. Downgraded from pass to needs-attention.";
|
|
88
|
+
return {
|
|
89
|
+
...params,
|
|
90
|
+
verdict: "needs-attention",
|
|
91
|
+
verdictRationale: params.verdictRationale.trim()
|
|
92
|
+
? `${params.verdictRationale.trim()}\n\n${note}`
|
|
93
|
+
: note,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Resolve the authoritative milestone validation verdict across DB and disk projections.
|
|
3
|
+
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
|
|
7
|
+
import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
|
|
8
|
+
import { loadFile } from "./files.js";
|
|
9
|
+
import { getLatestAssessmentByScope, isDbAvailable } from "./gsd-db.js";
|
|
10
|
+
import { gsdProjectionRoot } from "./paths.js";
|
|
11
|
+
import {
|
|
12
|
+
extractVerdict,
|
|
13
|
+
isValidMilestoneVerdict,
|
|
14
|
+
type ValidationVerdict,
|
|
15
|
+
} from "./verdict-parser.js";
|
|
16
|
+
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
17
|
+
import { resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
18
|
+
|
|
19
|
+
function verdictFromContent(content: string | null | undefined): ValidationVerdict | undefined {
|
|
20
|
+
if (!content) return undefined;
|
|
21
|
+
const verdict = extractVerdict(content);
|
|
22
|
+
return verdict && isValidMilestoneVerdict(verdict) ? verdict : undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function verdictFromDb(milestoneId: string): ValidationVerdict | undefined {
|
|
26
|
+
if (!isDbAvailable()) return undefined;
|
|
27
|
+
const assessment = getLatestAssessmentByScope(milestoneId, "milestone-validation");
|
|
28
|
+
const status = typeof assessment?.status === "string" ? assessment.status : undefined;
|
|
29
|
+
return status && isValidMilestoneVerdict(status) ? status : undefined;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function verdictFromValidationPath(path: string | null): Promise<ValidationVerdict | undefined> {
|
|
33
|
+
if (!path || !existsSync(path)) return undefined;
|
|
34
|
+
return verdictFromContent(await loadFile(path));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Resolve the milestone validation verdict using the same authority order as
|
|
39
|
+
* DB-backed state derivation, with filesystem fallbacks that mirror
|
|
40
|
+
* `resolveExpectedArtifactPath` (canonical worktree projection, then project
|
|
41
|
+
* root). Manual `/gsd verdict` overrides persist to the DB first; a stale
|
|
42
|
+
* worktree-local VALIDATION.md must not re-block auto-mode after the override.
|
|
43
|
+
*/
|
|
44
|
+
export async function resolveMilestoneValidationVerdict(
|
|
45
|
+
basePath: string,
|
|
46
|
+
milestoneId: string,
|
|
47
|
+
): Promise<ValidationVerdict | undefined> {
|
|
48
|
+
const dbVerdict = verdictFromDb(milestoneId);
|
|
49
|
+
if (dbVerdict) return dbVerdict;
|
|
50
|
+
|
|
51
|
+
const canonicalBase = resolveCanonicalMilestoneRoot(basePath, milestoneId);
|
|
52
|
+
const canonicalPath = resolveExpectedArtifactPath(
|
|
53
|
+
"validate-milestone",
|
|
54
|
+
milestoneId,
|
|
55
|
+
canonicalBase,
|
|
56
|
+
);
|
|
57
|
+
const canonicalVerdict = await verdictFromValidationPath(canonicalPath);
|
|
58
|
+
if (canonicalVerdict) return canonicalVerdict;
|
|
59
|
+
|
|
60
|
+
const projectRoot = resolveWorktreeProjectRoot(basePath);
|
|
61
|
+
if (projectRoot !== canonicalBase) {
|
|
62
|
+
const projectPath = resolveExpectedArtifactPath(
|
|
63
|
+
"validate-milestone",
|
|
64
|
+
milestoneId,
|
|
65
|
+
projectRoot,
|
|
66
|
+
);
|
|
67
|
+
const projectVerdict = await verdictFromValidationPath(projectPath);
|
|
68
|
+
if (projectVerdict) return projectVerdict;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Last resort: direct canonical projection path even when resolveDir helpers
|
|
72
|
+
// have not materialized the milestone directory yet.
|
|
73
|
+
const directPath = join(
|
|
74
|
+
gsdProjectionRoot(canonicalBase),
|
|
75
|
+
"milestones",
|
|
76
|
+
milestoneId,
|
|
77
|
+
`${milestoneId}-VALIDATION.md`,
|
|
78
|
+
);
|
|
79
|
+
return verdictFromValidationPath(directPath);
|
|
80
|
+
}
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* dependency satisfaction and file overlap across slice plans.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { existsSync } from "node:fs";
|
|
9
8
|
import { deriveState } from "./state.js";
|
|
10
|
-
import {
|
|
9
|
+
import { resolveMilestoneFile, resolveSliceFile } from "./paths.js";
|
|
11
10
|
import { findMilestoneIds } from "./guided-flow.js";
|
|
12
|
-
import { isDbAvailable, getMilestoneSlices, getSliceTasks
|
|
11
|
+
import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
|
|
12
|
+
import { openExistingWorkflowDatabase } from "./db-workspace.js";
|
|
13
13
|
import type { MilestoneRegistryEntry } from "./types.js";
|
|
14
14
|
|
|
15
15
|
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
@@ -98,8 +98,7 @@ export async function analyzeParallelEligibility(
|
|
|
98
98
|
basePath: string,
|
|
99
99
|
): Promise<ParallelCandidates> {
|
|
100
100
|
if (!isDbAvailable()) {
|
|
101
|
-
|
|
102
|
-
if (existsSync(projectDb)) openDatabase(projectDb);
|
|
101
|
+
openExistingWorkflowDatabase(basePath);
|
|
103
102
|
}
|
|
104
103
|
|
|
105
104
|
const milestoneIds = findMilestoneIds(basePath);
|
|
@@ -21,9 +21,10 @@ import { join, dirname } from "node:path";
|
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
import { gsdRoot } from "./paths.js";
|
|
23
23
|
import { createWorktree, worktreePath } from "./worktree-manager.js";
|
|
24
|
-
import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe, runWorktreePostCreateHook,
|
|
24
|
+
import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe, runWorktreePostCreateHook, syncGsdStateToWorktreeByScope } from "./auto-worktree.js";
|
|
25
25
|
import { nativeBranchExists } from "./native-git-bridge.js";
|
|
26
26
|
import { readIntegrationBranch } from "./git-service.js";
|
|
27
|
+
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
27
28
|
import { resolveParallelConfig } from "./preferences.js";
|
|
28
29
|
import type { GSDPreferences } from "./preferences.js";
|
|
29
30
|
import type { ParallelConfig } from "./types.js";
|
|
@@ -561,7 +562,10 @@ export function _createMilestoneWorktree(basePath: string, milestoneId: string):
|
|
|
561
562
|
// Copy .gsd/ planning artifacts (milestones, CONTEXT, ROADMAP, etc.) from the
|
|
562
563
|
// project root into the worktree. Without this, workers for newly-planned
|
|
563
564
|
// milestones can't find their roadmap and exit immediately (#2184 Bug 4).
|
|
564
|
-
|
|
565
|
+
syncGsdStateToWorktreeByScope(
|
|
566
|
+
scopeMilestone(createWorkspace(basePath), milestoneId),
|
|
567
|
+
scopeMilestone(createWorkspace(info.path), milestoneId),
|
|
568
|
+
);
|
|
565
569
|
|
|
566
570
|
return info.path;
|
|
567
571
|
}
|