@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
|
@@ -6,12 +6,15 @@ import assert from "node:assert/strict";
|
|
|
6
6
|
|
|
7
7
|
import {
|
|
8
8
|
autoSession,
|
|
9
|
+
clearAutoToolSurfaceSnapshot,
|
|
9
10
|
clearToolInvocationError,
|
|
10
11
|
getAutoRuntimeSnapshot,
|
|
12
|
+
recordAutoToolSurfaceSnapshot,
|
|
11
13
|
} from "../auto-runtime-state.ts";
|
|
12
14
|
|
|
13
15
|
test("getAutoRuntimeSnapshot includes orchestration phase when available", () => {
|
|
14
16
|
autoSession.reset();
|
|
17
|
+
clearAutoToolSurfaceSnapshot();
|
|
15
18
|
autoSession.active = true;
|
|
16
19
|
autoSession.basePath = "/tmp/project";
|
|
17
20
|
autoSession.orchestration = {
|
|
@@ -33,10 +36,40 @@ test("getAutoRuntimeSnapshot includes orchestration phase when available", () =>
|
|
|
33
36
|
assert.equal(snap.orchestrationPhase, "running");
|
|
34
37
|
assert.equal(snap.orchestrationTransitionCount, 3);
|
|
35
38
|
assert.equal(snap.orchestrationLastTransitionAt, 123);
|
|
39
|
+
assert.equal(snap.toolSurface, null);
|
|
36
40
|
|
|
37
41
|
autoSession.reset();
|
|
38
42
|
});
|
|
39
43
|
|
|
44
|
+
test("getAutoRuntimeSnapshot includes the active typed tool-surface snapshot", () => {
|
|
45
|
+
autoSession.reset();
|
|
46
|
+
clearAutoToolSurfaceSnapshot();
|
|
47
|
+
autoSession.active = true;
|
|
48
|
+
|
|
49
|
+
recordAutoToolSurfaceSnapshot({
|
|
50
|
+
source: "dispatch-scope",
|
|
51
|
+
unitType: "run-uat",
|
|
52
|
+
modelFacingToolNames: ["read", "read", "gsd_uat_exec"],
|
|
53
|
+
registeredToolNames: ["read", "browser_navigate"],
|
|
54
|
+
scopedToolNames: ["read", "browser_navigate"],
|
|
55
|
+
presentedToolNames: ["gsd_uat_exec"],
|
|
56
|
+
capturedAt: 123,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const snap = getAutoRuntimeSnapshot();
|
|
60
|
+
|
|
61
|
+
assert.equal(snap.toolSurface?.source, "dispatch-scope");
|
|
62
|
+
assert.equal(snap.toolSurface?.unitType, "run-uat");
|
|
63
|
+
assert.deepEqual(snap.toolSurface?.modelFacingToolNames, ["read", "gsd_uat_exec"]);
|
|
64
|
+
assert.deepEqual(snap.toolSurface?.registeredToolNames, ["read", "browser_navigate"]);
|
|
65
|
+
assert.deepEqual(snap.toolSurface?.scopedToolNames, ["read", "browser_navigate"]);
|
|
66
|
+
assert.deepEqual(snap.toolSurface?.presentedToolNames, ["gsd_uat_exec"]);
|
|
67
|
+
assert.equal(snap.toolSurface?.capturedAt, 123);
|
|
68
|
+
|
|
69
|
+
autoSession.reset();
|
|
70
|
+
clearAutoToolSurfaceSnapshot();
|
|
71
|
+
});
|
|
72
|
+
|
|
40
73
|
test("clearToolInvocationError clears stale tool error state for active auto sessions", () => {
|
|
41
74
|
autoSession.reset();
|
|
42
75
|
autoSession.active = true;
|
|
@@ -56,4 +89,5 @@ test("getAutoRuntimeSnapshot omits orchestration phase when seam not wired", ()
|
|
|
56
89
|
assert.equal(snap.orchestrationPhase, undefined);
|
|
57
90
|
assert.equal(snap.orchestrationTransitionCount, undefined);
|
|
58
91
|
assert.equal(snap.orchestrationLastTransitionAt, undefined);
|
|
92
|
+
assert.equal(snap.toolSurface, null);
|
|
59
93
|
});
|
|
@@ -17,6 +17,7 @@ import { tmpdir } from "node:os";
|
|
|
17
17
|
import { randomUUID } from "node:crypto";
|
|
18
18
|
|
|
19
19
|
import { resolveCanonicalMilestoneRoot } from "../worktree-manager.ts";
|
|
20
|
+
import { resolveCloseoutArtifactProjection } from "../artifact-projection.ts";
|
|
20
21
|
|
|
21
22
|
function makeTmpBase(): string {
|
|
22
23
|
const base = join(tmpdir(), `gsd-canon-test-${randomUUID()}`);
|
|
@@ -106,3 +107,22 @@ test("only returns the worktree for the requested milestone, not siblings", () =
|
|
|
106
107
|
cleanup(base);
|
|
107
108
|
}
|
|
108
109
|
});
|
|
110
|
+
|
|
111
|
+
test("resolveCloseoutArtifactProjection names project and canonical artifact roots", () => {
|
|
112
|
+
const base = makeTmpBase();
|
|
113
|
+
try {
|
|
114
|
+
const wtPath = makeLiveWorktree(base, "M001");
|
|
115
|
+
const projection = resolveCloseoutArtifactProjection({
|
|
116
|
+
milestoneId: "M001",
|
|
117
|
+
basePath: wtPath,
|
|
118
|
+
originalBasePath: base,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
assert.equal(projection.projectRoot, base);
|
|
122
|
+
assert.equal(projection.canonicalMilestoneRoot, wtPath);
|
|
123
|
+
assert.equal(projection.summaryArtifactBasePath, wtPath);
|
|
124
|
+
assert.equal(projection.gateEvidenceBasePath, wtPath);
|
|
125
|
+
} finally {
|
|
126
|
+
cleanup(base);
|
|
127
|
+
}
|
|
128
|
+
});
|
|
@@ -696,3 +696,25 @@ test("ensureCodebaseMapFresh: does not rewrite expired metadata when fingerprint
|
|
|
696
696
|
cleanup(base);
|
|
697
697
|
}
|
|
698
698
|
});
|
|
699
|
+
|
|
700
|
+
test("ensureCodebaseMapFresh: detects file changes within the TTL window", () => {
|
|
701
|
+
const base = makeTmpRepo();
|
|
702
|
+
try {
|
|
703
|
+
addFile(base, "src/main.ts");
|
|
704
|
+
// Generate initial map with a long TTL so the cache is still active.
|
|
705
|
+
const initial = ensureCodebaseMapFresh(base, undefined, { ttlMs: 60_000 });
|
|
706
|
+
assert.equal(initial.status, "generated");
|
|
707
|
+
|
|
708
|
+
// Add a new tracked file while the TTL is still active.
|
|
709
|
+
addFile(base, "src/new.ts");
|
|
710
|
+
|
|
711
|
+
// Must detect the change even though the TTL has not expired.
|
|
712
|
+
const refreshed = ensureCodebaseMapFresh(base, undefined, { ttlMs: 60_000 });
|
|
713
|
+
assert.equal(refreshed.status, "updated");
|
|
714
|
+
assert.equal(refreshed.reason, "files-changed");
|
|
715
|
+
const written = readCodebaseMap(base);
|
|
716
|
+
assert.ok(written?.includes("`src/new.ts`"));
|
|
717
|
+
} finally {
|
|
718
|
+
cleanup(base);
|
|
719
|
+
}
|
|
720
|
+
});
|
|
@@ -64,3 +64,14 @@ test("getWorkspaceGitBlockMessageForBase allows doctor on product conflicts", as
|
|
|
64
64
|
cleanup(base);
|
|
65
65
|
}
|
|
66
66
|
});
|
|
67
|
+
|
|
68
|
+
test("getWorkspaceGitBlockMessageForBase allows forensics on product conflicts", async () => {
|
|
69
|
+
const base = makeTempRepo("gsd-dispatch-ws-git-forensics-");
|
|
70
|
+
try {
|
|
71
|
+
seedProductConflict(base);
|
|
72
|
+
const blocked = await getWorkspaceGitBlockMessageForBase(base, "forensics");
|
|
73
|
+
assert.equal(blocked, null);
|
|
74
|
+
} finally {
|
|
75
|
+
cleanup(base);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import test from "node:test";
|
|
12
12
|
import assert from "node:assert/strict";
|
|
13
|
-
import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
13
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { randomUUID } from "node:crypto";
|
|
@@ -486,3 +486,40 @@ test("state.ts needs-remediation blocker messages reference /gsd verdict", async
|
|
|
486
486
|
`expected at least 2 references to /gsd verdict in state.ts blockers, found ${occurrences.length}`,
|
|
487
487
|
);
|
|
488
488
|
});
|
|
489
|
+
|
|
490
|
+
// ─── WAL checkpoint regression (#563) ───────────────────────────────────
|
|
491
|
+
|
|
492
|
+
test("handleVerdict pass checkpoints WAL so subsequent processes see the updated verdict (#563)", async () => {
|
|
493
|
+
// Regression: before the fix, executeValidateMilestone wrote the assessment
|
|
494
|
+
// only into the WAL file. The next /gsd auto invocation (a new process)
|
|
495
|
+
// opened gsd.db directly and saw stale pre-verdict data because the WAL
|
|
496
|
+
// had not been flushed. The fix adds checkpointDatabase() after a
|
|
497
|
+
// successful verdict so the WAL is truncated and gsd.db is self-contained.
|
|
498
|
+
const base = makeBase();
|
|
499
|
+
try {
|
|
500
|
+
openTestDb(base);
|
|
501
|
+
seedMilestone("M001", "Checkpoint Test Milestone");
|
|
502
|
+
seedSlice("M001", "S01", "complete");
|
|
503
|
+
writeValidation(base, "M001", "needs-attention");
|
|
504
|
+
|
|
505
|
+
const { ctx } = makeMockCtx();
|
|
506
|
+
await handleVerdict("pass --milestone M001", ctx, base);
|
|
507
|
+
|
|
508
|
+
// After handleVerdict succeeds, PRAGMA wal_checkpoint(TRUNCATE) must have
|
|
509
|
+
// run. The WAL file is truncated to zero bytes — a new process reading
|
|
510
|
+
// gsd.db directly sees the updated verdict without needing the WAL.
|
|
511
|
+
const walPath = join(base, ".gsd", "gsd.db-wal");
|
|
512
|
+
if (existsSync(walPath)) {
|
|
513
|
+
const { size } = statSync(walPath);
|
|
514
|
+
assert.equal(
|
|
515
|
+
size,
|
|
516
|
+
0,
|
|
517
|
+
"WAL must be zero bytes after handleVerdict pass — checkpointDatabase() was not called (#563)",
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
} finally {
|
|
521
|
+
closeDatabase();
|
|
522
|
+
invalidateStateCache();
|
|
523
|
+
cleanup(base);
|
|
524
|
+
}
|
|
525
|
+
});
|
|
@@ -14,7 +14,15 @@ import { execFileSync } from "node:child_process";
|
|
|
14
14
|
|
|
15
15
|
import { DISPATCH_RULES, resolveDispatch, type DispatchContext } from "../auto-dispatch.ts";
|
|
16
16
|
import { AutoSession } from "../auto/session.ts";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
closeDatabase,
|
|
19
|
+
getPendingGates,
|
|
20
|
+
insertAssessment,
|
|
21
|
+
insertGateRow,
|
|
22
|
+
insertMilestone,
|
|
23
|
+
insertSlice,
|
|
24
|
+
openDatabase,
|
|
25
|
+
} from "../gsd-db.ts";
|
|
18
26
|
|
|
19
27
|
function makeBase(): string {
|
|
20
28
|
const base = mkdtempSync(join(tmpdir(), "gsd-complete-dispatch-"));
|
|
@@ -243,7 +251,7 @@ describe("complete phase dispatch guard (#5683)", () => {
|
|
|
243
251
|
assert.equal(result?.reason, "All milestones complete.");
|
|
244
252
|
});
|
|
245
253
|
|
|
246
|
-
test("
|
|
254
|
+
test("closes stale pending gates from milestone validation before terminal stop", async () => {
|
|
247
255
|
base = makeBase();
|
|
248
256
|
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
249
257
|
insertMilestone({ id: "M001", title: "Milestone One", status: "complete" });
|
|
@@ -268,10 +276,33 @@ describe("complete phase dispatch guard (#5683)", () => {
|
|
|
268
276
|
|
|
269
277
|
const result = await rule.match(ctx);
|
|
270
278
|
|
|
279
|
+
assert.equal(result?.action, "stop");
|
|
280
|
+
assert.equal(result?.reason, "All milestones complete.");
|
|
281
|
+
assert.deepEqual(getPendingGates("M001", "S01"), []);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("blocks terminal stop when pending gates have no closeout evidence", async () => {
|
|
285
|
+
base = makeBase();
|
|
286
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
287
|
+
insertMilestone({ id: "M001", title: "Milestone One", status: "complete" });
|
|
288
|
+
insertSlice({ milestoneId: "M001", id: "S01", title: "Done", status: "complete" });
|
|
289
|
+
insertGateRow({
|
|
290
|
+
milestoneId: "M001",
|
|
291
|
+
sliceId: "S01",
|
|
292
|
+
gateId: "Q3",
|
|
293
|
+
scope: "slice",
|
|
294
|
+
status: "pending",
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
const ctx = buildDispatchCtx(base);
|
|
298
|
+
ctx.state.phase = "complete";
|
|
299
|
+
|
|
300
|
+
const result = await rule.match(ctx);
|
|
301
|
+
|
|
271
302
|
assert.equal(result?.action, "stop");
|
|
272
303
|
assert.equal(result?.level, "warning");
|
|
273
304
|
assert.match(result?.reason ?? "", /closeout-consistency-blocked/);
|
|
274
|
-
assert.match(result?.reason ?? "", /
|
|
305
|
+
assert.match(result?.reason ?? "", /latest milestone validation is "absent"/);
|
|
275
306
|
});
|
|
276
307
|
});
|
|
277
308
|
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Regression coverage for run-uat browser tool availability checks.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { tmpdir } from "node:os";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
|
|
10
|
+
import { DISPATCH_RULES, type DispatchContext } from "../auto-dispatch.ts";
|
|
11
|
+
import type { GSDState } from "../types.ts";
|
|
12
|
+
|
|
13
|
+
type DispatchRuleEntry = (typeof DISPATCH_RULES)[number];
|
|
14
|
+
|
|
15
|
+
function runUatRule(): DispatchRuleEntry {
|
|
16
|
+
const rule = DISPATCH_RULES.find((entry) => entry.name === "run-uat (post-completion)");
|
|
17
|
+
assert.ok(rule, "run-uat dispatch rule must exist");
|
|
18
|
+
return rule;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function makeState(): GSDState {
|
|
22
|
+
return {
|
|
23
|
+
activeMilestone: { id: "M001", title: "Browser UAT" },
|
|
24
|
+
activeSlice: { id: "S02", title: "Next Slice" },
|
|
25
|
+
activeTask: null,
|
|
26
|
+
phase: "verifying",
|
|
27
|
+
recentDecisions: [],
|
|
28
|
+
blockers: [],
|
|
29
|
+
nextAction: "",
|
|
30
|
+
registry: [],
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function scaffoldRunUatProject(basePath: string): void {
|
|
35
|
+
const milestoneDir = join(basePath, ".gsd", "milestones", "M001");
|
|
36
|
+
const sliceDir = join(milestoneDir, "slices", "S01");
|
|
37
|
+
mkdirSync(sliceDir, { recursive: true });
|
|
38
|
+
|
|
39
|
+
writeFileSync(join(milestoneDir, "M001-ROADMAP.md"), [
|
|
40
|
+
"# M001: Browser UAT",
|
|
41
|
+
"",
|
|
42
|
+
"## Slices",
|
|
43
|
+
"",
|
|
44
|
+
"- [x] **S01: Completed browser slice** `risk:low` `depends:[]`",
|
|
45
|
+
"- [ ] **S02: Next slice** `risk:low` `depends:[S01]`",
|
|
46
|
+
"",
|
|
47
|
+
].join("\n"), "utf-8");
|
|
48
|
+
|
|
49
|
+
writeFileSync(join(sliceDir, "S01-SUMMARY.md"), "# S01 Summary\n\nDone.\n", "utf-8");
|
|
50
|
+
writeFileSync(join(sliceDir, "S01-UAT.md"), [
|
|
51
|
+
"# S01 UAT",
|
|
52
|
+
"",
|
|
53
|
+
"## UAT Type",
|
|
54
|
+
"- UAT mode: human-experience",
|
|
55
|
+
"",
|
|
56
|
+
"Open the app in a browser and verify the completed user flow.",
|
|
57
|
+
"",
|
|
58
|
+
].join("\n"), "utf-8");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function makeContext(basePath: string, overrides: Partial<DispatchContext> = {}): DispatchContext {
|
|
62
|
+
return {
|
|
63
|
+
basePath,
|
|
64
|
+
mid: "M001",
|
|
65
|
+
midTitle: "Browser UAT",
|
|
66
|
+
state: makeState(),
|
|
67
|
+
prefs: undefined,
|
|
68
|
+
activeTools: ["read", "gsd_uat_exec", "gsd_uat_result_save"],
|
|
69
|
+
...overrides,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
test("run-uat browser preflight uses registered tools when the active surface is scoped", async (t) => {
|
|
74
|
+
const basePath = mkdtempSync(join(tmpdir(), "gsd-run-uat-browser-tools-"));
|
|
75
|
+
t.after(() => rmSync(basePath, { recursive: true, force: true }));
|
|
76
|
+
scaffoldRunUatProject(basePath);
|
|
77
|
+
|
|
78
|
+
const blocked = await runUatRule().match(makeContext(basePath));
|
|
79
|
+
assert.equal(blocked?.action, "stop");
|
|
80
|
+
assert.match(blocked?.action === "stop" ? blocked.reason : "", /run-uat tool surface has none/);
|
|
81
|
+
|
|
82
|
+
const dispatched = await runUatRule().match(makeContext(basePath, {
|
|
83
|
+
registeredTools: ["browser_navigate"],
|
|
84
|
+
}));
|
|
85
|
+
assert.equal(dispatched?.action, "dispatch");
|
|
86
|
+
assert.equal(dispatched?.action === "dispatch" ? dispatched.unitType : undefined, "run-uat");
|
|
87
|
+
assert.equal(dispatched?.action === "dispatch" ? dispatched.unitId : undefined, "M001/S01");
|
|
88
|
+
});
|
|
@@ -26,6 +26,24 @@ test("filterDoctorIssues keeps project and environment issues in scoped reports"
|
|
|
26
26
|
);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
+
test("filterDoctorIssues keeps invalid_preferences issues regardless of preferences file scope", () => {
|
|
30
|
+
// Both global and project preference diagnostics should survive scope filtering.
|
|
31
|
+
// doctor.ts uses unitId: "project" for all invalid_preferences issues so they
|
|
32
|
+
// pass through the scope filter the same way other project-level issues do.
|
|
33
|
+
const issues = [
|
|
34
|
+
{ severity: "error", code: "invalid_preferences", scope: "project", unitId: "project", message: "global PREFERENCES.md parse error", fixable: false },
|
|
35
|
+
{ severity: "error", code: "invalid_preferences", scope: "project", unitId: "project", message: "project PREFERENCES.md parse error", fixable: false },
|
|
36
|
+
{ severity: "error", code: "invalid_preferences", scope: "project", unitId: "global", message: "stale unitId — should be filtered out", fixable: false },
|
|
37
|
+
] as const;
|
|
38
|
+
|
|
39
|
+
const filtered = filterDoctorIssues([...issues], { scope: "M016", includeWarnings: true });
|
|
40
|
+
assert.deepEqual(
|
|
41
|
+
filtered.map((issue) => issue.message),
|
|
42
|
+
["global PREFERENCES.md parse error", "project PREFERENCES.md parse error"],
|
|
43
|
+
"invalid_preferences issues with unitId: project survive scope filtering; unitId: global is dropped",
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
29
47
|
test("checkEngineHealth reports db_unavailable when gsd.db exists but the DB is closed", async (t) => {
|
|
30
48
|
const base = mkdtempSync(join(tmpdir(), "gsd-doctor-db-unavailable-"));
|
|
31
49
|
t.after(() => rmSync(base, { recursive: true, force: true }));
|
|
@@ -38,6 +38,7 @@ test("execute-task prompt renders compact execution and completion gates", async
|
|
|
38
38
|
planPath: ".gsd/milestones/M001/slices/S01/S01-PLAN.md",
|
|
39
39
|
taskPlanPath: ".gsd/milestones/M001/slices/S01/tasks/T01-PLAN.md",
|
|
40
40
|
priorTaskLines: "- None",
|
|
41
|
+
onDemandContext: "",
|
|
41
42
|
skillActivation: "Load relevant skills.",
|
|
42
43
|
inlinedTemplates: "### Output Template: Task Summary\nSource: `templates/task-summary.md`",
|
|
43
44
|
templatesDir: join(fixtureRoot, "templates"),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { describe, test, beforeEach, afterEach } from "node:test";
|
|
5
5
|
import assert from "node:assert/strict";
|
|
6
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
6
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { tmpdir } from "node:os";
|
|
9
9
|
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
insertSlice,
|
|
19
19
|
} from "../gsd-db.ts";
|
|
20
20
|
import type { GateVerdict } from "../types.ts";
|
|
21
|
+
import { closeQualityGatesFromEvidence } from "../quality-gate-closure.ts";
|
|
21
22
|
|
|
22
23
|
describe("gate-state canonicalization (#4950)", () => {
|
|
23
24
|
let tmpDir: string;
|
|
@@ -99,4 +100,50 @@ describe("gate-state canonicalization (#4950)", () => {
|
|
|
99
100
|
assert.notEqual(g.verdict, "", `gate ${g.gate_id} verdict must not be empty string`);
|
|
100
101
|
}
|
|
101
102
|
});
|
|
103
|
+
|
|
104
|
+
test("closeQualityGatesFromEvidence repairs pending gate from durable section", () => {
|
|
105
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
106
|
+
mkdirSync(join(tmpDir, ".gsd", "milestones", "M001", "slices", "S01"), { recursive: true });
|
|
107
|
+
writeFileSync(
|
|
108
|
+
join(tmpDir, ".gsd", "milestones", "M001", "slices", "S01", "S01-PLAN.md"),
|
|
109
|
+
[
|
|
110
|
+
"# S01",
|
|
111
|
+
"",
|
|
112
|
+
"## Threat Surface",
|
|
113
|
+
"",
|
|
114
|
+
"- Credential stuffing is rate-limited.",
|
|
115
|
+
].join("\n"),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const result = closeQualityGatesFromEvidence("M001", { artifactBasePath: tmpDir });
|
|
119
|
+
|
|
120
|
+
assert.deepEqual(result.unresolved, []);
|
|
121
|
+
assert.deepEqual(result.repaired, [{ gateId: "Q3", sliceId: "S01", verdict: "pass" }]);
|
|
122
|
+
assert.equal(getPendingGates("M001", "S01").length, 0);
|
|
123
|
+
assert.equal(getGateResults("M001", "S01")[0].verdict, "pass");
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("closeQualityGatesFromEvidence omits stale pending gate after validation pass", () => {
|
|
127
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q4", scope: "slice" });
|
|
128
|
+
|
|
129
|
+
const result = closeQualityGatesFromEvidence("M001", {
|
|
130
|
+
artifactBasePath: tmpDir,
|
|
131
|
+
milestoneValidationPassed: true,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
assert.deepEqual(result.unresolved, []);
|
|
135
|
+
assert.deepEqual(result.repaired, [{ gateId: "Q4", sliceId: "S01", verdict: "omitted" }]);
|
|
136
|
+
assert.equal(getGateResults("M001", "S01")[0].verdict, "omitted");
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("closeQualityGatesFromEvidence leaves pending gate unresolved without evidence", () => {
|
|
140
|
+
insertGateRow({ milestoneId: "M001", sliceId: "S01", gateId: "Q3", scope: "slice" });
|
|
141
|
+
|
|
142
|
+
const result = closeQualityGatesFromEvidence("M001", { artifactBasePath: tmpDir });
|
|
143
|
+
|
|
144
|
+
assert.deepEqual(result.repaired, []);
|
|
145
|
+
assert.equal(result.unresolved.length, 1);
|
|
146
|
+
assert.equal(result.unresolved[0].gate_id, "Q3");
|
|
147
|
+
assert.equal(getPendingGates("M001", "S01").length, 1);
|
|
148
|
+
});
|
|
102
149
|
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Regression coverage for shared MCP tool-name parsing helpers.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
mcpToolMatchesBaseName,
|
|
9
|
+
parseMcpToolName,
|
|
10
|
+
stripMcpToolPrefix,
|
|
11
|
+
toMcpToolName,
|
|
12
|
+
toMcpWildcardToolName,
|
|
13
|
+
} from "../mcp-tool-name.ts";
|
|
14
|
+
|
|
15
|
+
test("parseMcpToolName parses exact and wildcard MCP tool names", () => {
|
|
16
|
+
assert.deepEqual(parseMcpToolName("mcp__gsd-workflow__ask_user_questions"), {
|
|
17
|
+
serverName: "gsd-workflow",
|
|
18
|
+
toolName: "ask_user_questions",
|
|
19
|
+
});
|
|
20
|
+
assert.deepEqual(parseMcpToolName("mcp__gsd-browser__*"), {
|
|
21
|
+
serverName: "gsd-browser",
|
|
22
|
+
toolName: "*",
|
|
23
|
+
});
|
|
24
|
+
assert.equal(parseMcpToolName("browser_navigate"), null);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("MCP tool-name helpers strip, match, and format names consistently", () => {
|
|
28
|
+
assert.equal(stripMcpToolPrefix("mcp__custom-workflow__gsd_exec"), "gsd_exec");
|
|
29
|
+
assert.equal(stripMcpToolPrefix("read"), "read");
|
|
30
|
+
assert.equal(mcpToolMatchesBaseName("mcp__custom-workflow__gsd_exec", "gsd_exec"), true);
|
|
31
|
+
assert.equal(mcpToolMatchesBaseName("mcp__custom-workflow__gsd_exec", "gsd_summary_save"), false);
|
|
32
|
+
assert.equal(toMcpToolName("custom-workflow", "gsd_exec"), "mcp__custom-workflow__gsd_exec");
|
|
33
|
+
assert.equal(toMcpWildcardToolName("custom-workflow"), "mcp__custom-workflow__*");
|
|
34
|
+
});
|
|
@@ -287,3 +287,61 @@ test("migration auto-check refreshes a stale open DB handle before comparing", a
|
|
|
287
287
|
cleanup(base);
|
|
288
288
|
}
|
|
289
289
|
});
|
|
290
|
+
|
|
291
|
+
test("rebuildMarkdownProjectionsFromDb realigns markdown when DB holds extra rows", async () => {
|
|
292
|
+
const base = makeBase();
|
|
293
|
+
try {
|
|
294
|
+
await writeGSDDirectory(projectFixture(), base); // markdown: M001 / S01 / T01
|
|
295
|
+
assert.equal(await ensureDbOpen(base), true);
|
|
296
|
+
insertMilestone({ id: "M001", title: "Legacy Milestone", status: "active" });
|
|
297
|
+
insertSlice({
|
|
298
|
+
id: "S01",
|
|
299
|
+
milestoneId: "M001",
|
|
300
|
+
title: "Legacy Slice",
|
|
301
|
+
status: "pending",
|
|
302
|
+
risk: "medium",
|
|
303
|
+
depends: [],
|
|
304
|
+
demo: "Legacy slice demo",
|
|
305
|
+
sequence: 1,
|
|
306
|
+
});
|
|
307
|
+
insertTask({
|
|
308
|
+
id: "T01",
|
|
309
|
+
sliceId: "S01",
|
|
310
|
+
milestoneId: "M001",
|
|
311
|
+
title: "Legacy Task",
|
|
312
|
+
status: "pending",
|
|
313
|
+
});
|
|
314
|
+
insertSlice({
|
|
315
|
+
id: "S02",
|
|
316
|
+
milestoneId: "M001",
|
|
317
|
+
title: "Added in DB",
|
|
318
|
+
status: "pending",
|
|
319
|
+
risk: "medium",
|
|
320
|
+
depends: [],
|
|
321
|
+
demo: "d",
|
|
322
|
+
sequence: 2,
|
|
323
|
+
});
|
|
324
|
+
insertTask({
|
|
325
|
+
id: "T02",
|
|
326
|
+
sliceId: "S02",
|
|
327
|
+
milestoneId: "M001",
|
|
328
|
+
title: "Added task",
|
|
329
|
+
status: "pending",
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const before = await checkMarkdownHierarchyAgainstDb(base);
|
|
333
|
+
assert.equal(before.recoveryCommand, "/gsd rebuild markdown");
|
|
334
|
+
|
|
335
|
+
const { rebuildMarkdownProjectionsFromDb } = await import("../commands-maintenance.ts");
|
|
336
|
+
const rebuild = await rebuildMarkdownProjectionsFromDb(base);
|
|
337
|
+
assert.ok(rebuild.rendered > 0, "expected markdown projections to render");
|
|
338
|
+
|
|
339
|
+
const after = await checkMarkdownHierarchyAgainstDb(base);
|
|
340
|
+
assert.equal(after.action, "none");
|
|
341
|
+
assert.equal(after.reason, "in-sync");
|
|
342
|
+
assert.deepEqual(after.markdown, { milestones: 1, slices: 2, tasks: 2 });
|
|
343
|
+
assert.deepEqual(after.beforeDb, { milestones: 1, slices: 2, tasks: 2 });
|
|
344
|
+
} finally {
|
|
345
|
+
cleanup(base);
|
|
346
|
+
}
|
|
347
|
+
});
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Tests for the shared milestone closeout proof surface.
|
|
3
|
+
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
closeDatabase,
|
|
12
|
+
insertAssessment,
|
|
13
|
+
insertMilestone,
|
|
14
|
+
insertSlice,
|
|
15
|
+
openDatabase,
|
|
16
|
+
} from "../gsd-db.js";
|
|
17
|
+
import { proveMilestoneCloseout } from "../milestone-closeout-proof.js";
|
|
18
|
+
|
|
19
|
+
const tmpDirs: string[] = [];
|
|
20
|
+
|
|
21
|
+
function makeBase(): string {
|
|
22
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-closeout-proof-"));
|
|
23
|
+
tmpDirs.push(base);
|
|
24
|
+
mkdirSync(join(base, ".gsd", "milestones", "M001"), { recursive: true });
|
|
25
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
26
|
+
openDatabase(join(base, ".gsd", "gsd.db"));
|
|
27
|
+
return base;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function insertValidationPass(): void {
|
|
31
|
+
insertAssessment({
|
|
32
|
+
path: "milestones/M001/M001-VALIDATION.md",
|
|
33
|
+
milestoneId: "M001",
|
|
34
|
+
status: "pass",
|
|
35
|
+
scope: "milestone-validation",
|
|
36
|
+
fullContent: "verdict: pass",
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function writeSummary(base: string, status = "complete"): void {
|
|
41
|
+
writeFileSync(
|
|
42
|
+
join(base, ".gsd", "milestones", "M001", "M001-SUMMARY.md"),
|
|
43
|
+
`---\nstatus: ${status}\n---\n\n# Summary\n`,
|
|
44
|
+
"utf-8",
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
test.after(() => {
|
|
49
|
+
try { closeDatabase(); } catch { /* noop */ }
|
|
50
|
+
for (const dir of tmpDirs) {
|
|
51
|
+
rmSync(dir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("proveMilestoneCloseout accepts closed DB state plus summary artifact", () => {
|
|
56
|
+
const base = makeBase();
|
|
57
|
+
insertMilestone({ id: "M001", title: "Done", status: "complete" });
|
|
58
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete" });
|
|
59
|
+
insertValidationPass();
|
|
60
|
+
writeSummary(base);
|
|
61
|
+
|
|
62
|
+
const result = proveMilestoneCloseout("M001", {
|
|
63
|
+
summaryArtifactBasePath: base,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
assert.deepEqual(result, { ok: true });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("proveMilestoneCloseout can prove readiness before DB milestone is closed", () => {
|
|
70
|
+
const base = makeBase();
|
|
71
|
+
insertMilestone({ id: "M001", title: "Ready", status: "active" });
|
|
72
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete" });
|
|
73
|
+
insertValidationPass();
|
|
74
|
+
writeSummary(base);
|
|
75
|
+
|
|
76
|
+
const result = proveMilestoneCloseout("M001", {
|
|
77
|
+
allowOpenMilestone: true,
|
|
78
|
+
summaryArtifactBasePath: base,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
assert.deepEqual(result, { ok: true });
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("proveMilestoneCloseout rejects explicit failure summaries", () => {
|
|
85
|
+
const base = makeBase();
|
|
86
|
+
insertMilestone({ id: "M001", title: "Done", status: "complete" });
|
|
87
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Done Slice", status: "complete" });
|
|
88
|
+
insertValidationPass();
|
|
89
|
+
writeSummary(base, "failed");
|
|
90
|
+
|
|
91
|
+
const result = proveMilestoneCloseout("M001", {
|
|
92
|
+
summaryArtifactBasePath: base,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
assert.equal(result.ok, false);
|
|
96
|
+
if (!result.ok) {
|
|
97
|
+
assert.equal(result.reason, "summary-artifact-failed");
|
|
98
|
+
}
|
|
99
|
+
});
|