@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
|
@@ -74,6 +74,29 @@ const PREPARE_WRITE_RE = /\.prepare\s*\(\s*[`'"][^`'"]*\b(INSERT|UPDATE|DELETE|R
|
|
|
74
74
|
|
|
75
75
|
// Match .exec("... INSERT|UPDATE|DELETE|REPLACE ...") or raw BEGIN/COMMIT/ROLLBACK.
|
|
76
76
|
const EXEC_WRITE_RE = /\.exec\s*\(\s*[`'"][^`'"]*\b(INSERT|UPDATE|DELETE|REPLACE|BEGIN|COMMIT|ROLLBACK)\b/i;
|
|
77
|
+
const DB_WORKSPACE_MECHANICS = new Set([
|
|
78
|
+
"backupDatabaseSnapshot",
|
|
79
|
+
"checkpointDatabase",
|
|
80
|
+
"closeAllDatabases",
|
|
81
|
+
"closeDatabase",
|
|
82
|
+
"closeDatabaseByWorkspace",
|
|
83
|
+
"getDbPath",
|
|
84
|
+
"getDbProvider",
|
|
85
|
+
"getDbStatus",
|
|
86
|
+
"openDatabase",
|
|
87
|
+
"openDatabaseByScope",
|
|
88
|
+
"openDatabaseByWorkspace",
|
|
89
|
+
"refreshOpenDatabaseFromDisk",
|
|
90
|
+
"vacuumDatabase",
|
|
91
|
+
"wasDbOpenAttempted",
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
function importNames(specifierBlock: string): string[] {
|
|
95
|
+
return specifierBlock
|
|
96
|
+
.split(",")
|
|
97
|
+
.map((name) => name.trim().replace(/^type\s+/, "").split(/\s+as\s+/)[0]?.trim() ?? "")
|
|
98
|
+
.filter(Boolean);
|
|
99
|
+
}
|
|
77
100
|
|
|
78
101
|
test("no module outside gsd-db.ts issues raw write SQL against the engine DB", () => {
|
|
79
102
|
const files = walkTsFiles(gsdDir);
|
|
@@ -166,6 +189,84 @@ test("gsd-db.ts exports the expected single-writer wrappers", async () => {
|
|
|
166
189
|
}
|
|
167
190
|
});
|
|
168
191
|
|
|
192
|
+
test("DB Workspace Interface owns database open-state and maintenance calls", async () => {
|
|
193
|
+
const workspaceDb = await import("../db-workspace.js");
|
|
194
|
+
|
|
195
|
+
const expected = [
|
|
196
|
+
"backupWorkflowDatabaseSnapshot",
|
|
197
|
+
"checkpointWorkflowDatabase",
|
|
198
|
+
"closeAllWorkflowDatabases",
|
|
199
|
+
"closeWorkflowDatabase",
|
|
200
|
+
"closeWorkflowDatabaseByWorkspace",
|
|
201
|
+
"getWorkflowDatabasePath",
|
|
202
|
+
"getWorkflowDatabaseProvider",
|
|
203
|
+
"getWorkflowDatabaseStatus",
|
|
204
|
+
"isWorkflowDatabaseOpen",
|
|
205
|
+
"openExistingWorkflowDatabase",
|
|
206
|
+
"openWorkflowDatabase",
|
|
207
|
+
"openWorkflowDatabaseByScope",
|
|
208
|
+
"openWorkflowDatabaseByWorkspace",
|
|
209
|
+
"openWorkflowDatabasePath",
|
|
210
|
+
"refreshWorkflowDatabaseFromDisk",
|
|
211
|
+
"resolveProjectRootDbPath",
|
|
212
|
+
"resolveWorkflowDatabaseLocation",
|
|
213
|
+
"vacuumWorkflowDatabase",
|
|
214
|
+
"wasWorkflowDatabaseOpenAttempted",
|
|
215
|
+
];
|
|
216
|
+
|
|
217
|
+
for (const name of expected) {
|
|
218
|
+
assert.ok(
|
|
219
|
+
typeof (workspaceDb as Record<string, unknown>)[name] === "function",
|
|
220
|
+
`db-workspace.ts must export ${name} as a function`,
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("production modules do not import DB open-state mechanics from gsd-db.ts", () => {
|
|
226
|
+
const files = walkTsFiles(gsdDir);
|
|
227
|
+
const violations: Violation[] = [];
|
|
228
|
+
const staticImportRe = /import\s*\{([\s\S]*?)\}\s*from\s*["'][^"']*gsd-db\.(?:js|ts)["']/g;
|
|
229
|
+
const dynamicImportRe = /(?:const|let)\s*\{([\s\S]*?)\}\s*=\s*await\s+import\(["'][^"']*gsd-db\.(?:js|ts)["']\)/g;
|
|
230
|
+
|
|
231
|
+
for (const abs of files) {
|
|
232
|
+
const rel = relative(gsdDir, abs);
|
|
233
|
+
if (rel === "gsd-db.ts" || rel === "db-workspace.ts") continue;
|
|
234
|
+
|
|
235
|
+
let content: string;
|
|
236
|
+
try {
|
|
237
|
+
content = readFileSync(abs, "utf-8");
|
|
238
|
+
} catch {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
for (const re of [staticImportRe, dynamicImportRe]) {
|
|
243
|
+
re.lastIndex = 0;
|
|
244
|
+
let match: RegExpExecArray | null;
|
|
245
|
+
while ((match = re.exec(content)) !== null) {
|
|
246
|
+
const leaked = importNames(match[1] ?? "").filter((name) => DB_WORKSPACE_MECHANICS.has(name));
|
|
247
|
+
if (leaked.length === 0) continue;
|
|
248
|
+
violations.push({
|
|
249
|
+
file: rel,
|
|
250
|
+
line: content.slice(0, match.index).split("\n").length,
|
|
251
|
+
snippet: leaked.join(", "),
|
|
252
|
+
kind: "db-workspace-leak",
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (violations.length > 0) {
|
|
259
|
+
const lines = violations.map(
|
|
260
|
+
(v) => ` ${v.file}:${v.line} [${v.kind}] — ${v.snippet}`,
|
|
261
|
+
);
|
|
262
|
+
assert.fail(
|
|
263
|
+
`Found ${violations.length} DB open-state import(s) from gsd-db.ts:\n` +
|
|
264
|
+
lines.join("\n") +
|
|
265
|
+
"\n\nImport these through db-workspace.ts so gsd-db.ts stays the single-writer implementation, not the caller-facing DB Workspace Interface.",
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
169
270
|
test("the invariant test touches every .ts module under gsd/ (sanity check)", () => {
|
|
170
271
|
const files = walkTsFiles(gsdDir);
|
|
171
272
|
// Rough sanity: ensure we're not accidentally walking an empty tree
|
|
@@ -177,4 +278,3 @@ test("the invariant test touches every .ts module under gsd/ (sanity check)", ()
|
|
|
177
278
|
assert.ok(rels.includes("memory-store.ts"), "walker must include memory-store.ts");
|
|
178
279
|
assert.ok(rels.includes("workflow-manifest.ts"), "walker must include workflow-manifest.ts");
|
|
179
280
|
});
|
|
180
|
-
|
|
@@ -74,6 +74,33 @@ describe("stale queued milestone selection (#3470)", () => {
|
|
|
74
74
|
assert.equal(m070Entry!.status, "active", "M070 should be active in registry");
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
+
test("queued milestone with roadmap projection but no DB slices stays deferred", async () => {
|
|
78
|
+
base = createFixtureBase();
|
|
79
|
+
openDatabase(":memory:");
|
|
80
|
+
|
|
81
|
+
// M068: queued shell with a stale ROADMAP projection, but no CONTEXT and no DB slices.
|
|
82
|
+
insertMilestone({ id: "M068", title: "Queued Roadmap Projection", status: "queued" });
|
|
83
|
+
writeFile(base, "milestones/M068/M068-ROADMAP.md", "# M068\n\n## Slices\n\n- [ ] **S99: Stale Slice**");
|
|
84
|
+
|
|
85
|
+
// M070: real active milestone — context, roadmap, slices, tasks
|
|
86
|
+
insertMilestone({ id: "M070", title: "Real Active", status: "active" });
|
|
87
|
+
insertSlice({ id: "S01", milestoneId: "M070", title: "Slice One", status: "active", risk: "low", depends: [] });
|
|
88
|
+
insertTask({ id: "T01", sliceId: "S01", milestoneId: "M070", title: "Task One", status: "pending" });
|
|
89
|
+
|
|
90
|
+
writeFile(base, "milestones/M070/M070-CONTEXT.md", "# M070: Real Active\n\nThis is the real milestone.");
|
|
91
|
+
writeFile(base, "milestones/M070/M070-ROADMAP.md", "# M070: Real Active\n\n## Slices\n\n- [ ] **S01: Slice One**");
|
|
92
|
+
writeFile(base, "milestones/M070/slices/S01/S01-PLAN.md", "# S01: Slice One\n\n## Tasks\n\n- [ ] **T01: Task One**");
|
|
93
|
+
|
|
94
|
+
invalidateStateCache();
|
|
95
|
+
const state = await deriveStateFromDb(base);
|
|
96
|
+
|
|
97
|
+
assert.equal(state.activeMilestone?.id, "M070", "ROADMAP-only queued milestone must not block active M070");
|
|
98
|
+
|
|
99
|
+
const m068Entry = state.registry.find((e: any) => e.id === "M068");
|
|
100
|
+
assert.ok(m068Entry, "M068 should still appear in registry");
|
|
101
|
+
assert.equal(m068Entry!.status, "pending", "M068 should stay pending without CONTEXT or DB slices");
|
|
102
|
+
});
|
|
103
|
+
|
|
77
104
|
test("queued milestone WITH context file can still be selected as active", async () => {
|
|
78
105
|
base = createFixtureBase();
|
|
79
106
|
openDatabase(":memory:");
|
|
@@ -364,6 +364,7 @@ test("effective unit isolation follows degraded branch fallback", () => {
|
|
|
364
364
|
|
|
365
365
|
test("discuss-to-auto handoff defaults to step mode unless explicitly disabled", () => {
|
|
366
366
|
const guidedFlowSrc = readGsdFile("guided-flow.ts");
|
|
367
|
+
const discussionHandoffSrc = readGsdFile("discussion-handoff.ts");
|
|
367
368
|
const workflowSrc = readGsdFile("commands/handlers/workflow.ts");
|
|
368
369
|
|
|
369
370
|
assert.ok(
|
|
@@ -371,7 +372,7 @@ test("discuss-to-auto handoff defaults to step mode unless explicitly disabled",
|
|
|
371
372
|
"guided-flow must not hardcode step: false on pending auto-start entries",
|
|
372
373
|
);
|
|
373
374
|
assert.match(
|
|
374
|
-
|
|
375
|
+
discussionHandoffSrc,
|
|
375
376
|
/scheduleAutoStartAfterIdle\(ctx, pi, basePath, false, \{ step: step \?\? true \}\)/,
|
|
376
377
|
"checkAutoStartAfterDiscuss should default missing step flags to step mode",
|
|
377
378
|
);
|
|
@@ -141,6 +141,41 @@ for (const customType of ["gsd-discuss", "gsd-run"] as const) {
|
|
|
141
141
|
});
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
for (const unitType of ["execute-task", "execute-task-simple", "reactive-execute"] as const) {
|
|
145
|
+
test(`${unitType}: resolves gsd_task_complete via alias gsd_complete_task when only alias is registered`, () => {
|
|
146
|
+
// Simulates the MCP transport registering gsd_complete_task (alias) instead of gsd_task_complete.
|
|
147
|
+
// adjust_tool_set strips aliases from providerCompatible, so gsd_complete_task is only present
|
|
148
|
+
// in registeredToolNames. resolveScopedToolNames must still surface it so the agent can complete tasks.
|
|
149
|
+
const base: string[] = [...FULL_REGISTERED_TOOLS];
|
|
150
|
+
const aliasOnlyRegistered = base
|
|
151
|
+
.filter((name) => name !== "gsd_task_complete")
|
|
152
|
+
.concat("gsd_complete_task");
|
|
153
|
+
const aliasStrippedActive = aliasOnlyRegistered.filter((name) => name !== "gsd_complete_task");
|
|
154
|
+
|
|
155
|
+
const result = buildMinimalAutoGsdToolSet(aliasStrippedActive, unitType, aliasOnlyRegistered);
|
|
156
|
+
|
|
157
|
+
assert.ok(
|
|
158
|
+
result.includes("gsd_task_complete") || result.includes("gsd_complete_task"),
|
|
159
|
+
`${unitType} missing gsd_task_complete / gsd_complete_task — agent cannot complete tasks`,
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test(`${unitType}: alias does not duplicate canonical when both are in the active set`, () => {
|
|
164
|
+
// When both canonical and alias are registered/active, only the canonical should be surfaced.
|
|
165
|
+
const bothPresent: string[] = [...FULL_REGISTERED_TOOLS, "gsd_complete_task"];
|
|
166
|
+
|
|
167
|
+
const result = buildMinimalAutoGsdToolSet(bothPresent, unitType, bothPresent);
|
|
168
|
+
|
|
169
|
+
const hasCanonical = result.includes("gsd_task_complete");
|
|
170
|
+
const hasAlias = result.includes("gsd_complete_task");
|
|
171
|
+
assert.ok(hasCanonical || hasAlias, `${unitType} missing completion tool`);
|
|
172
|
+
assert.ok(
|
|
173
|
+
!(hasCanonical && hasAlias),
|
|
174
|
+
`${unitType} surfaces both gsd_task_complete and gsd_complete_task — alias should not duplicate canonical`,
|
|
175
|
+
);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
144
179
|
test("discuss-milestone two-stage scoping matches adjust_tool_set request scope", () => {
|
|
145
180
|
const activeTools = simulateDiscussAllowlistFilter(FULL_REGISTERED_TOOLS);
|
|
146
181
|
const dispatchScoped = buildMinimalAutoGsdToolSet(
|
|
@@ -5,6 +5,10 @@ import { test } from 'node:test';
|
|
|
5
5
|
import assert from 'node:assert/strict';
|
|
6
6
|
import { registerDbTools } from '../bootstrap/db-tools.ts';
|
|
7
7
|
import { getLegacyTelemetry, resetLegacyTelemetry } from '../legacy-telemetry.ts';
|
|
8
|
+
import {
|
|
9
|
+
WORKFLOW_TOOL_ALIAS_PAIRS,
|
|
10
|
+
WORKFLOW_TOOL_CONTRACTS,
|
|
11
|
+
} from '../workflow-tool-surface.ts';
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
// ─── Mock PI ──────────────────────────────────────────────────────────────────
|
|
@@ -17,49 +21,38 @@ function makeMockPi() {
|
|
|
17
21
|
} as any;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
// ─── Rename map ───────────────────────────────────────────────────────────────
|
|
21
|
-
|
|
22
|
-
const RENAME_MAP: Array<{ canonical: string; alias: string }> = [
|
|
23
|
-
{ canonical: "gsd_decision_save", alias: "gsd_save_decision" },
|
|
24
|
-
{ canonical: "gsd_requirement_update", alias: "gsd_update_requirement" },
|
|
25
|
-
{ canonical: "gsd_requirement_save", alias: "gsd_save_requirement" },
|
|
26
|
-
{ canonical: "gsd_summary_save", alias: "gsd_save_summary" },
|
|
27
|
-
{ canonical: "gsd_milestone_generate_id", alias: "gsd_generate_milestone_id" },
|
|
28
|
-
{ canonical: "gsd_task_complete", alias: "gsd_complete_task" },
|
|
29
|
-
{ canonical: "gsd_slice_complete", alias: "gsd_complete_slice" },
|
|
30
|
-
{ canonical: "gsd_plan_milestone", alias: "gsd_milestone_plan" },
|
|
31
|
-
{ canonical: "gsd_plan_slice", alias: "gsd_slice_plan" },
|
|
32
|
-
{ canonical: "gsd_plan_task", alias: "gsd_task_plan" },
|
|
33
|
-
{ canonical: "gsd_replan_slice", alias: "gsd_slice_replan" },
|
|
34
|
-
{ canonical: "gsd_reassess_roadmap", alias: "gsd_roadmap_reassess" },
|
|
35
|
-
{ canonical: "gsd_complete_milestone", alias: "gsd_milestone_complete" },
|
|
36
|
-
{ canonical: "gsd_validate_milestone", alias: "gsd_milestone_validate" },
|
|
37
|
-
{ canonical: "gsd_task_reopen", alias: "gsd_reopen_task" },
|
|
38
|
-
{ canonical: "gsd_slice_reopen", alias: "gsd_reopen_slice" },
|
|
39
|
-
{ canonical: "gsd_milestone_reopen", alias: "gsd_reopen_milestone" },
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const STANDALONE_TOOLS = [
|
|
43
|
-
"gsd_save_gate_result",
|
|
44
|
-
"gsd_skip_slice",
|
|
45
|
-
"gsd_uat_result_save",
|
|
46
|
-
];
|
|
47
|
-
|
|
48
24
|
// ─── Registration count ──────────────────────────────────────────────────────
|
|
49
25
|
|
|
50
26
|
console.log('\n── Tool naming: registration count ──');
|
|
51
27
|
|
|
52
28
|
const pi = makeMockPi();
|
|
53
29
|
registerDbTools(pi);
|
|
54
|
-
|
|
30
|
+
const toolByName = new Map<string, any>(pi.tools.map((tool: any) => [tool.name, tool]));
|
|
31
|
+
const registeredCanonicalNames = new Set<string>(
|
|
32
|
+
WORKFLOW_TOOL_CONTRACTS
|
|
33
|
+
.map((tool) => tool.canonicalName)
|
|
34
|
+
.filter((name) => toolByName.has(name)),
|
|
35
|
+
);
|
|
36
|
+
const RENAME_MAP = WORKFLOW_TOOL_ALIAS_PAIRS.filter(({ canonical }) =>
|
|
37
|
+
registeredCanonicalNames.has(canonical),
|
|
38
|
+
);
|
|
39
|
+
const STANDALONE_TOOLS = WORKFLOW_TOOL_CONTRACTS
|
|
40
|
+
.filter((tool) => registeredCanonicalNames.has(tool.canonicalName) && tool.aliases.length === 0)
|
|
41
|
+
.map((tool) => tool.canonicalName);
|
|
42
|
+
const expectedRegisteredNames = [
|
|
43
|
+
...STANDALONE_TOOLS,
|
|
44
|
+
...RENAME_MAP.flatMap(({ canonical, alias }) => [canonical, alias]),
|
|
45
|
+
].sort();
|
|
46
|
+
|
|
47
|
+
assert.equal(pi.tools.length, toolByName.size, 'Tool registration should not produce duplicate names');
|
|
55
48
|
assert.deepStrictEqual(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
'Should register
|
|
49
|
+
[...toolByName.keys()].sort(),
|
|
50
|
+
expectedRegisteredNames,
|
|
51
|
+
'Should register only workflow surface tools and their declared aliases',
|
|
59
52
|
);
|
|
60
53
|
|
|
61
54
|
for (const name of STANDALONE_TOOLS) {
|
|
62
|
-
assert.ok(
|
|
55
|
+
assert.ok(toolByName.has(name), `Standalone tool "${name}" should be registered`);
|
|
63
56
|
}
|
|
64
57
|
|
|
65
58
|
// ─── Both names exist for each pair ──────────────────────────────────────────
|
|
@@ -67,8 +60,8 @@ for (const name of STANDALONE_TOOLS) {
|
|
|
67
60
|
console.log('\n── Tool naming: canonical and alias names exist ──');
|
|
68
61
|
|
|
69
62
|
for (const { canonical, alias } of RENAME_MAP) {
|
|
70
|
-
const canonicalTool =
|
|
71
|
-
const aliasTool =
|
|
63
|
+
const canonicalTool = toolByName.get(canonical);
|
|
64
|
+
const aliasTool = toolByName.get(alias);
|
|
72
65
|
|
|
73
66
|
assert.ok(canonicalTool !== undefined, `Canonical tool "${canonical}" should be registered`);
|
|
74
67
|
assert.ok(aliasTool !== undefined, `Alias tool "${alias}" should be registered`);
|
|
@@ -79,8 +72,8 @@ for (const { canonical, alias } of RENAME_MAP) {
|
|
|
79
72
|
console.log('\n── Tool naming: alias execute wrapper ──');
|
|
80
73
|
|
|
81
74
|
for (const { canonical, alias } of RENAME_MAP) {
|
|
82
|
-
const canonicalTool =
|
|
83
|
-
const aliasTool =
|
|
75
|
+
const canonicalTool = toolByName.get(canonical);
|
|
76
|
+
const aliasTool = toolByName.get(alias);
|
|
84
77
|
|
|
85
78
|
if (canonicalTool && aliasTool) {
|
|
86
79
|
assert.ok(
|
|
@@ -91,8 +84,8 @@ for (const { canonical, alias } of RENAME_MAP) {
|
|
|
91
84
|
}
|
|
92
85
|
|
|
93
86
|
test("alias execute increments legacy MCP alias telemetry before delegating", async () => {
|
|
94
|
-
const canonicalTool =
|
|
95
|
-
const aliasTool =
|
|
87
|
+
const canonicalTool = toolByName.get("gsd_decision_save");
|
|
88
|
+
const aliasTool = toolByName.get("gsd_save_decision");
|
|
96
89
|
assert.ok(canonicalTool);
|
|
97
90
|
assert.ok(aliasTool);
|
|
98
91
|
|
|
@@ -120,7 +113,7 @@ test("alias execute increments legacy MCP alias telemetry before delegating", as
|
|
|
120
113
|
console.log('\n── Tool naming: alias descriptions ──');
|
|
121
114
|
|
|
122
115
|
for (const { canonical, alias } of RENAME_MAP) {
|
|
123
|
-
const aliasTool =
|
|
116
|
+
const aliasTool = toolByName.get(alias);
|
|
124
117
|
|
|
125
118
|
if (aliasTool) {
|
|
126
119
|
assert.ok(
|
|
@@ -135,7 +128,7 @@ for (const { canonical, alias } of RENAME_MAP) {
|
|
|
135
128
|
console.log('\n── Tool naming: canonical promptGuidelines use canonical name ──');
|
|
136
129
|
|
|
137
130
|
for (const { canonical } of RENAME_MAP) {
|
|
138
|
-
const canonicalTool =
|
|
131
|
+
const canonicalTool = toolByName.get(canonical);
|
|
139
132
|
|
|
140
133
|
if (canonicalTool) {
|
|
141
134
|
const guidelinesText = canonicalTool.promptGuidelines.join(' ');
|
|
@@ -151,7 +144,7 @@ for (const { canonical } of RENAME_MAP) {
|
|
|
151
144
|
console.log('\n── Tool naming: alias promptGuidelines redirect to canonical ──');
|
|
152
145
|
|
|
153
146
|
for (const { canonical, alias } of RENAME_MAP) {
|
|
154
|
-
const aliasTool =
|
|
147
|
+
const aliasTool = toolByName.get(alias);
|
|
155
148
|
|
|
156
149
|
if (aliasTool) {
|
|
157
150
|
const guidelinesText = aliasTool.promptGuidelines.join(' ');
|
|
@@ -66,6 +66,9 @@ describe("uat-policy", () => {
|
|
|
66
66
|
it("detects direct and MCP-shaped browser tool surfaces", () => {
|
|
67
67
|
assert.equal(hasUatBrowserToolSurface(["read", "browser_navigate"]), true);
|
|
68
68
|
assert.equal(hasUatBrowserToolSurface(["read", "mcp__gsd-browser__browser_navigate"]), true);
|
|
69
|
+
assert.equal(hasUatBrowserToolSurface(["read", "mcp__gsd-browser__*"]), true);
|
|
70
|
+
assert.equal(hasUatBrowserToolSurface(["read", "mcp__browser-uat__*"]), true);
|
|
71
|
+
assert.equal(hasUatBrowserToolSurface(["read", "mcp__gsd-workflow__*"]), false);
|
|
69
72
|
assert.equal(hasUatBrowserToolSurface(["read", "gsd_uat_exec"]), false);
|
|
70
73
|
assert.equal(hasUatBrowserToolSurface(undefined), false);
|
|
71
74
|
});
|
|
@@ -89,6 +92,26 @@ describe("uat-policy", () => {
|
|
|
89
92
|
}),
|
|
90
93
|
null,
|
|
91
94
|
);
|
|
95
|
+
assert.equal(
|
|
96
|
+
getUatBrowserToolSupportError({
|
|
97
|
+
uatType: "human-experience",
|
|
98
|
+
activeTools: ["read", "gsd_uat_exec"],
|
|
99
|
+
registeredTools: ["browser_navigate"],
|
|
100
|
+
milestoneId: "M001",
|
|
101
|
+
sliceId: "S01",
|
|
102
|
+
}),
|
|
103
|
+
null,
|
|
104
|
+
);
|
|
105
|
+
assert.equal(
|
|
106
|
+
getUatBrowserToolSupportError({
|
|
107
|
+
uatType: "human-experience",
|
|
108
|
+
activeTools: ["read", "gsd_uat_exec"],
|
|
109
|
+
registeredTools: ["mcp__gsd-browser__*"],
|
|
110
|
+
milestoneId: "M001",
|
|
111
|
+
sliceId: "S01",
|
|
112
|
+
}),
|
|
113
|
+
null,
|
|
114
|
+
);
|
|
92
115
|
|
|
93
116
|
const error = getUatBrowserToolSupportError({
|
|
94
117
|
uatType: "browser-executable",
|
|
@@ -8,6 +8,7 @@ import { join } from "node:path";
|
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
|
+
composeContractedUnitContext,
|
|
11
12
|
composeContextModeInstructions,
|
|
12
13
|
composeInlinedContext,
|
|
13
14
|
composeUnitContext,
|
|
@@ -15,6 +16,7 @@ import {
|
|
|
15
16
|
type ArtifactResolver,
|
|
16
17
|
type ExcerptResolver,
|
|
17
18
|
} from "../unit-context-composer.ts";
|
|
19
|
+
import { compileUnitContextContract } from "../tool-contract.ts";
|
|
18
20
|
import type {
|
|
19
21
|
ArtifactKey,
|
|
20
22
|
BaseResolverContext,
|
|
@@ -268,6 +270,21 @@ test("#4782 phase 2: buildReassessRoadmapPrompt emits composer-shaped context wi
|
|
|
268
270
|
assert.ok(!prompt.includes("Slice Context (from discussion)"));
|
|
269
271
|
});
|
|
270
272
|
|
|
273
|
+
test("execute-task prompt surfaces contract-declared on-demand slice research", async (t) => {
|
|
274
|
+
const base = makeFixtureBase();
|
|
275
|
+
t.after(() => cleanup(base));
|
|
276
|
+
invalidateAllCaches();
|
|
277
|
+
|
|
278
|
+
seed(base, "M001");
|
|
279
|
+
writeArtifacts(base);
|
|
280
|
+
|
|
281
|
+
const prompt = await buildExecuteTaskPrompt("M001", "S01", "First", "T01", "Task", base);
|
|
282
|
+
|
|
283
|
+
assert.match(prompt, /## On-demand Context/);
|
|
284
|
+
assert.match(prompt, /\.gsd\/milestones\/M001\/slices\/S01\/S01-RESEARCH\.md/);
|
|
285
|
+
assert.match(prompt, /Read it only if the inlined task plan, slice plan excerpt, and carry-forward context do not explain/);
|
|
286
|
+
});
|
|
287
|
+
|
|
271
288
|
test("Context Mode resume injection: eligible prompts include one bounded snapshot block above inlined context", async (t) => {
|
|
272
289
|
const base = makeFixtureBase();
|
|
273
290
|
t.after(() => cleanup(base));
|
|
@@ -370,6 +387,36 @@ test("#4924 v2 composer: returns empty sections for unknown unit type", async ()
|
|
|
370
387
|
assert.deepEqual(out, { prepend: "", inline: "" });
|
|
371
388
|
});
|
|
372
389
|
|
|
390
|
+
test("Unit Context Contract composer exposes keyed blocks and on-demand artifacts", async () => {
|
|
391
|
+
const result = compileUnitContextContract("execute-task");
|
|
392
|
+
assert.equal(result.ok, true);
|
|
393
|
+
if (!result.ok) return;
|
|
394
|
+
|
|
395
|
+
const calls: ArtifactKey[] = [];
|
|
396
|
+
const out = await composeContractedUnitContext(result.contract, {
|
|
397
|
+
base: { ...fakeBase, unitType: "stale-unit", taskId: "T01" },
|
|
398
|
+
resolveArtifact: async (key) => {
|
|
399
|
+
calls.push(key);
|
|
400
|
+
return `BODY:${key}`;
|
|
401
|
+
},
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
assert.deepEqual(calls, [
|
|
405
|
+
"task-plan",
|
|
406
|
+
"slice-plan",
|
|
407
|
+
"prior-task-summaries",
|
|
408
|
+
"templates",
|
|
409
|
+
]);
|
|
410
|
+
assert.deepEqual(out.blocks.map((block) => [block.key, block.mode]), [
|
|
411
|
+
["task-plan", "inline"],
|
|
412
|
+
["slice-plan", "inline"],
|
|
413
|
+
["prior-task-summaries", "inline"],
|
|
414
|
+
["templates", "inline"],
|
|
415
|
+
]);
|
|
416
|
+
assert.deepEqual(out.onDemand, ["slice-research"]);
|
|
417
|
+
assert.match(out.inline, /BODY:task-plan\n\n---\n\nBODY:slice-plan/);
|
|
418
|
+
});
|
|
419
|
+
|
|
373
420
|
test("#4924 v2 composer: omitting resolveArtifact skips inline keys without erroring", async () => {
|
|
374
421
|
const out = await composeUnitContext("reassess-roadmap", { base: fakeBase });
|
|
375
422
|
assert.strictEqual(out.inline, "");
|
|
@@ -2,7 +2,11 @@ import test from "node:test";
|
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
3
|
|
|
4
4
|
import * as userInputBoundary from "../user-input-boundary.ts";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
isAwaitingUserInput,
|
|
7
|
+
messageHasPendingAskUserQuestionsTool,
|
|
8
|
+
shouldPauseForUserApprovalQuestion,
|
|
9
|
+
} from "../user-input-boundary.ts";
|
|
6
10
|
|
|
7
11
|
test("lastAssistantText extracts the latest assistant text block content", () => {
|
|
8
12
|
const lastAssistantText = (userInputBoundary as {
|
|
@@ -73,6 +77,87 @@ test("isAwaitingUserInput does not trigger on thinking-block approval phrases",
|
|
|
73
77
|
assert.equal(shouldPauseForUserApprovalQuestion("discuss-requirements", messages), false);
|
|
74
78
|
});
|
|
75
79
|
|
|
80
|
+
test("messageHasPendingAskUserQuestionsTool detects in-flight structured question tools", () => {
|
|
81
|
+
// state: "running" with no externalResult → still in-flight
|
|
82
|
+
assert.equal(
|
|
83
|
+
messageHasPendingAskUserQuestionsTool({
|
|
84
|
+
role: "assistant",
|
|
85
|
+
content: [
|
|
86
|
+
{ type: "text", text: "Which direction?" },
|
|
87
|
+
{ type: "toolCall", name: "mcp__gsd-workflow__ask_user_questions", state: "running" },
|
|
88
|
+
],
|
|
89
|
+
}),
|
|
90
|
+
true,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// no state, no externalResult — streaming block that hasn't completed yet
|
|
94
|
+
assert.equal(
|
|
95
|
+
messageHasPendingAskUserQuestionsTool({
|
|
96
|
+
role: "assistant",
|
|
97
|
+
content: [
|
|
98
|
+
{ type: "toolCall", name: "ask_user_questions" },
|
|
99
|
+
],
|
|
100
|
+
}),
|
|
101
|
+
true,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// state: "completed" — legacy state-based completion
|
|
105
|
+
assert.equal(
|
|
106
|
+
messageHasPendingAskUserQuestionsTool({
|
|
107
|
+
role: "assistant",
|
|
108
|
+
content: [
|
|
109
|
+
{ type: "toolCall", name: "ask_user_questions", state: "completed" },
|
|
110
|
+
],
|
|
111
|
+
}),
|
|
112
|
+
false,
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// externalResult present — Claude Code signals completion via externalResult, not state
|
|
116
|
+
assert.equal(
|
|
117
|
+
messageHasPendingAskUserQuestionsTool({
|
|
118
|
+
role: "assistant",
|
|
119
|
+
content: [
|
|
120
|
+
{ type: "toolCall", name: "ask_user_questions", externalResult: { content: [], isError: false } },
|
|
121
|
+
],
|
|
122
|
+
}),
|
|
123
|
+
false,
|
|
124
|
+
);
|
|
125
|
+
assert.equal(
|
|
126
|
+
messageHasPendingAskUserQuestionsTool({
|
|
127
|
+
role: "assistant",
|
|
128
|
+
content: [
|
|
129
|
+
{
|
|
130
|
+
type: "toolCall",
|
|
131
|
+
name: "ask_user_questions",
|
|
132
|
+
externalResult: { content: [{ type: "text", text: "answer" }], isError: false },
|
|
133
|
+
},
|
|
134
|
+
],
|
|
135
|
+
}),
|
|
136
|
+
false,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
// serverToolUse shape (claude-code-cli MCP path) — no externalResult → in-flight
|
|
140
|
+
assert.equal(
|
|
141
|
+
messageHasPendingAskUserQuestionsTool({
|
|
142
|
+
role: "assistant",
|
|
143
|
+
content: [
|
|
144
|
+
{ type: "serverToolUse", name: "mcp__gsd-workflow__ask_user_questions" },
|
|
145
|
+
],
|
|
146
|
+
}),
|
|
147
|
+
true,
|
|
148
|
+
);
|
|
149
|
+
// serverToolUse shape — externalResult present → completed
|
|
150
|
+
assert.equal(
|
|
151
|
+
messageHasPendingAskUserQuestionsTool({
|
|
152
|
+
role: "assistant",
|
|
153
|
+
content: [
|
|
154
|
+
{ type: "serverToolUse", name: "ask_user_questions", externalResult: { content: [], isError: false } },
|
|
155
|
+
],
|
|
156
|
+
}),
|
|
157
|
+
false,
|
|
158
|
+
);
|
|
159
|
+
});
|
|
160
|
+
|
|
76
161
|
test("isAwaitingUserInput still triggers on text-block question marks when thinking is also present", () => {
|
|
77
162
|
// When thinking + text are both present and the text asks a question, it should still pause.
|
|
78
163
|
const messages = [
|
|
@@ -12,6 +12,7 @@ import { clearPathCache } from "../paths.ts";
|
|
|
12
12
|
import {
|
|
13
13
|
openDatabase,
|
|
14
14
|
closeDatabase,
|
|
15
|
+
insertAssessment,
|
|
15
16
|
insertMilestone,
|
|
16
17
|
insertSlice,
|
|
17
18
|
} from "../gsd-db.ts";
|
|
@@ -222,6 +223,44 @@ describe("validate-milestone stuck-loop guard (#4094)", () => {
|
|
|
222
223
|
assert.equal(s.pendingVerificationRetry, null);
|
|
223
224
|
});
|
|
224
225
|
|
|
226
|
+
test("continues when DB pass overrides stale worktree needs-attention after /gsd verdict", async () => {
|
|
227
|
+
insertMilestone({ id: "M001" });
|
|
228
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|
|
229
|
+
writeWorktreeValidationFile("needs-attention");
|
|
230
|
+
|
|
231
|
+
const worktreeValidationPath = join(
|
|
232
|
+
tempDir,
|
|
233
|
+
".gsd",
|
|
234
|
+
"worktrees",
|
|
235
|
+
"M001",
|
|
236
|
+
".gsd",
|
|
237
|
+
"milestones",
|
|
238
|
+
"M001",
|
|
239
|
+
"M001-VALIDATION.md",
|
|
240
|
+
);
|
|
241
|
+
insertAssessment({
|
|
242
|
+
path: worktreeValidationPath,
|
|
243
|
+
milestoneId: "M001",
|
|
244
|
+
sliceId: null,
|
|
245
|
+
taskId: null,
|
|
246
|
+
status: "pass",
|
|
247
|
+
scope: "milestone-validation",
|
|
248
|
+
fullContent: "---\nverdict: pass\n---\n\n# Validation\nManually overridden via /gsd verdict\n",
|
|
249
|
+
});
|
|
250
|
+
invalidateAllCaches();
|
|
251
|
+
|
|
252
|
+
const ctx = makeMockCtx();
|
|
253
|
+
const pi = makeMockPi();
|
|
254
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
255
|
+
const s = makeMockSession(tempDir, "validate-milestone", "M001");
|
|
256
|
+
|
|
257
|
+
const result = await runPostUnitVerification({ s, ctx, pi } as VerificationContext, pauseAutoMock);
|
|
258
|
+
|
|
259
|
+
assert.equal(result, "continue");
|
|
260
|
+
assert.equal(pauseAutoMock.mock.callCount(), 0);
|
|
261
|
+
assert.equal(ctx.ui.notify.mock.callCount(), 0);
|
|
262
|
+
});
|
|
263
|
+
|
|
225
264
|
test("retries when no VALIDATION file exists yet", async () => {
|
|
226
265
|
insertMilestone({ id: "M001" });
|
|
227
266
|
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice 1", status: "complete" });
|