gsd-pi 2.43.0-next.8 → 2.44.0-dev.0b97ffd
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/cli.js +13 -1
- package/dist/help-text.js +24 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +21 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
- package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
- package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
- package/dist/resources/extensions/gsd/skill-health.js +3 -1
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
- package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
- package/dist/resources/extensions/gsd/workspace-index.js +46 -15
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
- 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/required-server-files.json +4 -4
- 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 +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 +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +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 +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.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 +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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- 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 +18 -18
- 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.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/app/_not-found/page-f2a7482d42a5614b.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +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 +4 -4
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
- package/packages/pi-coding-agent/dist/core/agent-session.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/compaction/branch-summarization.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.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/extensions/types.d.ts +37 -0
- 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/fallback-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
- package/packages/pi-coding-agent/dist/core/fallback-resolver.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/lifecycle-hooks.d.ts +38 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -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 +40 -3
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
- package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
- package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
- 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/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
- package/packages/pi-coding-agent/dist/core/sdk.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/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/index.d.ts +3 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +11 -199
- package/packages/pi-coding-agent/dist/main.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/agent-session.ts +13 -37
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
- package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
- package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
- package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/index.ts +7 -0
- package/packages/pi-coding-agent/src/main.ts +11 -232
- 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/auto-direct-dispatch.ts +22 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
- package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
- package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
- package/src/resources/extensions/gsd/skill-health.ts +2 -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-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-stash-merge.test.ts +3 -3
- 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/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 +390 -420
- 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.test.ts +152 -183
- 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/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/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/markdown-renderer.test.ts +150 -194
- 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/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/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/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/symlink-numbered-variants.test.ts +22 -28
- 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 +9 -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-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-milestone.ts +1 -18
- package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
- package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
- package/src/resources/extensions/gsd/workspace-index.ts +49 -18
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
- /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
// GSD Extension - Override Tests
|
|
2
2
|
// Tests for parseOverrides, appendOverride, loadActiveOverrides, formatOverridesSection, resolveAllOverrides
|
|
3
3
|
|
|
4
|
+
import { describe, test, afterEach } from 'node:test';
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
4
6
|
import { mkdtempSync, mkdirSync, readFileSync, writeFileSync, rmSync } from "node:fs";
|
|
5
7
|
import { join } from "node:path";
|
|
6
8
|
import { tmpdir } from "node:os";
|
|
7
|
-
import { createTestContext } from './test-helpers.ts';
|
|
8
9
|
import { parseOverrides, appendOverride, loadActiveOverrides, formatOverridesSection, resolveAllOverrides } from '../files.ts';
|
|
9
10
|
import type { Override } from '../files.ts';
|
|
10
11
|
|
|
11
|
-
const { assertEq, assertTrue, assertMatch, assertNoMatch, report } = createTestContext();
|
|
12
|
-
|
|
13
12
|
const tempDirs: string[] = [];
|
|
14
13
|
|
|
15
14
|
function makeTempDir(prefix: string): string {
|
|
@@ -26,106 +25,100 @@ function cleanup(): void {
|
|
|
26
25
|
tempDirs.length = 0;
|
|
27
26
|
}
|
|
28
27
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
await resolveAllOverrides(tmp);
|
|
127
|
-
assertTrue(true, "resolveAllOverrides with no file does not throw");
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
cleanup();
|
|
131
|
-
report();
|
|
28
|
+
describe('overrides', () => {
|
|
29
|
+
afterEach(() => cleanup());
|
|
30
|
+
|
|
31
|
+
test('parseOverrides: empty content', () => {
|
|
32
|
+
const result = parseOverrides(""); assert.deepStrictEqual(result.length, 0, "empty content returns no overrides");
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test('parseOverrides: single active override', () => {
|
|
36
|
+
const content = `# GSD Overrides\n\nUser-issued overrides that supersede plan document content.\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Use Postgres instead of SQLite\n**Scope:** active\n**Applied-at:** M001/S02/T03\n\n---\n`;
|
|
37
|
+
const result = parseOverrides(content);
|
|
38
|
+
assert.deepStrictEqual(result.length, 1, "parses one override");
|
|
39
|
+
assert.deepStrictEqual(result[0].timestamp, "2026-03-14T10:00:00.000Z", "correct timestamp");
|
|
40
|
+
assert.deepStrictEqual(result[0].change, "Use Postgres instead of SQLite", "correct change");
|
|
41
|
+
assert.deepStrictEqual(result[0].scope, "active", "correct scope");
|
|
42
|
+
assert.deepStrictEqual(result[0].appliedAt, "M001/S02/T03", "correct appliedAt");
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('parseOverrides: multiple overrides, mixed scopes', () => {
|
|
46
|
+
const content = `# GSD Overrides\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Use Postgres instead of SQLite\n**Scope:** resolved\n**Applied-at:** M001/S02/T03\n\n---\n\n## Override: 2026-03-14T11:00:00.000Z\n\n**Change:** Use JWT instead of session cookies\n**Scope:** active\n**Applied-at:** M001/S03/T01\n\n---\n`;
|
|
47
|
+
const result = parseOverrides(content);
|
|
48
|
+
assert.deepStrictEqual(result.length, 2, "parses two overrides");
|
|
49
|
+
assert.deepStrictEqual(result[0].scope, "resolved", "first is resolved");
|
|
50
|
+
assert.deepStrictEqual(result[1].scope, "active", "second is active");
|
|
51
|
+
assert.deepStrictEqual(result[1].change, "Use JWT instead of session cookies", "second change text");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('appendOverride: creates new file', async () => {
|
|
55
|
+
const tmp = makeTempDir("append-new");
|
|
56
|
+
await appendOverride(tmp, "Use Postgres", "M001/S01/T01");
|
|
57
|
+
const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
|
|
58
|
+
assert.ok(content.includes("# GSD Overrides"), "has header");
|
|
59
|
+
assert.ok(content.includes("**Change:** Use Postgres"), "has change");
|
|
60
|
+
assert.ok(content.includes("**Scope:** active"), "has active scope");
|
|
61
|
+
assert.ok(content.includes("**Applied-at:** M001/S01/T01"), "has appliedAt");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('appendOverride: appends to existing file', async () => {
|
|
65
|
+
const tmp = makeTempDir("append-existing");
|
|
66
|
+
await appendOverride(tmp, "First override", "M001/S01/T01");
|
|
67
|
+
await appendOverride(tmp, "Second override", "M001/S02/T02");
|
|
68
|
+
const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
|
|
69
|
+
assert.ok(content.includes("**Change:** First override"), "has first override");
|
|
70
|
+
assert.ok(content.includes("**Change:** Second override"), "has second override");
|
|
71
|
+
const parsed = parseOverrides(content);
|
|
72
|
+
assert.deepStrictEqual(parsed.length, 2, "two overrides in file");
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('loadActiveOverrides: no file', async () => {
|
|
76
|
+
const tmp = makeTempDir("load-no-file");
|
|
77
|
+
const result = await loadActiveOverrides(tmp);
|
|
78
|
+
assert.deepStrictEqual(result.length, 0, "returns empty when no file");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test('loadActiveOverrides: filters to active only', async () => {
|
|
82
|
+
const tmp = makeTempDir("load-filter");
|
|
83
|
+
const content = `# GSD Overrides\n\n---\n\n## Override: 2026-03-14T10:00:00.000Z\n\n**Change:** Resolved change\n**Scope:** resolved\n**Applied-at:** M001/S01/T01\n\n---\n\n## Override: 2026-03-14T11:00:00.000Z\n\n**Change:** Active change\n**Scope:** active\n**Applied-at:** M001/S02/T01\n\n---\n`;
|
|
84
|
+
writeFileSync(join(tmp, ".gsd", "OVERRIDES.md"), content, "utf-8");
|
|
85
|
+
const result = await loadActiveOverrides(tmp);
|
|
86
|
+
assert.deepStrictEqual(result.length, 1, "only one active override");
|
|
87
|
+
assert.deepStrictEqual(result[0].change, "Active change", "correct active change");
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('formatOverridesSection: empty array', () => {
|
|
91
|
+
const result = formatOverridesSection([]); assert.deepStrictEqual(result, "", "empty overrides returns empty string");
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test('formatOverridesSection: formats section', () => {
|
|
95
|
+
const overrides: Override[] = [
|
|
96
|
+
{ timestamp: "2026-03-14T10:00:00.000Z", change: "Use Postgres", scope: "active", appliedAt: "M001/S01/T01" },
|
|
97
|
+
];
|
|
98
|
+
const result = formatOverridesSection(overrides);
|
|
99
|
+
assert.ok(result.includes("## Active Overrides (supersede plan content)"), "has header");
|
|
100
|
+
assert.ok(result.includes("**Use Postgres**"), "has change text");
|
|
101
|
+
assert.ok(result.includes("supersede any conflicting content"), "has instruction");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('resolveAllOverrides: marks all as resolved', async () => {
|
|
105
|
+
const tmp = makeTempDir("resolve-all");
|
|
106
|
+
await appendOverride(tmp, "First", "M001/S01/T01");
|
|
107
|
+
await appendOverride(tmp, "Second", "M001/S02/T01");
|
|
108
|
+
let active = await loadActiveOverrides(tmp);
|
|
109
|
+
assert.deepStrictEqual(active.length, 2, "two active before resolve");
|
|
110
|
+
await resolveAllOverrides(tmp);
|
|
111
|
+
active = await loadActiveOverrides(tmp);
|
|
112
|
+
assert.deepStrictEqual(active.length, 0, "no active after resolve");
|
|
113
|
+
const content = readFileSync(join(tmp, ".gsd", "OVERRIDES.md"), "utf-8");
|
|
114
|
+
const allOverrides = parseOverrides(content);
|
|
115
|
+
assert.deepStrictEqual(allOverrides.length, 2, "still two overrides total");
|
|
116
|
+
assert.ok(allOverrides.every(o => o.scope === "resolved"), "all resolved");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('resolveAllOverrides: no file — no error', async () => {
|
|
120
|
+
const tmp = makeTempDir("resolve-no-file");
|
|
121
|
+
await resolveAllOverrides(tmp);
|
|
122
|
+
assert.ok(true, "resolveAllOverrides with no file does not throw");
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
* restored after a coordinator crash, with PID liveness filtering.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import { describe, test } from 'node:test';
|
|
9
|
+
import assert from 'node:assert/strict';
|
|
8
10
|
import {
|
|
9
11
|
mkdtempSync,
|
|
10
12
|
mkdirSync,
|
|
@@ -24,10 +26,6 @@ import {
|
|
|
24
26
|
type PersistedState,
|
|
25
27
|
} from "../parallel-orchestrator.ts";
|
|
26
28
|
import { writeSessionStatus, readAllSessionStatuses, removeSessionStatus } from "../session-status-io.ts";
|
|
27
|
-
import { createTestContext } from './test-helpers.ts';
|
|
28
|
-
|
|
29
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
30
|
-
|
|
31
29
|
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
32
30
|
|
|
33
31
|
function makeTempDir(): string {
|
|
@@ -57,8 +55,9 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
57
55
|
|
|
58
56
|
// ─── Tests ────────────────────────────────────────────────────────────────────
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
{
|
|
58
|
+
|
|
59
|
+
describe('parallel-crash-recovery', () => {
|
|
60
|
+
test('Test 1: persistState writes valid JSON', () => {
|
|
62
61
|
const basePath = makeTempDir();
|
|
63
62
|
try {
|
|
64
63
|
// We can't call persistState directly without internal state set up,
|
|
@@ -82,29 +81,27 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
82
81
|
|
|
83
82
|
const raw = readFileSync(stateFilePath(basePath), "utf-8");
|
|
84
83
|
const parsed = JSON.parse(raw) as PersistedState;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
84
|
+
assert.deepStrictEqual(parsed.active, true, "persistState: active field preserved");
|
|
85
|
+
assert.deepStrictEqual(parsed.workers.length, 1, "persistState: worker count preserved");
|
|
86
|
+
assert.deepStrictEqual(parsed.workers[0].milestoneId, "M001", "persistState: milestoneId preserved");
|
|
87
|
+
assert.deepStrictEqual(parsed.workers[0].cost, 0.15, "persistState: cost preserved");
|
|
88
|
+
assert.deepStrictEqual(parsed.totalCost, 0.15, "persistState: totalCost preserved");
|
|
90
89
|
} finally {
|
|
91
90
|
rmSync(basePath, { recursive: true, force: true });
|
|
92
91
|
}
|
|
93
|
-
}
|
|
92
|
+
});
|
|
94
93
|
|
|
95
|
-
|
|
96
|
-
{
|
|
94
|
+
test('Test 2: restoreState returns null for missing file', () => {
|
|
97
95
|
const basePath = makeTempDir();
|
|
98
96
|
try {
|
|
99
97
|
const result = restoreState(basePath);
|
|
100
|
-
|
|
98
|
+
assert.deepStrictEqual(result, null, "restoreState: returns null when no state file");
|
|
101
99
|
} finally {
|
|
102
100
|
rmSync(basePath, { recursive: true, force: true });
|
|
103
101
|
}
|
|
104
|
-
}
|
|
102
|
+
});
|
|
105
103
|
|
|
106
|
-
|
|
107
|
-
{
|
|
104
|
+
test('Test 3: restoreState filters dead PIDs', () => {
|
|
108
105
|
const basePath = makeTempDir();
|
|
109
106
|
try {
|
|
110
107
|
// PID 99999999 is almost certainly not alive
|
|
@@ -136,15 +133,14 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
136
133
|
|
|
137
134
|
const result = restoreState(basePath);
|
|
138
135
|
// Both PIDs are dead, so result should be null and file should be cleaned up
|
|
139
|
-
|
|
140
|
-
|
|
136
|
+
assert.deepStrictEqual(result, null, "restoreState: returns null when all PIDs dead");
|
|
137
|
+
assert.ok(!existsSync(stateFilePath(basePath)), "restoreState: cleans up state file when all dead");
|
|
141
138
|
} finally {
|
|
142
139
|
rmSync(basePath, { recursive: true, force: true });
|
|
143
140
|
}
|
|
144
|
-
}
|
|
141
|
+
});
|
|
145
142
|
|
|
146
|
-
|
|
147
|
-
{
|
|
143
|
+
test('Test 4: restoreState keeps alive PIDs', () => {
|
|
148
144
|
const basePath = makeTempDir();
|
|
149
145
|
try {
|
|
150
146
|
// Use current process PID (definitely alive)
|
|
@@ -176,18 +172,17 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
176
172
|
writeStateFile(basePath, state);
|
|
177
173
|
|
|
178
174
|
const result = restoreState(basePath);
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
175
|
+
assert.ok(result !== null, "restoreState: returns state when alive PID exists");
|
|
176
|
+
assert.deepStrictEqual(result!.workers.length, 1, "restoreState: filters out dead PID");
|
|
177
|
+
assert.deepStrictEqual(result!.workers[0].milestoneId, "M001", "restoreState: keeps alive worker");
|
|
178
|
+
assert.deepStrictEqual(result!.workers[0].pid, process.pid, "restoreState: preserves PID");
|
|
179
|
+
assert.deepStrictEqual(result!.workers[0].completedUnits, 5, "restoreState: preserves progress");
|
|
184
180
|
} finally {
|
|
185
181
|
rmSync(basePath, { recursive: true, force: true });
|
|
186
182
|
}
|
|
187
|
-
}
|
|
183
|
+
});
|
|
188
184
|
|
|
189
|
-
|
|
190
|
-
{
|
|
185
|
+
test('Test 5: restoreState skips stopped/error workers even with alive PIDs', () => {
|
|
191
186
|
const basePath = makeTempDir();
|
|
192
187
|
try {
|
|
193
188
|
const state = makePersistedState({
|
|
@@ -207,14 +202,13 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
207
202
|
writeStateFile(basePath, state);
|
|
208
203
|
|
|
209
204
|
const result = restoreState(basePath);
|
|
210
|
-
|
|
205
|
+
assert.deepStrictEqual(result, null, "restoreState: skips stopped workers");
|
|
211
206
|
} finally {
|
|
212
207
|
rmSync(basePath, { recursive: true, force: true });
|
|
213
208
|
}
|
|
214
|
-
}
|
|
209
|
+
});
|
|
215
210
|
|
|
216
|
-
|
|
217
|
-
{
|
|
211
|
+
test('Test 6: orphan detection finds stale sessions', () => {
|
|
218
212
|
const basePath = makeTempDir();
|
|
219
213
|
try {
|
|
220
214
|
// Write a session status with a dead PID
|
|
@@ -246,7 +240,7 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
246
240
|
|
|
247
241
|
// Read all sessions — both should exist initially
|
|
248
242
|
const before = readAllSessionStatuses(basePath);
|
|
249
|
-
|
|
243
|
+
assert.deepStrictEqual(before.length, 2, "orphan: both sessions exist before detection");
|
|
250
244
|
|
|
251
245
|
// Now simulate orphan detection logic (same as prepareParallelStart)
|
|
252
246
|
const sessions = readAllSessionStatuses(basePath);
|
|
@@ -265,34 +259,33 @@ function makePersistedState(overrides: Partial<PersistedState> = {}): PersistedS
|
|
|
265
259
|
}
|
|
266
260
|
}
|
|
267
261
|
|
|
268
|
-
|
|
262
|
+
assert.ok(orphans.length === 2, "orphan: detected both sessions");
|
|
269
263
|
const deadOrphan = orphans.find(o => o.milestoneId === "M001");
|
|
270
|
-
|
|
264
|
+
assert.ok(deadOrphan !== undefined && !deadOrphan.alive, "orphan: M001 detected as dead");
|
|
271
265
|
const aliveOrphan = orphans.find(o => o.milestoneId === "M002");
|
|
272
|
-
|
|
266
|
+
assert.ok(aliveOrphan !== undefined && aliveOrphan.alive, "orphan: M002 detected as alive");
|
|
273
267
|
|
|
274
268
|
// Dead session should be cleaned up
|
|
275
269
|
const after = readAllSessionStatuses(basePath);
|
|
276
|
-
|
|
277
|
-
|
|
270
|
+
assert.deepStrictEqual(after.length, 1, "orphan: dead session cleaned up");
|
|
271
|
+
assert.deepStrictEqual(after[0].milestoneId, "M002", "orphan: alive session remains");
|
|
278
272
|
} finally {
|
|
279
273
|
rmSync(basePath, { recursive: true, force: true });
|
|
280
274
|
}
|
|
281
|
-
}
|
|
275
|
+
});
|
|
282
276
|
|
|
283
|
-
|
|
284
|
-
{
|
|
277
|
+
test('Test 7: restoreState handles corrupt JSON gracefully', () => {
|
|
285
278
|
const basePath = makeTempDir();
|
|
286
279
|
try {
|
|
287
280
|
writeFileSync(stateFilePath(basePath), "{ not valid json !!!", "utf-8");
|
|
288
281
|
const result = restoreState(basePath);
|
|
289
|
-
|
|
282
|
+
assert.deepStrictEqual(result, null, "restoreState: returns null for corrupt JSON");
|
|
290
283
|
} finally {
|
|
291
284
|
rmSync(basePath, { recursive: true, force: true });
|
|
292
285
|
}
|
|
293
|
-
}
|
|
286
|
+
});
|
|
294
287
|
|
|
295
288
|
// Clean up module state
|
|
296
289
|
resetOrchestrator();
|
|
297
290
|
|
|
298
|
-
|
|
291
|
+
});
|
|
@@ -10,12 +10,11 @@
|
|
|
10
10
|
* 6. completedUnits counter increments on assistant message_end
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import assert from 'node:assert/strict';
|
|
13
14
|
import { describe, it, after } from "node:test";
|
|
14
15
|
import { mkdtempSync, rmSync, writeFileSync, mkdirSync } from "node:fs";
|
|
15
16
|
import { join } from "node:path";
|
|
16
17
|
import { tmpdir } from "node:os";
|
|
17
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
18
|
-
|
|
19
18
|
// We test processWorkerLine indirectly via the module's exported state.
|
|
20
19
|
// To test the internal function, we use the exported accessors.
|
|
21
20
|
import {
|
|
@@ -27,8 +26,6 @@ import {
|
|
|
27
26
|
refreshWorkerStatuses,
|
|
28
27
|
} from "../parallel-orchestrator.ts";
|
|
29
28
|
|
|
30
|
-
const { assertEq, assertTrue, report } = createTestContext();
|
|
31
|
-
|
|
32
29
|
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
33
30
|
|
|
34
31
|
/** Create a minimal message_end NDJSON line with cost data. */
|
|
@@ -52,7 +49,7 @@ function makeMessageEndLine(cost: number, role = "assistant"): string {
|
|
|
52
49
|
describe("parallel-worker-monitoring", () => {
|
|
53
50
|
after(() => {
|
|
54
51
|
resetOrchestrator();
|
|
55
|
-
|
|
52
|
+
|
|
56
53
|
});
|
|
57
54
|
|
|
58
55
|
// Note: processWorkerLine is not exported, so we test the observable effects
|
|
@@ -61,39 +58,39 @@ describe("parallel-worker-monitoring", () => {
|
|
|
61
58
|
|
|
62
59
|
it("isBudgetExceeded returns false when no state exists", () => {
|
|
63
60
|
resetOrchestrator();
|
|
64
|
-
|
|
61
|
+
assert.ok(!isBudgetExceeded(), "no state = not exceeded");
|
|
65
62
|
});
|
|
66
63
|
|
|
67
64
|
it("isBudgetExceeded returns false when no ceiling configured", () => {
|
|
68
65
|
resetOrchestrator();
|
|
69
66
|
// Can't directly set state without startParallel, so test the accessor
|
|
70
|
-
|
|
67
|
+
assert.ok(!isBudgetExceeded(), "no ceiling = not exceeded");
|
|
71
68
|
});
|
|
72
69
|
|
|
73
70
|
it("getAggregateCost returns 0 when no state exists", () => {
|
|
74
71
|
resetOrchestrator();
|
|
75
|
-
|
|
72
|
+
assert.deepStrictEqual(getAggregateCost(), 0, "no state = zero cost");
|
|
76
73
|
});
|
|
77
74
|
|
|
78
75
|
it("isParallelActive returns false after reset", () => {
|
|
79
76
|
resetOrchestrator();
|
|
80
|
-
|
|
77
|
+
assert.ok(!isParallelActive(), "reset = not active");
|
|
81
78
|
});
|
|
82
79
|
|
|
83
80
|
it("getWorkerStatuses returns empty array when no state", () => {
|
|
84
81
|
resetOrchestrator();
|
|
85
|
-
|
|
82
|
+
assert.deepStrictEqual(getWorkerStatuses().length, 0, "no state = empty workers");
|
|
86
83
|
});
|
|
87
84
|
|
|
88
85
|
it("NDJSON message_end format matches expected structure", () => {
|
|
89
86
|
// Verify the NDJSON line format we expect from workers
|
|
90
87
|
const line = makeMessageEndLine(0.05);
|
|
91
88
|
const parsed = JSON.parse(line);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
89
|
+
assert.deepStrictEqual(parsed.type, "message_end", "type is message_end");
|
|
90
|
+
assert.deepStrictEqual(parsed.message.role, "assistant", "role is assistant");
|
|
91
|
+
assert.deepStrictEqual(parsed.message.usage.cost.total, 0.05, "cost.total is 0.05");
|
|
92
|
+
assert.ok(typeof parsed.message.usage.input === "number", "input is number");
|
|
93
|
+
assert.ok(typeof parsed.message.usage.output === "number", "output is number");
|
|
97
94
|
});
|
|
98
95
|
|
|
99
96
|
it("malformed JSON does not throw (tested via parse safety)", () => {
|
|
@@ -111,7 +108,7 @@ describe("parallel-worker-monitoring", () => {
|
|
|
111
108
|
JSON.parse(line);
|
|
112
109
|
} catch {
|
|
113
110
|
// Expected — processWorkerLine catches this silently
|
|
114
|
-
|
|
111
|
+
assert.ok(true, `malformed line "${line.slice(0, 20)}" handled`);
|
|
115
112
|
}
|
|
116
113
|
}
|
|
117
114
|
});
|
|
@@ -122,25 +119,25 @@ describe("parallel-worker-monitoring", () => {
|
|
|
122
119
|
let total = 0;
|
|
123
120
|
for (const c of costs) total += c;
|
|
124
121
|
// Floating point: round to 2 decimal places for comparison
|
|
125
|
-
|
|
122
|
+
assert.deepStrictEqual(Math.round(total * 100) / 100, 0.28, "cost sum is correct");
|
|
126
123
|
});
|
|
127
124
|
|
|
128
125
|
it("budget ceiling comparison works with typical values", () => {
|
|
129
126
|
// Test the ceiling check pattern
|
|
130
127
|
const ceiling = 5.0;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
128
|
+
assert.ok(0 < ceiling, "0 is under ceiling");
|
|
129
|
+
assert.ok(4.99 < ceiling, "4.99 is under ceiling");
|
|
130
|
+
assert.ok(!(5.0 < ceiling), "5.0 is at ceiling");
|
|
131
|
+
assert.ok(!(5.01 < ceiling), "5.01 is over ceiling");
|
|
135
132
|
});
|
|
136
133
|
|
|
137
134
|
it("worker spawn args include --mode json", () => {
|
|
138
135
|
// Verify the spawn command includes JSON mode for NDJSON output.
|
|
139
136
|
// We can't easily test the actual spawn, but we verify the args pattern.
|
|
140
137
|
const expectedArgs = ["--mode", "json", "--print", "/gsd auto"];
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
assert.ok(expectedArgs.includes("--mode"), "args include --mode");
|
|
139
|
+
assert.ok(expectedArgs.includes("json"), "args include json");
|
|
140
|
+
assert.ok(expectedArgs.indexOf("--mode") < expectedArgs.indexOf("json"),
|
|
144
141
|
"--mode comes before json");
|
|
145
142
|
});
|
|
146
143
|
|
|
@@ -168,8 +165,8 @@ describe("parallel-worker-monitoring", () => {
|
|
|
168
165
|
}, null, 2));
|
|
169
166
|
refreshWorkerStatuses(base, { restoreIfNeeded: true });
|
|
170
167
|
const workers = getWorkerStatuses();
|
|
171
|
-
|
|
172
|
-
|
|
168
|
+
assert.deepStrictEqual(workers.length, 1, "restored one worker");
|
|
169
|
+
assert.deepStrictEqual(workers[0].milestoneId, "M001", "worker restored from persisted state");
|
|
173
170
|
} finally {
|
|
174
171
|
resetOrchestrator();
|
|
175
172
|
rmSync(base, { recursive: true, force: true });
|
|
@@ -193,8 +190,8 @@ describe("parallel-worker-monitoring", () => {
|
|
|
193
190
|
}, null, 2));
|
|
194
191
|
refreshWorkerStatuses(base, { restoreIfNeeded: true });
|
|
195
192
|
const workers = getWorkerStatuses();
|
|
196
|
-
|
|
197
|
-
|
|
193
|
+
assert.deepStrictEqual(workers[0].state, "running", "live session status restored");
|
|
194
|
+
assert.deepStrictEqual(workers[0].completedUnits, 3, "completed units restored from status file");
|
|
198
195
|
} finally {
|
|
199
196
|
resetOrchestrator();
|
|
200
197
|
rmSync(base, { recursive: true, force: true });
|