@opengsd/gsd-pi 1.2.0-dev.844675c9 → 1.2.0-dev.955e4da0
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/bg-shell/utilities.js +2 -2
- package/dist/resources/extensions/claude-code-cli/models.js +9 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +92 -230
- 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 +142 -15
- package/dist/resources/extensions/gsd/auto/phases.js +34 -4
- 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 +12 -9
- 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 +20 -36
- 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-repair.js +10 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +34 -289
- package/dist/resources/extensions/gsd/auto.js +15 -14
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +28 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +20 -43
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +131 -140
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +89 -8
- package/dist/resources/extensions/gsd/captures.js +5 -13
- package/dist/resources/extensions/gsd/closeout-consistency-gate.js +21 -4
- package/dist/resources/extensions/gsd/closeout-recovery.js +3 -2
- package/dist/resources/extensions/gsd/codebase-generator.js +8 -4
- package/dist/resources/extensions/gsd/commands/catalog.js +6 -62
- 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/engine.js +755 -0
- package/dist/resources/extensions/gsd/db/queries.js +372 -0
- package/dist/resources/extensions/gsd/db/sql-constants.js +11 -0
- package/dist/resources/extensions/gsd/db/writers/cascades.js +194 -0
- package/dist/resources/extensions/gsd/db/writers/import-restore.js +182 -0
- package/dist/resources/extensions/gsd/db/writers/memory.js +149 -0
- package/dist/resources/extensions/gsd/db/writers/reconcile.js +458 -0
- package/dist/resources/extensions/gsd/db/writers/status.js +70 -0
- 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-environment.js +8 -10
- package/dist/resources/extensions/gsd/doctor-git-checks.js +4 -3
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +9 -2
- 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/git-service.js +1 -0
- package/dist/resources/extensions/gsd/gitignore.js +3 -0
- package/dist/resources/extensions/gsd/gsd-db.js +183 -2048
- package/dist/resources/extensions/gsd/guided-flow.js +68 -471
- 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 +19 -11
- package/dist/resources/extensions/gsd/migration-auto-check.js +27 -5
- 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/model-cost-table.js +1 -0
- package/dist/resources/extensions/gsd/model-router.js +3 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +3 -6
- package/dist/resources/extensions/gsd/parallel-merge.js +14 -11
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +7 -5
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/paths.js +10 -24
- package/dist/resources/extensions/gsd/preferences-diagnostics.js +67 -0
- package/dist/resources/extensions/gsd/preferences.js +161 -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/recovery-classification.js +12 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +8 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +37 -4
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +7 -2
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +10 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +3 -2
- package/dist/resources/extensions/gsd/state-transition-matrix.js +38 -0
- package/dist/resources/extensions/gsd/state.js +13 -5
- package/dist/resources/extensions/gsd/status-guards.js +56 -8
- 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/complete-slice.js +24 -43
- package/dist/resources/extensions/gsd/tools/exec-tool.js +5 -5
- 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/reopen-milestone.js +11 -29
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +14 -33
- package/dist/resources/extensions/gsd/tools/skip-slice.js +18 -36
- 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/undo.js +8 -7
- 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-git-recovery.js +287 -0
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +9 -1
- package/dist/resources/extensions/gsd/worktree-manager.js +45 -28
- package/dist/resources/extensions/gsd/worktree-placement.js +59 -0
- package/dist/resources/extensions/gsd/worktree-reentry.js +12 -8
- package/dist/resources/extensions/gsd/worktree-root.js +17 -6
- package/dist/resources/extensions/gsd/worktree-safety.js +8 -5
- package/dist/resources/extensions/gsd/worktree-session-state.js +12 -10
- 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/resources/skills/gsd-browser/SKILL.md +1 -1
- 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 +12 -12
- 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/api/boot/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js.nft.json +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js.nft.json +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 +12 -12
- package/dist/web/standalone/.next/server/chunks/{5047.js → 5942.js} +2 -2
- 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/dist/worktree-status-banner.js +7 -3
- 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/components/tool-execution.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- 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 +32 -22
- 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/image-models.generated.d.ts +2 -2
- package/packages/pi-ai/dist/image-models.generated.js +6 -6
- package/packages/pi-ai/dist/image-models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +295 -98
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +309 -154
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +3 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +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/bg-shell/utilities.ts +2 -2
- package/src/resources/extensions/claude-code-cli/models.ts +9 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +114 -281
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +268 -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 +3 -1
- package/src/resources/extensions/gsd/auto/loop.ts +83 -61
- package/src/resources/extensions/gsd/auto/orchestrator.ts +164 -17
- package/src/resources/extensions/gsd/auto/phases.ts +45 -4
- 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 +16 -8
- 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 +25 -34
- 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-repair.ts +13 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +53 -306
- package/src/resources/extensions/gsd/auto.ts +27 -17
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +29 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +20 -43
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +147 -153
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +132 -6
- package/src/resources/extensions/gsd/captures.ts +5 -14
- package/src/resources/extensions/gsd/closeout-consistency-gate.ts +27 -5
- package/src/resources/extensions/gsd/closeout-recovery.ts +2 -1
- package/src/resources/extensions/gsd/codebase-generator.ts +9 -5
- package/src/resources/extensions/gsd/commands/catalog.ts +6 -68
- 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/engine.ts +809 -0
- package/src/resources/extensions/gsd/db/queries.ts +453 -0
- package/src/resources/extensions/gsd/db/sql-constants.ts +12 -0
- package/src/resources/extensions/gsd/db/writers/cascades.ts +237 -0
- package/src/resources/extensions/gsd/db/writers/import-restore.ts +310 -0
- package/src/resources/extensions/gsd/db/writers/memory.ts +220 -0
- package/src/resources/extensions/gsd/db/writers/reconcile.ts +500 -0
- package/src/resources/extensions/gsd/db/writers/status.ts +88 -0
- 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-environment.ts +8 -11
- package/src/resources/extensions/gsd/doctor-git-checks.ts +3 -3
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +10 -3
- 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/git-service.ts +1 -0
- package/src/resources/extensions/gsd/gitignore.ts +3 -0
- package/src/resources/extensions/gsd/gsd-db.ts +185 -2373
- package/src/resources/extensions/gsd/guided-flow.ts +81 -561
- 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 +17 -9
- package/src/resources/extensions/gsd/migration-auto-check.ts +30 -5
- 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/model-cost-table.ts +1 -0
- package/src/resources/extensions/gsd/model-router.ts +3 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +4 -5
- package/src/resources/extensions/gsd/parallel-merge.ts +12 -9
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +6 -5
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/paths.ts +9 -22
- 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 +191 -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/recovery-classification.ts +14 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +8 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +36 -4
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +7 -2
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +14 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +6 -2
- package/src/resources/extensions/gsd/state-transition-matrix.ts +42 -0
- package/src/resources/extensions/gsd/state.ts +15 -5
- package/src/resources/extensions/gsd/status-guards.ts +59 -8
- 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 +444 -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-paused-ui-cleanup.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-runtime-state.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-registry.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-worktree-repair.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +22 -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/evidence-xref-gsd-exec.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +33 -1
- 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/integration/auto-worktree-milestone-merge.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/mcp-tool-name.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +143 -1
- 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/recovery-classification-illegal-transition.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +185 -1
- 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/safety-harness-false-positives.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +80 -0
- package/src/resources/extensions/gsd/tests/session-switch-clears-pending-autostart.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +144 -7
- 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/state-transition-matrix.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/status-guards.test.ts +38 -0
- 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-lifecycle.test.ts +41 -4
- package/src/resources/extensions/gsd/tests/worktree-manager.test.ts +43 -1
- package/src/resources/extensions/gsd/tests/worktree-placement.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/worktree-projection-writers.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-reentry.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +3 -1
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +12 -6
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +121 -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/complete-slice.ts +23 -58
- package/src/resources/extensions/gsd/tools/exec-tool.ts +5 -5
- 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/reopen-milestone.ts +11 -38
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +14 -42
- package/src/resources/extensions/gsd/tools/skip-slice.ts +18 -44
- 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/undo.ts +9 -8
- 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-git-recovery.ts +308 -0
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +17 -17
- package/src/resources/extensions/gsd/worktree-manager.ts +47 -28
- package/src/resources/extensions/gsd/worktree-placement.ts +63 -0
- package/src/resources/extensions/gsd/worktree-reentry.ts +10 -7
- package/src/resources/extensions/gsd/worktree-root.ts +17 -6
- package/src/resources/extensions/gsd/worktree-safety.ts +8 -5
- package/src/resources/extensions/gsd/worktree-session-state.ts +12 -10
- 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/src/resources/skills/gsd-browser/SKILL.md +1 -1
- 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 → C24pqUd-aru-l0Dp0gLZP}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Qbr81pQ-pbQXP4bq2VXLv → C24pqUd-aru-l0Dp0gLZP}/_ssgManifest.js +0 -0
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
* This function performs DB writes only. The MCP wrapper in
|
|
10
10
|
* bootstrap/db-tools.ts handles state-cache invalidation and STATE.md rebuild.
|
|
11
11
|
*/
|
|
12
|
-
import {
|
|
13
|
-
import { isClosedStatus } from "../status-guards.js";
|
|
12
|
+
import { isDbAvailable, skipSliceCascade, } from "../gsd-db.js";
|
|
14
13
|
/**
|
|
15
14
|
* Mark a slice as "skipped" and cascade the skip to every non-closed task in
|
|
16
15
|
* that slice. Runs as a single transaction so slice status and task statuses
|
|
@@ -39,40 +38,23 @@ export function handleSkipSlice(params) {
|
|
|
39
38
|
if (!isDbAvailable()) {
|
|
40
39
|
throw new Error("handleSkipSlice: GSD database is not available");
|
|
41
40
|
}
|
|
42
|
-
// ──
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
// ── Atomic skip cascade (guards + writes in one transaction) ────────────
|
|
42
|
+
const outcome = skipSliceCascade(params.milestoneId, params.sliceId);
|
|
43
|
+
if (!outcome.ok) {
|
|
44
|
+
switch (outcome.reason) {
|
|
45
|
+
case "slice-not-found":
|
|
46
|
+
return {
|
|
47
|
+
...base,
|
|
48
|
+
error: `Slice ${params.sliceId} not found in milestone ${params.milestoneId}`,
|
|
49
|
+
errorCode: "slice_not_found",
|
|
50
|
+
};
|
|
51
|
+
case "slice-already-complete":
|
|
52
|
+
return {
|
|
53
|
+
...base,
|
|
54
|
+
error: `Slice ${params.sliceId} is already complete — cannot skip.`,
|
|
55
|
+
errorCode: "already_complete",
|
|
56
|
+
};
|
|
53
57
|
}
|
|
54
|
-
if (slice.status === "complete" || slice.status === "done") {
|
|
55
|
-
guardError = `Slice ${params.sliceId} is already complete — cannot skip.`;
|
|
56
|
-
guardCode = "already_complete";
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
wasAlreadySkipped = slice.status === "skipped";
|
|
60
|
-
if (!wasAlreadySkipped) {
|
|
61
|
-
updateSliceStatus(params.milestoneId, params.sliceId, "skipped");
|
|
62
|
-
}
|
|
63
|
-
// Cascade: mark every non-closed task as skipped so milestone completion
|
|
64
|
-
// doesn't trip the deep-task guard (#4375). Closed tasks (complete/done/
|
|
65
|
-
// skipped) are left untouched — we never downgrade.
|
|
66
|
-
const tasks = getSliceTasks(params.milestoneId, params.sliceId);
|
|
67
|
-
for (const task of tasks) {
|
|
68
|
-
if (!isClosedStatus(task.status)) {
|
|
69
|
-
updateTaskStatus(params.milestoneId, params.sliceId, task.id, "skipped");
|
|
70
|
-
tasksSkipped++;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
if (guardError) {
|
|
75
|
-
return { ...base, error: guardError, errorCode: guardCode ?? undefined };
|
|
76
58
|
}
|
|
77
|
-
return { ...base, tasksSkipped, wasAlreadySkipped };
|
|
59
|
+
return { ...base, tasksSkipped: outcome.tasksSkipped, wasAlreadySkipped: outcome.wasAlreadySkipped };
|
|
78
60
|
}
|
|
@@ -11,10 +11,11 @@
|
|
|
11
11
|
* despite passing validation.
|
|
12
12
|
*/
|
|
13
13
|
import { join } from "node:path";
|
|
14
|
-
import { transaction, insertAssessment, getMilestoneSlices, getMilestone,
|
|
15
|
-
import { gsdProjectionRoot, clearPathCache
|
|
14
|
+
import { transaction, insertAssessment, getMilestoneSlices, getMilestone, } from "../gsd-db.js";
|
|
15
|
+
import { gsdProjectionRoot, clearPathCache } from "../paths.js";
|
|
16
16
|
import { resolveCanonicalMilestoneRoot } from "../worktree-manager.js";
|
|
17
|
-
import {
|
|
17
|
+
import { resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
18
|
+
import { saveFile, clearParseCache } from "../files.js";
|
|
18
19
|
import { invalidateStateCache } from "../state.js";
|
|
19
20
|
import { VALIDATION_VERDICTS, isValidMilestoneVerdict } from "../verdict-parser.js";
|
|
20
21
|
import { insertMilestoneValidationGates } from "../milestone-validation-gates.js";
|
|
@@ -22,7 +23,7 @@ import { logWarning } from "../workflow-logger.js";
|
|
|
22
23
|
import { UokGateRunner } from "../uok/gate-runner.js";
|
|
23
24
|
import { loadEffectiveGSDPreferences } from "../preferences.js";
|
|
24
25
|
import { resolveUokFlags } from "../uok/flags.js";
|
|
25
|
-
import {
|
|
26
|
+
import { applyBrowserEvidenceGate, browserEvidenceGateRequiresAttention, } from "../milestone-validation-evidence.js";
|
|
26
27
|
function isVerificationNotApplicable(value) {
|
|
27
28
|
const v = (value ?? "").toLowerCase().trim().replace(/[.\s]+$/, "");
|
|
28
29
|
if (!v || v === "none")
|
|
@@ -44,80 +45,6 @@ function getRequiredVerificationClasses(milestoneId) {
|
|
|
44
45
|
required.push("UAT");
|
|
45
46
|
return required;
|
|
46
47
|
}
|
|
47
|
-
function hasRuntimeExecutableUatEvidenceText(text) {
|
|
48
|
-
if (!/\buatType:\s*runtime-executable\b/i.test(text))
|
|
49
|
-
return false;
|
|
50
|
-
if (!/\bverdict:\s*PASS\b/i.test(text))
|
|
51
|
-
return false;
|
|
52
|
-
return /^\|\s*[^|\n]+\s*\|\s*runtime\s*\|\s*PASS\s*\|[^|\n]*\bgsd_uat_exec\b/mi.test(text);
|
|
53
|
-
}
|
|
54
|
-
async function browserEvidenceGateRequiresAttention(params, basePath) {
|
|
55
|
-
if (params.verdict !== "pass")
|
|
56
|
-
return false;
|
|
57
|
-
const milestone = getMilestone(params.milestoneId);
|
|
58
|
-
const slices = getMilestoneSlices(params.milestoneId);
|
|
59
|
-
const requirementText = compactTextParts([
|
|
60
|
-
milestone?.vision,
|
|
61
|
-
milestone?.success_criteria,
|
|
62
|
-
milestone?.verification_uat,
|
|
63
|
-
params.successCriteriaChecklist,
|
|
64
|
-
params.verificationClasses,
|
|
65
|
-
...slices.flatMap((slice) => [
|
|
66
|
-
slice.demo,
|
|
67
|
-
slice.goal,
|
|
68
|
-
slice.success_criteria,
|
|
69
|
-
]),
|
|
70
|
-
]);
|
|
71
|
-
if (!hasBrowserRequiredText(requirementText))
|
|
72
|
-
return false;
|
|
73
|
-
// Collect per-slice evidence so the runtime bypass is checked independently
|
|
74
|
-
// for each slice. Concatenating all slices before checking would allow runtime
|
|
75
|
-
// evidence from one slice to cover another slice's browser requirements.
|
|
76
|
-
const sliceEvidencePairs = [];
|
|
77
|
-
for (const slice of slices) {
|
|
78
|
-
const chunks = [];
|
|
79
|
-
const artifactPath = `milestones/${params.milestoneId}/slices/${slice.id}/${slice.id}-ASSESSMENT.md`;
|
|
80
|
-
const artifact = getArtifact(artifactPath);
|
|
81
|
-
if (artifact?.full_content)
|
|
82
|
-
chunks.push(artifact.full_content);
|
|
83
|
-
const assessmentPath = resolveSliceFile(basePath, params.milestoneId, slice.id, "ASSESSMENT");
|
|
84
|
-
const assessmentContent = assessmentPath ? await loadFile(assessmentPath) : null;
|
|
85
|
-
if (assessmentContent)
|
|
86
|
-
chunks.push(assessmentContent);
|
|
87
|
-
sliceEvidencePairs.push({
|
|
88
|
-
sliceRequirementText: compactTextParts([slice.demo, slice.goal, slice.success_criteria]),
|
|
89
|
-
evidenceText: chunks.join("\n\n"),
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
const persistedEvidence = sliceEvidencePairs.map((s) => s.evidenceText).join("\n\n");
|
|
93
|
-
// Runtime bypass: each slice whose own requirement text has browser-observable
|
|
94
|
-
// criteria must have its own runtime-executable UAT evidence. When no individual
|
|
95
|
-
// slice has slice-level browser requirements (e.g., they come from milestone-level
|
|
96
|
-
// fields only), fall back to checking whether any slice has runtime evidence.
|
|
97
|
-
const browserRequiringSlices = sliceEvidencePairs.filter((s) => hasBrowserRequiredText(s.sliceRequirementText));
|
|
98
|
-
const runtimeBypasses = browserRequiringSlices.length > 0
|
|
99
|
-
? browserRequiringSlices.every((s) => hasRuntimeExecutableUatEvidenceText(s.evidenceText))
|
|
100
|
-
: sliceEvidencePairs.some((s) => hasRuntimeExecutableUatEvidenceText(s.evidenceText));
|
|
101
|
-
if (runtimeBypasses)
|
|
102
|
-
return false;
|
|
103
|
-
const validationEvidence = compactTextParts([
|
|
104
|
-
params.successCriteriaChecklist,
|
|
105
|
-
params.verificationClasses,
|
|
106
|
-
params.verdictRationale,
|
|
107
|
-
params.remediationPlan,
|
|
108
|
-
]);
|
|
109
|
-
return !hasBrowserEvidenceText(`${persistedEvidence}\n\n${validationEvidence}`);
|
|
110
|
-
}
|
|
111
|
-
function applyBrowserEvidenceGate(params) {
|
|
112
|
-
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.";
|
|
113
|
-
return {
|
|
114
|
-
...params,
|
|
115
|
-
verdict: "needs-attention",
|
|
116
|
-
verdictRationale: params.verdictRationale.trim()
|
|
117
|
-
? `${params.verdictRationale.trim()}\n\n${note}`
|
|
118
|
-
: note,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
48
|
function renderValidationMarkdown(params) {
|
|
122
49
|
let md = `---
|
|
123
50
|
verdict: ${params.verdict}
|
|
@@ -214,6 +141,16 @@ export async function handleValidateMilestone(params, basePath, opts) {
|
|
|
214
141
|
let projectionStale = false;
|
|
215
142
|
try {
|
|
216
143
|
await saveFile(validationPath, validationMd);
|
|
144
|
+
const projectRoot = resolveWorktreeProjectRoot(basePath);
|
|
145
|
+
if (projectRoot !== artifactBasePath) {
|
|
146
|
+
const projectValidationPath = join(gsdProjectionRoot(projectRoot), "milestones", effectiveParams.milestoneId, `${effectiveParams.milestoneId}-VALIDATION.md`);
|
|
147
|
+
try {
|
|
148
|
+
await saveFile(projectValidationPath, validationMd);
|
|
149
|
+
}
|
|
150
|
+
catch (mirrorErr) {
|
|
151
|
+
logWarning("projection", `validate_milestone project-root VALIDATION mirror failed for ${effectiveParams.milestoneId}`, { error: mirrorErr.message });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
217
154
|
}
|
|
218
155
|
catch (renderErr) {
|
|
219
156
|
projectionStale = true;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// File Purpose: Central UAT mode policy for dispatch, tool presentation, and result validation.
|
|
3
3
|
import { extractUatType } from "./files.js";
|
|
4
4
|
import { hasBrowserRequiredText } from "./browser-evidence.js";
|
|
5
|
+
import { parseMcpToolName } from "./mcp-tool-name.js";
|
|
5
6
|
export const UAT_TYPES = [
|
|
6
7
|
"artifact-driven",
|
|
7
8
|
"browser-executable",
|
|
@@ -80,26 +81,31 @@ export function shouldDispatchUatForContent(content, prefs) {
|
|
|
80
81
|
export function uatTypeIncludesBrowser(uatType) {
|
|
81
82
|
return isUatType(uatType) && UAT_MODE_POLICIES[uatType].browserTools;
|
|
82
83
|
}
|
|
83
|
-
function canonicalPresentedToolName(toolName) {
|
|
84
|
-
if (!toolName.startsWith("mcp__"))
|
|
85
|
-
return toolName;
|
|
86
|
-
const toolSeparator = toolName.indexOf("__", "mcp__".length);
|
|
87
|
-
return toolSeparator >= 0 ? toolName.slice(toolSeparator + 2) : toolName;
|
|
88
|
-
}
|
|
89
84
|
export function isUatBrowserToolName(toolName) {
|
|
90
|
-
|
|
85
|
+
const parsed = parseMcpToolName(toolName);
|
|
86
|
+
const canonicalName = parsed?.toolName ?? toolName;
|
|
87
|
+
if (canonicalName.startsWith("browser_"))
|
|
88
|
+
return true;
|
|
89
|
+
return parsed?.toolName === "*" && parsed.serverName.toLowerCase().includes("browser");
|
|
91
90
|
}
|
|
92
91
|
export function hasUatBrowserToolSurface(activeTools) {
|
|
93
92
|
return Array.isArray(activeTools) && activeTools.some(isUatBrowserToolName);
|
|
94
93
|
}
|
|
94
|
+
export function resolveUatBrowserToolSurface(options) {
|
|
95
|
+
const surfaces = [options.activeTools, options.registeredTools].filter(Array.isArray);
|
|
96
|
+
if (surfaces.length === 0)
|
|
97
|
+
return undefined;
|
|
98
|
+
return [...new Set(surfaces.flat())];
|
|
99
|
+
}
|
|
95
100
|
export function getUatBrowserToolSupportError(options) {
|
|
96
101
|
if (!uatTypeIncludesBrowser(options.uatType))
|
|
97
102
|
return null;
|
|
98
|
-
|
|
103
|
+
const toolSurface = resolveUatBrowserToolSurface(options);
|
|
104
|
+
if (!toolSurface)
|
|
99
105
|
return null;
|
|
100
|
-
if (hasUatBrowserToolSurface(
|
|
106
|
+
if (hasUatBrowserToolSurface(toolSurface))
|
|
101
107
|
return null;
|
|
102
|
-
return `Cannot dispatch browser-backed run-uat for ${options.milestoneId}/${options.sliceId}: UAT mode "${options.uatType}" requires browser tools, but the
|
|
108
|
+
return `Cannot dispatch browser-backed run-uat for ${options.milestoneId}/${options.sliceId}: UAT mode "${options.uatType}" requires browser tools, but the run-uat tool surface has none. Enable browser tools or change the UAT to a runtime-executable Playwright command, then rerun /gsd auto.`;
|
|
103
109
|
}
|
|
104
110
|
export function isPartialEligibleUatType(uatType) {
|
|
105
111
|
return !!uatType && UAT_MODE_POLICIES[uatType].partialEligible;
|
|
@@ -13,7 +13,7 @@ function isNonEmptyString(value) {
|
|
|
13
13
|
function mergeBlockedTools(current, canonical) {
|
|
14
14
|
const merged = new Map();
|
|
15
15
|
for (const entry of [...(current ?? []), ...canonical]) {
|
|
16
|
-
merged.set(canonicalWorkflowToolName(parseMcpToolName(entry.name)?.
|
|
16
|
+
merged.set(canonicalWorkflowToolName(parseMcpToolName(entry.name)?.toolName ?? entry.name), entry);
|
|
17
17
|
}
|
|
18
18
|
return [...merged.values()];
|
|
19
19
|
}
|
|
@@ -204,20 +204,15 @@ function quoteToolNames(toolNames) {
|
|
|
204
204
|
return toolNames.map((toolName) => `"${toolName}"`).join(", ");
|
|
205
205
|
}
|
|
206
206
|
function validateCanonicalPresentation(params) {
|
|
207
|
-
const aliasHints = {
|
|
208
|
-
gsd_save_summary: "gsd_summary_save",
|
|
209
|
-
gsd_complete_task: "gsd_task_complete",
|
|
210
|
-
gsd_complete_slice: "gsd_slice_complete",
|
|
211
|
-
gsd_milestone_complete: "gsd_complete_milestone",
|
|
212
|
-
};
|
|
213
207
|
const errors = [];
|
|
214
208
|
for (const toolName of params.presentation.presentedTools) {
|
|
215
|
-
const baseName = parseMcpToolName(toolName)?.
|
|
216
|
-
const canonical =
|
|
217
|
-
if (canonical)
|
|
209
|
+
const baseName = parseMcpToolName(toolName)?.toolName ?? toolName;
|
|
210
|
+
const canonical = canonicalWorkflowToolName(baseName);
|
|
211
|
+
if (canonical !== baseName) {
|
|
218
212
|
errors.push(`presentation tool "${toolName}" uses an alias; use canonical "${canonical}"`);
|
|
213
|
+
}
|
|
219
214
|
}
|
|
220
|
-
const presentedCanonical = new Set(params.presentation.presentedTools.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.
|
|
215
|
+
const presentedCanonical = new Set(params.presentation.presentedTools.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.toolName ?? toolName)));
|
|
221
216
|
const missingRequiredTools = RUN_UAT_WORKFLOW_TOOL_NAMES.filter((requiredTool) => !presentedCanonical.has(requiredTool));
|
|
222
217
|
if (missingRequiredTools.length === 1) {
|
|
223
218
|
errors.push(`presentation is missing required UAT tool "${missingRequiredTools[0]}"`);
|
|
@@ -227,10 +222,10 @@ function validateCanonicalPresentation(params) {
|
|
|
227
222
|
}
|
|
228
223
|
const forbiddenCanonical = new Set(RUN_UAT_FORBIDDEN_TOOL_NAMES
|
|
229
224
|
.filter((toolName) => !toolName.includes("*"))
|
|
230
|
-
.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.
|
|
225
|
+
.map((toolName) => canonicalWorkflowToolName(parseMcpToolName(toolName)?.toolName ?? toolName)));
|
|
231
226
|
const forbiddenPresentedTools = [];
|
|
232
227
|
for (const toolName of params.presentation.presentedTools) {
|
|
233
|
-
const canonical = canonicalWorkflowToolName(parseMcpToolName(toolName)?.
|
|
228
|
+
const canonical = canonicalWorkflowToolName(parseMcpToolName(toolName)?.toolName ?? toolName);
|
|
234
229
|
if (toolName === "mcp__gsd-workflow__*" || forbiddenCanonical.has(canonical)) {
|
|
235
230
|
forbiddenPresentedTools.push(toolName);
|
|
236
231
|
}
|
|
@@ -241,7 +236,7 @@ function validateCanonicalPresentation(params) {
|
|
|
241
236
|
else if (forbiddenPresentedTools.length > 1) {
|
|
242
237
|
errors.push(`presentation includes forbidden run-uat tools ${quoteToolNames(forbiddenPresentedTools)}`);
|
|
243
238
|
}
|
|
244
|
-
const blockedCanonical = new Set(params.presentation.blockedTools.map((entry) => canonicalWorkflowToolName(parseMcpToolName(entry.name)?.
|
|
239
|
+
const blockedCanonical = new Set(params.presentation.blockedTools.map((entry) => canonicalWorkflowToolName(parseMcpToolName(entry.name)?.toolName ?? entry.name)));
|
|
245
240
|
const missingBlockedTools = ["gsd_exec", "gsd_summary_save", "gsd_save_gate_result"].filter((blockedTool) => !blockedCanonical.has(blockedTool));
|
|
246
241
|
if (missingBlockedTools.length === 1) {
|
|
247
242
|
errors.push(`presentation must record "${missingBlockedTools[0]}" as blocked during run-uat`);
|
|
@@ -11,7 +11,7 @@ import { deriveState } from "./state.js";
|
|
|
11
11
|
import { invalidateAllCaches } from "./cache.js";
|
|
12
12
|
import { gsdRoot, resolveTasksDir, resolveSlicePath, resolveTaskFile, buildTaskFileName, buildSliceFileName } from "./paths.js";
|
|
13
13
|
import { sendDesktopNotification } from "./notifications.js";
|
|
14
|
-
import { getTask, getSlice, getSliceTasks, updateTaskStatus,
|
|
14
|
+
import { getTask, getSlice, getSliceTasks, updateTaskStatus, resetSliceCascade } from "./gsd-db.js";
|
|
15
15
|
import { renderPlanCheckboxes, renderRoadmapCheckboxes } from "./markdown-renderer.js";
|
|
16
16
|
/**
|
|
17
17
|
* Undo the last completed unit: revert git commits,
|
|
@@ -275,20 +275,21 @@ export async function handleResetSlice(args, ctx, _pi, basePath) {
|
|
|
275
275
|
`Run /gsd reset-slice ${rawId} --force to confirm.`, "warning");
|
|
276
276
|
return;
|
|
277
277
|
}
|
|
278
|
-
// Reset all
|
|
279
|
-
|
|
278
|
+
// Reset all task statuses to "pending" and the slice to "active" in one
|
|
279
|
+
// atomic commit (DB is source of truth). Previously a per-task updateTaskStatus
|
|
280
|
+
// loop + a separate updateSliceStatus, which could leave a partial reset if
|
|
281
|
+
// interrupted mid-loop.
|
|
282
|
+
resetSliceCascade(mid, sid);
|
|
283
|
+
// Delete task summary files — projection cleanup, separate from the DB reset.
|
|
284
|
+
const tasksReset = tasks.length;
|
|
280
285
|
let summariesDeleted = 0;
|
|
281
286
|
for (const t of tasks) {
|
|
282
|
-
updateTaskStatus(mid, sid, t.id, "pending");
|
|
283
|
-
tasksReset++;
|
|
284
287
|
const summaryPath = resolveTaskFile(basePath, mid, sid, t.id, "SUMMARY");
|
|
285
288
|
if (summaryPath && existsSync(summaryPath)) {
|
|
286
289
|
unlinkSync(summaryPath);
|
|
287
290
|
summariesDeleted++;
|
|
288
291
|
}
|
|
289
292
|
}
|
|
290
|
-
// Reset slice status
|
|
291
|
-
updateSliceStatus(mid, sid, "active");
|
|
292
293
|
// Delete slice summary and UAT files
|
|
293
294
|
let sliceFilesDeleted = 0;
|
|
294
295
|
const slicePath = resolveSlicePath(basePath, mid, sid);
|
|
@@ -135,37 +135,56 @@ export async function composeUnitContext(unitType, opts) {
|
|
|
135
135
|
const manifest = resolveManifest(unitType);
|
|
136
136
|
if (!manifest)
|
|
137
137
|
return { prepend: "", inline: "" };
|
|
138
|
-
|
|
138
|
+
const composed = await composeDeclaredUnitContext({
|
|
139
|
+
unitType,
|
|
140
|
+
artifacts: {
|
|
141
|
+
inline: manifest.artifacts.inline,
|
|
142
|
+
excerpt: manifest.artifacts.excerpt,
|
|
143
|
+
onDemand: manifest.artifacts.onDemand,
|
|
144
|
+
computed: manifest.artifacts.computed ?? [],
|
|
145
|
+
prepend: manifest.prepend ?? [],
|
|
146
|
+
},
|
|
147
|
+
}, opts);
|
|
148
|
+
return {
|
|
149
|
+
prepend: composed.prepend,
|
|
150
|
+
inline: composed.inline,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
export async function composeContractedUnitContext(contract, opts) {
|
|
154
|
+
return composeDeclaredUnitContext(contract, opts);
|
|
155
|
+
}
|
|
156
|
+
async function composeDeclaredUnitContext(contract, opts) {
|
|
157
|
+
// Single-source `unitType`: contract/manifest selection comes from the
|
|
139
158
|
// function arg, but computed builders read it from `base.unitType`.
|
|
140
|
-
//
|
|
141
|
-
// but a different one in opts.base), the composer would silently
|
|
142
|
-
// mix one unit's manifest with another unit's computed context.
|
|
143
|
-
// Normalize here so the composer dispatches a consistent identity
|
|
144
|
-
// through to every builder.
|
|
159
|
+
// Normalize here so every builder sees the same Unit identity.
|
|
145
160
|
const normalizedOpts = {
|
|
146
161
|
...opts,
|
|
147
|
-
base: { ...opts.base, unitType },
|
|
162
|
+
base: { ...opts.base, unitType: contract.unitType },
|
|
148
163
|
};
|
|
149
|
-
const prependBlocks = await
|
|
164
|
+
const prependBlocks = await runComputedBlocks(contract.artifacts.prepend, normalizedOpts, "prepend");
|
|
150
165
|
const inlineBlocks = [];
|
|
151
|
-
for (const key of
|
|
166
|
+
for (const key of contract.artifacts.inline) {
|
|
152
167
|
if (!normalizedOpts.resolveArtifact)
|
|
153
168
|
break;
|
|
154
169
|
const body = await normalizedOpts.resolveArtifact(key);
|
|
155
|
-
if (body && body.length > 0)
|
|
156
|
-
inlineBlocks.push(body);
|
|
170
|
+
if (body && body.length > 0) {
|
|
171
|
+
inlineBlocks.push({ key, mode: "inline", body });
|
|
172
|
+
}
|
|
157
173
|
}
|
|
158
|
-
for (const key of
|
|
174
|
+
for (const key of contract.artifacts.excerpt) {
|
|
159
175
|
if (!normalizedOpts.resolveExcerpt)
|
|
160
176
|
break;
|
|
161
177
|
const body = await normalizedOpts.resolveExcerpt(key);
|
|
162
|
-
if (body && body.length > 0)
|
|
163
|
-
inlineBlocks.push(body);
|
|
178
|
+
if (body && body.length > 0) {
|
|
179
|
+
inlineBlocks.push({ key, mode: "excerpt", body });
|
|
180
|
+
}
|
|
164
181
|
}
|
|
165
|
-
inlineBlocks.push(...await
|
|
182
|
+
inlineBlocks.push(...await runComputedBlocks(contract.artifacts.computed, normalizedOpts, "computed"));
|
|
166
183
|
return {
|
|
167
|
-
prepend: prependBlocks.join(SECTION_SEPARATOR),
|
|
168
|
-
inline: inlineBlocks.join(SECTION_SEPARATOR),
|
|
184
|
+
prepend: prependBlocks.map((block) => block.body).join(SECTION_SEPARATOR),
|
|
185
|
+
inline: inlineBlocks.map((block) => block.body).join(SECTION_SEPARATOR),
|
|
186
|
+
blocks: [...prependBlocks, ...inlineBlocks],
|
|
187
|
+
onDemand: contract.artifacts.onDemand,
|
|
169
188
|
};
|
|
170
189
|
}
|
|
171
190
|
/**
|
|
@@ -173,7 +192,7 @@ export async function composeUnitContext(unitType, opts) {
|
|
|
173
192
|
* Missing registry entries (manifest declares the id but caller didn't
|
|
174
193
|
* register it) are skipped silently — see composeUnitContext rationale.
|
|
175
194
|
*/
|
|
176
|
-
async function
|
|
195
|
+
async function runComputedBlocks(ids, opts, mode) {
|
|
177
196
|
if (ids.length === 0 || !opts.computed)
|
|
178
197
|
return [];
|
|
179
198
|
const registry = opts.computed;
|
|
@@ -183,8 +202,9 @@ async function runComputed(ids, opts) {
|
|
|
183
202
|
if (!entry)
|
|
184
203
|
continue;
|
|
185
204
|
const body = await entry.build(entry.inputs, opts.base);
|
|
186
|
-
if (body && body.length > 0)
|
|
187
|
-
out.push(body);
|
|
205
|
+
if (body && body.length > 0) {
|
|
206
|
+
out.push({ key: id, mode, body });
|
|
207
|
+
}
|
|
188
208
|
}
|
|
189
209
|
return out;
|
|
190
210
|
}
|
|
@@ -4,7 +4,8 @@ import { atomicWriteSync } from "./atomic-write.js";
|
|
|
4
4
|
import { gsdRoot, relSliceFile, relTaskFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
|
|
5
5
|
import { loadFile, parseTaskPlanMustHaves, countMustHavesMentionedInSummary } from "./files.js";
|
|
6
6
|
import { parseUnitId } from "./unit-id.js";
|
|
7
|
-
import { getTask, isDbAvailable
|
|
7
|
+
import { getTask, isDbAvailable } from "./gsd-db.js";
|
|
8
|
+
import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
|
|
8
9
|
import { isClosedStatus } from "./status-guards.js";
|
|
9
10
|
// Per-record advisory lock — prevents read-modify-write races between
|
|
10
11
|
// concurrent writers updating disjoint fields of the same runtime record.
|
|
@@ -169,7 +170,7 @@ export async function inspectExecuteTaskDurability(basePath, unitId) {
|
|
|
169
170
|
const nextActionAdvanced = !new RegExp(`Execute ${tid}\\b`).test(stateContent);
|
|
170
171
|
let dbComplete = false;
|
|
171
172
|
if (isDbAvailable()) {
|
|
172
|
-
|
|
173
|
+
refreshWorkflowDatabaseFromDisk();
|
|
173
174
|
const task = getTask(mid, sid, tid);
|
|
174
175
|
dbComplete = !!task && isClosedStatus(task.status);
|
|
175
176
|
}
|
|
@@ -60,6 +60,7 @@ export const UNIT_TOOL_CONTRACTS = {
|
|
|
60
60
|
"gsd_milestone_generate_id",
|
|
61
61
|
],
|
|
62
62
|
requiredWorkflowTools: [
|
|
63
|
+
"ask_user_questions",
|
|
63
64
|
"gsd_summary_save",
|
|
64
65
|
"gsd_requirement_save",
|
|
65
66
|
"gsd_requirement_update",
|
|
@@ -69,7 +70,7 @@ export const UNIT_TOOL_CONTRACTS = {
|
|
|
69
70
|
},
|
|
70
71
|
"discuss-slice": {
|
|
71
72
|
allowedGsdTools: ["gsd_summary_save", "gsd_decision_save"],
|
|
72
|
-
requiredWorkflowTools: ["gsd_summary_save"],
|
|
73
|
+
requiredWorkflowTools: ["ask_user_questions", "gsd_summary_save"],
|
|
73
74
|
},
|
|
74
75
|
"validate-milestone": {
|
|
75
76
|
allowedGsdTools: ["gsd_milestone_status", "gsd_validate_milestone", "gsd_reassess_roadmap", "subagent"],
|
|
@@ -177,6 +177,29 @@ export function isAwaitingApprovalBoundary(messages) {
|
|
|
177
177
|
return true;
|
|
178
178
|
return hasApprovalQuestion(text);
|
|
179
179
|
}
|
|
180
|
+
/** True when an assistant message already has an in-flight ask_user_questions tool call. */
|
|
181
|
+
export function messageHasPendingAskUserQuestionsTool(message) {
|
|
182
|
+
if (!message || typeof message !== "object")
|
|
183
|
+
return false;
|
|
184
|
+
const content = message.content;
|
|
185
|
+
if (!Array.isArray(content))
|
|
186
|
+
return false;
|
|
187
|
+
return content.some((block) => {
|
|
188
|
+
if (!block || typeof block !== "object")
|
|
189
|
+
return false;
|
|
190
|
+
// Claude Code marks completion by attaching externalResult, not by setting state.
|
|
191
|
+
// Streaming blocks often carry no state; serverToolUse is the claude-code-cli MCP path.
|
|
192
|
+
const tool = block;
|
|
193
|
+
if (tool.type !== "toolCall" && tool.type !== "serverToolUse")
|
|
194
|
+
return false;
|
|
195
|
+
const name = String(tool.name ?? "").toLowerCase();
|
|
196
|
+
if (!name.includes("ask_user_questions"))
|
|
197
|
+
return false;
|
|
198
|
+
if (tool.externalResult !== undefined)
|
|
199
|
+
return false;
|
|
200
|
+
return tool.state !== "completed" && tool.state !== "done";
|
|
201
|
+
});
|
|
202
|
+
}
|
|
180
203
|
export function shouldPauseForUserApprovalQuestion(unitType, messages) {
|
|
181
204
|
if (!unitType || !USER_APPROVAL_UNIT_TYPES.has(unitType))
|
|
182
205
|
return false;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { getAutoWorktreePath, isInAutoWorktree } from "./auto-worktree.js";
|
|
5
5
|
import { ensureDbOpen } from "./bootstrap/dynamic-tools.js";
|
|
6
|
+
import { refreshWorkflowDatabaseFromDisk } from "./db-workspace.js";
|
|
6
7
|
import { getIsolationMode } from "./preferences.js";
|
|
7
8
|
import { deriveState } from "./state.js";
|
|
8
9
|
import { detectWorktreeName } from "./worktree.js";
|
|
@@ -72,6 +73,7 @@ export function formatValidationBlockedMessage(state, attemptedCommand = "") {
|
|
|
72
73
|
}
|
|
73
74
|
export async function getValidationBlockMessageForBase(base, attemptedCommand = "") {
|
|
74
75
|
await ensureDbOpen(base);
|
|
76
|
+
refreshWorkflowDatabaseFromDisk();
|
|
75
77
|
let state = await deriveState(base);
|
|
76
78
|
if (state.activeMilestone &&
|
|
77
79
|
getIsolationMode(base) === "worktree" &&
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Web-app detection and Playwright/UAT guidance for planning and slice closeout.
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { detectWebApp } from "../browser-tools/web-app-detect.js";
|
|
6
|
+
export { detectWebApp };
|
|
7
|
+
function readPackageJson(projectRoot) {
|
|
8
|
+
const packageJsonPath = resolve(projectRoot, "package.json");
|
|
9
|
+
if (!existsSync(packageJsonPath))
|
|
10
|
+
return null;
|
|
11
|
+
try {
|
|
12
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
13
|
+
return parsed && typeof parsed === "object" ? parsed : null;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function hasPlaywrightTestDependency(projectRoot) {
|
|
20
|
+
const pkg = readPackageJson(projectRoot);
|
|
21
|
+
if (!pkg)
|
|
22
|
+
return false;
|
|
23
|
+
const names = [
|
|
24
|
+
...Object.keys(pkg.dependencies ?? {}),
|
|
25
|
+
...Object.keys(pkg.devDependencies ?? {}),
|
|
26
|
+
];
|
|
27
|
+
return names.some((name) => name === "playwright" || name === "@playwright/test");
|
|
28
|
+
}
|
|
29
|
+
export function findPlaywrightTestScript(projectRoot) {
|
|
30
|
+
const pkg = readPackageJson(projectRoot);
|
|
31
|
+
if (!pkg?.scripts)
|
|
32
|
+
return null;
|
|
33
|
+
for (const [name, value] of Object.entries(pkg.scripts)) {
|
|
34
|
+
if (typeof value !== "string")
|
|
35
|
+
continue;
|
|
36
|
+
if (/\bplaywright\s+test\b/.test(value)) {
|
|
37
|
+
return `npm run ${name}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Markdown block injected into plan/complete-slice prompts when the project
|
|
44
|
+
* looks browser-facing. Returns null for CLI/library-only repos.
|
|
45
|
+
*/
|
|
46
|
+
export function buildWebAppUatGuidanceBlock(projectRoot) {
|
|
47
|
+
if (!detectWebApp(projectRoot))
|
|
48
|
+
return null;
|
|
49
|
+
const playwrightScript = findPlaywrightTestScript(projectRoot);
|
|
50
|
+
const hasPlaywright = hasPlaywrightTestDependency(projectRoot) || playwrightScript !== null;
|
|
51
|
+
const lines = [
|
|
52
|
+
"### Web App UAT (detected)",
|
|
53
|
+
"",
|
|
54
|
+
"This project looks browser-facing. GSD exposes Playwright-backed `browser_*` tools by default for run-uat.",
|
|
55
|
+
"",
|
|
56
|
+
"**UAT modes (pick one per slice — do not use `artifact-driven` for browser steps):**",
|
|
57
|
+
"- `browser-executable` — navigate to `http://localhost:…`, click, screenshot, assert via `browser_*` tools during run-uat",
|
|
58
|
+
"- `runtime-executable` — run an automated browser test command via `gsd_uat_exec` (for example `npx playwright test`)",
|
|
59
|
+
"- `mixed` / `live-runtime` — combine runtime startup checks with interactive browser verification",
|
|
60
|
+
"",
|
|
61
|
+
"**Planning / closeout rules:**",
|
|
62
|
+
"- Preconditions must name the dev-server command and URL (for example `npm run dev` → `http://localhost:3000`)",
|
|
63
|
+
"- Slice Verification and UAT test cases must not say \"open in browser\" under `artifact-driven` — complete-slice rejects that",
|
|
64
|
+
"- Milestone `Verification Classes` → UAT row must describe browser-observable acceptance, not \"manual spot check\" alone",
|
|
65
|
+
];
|
|
66
|
+
if (hasPlaywright) {
|
|
67
|
+
lines.push("", "**Playwright:** dependency detected.");
|
|
68
|
+
if (playwrightScript) {
|
|
69
|
+
lines.push(`- Prefer slice verification and runtime-executable UAT referencing \`${playwrightScript}\` or a focused \`npx playwright test <spec>\` command`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
lines.push("- Prefer runtime-executable UAT with `npx playwright test` (or a focused spec path) when UI behavior is covered by specs");
|
|
73
|
+
}
|
|
74
|
+
lines.push("- Name concrete spec paths in slice Verification (for example `e2e/smoke.spec.ts`)");
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
lines.push("", "**Playwright scaffolding (first UI slice):** no `playwright` / `@playwright/test` dependency yet.", "- Add a planning task that installs Playwright, adds `playwright.config.ts`, and creates a minimal smoke spec (for example `e2e/smoke.spec.ts`)", "- Task `verify` should run `npx playwright test` (or the focused spec) with a safe, simple command", "- Until specs exist, use `browser-executable` UAT with localhost preconditions and interactive `browser_*` checks at slice closeout");
|
|
78
|
+
}
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|