@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,150 @@
|
|
|
1
|
+
import { describe, test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { tmpdir } from "node:os";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
buildWebAppUatGuidanceBlock,
|
|
9
|
+
detectWebApp,
|
|
10
|
+
findPlaywrightTestScript,
|
|
11
|
+
hasPlaywrightTestDependency,
|
|
12
|
+
} from "../web-app-uat.ts";
|
|
13
|
+
|
|
14
|
+
function scaffoldProject(root: string, pkg: Record<string, unknown>): void {
|
|
15
|
+
writeFileSync(join(root, "package.json"), JSON.stringify(pkg, null, 2));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
describe("web-app-uat guidance", () => {
|
|
19
|
+
test("returns null for non-web projects", () => {
|
|
20
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
21
|
+
try {
|
|
22
|
+
writeFileSync(join(root, "README.md"), "# CLI tool\n");
|
|
23
|
+
assert.equal(detectWebApp(root), false);
|
|
24
|
+
assert.equal(buildWebAppUatGuidanceBlock(root), null);
|
|
25
|
+
} finally {
|
|
26
|
+
rmSync(root, { recursive: true, force: true });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("returns guidance for react/vite web apps", () => {
|
|
31
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
32
|
+
try {
|
|
33
|
+
scaffoldProject(root, {
|
|
34
|
+
dependencies: { react: "19.0.0", "react-dom": "19.0.0" },
|
|
35
|
+
devDependencies: { vite: "6.0.0" },
|
|
36
|
+
scripts: { dev: "vite" },
|
|
37
|
+
});
|
|
38
|
+
assert.equal(detectWebApp(root), true);
|
|
39
|
+
const block = buildWebAppUatGuidanceBlock(root);
|
|
40
|
+
assert.ok(block);
|
|
41
|
+
assert.match(block!, /browser-executable/);
|
|
42
|
+
assert.match(block!, /Playwright scaffolding/);
|
|
43
|
+
} finally {
|
|
44
|
+
rmSync(root, { recursive: true, force: true });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("detects existing Playwright and npm script", () => {
|
|
49
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
50
|
+
try {
|
|
51
|
+
scaffoldProject(root, {
|
|
52
|
+
dependencies: { next: "15.0.0" },
|
|
53
|
+
devDependencies: { "@playwright/test": "1.60.0", playwright: "1.60.0" },
|
|
54
|
+
scripts: { "test:e2e": "playwright test" },
|
|
55
|
+
});
|
|
56
|
+
assert.equal(hasPlaywrightTestDependency(root), true);
|
|
57
|
+
assert.equal(findPlaywrightTestScript(root), "npm run test:e2e");
|
|
58
|
+
const block = buildWebAppUatGuidanceBlock(root);
|
|
59
|
+
assert.ok(block);
|
|
60
|
+
assert.match(block!, /dependency detected/);
|
|
61
|
+
assert.match(block!, /npm run test:e2e/);
|
|
62
|
+
assert.doesNotMatch(block!, /Playwright scaffolding/);
|
|
63
|
+
} finally {
|
|
64
|
+
rmSync(root, { recursive: true, force: true });
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test("does not mistake a non-playwright e2e script as playwright", () => {
|
|
69
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
70
|
+
try {
|
|
71
|
+
scaffoldProject(root, {
|
|
72
|
+
dependencies: { react: "19.0.0" },
|
|
73
|
+
devDependencies: { "@playwright/test": "1.60.0" },
|
|
74
|
+
scripts: { e2e: "cypress run", dev: "vite" },
|
|
75
|
+
});
|
|
76
|
+
// The e2e script runs Cypress, not Playwright — must not be returned
|
|
77
|
+
assert.equal(findPlaywrightTestScript(root), null);
|
|
78
|
+
const block = buildWebAppUatGuidanceBlock(root);
|
|
79
|
+
assert.ok(block);
|
|
80
|
+
// Playwright dep is present so guidance shows "dependency detected", not "scaffolding"
|
|
81
|
+
assert.match(block!, /dependency detected/);
|
|
82
|
+
assert.doesNotMatch(block!, /Playwright scaffolding/);
|
|
83
|
+
// Falls back to generic npx command because no playwright-named script exists
|
|
84
|
+
assert.doesNotMatch(block!, /npm run e2e/);
|
|
85
|
+
} finally {
|
|
86
|
+
rmSync(root, { recursive: true, force: true });
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("recognises playwright via script value even without a local dependency", () => {
|
|
91
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
92
|
+
try {
|
|
93
|
+
scaffoldProject(root, {
|
|
94
|
+
dependencies: { next: "15.0.0" },
|
|
95
|
+
scripts: { "test:e2e": "npx playwright test" },
|
|
96
|
+
});
|
|
97
|
+
assert.equal(hasPlaywrightTestDependency(root), false);
|
|
98
|
+
assert.equal(findPlaywrightTestScript(root), "npm run test:e2e");
|
|
99
|
+
const block = buildWebAppUatGuidanceBlock(root);
|
|
100
|
+
assert.ok(block);
|
|
101
|
+
// Script-based detection should trigger "dependency detected" path, not scaffolding
|
|
102
|
+
assert.match(block!, /dependency detected/);
|
|
103
|
+
assert.match(block!, /npm run test:e2e/);
|
|
104
|
+
assert.doesNotMatch(block!, /Playwright scaffolding/);
|
|
105
|
+
} finally {
|
|
106
|
+
rmSync(root, { recursive: true, force: true });
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("does not treat playwright install script as a test command", () => {
|
|
111
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
112
|
+
try {
|
|
113
|
+
scaffoldProject(root, {
|
|
114
|
+
dependencies: { react: "19.0.0" },
|
|
115
|
+
devDependencies: { "@playwright/test": "1.60.0" },
|
|
116
|
+
// postinstall runs 'playwright install' (browser setup), not a test
|
|
117
|
+
scripts: { postinstall: "playwright install", "test:e2e": "npx playwright test" },
|
|
118
|
+
});
|
|
119
|
+
// install script must not be returned; the real test script should be
|
|
120
|
+
assert.equal(findPlaywrightTestScript(root), "npm run test:e2e");
|
|
121
|
+
} finally {
|
|
122
|
+
rmSync(root, { recursive: true, force: true });
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("returns null when only an install script mentions playwright", () => {
|
|
127
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
128
|
+
try {
|
|
129
|
+
scaffoldProject(root, {
|
|
130
|
+
dependencies: { react: "19.0.0" },
|
|
131
|
+
devDependencies: { "@playwright/test": "1.60.0" },
|
|
132
|
+
scripts: { postinstall: "playwright install --with-deps" },
|
|
133
|
+
});
|
|
134
|
+
assert.equal(findPlaywrightTestScript(root), null);
|
|
135
|
+
} finally {
|
|
136
|
+
rmSync(root, { recursive: true, force: true });
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
test("detects static sites via index.html", () => {
|
|
141
|
+
const root = mkdtempSync(join(tmpdir(), "gsd-web-uat-"));
|
|
142
|
+
try {
|
|
143
|
+
mkdirSync(join(root, "public"), { recursive: true });
|
|
144
|
+
writeFileSync(join(root, "public", "index.html"), "<html></html>");
|
|
145
|
+
assert.equal(detectWebApp(root), true);
|
|
146
|
+
} finally {
|
|
147
|
+
rmSync(root, { recursive: true, force: true });
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
@@ -17,9 +17,11 @@ import {
|
|
|
17
17
|
getRequiredWorkflowToolsForAutoUnit,
|
|
18
18
|
getRequiredWorkflowToolsForGuidedUnit,
|
|
19
19
|
resolveWorkflowMcpProjectRoot,
|
|
20
|
+
isWorkflowMcpSurfaceTool,
|
|
20
21
|
supportsStructuredQuestions,
|
|
21
22
|
usesWorkflowMcpTransport,
|
|
22
23
|
} from "../workflow-mcp.ts";
|
|
24
|
+
import { DB_WORKFLOW_TOOL_NAMES } from "../workflow-tool-surface.ts";
|
|
23
25
|
|
|
24
26
|
const MCP_STDIO_TIMEOUT_MS = 90_000;
|
|
25
27
|
|
|
@@ -109,6 +111,18 @@ test("workflow MCP capability surface includes native legacy gsd aliases", () =>
|
|
|
109
111
|
assert.equal(err, null);
|
|
110
112
|
});
|
|
111
113
|
|
|
114
|
+
test("workflow MCP capability surface includes every shared workflow contract tool", () => {
|
|
115
|
+
for (const name of DB_WORKFLOW_TOOL_NAMES) {
|
|
116
|
+
assert.equal(isWorkflowMcpSurfaceTool(name), true, `${name} should be in workflow MCP surface`);
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("workflow MCP capability surface preserves session and read tools outside DB contracts", () => {
|
|
121
|
+
for (const name of ["gsd_execute", "gsd_status", "gsd_progress", "gsd_doctor", "gsd_graph"]) {
|
|
122
|
+
assert.equal(isWorkflowMcpSurfaceTool(name), true, `${name} should stay in workflow MCP surface`);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
112
126
|
test("deep project setup units declare required workflow MCP tools", () => {
|
|
113
127
|
assert.deepEqual(getRequiredWorkflowToolsForGuidedUnit("discuss-project"), [
|
|
114
128
|
"ask_user_questions",
|
|
@@ -615,23 +629,47 @@ test("usesWorkflowMcpTransport matches local externalCli providers", () => {
|
|
|
615
629
|
assert.equal(usesWorkflowMcpTransport("oauth", "local://custom"), false);
|
|
616
630
|
});
|
|
617
631
|
|
|
618
|
-
test("supportsStructuredQuestions
|
|
632
|
+
test("supportsStructuredQuestions recognizes workflow MCP question tools", () => {
|
|
619
633
|
assert.equal(
|
|
620
634
|
supportsStructuredQuestions(["ask_user_questions"], {
|
|
621
635
|
authMode: "externalCli",
|
|
622
636
|
baseUrl: "local://claude-code",
|
|
623
637
|
env: {},
|
|
624
638
|
}),
|
|
625
|
-
|
|
639
|
+
true,
|
|
626
640
|
);
|
|
627
641
|
assert.equal(
|
|
628
642
|
supportsStructuredQuestions(["mcp__gsd-workflow__ask_user_questions"], {
|
|
629
643
|
authMode: "externalCli",
|
|
630
644
|
baseUrl: "local://claude-code",
|
|
631
|
-
env: {
|
|
645
|
+
env: {},
|
|
646
|
+
}),
|
|
647
|
+
true,
|
|
648
|
+
);
|
|
649
|
+
assert.equal(
|
|
650
|
+
supportsStructuredQuestions(["mcp__gsd-workflow__*"], {
|
|
651
|
+
authMode: "externalCli",
|
|
652
|
+
baseUrl: "local://claude-code",
|
|
653
|
+
env: {},
|
|
632
654
|
}),
|
|
633
655
|
true,
|
|
634
656
|
);
|
|
657
|
+
assert.equal(
|
|
658
|
+
supportsStructuredQuestions(["mcp__gsd-browser__*"], {
|
|
659
|
+
authMode: "externalCli",
|
|
660
|
+
baseUrl: "local://claude-code",
|
|
661
|
+
env: {},
|
|
662
|
+
}),
|
|
663
|
+
false,
|
|
664
|
+
);
|
|
665
|
+
assert.equal(
|
|
666
|
+
supportsStructuredQuestions(["mcp__gsd-workflow__ask_user_questions"], {
|
|
667
|
+
authMode: "externalCli",
|
|
668
|
+
baseUrl: "local://claude-code",
|
|
669
|
+
env: { GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS: "0" } as NodeJS.ProcessEnv,
|
|
670
|
+
}),
|
|
671
|
+
false,
|
|
672
|
+
);
|
|
635
673
|
assert.equal(
|
|
636
674
|
supportsStructuredQuestions(["ask_user_questions"], {
|
|
637
675
|
authMode: "oauth",
|
|
@@ -648,6 +686,39 @@ test("supportsStructuredQuestions disables local workflow MCP questions unless e
|
|
|
648
686
|
);
|
|
649
687
|
});
|
|
650
688
|
|
|
689
|
+
test("supportsStructuredQuestions gates non-local externalCli providers", () => {
|
|
690
|
+
assert.equal(
|
|
691
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
692
|
+
authMode: "externalCli",
|
|
693
|
+
env: {},
|
|
694
|
+
}),
|
|
695
|
+
true,
|
|
696
|
+
);
|
|
697
|
+
assert.equal(
|
|
698
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
699
|
+
authMode: "externalCli",
|
|
700
|
+
baseUrl: "https://api.example.com",
|
|
701
|
+
env: {},
|
|
702
|
+
}),
|
|
703
|
+
true,
|
|
704
|
+
);
|
|
705
|
+
assert.equal(
|
|
706
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
707
|
+
authMode: "externalCli",
|
|
708
|
+
env: { GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS: "0" } as NodeJS.ProcessEnv,
|
|
709
|
+
}),
|
|
710
|
+
false,
|
|
711
|
+
);
|
|
712
|
+
assert.equal(
|
|
713
|
+
supportsStructuredQuestions(["ask_user_questions"], {
|
|
714
|
+
authMode: "externalCli",
|
|
715
|
+
baseUrl: "https://api.example.com",
|
|
716
|
+
env: { GSD_WORKFLOW_MCP_STRUCTURED_QUESTIONS: "0" } as NodeJS.ProcessEnv,
|
|
717
|
+
}),
|
|
718
|
+
false,
|
|
719
|
+
);
|
|
720
|
+
});
|
|
721
|
+
|
|
651
722
|
test("transport compatibility passes when required tools fit current MCP surface", () => {
|
|
652
723
|
const error = getWorkflowTransportSupportError(
|
|
653
724
|
"claude-code",
|
|
@@ -835,7 +906,7 @@ test("transport compatibility now allows replan-slice over workflow MCP surface"
|
|
|
835
906
|
assert.equal(error, null);
|
|
836
907
|
});
|
|
837
908
|
|
|
838
|
-
test("transport compatibility
|
|
909
|
+
test("transport compatibility accepts workflow MCP tools absent from parent active tool surface", () => {
|
|
839
910
|
const error = getWorkflowTransportSupportError(
|
|
840
911
|
"claude-code",
|
|
841
912
|
["gsd_summary_save"],
|
|
@@ -850,10 +921,10 @@ test("transport compatibility rejects MCP tools not connected in active tool sur
|
|
|
850
921
|
},
|
|
851
922
|
);
|
|
852
923
|
|
|
853
|
-
assert.
|
|
924
|
+
assert.equal(error, null);
|
|
854
925
|
});
|
|
855
926
|
|
|
856
|
-
test("transport compatibility checks
|
|
927
|
+
test("transport compatibility still checks non-MCP tools against parent active tool surface", () => {
|
|
857
928
|
const error = getWorkflowTransportSupportError(
|
|
858
929
|
"claude-code",
|
|
859
930
|
["gsd_summary_save", "secure_env_collect"],
|
|
@@ -868,9 +939,54 @@ test("transport compatibility checks all required tools against active tool surf
|
|
|
868
939
|
},
|
|
869
940
|
);
|
|
870
941
|
|
|
871
|
-
assert.match(error ?? "", /requires
|
|
872
|
-
assert.
|
|
873
|
-
|
|
942
|
+
assert.match(error ?? "", /requires secure_env_collect/);
|
|
943
|
+
assert.doesNotMatch(error ?? "", /gsd_summary_save/);
|
|
944
|
+
});
|
|
945
|
+
|
|
946
|
+
test("transport compatibility allows plan-slice MCP tools when parent surface is scoped (regression #457)", () => {
|
|
947
|
+
const error = getWorkflowTransportSupportError(
|
|
948
|
+
"claude-code",
|
|
949
|
+
getRequiredWorkflowToolsForAutoUnit("plan-slice"),
|
|
950
|
+
{
|
|
951
|
+
projectRoot: "/tmp/project",
|
|
952
|
+
env: { GSD_WORKFLOW_MCP_COMMAND: "node" },
|
|
953
|
+
surface: "auto-mode",
|
|
954
|
+
unitType: "plan-slice",
|
|
955
|
+
authMode: "externalCli",
|
|
956
|
+
baseUrl: "local://claude-code",
|
|
957
|
+
activeTools: [
|
|
958
|
+
"ScheduleWakeup",
|
|
959
|
+
"ToolSearch",
|
|
960
|
+
"ask_user_questions",
|
|
961
|
+
"async_bash",
|
|
962
|
+
"await_job",
|
|
963
|
+
"bash",
|
|
964
|
+
"bg_shell",
|
|
965
|
+
"cancel_job",
|
|
966
|
+
"capture_thought",
|
|
967
|
+
"discover_configs",
|
|
968
|
+
"edit",
|
|
969
|
+
"fetch_page",
|
|
970
|
+
"get_library_docs",
|
|
971
|
+
"gsd_checkpoint_db",
|
|
972
|
+
"gsd_exec",
|
|
973
|
+
"gsd_exec_search",
|
|
974
|
+
"gsd_milestone_status",
|
|
975
|
+
"gsd_resume",
|
|
976
|
+
"mcp_call",
|
|
977
|
+
"mcp_discover",
|
|
978
|
+
"mcp_servers",
|
|
979
|
+
"memory_query",
|
|
980
|
+
"read",
|
|
981
|
+
"resolve_library",
|
|
982
|
+
"secure_env_collect",
|
|
983
|
+
"subagent",
|
|
984
|
+
"write",
|
|
985
|
+
],
|
|
986
|
+
},
|
|
987
|
+
);
|
|
988
|
+
|
|
989
|
+
assert.equal(error, null);
|
|
874
990
|
});
|
|
875
991
|
|
|
876
992
|
test("transport compatibility still blocks units whose MCP tools are not exposed", () => {
|
|
@@ -895,6 +1011,7 @@ test("discuss-milestone guided flow does not abort when all required tools are o
|
|
|
895
1011
|
// Guided flow starts the workflow MCP server as part of dispatch, so the
|
|
896
1012
|
// parent session active-tool list is not authoritative for MCP tools.
|
|
897
1013
|
const discussMilestoneTools = [
|
|
1014
|
+
"ask_user_questions",
|
|
898
1015
|
"gsd_summary_save",
|
|
899
1016
|
"gsd_requirement_save",
|
|
900
1017
|
"gsd_requirement_update",
|
|
@@ -109,6 +109,21 @@ test("ensureWorkspaceGitReadyForPath blocks product file conflicts", async () =>
|
|
|
109
109
|
}
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
+
test("ensureWorkspaceGitReadyForPath does not block on staged files with trailing whitespace", async () => {
|
|
113
|
+
// Regression test for #599: git diff --check exits non-zero for whitespace
|
|
114
|
+
// errors as well as conflict markers. Staged files from auto-generated code
|
|
115
|
+
// often have trailing whitespace; these must not trigger the conflict gate.
|
|
116
|
+
const base = makeTempRepo("gsd-ws-git-whitespace-");
|
|
117
|
+
try {
|
|
118
|
+
writeFileSync(join(base, "app.ts"), "const x = 1; \n"); // trailing whitespace
|
|
119
|
+
git(base, "add", "app.ts");
|
|
120
|
+
const ready = await ensureWorkspaceGitReadyForPath(base);
|
|
121
|
+
assert.equal(ready.ok, true, "trailing whitespace in staged files must not block");
|
|
122
|
+
} finally {
|
|
123
|
+
cleanup(base);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
|
|
112
127
|
test("isWorkspaceGitAllowedCommand allowlists doctor, closeout, and dispatch complete-milestone", () => {
|
|
113
128
|
assert.equal(isWorkspaceGitAllowedCommand("doctor"), true);
|
|
114
129
|
assert.equal(isWorkspaceGitAllowedCommand("doctor fix"), true);
|
|
@@ -121,6 +121,27 @@ describe("createWorktree", () => {
|
|
|
121
121
|
run("git rev-parse --git-dir", info.path);
|
|
122
122
|
assert.ok(!existsSync(join(info.path, "orphan.txt")), "stale file removed by recovery");
|
|
123
123
|
});
|
|
124
|
+
|
|
125
|
+
test("removes stale worktree directory with .git file not registered with git and recreates", () => {
|
|
126
|
+
// Simulate the scenario from issue #590: removeWorktree() failed to delete
|
|
127
|
+
// the directory (e.g. EPERM on Windows) but git worktree prune cleaned up
|
|
128
|
+
// the registry — leaving an orphaned directory with a .git *file* (not
|
|
129
|
+
// directory) that git no longer knows about.
|
|
130
|
+
const staleDir = worktreePath(base, "M010");
|
|
131
|
+
mkdirSync(staleDir, { recursive: true });
|
|
132
|
+
// Write a .git file (worktree gitdir pointer) — not a directory
|
|
133
|
+
writeFileSync(join(staleDir, ".git"), "gitdir: ../../../../.git/worktrees/M010\n", "utf-8");
|
|
134
|
+
writeFileSync(join(staleDir, "orphan.txt"), "stale leftover\n", "utf-8");
|
|
135
|
+
|
|
136
|
+
// createWorktree must detect the orphan (not in git worktree list), clean it
|
|
137
|
+
// up, and succeed — not throw GSD_STALE_STATE as if it were a live conflict.
|
|
138
|
+
const info = createWorktree(base, "M010");
|
|
139
|
+
assert.strictEqual(info.name, "M010");
|
|
140
|
+
assert.ok(existsSync(info.path));
|
|
141
|
+
assert.ok(existsSync(join(info.path, ".git")), "recovered worktree has .git marker");
|
|
142
|
+
run("git rev-parse --git-dir", info.path);
|
|
143
|
+
assert.ok(!existsSync(join(info.path, "orphan.txt")), "stale file removed by recovery");
|
|
144
|
+
});
|
|
124
145
|
});
|
|
125
146
|
|
|
126
147
|
describe("createWorktree — duplicate rejection", () => {
|
|
@@ -171,7 +171,7 @@ test("validate-milestone invoked from the project root writes VALIDATION under t
|
|
|
171
171
|
const projectProjection = join(projectRoot, ".gsd", "milestones", MID, "M001-VALIDATION.md");
|
|
172
172
|
assert.equal(result.validationPath, expected);
|
|
173
173
|
assert.equal(existsSync(expected), true);
|
|
174
|
-
assert.equal(existsSync(projectProjection),
|
|
174
|
+
assert.equal(existsSync(projectProjection), true, "VALIDATION should mirror to project root for consistent reads");
|
|
175
175
|
});
|
|
176
176
|
|
|
177
177
|
test("complete-milestone writes SUMMARY under the active worktree projection", async (t) => {
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
emitWorktreeOrphaned,
|
|
19
19
|
emitAutoExit,
|
|
20
20
|
emitCanonicalRootRedirect,
|
|
21
|
+
autoExitReasonForTerminalOutcome,
|
|
21
22
|
normalizeAutoExitReason,
|
|
22
23
|
summarizeWorktreeTelemetry,
|
|
23
24
|
percentile,
|
|
@@ -117,6 +118,27 @@ test("normalizeAutoExitReason maps new buckets and ignores casing", () => {
|
|
|
117
118
|
}
|
|
118
119
|
});
|
|
119
120
|
|
|
121
|
+
test("autoExitReasonForTerminalOutcome maps typed terminal outcomes", () => {
|
|
122
|
+
assert.equal(
|
|
123
|
+
autoExitReasonForTerminalOutcome({
|
|
124
|
+
code: "all-complete",
|
|
125
|
+
displayReason: "All milestones complete",
|
|
126
|
+
allMilestonesComplete: true,
|
|
127
|
+
}),
|
|
128
|
+
"all-complete",
|
|
129
|
+
);
|
|
130
|
+
assert.equal(
|
|
131
|
+
autoExitReasonForTerminalOutcome({
|
|
132
|
+
code: "settlement-blocked",
|
|
133
|
+
displayReason: "Milestone complete, merge blocked",
|
|
134
|
+
nextAction: "Retry closeout",
|
|
135
|
+
milestoneId: "M001",
|
|
136
|
+
allMilestonesComplete: false,
|
|
137
|
+
}),
|
|
138
|
+
"blocked",
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
|
|
120
142
|
test("summarizeWorktreeTelemetry only counts unmerged exits from active worktrees", (t) => {
|
|
121
143
|
const base = makeTmpBase();
|
|
122
144
|
t.after(() => cleanup(base));
|
|
@@ -340,6 +340,8 @@ test('write-gate: reopening a gate revokes its previous verified approval', () =
|
|
|
340
340
|
// ═══════════════════════════════════════════════════════════════════════
|
|
341
341
|
|
|
342
342
|
import {
|
|
343
|
+
applyAskUserQuestionsGateResult,
|
|
344
|
+
formatPendingAskUserQuestionsGateMessage,
|
|
343
345
|
isGateQuestionId,
|
|
344
346
|
shouldBlockPendingGate,
|
|
345
347
|
shouldBlockPendingGateBash,
|
|
@@ -379,6 +381,83 @@ test('write-gate: pending gate lifecycle (set, get, clear)', () => {
|
|
|
379
381
|
assert.strictEqual(getPendingGate(), null, 'clearDiscussionFlowState clears pending gate');
|
|
380
382
|
});
|
|
381
383
|
|
|
384
|
+
test('write-gate: applyAskUserQuestionsGateResult keeps cancelled pending gate waiting', () => {
|
|
385
|
+
const base = join(tmpdir(), `gsd-write-gate-ask-waiting-${randomUUID()}`);
|
|
386
|
+
const gateId = 'depth_verification_M001_confirm';
|
|
387
|
+
|
|
388
|
+
try {
|
|
389
|
+
mkdirSync(base, { recursive: true });
|
|
390
|
+
clearDiscussionFlowState(base);
|
|
391
|
+
setPendingGate(gateId, base);
|
|
392
|
+
|
|
393
|
+
const result = applyAskUserQuestionsGateResult({
|
|
394
|
+
basePath: base,
|
|
395
|
+
questions: [{
|
|
396
|
+
id: gateId,
|
|
397
|
+
options: [{ label: 'Confirm depth (Recommended)' }, { label: 'Needs adjustment' }],
|
|
398
|
+
}],
|
|
399
|
+
details: { cancelled: true, interrupted: true },
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
assert.deepEqual(result, {
|
|
403
|
+
status: 'waiting',
|
|
404
|
+
pendingGateId: gateId,
|
|
405
|
+
interrupted: true,
|
|
406
|
+
});
|
|
407
|
+
assert.strictEqual(getPendingGate(base), gateId, 'cancelled question must leave gate pending');
|
|
408
|
+
assert.strictEqual(isMilestoneDepthVerified('M001', base), false, 'cancelled question must not verify depth');
|
|
409
|
+
assert.match(
|
|
410
|
+
formatPendingAskUserQuestionsGateMessage(gateId, true),
|
|
411
|
+
/Re-call ask_user_questions with the same gate question id/,
|
|
412
|
+
);
|
|
413
|
+
} finally {
|
|
414
|
+
clearDiscussionFlowState(base);
|
|
415
|
+
rmSync(base, { recursive: true, force: true });
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test('write-gate: applyAskUserQuestionsGateResult verifies confirmed pending gate', () => {
|
|
420
|
+
const base = join(tmpdir(), `gsd-write-gate-ask-verified-${randomUUID()}`);
|
|
421
|
+
const gateId = 'depth_verification_M001_confirm';
|
|
422
|
+
const confirmLabel = 'Confirm depth (Recommended)';
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
mkdirSync(base, { recursive: true });
|
|
426
|
+
clearDiscussionFlowState(base);
|
|
427
|
+
setPendingGate(gateId, base);
|
|
428
|
+
|
|
429
|
+
const result = applyAskUserQuestionsGateResult({
|
|
430
|
+
basePath: base,
|
|
431
|
+
questions: [{
|
|
432
|
+
id: gateId,
|
|
433
|
+
options: [{ label: confirmLabel }, { label: 'Needs adjustment' }],
|
|
434
|
+
}],
|
|
435
|
+
details: {
|
|
436
|
+
response: {
|
|
437
|
+
answers: {
|
|
438
|
+
[gateId]: { selected: confirmLabel },
|
|
439
|
+
},
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
});
|
|
443
|
+
|
|
444
|
+
assert.deepEqual(result, {
|
|
445
|
+
status: 'verified',
|
|
446
|
+
gateId,
|
|
447
|
+
milestoneId: 'M001',
|
|
448
|
+
});
|
|
449
|
+
assert.strictEqual(getPendingGate(base), null, 'confirmed gate must clear pending state');
|
|
450
|
+
assert.strictEqual(isMilestoneDepthVerified('M001', base), true, 'confirmed gate must verify milestone depth');
|
|
451
|
+
assert.ok(
|
|
452
|
+
loadWriteGateSnapshot(base).verifiedApprovalGates?.includes(gateId) ?? false,
|
|
453
|
+
'confirmed gate must record verified approval',
|
|
454
|
+
);
|
|
455
|
+
} finally {
|
|
456
|
+
clearDiscussionFlowState(base);
|
|
457
|
+
rmSync(base, { recursive: true, force: true });
|
|
458
|
+
}
|
|
459
|
+
});
|
|
460
|
+
|
|
382
461
|
// ─── Scenario 21: shouldBlockPendingGate blocks non-safe tools when gate is pending ──
|
|
383
462
|
|
|
384
463
|
test('write-gate: shouldBlockPendingGate blocks write/edit during pending gate', () => {
|