gsd-pi 2.44.0 → 2.45.0-dev.6b9da3e
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/README.md +30 -12
- 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 +37 -36
- package/dist/resources/extensions/gsd/auto-prompts.js +24 -1
- package/dist/resources/extensions/gsd/auto-start.js +31 -2
- 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 +9 -6
- package/dist/resources/extensions/gsd/auto.js +30 -3
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +156 -0
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +46 -12
- package/dist/resources/extensions/gsd/commands/catalog.js +7 -1
- 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/workflow.js +5 -0
- package/dist/resources/extensions/gsd/commands-mcp-status.js +187 -0
- package/dist/resources/extensions/gsd/db-writer.js +34 -16
- package/dist/resources/extensions/gsd/doctor.js +8 -0
- package/dist/resources/extensions/gsd/git-service.js +8 -3
- package/dist/resources/extensions/gsd/gsd-db.js +12 -1
- package/dist/resources/extensions/gsd/markdown-renderer.js +1 -1
- package/dist/resources/extensions/gsd/preferences.js +9 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.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/rethink.md +78 -0
- 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/state.js +41 -3
- package/dist/resources/extensions/gsd/tools/plan-slice.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +1 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +2 -0
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +88 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +32 -2
- package/dist/resources/extensions/gsd/worktree-resolver.js +6 -0
- package/dist/resources/extensions/mcp-client/index.js +14 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- 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/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- 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 +2 -2
- 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 +5 -5
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +5 -5
- 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 +4 -4
- 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.js +1 -1
- 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.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.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.js +2 -2
- 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.js +5 -5
- 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.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.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.js +2 -2
- 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.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.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.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.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.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.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.js +2 -2
- 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.js +2 -2
- 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.js +2 -2
- 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.js +4 -4
- 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.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.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.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.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 +6 -6
- 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 +6 -6
- 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 +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/229.js +1 -1
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- 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/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +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/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-6654a8cca61a3d1c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/webpack-0a4cd455ec4197d2.js +1 -0
- package/dist/web/standalone/.next/static/css/dd4ae3f58ac9b600.css +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -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/auth-storage.test.js +6 -8
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- 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.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +20 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
- package/packages/pi-coding-agent/dist/core/session-manager.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/core/tools/edit-diff.test.js +10 -12
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.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/dist/resources/extensions/memory/storage.test.js +43 -47
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/auth-storage.ts +15 -1
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/local-model-check.ts +45 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -1
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/settings-manager.ts +9 -0
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- 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/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- 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/phases.ts +46 -48
- package/src/resources/extensions/gsd/auto-prompts.ts +24 -1
- package/src/resources/extensions/gsd/auto-start.ts +39 -2
- 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 +9 -6
- package/src/resources/extensions/gsd/auto.ts +37 -3
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +148 -0
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +48 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +7 -1
- 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/workflow.ts +8 -0
- package/src/resources/extensions/gsd/commands-mcp-status.ts +247 -0
- package/src/resources/extensions/gsd/db-writer.ts +39 -17
- package/src/resources/extensions/gsd/doctor.ts +7 -1
- package/src/resources/extensions/gsd/git-service.ts +6 -2
- package/src/resources/extensions/gsd/gsd-db.ts +16 -1
- package/src/resources/extensions/gsd/markdown-renderer.ts +1 -1
- package/src/resources/extensions/gsd/preferences.ts +11 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +2 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.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/rethink.md +78 -0
- 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/state.ts +41 -1
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +88 -0
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
- package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +465 -416
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
- 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 +210 -181
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
- package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +120 -0
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
- 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/init-wizard.test.ts +16 -18
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +89 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
- package/src/resources/extensions/gsd/tests/mcp-status.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
- package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
- package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/preferences.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +11 -7
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +176 -0
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
- package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +10 -11
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
- package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
- package/src/resources/extensions/gsd/tools/plan-slice.ts +2 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +2 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +3 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +127 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +43 -2
- package/src/resources/extensions/gsd/worktree-resolver.ts +7 -0
- package/src/resources/extensions/mcp-client/index.ts +20 -0
- package/dist/web/standalone/.next/static/chunks/4024.0de81b543b28b9fe.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- 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/{mgkxN0mGP6gSUmGPEzbk_ → rzO54ZboyINyEt7cVM_uS}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{mgkxN0mGP6gSUmGPEzbk_ → rzO54ZboyINyEt7cVM_uS}/_ssgManifest.js +0 -0
|
@@ -1,13 +1,11 @@
|
|
|
1
|
+
import { describe, test } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
1
3
|
import { mkdtempSync, mkdirSync, rmSync, realpathSync } from "node:fs";
|
|
2
4
|
import { join } from "node:path";
|
|
3
5
|
import { tmpdir } from "node:os";
|
|
4
6
|
import { spawnSync } from "node:child_process";
|
|
5
7
|
|
|
6
8
|
import { gsdRoot, _clearGsdRootCache } from "../paths.ts";
|
|
7
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
8
|
-
|
|
9
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
10
|
-
|
|
11
9
|
/** Create a tmp dir and resolve symlinks + 8.3 short names (macOS /var→/private/var, Windows RUNNER~1→runneradmin). */
|
|
12
10
|
function tmp(): string {
|
|
13
11
|
const p = mkdtempSync(join(tmpdir(), "gsd-paths-test-"));
|
|
@@ -23,91 +21,78 @@ function initGit(dir: string): void {
|
|
|
23
21
|
spawnSync("git", ["commit", "--allow-empty", "-m", "init"], { cwd: dir });
|
|
24
22
|
}
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
} finally { cleanup(root); }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
{
|
|
40
|
-
// Case 2: .gsd exists at git root, cwd is a subdirectory
|
|
41
|
-
const root = tmp();
|
|
42
|
-
try {
|
|
43
|
-
initGit(root);
|
|
44
|
-
mkdirSync(join(root, ".gsd"));
|
|
45
|
-
const sub = join(root, "src", "deep");
|
|
46
|
-
mkdirSync(sub, { recursive: true });
|
|
47
|
-
_clearGsdRootCache();
|
|
48
|
-
const result = gsdRoot(sub);
|
|
49
|
-
assertEq(result, join(root, ".gsd"), "git-root probe: finds .gsd at git root from subdirectory");
|
|
50
|
-
} finally { cleanup(root); }
|
|
51
|
-
}
|
|
24
|
+
describe('paths', () => {
|
|
25
|
+
test('Case 1: .gsd exists at basePath — fast path', () => {
|
|
26
|
+
const root = tmp();
|
|
27
|
+
try {
|
|
28
|
+
mkdirSync(join(root, ".gsd"));
|
|
29
|
+
_clearGsdRootCache();
|
|
30
|
+
const result = gsdRoot(root);
|
|
31
|
+
assert.deepStrictEqual(result, join(root, ".gsd"), "fast path: returns basePath/.gsd");
|
|
32
|
+
} finally { cleanup(root); }
|
|
33
|
+
});
|
|
52
34
|
|
|
53
|
-
{
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
// git probe returns root (no .gsd there), so walk-up takes over and finds project/.gsd
|
|
66
|
-
const result = gsdRoot(deep);
|
|
67
|
-
assertEq(result, join(project, ".gsd"), "walk-up: finds .gsd in ancestor when git root has none");
|
|
68
|
-
} finally { cleanup(root); }
|
|
69
|
-
}
|
|
35
|
+
test('Case 2: .gsd exists at git root, cwd is a subdirectory', () => {
|
|
36
|
+
const root = tmp();
|
|
37
|
+
try {
|
|
38
|
+
initGit(root);
|
|
39
|
+
mkdirSync(join(root, ".gsd"));
|
|
40
|
+
const sub = join(root, "src", "deep");
|
|
41
|
+
mkdirSync(sub, { recursive: true });
|
|
42
|
+
_clearGsdRootCache();
|
|
43
|
+
const result = gsdRoot(sub);
|
|
44
|
+
assert.deepStrictEqual(result, join(root, ".gsd"), "git-root probe: finds .gsd at git root from subdirectory");
|
|
45
|
+
} finally { cleanup(root); }
|
|
46
|
+
});
|
|
70
47
|
|
|
71
|
-
{
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
}
|
|
48
|
+
test('Case 3: .gsd in an ancestor — walk-up finds it', () => {
|
|
49
|
+
const root = tmp();
|
|
50
|
+
try {
|
|
51
|
+
initGit(root);
|
|
52
|
+
const project = join(root, "project");
|
|
53
|
+
mkdirSync(join(project, ".gsd"), { recursive: true });
|
|
54
|
+
const deep = join(project, "src", "deep");
|
|
55
|
+
mkdirSync(deep, { recursive: true });
|
|
56
|
+
_clearGsdRootCache();
|
|
57
|
+
const result = gsdRoot(deep);
|
|
58
|
+
assert.deepStrictEqual(result, join(project, ".gsd"), "walk-up: finds .gsd in ancestor when git root has none");
|
|
59
|
+
} finally { cleanup(root); }
|
|
60
|
+
});
|
|
85
61
|
|
|
86
|
-
{
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
}
|
|
62
|
+
test('Case 4: .gsd nowhere — fallback returns original basePath/.gsd', () => {
|
|
63
|
+
const root = tmp();
|
|
64
|
+
try {
|
|
65
|
+
initGit(root);
|
|
66
|
+
const sub = join(root, "src");
|
|
67
|
+
mkdirSync(sub, { recursive: true });
|
|
68
|
+
_clearGsdRootCache();
|
|
69
|
+
const result = gsdRoot(sub);
|
|
70
|
+
assert.deepStrictEqual(result, join(sub, ".gsd"), "fallback: returns basePath/.gsd when .gsd not found anywhere");
|
|
71
|
+
} finally { cleanup(root); }
|
|
72
|
+
});
|
|
98
73
|
|
|
99
|
-
{
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
} finally { cleanup(outer); }
|
|
111
|
-
}
|
|
74
|
+
test('Case 5: cache — second call returns same value without re-probing', () => {
|
|
75
|
+
const root = tmp();
|
|
76
|
+
try {
|
|
77
|
+
mkdirSync(join(root, ".gsd"));
|
|
78
|
+
_clearGsdRootCache();
|
|
79
|
+
const first = gsdRoot(root);
|
|
80
|
+
const second = gsdRoot(root);
|
|
81
|
+
assert.deepStrictEqual(first, second, "cache: same result returned on second call");
|
|
82
|
+
assert.ok(first === second, "cache: identity check (same string)");
|
|
83
|
+
} finally { cleanup(root); }
|
|
84
|
+
});
|
|
112
85
|
|
|
113
|
-
|
|
86
|
+
test('Case 6: .gsd at basePath takes precedence over ancestor .gsd', () => {
|
|
87
|
+
const outer = tmp();
|
|
88
|
+
try {
|
|
89
|
+
initGit(outer);
|
|
90
|
+
mkdirSync(join(outer, ".gsd"));
|
|
91
|
+
const inner = join(outer, "nested");
|
|
92
|
+
mkdirSync(join(inner, ".gsd"), { recursive: true });
|
|
93
|
+
_clearGsdRootCache();
|
|
94
|
+
const result = gsdRoot(inner);
|
|
95
|
+
assert.deepStrictEqual(result, join(inner, ".gsd"), "precedence: nearest .gsd wins over ancestor");
|
|
96
|
+
} finally { cleanup(outer); }
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// GSD Extension — Hook Engine Tests (Post-Unit, Pre-Dispatch, State Persistence)
|
|
2
2
|
|
|
3
|
+
import { describe, test } from 'node:test';
|
|
4
|
+
import assert from 'node:assert/strict';
|
|
3
5
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync, readFileSync } from "node:fs";
|
|
4
6
|
import { join } from "node:path";
|
|
5
7
|
import { tmpdir } from "node:os";
|
|
6
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
7
8
|
import {
|
|
8
9
|
checkPostUnitHooks,
|
|
9
10
|
getActiveHook,
|
|
@@ -20,8 +21,6 @@ import {
|
|
|
20
21
|
triggerHookManually,
|
|
21
22
|
} from "../post-unit-hooks.ts";
|
|
22
23
|
|
|
23
|
-
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
24
|
-
|
|
25
24
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
26
25
|
|
|
27
26
|
function createFixtureBase(): string {
|
|
@@ -36,14 +35,14 @@ function createFixtureBase(): string {
|
|
|
36
35
|
|
|
37
36
|
// ─── resolveHookArtifactPath ───────────────────────────────────────────────
|
|
38
37
|
|
|
39
|
-
console.log("\n=== resolveHookArtifactPath ===");
|
|
40
38
|
|
|
41
|
-
{
|
|
39
|
+
describe('post-unit-hooks', () => {
|
|
40
|
+
test('resolveHookArtifactPath', () => {
|
|
42
41
|
const base = "/project";
|
|
43
42
|
|
|
44
43
|
// Task-level
|
|
45
44
|
const taskPath = resolveHookArtifactPath(base, "M001/S01/T01", "REVIEW-PASS.md");
|
|
46
|
-
|
|
45
|
+
assert.deepStrictEqual(
|
|
47
46
|
taskPath,
|
|
48
47
|
join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-REVIEW-PASS.md"),
|
|
49
48
|
"task-level artifact path",
|
|
@@ -51,7 +50,7 @@ console.log("\n=== resolveHookArtifactPath ===");
|
|
|
51
50
|
|
|
52
51
|
// Slice-level
|
|
53
52
|
const slicePath = resolveHookArtifactPath(base, "M001/S01", "REVIEW-PASS.md");
|
|
54
|
-
|
|
53
|
+
assert.deepStrictEqual(
|
|
55
54
|
slicePath,
|
|
56
55
|
join(base, ".gsd", "milestones", "M001", "slices", "S01", "REVIEW-PASS.md"),
|
|
57
56
|
"slice-level artifact path",
|
|
@@ -59,129 +58,106 @@ console.log("\n=== resolveHookArtifactPath ===");
|
|
|
59
58
|
|
|
60
59
|
// Milestone-level
|
|
61
60
|
const milestonePath = resolveHookArtifactPath(base, "M001", "REVIEW-PASS.md");
|
|
62
|
-
|
|
61
|
+
assert.deepStrictEqual(
|
|
63
62
|
milestonePath,
|
|
64
63
|
join(base, ".gsd", "milestones", "M001", "REVIEW-PASS.md"),
|
|
65
64
|
"milestone-level artifact path",
|
|
66
65
|
);
|
|
67
|
-
}
|
|
66
|
+
});
|
|
68
67
|
|
|
69
68
|
// ─── resetHookState ────────────────────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
console.log("\n=== resetHookState ===");
|
|
72
|
-
|
|
73
|
-
{
|
|
69
|
+
test('resetHookState', () => {
|
|
74
70
|
resetHookState();
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
71
|
+
assert.deepStrictEqual(getActiveHook(), null, "no active hook after reset");
|
|
72
|
+
assert.ok(!isRetryPending(), "no retry pending after reset");
|
|
73
|
+
assert.deepStrictEqual(consumeRetryTrigger(), null, "no retry trigger after reset");
|
|
74
|
+
});
|
|
79
75
|
|
|
80
76
|
// ─── checkPostUnitHooks with no hooks configured ───────────────────────────
|
|
81
|
-
|
|
82
|
-
console.log("\n=== No hooks configured ===");
|
|
83
|
-
|
|
84
|
-
{
|
|
77
|
+
test('No hooks configured', () => {
|
|
85
78
|
resetHookState();
|
|
86
79
|
const base = createFixtureBase();
|
|
87
80
|
try {
|
|
88
81
|
const result = checkPostUnitHooks("execute-task", "M001/S01/T01", base);
|
|
89
|
-
|
|
82
|
+
assert.deepStrictEqual(result, null, "returns null when no hooks configured");
|
|
90
83
|
} finally {
|
|
91
84
|
rmSync(base, { recursive: true, force: true });
|
|
92
85
|
}
|
|
93
|
-
}
|
|
86
|
+
});
|
|
94
87
|
|
|
95
88
|
// ─── Hook units don't trigger hooks (no hook-on-hook) ──────────────────────
|
|
96
|
-
|
|
97
|
-
console.log("\n=== Hook-on-hook prevention ===");
|
|
98
|
-
|
|
99
|
-
{
|
|
89
|
+
test('Hook-on-hook prevention', () => {
|
|
100
90
|
resetHookState();
|
|
101
91
|
const base = createFixtureBase();
|
|
102
92
|
try {
|
|
103
93
|
const result = checkPostUnitHooks("hook/code-review", "M001/S01/T01", base);
|
|
104
|
-
|
|
94
|
+
assert.deepStrictEqual(result, null, "hook units don't trigger other hooks");
|
|
105
95
|
} finally {
|
|
106
96
|
rmSync(base, { recursive: true, force: true });
|
|
107
97
|
}
|
|
108
|
-
}
|
|
98
|
+
});
|
|
109
99
|
|
|
110
100
|
// ─── consumeRetryTrigger clears state ──────────────────────────────────────
|
|
111
|
-
|
|
112
|
-
console.log("\n=== consumeRetryTrigger clears state ===");
|
|
113
|
-
|
|
114
|
-
{
|
|
101
|
+
test('consumeRetryTrigger clears state', () => {
|
|
115
102
|
resetHookState();
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
}
|
|
103
|
+
assert.deepStrictEqual(consumeRetryTrigger(), null, "no trigger initially");
|
|
104
|
+
assert.ok(!isRetryPending(), "no retry initially");
|
|
105
|
+
});
|
|
119
106
|
|
|
120
107
|
// ─── Variable substitution in prompts ──────────────────────────────────────
|
|
121
|
-
|
|
122
|
-
console.log("\n=== Variable substitution ===");
|
|
123
|
-
|
|
124
|
-
{
|
|
108
|
+
test('Variable substitution', () => {
|
|
125
109
|
const base = "/project";
|
|
126
110
|
|
|
127
111
|
// 3-part ID
|
|
128
112
|
const path3 = resolveHookArtifactPath(base, "M002/S03/T05", "result.md");
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
113
|
+
assert.ok(path3.includes("M002"), "3-part ID extracts milestoneId");
|
|
114
|
+
assert.ok(path3.includes("S03"), "3-part ID extracts sliceId");
|
|
115
|
+
assert.ok(path3.includes("T05"), "3-part ID extracts taskId");
|
|
116
|
+
assert.ok(path3.includes("milestones"), "3-part ID includes milestones/ segment");
|
|
133
117
|
|
|
134
118
|
// 2-part ID
|
|
135
119
|
const path2 = resolveHookArtifactPath(base, "M002/S03", "result.md");
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
120
|
+
assert.ok(path2.includes("M002"), "2-part ID extracts milestoneId");
|
|
121
|
+
assert.ok(path2.includes("S03"), "2-part ID extracts sliceId");
|
|
122
|
+
assert.ok(path2.includes("milestones"), "2-part ID includes milestones/ segment");
|
|
139
123
|
|
|
140
124
|
// 1-part ID
|
|
141
125
|
const path1 = resolveHookArtifactPath(base, "M002", "result.md");
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
126
|
+
assert.ok(path1.includes("M002"), "1-part ID extracts milestoneId");
|
|
127
|
+
assert.ok(path1.includes("milestones"), "1-part ID includes milestones/ segment");
|
|
128
|
+
});
|
|
145
129
|
|
|
146
130
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
147
131
|
// Phase 2: Pre-Dispatch Hook Tests
|
|
148
132
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
149
|
-
|
|
150
|
-
console.log("\n=== Pre-dispatch: no hooks configured ===");
|
|
151
|
-
|
|
152
|
-
{
|
|
133
|
+
test('Pre-dispatch: no hooks configured', () => {
|
|
153
134
|
const base = createFixtureBase();
|
|
154
135
|
try {
|
|
155
136
|
const result = runPreDispatchHooks("execute-task", "M001/S01/T01", "original prompt", base);
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
137
|
+
assert.deepStrictEqual(result.action, "proceed", "proceeds when no hooks");
|
|
138
|
+
assert.deepStrictEqual(result.prompt, "original prompt", "prompt unchanged");
|
|
139
|
+
assert.deepStrictEqual(result.firedHooks.length, 0, "no hooks fired");
|
|
159
140
|
} finally {
|
|
160
141
|
rmSync(base, { recursive: true, force: true });
|
|
161
142
|
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
console.log("\n=== Pre-dispatch: hook units bypass ===");
|
|
143
|
+
});
|
|
165
144
|
|
|
166
|
-
{
|
|
145
|
+
test('Pre-dispatch: hook units bypass', () => {
|
|
167
146
|
const base = createFixtureBase();
|
|
168
147
|
try {
|
|
169
148
|
const result = runPreDispatchHooks("hook/review", "M001/S01/T01", "hook prompt", base);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
149
|
+
assert.deepStrictEqual(result.action, "proceed", "hook units always proceed");
|
|
150
|
+
assert.deepStrictEqual(result.prompt, "hook prompt", "hook prompt unchanged");
|
|
151
|
+
assert.deepStrictEqual(result.firedHooks.length, 0, "no hooks fired for hook units");
|
|
173
152
|
} finally {
|
|
174
153
|
rmSync(base, { recursive: true, force: true });
|
|
175
154
|
}
|
|
176
|
-
}
|
|
155
|
+
});
|
|
177
156
|
|
|
178
157
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
179
158
|
// Phase 3: State Persistence Tests
|
|
180
159
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
181
|
-
|
|
182
|
-
console.log("\n=== State persistence: persist and restore ===");
|
|
183
|
-
|
|
184
|
-
{
|
|
160
|
+
test('State persistence: persist and restore', () => {
|
|
185
161
|
const base = createFixtureBase();
|
|
186
162
|
try {
|
|
187
163
|
resetHookState();
|
|
@@ -189,19 +165,17 @@ console.log("\n=== State persistence: persist and restore ===");
|
|
|
189
165
|
// Persist empty state
|
|
190
166
|
persistHookState(base);
|
|
191
167
|
const filePath = join(base, ".gsd", "hook-state.json");
|
|
192
|
-
|
|
168
|
+
assert.ok(existsSync(filePath), "hook-state.json created");
|
|
193
169
|
|
|
194
170
|
const content = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
195
|
-
|
|
196
|
-
|
|
171
|
+
assert.deepStrictEqual(typeof content.savedAt, "string", "savedAt is a string");
|
|
172
|
+
assert.deepStrictEqual(Object.keys(content.cycleCounts).length, 0, "empty cycle counts");
|
|
197
173
|
} finally {
|
|
198
174
|
rmSync(base, { recursive: true, force: true });
|
|
199
175
|
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
console.log("\n=== State persistence: restore from disk ===");
|
|
176
|
+
});
|
|
203
177
|
|
|
204
|
-
{
|
|
178
|
+
test('State persistence: restore from disk', () => {
|
|
205
179
|
const base = createFixtureBase();
|
|
206
180
|
try {
|
|
207
181
|
resetHookState();
|
|
@@ -222,16 +196,14 @@ console.log("\n=== State persistence: restore from disk ===");
|
|
|
222
196
|
// Verify by persisting and reading back
|
|
223
197
|
persistHookState(base);
|
|
224
198
|
const restored = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
225
|
-
|
|
226
|
-
|
|
199
|
+
assert.deepStrictEqual(restored.cycleCounts["review/execute-task/M001/S01/T01"], 2, "cycle count restored for review");
|
|
200
|
+
assert.deepStrictEqual(restored.cycleCounts["simplify/execute-task/M001/S01/T02"], 1, "cycle count restored for simplify");
|
|
227
201
|
} finally {
|
|
228
202
|
rmSync(base, { recursive: true, force: true });
|
|
229
203
|
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
console.log("\n=== State persistence: clear ===");
|
|
204
|
+
});
|
|
233
205
|
|
|
234
|
-
{
|
|
206
|
+
test('State persistence: clear', () => {
|
|
235
207
|
const base = createFixtureBase();
|
|
236
208
|
try {
|
|
237
209
|
resetHookState();
|
|
@@ -246,77 +218,65 @@ console.log("\n=== State persistence: clear ===");
|
|
|
246
218
|
clearPersistedHookState(base);
|
|
247
219
|
|
|
248
220
|
const cleared = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
249
|
-
|
|
221
|
+
assert.deepStrictEqual(Object.keys(cleared.cycleCounts).length, 0, "cycle counts cleared");
|
|
250
222
|
} finally {
|
|
251
223
|
rmSync(base, { recursive: true, force: true });
|
|
252
224
|
}
|
|
253
|
-
}
|
|
225
|
+
});
|
|
254
226
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
{
|
|
227
|
+
test('State persistence: restore handles missing file', () => {
|
|
258
228
|
const base = createFixtureBase();
|
|
259
229
|
try {
|
|
260
230
|
resetHookState();
|
|
261
231
|
// Should not throw
|
|
262
232
|
restoreHookState(base);
|
|
263
|
-
|
|
233
|
+
assert.deepStrictEqual(getActiveHook(), null, "no active hook after restore from missing file");
|
|
264
234
|
} finally {
|
|
265
235
|
rmSync(base, { recursive: true, force: true });
|
|
266
236
|
}
|
|
267
|
-
}
|
|
237
|
+
});
|
|
268
238
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
{
|
|
239
|
+
test('State persistence: restore handles corrupt file', () => {
|
|
272
240
|
const base = createFixtureBase();
|
|
273
241
|
try {
|
|
274
242
|
resetHookState();
|
|
275
243
|
writeFileSync(join(base, ".gsd", "hook-state.json"), "not json", "utf-8");
|
|
276
244
|
// Should not throw
|
|
277
245
|
restoreHookState(base);
|
|
278
|
-
|
|
246
|
+
assert.deepStrictEqual(getActiveHook(), null, "no active hook after corrupt restore");
|
|
279
247
|
} finally {
|
|
280
248
|
rmSync(base, { recursive: true, force: true });
|
|
281
249
|
}
|
|
282
|
-
}
|
|
250
|
+
});
|
|
283
251
|
|
|
284
252
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
285
253
|
// Phase 3: Hook Status Reporting Tests
|
|
286
254
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
287
|
-
|
|
288
|
-
console.log("\n=== Hook status: no hooks ===");
|
|
289
|
-
|
|
290
|
-
{
|
|
255
|
+
test('Hook status: no hooks', () => {
|
|
291
256
|
resetHookState();
|
|
292
257
|
const entries = getHookStatus();
|
|
293
258
|
// No preferences file = no hooks
|
|
294
|
-
|
|
259
|
+
assert.deepStrictEqual(entries.length, 0, "no entries when no hooks configured");
|
|
295
260
|
|
|
296
261
|
const formatted = formatHookStatus();
|
|
297
|
-
|
|
298
|
-
}
|
|
262
|
+
assert.match(formatted, /No hooks configured/, "status message says no hooks");
|
|
263
|
+
});
|
|
299
264
|
|
|
300
265
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
301
266
|
// Phase 4: Manual Hook Trigger Tests
|
|
302
267
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
303
|
-
|
|
304
|
-
console.log("\n=== triggerHookManually: hook not found ===");
|
|
305
|
-
|
|
306
|
-
{
|
|
268
|
+
test('triggerHookManually: hook not found', () => {
|
|
307
269
|
resetHookState();
|
|
308
270
|
const base = createFixtureBase();
|
|
309
271
|
try {
|
|
310
272
|
const result = triggerHookManually("nonexistent-hook", "execute-task", "M001/S01/T01", base);
|
|
311
|
-
|
|
273
|
+
assert.deepStrictEqual(result, null, "returns null when hook not found");
|
|
312
274
|
} finally {
|
|
313
275
|
rmSync(base, { recursive: true, force: true });
|
|
314
276
|
}
|
|
315
|
-
}
|
|
277
|
+
});
|
|
316
278
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
{
|
|
279
|
+
test('triggerHookManually: with configured hook', () => {
|
|
320
280
|
resetHookState();
|
|
321
281
|
const base = createFixtureBase();
|
|
322
282
|
try {
|
|
@@ -325,16 +285,16 @@ console.log("\n=== triggerHookManually: with configured hook ===");
|
|
|
325
285
|
const result = triggerHookManually("code-review", "execute-task", "M001/S01/T01", base);
|
|
326
286
|
// Result depends on whether code-review hook is configured in preferences
|
|
327
287
|
// The function should either return null or a valid HookDispatchResult
|
|
328
|
-
|
|
288
|
+
assert.ok(result === null || typeof result === "object", "returns null or object");
|
|
329
289
|
if (result) {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
290
|
+
assert.deepStrictEqual(result.hookName, "code-review", "hook name in result");
|
|
291
|
+
assert.deepStrictEqual(result.unitType, "hook/code-review", "unit type is hook-prefixed");
|
|
292
|
+
assert.deepStrictEqual(result.unitId, "M001/S01/T01", "unit ID preserved");
|
|
293
|
+
assert.ok(typeof result.prompt === "string", "prompt is a string");
|
|
334
294
|
}
|
|
335
295
|
} finally {
|
|
336
296
|
rmSync(base, { recursive: true, force: true });
|
|
337
297
|
}
|
|
338
|
-
}
|
|
298
|
+
});
|
|
339
299
|
|
|
340
|
-
|
|
300
|
+
});
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
applyModeDefaults,
|
|
16
16
|
getIsolationMode,
|
|
17
17
|
parsePreferencesMarkdown,
|
|
18
|
+
_resetParseWarningFlag,
|
|
18
19
|
} from "../preferences.ts";
|
|
19
20
|
import type { GSDPreferences, GSDModelConfigV2, GSDPhaseModelConfig } from "../preferences.ts";
|
|
20
21
|
|
|
@@ -352,3 +353,29 @@ test("handles empty models config", () => {
|
|
|
352
353
|
assert.notEqual(prefs, null);
|
|
353
354
|
assert.equal(prefs!.models, undefined);
|
|
354
355
|
});
|
|
356
|
+
|
|
357
|
+
// ── Warn-once for unrecognized format (#2373) ────────────────────────────────
|
|
358
|
+
|
|
359
|
+
test("unrecognized format warning is emitted at most once (#2373)", () => {
|
|
360
|
+
const warnings: string[] = [];
|
|
361
|
+
const origWarn = console.warn;
|
|
362
|
+
console.warn = (...args: unknown[]) => warnings.push(args.join(" "));
|
|
363
|
+
try {
|
|
364
|
+
// Reset internal warned flag so the test starts clean
|
|
365
|
+
_resetParseWarningFlag();
|
|
366
|
+
|
|
367
|
+
const unrecognized = "This is just plain text with no frontmatter or headings.";
|
|
368
|
+
|
|
369
|
+
// Call multiple times — simulates repeated preference loads
|
|
370
|
+
parsePreferencesMarkdown(unrecognized);
|
|
371
|
+
parsePreferencesMarkdown(unrecognized);
|
|
372
|
+
parsePreferencesMarkdown(unrecognized);
|
|
373
|
+
|
|
374
|
+
const relevant = warnings.filter(w => w.includes("unrecognized format"));
|
|
375
|
+
assert.equal(relevant.length, 1, `expected exactly 1 warning, got ${relevant.length}: ${JSON.stringify(relevant)}`);
|
|
376
|
+
} finally {
|
|
377
|
+
console.warn = origWarn;
|
|
378
|
+
// Reset so other tests aren't affected by the flag state
|
|
379
|
+
_resetParseWarningFlag();
|
|
380
|
+
}
|
|
381
|
+
});
|
|
@@ -147,12 +147,12 @@ test("plan-slice prompt no longer frames direct PLAN writes as the source of tru
|
|
|
147
147
|
assert.match(prompt, /Do \*\*not\*\* rely on direct `PLAN\.md` writes as the source of truth/i);
|
|
148
148
|
});
|
|
149
149
|
|
|
150
|
-
test("plan-slice prompt explicitly names gsd_plan_slice
|
|
150
|
+
test("plan-slice prompt explicitly names gsd_plan_slice as DB-backed planning tool", () => {
|
|
151
151
|
const prompt = readPrompt("plan-slice");
|
|
152
152
|
assert.match(prompt, /gsd_plan_slice/);
|
|
153
153
|
assert.match(prompt, /gsd_plan_task/);
|
|
154
|
-
// The prompt should describe
|
|
155
|
-
assert.match(prompt, /DB-backed
|
|
154
|
+
// The prompt should describe the DB-backed tool as the canonical write path
|
|
155
|
+
assert.match(prompt, /DB-backed tool is the canonical write path/i);
|
|
156
156
|
});
|
|
157
157
|
|
|
158
158
|
test("plan-slice prompt does not instruct direct file writes as a primary step", () => {
|
|
@@ -161,14 +161,18 @@ test("plan-slice prompt does not instruct direct file writes as a primary step",
|
|
|
161
161
|
assert.doesNotMatch(prompt, /^\d+\.\s+Write `?\{\{outputPath\}\}`?\s*$/m);
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
test("plan-slice prompt
|
|
164
|
+
test("plan-slice prompt clarifies gsd_plan_slice handles task persistence", () => {
|
|
165
165
|
const prompt = readPrompt("plan-slice");
|
|
166
|
-
|
|
166
|
+
// gsd_plan_slice persists tasks in its transaction — no separate gsd_plan_task calls needed
|
|
167
|
+
assert.match(prompt, /gsd_plan_task/);
|
|
168
|
+
assert.match(prompt, /gsd_plan_slice` handles task persistence/i);
|
|
167
169
|
});
|
|
168
170
|
|
|
169
|
-
test("replan-slice prompt
|
|
171
|
+
test("replan-slice prompt uses gsd_replan_slice as canonical DB-backed tool", () => {
|
|
170
172
|
const prompt = readPrompt("replan-slice");
|
|
171
|
-
assert.match(prompt, /
|
|
173
|
+
assert.match(prompt, /gsd_replan_slice/);
|
|
174
|
+
// Degraded fallback (direct file writes) was removed — DB tools are always available
|
|
175
|
+
assert.doesNotMatch(prompt, /Degraded fallback/i);
|
|
172
176
|
});
|
|
173
177
|
|
|
174
178
|
test("reassess-roadmap prompt references gsd_reassess_roadmap tool", () => {
|