gsd-pi 2.44.0-dev.848dd4c → 2.44.0
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 +12 -30
- package/dist/resources/extensions/gsd/auto-start.js +0 -10
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +0 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/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 +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 +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 +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 +14 -14
- 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 → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.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 +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +8 -6
- 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 +26 -24
- 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 +48 -29
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +44 -34
- 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 +34 -30
- 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 +12 -10
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +47 -43
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +43 -31
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +45 -40
- 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/resources/extensions/memory/storage.test.ts +74 -74
- package/src/resources/extensions/gsd/auto-start.ts +0 -14
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +0 -8
- 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 +16 -14
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +57 -43
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +13 -11
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +523 -465
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +75 -73
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +56 -34
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +656 -533
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +143 -165
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +52 -29
- package/src/resources/extensions/gsd/tests/captures.test.ts +176 -148
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +33 -32
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +143 -141
- 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 +59 -38
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +263 -228
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +302 -250
- package/src/resources/extensions/gsd/tests/context-store.test.ts +367 -354
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +72 -68
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +106 -92
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +35 -27
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +237 -220
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +420 -390
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +92 -76
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +83 -68
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +183 -152
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +101 -78
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +227 -192
- package/src/resources/extensions/gsd/tests/detection.test.ts +278 -232
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +34 -30
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +180 -164
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +49 -43
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +32 -28
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +29 -27
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +38 -34
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +75 -54
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +32 -21
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +97 -72
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +44 -38
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +145 -104
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +106 -84
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +60 -54
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +93 -72
- package/src/resources/extensions/gsd/tests/doctor.test.ts +134 -104
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +131 -123
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +24 -20
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +57 -48
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +42 -30
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +206 -198
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/git-service.test.ts +388 -285
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +39 -31
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +69 -63
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +264 -255
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +119 -108
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +103 -81
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +262 -229
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +102 -81
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +18 -16
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +46 -41
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +53 -42
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +91 -75
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +194 -150
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +125 -101
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +54 -45
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +93 -80
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +66 -57
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +93 -83
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +170 -161
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +141 -125
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +131 -107
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +96 -87
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +164 -125
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +94 -81
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +36 -35
- package/src/resources/extensions/gsd/tests/overrides.test.ts +106 -99
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +47 -40
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +28 -25
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +83 -66
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +77 -54
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +115 -68
- package/src/resources/extensions/gsd/tests/parsers.test.ts +611 -546
- package/src/resources/extensions/gsd/tests/paths.test.ts +87 -72
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +117 -77
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +119 -93
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +82 -70
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +55 -42
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +73 -45
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +38 -28
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +80 -73
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +74 -71
- package/src/resources/extensions/gsd/tests/requirements.test.ts +75 -70
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +66 -44
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +181 -114
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +65 -63
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +128 -66
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +25 -18
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +28 -22
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +56 -54
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +25 -23
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +11 -9
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +82 -66
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +47 -46
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +22 -20
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +86 -84
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +43 -41
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +96 -94
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +13 -11
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +29 -27
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +52 -50
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +13 -10
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +18 -14
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +39 -38
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +21 -17
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +30 -25
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +22 -15
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +66 -59
- package/src/resources/extensions/gsd/tests/worktree.test.ts +50 -44
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +0 -100
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +0 -63
- /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_ssgManifest.js +0 -0
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
// Tests for extractUatType — the core UAT classification primitive — plus
|
|
2
|
+
// prompt template loading and dispatch precondition assertions (via
|
|
3
|
+
// resolveSliceFile / extractUatType on real fixture files).
|
|
4
|
+
//
|
|
5
|
+
// Sections:
|
|
6
|
+
// (a)–(j) extractUatType classification (17 assertions from T01)
|
|
7
|
+
// (k) run-uat prompt template loading and content integrity (8 assertions)
|
|
8
|
+
// (l) dispatch precondition assertions via resolveSliceFile (4 assertions)
|
|
9
|
+
// (m) non-artifact UAT skip: human-experience UATs are not dispatched (1 assertion)
|
|
10
|
+
// (n) stale replay guard: existing UAT-RESULT never re-dispatches (1 assertion)
|
|
11
|
+
|
|
3
12
|
import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
4
13
|
import { join, dirname } from 'node:path';
|
|
5
14
|
import { tmpdir } from 'node:os';
|
|
@@ -8,6 +17,11 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
17
|
import { extractUatType } from '../files.ts';
|
|
9
18
|
import { resolveSliceFile } from '../paths.ts';
|
|
10
19
|
import { checkNeedsRunUat } from '../auto-prompts.ts';
|
|
20
|
+
import { createTestContext } from './test-helpers.ts';
|
|
21
|
+
|
|
22
|
+
// ─── Worktree-aware prompt loader ──────────────────────────────────────────
|
|
23
|
+
// Resolves prompts relative to this test file so the worktree copy is used
|
|
24
|
+
// instead of the main checkout copy (matches complete-milestone.test.ts pattern).
|
|
11
25
|
|
|
12
26
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
27
|
const worktreePromptsDir = join(__dirname, '..', 'prompts');
|
|
@@ -25,6 +39,10 @@ function loadPromptFromWorktree(name: string, vars: Record<string, string> = {})
|
|
|
25
39
|
return content.trim();
|
|
26
40
|
}
|
|
27
41
|
|
|
42
|
+
|
|
43
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
44
|
+
// ─── Fixture helpers ───────────────────────────────────────────────────────
|
|
45
|
+
|
|
28
46
|
function createFixtureBase(): string {
|
|
29
47
|
const base = mkdtempSync(join(tmpdir(), 'gsd-run-uat-test-'));
|
|
30
48
|
mkdirSync(join(base, '.gsd', 'milestones'), { recursive: true });
|
|
@@ -51,129 +69,154 @@ function makeUatContent(mode: string): string {
|
|
|
51
69
|
return `# UAT File\n\n## UAT Type\n\n- UAT mode: ${mode}\n- Some other bullet: value\n`;
|
|
52
70
|
}
|
|
53
71
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
73
|
+
// Tests
|
|
74
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
75
|
+
|
|
76
|
+
async function main(): Promise<void> {
|
|
77
|
+
|
|
78
|
+
// ─── (a) artifact-driven ──────────────────────────────────────────────────
|
|
79
|
+
console.log('\n── (a) artifact-driven');
|
|
80
|
+
|
|
81
|
+
assertEq(
|
|
57
82
|
extractUatType(makeUatContent('artifact-driven')),
|
|
58
83
|
'artifact-driven',
|
|
59
84
|
'plain artifact-driven → artifact-driven',
|
|
60
85
|
);
|
|
61
|
-
|
|
86
|
+
|
|
87
|
+
assertEq(
|
|
62
88
|
extractUatType('## UAT Type\n\n- UAT mode: artifact-driven\n'),
|
|
63
89
|
'artifact-driven',
|
|
64
90
|
'minimal content, artifact-driven',
|
|
65
91
|
);
|
|
66
|
-
});
|
|
67
92
|
|
|
68
|
-
|
|
69
|
-
|
|
93
|
+
// ─── (b) live-runtime ─────────────────────────────────────────────────────
|
|
94
|
+
console.log('\n── (b) live-runtime');
|
|
95
|
+
|
|
96
|
+
assertEq(
|
|
70
97
|
extractUatType(makeUatContent('live-runtime')),
|
|
71
98
|
'live-runtime',
|
|
72
99
|
'plain live-runtime → live-runtime',
|
|
73
100
|
);
|
|
74
|
-
});
|
|
75
101
|
|
|
76
|
-
|
|
77
|
-
|
|
102
|
+
// ─── (c) human-experience ─────────────────────────────────────────────────
|
|
103
|
+
console.log('\n── (c) human-experience');
|
|
104
|
+
|
|
105
|
+
assertEq(
|
|
78
106
|
extractUatType(makeUatContent('human-experience')),
|
|
79
107
|
'human-experience',
|
|
80
108
|
'plain human-experience → human-experience',
|
|
81
109
|
);
|
|
82
|
-
});
|
|
83
110
|
|
|
84
|
-
|
|
85
|
-
|
|
111
|
+
// ─── (d) mixed standalone ─────────────────────────────────────────────────
|
|
112
|
+
console.log('\n── (d) mixed standalone');
|
|
113
|
+
|
|
114
|
+
assertEq(
|
|
86
115
|
extractUatType(makeUatContent('mixed')),
|
|
87
116
|
'mixed',
|
|
88
117
|
'plain mixed → mixed',
|
|
89
118
|
);
|
|
90
|
-
});
|
|
91
119
|
|
|
92
|
-
|
|
93
|
-
|
|
120
|
+
// ─── (e) mixed with parenthetical ─────────────────────────────────────────
|
|
121
|
+
console.log('\n── (e) mixed parenthetical');
|
|
122
|
+
|
|
123
|
+
assertEq(
|
|
94
124
|
extractUatType(makeUatContent('mixed (artifact-driven + live-runtime)')),
|
|
95
125
|
'mixed',
|
|
96
126
|
'mixed (artifact-driven + live-runtime) → mixed (leading keyword only)',
|
|
97
127
|
);
|
|
98
|
-
|
|
128
|
+
|
|
129
|
+
assertEq(
|
|
99
130
|
extractUatType(makeUatContent('mixed (some other description)')),
|
|
100
131
|
'mixed',
|
|
101
132
|
'mixed with arbitrary parenthetical → mixed',
|
|
102
133
|
);
|
|
103
|
-
});
|
|
104
134
|
|
|
105
|
-
|
|
106
|
-
|
|
135
|
+
// ─── (f) missing ## UAT Type section ──────────────────────────────────────
|
|
136
|
+
console.log('\n── (f) missing UAT Type section');
|
|
137
|
+
|
|
138
|
+
assertEq(
|
|
107
139
|
extractUatType('# UAT File\n\n## Overview\n\nSome content.\n'),
|
|
108
140
|
undefined,
|
|
109
141
|
'no ## UAT Type section → undefined',
|
|
110
142
|
);
|
|
111
|
-
|
|
143
|
+
|
|
144
|
+
assertEq(
|
|
112
145
|
extractUatType(''),
|
|
113
146
|
undefined,
|
|
114
147
|
'empty content → undefined',
|
|
115
148
|
);
|
|
116
|
-
});
|
|
117
149
|
|
|
118
|
-
|
|
119
|
-
|
|
150
|
+
// ─── (g) ## UAT Type present but no UAT mode: bullet ─────────────────────
|
|
151
|
+
console.log('\n── (g) UAT Type section present, no UAT mode: bullet');
|
|
152
|
+
|
|
153
|
+
assertEq(
|
|
120
154
|
extractUatType('## UAT Type\n\n- Some other bullet: value\n- Another bullet\n'),
|
|
121
155
|
undefined,
|
|
122
156
|
'section present but no UAT mode: bullet → undefined',
|
|
123
157
|
);
|
|
124
|
-
|
|
158
|
+
|
|
159
|
+
assertEq(
|
|
125
160
|
extractUatType('## UAT Type\n\n'),
|
|
126
161
|
undefined,
|
|
127
162
|
'section present but empty → undefined',
|
|
128
163
|
);
|
|
129
|
-
});
|
|
130
164
|
|
|
131
|
-
|
|
132
|
-
|
|
165
|
+
// ─── (h) unknown keyword ──────────────────────────────────────────────────
|
|
166
|
+
console.log('\n── (h) unknown keyword');
|
|
167
|
+
|
|
168
|
+
assertEq(
|
|
133
169
|
extractUatType(makeUatContent('automated')),
|
|
134
170
|
undefined,
|
|
135
171
|
'unknown keyword automated → undefined',
|
|
136
172
|
);
|
|
137
|
-
|
|
173
|
+
|
|
174
|
+
assertEq(
|
|
138
175
|
extractUatType(makeUatContent('fully-automated')),
|
|
139
176
|
undefined,
|
|
140
177
|
'unknown keyword fully-automated → undefined',
|
|
141
178
|
);
|
|
142
|
-
});
|
|
143
179
|
|
|
144
|
-
|
|
145
|
-
|
|
180
|
+
// ─── (i) extra whitespace around value ────────────────────────────────────
|
|
181
|
+
console.log('\n── (i) extra whitespace');
|
|
182
|
+
|
|
183
|
+
assertEq(
|
|
146
184
|
extractUatType('## UAT Type\n\n- UAT mode: artifact-driven \n'),
|
|
147
185
|
'artifact-driven',
|
|
148
186
|
'leading/trailing whitespace around value → still classified correctly',
|
|
149
187
|
);
|
|
150
|
-
|
|
188
|
+
|
|
189
|
+
assertEq(
|
|
151
190
|
extractUatType('## UAT Type\n\n- UAT mode: mixed (artifact-driven + live-runtime) \n'),
|
|
152
191
|
'mixed',
|
|
153
192
|
'whitespace around mixed parenthetical → mixed',
|
|
154
193
|
);
|
|
155
|
-
});
|
|
156
194
|
|
|
157
|
-
|
|
158
|
-
|
|
195
|
+
// ─── (j) case sensitivity ─────────────────────────────────────────────────
|
|
196
|
+
console.log('\n── (j) case sensitivity');
|
|
197
|
+
|
|
198
|
+
assertEq(
|
|
159
199
|
extractUatType(makeUatContent('Artifact-Driven')),
|
|
160
200
|
'artifact-driven',
|
|
161
201
|
'Artifact-Driven (title case) → artifact-driven (function lowercases before matching)',
|
|
162
202
|
);
|
|
163
|
-
|
|
203
|
+
|
|
204
|
+
assertEq(
|
|
164
205
|
extractUatType(makeUatContent('MIXED')),
|
|
165
206
|
'mixed',
|
|
166
207
|
'MIXED (upper case) → mixed (function lowercases before matching)',
|
|
167
208
|
);
|
|
168
|
-
});
|
|
169
209
|
|
|
170
|
-
|
|
210
|
+
// ─── (k) prompt template loading and content integrity ────────────────────
|
|
211
|
+
console.log('\n── (k) run-uat prompt template');
|
|
212
|
+
|
|
171
213
|
const milestoneId = 'M001';
|
|
172
214
|
const sliceId = 'S01';
|
|
173
215
|
const uatPath = '.gsd/milestones/M001/slices/S01/S01-UAT.md';
|
|
174
216
|
const uatResultPath = '.gsd/milestones/M001/slices/S01/S01-UAT-RESULT.md';
|
|
175
217
|
const uatType = 'live-runtime';
|
|
176
218
|
const inlinedContext = '<!-- no context -->';
|
|
219
|
+
|
|
177
220
|
let promptResult: string | undefined;
|
|
178
221
|
let promptThrew = false;
|
|
179
222
|
try {
|
|
@@ -189,66 +232,71 @@ test('(k) run-uat prompt template', () => {
|
|
|
189
232
|
} catch {
|
|
190
233
|
promptThrew = true;
|
|
191
234
|
}
|
|
192
|
-
|
|
193
|
-
|
|
235
|
+
|
|
236
|
+
assertTrue(!promptThrew, 'loadPromptFromWorktree("run-uat", vars) does not throw');
|
|
237
|
+
assertTrue(
|
|
194
238
|
typeof promptResult === 'string' && promptResult.length > 0,
|
|
195
239
|
'run-uat prompt result is a non-empty string',
|
|
196
240
|
);
|
|
197
|
-
|
|
241
|
+
assertTrue(
|
|
198
242
|
promptResult?.includes(milestoneId) ?? false,
|
|
199
243
|
`prompt contains milestoneId value "${milestoneId}" after substitution`,
|
|
200
244
|
);
|
|
201
|
-
|
|
245
|
+
assertTrue(
|
|
202
246
|
promptResult?.includes(sliceId) ?? false,
|
|
203
247
|
`prompt contains sliceId value "${sliceId}" after substitution`,
|
|
204
248
|
);
|
|
205
|
-
|
|
249
|
+
assertTrue(
|
|
206
250
|
promptResult?.includes(uatResultPath) ?? false,
|
|
207
251
|
`prompt contains uatResultPath value after substitution`,
|
|
208
252
|
);
|
|
209
|
-
|
|
253
|
+
assertTrue(
|
|
210
254
|
promptResult?.includes(`Detected UAT mode:** \`${uatType}\``) ?? false,
|
|
211
255
|
`prompt contains detected dynamic uatType value "${uatType}" after substitution`,
|
|
212
256
|
);
|
|
213
|
-
|
|
257
|
+
assertTrue(
|
|
214
258
|
promptResult?.includes(`uatType: ${uatType}`) ?? false,
|
|
215
259
|
`prompt contains dynamic uatType frontmatter value "${uatType}" after substitution`,
|
|
216
260
|
);
|
|
217
|
-
|
|
261
|
+
assertTrue(
|
|
218
262
|
!/\{\{[^}]+\}\}/.test(promptResult ?? ''),
|
|
219
263
|
'no unreplaced {{...}} tokens remain after variable substitution',
|
|
220
264
|
);
|
|
221
|
-
|
|
265
|
+
assertTrue(
|
|
222
266
|
/browser|runtime|execute|run/i.test(promptResult ?? ''),
|
|
223
267
|
'prompt contains runtime execution language (browser/runtime/execute/run)',
|
|
224
268
|
);
|
|
225
|
-
|
|
269
|
+
assertTrue(
|
|
226
270
|
!/surfaced for human review/i.test(promptResult ?? ''),
|
|
227
271
|
'prompt does not contain "surfaced for human review" (non-artifact UATs are skipped, not dispatched)',
|
|
228
272
|
);
|
|
229
|
-
});
|
|
230
273
|
|
|
231
|
-
|
|
274
|
+
// ─── (l) dispatch precondition assertions via resolveSliceFile ────────────
|
|
275
|
+
console.log('\n── (l) dispatch preconditions via resolveSliceFile');
|
|
276
|
+
|
|
277
|
+
// State A: UAT file exists, UAT-RESULT file does NOT — triggers dispatch
|
|
278
|
+
{
|
|
232
279
|
const base = createFixtureBase();
|
|
233
280
|
const uatContent = makeUatContent('artifact-driven');
|
|
234
281
|
try {
|
|
235
282
|
writeSliceFile(base, 'M001', 'S01', 'UAT', uatContent);
|
|
236
283
|
|
|
237
284
|
const uatFilePath = resolveSliceFile(base, 'M001', 'S01', 'UAT');
|
|
238
|
-
|
|
285
|
+
assertTrue(
|
|
239
286
|
uatFilePath !== null,
|
|
240
287
|
'resolveSliceFile(..., "UAT") returns non-null when UAT file exists (dispatch trigger state)',
|
|
241
288
|
);
|
|
242
289
|
|
|
243
290
|
const uatResultFilePath = resolveSliceFile(base, 'M001', 'S01', 'UAT-RESULT');
|
|
244
|
-
|
|
291
|
+
assertEq(
|
|
245
292
|
uatResultFilePath,
|
|
246
293
|
null,
|
|
247
294
|
'resolveSliceFile(..., "UAT-RESULT") returns null when result file missing (dispatch trigger state)',
|
|
248
295
|
);
|
|
249
296
|
|
|
297
|
+
// End-to-end: file content → parse → classify
|
|
250
298
|
const rawContent = readFileSync(uatFilePath!, 'utf-8');
|
|
251
|
-
|
|
299
|
+
assertEq(
|
|
252
300
|
extractUatType(rawContent),
|
|
253
301
|
'artifact-driven',
|
|
254
302
|
'extractUatType on fixture UAT file returns expected type (end-to-end data flow)',
|
|
@@ -256,25 +304,29 @@ test('(l) dispatch preconditions via resolveSliceFile', () => {
|
|
|
256
304
|
} finally {
|
|
257
305
|
cleanup(base);
|
|
258
306
|
}
|
|
259
|
-
}
|
|
307
|
+
}
|
|
260
308
|
|
|
261
|
-
|
|
309
|
+
// State B: UAT-RESULT file exists — dispatch is skipped (idempotent)
|
|
310
|
+
{
|
|
262
311
|
const base = createFixtureBase();
|
|
263
312
|
try {
|
|
264
313
|
writeSliceFile(base, 'M001', 'S01', 'UAT', makeUatContent('artifact-driven'));
|
|
265
314
|
writeSliceFile(base, 'M001', 'S01', 'UAT-RESULT', '# UAT Result\n\nverdict: PASS\n');
|
|
266
315
|
|
|
267
316
|
const uatResultFilePath = resolveSliceFile(base, 'M001', 'S01', 'UAT-RESULT');
|
|
268
|
-
|
|
317
|
+
assertTrue(
|
|
269
318
|
uatResultFilePath !== null,
|
|
270
319
|
'resolveSliceFile(..., "UAT-RESULT") returns non-null when result file exists (idempotent skip state)',
|
|
271
320
|
);
|
|
272
321
|
} finally {
|
|
273
322
|
cleanup(base);
|
|
274
323
|
}
|
|
275
|
-
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ─── (m) non-artifact UATs are skipped (not dispatched) ─────────────────
|
|
327
|
+
console.log('\n── (m) non-artifact UAT skip');
|
|
276
328
|
|
|
277
|
-
|
|
329
|
+
{
|
|
278
330
|
const base = createFixtureBase();
|
|
279
331
|
try {
|
|
280
332
|
const roadmapDir = join(base, '.gsd', 'milestones', 'M001');
|
|
@@ -294,6 +346,7 @@ test('(m) non-artifact UAT skip', async () => {
|
|
|
294
346
|
].join('\n'),
|
|
295
347
|
);
|
|
296
348
|
|
|
349
|
+
// human-experience UAT still dispatches, but auto-mode later pauses for manual review
|
|
297
350
|
writeSliceFile(base, 'M001', 'S01', 'UAT', makeUatContent('human-experience'));
|
|
298
351
|
|
|
299
352
|
const state = {
|
|
@@ -308,7 +361,7 @@ test('(m) non-artifact UAT skip', async () => {
|
|
|
308
361
|
} as const;
|
|
309
362
|
|
|
310
363
|
const result = await checkNeedsRunUat(base, 'M001', state as any, { uat_dispatch: true } as any);
|
|
311
|
-
|
|
364
|
+
assertEq(
|
|
312
365
|
result,
|
|
313
366
|
{ sliceId: 'S01', uatType: 'human-experience' },
|
|
314
367
|
'human-experience UAT dispatches so auto-mode can pause for manual review',
|
|
@@ -316,9 +369,12 @@ test('(m) non-artifact UAT skip', async () => {
|
|
|
316
369
|
} finally {
|
|
317
370
|
cleanup(base);
|
|
318
371
|
}
|
|
319
|
-
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// ─── (n) existing UAT-RESULT never re-dispatches ──────────────────────
|
|
375
|
+
console.log('\n── (n) stale replay guard');
|
|
320
376
|
|
|
321
|
-
|
|
377
|
+
{
|
|
322
378
|
const base = createFixtureBase();
|
|
323
379
|
try {
|
|
324
380
|
const roadmapDir = join(base, '.gsd', 'milestones', 'M001');
|
|
@@ -353,7 +409,7 @@ test('(n) stale replay guard', async () => {
|
|
|
353
409
|
} as const;
|
|
354
410
|
|
|
355
411
|
const result = await checkNeedsRunUat(base, 'M001', state as any, { uat_dispatch: true } as any);
|
|
356
|
-
|
|
412
|
+
assertEq(
|
|
357
413
|
result,
|
|
358
414
|
null,
|
|
359
415
|
'existing UAT-RESULT with FAIL verdict does not re-dispatch; verdict gate owns blocking',
|
|
@@ -361,6 +417,12 @@ test('(n) stale replay guard', async () => {
|
|
|
361
417
|
} finally {
|
|
362
418
|
cleanup(base);
|
|
363
419
|
}
|
|
364
|
-
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
report();
|
|
423
|
+
}
|
|
365
424
|
|
|
425
|
+
main().catch((error) => {
|
|
426
|
+
console.error(error);
|
|
427
|
+
process.exit(1);
|
|
366
428
|
});
|
|
@@ -20,11 +20,11 @@ import {
|
|
|
20
20
|
_getRegisteredLockDirs,
|
|
21
21
|
} from '../session-lock.ts';
|
|
22
22
|
import { gsdRoot } from '../paths.ts';
|
|
23
|
-
import {
|
|
24
|
-
import assert from 'node:assert/strict';
|
|
23
|
+
import { createTestContext } from './test-helpers.ts';
|
|
25
24
|
|
|
25
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
async function main(): Promise<void> {
|
|
28
28
|
|
|
29
29
|
// ─── 1. Lock dir registry tracks gsdDir on acquisition ──────────────────
|
|
30
30
|
console.log('\n=== 1. Lock dir registry tracks gsdDir on acquisition ===');
|
|
@@ -34,17 +34,17 @@ describe('session-lock-multipath', async () => {
|
|
|
34
34
|
|
|
35
35
|
try {
|
|
36
36
|
const result = acquireSessionLock(base);
|
|
37
|
-
|
|
37
|
+
assertTrue(result.acquired, 'lock acquired');
|
|
38
38
|
|
|
39
39
|
const registered = _getRegisteredLockDirs();
|
|
40
40
|
const gsdDir = gsdRoot(base);
|
|
41
|
-
|
|
41
|
+
assertTrue(registered.includes(gsdDir), 'gsdDir is registered in lock dir registry');
|
|
42
42
|
|
|
43
43
|
releaseSessionLock(base);
|
|
44
44
|
|
|
45
45
|
// After release, registry should be cleared
|
|
46
46
|
const afterRelease = _getRegisteredLockDirs();
|
|
47
|
-
|
|
47
|
+
assertEq(afterRelease.length, 0, 'lock dir registry cleared after release');
|
|
48
48
|
} finally {
|
|
49
49
|
rmSync(base, { recursive: true, force: true });
|
|
50
50
|
}
|
|
@@ -62,7 +62,7 @@ describe('session-lock-multipath', async () => {
|
|
|
62
62
|
|
|
63
63
|
try {
|
|
64
64
|
const result = acquireSessionLock(base);
|
|
65
|
-
|
|
65
|
+
assertTrue(result.acquired, 'lock acquired');
|
|
66
66
|
|
|
67
67
|
// Manually plant a stale lock file at the secondary path to simulate
|
|
68
68
|
// multi-path lock accumulation
|
|
@@ -72,8 +72,8 @@ describe('session-lock-multipath', async () => {
|
|
|
72
72
|
mkdirSync(secondaryLockDir, { recursive: true });
|
|
73
73
|
|
|
74
74
|
// Verify they exist before release
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
assertTrue(existsSync(secondaryLockFile), 'secondary lock file exists before release');
|
|
76
|
+
assertTrue(existsSync(secondaryLockDir), 'secondary lock dir exists before release');
|
|
77
77
|
|
|
78
78
|
// Manually add the secondary dir to the registry (simulating ensureExitHandler call)
|
|
79
79
|
// We do this by acquiring knowledge of internals — the registry is populated
|
|
@@ -83,10 +83,10 @@ describe('session-lock-multipath', async () => {
|
|
|
83
83
|
|
|
84
84
|
// Primary lock artifacts should be cleaned
|
|
85
85
|
const primaryLockFile = join(gsdRoot(base), 'auto.lock');
|
|
86
|
-
|
|
86
|
+
assertTrue(!existsSync(primaryLockFile), 'primary auto.lock removed after release');
|
|
87
87
|
|
|
88
88
|
const primaryLockDir = gsdRoot(base) + '.lock';
|
|
89
|
-
|
|
89
|
+
assertTrue(!existsSync(primaryLockDir), 'primary .gsd.lock/ removed after release');
|
|
90
90
|
} finally {
|
|
91
91
|
rmSync(base, { recursive: true, force: true });
|
|
92
92
|
}
|
|
@@ -106,7 +106,7 @@ describe('session-lock-multipath', async () => {
|
|
|
106
106
|
const gsdDir = gsdRoot(base);
|
|
107
107
|
// Should only appear once (Set deduplication)
|
|
108
108
|
const count = registered.filter(d => d === gsdDir).length;
|
|
109
|
-
|
|
109
|
+
assertEq(count, 1, 'gsdDir registered exactly once after re-entrant acquisition');
|
|
110
110
|
|
|
111
111
|
releaseSessionLock(base);
|
|
112
112
|
} finally {
|
|
@@ -124,17 +124,17 @@ describe('session-lock-multipath', async () => {
|
|
|
124
124
|
|
|
125
125
|
try {
|
|
126
126
|
const r1 = acquireSessionLock(base1);
|
|
127
|
-
|
|
127
|
+
assertTrue(r1.acquired, 'first base lock acquired');
|
|
128
128
|
|
|
129
129
|
// Release first to acquire second (module state is single-lock)
|
|
130
130
|
releaseSessionLock(base1);
|
|
131
131
|
|
|
132
132
|
const r2 = acquireSessionLock(base2);
|
|
133
|
-
|
|
133
|
+
assertTrue(r2.acquired, 'second base lock acquired');
|
|
134
134
|
|
|
135
135
|
const registered = _getRegisteredLockDirs();
|
|
136
136
|
const gsd2 = gsdRoot(base2);
|
|
137
|
-
|
|
137
|
+
assertTrue(registered.includes(gsd2), 'second gsdDir is registered');
|
|
138
138
|
|
|
139
139
|
releaseSessionLock(base2);
|
|
140
140
|
} finally {
|
|
@@ -156,11 +156,18 @@ describe('session-lock-multipath', async () => {
|
|
|
156
156
|
// Verify everything is clean
|
|
157
157
|
const lockFile = join(gsdRoot(base), 'auto.lock');
|
|
158
158
|
const lockDir = gsdRoot(base) + '.lock';
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
159
|
+
assertTrue(!existsSync(lockFile), 'auto.lock cleaned');
|
|
160
|
+
assertTrue(!existsSync(lockDir), '.gsd.lock/ cleaned');
|
|
161
|
+
assertEq(_getRegisteredLockDirs().length, 0, 'registry empty');
|
|
162
162
|
} finally {
|
|
163
163
|
rmSync(base, { recursive: true, force: true });
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
+
|
|
167
|
+
report();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
main().catch((error) => {
|
|
171
|
+
console.error(error);
|
|
172
|
+
process.exit(1);
|
|
166
173
|
});
|