gsd-pi 2.44.0-dev.d25d507 → 2.45.0-dev.1afbdaa
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/help-text.js +1 -1
- package/dist/loader.js +34 -0
- package/dist/resources/extensions/gsd/activity-log.js +7 -0
- package/dist/resources/extensions/gsd/auto/infra-errors.js +3 -0
- package/dist/resources/extensions/gsd/auto/phases.js +63 -77
- package/dist/resources/extensions/gsd/auto/run-unit.js +6 -3
- package/dist/resources/extensions/gsd/auto/session.js +0 -11
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +112 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +25 -96
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
- package/dist/resources/extensions/gsd/auto-start.js +23 -5
- package/dist/resources/extensions/gsd/auto-timers.js +57 -3
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +14 -10
- package/dist/resources/extensions/gsd/auto.js +42 -60
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +170 -11
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +18 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- package/dist/resources/extensions/gsd/commands/context.js +0 -4
- package/dist/resources/extensions/gsd/commands/handlers/core.js +2 -0
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +10 -0
- package/dist/resources/extensions/gsd/commands/handlers/parallel.js +1 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
- package/dist/resources/extensions/gsd/crash-recovery.js +2 -4
- package/dist/resources/extensions/gsd/dashboard-overlay.js +0 -44
- package/dist/resources/extensions/gsd/db-writer.js +40 -22
- package/dist/resources/extensions/gsd/doctor-checks.js +167 -2
- package/dist/resources/extensions/gsd/doctor.js +13 -3
- package/dist/resources/extensions/gsd/git-service.js +8 -3
- package/dist/resources/extensions/gsd/gsd-db.js +28 -4
- package/dist/resources/extensions/gsd/guided-flow.js +1 -2
- package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
- package/dist/resources/extensions/gsd/parallel-merge.js +1 -1
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -18
- package/dist/resources/extensions/gsd/preferences-types.js +2 -2
- package/dist/resources/extensions/gsd/preferences.js +8 -4
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +10 -23
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +5 -15
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/dist/resources/extensions/gsd/prompts/queue.md +2 -2
- package/dist/resources/extensions/gsd/prompts/quick-task.md +2 -0
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/dist/resources/extensions/gsd/prompts/research-slice.md +3 -3
- package/dist/resources/extensions/gsd/prompts/rethink.md +83 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/dist/resources/extensions/gsd/provider-error-pause.js +7 -0
- package/dist/resources/extensions/gsd/repo-identity.js +45 -7
- package/dist/resources/extensions/gsd/rethink.js +115 -0
- package/dist/resources/extensions/gsd/session-lock.js +1 -3
- package/dist/resources/extensions/gsd/state.js +48 -3
- package/dist/resources/extensions/gsd/sync-lock.js +89 -0
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +61 -11
- package/dist/resources/extensions/gsd/tools/complete-slice.js +56 -11
- package/dist/resources/extensions/gsd/tools/complete-task.js +50 -2
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +37 -1
- package/dist/resources/extensions/gsd/tools/plan-slice.js +31 -1
- package/dist/resources/extensions/gsd/tools/plan-task.js +28 -1
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +32 -2
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +86 -0
- package/dist/resources/extensions/gsd/tools/reopen-task.js +90 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +34 -2
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
- package/dist/resources/extensions/gsd/unit-ownership.js +85 -0
- package/dist/resources/extensions/gsd/workflow-events.js +102 -0
- package/dist/resources/extensions/gsd/workflow-logger.js +193 -0
- package/dist/resources/extensions/gsd/workflow-manifest.js +244 -0
- package/dist/resources/extensions/gsd/workflow-migration.js +280 -0
- package/dist/resources/extensions/gsd/workflow-projections.js +373 -0
- package/dist/resources/extensions/gsd/workflow-reconcile.js +411 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +34 -3
- package/dist/resources/extensions/gsd/worktree-resolver.js +43 -0
- package/dist/resources/extensions/gsd/write-intercept.js +84 -0
- package/dist/resources/extensions/mcp-client/index.js +14 -0
- package/dist/resources/extensions/voice/index.js +11 -16
- package/dist/resources/extensions/voice/linux-ready.js +67 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- 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/page.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +2 -2
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
- 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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/4024.11ca5c01938e5948.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{3721.bf31263de6d5fa46.js → 485.243af25f0cdf50d6.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/{page-b9367c5ae13b99c6.js → page-6654a8cca61a3d1c.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
- package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
- package/package.json +2 -1
- package/packages/native/dist/stream-process/index.js +2 -2
- package/packages/native/src/__tests__/stream-process.test.mjs +34 -0
- package/packages/native/src/stream-process/index.ts +2 -2
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +15 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +10 -5
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js +185 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js +41 -0
- package/packages/pi-coding-agent/dist/core/local-model-check.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +239 -10
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +13 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-commands.test.js +206 -195
- package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +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 +6 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +17 -0
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js +32 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/timestamp.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +3 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +8 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js +12 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts +15 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js +40 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/timestamp.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +4 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts +5 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js +13 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +17 -8
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +7 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +2 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +2 -1
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.test.ts +227 -0
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +11 -5
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +297 -11
- package/packages/pi-coding-agent/src/core/model-registry.ts +51 -4
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +227 -205
- package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
- package/packages/pi-coding-agent/src/main.ts +19 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/timestamp.test.ts +38 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/settings-selector.ts +15 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/timestamp.ts +48 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +3 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/user-message.ts +18 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +8 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/activity-log.ts +1 -0
- package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -19
- package/src/resources/extensions/gsd/auto/phases.ts +69 -91
- package/src/resources/extensions/gsd/auto/run-unit.ts +6 -3
- package/src/resources/extensions/gsd/auto/session.ts +0 -18
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +131 -0
- package/src/resources/extensions/gsd/auto-dashboard.ts +0 -1
- package/src/resources/extensions/gsd/auto-post-unit.ts +25 -106
- package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
- package/src/resources/extensions/gsd/auto-start.ts +26 -5
- package/src/resources/extensions/gsd/auto-timers.ts +64 -3
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +5 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +17 -11
- package/src/resources/extensions/gsd/auto.ts +44 -86
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +162 -11
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +22 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- package/src/resources/extensions/gsd/commands/context.ts +0 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +2 -0
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +10 -0
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +1 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
- package/src/resources/extensions/gsd/crash-recovery.ts +1 -5
- package/src/resources/extensions/gsd/dashboard-overlay.ts +0 -50
- package/src/resources/extensions/gsd/db-writer.ts +41 -27
- package/src/resources/extensions/gsd/doctor-checks.ts +180 -2
- package/src/resources/extensions/gsd/doctor-types.ts +7 -1
- package/src/resources/extensions/gsd/doctor.ts +13 -4
- package/src/resources/extensions/gsd/git-service.ts +6 -2
- package/src/resources/extensions/gsd/gsd-db.ts +32 -4
- package/src/resources/extensions/gsd/guided-flow.ts +1 -2
- package/src/resources/extensions/gsd/journal.ts +6 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
- package/src/resources/extensions/gsd/parallel-merge.ts +1 -1
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +5 -21
- package/src/resources/extensions/gsd/preferences-types.ts +2 -2
- package/src/resources/extensions/gsd/preferences.ts +7 -3
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +21 -10
- package/src/resources/extensions/gsd/prompts/complete-slice.md +10 -23
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +5 -15
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-research-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +5 -3
- package/src/resources/extensions/gsd/prompts/queue.md +2 -2
- package/src/resources/extensions/gsd/prompts/quick-task.md +2 -0
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +1 -1
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -6
- package/src/resources/extensions/gsd/prompts/replan-slice.md +3 -14
- package/src/resources/extensions/gsd/prompts/research-slice.md +3 -3
- package/src/resources/extensions/gsd/prompts/rethink.md +83 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +7 -37
- package/src/resources/extensions/gsd/provider-error-pause.ts +9 -0
- package/src/resources/extensions/gsd/repo-identity.ts +46 -7
- package/src/resources/extensions/gsd/rethink.ts +154 -0
- package/src/resources/extensions/gsd/session-lock.ts +0 -4
- package/src/resources/extensions/gsd/state.ts +49 -1
- package/src/resources/extensions/gsd/sync-lock.ts +94 -0
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +5 -13
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +6 -10
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +264 -228
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +317 -250
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +2 -8
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/infra-error.test.ts +20 -2
- package/src/resources/extensions/gsd/tests/inherited-repo-home-dir.test.ts +121 -0
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +15 -24
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +8 -9
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +42 -3
- package/src/resources/extensions/gsd/tests/parallel-budget-atomicity.test.ts +0 -1
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +0 -7
- package/src/resources/extensions/gsd/tests/parallel-merge.test.ts +7 -8
- package/src/resources/extensions/gsd/tests/parallel-orchestration.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +0 -2
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +9 -6
- package/src/resources/extensions/gsd/tests/post-mutation-hook.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/projection-regression.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +26 -21
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/reopen-slice.test.ts +155 -0
- package/src/resources/extensions/gsd/tests/reopen-task.test.ts +165 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +1 -4
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/stop-auto-remote.test.ts +2 -3
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +122 -0
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/workflow-events.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +275 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +171 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +220 -0
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/write-intercept.test.ts +76 -0
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +74 -11
- package/src/resources/extensions/gsd/tools/complete-slice.ts +68 -11
- package/src/resources/extensions/gsd/tools/complete-task.ts +63 -1
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +45 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +40 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +37 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +39 -1
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +125 -0
- package/src/resources/extensions/gsd/tools/reopen-task.ts +129 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +41 -1
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
- package/src/resources/extensions/gsd/types.ts +8 -0
- package/src/resources/extensions/gsd/unit-ownership.ts +104 -0
- package/src/resources/extensions/gsd/workflow-events.ts +154 -0
- package/src/resources/extensions/gsd/workflow-logger.ts +243 -0
- package/src/resources/extensions/gsd/workflow-manifest.ts +334 -0
- package/src/resources/extensions/gsd/workflow-migration.ts +345 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +425 -0
- package/src/resources/extensions/gsd/workflow-reconcile.ts +503 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +41 -5
- package/src/resources/extensions/gsd/worktree-resolver.ts +44 -0
- package/src/resources/extensions/gsd/write-intercept.ts +90 -0
- package/src/resources/extensions/mcp-client/index.ts +20 -0
- package/src/resources/extensions/voice/index.ts +11 -21
- package/src/resources/extensions/voice/linux-ready.ts +87 -0
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +124 -0
- package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
- package/dist/web/standalone/.next/static/chunks/webpack-9014b5adb127a98a.js +0 -1
- package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +0 -1
- /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tokoGmfkYfWf1_Yl_Gz7i → j-BskPs0nxxPeYY-bSrab}/_ssgManifest.js +0 -0
|
@@ -297,7 +297,6 @@ describe("parallel-orchestrator: lifecycle", () => {
|
|
|
297
297
|
worktreePath: "/tmp/wt-M001",
|
|
298
298
|
startedAt: Date.now(),
|
|
299
299
|
state: "running",
|
|
300
|
-
completedUnits: 2,
|
|
301
300
|
cost: 0.25,
|
|
302
301
|
},
|
|
303
302
|
],
|
|
@@ -309,7 +308,6 @@ describe("parallel-orchestrator: lifecycle", () => {
|
|
|
309
308
|
const workers = getWorkerStatuses(base);
|
|
310
309
|
assert.equal(workers.length, 1);
|
|
311
310
|
assert.equal(workers[0].milestoneId, "M001");
|
|
312
|
-
assert.equal(workers[0].completedUnits, 2);
|
|
313
311
|
assert.equal(isParallelActive(), true);
|
|
314
312
|
} finally {
|
|
315
313
|
resetOrchestrator();
|
|
@@ -416,7 +414,6 @@ describe("parallel-orchestrator: lifecycle", () => {
|
|
|
416
414
|
const workers = getWorkerStatuses();
|
|
417
415
|
assert.equal(workers.length, 1);
|
|
418
416
|
assert.equal(workers[0].state, "running");
|
|
419
|
-
assert.equal(workers[0].completedUnits, 4);
|
|
420
417
|
} finally {
|
|
421
418
|
resetOrchestrator();
|
|
422
419
|
rmSync(base, { recursive: true, force: true });
|
|
@@ -552,7 +549,6 @@ function makeWorker(overrides: Partial<WorkerInfo> = {}): WorkerInfo {
|
|
|
552
549
|
worktreePath: "/tmp/test-worktree",
|
|
553
550
|
startedAt: Date.now() - 60_000,
|
|
554
551
|
state: "stopped",
|
|
555
|
-
completedUnits: 5,
|
|
556
552
|
cost: 2.50,
|
|
557
553
|
...overrides,
|
|
558
554
|
};
|
|
@@ -563,9 +559,9 @@ function makeWorker(overrides: Partial<WorkerInfo> = {}): WorkerInfo {
|
|
|
563
559
|
describe("parallel-merge: determineMergeOrder sequential", () => {
|
|
564
560
|
it("returns milestone IDs sorted alphabetically by default", () => {
|
|
565
561
|
const workers = [
|
|
566
|
-
makeWorker({ milestoneId: "M003", state: "stopped"
|
|
567
|
-
makeWorker({ milestoneId: "M001", state: "stopped"
|
|
568
|
-
makeWorker({ milestoneId: "M002", state: "stopped"
|
|
562
|
+
makeWorker({ milestoneId: "M003", state: "stopped" }),
|
|
563
|
+
makeWorker({ milestoneId: "M001", state: "stopped" }),
|
|
564
|
+
makeWorker({ milestoneId: "M002", state: "stopped" }),
|
|
569
565
|
];
|
|
570
566
|
const order = determineMergeOrder(workers, "sequential");
|
|
571
567
|
assert.deepEqual(order, ["M001", "M002", "M003"]);
|
|
@@ -573,27 +569,27 @@ describe("parallel-merge: determineMergeOrder sequential", () => {
|
|
|
573
569
|
|
|
574
570
|
it("excludes workers that are still running", () => {
|
|
575
571
|
const workers = [
|
|
576
|
-
makeWorker({ milestoneId: "M001", state: "stopped"
|
|
577
|
-
makeWorker({ milestoneId: "M002", state: "running"
|
|
578
|
-
makeWorker({ milestoneId: "M003", state: "stopped"
|
|
572
|
+
makeWorker({ milestoneId: "M001", state: "stopped" }),
|
|
573
|
+
makeWorker({ milestoneId: "M002", state: "running" }),
|
|
574
|
+
makeWorker({ milestoneId: "M003", state: "stopped" }),
|
|
579
575
|
];
|
|
580
576
|
const order = determineMergeOrder(workers, "sequential");
|
|
581
577
|
assert.deepEqual(order, ["M001", "M003"]);
|
|
582
578
|
});
|
|
583
579
|
|
|
584
|
-
it("
|
|
580
|
+
it("includes all stopped workers", () => {
|
|
585
581
|
const workers = [
|
|
586
|
-
makeWorker({ milestoneId: "M001", state: "stopped"
|
|
587
|
-
makeWorker({ milestoneId: "M002", state: "stopped"
|
|
582
|
+
makeWorker({ milestoneId: "M001", state: "stopped" }),
|
|
583
|
+
makeWorker({ milestoneId: "M002", state: "stopped" }),
|
|
588
584
|
];
|
|
589
585
|
const order = determineMergeOrder(workers, "sequential");
|
|
590
|
-
assert.deepEqual(order, ["M002"]);
|
|
586
|
+
assert.deepEqual(order, ["M001", "M002"]);
|
|
591
587
|
});
|
|
592
588
|
|
|
593
589
|
it("returns empty array when no workers are completed", () => {
|
|
594
590
|
const workers = [
|
|
595
|
-
makeWorker({ milestoneId: "M001", state: "running"
|
|
596
|
-
makeWorker({ milestoneId: "M002", state: "paused"
|
|
591
|
+
makeWorker({ milestoneId: "M001", state: "running" }),
|
|
592
|
+
makeWorker({ milestoneId: "M002", state: "paused" }),
|
|
597
593
|
];
|
|
598
594
|
const order = determineMergeOrder(workers);
|
|
599
595
|
assert.deepEqual(order, []);
|
|
@@ -601,8 +597,8 @@ describe("parallel-merge: determineMergeOrder sequential", () => {
|
|
|
601
597
|
|
|
602
598
|
it("uses sequential order as the default when no order arg provided", () => {
|
|
603
599
|
const workers = [
|
|
604
|
-
makeWorker({ milestoneId: "M002", state: "stopped"
|
|
605
|
-
makeWorker({ milestoneId: "M001", state: "stopped"
|
|
600
|
+
makeWorker({ milestoneId: "M002", state: "stopped" }),
|
|
601
|
+
makeWorker({ milestoneId: "M001", state: "stopped" }),
|
|
606
602
|
];
|
|
607
603
|
// Call with no second argument — should default to "sequential"
|
|
608
604
|
const order = determineMergeOrder(workers);
|
|
@@ -614,9 +610,9 @@ describe("parallel-merge: determineMergeOrder by-completion", () => {
|
|
|
614
610
|
it("returns milestones sorted by startedAt (earliest first)", () => {
|
|
615
611
|
const now = Date.now();
|
|
616
612
|
const workers = [
|
|
617
|
-
makeWorker({ milestoneId: "M003", state: "stopped",
|
|
618
|
-
makeWorker({ milestoneId: "M001", state: "stopped",
|
|
619
|
-
makeWorker({ milestoneId: "M002", state: "stopped",
|
|
613
|
+
makeWorker({ milestoneId: "M003", state: "stopped", startedAt: now - 30_000 }),
|
|
614
|
+
makeWorker({ milestoneId: "M001", state: "stopped", startedAt: now - 90_000 }),
|
|
615
|
+
makeWorker({ milestoneId: "M002", state: "stopped", startedAt: now - 60_000 }),
|
|
620
616
|
];
|
|
621
617
|
const order = determineMergeOrder(workers, "by-completion");
|
|
622
618
|
assert.deepEqual(order, ["M001", "M002", "M003"]);
|
|
@@ -625,9 +621,9 @@ describe("parallel-merge: determineMergeOrder by-completion", () => {
|
|
|
625
621
|
it("excludes paused workers from by-completion order", () => {
|
|
626
622
|
const now = Date.now();
|
|
627
623
|
const workers = [
|
|
628
|
-
makeWorker({ milestoneId: "M001", state: "stopped",
|
|
629
|
-
makeWorker({ milestoneId: "M002", state: "paused",
|
|
630
|
-
makeWorker({ milestoneId: "M003", state: "stopped",
|
|
624
|
+
makeWorker({ milestoneId: "M001", state: "stopped", startedAt: now - 90_000 }),
|
|
625
|
+
makeWorker({ milestoneId: "M002", state: "paused", startedAt: now - 60_000 }),
|
|
626
|
+
makeWorker({ milestoneId: "M003", state: "stopped", startedAt: now - 30_000 }),
|
|
631
627
|
];
|
|
632
628
|
const order = determineMergeOrder(workers, "by-completion");
|
|
633
629
|
assert.deepEqual(order, ["M001", "M003"]);
|
|
@@ -155,7 +155,6 @@ describe("parallel-worker-monitoring", () => {
|
|
|
155
155
|
worktreePath: "/tmp/wt-M001",
|
|
156
156
|
startedAt: Date.now(),
|
|
157
157
|
state: "running",
|
|
158
|
-
completedUnits: 1,
|
|
159
158
|
cost: 0.1,
|
|
160
159
|
},
|
|
161
160
|
],
|
|
@@ -191,7 +190,6 @@ describe("parallel-worker-monitoring", () => {
|
|
|
191
190
|
refreshWorkerStatuses(base, { restoreIfNeeded: true });
|
|
192
191
|
const workers = getWorkerStatuses();
|
|
193
192
|
assert.deepStrictEqual(workers[0].state, "running", "live session status restored");
|
|
194
|
-
assert.deepStrictEqual(workers[0].completedUnits, 3, "completed units restored from status file");
|
|
195
193
|
} finally {
|
|
196
194
|
resetOrchestrator();
|
|
197
195
|
rmSync(base, { recursive: true, force: true });
|
|
@@ -92,9 +92,11 @@ test('handlePlanMilestone writes milestone and slice planning state and renders
|
|
|
92
92
|
assert.ok(existsSync(roadmapPath), 'roadmap should be rendered to disk');
|
|
93
93
|
const roadmap = readFileSync(roadmapPath, 'utf-8');
|
|
94
94
|
assert.match(roadmap, /# M001: DB-backed planning/);
|
|
95
|
-
assert.match(roadmap,
|
|
96
|
-
assert.match(roadmap,
|
|
97
|
-
assert.match(roadmap,
|
|
95
|
+
assert.match(roadmap, /## Vision/);
|
|
96
|
+
assert.match(roadmap, /Make planning write through the database\./);
|
|
97
|
+
assert.match(roadmap, /## Slice Overview/);
|
|
98
|
+
assert.match(roadmap, /\| S01 \| Tool wiring \| medium \|/);
|
|
99
|
+
assert.match(roadmap, /\| S02 \| Prompt migration \| low \| S01 \|/);
|
|
98
100
|
} finally {
|
|
99
101
|
cleanup(base);
|
|
100
102
|
}
|
|
@@ -152,9 +154,10 @@ test('handlePlanMilestone clears parse-visible roadmap state after successful re
|
|
|
152
154
|
const result = await handlePlanMilestone(validParams(), base);
|
|
153
155
|
assert.ok(!('error' in result));
|
|
154
156
|
|
|
155
|
-
const
|
|
156
|
-
assert.
|
|
157
|
-
assert.
|
|
157
|
+
const contentAfter = readFileSync(roadmapPath, 'utf-8');
|
|
158
|
+
assert.match(contentAfter, /Make planning write through the database\./);
|
|
159
|
+
assert.match(contentAfter, /S01/);
|
|
160
|
+
assert.match(contentAfter, /S02/);
|
|
158
161
|
} finally {
|
|
159
162
|
cleanup(base);
|
|
160
163
|
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
// GSD Extension — post-mutation hook regression tests
|
|
2
|
+
// Verifies that after a successful handleCompleteTask call, the post-mutation
|
|
3
|
+
// hook fires: event-log.jsonl and state-manifest.json are both written.
|
|
4
|
+
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import assert from 'node:assert/strict';
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import * as os from 'node:os';
|
|
10
|
+
import { openDatabase, closeDatabase } from '../gsd-db.ts';
|
|
11
|
+
import { handleCompleteTask } from '../tools/complete-task.ts';
|
|
12
|
+
import { readEvents } from '../workflow-events.ts';
|
|
13
|
+
import { readManifest } from '../workflow-manifest.ts';
|
|
14
|
+
|
|
15
|
+
function tempDir(): string {
|
|
16
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'gsd-post-hook-'));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function cleanupDir(dirPath: string): void {
|
|
20
|
+
try { fs.rmSync(dirPath, { recursive: true, force: true }); } catch { /* best effort */ }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Create a minimal project directory with a PLAN.md for complete-task to find. */
|
|
24
|
+
function createProject(basePath: string): void {
|
|
25
|
+
const sliceDir = path.join(basePath, '.gsd', 'milestones', 'M001', 'slices', 'S01');
|
|
26
|
+
const tasksDir = path.join(sliceDir, 'tasks');
|
|
27
|
+
fs.mkdirSync(tasksDir, { recursive: true });
|
|
28
|
+
fs.writeFileSync(path.join(sliceDir, 'S01-PLAN.md'), `# S01: Test Slice
|
|
29
|
+
|
|
30
|
+
## Tasks
|
|
31
|
+
|
|
32
|
+
- [ ] **T01: Test task** \`est:30m\`
|
|
33
|
+
- Do: Implement the thing
|
|
34
|
+
- Verify: Run tests
|
|
35
|
+
|
|
36
|
+
- [ ] **T02: Second task** \`est:1h\`
|
|
37
|
+
- Do: Implement more
|
|
38
|
+
- Verify: Run more tests
|
|
39
|
+
`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function makeCompleteTaskParams() {
|
|
43
|
+
return {
|
|
44
|
+
taskId: 'T01',
|
|
45
|
+
sliceId: 'S01',
|
|
46
|
+
milestoneId: 'M001',
|
|
47
|
+
oneLiner: 'Implemented auth middleware',
|
|
48
|
+
narrative: 'Added JWT validation middleware with proper error handling.',
|
|
49
|
+
verification: 'Ran npm test — all tests pass.',
|
|
50
|
+
deviations: 'None.',
|
|
51
|
+
knownIssues: 'None.',
|
|
52
|
+
keyFiles: ['src/middleware/auth.ts'],
|
|
53
|
+
keyDecisions: [],
|
|
54
|
+
blockerDiscovered: false,
|
|
55
|
+
verificationEvidence: [
|
|
56
|
+
{ command: 'npm test', exitCode: 0, verdict: '✅ pass', durationMs: 2500 },
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ─── Post-mutation hook: event log ───────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
test('post-mutation-hook: event-log.jsonl exists after handleCompleteTask', async () => {
|
|
64
|
+
const base = tempDir();
|
|
65
|
+
const dbPath = path.join(base, 'test.db');
|
|
66
|
+
openDatabase(dbPath);
|
|
67
|
+
createProject(base);
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const result = await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
71
|
+
assert.ok(!('error' in result), `handler should succeed, got: ${JSON.stringify(result)}`);
|
|
72
|
+
|
|
73
|
+
const logPath = path.join(base, '.gsd', 'event-log.jsonl');
|
|
74
|
+
assert.ok(fs.existsSync(logPath), 'event-log.jsonl should exist after handler completes');
|
|
75
|
+
} finally {
|
|
76
|
+
closeDatabase();
|
|
77
|
+
cleanupDir(base);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('post-mutation-hook: event log contains complete-task event with correct params', async () => {
|
|
82
|
+
const base = tempDir();
|
|
83
|
+
const dbPath = path.join(base, 'test.db');
|
|
84
|
+
openDatabase(dbPath);
|
|
85
|
+
createProject(base);
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
89
|
+
|
|
90
|
+
const logPath = path.join(base, '.gsd', 'event-log.jsonl');
|
|
91
|
+
const events = readEvents(logPath);
|
|
92
|
+
assert.ok(events.length > 0, 'event log should have at least one event');
|
|
93
|
+
|
|
94
|
+
const ev = events.find((e) => e.cmd === 'complete-task');
|
|
95
|
+
assert.ok(ev !== undefined, 'should have a complete-task event');
|
|
96
|
+
assert.strictEqual((ev!.params as { milestoneId?: string }).milestoneId, 'M001');
|
|
97
|
+
assert.strictEqual((ev!.params as { sliceId?: string }).sliceId, 'S01');
|
|
98
|
+
assert.strictEqual((ev!.params as { taskId?: string }).taskId, 'T01');
|
|
99
|
+
assert.strictEqual(ev!.actor, 'agent');
|
|
100
|
+
} finally {
|
|
101
|
+
closeDatabase();
|
|
102
|
+
cleanupDir(base);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// ─── Post-mutation hook: manifest ────────────────────────────────────────
|
|
107
|
+
|
|
108
|
+
test('post-mutation-hook: state-manifest.json exists after handleCompleteTask', async () => {
|
|
109
|
+
const base = tempDir();
|
|
110
|
+
const dbPath = path.join(base, 'test.db');
|
|
111
|
+
openDatabase(dbPath);
|
|
112
|
+
createProject(base);
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
const result = await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
116
|
+
assert.ok(!('error' in result), `handler should succeed, got: ${JSON.stringify(result)}`);
|
|
117
|
+
|
|
118
|
+
const manifestPath = path.join(base, '.gsd', 'state-manifest.json');
|
|
119
|
+
assert.ok(fs.existsSync(manifestPath), 'state-manifest.json should exist after handler completes');
|
|
120
|
+
} finally {
|
|
121
|
+
closeDatabase();
|
|
122
|
+
cleanupDir(base);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test('post-mutation-hook: manifest has version 1 and includes completed task', async () => {
|
|
127
|
+
const base = tempDir();
|
|
128
|
+
const dbPath = path.join(base, 'test.db');
|
|
129
|
+
openDatabase(dbPath);
|
|
130
|
+
createProject(base);
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
134
|
+
|
|
135
|
+
const manifest = readManifest(base);
|
|
136
|
+
assert.ok(manifest !== null, 'manifest should be readable');
|
|
137
|
+
assert.strictEqual(manifest!.version, 1);
|
|
138
|
+
|
|
139
|
+
const task = manifest!.tasks.find((t) => t.id === 'T01');
|
|
140
|
+
assert.ok(task !== undefined, 'T01 should appear in manifest');
|
|
141
|
+
assert.strictEqual(task!.status, 'complete');
|
|
142
|
+
assert.strictEqual(task!.milestone_id, 'M001');
|
|
143
|
+
assert.strictEqual(task!.slice_id, 'S01');
|
|
144
|
+
} finally {
|
|
145
|
+
closeDatabase();
|
|
146
|
+
cleanupDir(base);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// ─── Post-mutation hook: non-fatal on hook failure ───────────────────────
|
|
151
|
+
|
|
152
|
+
test('post-mutation-hook: handler still returns success even if projections dir is missing', async () => {
|
|
153
|
+
// basePath with NO .gsd directory — projections will fail to find milestones
|
|
154
|
+
// but handler should still return a result (not throw)
|
|
155
|
+
const base = tempDir();
|
|
156
|
+
const dbPath = path.join(base, 'test.db');
|
|
157
|
+
openDatabase(dbPath);
|
|
158
|
+
|
|
159
|
+
// Create tasks dir but NO plan file (projections will soft-fail)
|
|
160
|
+
const tasksDir = path.join(base, '.gsd', 'milestones', 'M001', 'slices', 'S01', 'tasks');
|
|
161
|
+
fs.mkdirSync(tasksDir, { recursive: true });
|
|
162
|
+
|
|
163
|
+
try {
|
|
164
|
+
const result = await handleCompleteTask(makeCompleteTaskParams(), base);
|
|
165
|
+
// Handler should succeed (post-hook failures are non-fatal)
|
|
166
|
+
assert.ok(!('error' in result), `handler should not propagate hook errors, got: ${JSON.stringify(result)}`);
|
|
167
|
+
} finally {
|
|
168
|
+
closeDatabase();
|
|
169
|
+
cleanupDir(base);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
@@ -41,18 +41,16 @@ test("git.merge_to_main produces deprecation warning", () => {
|
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
test("getIsolationMode defaults to
|
|
44
|
+
test("getIsolationMode defaults to none when preferences have no isolation setting", () => {
|
|
45
45
|
// Validate the default via validatePreferences: when no isolation is set,
|
|
46
|
-
// preferences.git.isolation is undefined, and getIsolationMode returns "
|
|
47
|
-
//
|
|
46
|
+
// preferences.git.isolation is undefined, and getIsolationMode returns "none".
|
|
47
|
+
// Default changed from "worktree" to "none" so GSD works out of the box
|
|
48
|
+
// without preferences.md (#2480).
|
|
48
49
|
const { preferences } = validatePreferences({});
|
|
49
50
|
assert.equal(preferences.git?.isolation, undefined, "no isolation in empty prefs");
|
|
50
|
-
// The function returns "worktree" when prefs?.git?.isolation is not "none" or "branch"
|
|
51
|
-
// This is a compile-time-verifiable truth from the function body — test it directly
|
|
52
|
-
// by constructing the same conditions getIsolationMode checks.
|
|
53
51
|
const isolation = preferences.git?.isolation;
|
|
54
|
-
const expected = isolation === "
|
|
55
|
-
assert.equal(expected, "
|
|
52
|
+
const expected = isolation === "worktree" ? "worktree" : isolation === "branch" ? "branch" : "none";
|
|
53
|
+
assert.equal(expected, "none", "default isolation mode is none");
|
|
56
54
|
});
|
|
57
55
|
|
|
58
56
|
// ── Mode defaults ────────────────────────────────────────────────────────────
|
|
@@ -63,7 +61,7 @@ test("solo mode applies correct defaults", () => {
|
|
|
63
61
|
assert.equal(result.git?.push_branches, false);
|
|
64
62
|
assert.equal(result.git?.pre_merge_check, false);
|
|
65
63
|
assert.equal(result.git?.merge_strategy, "squash");
|
|
66
|
-
assert.equal(result.git?.isolation, "
|
|
64
|
+
assert.equal(result.git?.isolation, "none");
|
|
67
65
|
assert.equal(result.unique_milestone_ids, false);
|
|
68
66
|
});
|
|
69
67
|
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
// GSD — projection renderer regression tests
|
|
2
|
+
// Verifies that "done" vs "complete" status mismatch doesn't recur.
|
|
3
|
+
// Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
4
|
+
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import assert from 'node:assert/strict';
|
|
7
|
+
|
|
8
|
+
import { renderPlanContent, renderRoadmapContent } from '../workflow-projections.ts';
|
|
9
|
+
import type { SliceRow, TaskRow } from '../gsd-db.ts';
|
|
10
|
+
|
|
11
|
+
// ─── Helpers ─────────────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
function makeSliceRow(overrides?: Partial<SliceRow>): SliceRow {
|
|
14
|
+
return {
|
|
15
|
+
milestone_id: 'M001',
|
|
16
|
+
id: 'S01',
|
|
17
|
+
title: 'Test Slice',
|
|
18
|
+
status: 'pending',
|
|
19
|
+
risk: 'medium',
|
|
20
|
+
depends: [],
|
|
21
|
+
demo: 'Demo.',
|
|
22
|
+
created_at: '2026-01-01T00:00:00Z',
|
|
23
|
+
completed_at: null,
|
|
24
|
+
full_summary_md: '',
|
|
25
|
+
full_uat_md: '',
|
|
26
|
+
goal: 'Test goal',
|
|
27
|
+
success_criteria: '',
|
|
28
|
+
proof_level: '',
|
|
29
|
+
integration_closure: '',
|
|
30
|
+
observability_impact: '',
|
|
31
|
+
sequence: 0,
|
|
32
|
+
replan_triggered_at: null,
|
|
33
|
+
...overrides,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function makeTaskRow(overrides?: Partial<TaskRow>): TaskRow {
|
|
38
|
+
return {
|
|
39
|
+
milestone_id: 'M001',
|
|
40
|
+
slice_id: 'S01',
|
|
41
|
+
id: 'T01',
|
|
42
|
+
title: 'Test Task',
|
|
43
|
+
status: 'pending',
|
|
44
|
+
one_liner: '',
|
|
45
|
+
narrative: '',
|
|
46
|
+
verification_result: '',
|
|
47
|
+
duration: '',
|
|
48
|
+
completed_at: null,
|
|
49
|
+
blocker_discovered: false,
|
|
50
|
+
deviations: '',
|
|
51
|
+
known_issues: '',
|
|
52
|
+
key_files: [],
|
|
53
|
+
key_decisions: [],
|
|
54
|
+
full_summary_md: '',
|
|
55
|
+
full_plan_md: '',
|
|
56
|
+
description: 'Test description',
|
|
57
|
+
estimate: '30m',
|
|
58
|
+
files: ['src/test.ts'],
|
|
59
|
+
verify: 'npm test',
|
|
60
|
+
inputs: [],
|
|
61
|
+
expected_output: [],
|
|
62
|
+
observability_impact: '',
|
|
63
|
+
sequence: 0,
|
|
64
|
+
...overrides,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function makeMilestoneRow() {
|
|
69
|
+
return {
|
|
70
|
+
id: 'M001',
|
|
71
|
+
title: 'Test Milestone',
|
|
72
|
+
status: 'active',
|
|
73
|
+
depends_on: [],
|
|
74
|
+
created_at: '2026-01-01T00:00:00Z',
|
|
75
|
+
completed_at: null,
|
|
76
|
+
vision: 'Test vision',
|
|
77
|
+
success_criteria: [],
|
|
78
|
+
key_risks: [],
|
|
79
|
+
proof_strategy: [],
|
|
80
|
+
verification_contract: '',
|
|
81
|
+
verification_integration: '',
|
|
82
|
+
verification_operational: '',
|
|
83
|
+
verification_uat: '',
|
|
84
|
+
definition_of_done: [],
|
|
85
|
+
requirement_coverage: '',
|
|
86
|
+
boundary_map_markdown: '',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ─── renderPlanContent: checkbox regression ──────────────────────────────
|
|
91
|
+
|
|
92
|
+
test('renderPlanContent: task with status "complete" renders [x] checkbox', () => {
|
|
93
|
+
const slice = makeSliceRow();
|
|
94
|
+
const tasks = [makeTaskRow({ id: 'T01', status: 'complete', title: 'Completed Task' })];
|
|
95
|
+
|
|
96
|
+
const content = renderPlanContent(slice, tasks);
|
|
97
|
+
|
|
98
|
+
assert.match(content, /\[x\]\s+\*\*T01:/, 'complete task should have [x] checkbox');
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test('renderPlanContent: task with status "done" renders [x] checkbox', () => {
|
|
102
|
+
const slice = makeSliceRow();
|
|
103
|
+
const tasks = [makeTaskRow({ id: 'T01', status: 'done', title: 'Done Task' })];
|
|
104
|
+
|
|
105
|
+
const content = renderPlanContent(slice, tasks);
|
|
106
|
+
|
|
107
|
+
assert.match(content, /\[x\]\s+\*\*T01:/, 'done task should have [x] checkbox');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test('renderPlanContent: task with status "pending" renders [ ] checkbox', () => {
|
|
111
|
+
const slice = makeSliceRow();
|
|
112
|
+
const tasks = [makeTaskRow({ id: 'T01', status: 'pending', title: 'Pending Task' })];
|
|
113
|
+
|
|
114
|
+
const content = renderPlanContent(slice, tasks);
|
|
115
|
+
|
|
116
|
+
assert.match(content, /\[ \]\s+\*\*T01:/, 'pending task should have [ ] checkbox');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('renderPlanContent: mixed statuses render correct checkboxes', () => {
|
|
120
|
+
const slice = makeSliceRow();
|
|
121
|
+
const tasks = [
|
|
122
|
+
makeTaskRow({ id: 'T01', status: 'complete', title: 'Done One' }),
|
|
123
|
+
makeTaskRow({ id: 'T02', status: 'pending', title: 'Pending One' }),
|
|
124
|
+
makeTaskRow({ id: 'T03', status: 'done', title: 'Done Two' }),
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const content = renderPlanContent(slice, tasks);
|
|
128
|
+
|
|
129
|
+
assert.match(content, /\[x\]\s+\*\*T01:/, 'T01 (complete) should be checked');
|
|
130
|
+
assert.match(content, /\[ \]\s+\*\*T02:/, 'T02 (pending) should be unchecked');
|
|
131
|
+
assert.match(content, /\[x\]\s+\*\*T03:/, 'T03 (done) should be checked');
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// ─── renderPlanContent: format regression (parsePlan compatibility) ──────
|
|
135
|
+
|
|
136
|
+
test('renderPlanContent: format matches parsePlan regex **ID: title**', () => {
|
|
137
|
+
const slice = makeSliceRow();
|
|
138
|
+
const tasks = [makeTaskRow({ id: 'T01', status: 'pending', title: 'My Task' })];
|
|
139
|
+
|
|
140
|
+
const content = renderPlanContent(slice, tasks);
|
|
141
|
+
|
|
142
|
+
// parsePlan expects: **T01: My Task** (both ID and title inside bold)
|
|
143
|
+
// NOT: **T01:** My Task (only ID in bold)
|
|
144
|
+
assert.match(content, /\*\*T01: My Task\*\*/, 'ID and title should both be inside bold markers');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
// ─── renderRoadmapContent: status regression ─────────────────────────────
|
|
148
|
+
|
|
149
|
+
test('renderRoadmapContent: slice with status "complete" shows ✅', () => {
|
|
150
|
+
const milestone = makeMilestoneRow();
|
|
151
|
+
const slices = [makeSliceRow({ id: 'S01', status: 'complete' })];
|
|
152
|
+
|
|
153
|
+
const content = renderRoadmapContent(milestone, slices);
|
|
154
|
+
|
|
155
|
+
assert.ok(content.includes('✅'), 'complete slice should show ✅');
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('renderRoadmapContent: slice with status "done" shows ✅', () => {
|
|
159
|
+
const milestone = makeMilestoneRow();
|
|
160
|
+
const slices = [makeSliceRow({ id: 'S01', status: 'done' })];
|
|
161
|
+
|
|
162
|
+
const content = renderRoadmapContent(milestone, slices);
|
|
163
|
+
|
|
164
|
+
assert.ok(content.includes('✅'), 'done slice should show ✅');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test('renderRoadmapContent: slice with status "pending" shows ⬜', () => {
|
|
168
|
+
const milestone = makeMilestoneRow();
|
|
169
|
+
const slices = [makeSliceRow({ id: 'S01', status: 'pending' })];
|
|
170
|
+
|
|
171
|
+
const content = renderRoadmapContent(milestone, slices);
|
|
172
|
+
|
|
173
|
+
assert.ok(content.includes('⬜'), 'pending slice should show ⬜');
|
|
174
|
+
});
|
|
@@ -58,17 +58,18 @@ test("guided-resume-task prompt preserves recovery state until work is supersede
|
|
|
58
58
|
assert.doesNotMatch(prompt, /Delete the continue file after reading it/i);
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
// ─── Prompt migration: execute-task →
|
|
61
|
+
// ─── Prompt migration: execute-task → gsd_complete_task ───────────────
|
|
62
62
|
|
|
63
|
-
test("execute-task prompt references
|
|
63
|
+
test("execute-task prompt references gsd_complete_task tool", () => {
|
|
64
64
|
const prompt = readPrompt("execute-task");
|
|
65
|
-
assert.match(prompt, /
|
|
65
|
+
assert.match(prompt, /gsd_complete_task/);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
test("execute-task prompt
|
|
68
|
+
test("execute-task prompt instructs writing task summary before tool call", () => {
|
|
69
69
|
const prompt = readPrompt("execute-task");
|
|
70
|
-
//
|
|
71
|
-
assert.
|
|
70
|
+
// The prompt instructs writing the summary file AND calling the tool
|
|
71
|
+
assert.match(prompt, /\{\{taskSummaryPath\}\}/);
|
|
72
|
+
assert.match(prompt, /gsd_complete_task/);
|
|
72
73
|
});
|
|
73
74
|
|
|
74
75
|
test("execute-task prompt does not instruct LLM to toggle checkboxes manually", () => {
|
|
@@ -93,12 +94,11 @@ test("guided-execute-task prompt does not instruct manual file write", () => {
|
|
|
93
94
|
assert.doesNotMatch(prompt, /Write `?\{\{taskId\}\}-SUMMARY\.md`?.*mark it done/i);
|
|
94
95
|
});
|
|
95
96
|
|
|
96
|
-
// ─── Prompt migration: complete-slice →
|
|
97
|
-
// These tests are for T02 — expected to fail until that task runs.
|
|
97
|
+
// ─── Prompt migration: complete-slice → gsd_complete_slice ────────────
|
|
98
98
|
|
|
99
|
-
test("complete-slice prompt references
|
|
99
|
+
test("complete-slice prompt references gsd_complete_slice tool", () => {
|
|
100
100
|
const prompt = readPrompt("complete-slice");
|
|
101
|
-
assert.match(prompt, /
|
|
101
|
+
assert.match(prompt, /gsd_complete_slice/);
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
test("complete-slice prompt does not instruct LLM to toggle checkboxes manually", () => {
|
|
@@ -111,10 +111,12 @@ test("guided-complete-slice prompt references gsd_slice_complete tool", () => {
|
|
|
111
111
|
assert.match(prompt, /gsd_slice_complete/);
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
test("complete-slice prompt
|
|
114
|
+
test("complete-slice prompt instructs writing summary and UAT files before tool call", () => {
|
|
115
115
|
const prompt = readPrompt("complete-slice");
|
|
116
|
-
|
|
117
|
-
assert.
|
|
116
|
+
// The prompt instructs writing the summary AND UAT files, then calling the tool
|
|
117
|
+
assert.match(prompt, /\{\{sliceSummaryPath\}\}/);
|
|
118
|
+
assert.match(prompt, /\{\{sliceUatPath\}\}/);
|
|
119
|
+
assert.match(prompt, /gsd_complete_slice/);
|
|
118
120
|
});
|
|
119
121
|
|
|
120
122
|
test("complete-slice prompt preserves decisions and knowledge review steps", () => {
|
|
@@ -127,7 +129,6 @@ test("complete-slice prompt still contains template variables for context", () =
|
|
|
127
129
|
const prompt = readPrompt("complete-slice");
|
|
128
130
|
assert.match(prompt, /\{\{sliceSummaryPath\}\}/);
|
|
129
131
|
assert.match(prompt, /\{\{sliceUatPath\}\}/);
|
|
130
|
-
assert.match(prompt, /\{\{roadmapPath\}\}/);
|
|
131
132
|
});
|
|
132
133
|
|
|
133
134
|
test("plan-milestone prompt references DB-backed planning tool and explicitly forbids manual roadmap writes", () => {
|
|
@@ -147,12 +148,12 @@ test("plan-slice prompt no longer frames direct PLAN writes as the source of tru
|
|
|
147
148
|
assert.match(prompt, /Do \*\*not\*\* rely on direct `PLAN\.md` writes as the source of truth/i);
|
|
148
149
|
});
|
|
149
150
|
|
|
150
|
-
test("plan-slice prompt explicitly names gsd_plan_slice
|
|
151
|
+
test("plan-slice prompt explicitly names gsd_plan_slice as DB-backed planning tool", () => {
|
|
151
152
|
const prompt = readPrompt("plan-slice");
|
|
152
153
|
assert.match(prompt, /gsd_plan_slice/);
|
|
153
154
|
assert.match(prompt, /gsd_plan_task/);
|
|
154
|
-
// The prompt should describe
|
|
155
|
-
assert.match(prompt, /DB-backed
|
|
155
|
+
// The prompt should describe the DB-backed tool as the canonical write path
|
|
156
|
+
assert.match(prompt, /DB-backed tool is the canonical write path/i);
|
|
156
157
|
});
|
|
157
158
|
|
|
158
159
|
test("plan-slice prompt does not instruct direct file writes as a primary step", () => {
|
|
@@ -161,14 +162,18 @@ test("plan-slice prompt does not instruct direct file writes as a primary step",
|
|
|
161
162
|
assert.doesNotMatch(prompt, /^\d+\.\s+Write `?\{\{outputPath\}\}`?\s*$/m);
|
|
162
163
|
});
|
|
163
164
|
|
|
164
|
-
test("plan-slice prompt
|
|
165
|
+
test("plan-slice prompt clarifies gsd_plan_slice handles task persistence", () => {
|
|
165
166
|
const prompt = readPrompt("plan-slice");
|
|
166
|
-
|
|
167
|
+
// gsd_plan_slice persists tasks in its transaction — no separate gsd_plan_task calls needed
|
|
168
|
+
assert.match(prompt, /gsd_plan_task/);
|
|
169
|
+
assert.match(prompt, /gsd_plan_slice` handles task persistence/i);
|
|
167
170
|
});
|
|
168
171
|
|
|
169
|
-
test("replan-slice prompt
|
|
172
|
+
test("replan-slice prompt uses gsd_replan_slice as canonical DB-backed tool", () => {
|
|
170
173
|
const prompt = readPrompt("replan-slice");
|
|
171
|
-
assert.match(prompt, /
|
|
174
|
+
assert.match(prompt, /gsd_replan_slice/);
|
|
175
|
+
// Degraded fallback (direct file writes) was removed — DB tools are always available
|
|
176
|
+
assert.doesNotMatch(prompt, /Degraded fallback/i);
|
|
172
177
|
});
|
|
173
178
|
|
|
174
179
|
test("reassess-roadmap prompt references gsd_reassess_roadmap tool", () => {
|