@opengsd/gsd-pi 1.2.0-dev.e8563f58 → 1.2.0-dev.fbdca60b
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-model-override.d.ts +15 -0
- package/dist/cli-model-override.js +21 -0
- package/dist/cli.js +1 -18
- package/dist/loader.js +6 -4
- package/dist/register-agent-bundles.d.ts +11 -2
- package/dist/register-agent-bundles.js +18 -4
- package/dist/resource-loader.d.ts +10 -5
- package/dist/resource-loader.js +121 -6
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/ask-user-questions.js +3 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +447 -215
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +33 -1
- package/dist/resources/extensions/gsd/auto/closeout.js +215 -0
- package/dist/resources/extensions/gsd/auto/dispatch-history.js +21 -6
- package/dist/resources/extensions/gsd/auto/dispatch.js +365 -0
- package/dist/resources/extensions/gsd/auto/finalize.js +347 -0
- package/dist/resources/extensions/gsd/auto/loop.js +4 -1
- package/dist/resources/extensions/gsd/auto/milestone-lease-reclaim.js +56 -0
- package/dist/resources/extensions/gsd/auto/orchestrator.js +85 -15
- package/dist/resources/extensions/gsd/auto/phase-helpers.js +146 -0
- package/dist/resources/extensions/gsd/auto/phases.js +17 -2329
- package/dist/resources/extensions/gsd/auto/pre-dispatch.js +534 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto/unit-phase.js +694 -0
- package/dist/resources/extensions/gsd/auto/workflow-unit-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto/worktree-safety-phase.js +125 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +3 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +11 -2
- package/dist/resources/extensions/gsd/auto-post-unit.js +18 -6
- package/dist/resources/extensions/gsd/auto-start.js +23 -3
- package/dist/resources/extensions/gsd/auto-unit-closeout.js +45 -21
- package/dist/resources/extensions/gsd/auto-verification.js +14 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +15 -2
- package/dist/resources/extensions/gsd/auto.js +45 -2
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -7
- package/dist/resources/extensions/gsd/commands/context.js +16 -2
- package/dist/resources/extensions/gsd/commands-mcp-status.js +2 -2
- package/dist/resources/extensions/gsd/commands-workflow-templates.js +9 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +8 -3
- package/dist/resources/extensions/gsd/db/engine.js +24 -6
- package/dist/resources/extensions/gsd/db/queries.js +30 -0
- package/dist/resources/extensions/gsd/db-migration-backup.js +51 -8
- package/dist/resources/extensions/gsd/db-transaction.js +27 -23
- package/dist/resources/extensions/gsd/db-writer.js +8 -17
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +5 -5
- package/dist/resources/extensions/gsd/doctor-environment.js +256 -125
- package/dist/resources/extensions/gsd/gsd-db.js +15 -20
- package/dist/resources/extensions/gsd/guided-flow.js +93 -4
- package/dist/resources/extensions/gsd/health-widget.js +87 -28
- package/dist/resources/extensions/gsd/mcp-bridge.js +10 -0
- package/dist/resources/extensions/gsd/memory-relations.js +1 -1
- package/dist/resources/extensions/gsd/milestone-planning-persistence.js +2 -2
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +3 -5
- package/dist/resources/extensions/gsd/milestone-settlement.js +2 -2
- package/dist/resources/extensions/gsd/notifications.js +12 -7
- package/dist/resources/extensions/gsd/projection-flush.js +7 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/dist/resources/extensions/gsd/prompts/run-uat.md +3 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/dist/resources/extensions/gsd/roadmap-slices.js +25 -3
- package/dist/resources/extensions/gsd/session-lock.js +1 -1
- package/dist/resources/extensions/gsd/skill-activation.js +3 -6
- package/dist/resources/extensions/gsd/state.js +6 -2
- package/dist/resources/extensions/gsd/tool-contract.js +14 -3
- package/dist/resources/extensions/gsd/tool-surface-readiness.js +83 -31
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +3 -2
- package/dist/resources/extensions/gsd/tools/complete-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/complete-task.js +65 -2
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/plan-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +2 -2
- package/dist/resources/extensions/gsd/tools/reopen-task.js +2 -2
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +1 -1
- package/dist/resources/extensions/gsd/unit-registry.js +34 -4
- package/dist/resources/extensions/gsd/verification-verdict.js +2 -1
- package/dist/resources/extensions/gsd/workflow-event-ledger.js +91 -0
- package/dist/resources/extensions/gsd/workflow-event-vocabulary.js +46 -0
- package/dist/resources/extensions/gsd/workflow-events.js +6 -18
- package/dist/resources/extensions/gsd/workflow-mcp-auto-prep.js +2 -0
- package/dist/resources/extensions/gsd/workflow-mcp-readiness-cache.js +105 -0
- package/dist/resources/extensions/gsd/workflow-reconcile.js +21 -56
- package/dist/resources/extensions/gsd/worktree-manager.js +7 -1
- package/dist/resources/extensions/gsd/worktree-safety.js +28 -26
- package/dist/resources/extensions/gsd/worktree.js +8 -1
- package/dist/resources/extensions/mcp-client/manager.js +6 -1
- package/dist/resources/skills/create-skill/SKILL.md +3 -0
- package/dist/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/runtime-checks.d.ts +10 -0
- package/dist/runtime-checks.js +27 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- 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 +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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 +7 -7
- package/dist/web/standalone/.next/server/chunks/{5942.js → 1128.js} +1 -1
- 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/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/node_modules/node-pty/build/Makefile +1 -1
- package/package.json +3 -3
- 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/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +6 -4
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +10 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.d.ts +8 -0
- 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 +50 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts +2 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +34 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js +17 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js +4 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-settings.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/README.md +12 -3
- package/packages/mcp-server/dist/cli-runner.d.ts +40 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -0
- package/packages/mcp-server/dist/cli-runner.js +137 -0
- package/packages/mcp-server/dist/cli-runner.js.map +1 -0
- package/packages/mcp-server/dist/cli.js +2 -53
- package/packages/mcp-server/dist/cli.js.map +1 -1
- package/packages/mcp-server/dist/pid-registry.d.ts +46 -0
- package/packages/mcp-server/dist/pid-registry.d.ts.map +1 -0
- package/packages/mcp-server/dist/pid-registry.js +459 -0
- package/packages/mcp-server/dist/pid-registry.js.map +1 -0
- package/packages/mcp-server/dist/probe-mode.d.ts +4 -0
- package/packages/mcp-server/dist/probe-mode.d.ts.map +1 -0
- package/packages/mcp-server/dist/probe-mode.js +10 -0
- package/packages/mcp-server/dist/probe-mode.js.map +1 -0
- package/packages/mcp-server/dist/stdio-watchdog.d.ts +8 -0
- package/packages/mcp-server/dist/stdio-watchdog.d.ts.map +1 -0
- package/packages/mcp-server/dist/stdio-watchdog.js +40 -0
- package/packages/mcp-server/dist/stdio-watchdog.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +62 -43
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +5 -5
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +43 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +11 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +45 -17
- package/packages/pi-coding-agent/dist/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/README.md +15 -0
- package/packages/pi-tui/dist/index.d.ts +2 -2
- package/packages/pi-tui/dist/index.d.ts.map +1 -1
- package/packages/pi-tui/dist/index.js +2 -2
- package/packages/pi-tui/dist/index.js.map +1 -1
- package/packages/pi-tui/dist/terminal-image.d.ts +33 -0
- package/packages/pi-tui/dist/terminal-image.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal-image.js +54 -2
- package/packages/pi-tui/dist/terminal-image.js.map +1 -1
- package/packages/pi-tui/dist/terminal.d.ts +12 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +70 -25
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +15 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +106 -21
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/dist/utils.d.ts.map +1 -1
- package/packages/pi-tui/dist/utils.js +110 -36
- package/packages/pi-tui/dist/utils.js.map +1 -1
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +45 -17
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/ask-user-questions.ts +7 -2
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +531 -226
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +672 -7
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +38 -1
- package/src/resources/extensions/gsd/auto/closeout.ts +309 -0
- package/src/resources/extensions/gsd/auto/dispatch-history.ts +22 -6
- package/src/resources/extensions/gsd/auto/dispatch.ts +449 -0
- package/src/resources/extensions/gsd/auto/finalize.ts +445 -0
- package/src/resources/extensions/gsd/auto/loop.ts +4 -1
- package/src/resources/extensions/gsd/auto/milestone-lease-reclaim.ts +74 -0
- package/src/resources/extensions/gsd/auto/orchestrator.ts +95 -15
- package/src/resources/extensions/gsd/auto/phase-helpers.ts +199 -0
- package/src/resources/extensions/gsd/auto/phases.ts +58 -3022
- package/src/resources/extensions/gsd/auto/pre-dispatch.ts +704 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/unit-phase.ts +910 -0
- package/src/resources/extensions/gsd/auto/workflow-unit-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto/worktree-safety-phase.ts +149 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +10 -16
- package/src/resources/extensions/gsd/auto-dispatch.ts +11 -10
- package/src/resources/extensions/gsd/auto-post-unit.ts +21 -6
- package/src/resources/extensions/gsd/auto-start.ts +24 -4
- package/src/resources/extensions/gsd/auto-unit-closeout.ts +83 -28
- package/src/resources/extensions/gsd/auto-verification.ts +18 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +15 -2
- package/src/resources/extensions/gsd/auto.ts +56 -2
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +56 -6
- package/src/resources/extensions/gsd/commands/context.ts +16 -2
- package/src/resources/extensions/gsd/commands-mcp-status.ts +2 -2
- package/src/resources/extensions/gsd/commands-workflow-templates.ts +11 -4
- package/src/resources/extensions/gsd/crash-recovery.ts +10 -2
- package/src/resources/extensions/gsd/db/engine.ts +26 -6
- package/src/resources/extensions/gsd/db/queries.ts +29 -0
- package/src/resources/extensions/gsd/db-migration-backup.ts +56 -7
- package/src/resources/extensions/gsd/db-transaction.ts +37 -20
- package/src/resources/extensions/gsd/db-writer.ts +11 -19
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor-environment.ts +267 -142
- package/src/resources/extensions/gsd/gsd-db.ts +15 -19
- package/src/resources/extensions/gsd/guided-flow.ts +145 -24
- package/src/resources/extensions/gsd/health-widget.ts +91 -27
- package/src/resources/extensions/gsd/mcp-bridge.ts +39 -0
- package/src/resources/extensions/gsd/memory-relations.ts +1 -1
- package/src/resources/extensions/gsd/milestone-planning-persistence.ts +2 -2
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +3 -6
- package/src/resources/extensions/gsd/milestone-settlement.ts +2 -2
- package/src/resources/extensions/gsd/notifications.ts +13 -6
- package/src/resources/extensions/gsd/projection-flush.ts +20 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +1 -1
- package/src/resources/extensions/gsd/prompts/refine-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/rewrite-docs.md +1 -1
- package/src/resources/extensions/gsd/prompts/run-uat.md +3 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/workflow-start.md +2 -1
- package/src/resources/extensions/gsd/roadmap-slices.ts +28 -3
- package/src/resources/extensions/gsd/session-lock.ts +1 -1
- package/src/resources/extensions/gsd/skill-activation.ts +3 -6
- package/src/resources/extensions/gsd/state.ts +7 -1
- package/src/resources/extensions/gsd/tests/auto-abort-pause-regression.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-blocked-remediation-message.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +206 -22
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +76 -12
- package/src/resources/extensions/gsd/tests/auto-pause-double-entry-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +77 -1
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-remote-session-lock-cleanup.test.ts +65 -3
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +236 -0
- package/src/resources/extensions/gsd/tests/auto-unit-closeout.test.ts +169 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +141 -5
- package/src/resources/extensions/gsd/tests/db-migration-backup.test.ts +68 -19
- package/src/resources/extensions/gsd/tests/db-transaction.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +12 -2
- package/src/resources/extensions/gsd/tests/dispatch-history.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +8 -0
- package/src/resources/extensions/gsd/tests/engine-interfaces-contract.test.ts +117 -91
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/guided-dispatch-root.test.ts +18 -6
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-environment-async.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +47 -16
- package/src/resources/extensions/gsd/tests/mcp-readiness-preflight.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +6 -5
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-report-path.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-settlement.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/notifications.test.ts +64 -9
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/phases-terminal-complete-idempotent.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +63 -2
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +10 -2
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +2 -4
- package/src/resources/extensions/gsd/tests/remote-notification-from-desktop.test.ts +31 -81
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/runtime-invariant-modules.test.ts +26 -2
- package/src/resources/extensions/gsd/tests/single-writer-invariant.test.ts +170 -48
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -17
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +7 -3
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/teardown-chdir-failure-clears-registry.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/tool-surface-readiness.test.ts +184 -10
- package/src/resources/extensions/gsd/tests/tool-unavailable-retry.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/transport-gate-double-complete.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/uok-audit-unified.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-verdict.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp-readiness-cache.test.ts +119 -0
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/workflow-phase-contract-matrix.test.ts +332 -0
- package/src/resources/extensions/gsd/tests/workflow-reconcile.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/worktree-safety-phase.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/worktree-safety.test.ts +72 -0
- package/src/resources/extensions/gsd/tests/worktree-teardown-safety.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/worktree.test.ts +18 -0
- package/src/resources/extensions/gsd/tool-contract.ts +38 -3
- package/src/resources/extensions/gsd/tool-surface-readiness.ts +126 -19
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +3 -2
- package/src/resources/extensions/gsd/tools/complete-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/complete-task.ts +90 -2
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +2 -2
- package/src/resources/extensions/gsd/tools/reopen-task.ts +2 -2
- package/src/resources/extensions/gsd/tools/replan-slice.ts +2 -2
- package/src/resources/extensions/gsd/unit-context-composer.ts +1 -1
- package/src/resources/extensions/gsd/unit-registry.ts +34 -4
- package/src/resources/extensions/gsd/verification-verdict.ts +4 -2
- package/src/resources/extensions/gsd/workflow-event-ledger.ts +131 -0
- package/src/resources/extensions/gsd/workflow-event-vocabulary.ts +59 -0
- package/src/resources/extensions/gsd/workflow-events.ts +12 -20
- package/src/resources/extensions/gsd/workflow-mcp-auto-prep.ts +2 -0
- package/src/resources/extensions/gsd/workflow-mcp-readiness-cache.ts +150 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +29 -62
- package/src/resources/extensions/gsd/worktree-manager.ts +6 -1
- package/src/resources/extensions/gsd/worktree-safety.ts +41 -39
- package/src/resources/extensions/gsd/worktree.ts +7 -1
- package/src/resources/extensions/mcp-client/manager.ts +7 -1
- package/src/resources/skills/create-skill/SKILL.md +3 -0
- package/src/resources/skills/create-skill/references/skill-structure.md +1 -0
- package/dist/resources/skills/gsd-browser/SKILL.md +0 -41
- package/src/resources/skills/gsd-browser/SKILL.md +0 -41
- /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{LDHRKiRBIVZmiuMjrL1Vy → 2T9IOdiiM3o3gZ4UbPi8E}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
// Project/App: gsd-pi
|
|
2
|
+
// File Purpose: Regression tests for milestone closeout settlement guidance.
|
|
3
|
+
|
|
4
|
+
import test, { afterEach } from "node:test";
|
|
5
|
+
import assert from "node:assert/strict";
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
8
|
+
import { tmpdir } from "node:os";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
|
|
11
|
+
import { evaluateAllCompleteSettlement } from "../milestone-settlement.ts";
|
|
12
|
+
import { resolveExpectedArtifactPath } from "../auto-artifact-paths.ts";
|
|
13
|
+
import {
|
|
14
|
+
closeDatabase,
|
|
15
|
+
insertAssessment,
|
|
16
|
+
insertMilestone,
|
|
17
|
+
insertSlice,
|
|
18
|
+
insertTask,
|
|
19
|
+
openDatabase,
|
|
20
|
+
} from "../gsd-db.ts";
|
|
21
|
+
|
|
22
|
+
let base = "";
|
|
23
|
+
|
|
24
|
+
function runGit(cwd: string, args: string[]): void {
|
|
25
|
+
execFileSync("git", args, { cwd, stdio: "ignore" });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function initRepo(root: string): void {
|
|
29
|
+
runGit(root, ["init", "-b", "main"]);
|
|
30
|
+
runGit(root, ["config", "user.email", "test@example.com"]);
|
|
31
|
+
runGit(root, ["config", "user.name", "Test User"]);
|
|
32
|
+
writeFileSync(join(root, "README.md"), "# fixture\n");
|
|
33
|
+
runGit(root, ["add", "."]);
|
|
34
|
+
runGit(root, ["commit", "-m", "chore: init"]);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function seedClosedMilestone(root: string, worktree: string): void {
|
|
38
|
+
mkdirSync(join(root, ".gsd"), { recursive: true });
|
|
39
|
+
openDatabase(join(root, ".gsd", "gsd.db"));
|
|
40
|
+
insertMilestone({ id: "M001", title: "Milestone One", status: "complete" });
|
|
41
|
+
insertSlice({ id: "S01", milestoneId: "M001", title: "Slice One", status: "complete" });
|
|
42
|
+
insertTask({
|
|
43
|
+
id: "T01",
|
|
44
|
+
sliceId: "S01",
|
|
45
|
+
milestoneId: "M001",
|
|
46
|
+
title: "Task One",
|
|
47
|
+
status: "complete",
|
|
48
|
+
verificationResult: "passed",
|
|
49
|
+
});
|
|
50
|
+
insertAssessment({
|
|
51
|
+
path: ".gsd/milestones/M001/M001-VALIDATION.md",
|
|
52
|
+
milestoneId: "M001",
|
|
53
|
+
status: "pass",
|
|
54
|
+
scope: "milestone-validation",
|
|
55
|
+
fullContent: "verdict: pass\n",
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
mkdirSync(join(worktree, ".gsd", "milestones", "M001"), { recursive: true });
|
|
59
|
+
const summaryPath = resolveExpectedArtifactPath("complete-milestone", "M001", worktree);
|
|
60
|
+
assert.ok(summaryPath, "complete-milestone summary path should resolve");
|
|
61
|
+
mkdirSync(dirname(summaryPath), { recursive: true });
|
|
62
|
+
writeFileSync(summaryPath, "# Milestone One\n\nComplete.\n");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
try { closeDatabase(); } catch { /* ignore */ }
|
|
67
|
+
if (base) rmSync(base, { recursive: true, force: true });
|
|
68
|
+
base = "";
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("merge-pending settlement routes back to complete-milestone dispatch without manual merge guidance", () => {
|
|
72
|
+
base = mkdtempSync(join(tmpdir(), "gsd-milestone-settlement-"));
|
|
73
|
+
initRepo(base);
|
|
74
|
+
const worktree = join(base, ".gsd", "worktrees", "M001");
|
|
75
|
+
mkdirSync(dirname(worktree), { recursive: true });
|
|
76
|
+
runGit(base, ["worktree", "add", "-b", "milestone/M001", worktree, "HEAD"]);
|
|
77
|
+
seedClosedMilestone(base, worktree);
|
|
78
|
+
|
|
79
|
+
const result = evaluateAllCompleteSettlement({
|
|
80
|
+
milestoneId: "M001",
|
|
81
|
+
statePhase: "complete",
|
|
82
|
+
basePath: worktree,
|
|
83
|
+
originalBasePath: base,
|
|
84
|
+
milestoneMerged: false,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
assert.equal(result.ok, false);
|
|
88
|
+
assert.equal(result.reason, "merge-pending");
|
|
89
|
+
assert.equal(result.nextAction, "Retry `/gsd dispatch complete-milestone M001`.");
|
|
90
|
+
assert.doesNotMatch(result.message, /merge manually/i);
|
|
91
|
+
assert.doesNotMatch(result.nextAction, /merge manually/i);
|
|
92
|
+
});
|
|
@@ -14,7 +14,7 @@ import { readFileSync, mkdtempSync, mkdirSync, writeFileSync, existsSync, rmSync
|
|
|
14
14
|
import { join } from "node:path";
|
|
15
15
|
import { tmpdir } from "node:os";
|
|
16
16
|
import { AutoSession } from "../auto/session.ts";
|
|
17
|
-
import { runPreDispatch } from "../auto/
|
|
17
|
+
import { runPreDispatch } from "../auto/pre-dispatch.ts";
|
|
18
18
|
|
|
19
19
|
test("milestone transition archives completed units and rebuilds state", async () => {
|
|
20
20
|
const tempDir = realpathSync(mkdtempSync(join(tmpdir(), "gsd-cu-reset-")));
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import test from "node:test";
|
|
2
2
|
import assert from "node:assert/strict";
|
|
3
|
-
import {
|
|
3
|
+
import { mkdtempSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { tmpdir } from "node:os";
|
|
5
|
+
import { join } from "node:path";
|
|
4
6
|
|
|
7
|
+
import { playQuestionBell } from "../../ask-user-questions.js";
|
|
8
|
+
import { stopAuto } from "../auto.js";
|
|
9
|
+
import { autoSession } from "../auto-runtime-state.js";
|
|
5
10
|
import {
|
|
6
11
|
buildDesktopNotificationCommand,
|
|
7
12
|
shouldSendDesktopNotification,
|
|
@@ -58,18 +63,68 @@ test("playNotificationBell is silent when disabled", () => {
|
|
|
58
63
|
assert.equal(output, "");
|
|
59
64
|
});
|
|
60
65
|
|
|
61
|
-
test("
|
|
62
|
-
|
|
66
|
+
test("playQuestionBell writes a terminal bell when local bell is enabled", async () => {
|
|
67
|
+
let output = "";
|
|
68
|
+
const stream = { write: (chunk: string) => { output += chunk; } };
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
70
|
+
await playQuestionBell({ enabled: true, local_bell: true }, stream);
|
|
71
|
+
|
|
72
|
+
assert.equal(output, "\u0007");
|
|
66
73
|
});
|
|
67
74
|
|
|
68
|
-
test("
|
|
69
|
-
|
|
75
|
+
test("playQuestionBell is silent when local bell is disabled", async () => {
|
|
76
|
+
let output = "";
|
|
77
|
+
const stream = { write: (chunk: string) => { output += chunk; } };
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
|
|
79
|
+
await playQuestionBell({ enabled: true, local_bell: false }, stream);
|
|
80
|
+
|
|
81
|
+
assert.equal(output, "");
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("stopAuto plays local bell for auto-mode stop notifications", async () => {
|
|
85
|
+
const base = mkdtempSync(join(tmpdir(), "gsd-stop-bell-"));
|
|
86
|
+
const previousCwd = process.cwd();
|
|
87
|
+
const previousStderrWrite = process.stderr.write;
|
|
88
|
+
const previousStderrIsTTY = process.stderr.isTTY;
|
|
89
|
+
let bellOutput = "";
|
|
90
|
+
|
|
91
|
+
autoSession.reset();
|
|
92
|
+
autoSession.active = true;
|
|
93
|
+
autoSession.basePath = base;
|
|
94
|
+
|
|
95
|
+
mkdirSync(join(base, ".gsd"), { recursive: true });
|
|
96
|
+
writeFileSync(
|
|
97
|
+
join(base, ".gsd", "PREFERENCES.md"),
|
|
98
|
+
"---\nnotifications:\n enabled: true\n local_bell: true\n---\n",
|
|
99
|
+
"utf-8",
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
process.stderr.isTTY = true;
|
|
103
|
+
process.stderr.write = ((chunk: string | Uint8Array) => {
|
|
104
|
+
if (typeof chunk === "string") {
|
|
105
|
+
bellOutput += chunk;
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}) as typeof process.stderr.write;
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
await stopAuto(
|
|
112
|
+
{ hasUI: false, ui: { notify: () => {}, setStatus: () => {}, setWidget: () => {}, setHeader: () => {} } } as any,
|
|
113
|
+
undefined,
|
|
114
|
+
"test stop",
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
assert.ok(
|
|
118
|
+
bellOutput.includes("\u0007"),
|
|
119
|
+
"stopAuto must write a terminal bell to stderr when the local bell preference is enabled",
|
|
120
|
+
);
|
|
121
|
+
} finally {
|
|
122
|
+
process.stderr.write = previousStderrWrite;
|
|
123
|
+
process.stderr.isTTY = previousStderrIsTTY;
|
|
124
|
+
autoSession.reset();
|
|
125
|
+
process.chdir(previousCwd);
|
|
126
|
+
rmSync(base, { recursive: true, force: true });
|
|
127
|
+
}
|
|
73
128
|
});
|
|
74
129
|
|
|
75
130
|
test("buildDesktopNotificationCommand falls back to osascript on macOS when terminal-notifier is absent", () => {
|
|
@@ -29,8 +29,8 @@ import {
|
|
|
29
29
|
|
|
30
30
|
const SKILL_NAME = "testskill";
|
|
31
31
|
const COMPLETE_SLICE_SKILL_NAME = "complete-slice-policies";
|
|
32
|
-
const SKILL_ACTIVATION_SUBSTRING = `
|
|
33
|
-
const COMPLETE_SLICE_SKILL_ACTIVATION_SUBSTRING = `
|
|
32
|
+
const SKILL_ACTIVATION_SUBSTRING = `Read the installed '${SKILL_NAME}' skill file from <available_skills>`;
|
|
33
|
+
const COMPLETE_SLICE_SKILL_ACTIVATION_SUBSTRING = `Read the installed '${COMPLETE_SLICE_SKILL_NAME}' skill file from <available_skills>`;
|
|
34
34
|
|
|
35
35
|
const tmpDirs: string[] = [];
|
|
36
36
|
let savedCwd: string | undefined;
|
|
@@ -28,6 +28,11 @@ const BANNED_DECISION_PATHS = new Set([
|
|
|
28
28
|
"gsd/auto-post-unit.ts",
|
|
29
29
|
"gsd/milestone-closeout.ts",
|
|
30
30
|
"gsd/auto/phases.ts",
|
|
31
|
+
"gsd/auto/pre-dispatch.ts",
|
|
32
|
+
"gsd/auto/dispatch.ts",
|
|
33
|
+
"gsd/auto/unit-phase.ts",
|
|
34
|
+
"gsd/auto/finalize.ts",
|
|
35
|
+
"gsd/auto/closeout.ts",
|
|
31
36
|
"gsd/auto/orchestrator.ts",
|
|
32
37
|
"gsd/auto/loop.ts",
|
|
33
38
|
"gsd/tools/complete-slice.ts",
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* phases-terminal-complete-idempotent.test.ts — Regression test for the
|
|
3
|
+
* milestone-completion double-closeout guard in `runPreDispatch`.
|
|
4
|
+
*
|
|
5
|
+
* When `runPreDispatch` observes that the active milestone (or the last one
|
|
6
|
+
* the session was working on) has already been closed by another session,
|
|
7
|
+
* the loop must exit cleanly with `{ action: "break", reason:
|
|
8
|
+
* "milestone-complete" }` and must NOT replay merge, desktop / cmux
|
|
9
|
+
* notifications, unit closeout, or `stopAuto`.
|
|
10
|
+
*
|
|
11
|
+
* There are two `deriveState` shapes the guard must cover, and both are
|
|
12
|
+
* exercised below because the canonical one is easy to miss:
|
|
13
|
+
*
|
|
14
|
+
* 1. `state.phase === "complete"` with `activeMilestone` set, so the
|
|
15
|
+
* loop computes a non-null `mid` from `state.activeMilestone.id`.
|
|
16
|
+
*
|
|
17
|
+
* 2. `state.phase === "complete"` with `activeMilestone: null` — the
|
|
18
|
+
* canonical "all milestones complete" return from `deriveState`
|
|
19
|
+
* (state.ts:613, state.ts:1293). `mid` is undefined here, so the
|
|
20
|
+
* guard must consult `s.currentMilestoneId` (the milestone this
|
|
21
|
+
* session was working on) instead. Without coverage for this case,
|
|
22
|
+
* a guard that only inspects `mid` is unreachable in production and
|
|
23
|
+
* the loop replays `_runMilestoneMergeOnceWithStashRestore`,
|
|
24
|
+
* `sendDesktopNotification("All milestones complete!")`,
|
|
25
|
+
* `logCmuxEvent`, and `stopAuto` — exactly the duplicate side
|
|
26
|
+
* effects this fix exists to prevent.
|
|
27
|
+
*
|
|
28
|
+
* Both fire-paths of the guard (`completionStopInProgress` and a
|
|
29
|
+
* DB-already-closed milestone) are exercised against each shape.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
33
|
+
import { runPreDispatch } from "../auto/pre-dispatch.ts";
|
|
34
|
+
import {
|
|
35
|
+
openDatabase,
|
|
36
|
+
closeDatabase,
|
|
37
|
+
insertMilestone,
|
|
38
|
+
isDbAvailable,
|
|
39
|
+
} from "../gsd-db.ts";
|
|
40
|
+
|
|
41
|
+
const { assertTrue, report } = createTestContext();
|
|
42
|
+
|
|
43
|
+
type SideEffect = string;
|
|
44
|
+
|
|
45
|
+
interface ScenarioOverrides {
|
|
46
|
+
completionStopInProgress: boolean;
|
|
47
|
+
sideEffects: SideEffect[];
|
|
48
|
+
notifications: Array<{ message: string; level?: string }>;
|
|
49
|
+
// When `null`, deriveState returns activeMilestone: null (canonical
|
|
50
|
+
// all-complete path). Otherwise, returns an activeMilestone with this id.
|
|
51
|
+
activeMilestone: { id: string; title: string } | null;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function makeIterationContext(overrides: ScenarioOverrides): any {
|
|
55
|
+
const basePath = "/tmp/gsd-test-terminal-complete";
|
|
56
|
+
const recordSideEffect = (label: string) => {
|
|
57
|
+
overrides.sideEffects.push(label);
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
ctx: {
|
|
61
|
+
ui: {
|
|
62
|
+
notify(message: string, level?: string) {
|
|
63
|
+
overrides.notifications.push({ message, level });
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
pi: {},
|
|
68
|
+
s: {
|
|
69
|
+
basePath,
|
|
70
|
+
originalBasePath: basePath,
|
|
71
|
+
canonicalProjectRoot: basePath,
|
|
72
|
+
resourceVersionOnStart: "test",
|
|
73
|
+
// Critical for the `!mid` canonical path: even when deriveState returns
|
|
74
|
+
// activeMilestone: null, the session still remembers the milestone it
|
|
75
|
+
// was working on, and we use that to look up DB status.
|
|
76
|
+
currentMilestoneId: "M001",
|
|
77
|
+
currentUnit: null,
|
|
78
|
+
milestoneMergedInPhases: false,
|
|
79
|
+
completionStopInProgress: overrides.completionStopInProgress,
|
|
80
|
+
},
|
|
81
|
+
prefs: undefined,
|
|
82
|
+
iteration: 1,
|
|
83
|
+
flowId: "test-flow",
|
|
84
|
+
nextSeq: () => 1,
|
|
85
|
+
deps: {
|
|
86
|
+
checkResourcesStale() {
|
|
87
|
+
return null;
|
|
88
|
+
},
|
|
89
|
+
invalidateAllCaches() {},
|
|
90
|
+
async preDispatchHealthGate() {
|
|
91
|
+
return { proceed: true, fixesApplied: [] };
|
|
92
|
+
},
|
|
93
|
+
async deriveState() {
|
|
94
|
+
return {
|
|
95
|
+
phase: "complete",
|
|
96
|
+
activeMilestone: overrides.activeMilestone,
|
|
97
|
+
activeSlice: null,
|
|
98
|
+
activeTask: null,
|
|
99
|
+
// Registry says M001 is complete and no other milestones exist, so
|
|
100
|
+
// `incomplete.length === 0 && state.registry.length > 0` evaluates
|
|
101
|
+
// true in the `!mid` branch.
|
|
102
|
+
registry: [{ id: "M001", status: "complete" }],
|
|
103
|
+
nextAction: "complete",
|
|
104
|
+
};
|
|
105
|
+
},
|
|
106
|
+
syncCmuxSidebar() {},
|
|
107
|
+
setActiveMilestoneId() {},
|
|
108
|
+
reconcileMergeState() {
|
|
109
|
+
return "clean";
|
|
110
|
+
},
|
|
111
|
+
// Anything below this point MUST NOT be reached when the guard fires.
|
|
112
|
+
preflightCleanRoot() {
|
|
113
|
+
recordSideEffect("preflight");
|
|
114
|
+
return { ok: true, stashPushed: false, stashMarker: null };
|
|
115
|
+
},
|
|
116
|
+
postflightPopStash() {
|
|
117
|
+
recordSideEffect("postflight");
|
|
118
|
+
return { ok: true, needsManualRecovery: false };
|
|
119
|
+
},
|
|
120
|
+
lifecycle: {
|
|
121
|
+
exitMilestone() {
|
|
122
|
+
recordSideEffect("merge");
|
|
123
|
+
return { ok: true };
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
sendDesktopNotification() {
|
|
127
|
+
recordSideEffect("desktop-notify");
|
|
128
|
+
},
|
|
129
|
+
logCmuxEvent() {
|
|
130
|
+
recordSideEffect("cmux-event");
|
|
131
|
+
},
|
|
132
|
+
async closeoutUnit() {
|
|
133
|
+
recordSideEffect("closeout-unit");
|
|
134
|
+
},
|
|
135
|
+
buildSnapshotOpts() {
|
|
136
|
+
return {};
|
|
137
|
+
},
|
|
138
|
+
async stopAuto(_ctx: unknown, _pi: unknown, reason?: string) {
|
|
139
|
+
recordSideEffect(`stop:${reason ?? ""}`);
|
|
140
|
+
},
|
|
141
|
+
async pauseAuto() {
|
|
142
|
+
recordSideEffect("pause");
|
|
143
|
+
},
|
|
144
|
+
emitJournalEvent() {
|
|
145
|
+
recordSideEffect("journal-event");
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
async function runScenario(opts: {
|
|
152
|
+
label: string;
|
|
153
|
+
completionStopInProgress: boolean;
|
|
154
|
+
activeMilestone: { id: string; title: string } | null;
|
|
155
|
+
// When true, the test opens an in-memory DB and inserts M001 with status
|
|
156
|
+
// "complete" so the DB-closed branch of the guard can fire.
|
|
157
|
+
dbAlreadyClosed: boolean;
|
|
158
|
+
}): Promise<void> {
|
|
159
|
+
if (isDbAvailable()) {
|
|
160
|
+
closeDatabase();
|
|
161
|
+
}
|
|
162
|
+
if (opts.dbAlreadyClosed) {
|
|
163
|
+
openDatabase(":memory:");
|
|
164
|
+
insertMilestone({ id: "M001", title: "Milestone one", status: "complete" });
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const sideEffects: SideEffect[] = [];
|
|
169
|
+
const notifications: Array<{ message: string; level?: string }> = [];
|
|
170
|
+
const ic = makeIterationContext({
|
|
171
|
+
completionStopInProgress: opts.completionStopInProgress,
|
|
172
|
+
sideEffects,
|
|
173
|
+
notifications,
|
|
174
|
+
activeMilestone: opts.activeMilestone,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const result = await runPreDispatch(ic, {
|
|
178
|
+
recentUnits: [],
|
|
179
|
+
stuckRecoveryAttempts: 0,
|
|
180
|
+
consecutiveFinalizeTimeouts: 0,
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
assertTrue(
|
|
184
|
+
result.action === "break",
|
|
185
|
+
`${opts.label}: returns break instead of next`,
|
|
186
|
+
);
|
|
187
|
+
if (result.action === "break") {
|
|
188
|
+
assertTrue(
|
|
189
|
+
result.reason === "milestone-complete",
|
|
190
|
+
`${opts.label}: reason is milestone-complete (got "${result.reason}")`,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
assertTrue(
|
|
194
|
+
sideEffects.length === 0,
|
|
195
|
+
`${opts.label}: no closeout side effects replayed (saw [${sideEffects.join(", ")}])`,
|
|
196
|
+
);
|
|
197
|
+
assertTrue(
|
|
198
|
+
notifications.length === 0,
|
|
199
|
+
`${opts.label}: no user notifications emitted (saw ${notifications.length})`,
|
|
200
|
+
);
|
|
201
|
+
} finally {
|
|
202
|
+
if (isDbAvailable()) {
|
|
203
|
+
closeDatabase();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
console.log("\n=== Terminal complete is idempotent across both observer paths ===");
|
|
209
|
+
|
|
210
|
+
// ── state.phase === "complete" branch (activeMilestone non-null) ────────────
|
|
211
|
+
await runScenario({
|
|
212
|
+
label: "phase=complete + mid set + completionStopInProgress",
|
|
213
|
+
completionStopInProgress: true,
|
|
214
|
+
activeMilestone: { id: "M001", title: "Milestone one" },
|
|
215
|
+
dbAlreadyClosed: false,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await runScenario({
|
|
219
|
+
label: "phase=complete + mid set + DB closed",
|
|
220
|
+
completionStopInProgress: false,
|
|
221
|
+
activeMilestone: { id: "M001", title: "Milestone one" },
|
|
222
|
+
dbAlreadyClosed: true,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
// ── Canonical !mid "all milestones complete" sub-branch ────────────────────
|
|
226
|
+
// deriveState returns phase: "complete" with activeMilestone: null. The
|
|
227
|
+
// session's s.currentMilestoneId (M001) is what the guard consults.
|
|
228
|
+
await runScenario({
|
|
229
|
+
label: "phase=complete + activeMilestone=null + completionStopInProgress",
|
|
230
|
+
completionStopInProgress: true,
|
|
231
|
+
activeMilestone: null,
|
|
232
|
+
dbAlreadyClosed: false,
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await runScenario({
|
|
236
|
+
label: "phase=complete + activeMilestone=null + DB closed",
|
|
237
|
+
completionStopInProgress: false,
|
|
238
|
+
activeMilestone: null,
|
|
239
|
+
dbAlreadyClosed: true,
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
report();
|
|
@@ -18,12 +18,12 @@ function readSrc(file: string): string {
|
|
|
18
18
|
return readFileSync(join(gsdDir, file), "utf-8");
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
test("#4620: auto/
|
|
22
|
-
const src = readSrc("auto/
|
|
21
|
+
test("#4620: auto/pre-dispatch plan gate failed message includes doctor heal hint", () => {
|
|
22
|
+
const src = readSrc("auto/pre-dispatch.ts");
|
|
23
23
|
assert.match(
|
|
24
24
|
src,
|
|
25
25
|
/Plan gate failed-closed:[\s\S]*\/gsd doctor heal/,
|
|
26
|
-
"auto/
|
|
26
|
+
"auto/pre-dispatch.ts should include /gsd doctor heal in plan gate failed notification",
|
|
27
27
|
);
|
|
28
28
|
});
|
|
29
29
|
|
|
@@ -145,7 +145,7 @@ function createBasicTask(): void {
|
|
|
145
145
|
});
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
function createTaskWithoutVerify(): void {
|
|
148
|
+
function createTaskWithoutVerify(status = "pending"): void {
|
|
149
149
|
insertMilestone({ id: "M001" });
|
|
150
150
|
insertSlice({
|
|
151
151
|
id: "S01",
|
|
@@ -159,7 +159,7 @@ function createTaskWithoutVerify(): void {
|
|
|
159
159
|
sliceId: "S01",
|
|
160
160
|
milestoneId: "M001",
|
|
161
161
|
title: "Task without host verification",
|
|
162
|
-
status
|
|
162
|
+
status,
|
|
163
163
|
planning: {
|
|
164
164
|
description: "Task intentionally missing runnable verification",
|
|
165
165
|
estimate: "1h",
|
|
@@ -558,6 +558,32 @@ describe("Post-execution blocking failure retry bypass", () => {
|
|
|
558
558
|
assert.equal(pauseAutoMock.mock.callCount(), 1);
|
|
559
559
|
assert.equal(s.pendingVerificationRetry, null);
|
|
560
560
|
|
|
561
|
+
const notifyMessages = ctx.ui.notify.mock.calls.map((c: { arguments: unknown[] }) =>
|
|
562
|
+
String(c.arguments[0])
|
|
563
|
+
);
|
|
564
|
+
assert.ok(
|
|
565
|
+
notifyMessages.some(
|
|
566
|
+
(m: string) =>
|
|
567
|
+
m.includes(".gsd/PREFERENCES.md") &&
|
|
568
|
+
m.includes("task-plan Verify command") &&
|
|
569
|
+
m.includes("/gsd next")
|
|
570
|
+
),
|
|
571
|
+
"no-host-checks notification should guide the user to add verification and resume",
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
const pauseCalls = pauseAutoMock.mock.calls as Array<{ arguments: unknown[] }>;
|
|
575
|
+
const pauseCallArgs = pauseCalls[0]?.arguments[2] as
|
|
576
|
+
| { message?: string }
|
|
577
|
+
| undefined;
|
|
578
|
+
assert.ok(
|
|
579
|
+
pauseCallArgs?.message?.includes(".gsd/PREFERENCES.md"),
|
|
580
|
+
"pause reason should include the project verification configuration path",
|
|
581
|
+
);
|
|
582
|
+
assert.ok(
|
|
583
|
+
pauseCallArgs?.message?.includes("/gsd next"),
|
|
584
|
+
"pause reason should tell the user how to resume",
|
|
585
|
+
);
|
|
586
|
+
|
|
561
587
|
const evidencePath = join(tempDir, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-VERIFY.json");
|
|
562
588
|
const evidence = JSON.parse(readFileSync(evidencePath, "utf-8"));
|
|
563
589
|
assert.equal(evidence.passed, false);
|
|
@@ -566,6 +592,41 @@ describe("Post-execution blocking failure retry bypass", () => {
|
|
|
566
592
|
assert.ok(!("maxRetries" in evidence), "no-host-checks evidence must not include maxRetries");
|
|
567
593
|
});
|
|
568
594
|
|
|
595
|
+
test("completed browser-facing execute-task with no host-owned verification continues toward browser UAT", async () => {
|
|
596
|
+
createTaskWithoutVerify("complete");
|
|
597
|
+
writeFileSync(join(tempDir, "index.html"), "<!doctype html><button>Import</button>", "utf-8");
|
|
598
|
+
|
|
599
|
+
const ctx = makeMockCtx();
|
|
600
|
+
const pi = makeMockPi();
|
|
601
|
+
const pauseAutoMock = mock.fn(async () => {});
|
|
602
|
+
const s = makeMockSession(tempDir, { type: "execute-task", id: "M001/S01/T01" });
|
|
603
|
+
|
|
604
|
+
const result = await runPostUnitVerification({ s, ctx, pi }, pauseAutoMock);
|
|
605
|
+
|
|
606
|
+
assert.equal(result, "continue");
|
|
607
|
+
assert.equal(pauseAutoMock.mock.callCount(), 0);
|
|
608
|
+
assert.equal(s.pendingVerificationRetry, null);
|
|
609
|
+
|
|
610
|
+
const notifyMessages = ctx.ui.notify.mock.calls.map((c: { arguments: unknown[] }) =>
|
|
611
|
+
String(c.arguments[0])
|
|
612
|
+
);
|
|
613
|
+
assert.ok(
|
|
614
|
+
notifyMessages.some(
|
|
615
|
+
(m: string) =>
|
|
616
|
+
m.includes("browser-facing task") &&
|
|
617
|
+
m.includes("slice UAT") &&
|
|
618
|
+
m.includes("browser tools")
|
|
619
|
+
),
|
|
620
|
+
"completed web tasks without task-level commands should explain browser UAT handoff",
|
|
621
|
+
);
|
|
622
|
+
|
|
623
|
+
const evidencePath = join(tempDir, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-VERIFY.json");
|
|
624
|
+
const evidence = JSON.parse(readFileSync(evidencePath, "utf-8"));
|
|
625
|
+
assert.equal(evidence.passed, false);
|
|
626
|
+
assert.equal(evidence.discoverySource, "none");
|
|
627
|
+
assert.ok(!("retryAttempt" in evidence), "browser-UAT handoff evidence must not request a task retry");
|
|
628
|
+
});
|
|
629
|
+
|
|
569
630
|
test("auto-discovered package.json verification failure retries instead of continuing", async () => {
|
|
570
631
|
createTaskWithoutVerify();
|
|
571
632
|
writeFileSync(
|
|
@@ -55,14 +55,20 @@ const PHASE_PROMPT_TOOL_CALLS: Record<string, readonly string[]> = {
|
|
|
55
55
|
"plan-slice": ["gsd_reassess_roadmap", "gsd_plan_slice", "gsd_decision_save"],
|
|
56
56
|
"refine-slice": ["gsd_plan_slice", "gsd_decision_save"],
|
|
57
57
|
"replan-slice": ["gsd_replan_slice"],
|
|
58
|
-
"execute-task": [
|
|
58
|
+
"execute-task": [
|
|
59
|
+
"gsd_task_complete",
|
|
60
|
+
"gsd_exec",
|
|
61
|
+
"gsd_exec_search",
|
|
62
|
+
"gsd_resume",
|
|
63
|
+
"gsd_capture_thought",
|
|
64
|
+
],
|
|
59
65
|
"reactive-execute": ["gsd_summary_save"],
|
|
60
66
|
"complete-slice": [
|
|
61
67
|
"gsd_exec",
|
|
62
68
|
"gsd_task_reopen",
|
|
63
69
|
"gsd_replan_slice",
|
|
64
70
|
"gsd_requirement_update",
|
|
65
|
-
"
|
|
71
|
+
"gsd_capture_thought",
|
|
66
72
|
"gsd_slice_complete",
|
|
67
73
|
"gsd_summary_save",
|
|
68
74
|
],
|
|
@@ -240,6 +246,8 @@ test("workflow-start prompt defaults to autonomy instead of per-phase confirmati
|
|
|
240
246
|
const prompt = readPrompt("workflow-start");
|
|
241
247
|
assert.match(prompt, /Keep moving by default/i);
|
|
242
248
|
assert.match(prompt, /Decision gates, not ceremony/i);
|
|
249
|
+
assert.match(prompt, /Persist workflow state/i);
|
|
250
|
+
assert.match(prompt, /completedAt/i);
|
|
243
251
|
assert.doesNotMatch(prompt, /confirm with the user before proceeding/i);
|
|
244
252
|
assert.doesNotMatch(prompt, /Gate between phases/i);
|
|
245
253
|
});
|
|
@@ -17,10 +17,8 @@ import {
|
|
|
17
17
|
shouldDeferTransientErrorToCoreRetry,
|
|
18
18
|
suppressTerminalDeletedWorktreeMessageEnd,
|
|
19
19
|
} from "../bootstrap/agent-end-recovery.ts";
|
|
20
|
-
import {
|
|
21
|
-
|
|
22
|
-
_classifyZeroToolProviderMessageForTest,
|
|
23
|
-
} from "../auto/phases.ts";
|
|
20
|
+
import { _buildCancelledUnitStopReason } from "../auto/phase-helpers.ts";
|
|
21
|
+
import { _classifyZeroToolProviderMessageForTest } from "../auto/unit-phase.ts";
|
|
24
22
|
import { autoSession } from "../auto-runtime-state.ts";
|
|
25
23
|
import { getNextFallbackModel } from "../preferences.ts";
|
|
26
24
|
// Zero-import module — imported by path rather than through the package
|