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
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
* strips backslashes (escape characters), producing `C:Usersuserproject`.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import {
|
|
10
|
-
import assert from 'node:assert/strict';
|
|
9
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
11
10
|
|
|
11
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
12
12
|
|
|
13
13
|
// ─── shellEscape + path normalization ──────────────────────────────────────
|
|
14
14
|
|
|
@@ -25,42 +25,42 @@ function bashPath(p: string): string {
|
|
|
25
25
|
console.log("\n=== Windows backslash path normalization (#1436) ===");
|
|
26
26
|
|
|
27
27
|
// Backslash paths are converted to forward slashes
|
|
28
|
-
|
|
28
|
+
assertEq(
|
|
29
29
|
bashPath("C:\\Users\\user\\project"),
|
|
30
30
|
"'C:/Users/user/project'",
|
|
31
31
|
"backslash path normalised to forward slashes in shell-escaped string",
|
|
32
32
|
);
|
|
33
33
|
|
|
34
34
|
// Unix paths pass through unchanged
|
|
35
|
-
|
|
35
|
+
assertEq(
|
|
36
36
|
bashPath("/home/user/project"),
|
|
37
37
|
"'/home/user/project'",
|
|
38
38
|
"Unix path unchanged",
|
|
39
39
|
);
|
|
40
40
|
|
|
41
41
|
// Mixed separators are normalised
|
|
42
|
-
|
|
42
|
+
assertEq(
|
|
43
43
|
bashPath("C:\\Users/user\\project/src"),
|
|
44
44
|
"'C:/Users/user/project/src'",
|
|
45
45
|
"mixed separators normalised",
|
|
46
46
|
);
|
|
47
47
|
|
|
48
48
|
// Paths with single quotes are still properly escaped
|
|
49
|
-
|
|
49
|
+
assertEq(
|
|
50
50
|
bashPath("C:\\Users\\o'brien\\project"),
|
|
51
51
|
"'C:/Users/o'\\''brien/project'",
|
|
52
52
|
"single quote in path is escaped after normalisation",
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
// UNC paths
|
|
56
|
-
|
|
56
|
+
assertEq(
|
|
57
57
|
bashPath("\\\\server\\share\\dir"),
|
|
58
58
|
"'//server/share/dir'",
|
|
59
59
|
"UNC path normalised",
|
|
60
60
|
);
|
|
61
61
|
|
|
62
62
|
// Empty string
|
|
63
|
-
|
|
63
|
+
assertEq(
|
|
64
64
|
bashPath(""),
|
|
65
65
|
"''",
|
|
66
66
|
"empty string handled",
|
|
@@ -72,14 +72,14 @@ console.log("\n=== cd command construction with normalised paths ===");
|
|
|
72
72
|
|
|
73
73
|
const windowsCwd = "C:\\Users\\user\\project\\.gsd\\worktrees\\M001";
|
|
74
74
|
const cdCommand = `cd ${bashPath(windowsCwd)}`;
|
|
75
|
-
|
|
75
|
+
assertEq(
|
|
76
76
|
cdCommand,
|
|
77
77
|
"cd 'C:/Users/user/project/.gsd/worktrees/M001'",
|
|
78
78
|
"cd command uses forward slashes for Windows worktree path",
|
|
79
79
|
);
|
|
80
80
|
|
|
81
81
|
// Verify the mangled form from #1436 is NOT produced
|
|
82
|
-
|
|
82
|
+
assertTrue(
|
|
83
83
|
!cdCommand.includes("C:Users"),
|
|
84
84
|
"mangled path C:Usersuserproject must not appear",
|
|
85
85
|
);
|
|
@@ -90,8 +90,10 @@ console.log("\n=== teardown orphan warning path formatting ===");
|
|
|
90
90
|
|
|
91
91
|
const windowsWtDir = "C:\\Users\\user\\project\\.gsd\\worktrees\\M001";
|
|
92
92
|
const helpCommand = `rm -rf "${windowsWtDir.replaceAll("\\", "/")}"`;
|
|
93
|
-
|
|
93
|
+
assertEq(
|
|
94
94
|
helpCommand,
|
|
95
95
|
'rm -rf "C:/Users/user/project/.gsd/worktrees/M001"',
|
|
96
96
|
"orphan cleanup help command uses forward slashes",
|
|
97
97
|
);
|
|
98
|
+
|
|
99
|
+
report();
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
* and the hasActiveWorkers() status check.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
9
|
-
import assert from 'node:assert/strict';
|
|
8
|
+
import { createTestContext } from './test-helpers.ts';
|
|
10
9
|
import {
|
|
11
10
|
registerWorker,
|
|
12
11
|
updateWorker,
|
|
@@ -16,6 +15,7 @@ import {
|
|
|
16
15
|
resetWorkerRegistry,
|
|
17
16
|
} from '../../subagent/worker-registry.ts';
|
|
18
17
|
|
|
18
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
19
19
|
|
|
20
20
|
// ─── Setup ────────────────────────────────────────────────────────────────────
|
|
21
21
|
|
|
@@ -28,15 +28,15 @@ console.log("\n=== Worker Registration ===");
|
|
|
28
28
|
{
|
|
29
29
|
resetWorkerRegistry();
|
|
30
30
|
const id = registerWorker("scout", "Explore codebase", 0, 3, "batch-1");
|
|
31
|
-
|
|
31
|
+
assertTrue(id.startsWith("worker-"), "worker ID has correct prefix");
|
|
32
32
|
const workers = getActiveWorkers();
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
assertEq(workers.length, 1, "one worker registered");
|
|
34
|
+
assertEq(workers[0].agent, "scout", "worker agent name correct");
|
|
35
|
+
assertEq(workers[0].task, "Explore codebase", "worker task correct");
|
|
36
|
+
assertEq(workers[0].status, "running", "worker starts as running");
|
|
37
|
+
assertEq(workers[0].index, 0, "worker index correct");
|
|
38
|
+
assertEq(workers[0].batchSize, 3, "worker batch size correct");
|
|
39
|
+
assertEq(workers[0].batchId, "batch-1", "worker batch ID correct");
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
// ─── Multiple workers in a batch ──────────────────────────────────────────────
|
|
@@ -50,14 +50,14 @@ console.log("\n=== Multiple Workers in a Batch ===");
|
|
|
50
50
|
const id3 = registerWorker("worker", "Task C", 2, 3, "batch-2");
|
|
51
51
|
|
|
52
52
|
const workers = getActiveWorkers();
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
assertEq(workers.length, 3, "three workers registered");
|
|
54
|
+
assertTrue(hasActiveWorkers(), "has active workers");
|
|
55
55
|
|
|
56
56
|
const batches = getWorkerBatches();
|
|
57
|
-
|
|
57
|
+
assertEq(batches.size, 1, "one batch");
|
|
58
58
|
const batch = batches.get("batch-2");
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
assertTrue(batch !== undefined, "batch-2 exists");
|
|
60
|
+
assertEq(batch!.length, 3, "batch has 3 workers");
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
// ─── Worker status updates ────────────────────────────────────────────────────
|
|
@@ -72,11 +72,11 @@ console.log("\n=== Worker Status Updates ===");
|
|
|
72
72
|
updateWorker(id1, "completed");
|
|
73
73
|
const workers = getActiveWorkers();
|
|
74
74
|
const w1 = workers.find(w => w.id === id1);
|
|
75
|
-
|
|
75
|
+
assertEq(w1?.status, "completed", "worker 1 marked completed");
|
|
76
76
|
|
|
77
77
|
const w2 = workers.find(w => w.id === id2);
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
assertEq(w2?.status, "running", "worker 2 still running");
|
|
79
|
+
assertTrue(hasActiveWorkers(), "still has active workers (worker 2 running)");
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// ─── Failed worker ────────────────────────────────────────────────────────────
|
|
@@ -88,7 +88,7 @@ console.log("\n=== Failed Worker ===");
|
|
|
88
88
|
const id = registerWorker("scout", "Task A", 0, 1, "batch-4");
|
|
89
89
|
updateWorker(id, "failed");
|
|
90
90
|
const workers = getActiveWorkers();
|
|
91
|
-
|
|
91
|
+
assertEq(workers[0].status, "failed", "worker marked failed");
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
// ─── Multiple batches ─────────────────────────────────────────────────────────
|
|
@@ -102,9 +102,9 @@ console.log("\n=== Multiple Batches ===");
|
|
|
102
102
|
registerWorker("researcher", "Task C", 0, 1, "batch-6");
|
|
103
103
|
|
|
104
104
|
const batches = getWorkerBatches();
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
105
|
+
assertEq(batches.size, 2, "two batches");
|
|
106
|
+
assertEq(batches.get("batch-5")!.length, 2, "batch-5 has 2 workers");
|
|
107
|
+
assertEq(batches.get("batch-6")!.length, 1, "batch-6 has 1 worker");
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// ─── hasActiveWorkers with all completed ──────────────────────────────────────
|
|
@@ -117,7 +117,7 @@ console.log("\n=== hasActiveWorkers — all completed ===");
|
|
|
117
117
|
const id2 = registerWorker("worker", "Task B", 1, 2, "batch-7");
|
|
118
118
|
updateWorker(id1, "completed");
|
|
119
119
|
updateWorker(id2, "completed");
|
|
120
|
-
|
|
120
|
+
assertTrue(!hasActiveWorkers(), "no active workers when all completed");
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// ─── Reset clears everything ─────────────────────────────────────────────────
|
|
@@ -126,10 +126,10 @@ console.log("\n=== Reset ===");
|
|
|
126
126
|
|
|
127
127
|
{
|
|
128
128
|
registerWorker("scout", "Task", 0, 1, "batch-8");
|
|
129
|
-
|
|
129
|
+
assertTrue(getActiveWorkers().length > 0, "workers exist before reset");
|
|
130
130
|
resetWorkerRegistry();
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
assertEq(getActiveWorkers().length, 0, "no workers after reset");
|
|
132
|
+
assertTrue(!hasActiveWorkers(), "hasActiveWorkers false after reset");
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
// ─── Update non-existent worker is no-op ──────────────────────────────────────
|
|
@@ -140,7 +140,9 @@ console.log("\n=== Update non-existent worker ===");
|
|
|
140
140
|
resetWorkerRegistry();
|
|
141
141
|
// Should not throw
|
|
142
142
|
updateWorker("nonexistent-id", "completed");
|
|
143
|
-
|
|
143
|
+
assertEq(getActiveWorkers().length, 0, "no workers created by updating nonexistent");
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
// ─── Summary ──────────────────────────────────────────────────────────────────
|
|
147
|
+
|
|
148
|
+
report();
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Tests registry loading, template resolution, auto-detection, and listing.
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
import assert from 'node:assert/strict';
|
|
5
|
+
import { createTestContext } from './test-helpers.ts';
|
|
7
6
|
import {
|
|
8
7
|
loadRegistry,
|
|
9
8
|
resolveByName,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
loadWorkflowTemplate,
|
|
14
13
|
} from '../workflow-templates.ts';
|
|
15
14
|
|
|
15
|
+
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
16
16
|
|
|
17
17
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
18
18
|
// Registry Loading
|
|
@@ -22,23 +22,23 @@ console.log('\n── Registry Loading ──');
|
|
|
22
22
|
|
|
23
23
|
{
|
|
24
24
|
const registry = loadRegistry();
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
assertTrue(registry !== null, 'Registry should load');
|
|
26
|
+
assertEq(registry.version, 1, 'Registry version should be 1');
|
|
27
|
+
assertTrue(Object.keys(registry.templates).length >= 8, 'Should have at least 8 templates');
|
|
28
28
|
|
|
29
29
|
// Verify required template keys exist
|
|
30
30
|
const expectedIds = ['full-project', 'bugfix', 'small-feature', 'refactor', 'spike', 'hotfix', 'security-audit', 'dep-upgrade'];
|
|
31
31
|
for (const id of expectedIds) {
|
|
32
|
-
|
|
32
|
+
assertTrue(id in registry.templates, `Template "${id}" should exist in registry`);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// Verify each template has required fields
|
|
36
36
|
for (const [id, entry] of Object.entries(registry.templates)) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
assertTrue(typeof entry.name === 'string' && entry.name.length > 0, `${id}: name should be non-empty string`);
|
|
38
|
+
assertTrue(typeof entry.description === 'string' && entry.description.length > 0, `${id}: description should be non-empty`);
|
|
39
|
+
assertTrue(typeof entry.file === 'string' && entry.file.endsWith('.md'), `${id}: file should be a .md path`);
|
|
40
|
+
assertTrue(Array.isArray(entry.phases) && entry.phases.length > 0, `${id}: phases should be non-empty array`);
|
|
41
|
+
assertTrue(Array.isArray(entry.triggers) && entry.triggers.length > 0, `${id}: triggers should be non-empty array`);
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -51,31 +51,31 @@ console.log('\n── Resolve by Name ──');
|
|
|
51
51
|
{
|
|
52
52
|
// Exact match
|
|
53
53
|
const bugfix = resolveByName('bugfix');
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
assertTrue(bugfix !== null, 'Should resolve "bugfix"');
|
|
55
|
+
assertEq(bugfix!.id, 'bugfix', 'ID should be "bugfix"');
|
|
56
|
+
assertEq(bugfix!.confidence, 'exact', 'Exact name should have exact confidence');
|
|
57
57
|
|
|
58
58
|
// Case-insensitive name match
|
|
59
59
|
const spike = resolveByName('Research Spike');
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
assertTrue(spike !== null, 'Should resolve "Research Spike" by name');
|
|
61
|
+
assertEq(spike!.id, 'spike', 'Should resolve to spike');
|
|
62
62
|
|
|
63
63
|
// Alias match
|
|
64
64
|
const bug = resolveByName('bug');
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
assertTrue(bug !== null, 'Should resolve "bug" alias');
|
|
66
|
+
assertEq(bug!.id, 'bugfix', 'Alias "bug" should map to bugfix');
|
|
67
67
|
|
|
68
68
|
const feat = resolveByName('feat');
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
assertTrue(feat !== null, 'Should resolve "feat" alias');
|
|
70
|
+
assertEq(feat!.id, 'small-feature', 'Alias "feat" should map to small-feature');
|
|
71
71
|
|
|
72
72
|
const deps = resolveByName('deps');
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
assertTrue(deps !== null, 'Should resolve "deps" alias');
|
|
74
|
+
assertEq(deps!.id, 'dep-upgrade', 'Alias "deps" should map to dep-upgrade');
|
|
75
75
|
|
|
76
76
|
// No match
|
|
77
77
|
const missing = resolveByName('nonexistent-template');
|
|
78
|
-
|
|
78
|
+
assertTrue(missing === null, 'Should return null for unknown template');
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -87,32 +87,32 @@ console.log('\n── Auto-Detection ──');
|
|
|
87
87
|
{
|
|
88
88
|
// Should detect bugfix from "fix" keyword
|
|
89
89
|
const fixMatches = autoDetect('fix the login button');
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
assertTrue(fixMatches.length > 0, 'Should detect matches for "fix the login button"');
|
|
91
|
+
assertTrue(fixMatches.some(m => m.id === 'bugfix'), 'Should include bugfix in matches');
|
|
92
92
|
|
|
93
93
|
// Should detect spike from "research" keyword
|
|
94
94
|
const researchMatches = autoDetect('research authentication libraries');
|
|
95
|
-
|
|
96
|
-
|
|
95
|
+
assertTrue(researchMatches.length > 0, 'Should detect matches for "research"');
|
|
96
|
+
assertTrue(researchMatches.some(m => m.id === 'spike'), 'Should include spike in matches');
|
|
97
97
|
|
|
98
98
|
// Should detect hotfix from "urgent" keyword
|
|
99
99
|
const urgentMatches = autoDetect('urgent production is down');
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
assertTrue(urgentMatches.length > 0, 'Should detect matches for "urgent"');
|
|
101
|
+
assertTrue(urgentMatches.some(m => m.id === 'hotfix'), 'Should include hotfix in matches');
|
|
102
102
|
|
|
103
103
|
// Should detect dep-upgrade from "upgrade" keyword
|
|
104
104
|
const upgradeMatches = autoDetect('upgrade react to v19');
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
assertTrue(upgradeMatches.length > 0, 'Should detect matches for "upgrade"');
|
|
106
|
+
assertTrue(upgradeMatches.some(m => m.id === 'dep-upgrade'), 'Should include dep-upgrade in matches');
|
|
107
107
|
|
|
108
108
|
// Multi-word triggers should score higher
|
|
109
109
|
const projectMatches = autoDetect('create a new project from scratch');
|
|
110
110
|
const projectMatch = projectMatches.find(m => m.id === 'full-project');
|
|
111
|
-
|
|
111
|
+
assertTrue(projectMatch !== undefined, 'Should detect full-project for "from scratch"');
|
|
112
112
|
|
|
113
113
|
// Empty input should return no matches
|
|
114
114
|
const emptyMatches = autoDetect('');
|
|
115
|
-
|
|
115
|
+
assertEq(emptyMatches.length, 0, 'Empty input should return no matches');
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -123,11 +123,11 @@ console.log('\n── List Templates ──');
|
|
|
123
123
|
|
|
124
124
|
{
|
|
125
125
|
const output = listTemplates();
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
126
|
+
assertTrue(output.includes('Workflow Templates'), 'Should have header');
|
|
127
|
+
assertTrue(output.includes('bugfix'), 'Should list bugfix');
|
|
128
|
+
assertTrue(output.includes('spike'), 'Should list spike');
|
|
129
|
+
assertTrue(output.includes('hotfix'), 'Should list hotfix');
|
|
130
|
+
assertTrue(output.includes('/gsd start'), 'Should include usage hint');
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -138,13 +138,13 @@ console.log('\n── Template Info ──');
|
|
|
138
138
|
|
|
139
139
|
{
|
|
140
140
|
const info = getTemplateInfo('bugfix');
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
assertTrue(info !== null, 'Should return info for bugfix');
|
|
142
|
+
assertTrue(info!.includes('Bug Fix'), 'Should include template name');
|
|
143
|
+
assertTrue(info!.includes('triage'), 'Should include phase names');
|
|
144
|
+
assertTrue(info!.includes('Triggers'), 'Should include triggers section');
|
|
145
145
|
|
|
146
146
|
const missing = getTemplateInfo('nonexistent');
|
|
147
|
-
|
|
147
|
+
assertTrue(missing === null, 'Should return null for unknown template');
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
@@ -155,17 +155,19 @@ console.log('\n── Load Workflow Template ──');
|
|
|
155
155
|
|
|
156
156
|
{
|
|
157
157
|
const content = loadWorkflowTemplate('bugfix');
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
assertTrue(content !== null, 'Should load bugfix template');
|
|
159
|
+
assertTrue(content!.includes('Bugfix Workflow'), 'Should contain workflow title');
|
|
160
|
+
assertTrue(content!.includes('Phase 1: Triage'), 'Should contain triage phase');
|
|
161
|
+
assertTrue(content!.includes('Phase 4: Ship'), 'Should contain ship phase');
|
|
162
162
|
|
|
163
163
|
const hotfixContent = loadWorkflowTemplate('hotfix');
|
|
164
|
-
|
|
165
|
-
|
|
164
|
+
assertTrue(hotfixContent !== null, 'Should load hotfix template');
|
|
165
|
+
assertTrue(hotfixContent!.includes('Hotfix Workflow'), 'Should contain hotfix title');
|
|
166
166
|
|
|
167
167
|
const missingContent = loadWorkflowTemplate('nonexistent');
|
|
168
|
-
|
|
168
|
+
assertTrue(missingContent === null, 'Should return null for unknown template');
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
172
|
+
|
|
173
|
+
report();
|
|
@@ -14,10 +14,12 @@ import { join } from "node:path";
|
|
|
14
14
|
import { tmpdir } from "node:os";
|
|
15
15
|
import { execSync } from "node:child_process";
|
|
16
16
|
import { describe, it, after } from "node:test";
|
|
17
|
-
import assert from 'node:assert/strict';
|
|
18
17
|
|
|
19
18
|
import { resolveGitDir } from "../worktree-manager.ts";
|
|
20
19
|
import { detectWorktreeName, captureIntegrationBranch } from "../worktree.ts";
|
|
20
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
21
|
+
|
|
22
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
21
23
|
|
|
22
24
|
// ─── Helpers ──────────────────────────────────────────────────────────────
|
|
23
25
|
|
|
@@ -38,6 +40,7 @@ describe("worktree-bugfix", () => {
|
|
|
38
40
|
const dirs: string[] = [];
|
|
39
41
|
after(() => {
|
|
40
42
|
for (const d of dirs) rmSync(d, { recursive: true, force: true });
|
|
43
|
+
report();
|
|
41
44
|
});
|
|
42
45
|
|
|
43
46
|
it("resolveGitDir returns .git directory in normal repo", () => {
|
|
@@ -45,8 +48,8 @@ describe("worktree-bugfix", () => {
|
|
|
45
48
|
dirs.push(repo);
|
|
46
49
|
initRepo(repo);
|
|
47
50
|
const gitDir = resolveGitDir(repo);
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
assertTrue(gitDir.endsWith(".git"), "ends with .git");
|
|
52
|
+
assertTrue(existsSync(gitDir), ".git dir exists");
|
|
50
53
|
});
|
|
51
54
|
|
|
52
55
|
it("resolveGitDir follows gitdir: pointer in worktree", () => {
|
|
@@ -62,18 +65,18 @@ describe("worktree-bugfix", () => {
|
|
|
62
65
|
writeFileSync(join(wtDir, ".git"), `gitdir: ${realGitDir}\n`);
|
|
63
66
|
|
|
64
67
|
const resolved = resolveGitDir(wtDir);
|
|
65
|
-
|
|
68
|
+
assertEq(resolved, realGitDir, "resolves to real git dir");
|
|
66
69
|
});
|
|
67
70
|
|
|
68
71
|
it("resolveGitDir returns default when .git doesn't exist", () => {
|
|
69
72
|
const noGit = mkdtempSync(join(tmpdir(), "gsd-wt-fix-"));
|
|
70
73
|
dirs.push(noGit);
|
|
71
74
|
const gitDir = resolveGitDir(noGit);
|
|
72
|
-
|
|
75
|
+
assertTrue(gitDir.endsWith(".git"), "returns default .git path");
|
|
73
76
|
});
|
|
74
77
|
|
|
75
78
|
it("detectWorktreeName returns name for worktree path", () => {
|
|
76
|
-
|
|
79
|
+
assertEq(
|
|
77
80
|
detectWorktreeName("/project/.gsd/worktrees/M005"),
|
|
78
81
|
"M005",
|
|
79
82
|
"detects worktree name",
|
|
@@ -81,7 +84,7 @@ describe("worktree-bugfix", () => {
|
|
|
81
84
|
});
|
|
82
85
|
|
|
83
86
|
it("detectWorktreeName returns null for normal repo", () => {
|
|
84
|
-
|
|
87
|
+
assertEq(
|
|
85
88
|
detectWorktreeName("/project"),
|
|
86
89
|
null,
|
|
87
90
|
"null for non-worktree path",
|
|
@@ -103,7 +106,7 @@ describe("worktree-bugfix", () => {
|
|
|
103
106
|
// captureIntegrationBranch should be a no-op — no META.json written
|
|
104
107
|
const metaPath = join(wtPath, ".gsd", "milestones", "M005", "M005-META.json");
|
|
105
108
|
captureIntegrationBranch(wtPath, "M005");
|
|
106
|
-
|
|
109
|
+
assertTrue(!existsSync(metaPath), "no META.json written in worktree");
|
|
107
110
|
});
|
|
108
111
|
|
|
109
112
|
it("detectWorktreeName prevents pull in worktree context", () => {
|
|
@@ -111,7 +114,7 @@ describe("worktree-bugfix", () => {
|
|
|
111
114
|
// the caller should skip pull/fetch operations
|
|
112
115
|
const inWorktree = detectWorktreeName("/project/.gsd/worktrees/M006");
|
|
113
116
|
const inNormal = detectWorktreeName("/project");
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
assertTrue(inWorktree !== null, "worktree detected → skip pull");
|
|
118
|
+
assertTrue(inNormal === null, "normal repo → allow pull");
|
|
116
119
|
});
|
|
117
120
|
});
|
|
@@ -29,9 +29,9 @@ import {
|
|
|
29
29
|
isDbAvailable,
|
|
30
30
|
} from "../gsd-db.ts";
|
|
31
31
|
|
|
32
|
-
import {
|
|
33
|
-
import assert from 'node:assert/strict';
|
|
32
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
34
33
|
|
|
34
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
35
35
|
|
|
36
36
|
function run(command: string, cwd: string): string {
|
|
37
37
|
return execSync(command, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
@@ -49,7 +49,7 @@ function createTempRepo(): string {
|
|
|
49
49
|
return dir;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
async function main(): Promise<void> {
|
|
53
53
|
const savedCwd = process.cwd();
|
|
54
54
|
const tempDirs: string[] = [];
|
|
55
55
|
|
|
@@ -82,7 +82,7 @@ describe('worktree-db-integration', async () => {
|
|
|
82
82
|
const wtPath = createAutoWorktree(tempDir, "M004");
|
|
83
83
|
|
|
84
84
|
const worktreeDbPath = join(worktreePath(tempDir, "M004"), ".gsd", "gsd.db");
|
|
85
|
-
|
|
85
|
+
assertTrue(
|
|
86
86
|
existsSync(worktreeDbPath),
|
|
87
87
|
"gsd.db exists in worktree .gsd after createAutoWorktree",
|
|
88
88
|
);
|
|
@@ -107,10 +107,10 @@ describe('worktree-db-integration', async () => {
|
|
|
107
107
|
console.error(" Unexpected throw:", err);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
|
|
110
|
+
assertTrue(!threw, "createAutoWorktree does not throw when no source DB");
|
|
111
111
|
|
|
112
112
|
const worktreeDbPath = join(worktreePath(tempDir, "M004"), ".gsd", "gsd.db");
|
|
113
|
-
|
|
113
|
+
assertTrue(
|
|
114
114
|
!existsSync(worktreeDbPath),
|
|
115
115
|
"gsd.db is absent in worktree when source had none",
|
|
116
116
|
);
|
|
@@ -145,7 +145,7 @@ describe('worktree-db-integration', async () => {
|
|
|
145
145
|
|
|
146
146
|
// Reconcile worktree → main
|
|
147
147
|
const result = reconcileWorktreeDb(mainDbPath, worktreeDbPath);
|
|
148
|
-
|
|
148
|
+
assertTrue(result.decisions >= 1, "reconcile reports at least 1 decision merged");
|
|
149
149
|
|
|
150
150
|
// Open main DB and verify the row is present
|
|
151
151
|
openDatabase(mainDbPath);
|
|
@@ -153,7 +153,7 @@ describe('worktree-db-integration', async () => {
|
|
|
153
153
|
closeDatabase();
|
|
154
154
|
|
|
155
155
|
const found = decisions.some((d) => d.id === "D-WT-001");
|
|
156
|
-
|
|
156
|
+
assertTrue(found, "worktree decision D-WT-001 present in main DB after reconcile");
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
// ─── Test 4: reconcile non-fatal when both paths nonexistent ─────
|
|
@@ -165,7 +165,7 @@ describe('worktree-db-integration', async () => {
|
|
|
165
165
|
} catch {
|
|
166
166
|
threw = true;
|
|
167
167
|
}
|
|
168
|
-
|
|
168
|
+
assertTrue(!threw, "reconcileWorktreeDb does not throw when worktree DB is absent");
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// ─── Test 5: failure path observable via stderr (diagnostic) ─────
|
|
@@ -181,10 +181,10 @@ describe('worktree-db-integration', async () => {
|
|
|
181
181
|
closeDatabase();
|
|
182
182
|
|
|
183
183
|
const result = reconcileWorktreeDb(mainDbPath, "/definitely/does/not/exist.db");
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
184
|
+
assertEq(result.decisions, 0, "decisions is 0 when worktree DB absent");
|
|
185
|
+
assertEq(result.requirements, 0, "requirements is 0 when worktree DB absent");
|
|
186
|
+
assertEq(result.artifacts, 0, "artifacts is 0 when worktree DB absent");
|
|
187
|
+
assertEq(result.conflicts.length, 0, "conflicts is empty when worktree DB absent");
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
} finally {
|
|
@@ -199,4 +199,8 @@ describe('worktree-db-integration', async () => {
|
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
|
|
203
|
+
report();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
main();
|