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,11 +1,13 @@
|
|
|
1
|
-
import { describe, test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
1
|
import { mkdtempSync, mkdirSync, rmSync, realpathSync } from "node:fs";
|
|
4
2
|
import { join } from "node:path";
|
|
5
3
|
import { tmpdir } from "node:os";
|
|
6
4
|
import { spawnSync } from "node:child_process";
|
|
7
5
|
|
|
8
6
|
import { gsdRoot, _clearGsdRootCache } from "../paths.ts";
|
|
7
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
8
|
+
|
|
9
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
10
|
+
|
|
9
11
|
/** Create a tmp dir and resolve symlinks + 8.3 short names (macOS /var→/private/var, Windows RUNNER~1→runneradmin). */
|
|
10
12
|
function tmp(): string {
|
|
11
13
|
const p = mkdtempSync(join(tmpdir(), "gsd-paths-test-"));
|
|
@@ -21,78 +23,91 @@ function initGit(dir: string): void {
|
|
|
21
23
|
spawnSync("git", ["commit", "--allow-empty", "-m", "init"], { cwd: dir });
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
// ── tests ──────────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
{
|
|
29
|
+
// Case 1: .gsd exists at basePath — fast path
|
|
30
|
+
const root = tmp();
|
|
31
|
+
try {
|
|
32
|
+
mkdirSync(join(root, ".gsd"));
|
|
33
|
+
_clearGsdRootCache();
|
|
34
|
+
const result = gsdRoot(root);
|
|
35
|
+
assertEq(result, join(root, ".gsd"), "fast path: returns basePath/.gsd");
|
|
36
|
+
} finally { cleanup(root); }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
{
|
|
40
|
+
// Case 2: .gsd exists at git root, cwd is a subdirectory
|
|
41
|
+
const root = tmp();
|
|
42
|
+
try {
|
|
43
|
+
initGit(root);
|
|
44
|
+
mkdirSync(join(root, ".gsd"));
|
|
45
|
+
const sub = join(root, "src", "deep");
|
|
46
|
+
mkdirSync(sub, { recursive: true });
|
|
47
|
+
_clearGsdRootCache();
|
|
48
|
+
const result = gsdRoot(sub);
|
|
49
|
+
assertEq(result, join(root, ".gsd"), "git-root probe: finds .gsd at git root from subdirectory");
|
|
50
|
+
} finally { cleanup(root); }
|
|
51
|
+
}
|
|
34
52
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
{
|
|
54
|
+
// Case 3: .gsd in an ancestor — walk-up finds it (git repo with no .gsd at root)
|
|
55
|
+
const root = tmp();
|
|
56
|
+
try {
|
|
57
|
+
// Init a git repo so git probe returns root — but put .gsd one level deeper
|
|
58
|
+
// to force the walk-up path: root/project/.gsd, cwd = root/project/src/deep
|
|
59
|
+
initGit(root);
|
|
60
|
+
const project = join(root, "project");
|
|
61
|
+
mkdirSync(join(project, ".gsd"), { recursive: true });
|
|
62
|
+
const deep = join(project, "src", "deep");
|
|
63
|
+
mkdirSync(deep, { recursive: true });
|
|
64
|
+
_clearGsdRootCache();
|
|
65
|
+
// git probe returns root (no .gsd there), so walk-up takes over and finds project/.gsd
|
|
66
|
+
const result = gsdRoot(deep);
|
|
67
|
+
assertEq(result, join(project, ".gsd"), "walk-up: finds .gsd in ancestor when git root has none");
|
|
68
|
+
} finally { cleanup(root); }
|
|
69
|
+
}
|
|
47
70
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
});
|
|
71
|
+
{
|
|
72
|
+
// Case 4: .gsd nowhere — fallback returns original basePath/.gsd
|
|
73
|
+
// Use an isolated git repo so we fully control the environment above basePath
|
|
74
|
+
const root = tmp();
|
|
75
|
+
try {
|
|
76
|
+
initGit(root); // git root = root, no .gsd anywhere
|
|
77
|
+
const sub = join(root, "src");
|
|
78
|
+
mkdirSync(sub, { recursive: true });
|
|
79
|
+
_clearGsdRootCache();
|
|
80
|
+
const result = gsdRoot(sub);
|
|
81
|
+
// git probe finds root (no .gsd), walk-up finds nothing → fallback = sub/.gsd
|
|
82
|
+
assertEq(result, join(sub, ".gsd"), "fallback: returns basePath/.gsd when .gsd not found anywhere");
|
|
83
|
+
} finally { cleanup(root); }
|
|
84
|
+
}
|
|
61
85
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
});
|
|
86
|
+
{
|
|
87
|
+
// Case 5: cache — second call returns same value without re-probing
|
|
88
|
+
const root = tmp();
|
|
89
|
+
try {
|
|
90
|
+
mkdirSync(join(root, ".gsd"));
|
|
91
|
+
_clearGsdRootCache();
|
|
92
|
+
const first = gsdRoot(root);
|
|
93
|
+
const second = gsdRoot(root);
|
|
94
|
+
assertEq(first, second, "cache: same result returned on second call");
|
|
95
|
+
assertTrue(first === second, "cache: identity check (same string)");
|
|
96
|
+
} finally { cleanup(root); }
|
|
97
|
+
}
|
|
73
98
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
99
|
+
{
|
|
100
|
+
// Case 6: .gsd at basePath takes precedence over ancestor .gsd
|
|
101
|
+
const outer = tmp();
|
|
102
|
+
try {
|
|
103
|
+
initGit(outer);
|
|
104
|
+
mkdirSync(join(outer, ".gsd"));
|
|
105
|
+
const inner = join(outer, "nested");
|
|
106
|
+
mkdirSync(join(inner, ".gsd"), { recursive: true });
|
|
107
|
+
_clearGsdRootCache();
|
|
108
|
+
const result = gsdRoot(inner);
|
|
109
|
+
assertEq(result, join(inner, ".gsd"), "precedence: nearest .gsd wins over ancestor");
|
|
110
|
+
} finally { cleanup(outer); }
|
|
111
|
+
}
|
|
85
112
|
|
|
86
|
-
|
|
87
|
-
const outer = tmp();
|
|
88
|
-
try {
|
|
89
|
-
initGit(outer);
|
|
90
|
-
mkdirSync(join(outer, ".gsd"));
|
|
91
|
-
const inner = join(outer, "nested");
|
|
92
|
-
mkdirSync(join(inner, ".gsd"), { recursive: true });
|
|
93
|
-
_clearGsdRootCache();
|
|
94
|
-
const result = gsdRoot(inner);
|
|
95
|
-
assert.deepStrictEqual(result, join(inner, ".gsd"), "precedence: nearest .gsd wins over ancestor");
|
|
96
|
-
} finally { cleanup(outer); }
|
|
97
|
-
});
|
|
98
|
-
});
|
|
113
|
+
report();
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
// GSD Extension — Hook Engine Tests (Post-Unit, Pre-Dispatch, State Persistence)
|
|
2
2
|
|
|
3
|
-
import { describe, test } from 'node:test';
|
|
4
|
-
import assert from 'node:assert/strict';
|
|
5
3
|
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, existsSync, readFileSync } from "node:fs";
|
|
6
4
|
import { join } from "node:path";
|
|
7
5
|
import { tmpdir } from "node:os";
|
|
6
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
8
7
|
import {
|
|
9
8
|
checkPostUnitHooks,
|
|
10
9
|
getActiveHook,
|
|
@@ -21,6 +20,8 @@ import {
|
|
|
21
20
|
triggerHookManually,
|
|
22
21
|
} from "../post-unit-hooks.ts";
|
|
23
22
|
|
|
23
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
24
|
+
|
|
24
25
|
// ─── Fixture Helpers ───────────────────────────────────────────────────────
|
|
25
26
|
|
|
26
27
|
function createFixtureBase(): string {
|
|
@@ -35,14 +36,14 @@ function createFixtureBase(): string {
|
|
|
35
36
|
|
|
36
37
|
// ─── resolveHookArtifactPath ───────────────────────────────────────────────
|
|
37
38
|
|
|
39
|
+
console.log("\n=== resolveHookArtifactPath ===");
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
test('resolveHookArtifactPath', () => {
|
|
41
|
+
{
|
|
41
42
|
const base = "/project";
|
|
42
43
|
|
|
43
44
|
// Task-level
|
|
44
45
|
const taskPath = resolveHookArtifactPath(base, "M001/S01/T01", "REVIEW-PASS.md");
|
|
45
|
-
|
|
46
|
+
assertEq(
|
|
46
47
|
taskPath,
|
|
47
48
|
join(base, ".gsd", "milestones", "M001", "slices", "S01", "tasks", "T01-REVIEW-PASS.md"),
|
|
48
49
|
"task-level artifact path",
|
|
@@ -50,7 +51,7 @@ test('resolveHookArtifactPath', () => {
|
|
|
50
51
|
|
|
51
52
|
// Slice-level
|
|
52
53
|
const slicePath = resolveHookArtifactPath(base, "M001/S01", "REVIEW-PASS.md");
|
|
53
|
-
|
|
54
|
+
assertEq(
|
|
54
55
|
slicePath,
|
|
55
56
|
join(base, ".gsd", "milestones", "M001", "slices", "S01", "REVIEW-PASS.md"),
|
|
56
57
|
"slice-level artifact path",
|
|
@@ -58,106 +59,129 @@ test('resolveHookArtifactPath', () => {
|
|
|
58
59
|
|
|
59
60
|
// Milestone-level
|
|
60
61
|
const milestonePath = resolveHookArtifactPath(base, "M001", "REVIEW-PASS.md");
|
|
61
|
-
|
|
62
|
+
assertEq(
|
|
62
63
|
milestonePath,
|
|
63
64
|
join(base, ".gsd", "milestones", "M001", "REVIEW-PASS.md"),
|
|
64
65
|
"milestone-level artifact path",
|
|
65
66
|
);
|
|
66
|
-
}
|
|
67
|
+
}
|
|
67
68
|
|
|
68
69
|
// ─── resetHookState ────────────────────────────────────────────────────────
|
|
69
|
-
|
|
70
|
+
|
|
71
|
+
console.log("\n=== resetHookState ===");
|
|
72
|
+
|
|
73
|
+
{
|
|
70
74
|
resetHookState();
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
+
assertEq(getActiveHook(), null, "no active hook after reset");
|
|
76
|
+
assertTrue(!isRetryPending(), "no retry pending after reset");
|
|
77
|
+
assertEq(consumeRetryTrigger(), null, "no retry trigger after reset");
|
|
78
|
+
}
|
|
75
79
|
|
|
76
80
|
// ─── checkPostUnitHooks with no hooks configured ───────────────────────────
|
|
77
|
-
|
|
81
|
+
|
|
82
|
+
console.log("\n=== No hooks configured ===");
|
|
83
|
+
|
|
84
|
+
{
|
|
78
85
|
resetHookState();
|
|
79
86
|
const base = createFixtureBase();
|
|
80
87
|
try {
|
|
81
88
|
const result = checkPostUnitHooks("execute-task", "M001/S01/T01", base);
|
|
82
|
-
|
|
89
|
+
assertEq(result, null, "returns null when no hooks configured");
|
|
83
90
|
} finally {
|
|
84
91
|
rmSync(base, { recursive: true, force: true });
|
|
85
92
|
}
|
|
86
|
-
}
|
|
93
|
+
}
|
|
87
94
|
|
|
88
95
|
// ─── Hook units don't trigger hooks (no hook-on-hook) ──────────────────────
|
|
89
|
-
|
|
96
|
+
|
|
97
|
+
console.log("\n=== Hook-on-hook prevention ===");
|
|
98
|
+
|
|
99
|
+
{
|
|
90
100
|
resetHookState();
|
|
91
101
|
const base = createFixtureBase();
|
|
92
102
|
try {
|
|
93
103
|
const result = checkPostUnitHooks("hook/code-review", "M001/S01/T01", base);
|
|
94
|
-
|
|
104
|
+
assertEq(result, null, "hook units don't trigger other hooks");
|
|
95
105
|
} finally {
|
|
96
106
|
rmSync(base, { recursive: true, force: true });
|
|
97
107
|
}
|
|
98
|
-
}
|
|
108
|
+
}
|
|
99
109
|
|
|
100
110
|
// ─── consumeRetryTrigger clears state ──────────────────────────────────────
|
|
101
|
-
|
|
111
|
+
|
|
112
|
+
console.log("\n=== consumeRetryTrigger clears state ===");
|
|
113
|
+
|
|
114
|
+
{
|
|
102
115
|
resetHookState();
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
116
|
+
assertEq(consumeRetryTrigger(), null, "no trigger initially");
|
|
117
|
+
assertTrue(!isRetryPending(), "no retry initially");
|
|
118
|
+
}
|
|
106
119
|
|
|
107
120
|
// ─── Variable substitution in prompts ──────────────────────────────────────
|
|
108
|
-
|
|
121
|
+
|
|
122
|
+
console.log("\n=== Variable substitution ===");
|
|
123
|
+
|
|
124
|
+
{
|
|
109
125
|
const base = "/project";
|
|
110
126
|
|
|
111
127
|
// 3-part ID
|
|
112
128
|
const path3 = resolveHookArtifactPath(base, "M002/S03/T05", "result.md");
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
129
|
+
assertTrue(path3.includes("M002"), "3-part ID extracts milestoneId");
|
|
130
|
+
assertTrue(path3.includes("S03"), "3-part ID extracts sliceId");
|
|
131
|
+
assertTrue(path3.includes("T05"), "3-part ID extracts taskId");
|
|
132
|
+
assertTrue(path3.includes("milestones"), "3-part ID includes milestones/ segment");
|
|
117
133
|
|
|
118
134
|
// 2-part ID
|
|
119
135
|
const path2 = resolveHookArtifactPath(base, "M002/S03", "result.md");
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
136
|
+
assertTrue(path2.includes("M002"), "2-part ID extracts milestoneId");
|
|
137
|
+
assertTrue(path2.includes("S03"), "2-part ID extracts sliceId");
|
|
138
|
+
assertTrue(path2.includes("milestones"), "2-part ID includes milestones/ segment");
|
|
123
139
|
|
|
124
140
|
// 1-part ID
|
|
125
141
|
const path1 = resolveHookArtifactPath(base, "M002", "result.md");
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
142
|
+
assertTrue(path1.includes("M002"), "1-part ID extracts milestoneId");
|
|
143
|
+
assertTrue(path1.includes("milestones"), "1-part ID includes milestones/ segment");
|
|
144
|
+
}
|
|
129
145
|
|
|
130
146
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
131
147
|
// Phase 2: Pre-Dispatch Hook Tests
|
|
132
148
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
133
|
-
|
|
149
|
+
|
|
150
|
+
console.log("\n=== Pre-dispatch: no hooks configured ===");
|
|
151
|
+
|
|
152
|
+
{
|
|
134
153
|
const base = createFixtureBase();
|
|
135
154
|
try {
|
|
136
155
|
const result = runPreDispatchHooks("execute-task", "M001/S01/T01", "original prompt", base);
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
156
|
+
assertEq(result.action, "proceed", "proceeds when no hooks");
|
|
157
|
+
assertEq(result.prompt, "original prompt", "prompt unchanged");
|
|
158
|
+
assertEq(result.firedHooks.length, 0, "no hooks fired");
|
|
140
159
|
} finally {
|
|
141
160
|
rmSync(base, { recursive: true, force: true });
|
|
142
161
|
}
|
|
143
|
-
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
console.log("\n=== Pre-dispatch: hook units bypass ===");
|
|
144
165
|
|
|
145
|
-
|
|
166
|
+
{
|
|
146
167
|
const base = createFixtureBase();
|
|
147
168
|
try {
|
|
148
169
|
const result = runPreDispatchHooks("hook/review", "M001/S01/T01", "hook prompt", base);
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
170
|
+
assertEq(result.action, "proceed", "hook units always proceed");
|
|
171
|
+
assertEq(result.prompt, "hook prompt", "hook prompt unchanged");
|
|
172
|
+
assertEq(result.firedHooks.length, 0, "no hooks fired for hook units");
|
|
152
173
|
} finally {
|
|
153
174
|
rmSync(base, { recursive: true, force: true });
|
|
154
175
|
}
|
|
155
|
-
}
|
|
176
|
+
}
|
|
156
177
|
|
|
157
178
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
158
179
|
// Phase 3: State Persistence Tests
|
|
159
180
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
160
|
-
|
|
181
|
+
|
|
182
|
+
console.log("\n=== State persistence: persist and restore ===");
|
|
183
|
+
|
|
184
|
+
{
|
|
161
185
|
const base = createFixtureBase();
|
|
162
186
|
try {
|
|
163
187
|
resetHookState();
|
|
@@ -165,17 +189,19 @@ test('State persistence: persist and restore', () => {
|
|
|
165
189
|
// Persist empty state
|
|
166
190
|
persistHookState(base);
|
|
167
191
|
const filePath = join(base, ".gsd", "hook-state.json");
|
|
168
|
-
|
|
192
|
+
assertTrue(existsSync(filePath), "hook-state.json created");
|
|
169
193
|
|
|
170
194
|
const content = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
171
|
-
|
|
172
|
-
|
|
195
|
+
assertEq(typeof content.savedAt, "string", "savedAt is a string");
|
|
196
|
+
assertEq(Object.keys(content.cycleCounts).length, 0, "empty cycle counts");
|
|
173
197
|
} finally {
|
|
174
198
|
rmSync(base, { recursive: true, force: true });
|
|
175
199
|
}
|
|
176
|
-
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
console.log("\n=== State persistence: restore from disk ===");
|
|
177
203
|
|
|
178
|
-
|
|
204
|
+
{
|
|
179
205
|
const base = createFixtureBase();
|
|
180
206
|
try {
|
|
181
207
|
resetHookState();
|
|
@@ -196,14 +222,16 @@ test('State persistence: restore from disk', () => {
|
|
|
196
222
|
// Verify by persisting and reading back
|
|
197
223
|
persistHookState(base);
|
|
198
224
|
const restored = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
199
|
-
|
|
200
|
-
|
|
225
|
+
assertEq(restored.cycleCounts["review/execute-task/M001/S01/T01"], 2, "cycle count restored for review");
|
|
226
|
+
assertEq(restored.cycleCounts["simplify/execute-task/M001/S01/T02"], 1, "cycle count restored for simplify");
|
|
201
227
|
} finally {
|
|
202
228
|
rmSync(base, { recursive: true, force: true });
|
|
203
229
|
}
|
|
204
|
-
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
console.log("\n=== State persistence: clear ===");
|
|
205
233
|
|
|
206
|
-
|
|
234
|
+
{
|
|
207
235
|
const base = createFixtureBase();
|
|
208
236
|
try {
|
|
209
237
|
resetHookState();
|
|
@@ -218,65 +246,77 @@ test('State persistence: clear', () => {
|
|
|
218
246
|
clearPersistedHookState(base);
|
|
219
247
|
|
|
220
248
|
const cleared = JSON.parse(readFileSync(stateFile, "utf-8"));
|
|
221
|
-
|
|
249
|
+
assertEq(Object.keys(cleared.cycleCounts).length, 0, "cycle counts cleared");
|
|
222
250
|
} finally {
|
|
223
251
|
rmSync(base, { recursive: true, force: true });
|
|
224
252
|
}
|
|
225
|
-
}
|
|
253
|
+
}
|
|
226
254
|
|
|
227
|
-
|
|
255
|
+
console.log("\n=== State persistence: restore handles missing file ===");
|
|
256
|
+
|
|
257
|
+
{
|
|
228
258
|
const base = createFixtureBase();
|
|
229
259
|
try {
|
|
230
260
|
resetHookState();
|
|
231
261
|
// Should not throw
|
|
232
262
|
restoreHookState(base);
|
|
233
|
-
|
|
263
|
+
assertEq(getActiveHook(), null, "no active hook after restore from missing file");
|
|
234
264
|
} finally {
|
|
235
265
|
rmSync(base, { recursive: true, force: true });
|
|
236
266
|
}
|
|
237
|
-
}
|
|
267
|
+
}
|
|
238
268
|
|
|
239
|
-
|
|
269
|
+
console.log("\n=== State persistence: restore handles corrupt file ===");
|
|
270
|
+
|
|
271
|
+
{
|
|
240
272
|
const base = createFixtureBase();
|
|
241
273
|
try {
|
|
242
274
|
resetHookState();
|
|
243
275
|
writeFileSync(join(base, ".gsd", "hook-state.json"), "not json", "utf-8");
|
|
244
276
|
// Should not throw
|
|
245
277
|
restoreHookState(base);
|
|
246
|
-
|
|
278
|
+
assertEq(getActiveHook(), null, "no active hook after corrupt restore");
|
|
247
279
|
} finally {
|
|
248
280
|
rmSync(base, { recursive: true, force: true });
|
|
249
281
|
}
|
|
250
|
-
}
|
|
282
|
+
}
|
|
251
283
|
|
|
252
284
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
253
285
|
// Phase 3: Hook Status Reporting Tests
|
|
254
286
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
255
|
-
|
|
287
|
+
|
|
288
|
+
console.log("\n=== Hook status: no hooks ===");
|
|
289
|
+
|
|
290
|
+
{
|
|
256
291
|
resetHookState();
|
|
257
292
|
const entries = getHookStatus();
|
|
258
293
|
// No preferences file = no hooks
|
|
259
|
-
|
|
294
|
+
assertEq(entries.length, 0, "no entries when no hooks configured");
|
|
260
295
|
|
|
261
296
|
const formatted = formatHookStatus();
|
|
262
|
-
|
|
263
|
-
}
|
|
297
|
+
assertMatch(formatted, /No hooks configured/, "status message says no hooks");
|
|
298
|
+
}
|
|
264
299
|
|
|
265
300
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
266
301
|
// Phase 4: Manual Hook Trigger Tests
|
|
267
302
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
268
|
-
|
|
303
|
+
|
|
304
|
+
console.log("\n=== triggerHookManually: hook not found ===");
|
|
305
|
+
|
|
306
|
+
{
|
|
269
307
|
resetHookState();
|
|
270
308
|
const base = createFixtureBase();
|
|
271
309
|
try {
|
|
272
310
|
const result = triggerHookManually("nonexistent-hook", "execute-task", "M001/S01/T01", base);
|
|
273
|
-
|
|
311
|
+
assertEq(result, null, "returns null when hook not found");
|
|
274
312
|
} finally {
|
|
275
313
|
rmSync(base, { recursive: true, force: true });
|
|
276
314
|
}
|
|
277
|
-
}
|
|
315
|
+
}
|
|
278
316
|
|
|
279
|
-
|
|
317
|
+
console.log("\n=== triggerHookManually: with configured hook ===");
|
|
318
|
+
|
|
319
|
+
{
|
|
280
320
|
resetHookState();
|
|
281
321
|
const base = createFixtureBase();
|
|
282
322
|
try {
|
|
@@ -285,16 +325,16 @@ test('triggerHookManually: with configured hook', () => {
|
|
|
285
325
|
const result = triggerHookManually("code-review", "execute-task", "M001/S01/T01", base);
|
|
286
326
|
// Result depends on whether code-review hook is configured in preferences
|
|
287
327
|
// The function should either return null or a valid HookDispatchResult
|
|
288
|
-
|
|
328
|
+
assertTrue(result === null || typeof result === "object", "returns null or object");
|
|
289
329
|
if (result) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
330
|
+
assertEq(result.hookName, "code-review", "hook name in result");
|
|
331
|
+
assertEq(result.unitType, "hook/code-review", "unit type is hook-prefixed");
|
|
332
|
+
assertEq(result.unitId, "M001/S01/T01", "unit ID preserved");
|
|
333
|
+
assertTrue(typeof result.prompt === "string", "prompt is a string");
|
|
294
334
|
}
|
|
295
335
|
} finally {
|
|
296
336
|
rmSync(base, { recursive: true, force: true });
|
|
297
337
|
}
|
|
298
|
-
}
|
|
338
|
+
}
|
|
299
339
|
|
|
300
|
-
|
|
340
|
+
report();
|