@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
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
import {
|
|
5
5
|
resolveManifest,
|
|
6
6
|
type ArtifactKey,
|
|
7
|
+
type ComputedArtifactId,
|
|
7
8
|
type ContextModePolicy,
|
|
8
9
|
type ToolsPolicy,
|
|
10
|
+
type UnitContextManifest,
|
|
9
11
|
} from "./unit-context-manifest.js";
|
|
10
12
|
import { getRequiredWorkflowToolsForAutoUnit } from "./workflow-mcp.js";
|
|
11
13
|
import { getUnitToolSurfaceContract } from "./unit-tool-contracts.js";
|
|
@@ -21,6 +23,7 @@ export interface UnitToolContract {
|
|
|
21
23
|
requiredWorkflowTools: readonly string[];
|
|
22
24
|
forbiddenWorkflowTools: readonly { name: string; reason: string }[];
|
|
23
25
|
promptObligations: readonly string[];
|
|
26
|
+
promptContext: UnitPromptContextContract;
|
|
24
27
|
validationRules: readonly string[];
|
|
25
28
|
closeoutTools: readonly string[];
|
|
26
29
|
sourceObservations: UnitSourceObservationContract;
|
|
@@ -31,6 +34,22 @@ export interface UnitToolContract {
|
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
|
|
37
|
+
export interface UnitPromptContextContract {
|
|
38
|
+
unitType: string;
|
|
39
|
+
contextMode: ContextModePolicy;
|
|
40
|
+
toolsPolicy: ToolsPolicy;
|
|
41
|
+
obligations: readonly string[];
|
|
42
|
+
sourceObservations: UnitSourceObservationContract;
|
|
43
|
+
artifacts: {
|
|
44
|
+
inline: readonly ArtifactKey[];
|
|
45
|
+
excerpt: readonly ArtifactKey[];
|
|
46
|
+
onDemand: readonly ArtifactKey[];
|
|
47
|
+
computed: readonly ComputedArtifactId[];
|
|
48
|
+
prepend: readonly ComputedArtifactId[];
|
|
49
|
+
};
|
|
50
|
+
maxSystemPromptChars: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
34
53
|
export type UnitSourceObservationContract =
|
|
35
54
|
| { mode: "none" }
|
|
36
55
|
| {
|
|
@@ -45,6 +64,22 @@ export type ToolContractResult =
|
|
|
45
64
|
| { ok: true; contract: UnitToolContract }
|
|
46
65
|
| { ok: false; reason: "unknown-unit-type" | "missing-closeout-tool"; detail: string };
|
|
47
66
|
|
|
67
|
+
export type UnitContextContractResult =
|
|
68
|
+
| { ok: true; contract: UnitPromptContextContract }
|
|
69
|
+
| { ok: false; reason: "unknown-unit-type"; detail: string };
|
|
70
|
+
|
|
71
|
+
export function compileUnitContextContract(unitType: string): UnitContextContractResult {
|
|
72
|
+
const manifest = resolveManifest(unitType);
|
|
73
|
+
if (!manifest) {
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
reason: "unknown-unit-type",
|
|
77
|
+
detail: `No Unit manifest is registered for ${unitType}`,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return { ok: true, contract: buildPromptContextContract(unitType, manifest) };
|
|
81
|
+
}
|
|
82
|
+
|
|
48
83
|
export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
49
84
|
const manifest = resolveManifest(unitType);
|
|
50
85
|
const surfaceContract = getUnitToolSurfaceContract(unitType);
|
|
@@ -71,6 +106,8 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
|
71
106
|
};
|
|
72
107
|
}
|
|
73
108
|
|
|
109
|
+
const promptContext = buildPromptContextContract(unitType, manifest);
|
|
110
|
+
|
|
74
111
|
return {
|
|
75
112
|
ok: true,
|
|
76
113
|
contract: {
|
|
@@ -79,10 +116,8 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
|
79
116
|
toolsPolicy: manifest.tools,
|
|
80
117
|
requiredWorkflowTools,
|
|
81
118
|
forbiddenWorkflowTools,
|
|
82
|
-
promptObligations:
|
|
83
|
-
|
|
84
|
-
`tools-policy:${manifest.tools.mode}`,
|
|
85
|
-
],
|
|
119
|
+
promptObligations: promptContext.obligations,
|
|
120
|
+
promptContext,
|
|
86
121
|
validationRules: [
|
|
87
122
|
"unit-manifest-present",
|
|
88
123
|
"workflow-tool-surface-present",
|
|
@@ -90,16 +125,59 @@ export function compileUnitToolContract(unitType: string): ToolContractResult {
|
|
|
90
125
|
...(unitType === "execute-task" ? ["source-observation-contract-present"] : []),
|
|
91
126
|
],
|
|
92
127
|
closeoutTools,
|
|
93
|
-
sourceObservations:
|
|
128
|
+
sourceObservations: promptContext.sourceObservations,
|
|
94
129
|
artifacts: {
|
|
95
|
-
inline:
|
|
96
|
-
excerpt:
|
|
97
|
-
onDemand:
|
|
130
|
+
inline: promptContext.artifacts.inline,
|
|
131
|
+
excerpt: promptContext.artifacts.excerpt,
|
|
132
|
+
onDemand: promptContext.artifacts.onDemand,
|
|
98
133
|
},
|
|
99
134
|
},
|
|
100
135
|
};
|
|
101
136
|
}
|
|
102
137
|
|
|
138
|
+
function buildPromptContextContract(
|
|
139
|
+
unitType: string,
|
|
140
|
+
manifest: UnitContextManifest,
|
|
141
|
+
): UnitPromptContextContract {
|
|
142
|
+
const sourceObservations = sourceObservationContractForUnit(unitType);
|
|
143
|
+
return {
|
|
144
|
+
unitType,
|
|
145
|
+
contextMode: manifest.contextMode,
|
|
146
|
+
toolsPolicy: manifest.tools,
|
|
147
|
+
obligations: promptContextObligations(manifest, sourceObservations),
|
|
148
|
+
sourceObservations,
|
|
149
|
+
artifacts: {
|
|
150
|
+
inline: manifest.artifacts.inline,
|
|
151
|
+
excerpt: manifest.artifacts.excerpt,
|
|
152
|
+
onDemand: manifest.artifacts.onDemand,
|
|
153
|
+
computed: manifest.artifacts.computed ?? [],
|
|
154
|
+
prepend: manifest.prepend ?? [],
|
|
155
|
+
},
|
|
156
|
+
maxSystemPromptChars: manifest.maxSystemPromptChars,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function promptContextObligations(
|
|
161
|
+
manifest: UnitContextManifest,
|
|
162
|
+
sourceObservations: UnitSourceObservationContract,
|
|
163
|
+
): string[] {
|
|
164
|
+
const obligations = [
|
|
165
|
+
`context-mode:${manifest.contextMode}`,
|
|
166
|
+
`tools-policy:${manifest.tools.mode}`,
|
|
167
|
+
artifactObligation("context-inline", manifest.artifacts.inline),
|
|
168
|
+
artifactObligation("context-excerpt", manifest.artifacts.excerpt),
|
|
169
|
+
artifactObligation("context-on-demand", manifest.artifacts.onDemand),
|
|
170
|
+
];
|
|
171
|
+
if (sourceObservations.mode !== "none") {
|
|
172
|
+
obligations.push(`source-observations:${sourceObservations.mode}`);
|
|
173
|
+
}
|
|
174
|
+
return obligations;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function artifactObligation(label: string, artifacts: readonly ArtifactKey[]): string {
|
|
178
|
+
return `${label}:${artifacts.length > 0 ? artifacts.join(",") : "none"}`;
|
|
179
|
+
}
|
|
180
|
+
|
|
103
181
|
function sourceObservationContractForUnit(unitType: string): UnitSourceObservationContract {
|
|
104
182
|
if (unitType !== "execute-task") return { mode: "none" };
|
|
105
183
|
return {
|
|
@@ -7,7 +7,10 @@ import {
|
|
|
7
7
|
RUN_UAT_TOOL_PRESENTATION_PLAN_ID,
|
|
8
8
|
RUN_UAT_WORKFLOW_TOOL_NAMES,
|
|
9
9
|
} from "./unit-tool-contracts.js";
|
|
10
|
+
import { parseMcpToolName, toMcpToolName } from "./mcp-tool-name.js";
|
|
11
|
+
import { createToolSurfaceSnapshot, type ToolSurfaceSnapshot } from "./tool-surface-snapshot.js";
|
|
10
12
|
import { uatTypeIncludesBrowser } from "./uat-policy.js";
|
|
13
|
+
import { canonicalWorkflowSurfaceToolName } from "./workflow-tool-surface.js";
|
|
11
14
|
|
|
12
15
|
export {
|
|
13
16
|
RUN_UAT_BROWSER_TOOL_NAMES,
|
|
@@ -33,6 +36,7 @@ export interface ToolPresentationPlan {
|
|
|
33
36
|
blockedToolNames: Array<{ name: string; reason: string }>;
|
|
34
37
|
aliases: Array<{ requested: string; canonical: string }>;
|
|
35
38
|
diagnostics: string[];
|
|
39
|
+
toolSurface: ToolSurfaceSnapshot;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
export interface RunUatResultPresentation {
|
|
@@ -62,44 +66,14 @@ export const RUN_UAT_CLAUDE_NATIVE_TOOL_NAMES = [
|
|
|
62
66
|
"Grep",
|
|
63
67
|
] as const;
|
|
64
68
|
|
|
65
|
-
const WORKFLOW_ALIAS_TO_CANONICAL: Record<string, string> = {
|
|
66
|
-
gsd_save_decision: "gsd_decision_save",
|
|
67
|
-
gsd_update_requirement: "gsd_requirement_update",
|
|
68
|
-
gsd_save_requirement: "gsd_requirement_save",
|
|
69
|
-
gsd_save_summary: "gsd_summary_save",
|
|
70
|
-
gsd_generate_milestone_id: "gsd_milestone_generate_id",
|
|
71
|
-
gsd_milestone_plan: "gsd_plan_milestone",
|
|
72
|
-
gsd_slice_plan: "gsd_plan_slice",
|
|
73
|
-
gsd_task_plan: "gsd_plan_task",
|
|
74
|
-
gsd_slice_replan: "gsd_replan_slice",
|
|
75
|
-
gsd_complete_slice: "gsd_slice_complete",
|
|
76
|
-
gsd_milestone_complete: "gsd_complete_milestone",
|
|
77
|
-
gsd_milestone_validate: "gsd_validate_milestone",
|
|
78
|
-
gsd_roadmap_reassess: "gsd_reassess_roadmap",
|
|
79
|
-
gsd_complete_task: "gsd_task_complete",
|
|
80
|
-
gsd_reopen_task: "gsd_task_reopen",
|
|
81
|
-
gsd_reopen_slice: "gsd_slice_reopen",
|
|
82
|
-
gsd_reopen_milestone: "gsd_milestone_reopen",
|
|
83
|
-
};
|
|
84
|
-
|
|
85
69
|
export function canonicalWorkflowToolName(toolName: string): string {
|
|
86
|
-
|
|
87
|
-
const baseName = mcp?.tool ?? toolName;
|
|
88
|
-
return WORKFLOW_ALIAS_TO_CANONICAL[baseName] ?? baseName;
|
|
70
|
+
return canonicalWorkflowSurfaceToolName(toolName);
|
|
89
71
|
}
|
|
90
72
|
|
|
91
|
-
export
|
|
92
|
-
if (!toolName.startsWith("mcp__")) return null;
|
|
93
|
-
const toolSeparator = toolName.indexOf("__", "mcp__".length);
|
|
94
|
-
if (toolSeparator < 0) return null;
|
|
95
|
-
return {
|
|
96
|
-
server: toolName.slice("mcp__".length, toolSeparator),
|
|
97
|
-
tool: toolName.slice(toolSeparator + 2),
|
|
98
|
-
};
|
|
99
|
-
}
|
|
73
|
+
export { parseMcpToolName } from "./mcp-tool-name.js";
|
|
100
74
|
|
|
101
75
|
export function toWorkflowMcpToolName(serverName: string, toolName: string): string {
|
|
102
|
-
return
|
|
76
|
+
return toMcpToolName(serverName, canonicalWorkflowToolName(toolName));
|
|
103
77
|
}
|
|
104
78
|
|
|
105
79
|
function dedupe(values: readonly string[]): string[] {
|
|
@@ -212,6 +186,14 @@ export function resolveToolPresentationPlan(options: {
|
|
|
212
186
|
: name
|
|
213
187
|
)
|
|
214
188
|
: allowedToolNames;
|
|
189
|
+
const toolSurface = createToolSurfaceSnapshot({
|
|
190
|
+
source: "presentation-plan",
|
|
191
|
+
phase: options.phase,
|
|
192
|
+
modelFacingToolNames: options.availableToolNames ?? requested,
|
|
193
|
+
registeredToolNames: options.availableToolNames ?? requested,
|
|
194
|
+
scopedToolNames: allowedToolNames,
|
|
195
|
+
presentedToolNames,
|
|
196
|
+
});
|
|
215
197
|
|
|
216
198
|
if (options.phase === "run-uat") {
|
|
217
199
|
for (const forbidden of RUN_UAT_FORBIDDEN_TOOL_NAMES) {
|
|
@@ -228,5 +210,6 @@ export function resolveToolPresentationPlan(options: {
|
|
|
228
210
|
blockedToolNames,
|
|
229
211
|
aliases,
|
|
230
212
|
diagnostics: [],
|
|
213
|
+
toolSurface,
|
|
231
214
|
};
|
|
232
215
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Typed snapshots for model-facing, registered, scoped, and presented tool surfaces.
|
|
3
|
+
|
|
4
|
+
export type ToolSurfaceSnapshotSource =
|
|
5
|
+
| "runtime-scope"
|
|
6
|
+
| "dispatch-scope"
|
|
7
|
+
| "provider-adjustment"
|
|
8
|
+
| "presentation-plan";
|
|
9
|
+
|
|
10
|
+
export interface ToolSurfaceSnapshot {
|
|
11
|
+
source: ToolSurfaceSnapshotSource;
|
|
12
|
+
unitType?: string;
|
|
13
|
+
phase?: string;
|
|
14
|
+
modelFacingToolNames: string[];
|
|
15
|
+
registeredToolNames: string[];
|
|
16
|
+
scopedToolNames: string[];
|
|
17
|
+
presentedToolNames: string[];
|
|
18
|
+
capturedAt: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface ToolSurfaceSnapshotInput {
|
|
22
|
+
source: ToolSurfaceSnapshotSource;
|
|
23
|
+
unitType?: string;
|
|
24
|
+
phase?: string;
|
|
25
|
+
modelFacingToolNames?: readonly string[];
|
|
26
|
+
registeredToolNames?: readonly string[];
|
|
27
|
+
scopedToolNames?: readonly string[];
|
|
28
|
+
presentedToolNames?: readonly string[];
|
|
29
|
+
capturedAt?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function dedupeToolNames(toolNames: readonly string[] | undefined): string[] {
|
|
33
|
+
return [...new Set(toolNames ?? [])];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function createToolSurfaceSnapshot(input: ToolSurfaceSnapshotInput): ToolSurfaceSnapshot {
|
|
37
|
+
return {
|
|
38
|
+
source: input.source,
|
|
39
|
+
unitType: input.unitType,
|
|
40
|
+
phase: input.phase,
|
|
41
|
+
modelFacingToolNames: dedupeToolNames(input.modelFacingToolNames),
|
|
42
|
+
registeredToolNames: dedupeToolNames(input.registeredToolNames),
|
|
43
|
+
scopedToolNames: dedupeToolNames(input.scopedToolNames),
|
|
44
|
+
presentedToolNames: dedupeToolNames(input.presentedToolNames),
|
|
45
|
+
capturedAt: input.capturedAt ?? Date.now(),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -1,25 +1,8 @@
|
|
|
1
1
|
// Project/App: gsd-pi
|
|
2
2
|
// File Purpose: Plans milestone roadmap state through DB-backed workflow tools.
|
|
3
3
|
|
|
4
|
-
import { clearParseCache } from "../files.js";
|
|
5
|
-
import { isClosedStatus } from "../status-guards.js";
|
|
6
4
|
import { isNonEmptyString, validateStringArray, validateTitle } from "../validation.js";
|
|
7
|
-
import {
|
|
8
|
-
transaction,
|
|
9
|
-
getMilestone,
|
|
10
|
-
getMilestoneSlices,
|
|
11
|
-
getSlice,
|
|
12
|
-
insertMilestone,
|
|
13
|
-
insertSlice,
|
|
14
|
-
upsertMilestonePlanning,
|
|
15
|
-
upsertSlicePlanning,
|
|
16
|
-
} from "../gsd-db.js";
|
|
17
|
-
import { invalidateStateCache } from "../state.js";
|
|
18
|
-
import { renderRoadmapFromDb } from "../markdown-renderer.js";
|
|
19
|
-
import { renderAllProjections } from "../workflow-projections.js";
|
|
20
|
-
import { writeManifest } from "../workflow-manifest.js";
|
|
21
|
-
import { appendEvent } from "../workflow-events.js";
|
|
22
|
-
import { logWarning } from "../workflow-logger.js";
|
|
5
|
+
import { persistMilestonePlan } from "../milestone-planning-persistence.js";
|
|
23
6
|
|
|
24
7
|
export interface PlanMilestoneSliceInput {
|
|
25
8
|
sliceId: string;
|
|
@@ -115,11 +98,21 @@ function validateProofStrategy(value: unknown): Array<{ riskOrUnknown: string; r
|
|
|
115
98
|
});
|
|
116
99
|
}
|
|
117
100
|
|
|
101
|
+
const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
102
|
+
|
|
118
103
|
function validateSlices(value: unknown): PlanMilestoneSliceInput[] {
|
|
119
104
|
if (!Array.isArray(value) || value.length === 0) {
|
|
120
105
|
throw new Error("slices must be a non-empty array");
|
|
121
106
|
}
|
|
122
107
|
|
|
108
|
+
// Pre-collect all slice IDs so depends cross-validation can reference the full set.
|
|
109
|
+
const allSliceIds = new Set<string>(
|
|
110
|
+
(value as unknown[])
|
|
111
|
+
.filter((e): e is Record<string, unknown> => !!e && typeof e === "object")
|
|
112
|
+
.map(e => e.sliceId)
|
|
113
|
+
.filter((id): id is string => isNonEmptyString(id)),
|
|
114
|
+
);
|
|
115
|
+
|
|
123
116
|
const seen = new Set<string>();
|
|
124
117
|
return value.map((entry, index) => {
|
|
125
118
|
if (!entry || typeof entry !== "object") {
|
|
@@ -154,8 +147,13 @@ function validateSlices(value: unknown): PlanMilestoneSliceInput[] {
|
|
|
154
147
|
const titleIssue = validateTitle(title);
|
|
155
148
|
if (titleIssue) throw new Error(`slices[${index}].title is invalid: ${titleIssue}`);
|
|
156
149
|
if (!isNonEmptyString(risk)) throw new Error(`slices[${index}].risk must be a non-empty string`);
|
|
157
|
-
if (!Array.isArray(depends) || depends.some((item) => !isNonEmptyString(item))) {
|
|
158
|
-
throw new Error(`slices[${index}].depends must be an array of
|
|
150
|
+
if (!Array.isArray(depends) || depends.some((item) => !isNonEmptyString(item) || !SLICE_ID_RE.test(item as string))) {
|
|
151
|
+
throw new Error(`slices[${index}].depends must be an array of valid slice IDs (e.g. "S01")`);
|
|
152
|
+
}
|
|
153
|
+
for (const dep of depends as string[]) {
|
|
154
|
+
if (!allSliceIds.has(dep)) {
|
|
155
|
+
throw new Error(`slices[${index}].depends references unknown slice "${dep}" — check that it is defined in the same milestone`);
|
|
156
|
+
}
|
|
159
157
|
}
|
|
160
158
|
if (!isNonEmptyString(demo)) throw new Error(`slices[${index}].demo must be a non-empty string`);
|
|
161
159
|
if (!isNonEmptyString(goal)) throw new Error(`slices[${index}].goal must be a non-empty string`);
|
|
@@ -227,144 +225,5 @@ export async function handlePlanMilestone(
|
|
|
227
225
|
return { error: `validation failed: ${(err as Error).message}` };
|
|
228
226
|
}
|
|
229
227
|
|
|
230
|
-
|
|
231
|
-
// Guards must be inside the transaction so the state they check cannot
|
|
232
|
-
// change between the read and the write (#2723).
|
|
233
|
-
let guardError: string | null = null;
|
|
234
|
-
|
|
235
|
-
try {
|
|
236
|
-
transaction(() => {
|
|
237
|
-
const existingMilestone = getMilestone(params.milestoneId);
|
|
238
|
-
if (existingMilestone && isClosedStatus(existingMilestone.status)) {
|
|
239
|
-
guardError = `cannot re-plan milestone ${params.milestoneId}: it is already complete`;
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Guard: refuse to re-plan a milestone that would drop completed slices (#2960).
|
|
244
|
-
// Allow re-planning when all completed slices are still present in the
|
|
245
|
-
// incoming plan — their status is preserved below (#2558). Block only when
|
|
246
|
-
// the new plan omits a completed slice, which could shadow completed work.
|
|
247
|
-
const existingSlices = getMilestoneSlices(params.milestoneId);
|
|
248
|
-
const completedSlices = existingSlices.filter(s => isClosedStatus(s.status));
|
|
249
|
-
if (completedSlices.length > 0) {
|
|
250
|
-
const incomingSliceIds = new Set(params.slices.map(s => s.sliceId));
|
|
251
|
-
const droppedCompleted = completedSlices.filter(s => !incomingSliceIds.has(s.id));
|
|
252
|
-
if (droppedCompleted.length > 0) {
|
|
253
|
-
guardError = `cannot re-plan milestone ${params.milestoneId}: ${droppedCompleted.length} completed slice(s) would be dropped (${droppedCompleted.map(s => s.id).join(", ")}). Use gsd_reassess_roadmap to modify the roadmap.`;
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Validate depends_on: all dependencies must exist and be complete
|
|
259
|
-
if (params.dependsOn && params.dependsOn.length > 0) {
|
|
260
|
-
for (const depId of params.dependsOn) {
|
|
261
|
-
const dep = getMilestone(depId);
|
|
262
|
-
if (!dep) {
|
|
263
|
-
guardError = `depends_on references unknown milestone: ${depId}`;
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
if (!isClosedStatus(dep.status)) {
|
|
267
|
-
guardError = `depends_on milestone ${depId} is not yet complete (status: ${dep.status})`;
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
insertMilestone({
|
|
274
|
-
id: params.milestoneId,
|
|
275
|
-
title: params.title,
|
|
276
|
-
status: params.status ?? "active",
|
|
277
|
-
depends_on: params.dependsOn ?? [],
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
upsertMilestonePlanning(params.milestoneId, {
|
|
281
|
-
title: params.title,
|
|
282
|
-
status: params.status ?? "active",
|
|
283
|
-
depends_on: params.dependsOn ?? [],
|
|
284
|
-
vision: params.vision,
|
|
285
|
-
successCriteria: params.successCriteria,
|
|
286
|
-
keyRisks: params.keyRisks,
|
|
287
|
-
proofStrategy: params.proofStrategy,
|
|
288
|
-
verificationContract: params.verificationContract,
|
|
289
|
-
verificationIntegration: params.verificationIntegration,
|
|
290
|
-
verificationOperational: params.verificationOperational,
|
|
291
|
-
verificationUat: params.verificationUat,
|
|
292
|
-
definitionOfDone: params.definitionOfDone,
|
|
293
|
-
requirementCoverage: params.requirementCoverage,
|
|
294
|
-
boundaryMapMarkdown: params.boundaryMapMarkdown,
|
|
295
|
-
});
|
|
296
|
-
|
|
297
|
-
for (let i = 0; i < params.slices.length; i++) {
|
|
298
|
-
const slice = params.slices[i]!;
|
|
299
|
-
// Preserve completed/done status on re-plan (#2558).
|
|
300
|
-
// Without this, a re-plan after milestone transition would reset
|
|
301
|
-
// already-completed slices back to "pending".
|
|
302
|
-
const existing = getSlice(params.milestoneId, slice.sliceId);
|
|
303
|
-
const status = existing && (existing.status === "complete" || existing.status === "done")
|
|
304
|
-
? existing.status
|
|
305
|
-
: "pending";
|
|
306
|
-
insertSlice({
|
|
307
|
-
id: slice.sliceId,
|
|
308
|
-
milestoneId: params.milestoneId,
|
|
309
|
-
title: slice.title,
|
|
310
|
-
status,
|
|
311
|
-
risk: slice.risk,
|
|
312
|
-
depends: slice.depends,
|
|
313
|
-
demo: slice.demo,
|
|
314
|
-
sequence: i + 1, // Preserve agent-ordered sequence (#3356)
|
|
315
|
-
// ADR-011: pass undefined through so ON CONFLICT preserves existing values
|
|
316
|
-
// when the caller omitted the fields on a re-plan.
|
|
317
|
-
isSketch: slice.isSketch,
|
|
318
|
-
sketchScope: slice.sketchScope,
|
|
319
|
-
});
|
|
320
|
-
upsertSlicePlanning(params.milestoneId, slice.sliceId, {
|
|
321
|
-
goal: slice.goal,
|
|
322
|
-
successCriteria: slice.successCriteria,
|
|
323
|
-
proofLevel: slice.proofLevel,
|
|
324
|
-
integrationClosure: slice.integrationClosure,
|
|
325
|
-
observabilityImpact: slice.observabilityImpact,
|
|
326
|
-
});
|
|
327
|
-
}
|
|
328
|
-
});
|
|
329
|
-
} catch (err) {
|
|
330
|
-
return { error: `db write failed: ${(err as Error).message}` };
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
if (guardError) {
|
|
334
|
-
return { error: guardError };
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
let roadmapPath: string;
|
|
338
|
-
try {
|
|
339
|
-
const renderResult = await renderRoadmapFromDb(basePath, params.milestoneId);
|
|
340
|
-
roadmapPath = renderResult.roadmapPath;
|
|
341
|
-
} catch (renderErr) {
|
|
342
|
-
logWarning("tool", `plan_milestone — render failed (DB rows preserved for debugging): ${(renderErr as Error).message}`);
|
|
343
|
-
invalidateStateCache();
|
|
344
|
-
return { error: `render failed: ${(renderErr as Error).message}` };
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
invalidateStateCache();
|
|
348
|
-
clearParseCache();
|
|
349
|
-
|
|
350
|
-
// ── Post-mutation hook: projections, manifest, event log ───────────────
|
|
351
|
-
try {
|
|
352
|
-
await renderAllProjections(basePath, params.milestoneId);
|
|
353
|
-
writeManifest(basePath);
|
|
354
|
-
appendEvent(basePath, {
|
|
355
|
-
cmd: "plan-milestone",
|
|
356
|
-
params: { milestoneId: params.milestoneId },
|
|
357
|
-
ts: new Date().toISOString(),
|
|
358
|
-
actor: "agent",
|
|
359
|
-
actor_name: params.actorName,
|
|
360
|
-
trigger_reason: params.triggerReason,
|
|
361
|
-
});
|
|
362
|
-
} catch (hookErr) {
|
|
363
|
-
logWarning("tool", `plan-milestone post-mutation hook warning: ${(hookErr as Error).message}`);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
return {
|
|
367
|
-
milestoneId: params.milestoneId,
|
|
368
|
-
roadmapPath,
|
|
369
|
-
};
|
|
228
|
+
return persistMilestonePlan(params, basePath);
|
|
370
229
|
}
|
|
@@ -75,12 +75,19 @@ function validateParams(params: ReassessRoadmapParams): ReassessRoadmapParams {
|
|
|
75
75
|
throw new Error("sliceChanges.removed must be an array");
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
const SLICE_ID_RE = /^[A-Za-z0-9][A-Za-z0-9-]*$/;
|
|
79
|
+
|
|
78
80
|
// Validate each modified slice
|
|
79
81
|
for (let i = 0; i < params.sliceChanges.modified.length; i++) {
|
|
80
82
|
const s = params.sliceChanges.modified[i];
|
|
81
83
|
if (!s || typeof s !== "object") throw new Error(`sliceChanges.modified[${i}] must be an object`);
|
|
82
84
|
if (!isNonEmptyString(s.sliceId)) throw new Error(`sliceChanges.modified[${i}].sliceId is required`);
|
|
83
85
|
if (!isNonEmptyString(s.title)) throw new Error(`sliceChanges.modified[${i}].title is required`);
|
|
86
|
+
if (s.depends !== undefined) {
|
|
87
|
+
if (!Array.isArray(s.depends) || s.depends.some((item: unknown) => !isNonEmptyString(item) || !SLICE_ID_RE.test(item as string))) {
|
|
88
|
+
throw new Error(`sliceChanges.modified[${i}].depends must be an array of valid slice IDs (e.g. "S01")`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
84
91
|
}
|
|
85
92
|
|
|
86
93
|
// Validate each added slice
|
|
@@ -89,6 +96,11 @@ function validateParams(params: ReassessRoadmapParams): ReassessRoadmapParams {
|
|
|
89
96
|
if (!s || typeof s !== "object") throw new Error(`sliceChanges.added[${i}] must be an object`);
|
|
90
97
|
if (!isNonEmptyString(s.sliceId)) throw new Error(`sliceChanges.added[${i}].sliceId is required`);
|
|
91
98
|
if (!isNonEmptyString(s.title)) throw new Error(`sliceChanges.added[${i}].title is required`);
|
|
99
|
+
if (s.depends !== undefined) {
|
|
100
|
+
if (!Array.isArray(s.depends) || s.depends.some((item: unknown) => !isNonEmptyString(item) || !SLICE_ID_RE.test(item as string))) {
|
|
101
|
+
throw new Error(`sliceChanges.added[${i}].depends must be an array of valid slice IDs (e.g. "S01")`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
92
104
|
}
|
|
93
105
|
|
|
94
106
|
return params;
|
|
@@ -166,6 +178,37 @@ export async function handleReassessRoadmap(
|
|
|
166
178
|
}
|
|
167
179
|
}
|
|
168
180
|
|
|
181
|
+
// Cross-milestone depends validation — effective slice ID set after this reassessment
|
|
182
|
+
const removedIds = new Set<string>(params.sliceChanges.removed);
|
|
183
|
+
const effectiveSliceIds = new Set<string>(
|
|
184
|
+
existingSlices.map(s => s.id).filter(id => !removedIds.has(id)),
|
|
185
|
+
);
|
|
186
|
+
for (const added of params.sliceChanges.added) {
|
|
187
|
+
effectiveSliceIds.add(added.sliceId);
|
|
188
|
+
}
|
|
189
|
+
for (let i = 0; i < params.sliceChanges.modified.length; i++) {
|
|
190
|
+
const mod = params.sliceChanges.modified[i]!;
|
|
191
|
+
if (mod.depends !== undefined) {
|
|
192
|
+
for (const dep of mod.depends) {
|
|
193
|
+
if (!effectiveSliceIds.has(dep)) {
|
|
194
|
+
guardError = `sliceChanges.modified[${i}].depends references unknown slice "${dep}" — check that it is defined in this milestone`;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
for (let i = 0; i < params.sliceChanges.added.length; i++) {
|
|
201
|
+
const added = params.sliceChanges.added[i]!;
|
|
202
|
+
if (added.depends !== undefined) {
|
|
203
|
+
for (const dep of added.depends) {
|
|
204
|
+
if (!effectiveSliceIds.has(dep)) {
|
|
205
|
+
guardError = `sliceChanges.added[${i}].depends references unknown slice "${dep}" — check that it is defined in this milestone`;
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
169
212
|
// Record assessment
|
|
170
213
|
insertAssessment({
|
|
171
214
|
path: assessmentRelPath,
|