@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,41 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Process-level pull request policy for GSD-generated PRs.
|
|
3
|
+
|
|
4
|
+
import { createDraftPR } from "./git-service.js";
|
|
5
|
+
import {
|
|
6
|
+
buildPrEvidence,
|
|
7
|
+
type PrEvidence,
|
|
8
|
+
type PrEvidenceInput,
|
|
9
|
+
} from "./pr-evidence.js";
|
|
10
|
+
|
|
11
|
+
export interface DraftPullRequestOptions {
|
|
12
|
+
head: string;
|
|
13
|
+
base: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface DraftPullRequestDeps {
|
|
17
|
+
createDraftPR: (
|
|
18
|
+
basePath: string,
|
|
19
|
+
milestoneId: string,
|
|
20
|
+
title: string,
|
|
21
|
+
body: string,
|
|
22
|
+
opts: DraftPullRequestOptions,
|
|
23
|
+
) => string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function buildPullRequestEvidence(input: PrEvidenceInput): PrEvidence {
|
|
27
|
+
return buildPrEvidence({
|
|
28
|
+
...input,
|
|
29
|
+
aiAssisted: false,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createDraftPullRequestFromEvidence(
|
|
34
|
+
basePath: string,
|
|
35
|
+
milestoneId: string,
|
|
36
|
+
evidence: PrEvidence,
|
|
37
|
+
options: DraftPullRequestOptions,
|
|
38
|
+
deps: DraftPullRequestDeps = { createDraftPR },
|
|
39
|
+
): string | null {
|
|
40
|
+
return deps.createDraftPR(basePath, milestoneId, evidence.title, evidence.body, options);
|
|
41
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Canonical quality-gate closure from durable DB and artifact evidence.
|
|
3
|
+
|
|
4
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
+
|
|
6
|
+
import { extractSection } from "./files.js";
|
|
7
|
+
import { getGateDefinition } from "./gate-registry.js";
|
|
8
|
+
import { getMilestoneSlices, getPendingGates, saveGateResult } from "./gsd-db.js";
|
|
9
|
+
import { resolveSliceFile, resolveTaskFile } from "./paths.js";
|
|
10
|
+
import type { GateId, GateRow, GateVerdict } from "./types.js";
|
|
11
|
+
|
|
12
|
+
export interface QualityGateClosureOptions {
|
|
13
|
+
artifactBasePath?: string;
|
|
14
|
+
milestoneValidationPassed?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface QualityGateClosureResult {
|
|
18
|
+
repaired: Array<{ gateId: GateId; sliceId: string; taskId?: string; verdict: GateVerdict }>;
|
|
19
|
+
unresolved: GateRow[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface GateEvidence {
|
|
23
|
+
verdict: GateVerdict;
|
|
24
|
+
rationale: string;
|
|
25
|
+
findings: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const GATE_SECTION_HEADINGS: Partial<Record<GateId, string[]>> = {
|
|
29
|
+
Q3: ["Threat Surface", "Abuse Surface"],
|
|
30
|
+
Q4: ["Requirement Impact", "Broken Promises"],
|
|
31
|
+
Q5: ["Failure Modes"],
|
|
32
|
+
Q6: ["Load Profile"],
|
|
33
|
+
Q7: ["Negative Tests"],
|
|
34
|
+
Q8: ["Operational Readiness"],
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function readFile(path: string | null): string | null {
|
|
38
|
+
if (!path || !existsSync(path)) return null;
|
|
39
|
+
return readFileSync(path, "utf-8");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function firstSection(content: string | null, gateId: GateId): string | null {
|
|
43
|
+
if (!content) return null;
|
|
44
|
+
for (const heading of GATE_SECTION_HEADINGS[gateId] ?? []) {
|
|
45
|
+
const section = extractSection(content, heading);
|
|
46
|
+
if (section) return section;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function evidenceArtifactContent(row: GateRow, basePath: string): string | null {
|
|
52
|
+
const def = getGateDefinition(row.gate_id);
|
|
53
|
+
switch (def?.ownerTurn) {
|
|
54
|
+
case "gate-evaluate":
|
|
55
|
+
return readFile(resolveSliceFile(basePath, row.milestone_id, row.slice_id, "PLAN"));
|
|
56
|
+
case "execute-task":
|
|
57
|
+
return readFile(resolveTaskFile(basePath, row.milestone_id, row.slice_id, row.task_id, "SUMMARY"));
|
|
58
|
+
case "complete-slice":
|
|
59
|
+
return readFile(resolveSliceFile(basePath, row.milestone_id, row.slice_id, "SUMMARY"));
|
|
60
|
+
default:
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function closureEvidence(row: GateRow, options: QualityGateClosureOptions): GateEvidence | null {
|
|
66
|
+
const def = getGateDefinition(row.gate_id);
|
|
67
|
+
if (!def) return null;
|
|
68
|
+
|
|
69
|
+
if (def.ownerTurn === "validate-milestone" && options.milestoneValidationPassed) {
|
|
70
|
+
return {
|
|
71
|
+
verdict: "pass",
|
|
72
|
+
rationale: `${def.promptSection} covered by passing milestone validation`,
|
|
73
|
+
findings: "",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!options.artifactBasePath) return null;
|
|
78
|
+
|
|
79
|
+
const section = firstSection(evidenceArtifactContent(row, options.artifactBasePath), row.gate_id);
|
|
80
|
+
if (section) {
|
|
81
|
+
return {
|
|
82
|
+
verdict: "pass",
|
|
83
|
+
rationale: `${def.promptSection} evidence found in durable artifact`,
|
|
84
|
+
findings: section,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!options.milestoneValidationPassed) return null;
|
|
89
|
+
return {
|
|
90
|
+
verdict: "omitted",
|
|
91
|
+
rationale: `${def.promptSection} has no durable artifact section; milestone validation passed`,
|
|
92
|
+
findings: "",
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function closeGate(row: GateRow, evidence: GateEvidence): void {
|
|
97
|
+
saveGateResult({
|
|
98
|
+
milestoneId: row.milestone_id,
|
|
99
|
+
sliceId: row.slice_id,
|
|
100
|
+
gateId: row.gate_id,
|
|
101
|
+
taskId: row.task_id,
|
|
102
|
+
verdict: evidence.verdict,
|
|
103
|
+
rationale: evidence.rationale,
|
|
104
|
+
findings: evidence.findings,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export function closeQualityGatesFromEvidence(
|
|
109
|
+
milestoneId: string,
|
|
110
|
+
options: QualityGateClosureOptions = {},
|
|
111
|
+
): QualityGateClosureResult {
|
|
112
|
+
const repaired: QualityGateClosureResult["repaired"] = [];
|
|
113
|
+
const unresolved: GateRow[] = [];
|
|
114
|
+
|
|
115
|
+
for (const slice of getMilestoneSlices(milestoneId)) {
|
|
116
|
+
const sliceId = slice.id;
|
|
117
|
+
for (const row of getPendingGates(milestoneId, sliceId)) {
|
|
118
|
+
if (!getGateDefinition(row.gate_id)) {
|
|
119
|
+
unresolved.push(row);
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const evidence = closureEvidence(row, options);
|
|
124
|
+
if (!evidence) {
|
|
125
|
+
unresolved.push(row);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
closeGate(row, evidence);
|
|
130
|
+
repaired.push({
|
|
131
|
+
gateId: row.gate_id,
|
|
132
|
+
sliceId: row.slice_id,
|
|
133
|
+
...(row.task_id ? { taskId: row.task_id } : {}),
|
|
134
|
+
verdict: evidence.verdict,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return { repaired, unresolved };
|
|
140
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Resolve how workflow units should ask the user for input.
|
|
3
|
+
|
|
4
|
+
import { parseMcpToolName, toMcpToolName } from "./mcp-tool-name.js";
|
|
5
|
+
|
|
6
|
+
export type StructuredQuestionsFlag = "true" | "false";
|
|
7
|
+
|
|
8
|
+
export interface QuestionTransportOptions {
|
|
9
|
+
activeTools: string[];
|
|
10
|
+
authMode?: "apiKey" | "oauth" | "externalCli" | "none";
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
env?: NodeJS.ProcessEnv;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface QuestionTransportResolution {
|
|
16
|
+
structuredQuestionsAvailable: StructuredQuestionsFlag;
|
|
17
|
+
questionToolAvailable: boolean;
|
|
18
|
+
usesWorkflowMcp: boolean;
|
|
19
|
+
reason: "question-tool-available" | "question-tool-missing" | "workflow-mcp-disabled";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface WorkflowQuestionToolSurfaceOptions {
|
|
23
|
+
workflowServerName?: string;
|
|
24
|
+
workflowExplicitlyBlocked?: boolean;
|
|
25
|
+
workflowMcpTools: string[];
|
|
26
|
+
exactWorkflowMcpTools: string[];
|
|
27
|
+
env?: NodeJS.ProcessEnv;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface WorkflowQuestionToolSurfaceResolution extends QuestionTransportResolution {
|
|
31
|
+
questionToolName?: string;
|
|
32
|
+
workflowQuestionsEnabled: boolean;
|
|
33
|
+
disallowedTools: string[];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function isWorkflowMcpServerName(serverName: string): boolean {
|
|
37
|
+
const normalized = serverName.toLowerCase();
|
|
38
|
+
return normalized === "gsd" || normalized.includes("workflow");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function usesWorkflowMcpTransport(
|
|
42
|
+
authMode: QuestionTransportOptions["authMode"],
|
|
43
|
+
baseUrl: string | undefined,
|
|
44
|
+
): boolean {
|
|
45
|
+
return authMode === "externalCli" && typeof baseUrl === "string" && baseUrl.startsWith("local://");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function hasAskUserQuestionsTool(activeTools: string[]): boolean {
|
|
49
|
+
return activeTools.some((toolName) => {
|
|
50
|
+
if (toolName === "ask_user_questions") return true;
|
|
51
|
+
const mcp = parseMcpToolName(toolName);
|
|
52
|
+
if (!mcp) return false;
|
|
53
|
+
if (mcp.toolName === "ask_user_questions") return true;
|
|
54
|
+
return mcp.toolName === "*" && isWorkflowMcpServerName(mcp.serverName);
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function workflowMcpStructuredQuestionsEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
59
|
+
const value = env.GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS?.trim().toLowerCase();
|
|
60
|
+
return value !== "0" && value !== "false" && value !== "off";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function resolveQuestionTransport(
|
|
64
|
+
options: QuestionTransportOptions,
|
|
65
|
+
): QuestionTransportResolution {
|
|
66
|
+
const questionToolAvailable = hasAskUserQuestionsTool(options.activeTools);
|
|
67
|
+
const usesWorkflowMcp = usesWorkflowMcpTransport(options.authMode, options.baseUrl);
|
|
68
|
+
|
|
69
|
+
if (!questionToolAvailable) {
|
|
70
|
+
return {
|
|
71
|
+
structuredQuestionsAvailable: "false",
|
|
72
|
+
questionToolAvailable,
|
|
73
|
+
usesWorkflowMcp,
|
|
74
|
+
reason: "question-tool-missing",
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (options.authMode === "externalCli" && !workflowMcpStructuredQuestionsEnabled(options.env)) {
|
|
79
|
+
return {
|
|
80
|
+
structuredQuestionsAvailable: "false",
|
|
81
|
+
questionToolAvailable,
|
|
82
|
+
usesWorkflowMcp,
|
|
83
|
+
reason: "workflow-mcp-disabled",
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return {
|
|
88
|
+
structuredQuestionsAvailable: "true",
|
|
89
|
+
questionToolAvailable,
|
|
90
|
+
usesWorkflowMcp,
|
|
91
|
+
reason: "question-tool-available",
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function supportsStructuredQuestions(
|
|
96
|
+
activeTools: string[],
|
|
97
|
+
options: Omit<QuestionTransportOptions, "activeTools"> = {},
|
|
98
|
+
): boolean {
|
|
99
|
+
return resolveQuestionTransport({
|
|
100
|
+
...options,
|
|
101
|
+
activeTools,
|
|
102
|
+
}).structuredQuestionsAvailable === "true";
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function resolveWorkflowQuestionToolSurface(
|
|
106
|
+
options: WorkflowQuestionToolSurfaceOptions,
|
|
107
|
+
): WorkflowQuestionToolSurfaceResolution {
|
|
108
|
+
const questionToolName = options.workflowServerName && !options.workflowExplicitlyBlocked
|
|
109
|
+
? toMcpToolName(options.workflowServerName, "ask_user_questions")
|
|
110
|
+
: undefined;
|
|
111
|
+
const activeTools = [
|
|
112
|
+
...options.exactWorkflowMcpTools,
|
|
113
|
+
...options.workflowMcpTools,
|
|
114
|
+
...(questionToolName ? [questionToolName] : []),
|
|
115
|
+
];
|
|
116
|
+
const transport = resolveQuestionTransport({
|
|
117
|
+
activeTools,
|
|
118
|
+
authMode: "externalCli",
|
|
119
|
+
baseUrl: "local://claude-code",
|
|
120
|
+
env: options.env,
|
|
121
|
+
});
|
|
122
|
+
const exactQuestionToolAllowed =
|
|
123
|
+
!!questionToolName && options.exactWorkflowMcpTools.includes(questionToolName);
|
|
124
|
+
const workflowQuestionsEnabled =
|
|
125
|
+
transport.structuredQuestionsAvailable === "true" &&
|
|
126
|
+
(options.workflowMcpTools.length > 0 || exactQuestionToolAllowed);
|
|
127
|
+
const disallowedTools =
|
|
128
|
+
options.workflowServerName && transport.questionToolAvailable && !workflowQuestionsEnabled
|
|
129
|
+
? [toMcpToolName(options.workflowServerName, "ask_user_questions")]
|
|
130
|
+
: [];
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
...transport,
|
|
134
|
+
questionToolName,
|
|
135
|
+
workflowQuestionsEnabled,
|
|
136
|
+
disallowedTools,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
@@ -189,9 +189,15 @@ export function parseRoadmapSlices(content: string): RoadmapSliceEntry[] {
|
|
|
189
189
|
const risk = (riskMatch ? riskMatch[1] : "low") as RiskLevel;
|
|
190
190
|
|
|
191
191
|
const depsMatch = rest.match(/`depends:\[([^\]]*)\]`/);
|
|
192
|
-
|
|
193
|
-
|
|
192
|
+
// Recovery fallback: double-bracket form `[[id]]` from serialized bracket-wrapped IDs
|
|
193
|
+
const fallbackDepsMatch = depsMatch ? null : rest.match(/`depends:\[(\[(?:[^\]]*)\](?:,\[(?:[^\]]*)\])*)\]`/);
|
|
194
|
+
const rawDepContent = (depsMatch ?? fallbackDepsMatch)?.[1] ?? "";
|
|
195
|
+
const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
196
|
+
const RANGE_RE = /^[A-Za-z]+\d+(?:-|\.\.)[A-Za-z]+\d+$/;
|
|
197
|
+
const rawDepParts = rawDepContent.trim()
|
|
198
|
+
? rawDepContent.replace(/\[|\]/g, "").split(",").map(s => s.trim()).filter(s => SLICE_ID_RE.test(s) || RANGE_RE.test(s))
|
|
194
199
|
: [];
|
|
200
|
+
const depends = expandDependencies(rawDepParts);
|
|
195
201
|
|
|
196
202
|
// ADR-011: the renderer writes a `[sketch]` badge for sketch slices.
|
|
197
203
|
// Parse it back so the is_sketch flag survives a markdown → DB re-import
|
|
@@ -30,7 +30,8 @@ import { isAbsolute, join, dirname, resolve } from "node:path";
|
|
|
30
30
|
import { fileURLToPath } from "node:url";
|
|
31
31
|
import { gsdRoot } from "./paths.js";
|
|
32
32
|
import { createWorktree, worktreePath, removeWorktree } from "./worktree-manager.js";
|
|
33
|
-
import { autoWorktreeBranch, runWorktreePostCreateHook,
|
|
33
|
+
import { autoWorktreeBranch, runWorktreePostCreateHook, syncGsdStateToWorktreeByScope } from "./auto-worktree.js";
|
|
34
|
+
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
34
35
|
import {
|
|
35
36
|
writeSessionStatus,
|
|
36
37
|
removeSessionStatus,
|
|
@@ -163,7 +164,10 @@ function createSliceWorktree(basePath: string, milestoneId: string, sliceId: str
|
|
|
163
164
|
if (hookError) {
|
|
164
165
|
throw new Error(`slice worktree post-create hook failed (${wtName}): ${hookError}`);
|
|
165
166
|
}
|
|
166
|
-
|
|
167
|
+
syncGsdStateToWorktreeByScope(
|
|
168
|
+
scopeMilestone(createWorkspace(basePath), milestoneId),
|
|
169
|
+
scopeMilestone(createWorkspace(wtPath), milestoneId),
|
|
170
|
+
);
|
|
167
171
|
|
|
168
172
|
if (!existsSync(join(wtPath, ".gsd"))) {
|
|
169
173
|
throw new Error(`slice worktree preflight failed (${wtName}): missing .gsd in worktree`);
|
|
@@ -52,7 +52,6 @@ import { isTerminalMilestoneSummaryContent } from './milestone-summary-classifie
|
|
|
52
52
|
|
|
53
53
|
import {
|
|
54
54
|
isDbAvailable,
|
|
55
|
-
wasDbOpenAttempted,
|
|
56
55
|
getAllMilestones,
|
|
57
56
|
getMilestone,
|
|
58
57
|
getMilestoneSlices,
|
|
@@ -63,9 +62,14 @@ import {
|
|
|
63
62
|
getLatestAssessmentByScope,
|
|
64
63
|
getPendingGateCountForTurn,
|
|
65
64
|
} from './gsd-db.js';
|
|
65
|
+
import { wasWorkflowDatabaseOpenAttempted } from './db-workspace.js';
|
|
66
66
|
import { formatCompletePhaseNextAction, countUnmappedActiveRequirements } from './requirements-backlog.js';
|
|
67
67
|
import type { MilestoneRow } from './db-milestone-artifact-rows.js';
|
|
68
68
|
import type { SliceRow, TaskRow } from './db-task-slice-rows.js';
|
|
69
|
+
import {
|
|
70
|
+
classifyMilestoneReadiness,
|
|
71
|
+
readinessNeedsDiscussion,
|
|
72
|
+
} from './milestone-readiness.js';
|
|
69
73
|
|
|
70
74
|
function formatNeedsAttentionBlocker(milestoneId: string): string {
|
|
71
75
|
return [
|
|
@@ -395,7 +399,7 @@ export async function deriveState(
|
|
|
395
399
|
stopDbTimer({ phase: result.phase, milestone: result.activeMilestone?.id });
|
|
396
400
|
_telemetry.dbDeriveCount++;
|
|
397
401
|
} else {
|
|
398
|
-
if (
|
|
402
|
+
if (wasWorkflowDatabaseOpenAttempted()) {
|
|
399
403
|
logWarning("state", "DB unavailable — refusing implicit markdown state derivation");
|
|
400
404
|
}
|
|
401
405
|
result = {
|
|
@@ -507,6 +511,12 @@ async function buildRegistryAndFindActive(
|
|
|
507
511
|
const title = stripMilestonePrefix(m.title) || m.id;
|
|
508
512
|
const hasContext = !!resolveMilestoneFile(basePath, m.id, "CONTEXT");
|
|
509
513
|
const hasDraftContext = !hasContext && !!resolveMilestoneFile(basePath, m.id, "CONTEXT-DRAFT");
|
|
514
|
+
const readiness = classifyMilestoneReadiness({
|
|
515
|
+
status: m.status,
|
|
516
|
+
hasContext,
|
|
517
|
+
hasDraftContext,
|
|
518
|
+
sliceCount: slices.length,
|
|
519
|
+
});
|
|
510
520
|
|
|
511
521
|
if (!activeMilestoneFound) {
|
|
512
522
|
const deps = m.depends_on;
|
|
@@ -517,9 +527,9 @@ async function buildRegistryAndFindActive(
|
|
|
517
527
|
continue;
|
|
518
528
|
}
|
|
519
529
|
|
|
520
|
-
if (
|
|
530
|
+
if (readiness.kind === 'queued-shell') {
|
|
521
531
|
if (!firstDeferredQueuedShell) {
|
|
522
|
-
firstDeferredQueuedShell = { id: m.id, title, deps, hasDraftContext };
|
|
532
|
+
firstDeferredQueuedShell = { id: m.id, title, deps, hasDraftContext: readiness.hasDraftContext };
|
|
523
533
|
}
|
|
524
534
|
registry.push({ id: m.id, title, status: 'pending', ...(deps.length > 0 ? { dependsOn: deps } : {}) });
|
|
525
535
|
continue;
|
|
@@ -533,7 +543,7 @@ async function buildRegistryAndFindActive(
|
|
|
533
543
|
continue;
|
|
534
544
|
}
|
|
535
545
|
|
|
536
|
-
if ((
|
|
546
|
+
if (readinessNeedsDiscussion(readiness)) activeMilestoneHasDraft = true;
|
|
537
547
|
|
|
538
548
|
activeMilestone = { id: m.id, title };
|
|
539
549
|
activeMilestoneSlices = slices;
|
|
@@ -46,6 +46,13 @@
|
|
|
46
46
|
For simple projects or scripts:
|
|
47
47
|
- Executable verification commands (bash assertions, curl checks, etc.) are sufficient
|
|
48
48
|
|
|
49
|
+
For browser-facing web apps (React, Next, Vue, Vite, static HTML, etc.):
|
|
50
|
+
- Prefer `npx playwright test <spec>` in Verification when `@playwright/test` exists
|
|
51
|
+
- If Playwright is not set up yet, the first UI slice should add `playwright.config.ts`,
|
|
52
|
+
a minimal smoke spec (for example `e2e/smoke.spec.ts`), and a safe verify command
|
|
53
|
+
- Slice closeout UAT must declare `browser-executable` or `runtime-executable` — not
|
|
54
|
+
`artifact-driven` — when checks navigate to localhost or exercise the live UI
|
|
55
|
+
|
|
49
56
|
If the project has no test framework and the work is non-trivial,
|
|
50
57
|
the first task should set one up. A test runner costs 2 minutes
|
|
51
58
|
and pays for itself immediately.
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
- **Complexity:** {{simple | complex}}
|
|
22
22
|
- **Why:** {{one-line rationale citing the signals that decided it}}
|
|
23
|
+
- **Web stack:** {{browser-facing framework or "not a web UI" — e.g. Next.js + Playwright, static HTML, N/A for CLI/API-only}}
|
|
23
24
|
|
|
24
25
|
## Current State
|
|
25
26
|
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
- Contract verification: {{tests / shell verifiers / fixtures / artifact checks}}
|
|
43
43
|
- Integration verification: {{real subsystem interaction that must be exercised, or none}}
|
|
44
44
|
- Operational verification: {{service lifecycle / restart / reconnect / supervision / deploy-install behavior, or none}}
|
|
45
|
-
- UAT / human verification: {{what needs real human judgment, or none}}
|
|
45
|
+
- UAT / human verification: {{what needs real human judgment, or none — for web apps prefer browser-executable / runtime-executable Playwright checks over deferring UI proof to humans}}
|
|
46
46
|
|
|
47
47
|
## Milestone Definition of Done
|
|
48
48
|
|
|
@@ -5,9 +5,13 @@
|
|
|
5
5
|
|
|
6
6
|
## UAT Type
|
|
7
7
|
|
|
8
|
-
- UAT mode: {{artifact-driven | live-runtime | human-experience | mixed}}
|
|
8
|
+
- UAT mode: {{artifact-driven | browser-executable | runtime-executable | live-runtime | human-experience | mixed}}
|
|
9
9
|
- Why this mode is sufficient: {{reason}}
|
|
10
10
|
|
|
11
|
+
<!-- Web apps: never use artifact-driven when steps open a browser, navigate to localhost,
|
|
12
|
+
or capture screenshots. Use browser-executable (browser_* tools) or runtime-executable
|
|
13
|
+
(npx playwright test). Name dev-server preconditions below. -->
|
|
14
|
+
|
|
11
15
|
## Preconditions
|
|
12
16
|
|
|
13
17
|
{{whatMustBeTrueBeforeTesting — server running, data seeded, etc.}}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression tests for ask_user_questions renderResult when Claude Code MCP
|
|
3
|
+
* omits structuredContent and the chat controller passes details as undefined
|
|
4
|
+
* or an empty object.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import assert from "node:assert/strict";
|
|
8
|
+
import { test } from "node:test";
|
|
9
|
+
import askUserQuestionsExtension from "../../ask-user-questions.ts";
|
|
10
|
+
|
|
11
|
+
const fakeTheme = {
|
|
12
|
+
fg: (_color: string, text: string) => text,
|
|
13
|
+
bold: (text: string) => text,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function getAskUserQuestionsTool() {
|
|
17
|
+
const tools: any[] = [];
|
|
18
|
+
askUserQuestionsExtension({ registerTool: (tool: any) => tools.push(tool) } as any);
|
|
19
|
+
const tool = tools.find((t) => t.name === "ask_user_questions");
|
|
20
|
+
assert.ok(tool, "ask_user_questions should be registered");
|
|
21
|
+
return tool;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function renderText(tool: any, result: unknown, args?: unknown): string {
|
|
25
|
+
const rendered = tool.renderResult(result, {}, fakeTheme, { args });
|
|
26
|
+
return String((rendered as any).content ?? (rendered as any).text ?? rendered);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const depthQuestion = {
|
|
30
|
+
id: "depth_check",
|
|
31
|
+
header: "Depth Check",
|
|
32
|
+
question: "Did I capture the depth right?",
|
|
33
|
+
options: [
|
|
34
|
+
{ label: "Yes, you got it", description: "Proceed" },
|
|
35
|
+
{ label: "Not quite - let me clarify", description: "Clarify" },
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
test("ask_user_questions renderResult shows answers when details is undefined (MCP text-only wire)", () => {
|
|
40
|
+
const tool = getAskUserQuestionsTool();
|
|
41
|
+
const contentText = JSON.stringify({
|
|
42
|
+
answers: { depth_check: { answers: ["Yes, you got it"] } },
|
|
43
|
+
});
|
|
44
|
+
const text = renderText(
|
|
45
|
+
tool,
|
|
46
|
+
{
|
|
47
|
+
content: [{ type: "text", text: contentText }],
|
|
48
|
+
details: undefined,
|
|
49
|
+
isError: false,
|
|
50
|
+
},
|
|
51
|
+
{ questions: [depthQuestion] },
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
assert.match(text, /✓/);
|
|
55
|
+
assert.match(text, /Depth Check/);
|
|
56
|
+
assert.match(text, /Yes, you got it/);
|
|
57
|
+
assert.doesNotMatch(text, /Cancelled/i);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("ask_user_questions renderResult shows answers when details is empty object (#cc-elicitation)", () => {
|
|
61
|
+
const tool = getAskUserQuestionsTool();
|
|
62
|
+
const contentText = JSON.stringify({
|
|
63
|
+
answers: { depth_check: { answers: ["Yes, you got it"] } },
|
|
64
|
+
});
|
|
65
|
+
const text = renderText(
|
|
66
|
+
tool,
|
|
67
|
+
{
|
|
68
|
+
content: [{ type: "text", text: contentText }],
|
|
69
|
+
details: {},
|
|
70
|
+
isError: false,
|
|
71
|
+
},
|
|
72
|
+
{ questions: [depthQuestion] },
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
assert.match(text, /Yes, you got it/);
|
|
76
|
+
assert.doesNotMatch(text, /Cancelled/i);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("ask_user_questions renderResult still shows Cancelled for explicit cancel payload", () => {
|
|
80
|
+
const tool = getAskUserQuestionsTool();
|
|
81
|
+
const text = renderText(
|
|
82
|
+
tool,
|
|
83
|
+
{
|
|
84
|
+
content: [{ type: "text", text: "ask_user_questions was cancelled before receiving a response" }],
|
|
85
|
+
details: { questions: [depthQuestion], response: null, cancelled: true },
|
|
86
|
+
isError: false,
|
|
87
|
+
},
|
|
88
|
+
{ questions: [depthQuestion] },
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
assert.match(text, /Cancelled/i);
|
|
92
|
+
});
|
|
@@ -29,11 +29,16 @@ import {
|
|
|
29
29
|
_refreshLastCommitForTests,
|
|
30
30
|
_getLastCommitForTests,
|
|
31
31
|
_getLastCommitFetchedAtForTests,
|
|
32
|
+
formatToolSurfaceSnapshot,
|
|
32
33
|
formatRuntimeHealthSignal,
|
|
33
34
|
shouldRenderRoadmapProgress,
|
|
34
35
|
} from "../auto-dashboard.ts";
|
|
35
36
|
import { getAutoDashboardData } from "../auto.ts";
|
|
36
|
-
import {
|
|
37
|
+
import {
|
|
38
|
+
autoSession,
|
|
39
|
+
clearAutoToolSurfaceSnapshot,
|
|
40
|
+
recordAutoToolSurfaceSnapshot,
|
|
41
|
+
} from "../auto-runtime-state.ts";
|
|
37
42
|
import { formatRtkSavingsLabel } from "../../shared/rtk-session-stats.ts";
|
|
38
43
|
import {
|
|
39
44
|
openDatabase,
|
|
@@ -530,6 +535,29 @@ test("getAutoDashboardData returns RTK savings in the dashboard payload", () =>
|
|
|
530
535
|
}
|
|
531
536
|
});
|
|
532
537
|
|
|
538
|
+
test("getAutoDashboardData exposes typed tool-surface snapshots", () => {
|
|
539
|
+
autoSession.reset();
|
|
540
|
+
clearAutoToolSurfaceSnapshot();
|
|
541
|
+
autoSession.active = true;
|
|
542
|
+
recordAutoToolSurfaceSnapshot({
|
|
543
|
+
source: "provider-adjustment",
|
|
544
|
+
unitType: "run-uat",
|
|
545
|
+
modelFacingToolNames: ["read"],
|
|
546
|
+
registeredToolNames: ["read", "browser_navigate"],
|
|
547
|
+
scopedToolNames: ["read", "browser_navigate"],
|
|
548
|
+
presentedToolNames: ["browser_navigate"],
|
|
549
|
+
capturedAt: 456,
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
const data = getAutoDashboardData();
|
|
553
|
+
|
|
554
|
+
assert.equal(data.toolSurface?.source, "provider-adjustment");
|
|
555
|
+
assert.equal(formatToolSurfaceSnapshot(data.toolSurface), "run-uat: model 1 / registered 2 / scoped 2 / presented 1");
|
|
556
|
+
|
|
557
|
+
autoSession.reset();
|
|
558
|
+
clearAutoToolSurfaceSnapshot();
|
|
559
|
+
});
|
|
560
|
+
|
|
533
561
|
test("RTK savings label formats the dashboard footer text", () => {
|
|
534
562
|
assert.equal(formatRtkSavingsLabel(null), null);
|
|
535
563
|
assert.equal(
|