@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.b1abb545
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-web-branch.d.ts +2 -0
- package/dist/cli-web-branch.js +9 -2
- package/dist/help-text.js +5 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +78 -23
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +84 -228
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +224 -0
- package/dist/resources/extensions/github-sync/templates.js +3 -3
- package/dist/resources/extensions/gsd/artifact-projection.js +14 -0
- package/dist/resources/extensions/gsd/auto/loop.js +74 -56
- package/dist/resources/extensions/gsd/auto/orchestrator.js +109 -11
- package/dist/resources/extensions/gsd/auto/phases.js +28 -3
- package/dist/resources/extensions/gsd/auto/run-unit.js +2 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dashboard.js +16 -4
- package/dist/resources/extensions/gsd/auto-dispatch.js +6 -5
- package/dist/resources/extensions/gsd/auto-model-selection.js +8 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +81 -8
- package/dist/resources/extensions/gsd/auto-recovery.js +48 -49
- package/dist/resources/extensions/gsd/auto-runtime-state.js +14 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -23
- package/dist/resources/extensions/gsd/auto-timers.js +16 -2
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +32 -0
- package/dist/resources/extensions/gsd/auto-unit-tool-scope.js +4 -29
- package/dist/resources/extensions/gsd/auto-verification.js +7 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +21 -19
- package/dist/resources/extensions/gsd/auto.js +11 -7
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +11 -37
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +100 -138
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +63 -4
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +3 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +20 -0
- package/dist/resources/extensions/gsd/commands-inspect.js +4 -8
- package/dist/resources/extensions/gsd/commands-maintenance.js +61 -41
- package/dist/resources/extensions/gsd/commands-ship.js +2 -2
- package/dist/resources/extensions/gsd/commands-verdict.js +12 -2
- package/dist/resources/extensions/gsd/db-workspace.js +103 -0
- package/dist/resources/extensions/gsd/delegation-policy.js +2 -10
- package/dist/resources/extensions/gsd/discussion-handoff.js +218 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/dist/resources/extensions/gsd/doctor.js +16 -9
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/git-conflict-state.js +16 -1
- package/dist/resources/extensions/gsd/gsd-db.js +12 -0
- package/dist/resources/extensions/gsd/guided-flow.js +34 -468
- package/dist/resources/extensions/gsd/guided-unit-completion.js +225 -0
- package/dist/resources/extensions/gsd/markdown-renderer.js +2 -1
- package/dist/resources/extensions/gsd/mcp-filter.js +2 -1
- package/dist/resources/extensions/gsd/mcp-tool-name.js +26 -0
- package/dist/resources/extensions/gsd/md-importer.js +4 -3
- package/dist/resources/extensions/gsd/migrate/safety.js +2 -2
- package/dist/resources/extensions/gsd/migration-auto-check.js +3 -2
- package/dist/resources/extensions/gsd/milestone-closeout-proof.js +72 -0
- package/dist/resources/extensions/gsd/milestone-closeout.js +12 -4
- package/dist/resources/extensions/gsd/milestone-merge-transaction.js +10 -0
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +156 -0
- package/dist/resources/extensions/gsd/milestone-readiness.js +77 -0
- package/dist/resources/extensions/gsd/milestone-settlement.js +50 -0
- package/dist/resources/extensions/gsd/milestone-validation-evidence.js +73 -0
- package/dist/resources/extensions/gsd/milestone-validation-verdict.js +57 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +147 -29
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/provider-payload-policy.js +83 -0
- package/dist/resources/extensions/gsd/pull-request-process.js +13 -0
- package/dist/resources/extensions/gsd/quality-gate-closure.js +109 -0
- package/dist/resources/extensions/gsd/question-transport.js +86 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state.js +13 -5
- package/dist/resources/extensions/gsd/templates/plan.md +7 -0
- package/dist/resources/extensions/gsd/templates/project.md +1 -0
- package/dist/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/dist/resources/extensions/gsd/templates/uat.md +5 -1
- package/dist/resources/extensions/gsd/tool-contract.js +52 -8
- package/dist/resources/extensions/gsd/tool-presentation-plan.js +15 -34
- package/dist/resources/extensions/gsd/tool-surface-snapshot.js +17 -0
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +15 -143
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +39 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +15 -78
- package/dist/resources/extensions/gsd/uat-policy.js +16 -10
- package/dist/resources/extensions/gsd/uat-run.js +9 -14
- package/dist/resources/extensions/gsd/unit-context-composer.js +40 -20
- package/dist/resources/extensions/gsd/unit-runtime.js +3 -2
- package/dist/resources/extensions/gsd/unit-tool-contracts.js +2 -1
- package/dist/resources/extensions/gsd/user-input-boundary.js +23 -0
- package/dist/resources/extensions/gsd/validation-block-guard.js +2 -0
- package/dist/resources/extensions/gsd/web-app-uat.js +80 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +15 -102
- package/dist/resources/extensions/gsd/workflow-reconcile.js +4 -3
- package/dist/resources/extensions/gsd/workflow-tool-surface.js +46 -0
- package/dist/resources/extensions/gsd/workspace-git-guard.js +2 -0
- package/dist/resources/extensions/gsd/worktree-state-projection.js +33 -4
- package/dist/resources/extensions/gsd/worktree-telemetry.js +12 -0
- package/dist/resources/extensions/shared/interview-ui.js +2 -2
- package/dist/resources/shared/claude-runtime-floor.js +182 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/update-cmd.js +20 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +7 -7
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +8 -8
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +7 -7
- package/dist/web/standalone/.next/server/chunks/8357.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/2659.b7b129ee6a769448.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2772.bfa657f49f955239.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{3616.4113d484a994e411.js → 3616.3c60753b8ffcbd2e.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/4283.e4873b058df143a1.js +2 -0
- package/dist/web/standalone/.next/static/chunks/5826.a46ecdd1cfe8dabc.js +1 -0
- package/dist/web/standalone/.next/static/chunks/796.cf859a427a2cb2ac.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8785.2e5a118797fb2dd2.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-dda80a1ef5587410.js → webpack-fbea77b5f9953368.js} +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +1 -1
- package/dist/web-mode.d.ts +2 -0
- package/dist/web-mode.js +20 -8
- package/package.json +2 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +2 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +14 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js +106 -40
- package/packages/gsd-agent-modes/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js +6 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-extension-widgets.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/server.d.ts +10 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +8 -0
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +41 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +2 -1
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +8 -93
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +35 -120
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/dist/components/input.js +1 -1
- package/packages/pi-tui/dist/components/input.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +39 -30
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/packages/pi-tui/dist/stdin-buffer.js +22 -0
- package/packages/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +87 -24
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +108 -281
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +240 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +287 -0
- package/src/resources/extensions/github-sync/templates.ts +3 -3
- package/src/resources/extensions/github-sync/tests/templates.test.ts +2 -2
- package/src/resources/extensions/gsd/artifact-projection.ts +31 -0
- package/src/resources/extensions/gsd/auto/contracts.ts +32 -2
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -0
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +125 -12
- package/src/resources/extensions/gsd/auto/phases.ts +35 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +2 -1
- package/src/resources/extensions/gsd/auto/session.ts +4 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +18 -4
- package/src/resources/extensions/gsd/auto-dispatch.ts +20 -7
- package/src/resources/extensions/gsd/auto-model-selection.ts +8 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +107 -9
- package/src/resources/extensions/gsd/auto-recovery.ts +50 -50
- package/src/resources/extensions/gsd/auto-runtime-state.ts +26 -0
- package/src/resources/extensions/gsd/auto-start.ts +17 -20
- package/src/resources/extensions/gsd/auto-timers.ts +16 -2
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +35 -0
- package/src/resources/extensions/gsd/auto-unit-tool-scope.ts +9 -30
- package/src/resources/extensions/gsd/auto-verification.ts +7 -8
- package/src/resources/extensions/gsd/auto-worktree.ts +33 -26
- package/src/resources/extensions/gsd/auto.ts +15 -8
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +10 -37
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +116 -151
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +107 -3
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +3 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +18 -0
- package/src/resources/extensions/gsd/commands-inspect.ts +7 -8
- package/src/resources/extensions/gsd/commands-maintenance.ts +74 -40
- package/src/resources/extensions/gsd/commands-ship.ts +2 -2
- package/src/resources/extensions/gsd/commands-verdict.ts +19 -2
- package/src/resources/extensions/gsd/db-workspace.ts +170 -0
- package/src/resources/extensions/gsd/delegation-policy.ts +3 -11
- package/src/resources/extensions/gsd/discussion-handoff.ts +276 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +9 -0
- package/src/resources/extensions/gsd/doctor.ts +15 -5
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/git-conflict-state.ts +17 -1
- package/src/resources/extensions/gsd/gsd-db.ts +12 -0
- package/src/resources/extensions/gsd/guided-flow.ts +47 -558
- package/src/resources/extensions/gsd/guided-unit-completion.ts +275 -0
- package/src/resources/extensions/gsd/markdown-renderer.ts +2 -1
- package/src/resources/extensions/gsd/mcp-filter.ts +2 -1
- package/src/resources/extensions/gsd/mcp-tool-name.ts +35 -0
- package/src/resources/extensions/gsd/md-importer.ts +3 -3
- package/src/resources/extensions/gsd/migrate/safety.ts +2 -2
- package/src/resources/extensions/gsd/migration-auto-check.ts +2 -2
- package/src/resources/extensions/gsd/milestone-closeout-proof.ts +131 -0
- package/src/resources/extensions/gsd/milestone-closeout.ts +12 -4
- package/src/resources/extensions/gsd/milestone-merge-transaction.ts +47 -0
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +224 -0
- package/src/resources/extensions/gsd/milestone-readiness.ts +125 -0
- package/src/resources/extensions/gsd/milestone-settlement.ts +81 -0
- package/src/resources/extensions/gsd/milestone-validation-evidence.ts +95 -0
- package/src/resources/extensions/gsd/milestone-validation-verdict.ts +80 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/preferences-diagnostics.ts +98 -0
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +173 -28
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/execute-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/guided-discuss-project.md +3 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/provider-payload-policy.ts +140 -0
- package/src/resources/extensions/gsd/pull-request-process.ts +41 -0
- package/src/resources/extensions/gsd/quality-gate-closure.ts +140 -0
- package/src/resources/extensions/gsd/question-transport.ts +138 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state.ts +15 -5
- package/src/resources/extensions/gsd/templates/plan.md +7 -0
- package/src/resources/extensions/gsd/templates/project.md +1 -0
- package/src/resources/extensions/gsd/templates/roadmap.md +1 -1
- package/src/resources/extensions/gsd/templates/uat.md +5 -1
- package/src/resources/extensions/gsd/tests/ask-user-questions-render.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +29 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +321 -5
- package/src/resources/extensions/gsd/tests/auto-milestone-target.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +133 -4
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/codebase-generator.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +34 -3
- package/src/resources/extensions/gsd/tests/dispatch-run-uat-browser-tools.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-no-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/fixtures/pr-body/swarm-lane-with-blockers.md +1 -5
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout-proof.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/milestone-closeout.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-transaction.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/milestone-readiness.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-evidence.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/milestone-validation-verdict.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/preferences-diagnostics.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +183 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/provider-payload-policy.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/pull-request-process.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +94 -0
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +25 -1
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/stale-queued-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/tool-availability-audit.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +35 -42
- package/src/resources/extensions/gsd/tests/uat-policy.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +86 -1
- package/src/resources/extensions/gsd/tests/validate-milestone-stuck-guard.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/web-app-uat.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +126 -9
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +79 -0
- package/src/resources/extensions/gsd/tool-contract.ts +86 -8
- package/src/resources/extensions/gsd/tool-presentation-plan.ts +16 -33
- package/src/resources/extensions/gsd/tool-surface-snapshot.ts +47 -0
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +19 -160
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +43 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -84
- package/src/resources/extensions/gsd/uat-policy.ts +19 -10
- package/src/resources/extensions/gsd/uat-run.ts +10 -14
- package/src/resources/extensions/gsd/unit-context-composer.ts +85 -20
- package/src/resources/extensions/gsd/unit-runtime.ts +3 -2
- package/src/resources/extensions/gsd/unit-tool-contracts.ts +2 -1
- package/src/resources/extensions/gsd/user-input-boundary.ts +18 -0
- package/src/resources/extensions/gsd/validation-block-guard.ts +2 -0
- package/src/resources/extensions/gsd/web-app-uat.ts +101 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +22 -110
- package/src/resources/extensions/gsd/workflow-reconcile.ts +3 -3
- package/src/resources/extensions/gsd/workflow-tool-surface.ts +73 -0
- package/src/resources/extensions/gsd/workspace-git-guard.ts +1 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +7 -16
- package/src/resources/extensions/gsd/worktree-state-projection.ts +55 -7
- package/src/resources/extensions/gsd/worktree-telemetry.ts +16 -0
- package/src/resources/extensions/shared/interview-ui.ts +15 -2
- package/src/resources/shared/claude-runtime-floor.ts +248 -0
- package/dist/web/standalone/.next/static/chunks/2659.feb6499ca863ebfc.js +0 -1
- package/dist/web/standalone/.next/static/chunks/2772.151789db0edea835.js +0 -1
- package/dist/web/standalone/.next/static/chunks/4283.10a065467b5340d8.js +0 -2
- package/dist/web/standalone/.next/static/chunks/5826.960dc4634cc9b0d3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/796.46f811c0fac23aab.js +0 -10
- package/dist/web/standalone/.next/static/chunks/8785.d32f7a61f55c1600.js +0 -1
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → 3PtrU9qGPEXwNLWkIyiqk}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Classify milestone readiness from DB status, slices, and artifacts.
|
|
3
|
+
import { readFileSync } from "node:fs";
|
|
4
|
+
import { getMilestone, getMilestoneSlices, isDbAvailable } from "./gsd-db.js";
|
|
5
|
+
import { parseRoadmapSlices } from "./roadmap-slices.js";
|
|
6
|
+
import { logWarning } from "./workflow-logger.js";
|
|
7
|
+
export function classifyMilestoneReadiness(input) {
|
|
8
|
+
const hasContext = input.hasContext === true;
|
|
9
|
+
const hasDraftContext = !hasContext && input.hasDraftContext === true;
|
|
10
|
+
const hasSummary = input.hasSummary === true;
|
|
11
|
+
const sliceCount = input.sliceCount ?? 0;
|
|
12
|
+
const hasExecutablePlan = sliceCount > 0;
|
|
13
|
+
const status = input.status ?? null;
|
|
14
|
+
if (status === "complete" || hasSummary) {
|
|
15
|
+
return { kind: "terminal", hasContext, hasDraftContext, hasExecutablePlan };
|
|
16
|
+
}
|
|
17
|
+
if (status === "queued" && !hasContext && sliceCount === 0) {
|
|
18
|
+
return { kind: "queued-shell", hasContext, hasDraftContext, hasExecutablePlan };
|
|
19
|
+
}
|
|
20
|
+
if ((status === "needs-discussion" && !hasContext) || hasDraftContext) {
|
|
21
|
+
return { kind: "needs-discussion", hasContext, hasDraftContext, hasExecutablePlan };
|
|
22
|
+
}
|
|
23
|
+
if (hasExecutablePlan) {
|
|
24
|
+
return { kind: "executable-plan", hasContext, hasDraftContext, hasExecutablePlan };
|
|
25
|
+
}
|
|
26
|
+
return { kind: "planning-pending", hasContext, hasDraftContext, hasExecutablePlan };
|
|
27
|
+
}
|
|
28
|
+
export function readinessNeedsDiscussion(readiness) {
|
|
29
|
+
return readiness.kind === "needs-discussion" ||
|
|
30
|
+
(readiness.kind === "queued-shell" && readiness.hasDraftContext);
|
|
31
|
+
}
|
|
32
|
+
export function describeMilestoneReadinessPhase(phase) {
|
|
33
|
+
switch (phase) {
|
|
34
|
+
case "needs-discussion":
|
|
35
|
+
return {
|
|
36
|
+
label: "Discuss milestone draft",
|
|
37
|
+
description: "Milestone has a draft context — needs discussion before planning.",
|
|
38
|
+
};
|
|
39
|
+
case "pre-planning":
|
|
40
|
+
return {
|
|
41
|
+
label: "Research & plan milestone",
|
|
42
|
+
description: "Scout the landscape and create the roadmap.",
|
|
43
|
+
};
|
|
44
|
+
default:
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function executablePlanSliceCount(milestoneId, roadmapFile) {
|
|
49
|
+
if (isDbAvailable()) {
|
|
50
|
+
return getMilestoneSlices(milestoneId).length;
|
|
51
|
+
}
|
|
52
|
+
if (!roadmapFile)
|
|
53
|
+
return 0;
|
|
54
|
+
try {
|
|
55
|
+
return parseRoadmapSlices(readFileSync(roadmapFile, "utf-8")).length;
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
logWarning("guided", `failed to parse roadmap slices for ${milestoneId}: ${e.message}`);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function assessMilestoneHandoffReadiness(input) {
|
|
63
|
+
const milestone = isDbAvailable() ? getMilestone(input.milestoneId) : null;
|
|
64
|
+
return classifyMilestoneReadiness({
|
|
65
|
+
status: milestone?.status,
|
|
66
|
+
hasContext: input.contextFile != null,
|
|
67
|
+
sliceCount: executablePlanSliceCount(input.milestoneId, input.roadmapFile),
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export function formatAcceptedDiscussHandoffMessage(milestoneId, readiness) {
|
|
71
|
+
if (readiness.hasExecutablePlan)
|
|
72
|
+
return `Milestone ${milestoneId} ready.`;
|
|
73
|
+
if (readiness.hasContext) {
|
|
74
|
+
return `Milestone ${milestoneId} context captured. Continuing the planning pipeline.`;
|
|
75
|
+
}
|
|
76
|
+
return `Milestone ${milestoneId} planning artifacts captured. Continuing the planning pipeline.`;
|
|
77
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Milestone closeout settlement state across DB proof, artifacts, merge, and cleanup.
|
|
3
|
+
import { isInAutoWorktree } from "./auto-worktree.js";
|
|
4
|
+
import { formatCloseoutProofBlock, proveMilestoneCloseout, } from "./milestone-closeout-proof.js";
|
|
5
|
+
import { resolveCloseoutArtifactProjection } from "./artifact-projection.js";
|
|
6
|
+
function isActiveUnmergedWorktree(input) {
|
|
7
|
+
if (!input.milestoneId || input.milestoneMerged)
|
|
8
|
+
return false;
|
|
9
|
+
return isInAutoWorktree(input.basePath);
|
|
10
|
+
}
|
|
11
|
+
export function evaluateAllCompleteSettlement(input) {
|
|
12
|
+
if (input.statePhase !== "complete") {
|
|
13
|
+
return { ok: true, reason: "not-applicable" };
|
|
14
|
+
}
|
|
15
|
+
if (!isActiveUnmergedWorktree(input)) {
|
|
16
|
+
return { ok: true, reason: "settled" };
|
|
17
|
+
}
|
|
18
|
+
const milestoneId = input.milestoneId;
|
|
19
|
+
if (!milestoneId) {
|
|
20
|
+
return { ok: true, reason: "settled" };
|
|
21
|
+
}
|
|
22
|
+
const projection = resolveCloseoutArtifactProjection({
|
|
23
|
+
milestoneId,
|
|
24
|
+
basePath: input.basePath,
|
|
25
|
+
originalBasePath: input.originalBasePath,
|
|
26
|
+
});
|
|
27
|
+
const proof = proveMilestoneCloseout(milestoneId, {
|
|
28
|
+
refreshFromDisk: true,
|
|
29
|
+
summaryArtifactBasePath: projection.summaryArtifactBasePath,
|
|
30
|
+
});
|
|
31
|
+
if (!proof.ok) {
|
|
32
|
+
return {
|
|
33
|
+
ok: false,
|
|
34
|
+
reason: "closeout-blocked",
|
|
35
|
+
action: "pause",
|
|
36
|
+
message: `${formatCloseoutProofBlock(proof)} The milestone branch has not been merged to main.`,
|
|
37
|
+
nextAction: `Resolve closeout blockers, then retry \`/gsd dispatch complete-milestone ${milestoneId}\`.`,
|
|
38
|
+
milestoneId,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
reason: "merge-pending",
|
|
44
|
+
action: "pause",
|
|
45
|
+
message: `Milestone ${milestoneId} is complete, but its worktree branch has not been merged to main. ` +
|
|
46
|
+
`Retry with \`/gsd dispatch complete-milestone ${milestoneId}\` or merge manually.`,
|
|
47
|
+
nextAction: `Retry \`/gsd dispatch complete-milestone ${milestoneId}\` or merge manually.`,
|
|
48
|
+
milestoneId,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Forwarded validation evidence rules for milestone validation.
|
|
3
|
+
import { getArtifact, getMilestone, getMilestoneSlices } from "./gsd-db.js";
|
|
4
|
+
import { loadFile } from "./files.js";
|
|
5
|
+
import { resolveSliceFile } from "./paths.js";
|
|
6
|
+
import { compactTextParts, hasBrowserEvidenceText, hasBrowserRequiredText, } from "./browser-evidence.js";
|
|
7
|
+
export function hasRuntimeExecutableUatEvidenceText(text) {
|
|
8
|
+
if (!/\buatType:\s*runtime-executable\b/i.test(text))
|
|
9
|
+
return false;
|
|
10
|
+
if (!/\bverdict:\s*PASS\b/i.test(text))
|
|
11
|
+
return false;
|
|
12
|
+
return /^\|\s*[^|\n]+\s*\|\s*runtime\s*\|\s*PASS\s*\|[^|\n]*\bgsd_uat_exec\b/mi.test(text);
|
|
13
|
+
}
|
|
14
|
+
export async function browserEvidenceGateRequiresAttention(params, basePath) {
|
|
15
|
+
if (params.verdict !== "pass")
|
|
16
|
+
return false;
|
|
17
|
+
const milestone = getMilestone(params.milestoneId);
|
|
18
|
+
const slices = getMilestoneSlices(params.milestoneId);
|
|
19
|
+
const requirementText = compactTextParts([
|
|
20
|
+
milestone?.vision,
|
|
21
|
+
milestone?.success_criteria,
|
|
22
|
+
milestone?.verification_uat,
|
|
23
|
+
params.successCriteriaChecklist,
|
|
24
|
+
params.verificationClasses,
|
|
25
|
+
...slices.flatMap((slice) => [
|
|
26
|
+
slice.demo,
|
|
27
|
+
slice.goal,
|
|
28
|
+
slice.success_criteria,
|
|
29
|
+
]),
|
|
30
|
+
]);
|
|
31
|
+
if (!hasBrowserRequiredText(requirementText))
|
|
32
|
+
return false;
|
|
33
|
+
const sliceEvidencePairs = [];
|
|
34
|
+
for (const slice of slices) {
|
|
35
|
+
const chunks = [];
|
|
36
|
+
const artifactPath = `milestones/${params.milestoneId}/slices/${slice.id}/${slice.id}-ASSESSMENT.md`;
|
|
37
|
+
const artifact = getArtifact(artifactPath);
|
|
38
|
+
if (artifact?.full_content)
|
|
39
|
+
chunks.push(artifact.full_content);
|
|
40
|
+
const assessmentPath = resolveSliceFile(basePath, params.milestoneId, slice.id, "ASSESSMENT");
|
|
41
|
+
const assessmentContent = assessmentPath ? await loadFile(assessmentPath) : null;
|
|
42
|
+
if (assessmentContent)
|
|
43
|
+
chunks.push(assessmentContent);
|
|
44
|
+
sliceEvidencePairs.push({
|
|
45
|
+
sliceRequirementText: compactTextParts([slice.demo, slice.goal, slice.success_criteria]),
|
|
46
|
+
evidenceText: chunks.join("\n\n"),
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const browserRequiringSlices = sliceEvidencePairs.filter((slice) => hasBrowserRequiredText(slice.sliceRequirementText));
|
|
50
|
+
const runtimeBypasses = browserRequiringSlices.length > 0
|
|
51
|
+
? browserRequiringSlices.every((slice) => hasRuntimeExecutableUatEvidenceText(slice.evidenceText))
|
|
52
|
+
: sliceEvidencePairs.some((slice) => hasRuntimeExecutableUatEvidenceText(slice.evidenceText));
|
|
53
|
+
if (runtimeBypasses)
|
|
54
|
+
return false;
|
|
55
|
+
const persistedEvidence = sliceEvidencePairs.map((slice) => slice.evidenceText).join("\n\n");
|
|
56
|
+
const validationEvidence = compactTextParts([
|
|
57
|
+
params.successCriteriaChecklist,
|
|
58
|
+
params.verificationClasses,
|
|
59
|
+
params.verdictRationale,
|
|
60
|
+
params.remediationPlan,
|
|
61
|
+
]);
|
|
62
|
+
return !hasBrowserEvidenceText(`${persistedEvidence}\n\n${validationEvidence}`);
|
|
63
|
+
}
|
|
64
|
+
export function applyBrowserEvidenceGate(params) {
|
|
65
|
+
const note = "Browser evidence gate: Browser-observable acceptance criteria were detected, but no persisted ASSESSMENT or validation evidence recorded browser actions with assertions. Downgraded from pass to needs-attention.";
|
|
66
|
+
return {
|
|
67
|
+
...params,
|
|
68
|
+
verdict: "needs-attention",
|
|
69
|
+
verdictRationale: params.verdictRationale.trim()
|
|
70
|
+
? `${params.verdictRationale.trim()}\n\n${note}`
|
|
71
|
+
: note,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Resolve the authoritative milestone validation verdict across DB and disk projections.
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { resolveExpectedArtifactPath } from "./auto-artifact-paths.js";
|
|
6
|
+
import { loadFile } from "./files.js";
|
|
7
|
+
import { getLatestAssessmentByScope, isDbAvailable } from "./gsd-db.js";
|
|
8
|
+
import { gsdProjectionRoot } from "./paths.js";
|
|
9
|
+
import { extractVerdict, isValidMilestoneVerdict, } from "./verdict-parser.js";
|
|
10
|
+
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
11
|
+
import { resolveWorktreeProjectRoot } from "./worktree-root.js";
|
|
12
|
+
function verdictFromContent(content) {
|
|
13
|
+
if (!content)
|
|
14
|
+
return undefined;
|
|
15
|
+
const verdict = extractVerdict(content);
|
|
16
|
+
return verdict && isValidMilestoneVerdict(verdict) ? verdict : undefined;
|
|
17
|
+
}
|
|
18
|
+
function verdictFromDb(milestoneId) {
|
|
19
|
+
if (!isDbAvailable())
|
|
20
|
+
return undefined;
|
|
21
|
+
const assessment = getLatestAssessmentByScope(milestoneId, "milestone-validation");
|
|
22
|
+
const status = typeof assessment?.status === "string" ? assessment.status : undefined;
|
|
23
|
+
return status && isValidMilestoneVerdict(status) ? status : undefined;
|
|
24
|
+
}
|
|
25
|
+
async function verdictFromValidationPath(path) {
|
|
26
|
+
if (!path || !existsSync(path))
|
|
27
|
+
return undefined;
|
|
28
|
+
return verdictFromContent(await loadFile(path));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the milestone validation verdict using the same authority order as
|
|
32
|
+
* DB-backed state derivation, with filesystem fallbacks that mirror
|
|
33
|
+
* `resolveExpectedArtifactPath` (canonical worktree projection, then project
|
|
34
|
+
* root). Manual `/gsd verdict` overrides persist to the DB first; a stale
|
|
35
|
+
* worktree-local VALIDATION.md must not re-block auto-mode after the override.
|
|
36
|
+
*/
|
|
37
|
+
export async function resolveMilestoneValidationVerdict(basePath, milestoneId) {
|
|
38
|
+
const dbVerdict = verdictFromDb(milestoneId);
|
|
39
|
+
if (dbVerdict)
|
|
40
|
+
return dbVerdict;
|
|
41
|
+
const canonicalBase = resolveCanonicalMilestoneRoot(basePath, milestoneId);
|
|
42
|
+
const canonicalPath = resolveExpectedArtifactPath("validate-milestone", milestoneId, canonicalBase);
|
|
43
|
+
const canonicalVerdict = await verdictFromValidationPath(canonicalPath);
|
|
44
|
+
if (canonicalVerdict)
|
|
45
|
+
return canonicalVerdict;
|
|
46
|
+
const projectRoot = resolveWorktreeProjectRoot(basePath);
|
|
47
|
+
if (projectRoot !== canonicalBase) {
|
|
48
|
+
const projectPath = resolveExpectedArtifactPath("validate-milestone", milestoneId, projectRoot);
|
|
49
|
+
const projectVerdict = await verdictFromValidationPath(projectPath);
|
|
50
|
+
if (projectVerdict)
|
|
51
|
+
return projectVerdict;
|
|
52
|
+
}
|
|
53
|
+
// Last resort: direct canonical projection path even when resolveDir helpers
|
|
54
|
+
// have not materialized the milestone directory yet.
|
|
55
|
+
const directPath = join(gsdProjectionRoot(canonicalBase), "milestones", milestoneId, `${milestoneId}-VALIDATION.md`);
|
|
56
|
+
return verdictFromValidationPath(directPath);
|
|
57
|
+
}
|
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
* Analyzes which milestones can safely run in parallel by checking
|
|
5
5
|
* dependency satisfaction and file overlap across slice plans.
|
|
6
6
|
*/
|
|
7
|
-
import { existsSync } from "node:fs";
|
|
8
7
|
import { deriveState } from "./state.js";
|
|
9
|
-
import { resolveGsdPathContract } from "./paths.js";
|
|
10
8
|
import { findMilestoneIds } from "./guided-flow.js";
|
|
11
|
-
import { isDbAvailable, getMilestoneSlices, getSliceTasks
|
|
9
|
+
import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
|
|
10
|
+
import { openExistingWorkflowDatabase } from "./db-workspace.js";
|
|
12
11
|
// ─── File Collection ─────────────────────────────────────────────────────────
|
|
13
12
|
/**
|
|
14
13
|
* Collect all `filesLikelyTouched` across every slice plan in a milestone.
|
|
@@ -64,9 +63,7 @@ function detectFileOverlaps(fileSets) {
|
|
|
64
63
|
*/
|
|
65
64
|
export async function analyzeParallelEligibility(basePath) {
|
|
66
65
|
if (!isDbAvailable()) {
|
|
67
|
-
|
|
68
|
-
if (existsSync(projectDb))
|
|
69
|
-
openDatabase(projectDb);
|
|
66
|
+
openExistingWorkflowDatabase(basePath);
|
|
70
67
|
}
|
|
71
68
|
const milestoneIds = findMilestoneIds(basePath);
|
|
72
69
|
const state = await deriveState(basePath);
|
|
@@ -12,9 +12,10 @@ import { join, dirname } from "node:path";
|
|
|
12
12
|
import { fileURLToPath } from "node:url";
|
|
13
13
|
import { gsdRoot } from "./paths.js";
|
|
14
14
|
import { createWorktree, worktreePath } from "./worktree-manager.js";
|
|
15
|
-
import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe, runWorktreePostCreateHook,
|
|
15
|
+
import { autoWorktreeBranch, fastForwardReusedMilestoneBranchIfSafe, runWorktreePostCreateHook, syncGsdStateToWorktreeByScope } from "./auto-worktree.js";
|
|
16
16
|
import { nativeBranchExists } from "./native-git-bridge.js";
|
|
17
17
|
import { readIntegrationBranch } from "./git-service.js";
|
|
18
|
+
import { createWorkspace, scopeMilestone } from "./workspace.js";
|
|
18
19
|
import { resolveParallelConfig } from "./preferences.js";
|
|
19
20
|
import { writeSessionStatus, readAllSessionStatuses, readSessionStatus, removeSessionStatus, sendSignal, cleanupStaleSessions, } from "./session-status-io.js";
|
|
20
21
|
import { analyzeParallelEligibility, } from "./parallel-eligibility.js";
|
|
@@ -448,7 +449,7 @@ export function _createMilestoneWorktree(basePath, milestoneId) {
|
|
|
448
449
|
// Copy .gsd/ planning artifacts (milestones, CONTEXT, ROADMAP, etc.) from the
|
|
449
450
|
// project root into the worktree. Without this, workers for newly-planned
|
|
450
451
|
// milestones can't find their roadmap and exit immediately (#2184 Bug 4).
|
|
451
|
-
|
|
452
|
+
syncGsdStateToWorktreeByScope(scopeMilestone(createWorkspace(basePath), milestoneId), scopeMilestone(createWorkspace(info.path), milestoneId));
|
|
452
453
|
return info.path;
|
|
453
454
|
}
|
|
454
455
|
// ─── Worker Spawning ───────────────────────────────────────────────────
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { loadGlobalGSDPreferences, loadProjectGSDPreferences, } from "./preferences.js";
|
|
2
|
+
const notifiedPreferenceDiagnostics = new Set();
|
|
3
|
+
export function collectPreferenceDiagnostics(basePath) {
|
|
4
|
+
const diagnostics = [
|
|
5
|
+
...(loadGlobalGSDPreferences()?.diagnostics ?? []),
|
|
6
|
+
...(loadProjectGSDPreferences(basePath)?.diagnostics ?? []),
|
|
7
|
+
];
|
|
8
|
+
const seen = new Set();
|
|
9
|
+
const unique = [];
|
|
10
|
+
for (const diagnostic of diagnostics) {
|
|
11
|
+
const signature = preferenceDiagnosticSignature(diagnostic);
|
|
12
|
+
if (seen.has(signature))
|
|
13
|
+
continue;
|
|
14
|
+
seen.add(signature);
|
|
15
|
+
unique.push(diagnostic);
|
|
16
|
+
}
|
|
17
|
+
return unique;
|
|
18
|
+
}
|
|
19
|
+
export function formatPreferenceDiagnostic(diagnostic) {
|
|
20
|
+
const scope = diagnostic.scope === "global" ? "global" : "project";
|
|
21
|
+
const level = diagnostic.severity === "error" ? "error" : "warning";
|
|
22
|
+
const heading = diagnostic.kind === "parse"
|
|
23
|
+
? `GSD ${scope} preferences ${level}: ${diagnostic.path} could not be parsed.`
|
|
24
|
+
: `GSD ${scope} preferences ${level}: ${diagnostic.path} contains invalid settings.`;
|
|
25
|
+
const detail = formatPreferenceDiagnosticDetail(diagnostic);
|
|
26
|
+
const impact = diagnostic.ignored
|
|
27
|
+
? "Preferences from this file were ignored; auto-mode may be using defaults."
|
|
28
|
+
: "Invalid settings were ignored or sanitized; auto-mode may be using defaults for them.";
|
|
29
|
+
return `${heading}\n${detail}\n${impact}\nRun /gsd doctor for details.`;
|
|
30
|
+
}
|
|
31
|
+
export function formatPreferenceDiagnosticDetail(diagnostic) {
|
|
32
|
+
if (diagnostic.line !== undefined && diagnostic.column !== undefined) {
|
|
33
|
+
return `YAML error at line ${diagnostic.line}, column ${diagnostic.column}: ${diagnostic.message}`;
|
|
34
|
+
}
|
|
35
|
+
return diagnostic.message;
|
|
36
|
+
}
|
|
37
|
+
export function notifyPreferenceDiagnostics(ctx, basePath, options) {
|
|
38
|
+
let notified = 0;
|
|
39
|
+
for (const diagnostic of collectPreferenceDiagnostics(basePath)) {
|
|
40
|
+
const signature = preferenceDiagnosticNotificationSignature(diagnostic, options?.surface);
|
|
41
|
+
if (notifiedPreferenceDiagnostics.has(signature))
|
|
42
|
+
continue;
|
|
43
|
+
notifiedPreferenceDiagnostics.add(signature);
|
|
44
|
+
ctx.ui.notify(formatPreferenceDiagnostic(diagnostic), diagnostic.severity === "error" ? "error" : "warning");
|
|
45
|
+
notified++;
|
|
46
|
+
}
|
|
47
|
+
return notified;
|
|
48
|
+
}
|
|
49
|
+
export function _resetPreferenceDiagnosticNotificationsForTests() {
|
|
50
|
+
notifiedPreferenceDiagnostics.clear();
|
|
51
|
+
}
|
|
52
|
+
function preferenceDiagnosticSignature(diagnostic) {
|
|
53
|
+
return [
|
|
54
|
+
diagnostic.path,
|
|
55
|
+
diagnostic.scope,
|
|
56
|
+
diagnostic.severity,
|
|
57
|
+
diagnostic.kind,
|
|
58
|
+
diagnostic.message,
|
|
59
|
+
diagnostic.line ?? "",
|
|
60
|
+
diagnostic.column ?? "",
|
|
61
|
+
diagnostic.ignored === true ? "ignored" : "",
|
|
62
|
+
diagnostic.sanitized === true ? "sanitized" : "",
|
|
63
|
+
].join("\u0000");
|
|
64
|
+
}
|
|
65
|
+
function preferenceDiagnosticNotificationSignature(diagnostic, surface = "default") {
|
|
66
|
+
return `${surface}\u0000${preferenceDiagnosticSignature(diagnostic)}`;
|
|
67
|
+
}
|
|
@@ -98,37 +98,41 @@ export function normalizePreferencesShape(loaded) {
|
|
|
98
98
|
}
|
|
99
99
|
// ─── Loading ────────────────────────────────────────────────────────────────
|
|
100
100
|
export function loadGlobalGSDPreferences() {
|
|
101
|
-
return
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
return loadFirstUsablePreferencesFile([
|
|
102
|
+
globalPreferencesPath(),
|
|
103
|
+
legacyGlobalPreferencesPathLowercase(),
|
|
104
|
+
legacyGlobalPreferencesPath(),
|
|
105
|
+
], "global");
|
|
104
106
|
}
|
|
105
107
|
export function loadProjectGSDPreferences(basePath) {
|
|
106
|
-
return
|
|
107
|
-
|
|
108
|
+
return loadFirstUsablePreferencesFile([
|
|
109
|
+
projectPreferencesPath(basePath),
|
|
110
|
+
legacyProjectPreferencesPathLowercase(basePath),
|
|
111
|
+
], "project");
|
|
108
112
|
}
|
|
109
113
|
export function loadEffectiveGSDPreferences(basePath, opts) {
|
|
110
114
|
const globalPreferences = loadGlobalGSDPreferences();
|
|
111
115
|
const projectPreferences = loadProjectGSDPreferences(basePath);
|
|
112
|
-
const
|
|
113
|
-
|
|
116
|
+
const effectiveGlobalPreferences = globalPreferences?.ignored ? null : globalPreferences;
|
|
117
|
+
const effectiveProjectPreferences = projectPreferences?.ignored ? null : projectPreferences;
|
|
118
|
+
const projectHasPlanningDepth = effectiveProjectPreferences?.preferences.planning_depth !== undefined;
|
|
119
|
+
if (!effectiveGlobalPreferences && !effectiveProjectPreferences)
|
|
114
120
|
return null;
|
|
115
121
|
let result;
|
|
116
|
-
if (!
|
|
117
|
-
result =
|
|
122
|
+
if (!effectiveGlobalPreferences) {
|
|
123
|
+
result = effectiveProjectPreferences;
|
|
118
124
|
}
|
|
119
|
-
else if (!
|
|
120
|
-
result =
|
|
125
|
+
else if (!effectiveProjectPreferences) {
|
|
126
|
+
result = mergePreferenceMetadata(effectiveGlobalPreferences, projectPreferences);
|
|
121
127
|
}
|
|
122
128
|
else {
|
|
123
|
-
const
|
|
124
|
-
...(globalPreferences.warnings ?? []),
|
|
125
|
-
...(projectPreferences.warnings ?? []),
|
|
126
|
-
];
|
|
129
|
+
const metadata = mergePreferenceMetadata(effectiveGlobalPreferences, effectiveProjectPreferences);
|
|
127
130
|
result = {
|
|
128
|
-
path:
|
|
131
|
+
path: effectiveProjectPreferences.path,
|
|
129
132
|
scope: "project",
|
|
130
|
-
preferences: mergePreferences(
|
|
131
|
-
...(
|
|
133
|
+
preferences: mergePreferences(effectiveGlobalPreferences.preferences, effectiveProjectPreferences.preferences),
|
|
134
|
+
...(metadata.warnings ? { warnings: metadata.warnings } : {}),
|
|
135
|
+
...(metadata.diagnostics ? { diagnostics: metadata.diagnostics } : {}),
|
|
132
136
|
};
|
|
133
137
|
}
|
|
134
138
|
// Apply token-profile defaults as the lowest-priority layer so that
|
|
@@ -152,6 +156,35 @@ export function loadEffectiveGSDPreferences(basePath, opts) {
|
|
|
152
156
|
result = stripInheritedPlanningDepth(result, projectHasPlanningDepth);
|
|
153
157
|
return result;
|
|
154
158
|
}
|
|
159
|
+
function mergePreferenceMetadata(primary, secondary) {
|
|
160
|
+
const mergedWarnings = [
|
|
161
|
+
...(primary.warnings ?? []),
|
|
162
|
+
...(secondary?.warnings ?? []),
|
|
163
|
+
];
|
|
164
|
+
const mergedDiagnostics = [
|
|
165
|
+
...(primary.diagnostics ?? []),
|
|
166
|
+
...(secondary?.diagnostics ?? []),
|
|
167
|
+
];
|
|
168
|
+
return {
|
|
169
|
+
...primary,
|
|
170
|
+
...(mergedWarnings.length > 0 ? { warnings: mergedWarnings } : {}),
|
|
171
|
+
...(mergedDiagnostics.length > 0 ? { diagnostics: mergedDiagnostics } : {}),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function loadFirstUsablePreferencesFile(paths, scope) {
|
|
175
|
+
let ignoredPreferences = null;
|
|
176
|
+
for (const path of paths) {
|
|
177
|
+
const loaded = loadPreferencesFile(path, scope);
|
|
178
|
+
if (!loaded)
|
|
179
|
+
continue;
|
|
180
|
+
if (!loaded.ignored)
|
|
181
|
+
return mergePreferenceMetadata(loaded, ignoredPreferences);
|
|
182
|
+
ignoredPreferences = ignoredPreferences
|
|
183
|
+
? mergePreferenceMetadata(ignoredPreferences, loaded)
|
|
184
|
+
: loaded;
|
|
185
|
+
}
|
|
186
|
+
return ignoredPreferences;
|
|
187
|
+
}
|
|
155
188
|
function stripInheritedPlanningDepth(loaded, projectHasPlanningDepth) {
|
|
156
189
|
if (projectHasPlanningDepth || loaded.preferences.planning_depth === undefined) {
|
|
157
190
|
return loaded;
|
|
@@ -167,16 +200,39 @@ function loadPreferencesFile(path, scope) {
|
|
|
167
200
|
if (!existsSync(path))
|
|
168
201
|
return null;
|
|
169
202
|
const raw = readFileSync(path, "utf-8");
|
|
170
|
-
const
|
|
171
|
-
if (!preferences)
|
|
203
|
+
const parsed = parsePreferencesMarkdownWithDiagnostics(raw);
|
|
204
|
+
if (!parsed.preferences && parsed.diagnostics.length === 0)
|
|
172
205
|
return null;
|
|
206
|
+
const ignored = parsed.diagnostics.some((diagnostic) => diagnostic.ignored === true);
|
|
207
|
+
const preferences = parsed.preferences ?? {};
|
|
173
208
|
const validation = validatePreferences(preferences);
|
|
174
209
|
const allWarnings = [...validation.warnings, ...validation.errors];
|
|
210
|
+
const diagnostics = [
|
|
211
|
+
...parsed.diagnostics.map((diagnostic) => ({ ...diagnostic, path, scope })),
|
|
212
|
+
...validation.errors.map((message) => ({
|
|
213
|
+
path,
|
|
214
|
+
scope,
|
|
215
|
+
severity: "error",
|
|
216
|
+
kind: "validation",
|
|
217
|
+
message,
|
|
218
|
+
sanitized: true,
|
|
219
|
+
})),
|
|
220
|
+
...validation.warnings.map((message) => ({
|
|
221
|
+
path,
|
|
222
|
+
scope,
|
|
223
|
+
severity: "warning",
|
|
224
|
+
kind: "validation",
|
|
225
|
+
message,
|
|
226
|
+
sanitized: true,
|
|
227
|
+
})),
|
|
228
|
+
];
|
|
175
229
|
return {
|
|
176
230
|
path,
|
|
177
231
|
scope,
|
|
178
232
|
preferences: validation.preferences,
|
|
233
|
+
...(ignored ? { ignored: true } : {}),
|
|
179
234
|
...(allWarnings.length > 0 ? { warnings: allWarnings } : {}),
|
|
235
|
+
...(diagnostics.length > 0 ? { diagnostics } : {}),
|
|
180
236
|
};
|
|
181
237
|
}
|
|
182
238
|
let _warnedUnrecognizedFormat = false;
|
|
@@ -189,20 +245,35 @@ export function _resetParseWarningFlag() {
|
|
|
189
245
|
}
|
|
190
246
|
/** @internal Exported for testing only */
|
|
191
247
|
export function parsePreferencesMarkdown(content) {
|
|
248
|
+
return parsePreferencesMarkdownWithDiagnostics(content).preferences;
|
|
249
|
+
}
|
|
250
|
+
function parsePreferencesMarkdownWithDiagnostics(content) {
|
|
192
251
|
// Use indexOf instead of [\s\S]*? regex to avoid backtracking (#468)
|
|
193
252
|
const startMarker = content.startsWith('---\r\n') ? '---\r\n' : '---\n';
|
|
194
253
|
if (content.startsWith(startMarker)) {
|
|
195
254
|
const searchStart = startMarker.length;
|
|
196
255
|
const endIdx = content.indexOf('\n---', searchStart);
|
|
197
|
-
if (endIdx === -1)
|
|
198
|
-
return
|
|
256
|
+
if (endIdx === -1) {
|
|
257
|
+
return {
|
|
258
|
+
preferences: null,
|
|
259
|
+
diagnostics: [{
|
|
260
|
+
severity: "error",
|
|
261
|
+
kind: "parse",
|
|
262
|
+
message: "preferences frontmatter is missing a closing --- delimiter",
|
|
263
|
+
ignored: true,
|
|
264
|
+
}],
|
|
265
|
+
};
|
|
266
|
+
}
|
|
199
267
|
const block = content.slice(searchStart, endIdx);
|
|
200
|
-
return
|
|
268
|
+
return parseFrontmatterBlockWithDiagnostics(block.replace(/\r/g, ''), 1);
|
|
201
269
|
}
|
|
202
270
|
// Fallback: heading+list format (e.g. "## Git\n- isolation: none") (#2036)
|
|
203
271
|
// GSD agents may write preferences files without frontmatter delimiters.
|
|
204
272
|
if (/^##\s+\w/m.test(content)) {
|
|
205
|
-
return
|
|
273
|
+
return {
|
|
274
|
+
preferences: parseHeadingListFormat(content),
|
|
275
|
+
diagnostics: [],
|
|
276
|
+
};
|
|
206
277
|
}
|
|
207
278
|
// Warn when a non-empty file exists but lacks frontmatter delimiters (#2036).
|
|
208
279
|
if (content.trim().length > 0 && !_warnedUnrecognizedFormat) {
|
|
@@ -210,16 +281,37 @@ export function parsePreferencesMarkdown(content) {
|
|
|
210
281
|
console.warn("[GSD] Warning: preferences file has unrecognized format — content does not use YAML frontmatter delimiters (---). " +
|
|
211
282
|
"Wrap your preferences in --- fences. See https://github.com/open-gsd/gsd-pi/issues/2036");
|
|
212
283
|
}
|
|
213
|
-
return
|
|
284
|
+
return {
|
|
285
|
+
preferences: null,
|
|
286
|
+
diagnostics: content.trim().length > 0
|
|
287
|
+
? [{
|
|
288
|
+
severity: "error",
|
|
289
|
+
kind: "parse",
|
|
290
|
+
message: "preferences file has unrecognized format; expected YAML frontmatter delimiters (---) or markdown preference sections",
|
|
291
|
+
ignored: true,
|
|
292
|
+
}]
|
|
293
|
+
: [],
|
|
294
|
+
};
|
|
214
295
|
}
|
|
215
296
|
let _warnedFrontmatterParse = false;
|
|
216
|
-
function
|
|
297
|
+
function parseFrontmatterBlockWithDiagnostics(frontmatter, lineOffset) {
|
|
217
298
|
try {
|
|
218
299
|
const parsed = parseYaml(frontmatter);
|
|
219
300
|
if (typeof parsed !== 'object' || parsed === null) {
|
|
220
|
-
return {
|
|
301
|
+
return {
|
|
302
|
+
preferences: {},
|
|
303
|
+
diagnostics: [{
|
|
304
|
+
severity: "error",
|
|
305
|
+
kind: "validation",
|
|
306
|
+
message: "preferences frontmatter must be a YAML object",
|
|
307
|
+
ignored: true,
|
|
308
|
+
}],
|
|
309
|
+
};
|
|
221
310
|
}
|
|
222
|
-
return
|
|
311
|
+
return {
|
|
312
|
+
preferences: normalizeParsedPreferences(parsed),
|
|
313
|
+
diagnostics: [],
|
|
314
|
+
};
|
|
223
315
|
}
|
|
224
316
|
catch (e) {
|
|
225
317
|
// Warn at most once per session to avoid flooding TUI (#3376)
|
|
@@ -227,9 +319,35 @@ function parseFrontmatterBlock(frontmatter) {
|
|
|
227
319
|
_warnedFrontmatterParse = true;
|
|
228
320
|
logWarning("guided", `YAML parse error in preferences frontmatter (suppressing further): ${e.message}`);
|
|
229
321
|
}
|
|
230
|
-
|
|
322
|
+
const location = extractYamlErrorLocation(e, lineOffset);
|
|
323
|
+
return {
|
|
324
|
+
preferences: {},
|
|
325
|
+
diagnostics: [{
|
|
326
|
+
severity: "error",
|
|
327
|
+
kind: "parse",
|
|
328
|
+
message: cleanYamlErrorMessage(e),
|
|
329
|
+
...(location.line !== undefined ? { line: location.line } : {}),
|
|
330
|
+
...(location.column !== undefined ? { column: location.column } : {}),
|
|
331
|
+
ignored: true,
|
|
332
|
+
}],
|
|
333
|
+
};
|
|
231
334
|
}
|
|
232
335
|
}
|
|
336
|
+
function cleanYamlErrorMessage(error) {
|
|
337
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
338
|
+
const firstLine = message.split("\n")[0]?.trim() ?? "unknown YAML parse error";
|
|
339
|
+
return firstLine.replace(/\s+at line \d+, column \d+:?$/, "");
|
|
340
|
+
}
|
|
341
|
+
function extractYamlErrorLocation(error, lineOffset) {
|
|
342
|
+
const linePos = error?.linePos;
|
|
343
|
+
const first = Array.isArray(linePos) ? linePos[0] : undefined;
|
|
344
|
+
const line = typeof first?.line === "number" ? first.line + lineOffset : undefined;
|
|
345
|
+
const column = typeof first?.col === "number" ? first.col : undefined;
|
|
346
|
+
return {
|
|
347
|
+
...(line !== undefined ? { line } : {}),
|
|
348
|
+
...(column !== undefined ? { column } : {}),
|
|
349
|
+
};
|
|
350
|
+
}
|
|
233
351
|
function normalizeParsedPreferences(preferences) {
|
|
234
352
|
const remoteQuestions = preferences.remote_questions;
|
|
235
353
|
if (remoteQuestions && typeof remoteQuestions === "object" && typeof remoteQuestions.channel_id === "number") {
|
|
@@ -37,6 +37,7 @@ Use `subagent` only when useful: reviewer, security, or tester. Apply findings b
|
|
|
37
37
|
9. If requirement status changed, call `gsd_requirement_update`; do not write `.gsd/REQUIREMENTS.md` directly.
|
|
38
38
|
10. Prepare `gsd_slice_complete` content with camelCase fields `milestoneId`, `sliceId`, `sliceTitle`, `oneLiner`, `narrative`, `verification`, and `uatContent`.
|
|
39
39
|
11. Draft concrete UAT with preconditions, steps, expected outcomes, edge cases, and UAT Type.
|
|
40
|
+
**Web apps:** when inlined Web App UAT guidance is present, declare `browser-executable` or `runtime-executable` (not `artifact-driven`) for localhost/browser/screenshot steps; include dev-server preconditions and name Playwright specs when they exist.
|
|
40
41
|
12. Review the inlined task-summary excerpts for DECISIONS.md/KNOWLEDGE.md-worthy decisions and gotchas. Read full `*-SUMMARY.md` only if needed. Capture with `capture_thought`; do not append knowledge files.
|
|
41
42
|
13. When verification passes, call `gsd_slice_complete`. The DB-backed tool is the canonical write path. Do **not** manually write `{{sliceSummaryPath}}`. Do **not** manually write `{{sliceUatPath}}`. Do not edit roadmap checkboxes.
|
|
42
43
|
14. Do not run git commands.
|
|
@@ -32,6 +32,8 @@ You execute. The inlined task plan is authoritative. Verify referenced files and
|
|
|
32
32
|
- Prior task summaries:
|
|
33
33
|
{{priorTaskLines}}
|
|
34
34
|
|
|
35
|
+
{{onDemandContext}}
|
|
36
|
+
|
|
35
37
|
## Execution Rules
|
|
36
38
|
|
|
37
39
|
1. Tersely narrate transitions, decisions, and verification outcomes between tool-call clusters.
|