gsd-pi 2.44.0-dev.848dd4c → 2.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -30
- package/dist/resources/extensions/gsd/auto-start.js +0 -10
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +0 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +14 -14
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +14 -14
- package/dist/web/standalone/.next/server/chunks/229.js +1 -1
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-7e9530a7122506c5.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +8 -6
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +26 -24
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +48 -29
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +44 -34
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +34 -30
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +12 -10
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +47 -43
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +43 -31
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +45 -40
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/src/resources/extensions/gsd/auto-start.ts +0 -14
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +0 -8
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +16 -14
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +57 -43
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +13 -11
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +523 -465
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +75 -73
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +56 -34
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +656 -533
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +143 -165
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +52 -29
- package/src/resources/extensions/gsd/tests/captures.test.ts +176 -148
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +33 -32
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +143 -141
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +59 -38
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +263 -228
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +302 -250
- package/src/resources/extensions/gsd/tests/context-store.test.ts +367 -354
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +72 -68
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +106 -92
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +35 -27
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +237 -220
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +420 -390
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +92 -76
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +83 -68
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +183 -152
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +101 -78
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +227 -192
- package/src/resources/extensions/gsd/tests/detection.test.ts +278 -232
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +34 -30
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +180 -164
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +49 -43
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +32 -28
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +29 -27
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +38 -34
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +75 -54
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +32 -21
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +97 -72
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +44 -38
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +145 -104
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +106 -84
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +60 -54
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +93 -72
- package/src/resources/extensions/gsd/tests/doctor.test.ts +134 -104
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +131 -123
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +24 -20
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +57 -48
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +42 -30
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +206 -198
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/git-service.test.ts +388 -285
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +39 -31
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +69 -63
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +264 -255
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +119 -108
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +103 -81
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +262 -229
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +102 -81
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +18 -16
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +46 -41
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +53 -42
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +91 -75
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +194 -150
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +125 -101
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +54 -45
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +93 -80
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +66 -57
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +93 -83
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +170 -161
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +141 -125
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +131 -107
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +96 -87
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +164 -125
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +94 -81
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +36 -35
- package/src/resources/extensions/gsd/tests/overrides.test.ts +106 -99
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +47 -40
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +28 -25
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +83 -66
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +77 -54
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +115 -68
- package/src/resources/extensions/gsd/tests/parsers.test.ts +611 -546
- package/src/resources/extensions/gsd/tests/paths.test.ts +87 -72
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +117 -77
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +119 -93
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +82 -70
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +55 -42
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +73 -45
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +38 -28
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +80 -73
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +74 -71
- package/src/resources/extensions/gsd/tests/requirements.test.ts +75 -70
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +66 -44
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +181 -114
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +65 -63
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +128 -66
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +25 -18
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +28 -22
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +56 -54
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +25 -23
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +11 -9
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +82 -66
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +47 -46
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +22 -20
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +86 -84
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +43 -41
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +96 -94
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +13 -11
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +29 -27
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +52 -50
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +13 -10
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +18 -14
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +39 -38
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +21 -17
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +30 -25
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +22 -15
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +66 -59
- package/src/resources/extensions/gsd/tests/worktree.test.ts +50 -44
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +0 -100
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +0 -63
- /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{-zps1Q9mQmioAKLcQiCr8 → mgkxN0mGP6gSUmGPEzbk_}/_ssgManifest.js +0 -0
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { describe, test } from 'node:test';
|
|
2
|
-
import assert from 'node:assert/strict';
|
|
3
1
|
/**
|
|
4
2
|
* doctor-git.test.ts — Integration tests for doctor git health checks.
|
|
5
3
|
*
|
|
@@ -16,6 +14,10 @@ import { tmpdir } from "node:os";
|
|
|
16
14
|
import { execSync } from "node:child_process";
|
|
17
15
|
|
|
18
16
|
import { runGSDDoctor } from "../doctor.ts";
|
|
17
|
+
import { createTestContext } from "./test-helpers.ts";
|
|
18
|
+
|
|
19
|
+
const { assertEq, assertTrue, report } = createTestContext();
|
|
20
|
+
|
|
19
21
|
function run(cmd: string, cwd: string): string {
|
|
20
22
|
return execSync(cmd, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
21
23
|
}
|
|
@@ -112,7 +114,7 @@ _None_
|
|
|
112
114
|
return dir;
|
|
113
115
|
}
|
|
114
116
|
|
|
115
|
-
|
|
117
|
+
async function main(): Promise<void> {
|
|
116
118
|
const cleanups: string[] = [];
|
|
117
119
|
|
|
118
120
|
try {
|
|
@@ -122,7 +124,8 @@ describe('doctor-git', async () => {
|
|
|
122
124
|
// logic is correct (tested on macOS/Linux) — the test infra doesn't
|
|
123
125
|
// produce matching paths on Windows CI.
|
|
124
126
|
if (process.platform !== "win32") {
|
|
125
|
-
|
|
127
|
+
console.log("\n=== orphaned_auto_worktree ===");
|
|
128
|
+
{
|
|
126
129
|
const dir = createRepoWithCompletedMilestone();
|
|
127
130
|
cleanups.push(dir);
|
|
128
131
|
|
|
@@ -132,24 +135,26 @@ describe('doctor-git', async () => {
|
|
|
132
135
|
|
|
133
136
|
const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
|
|
134
137
|
const orphanIssues = detect.issues.filter(i => i.code === "orphaned_auto_worktree");
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
assertTrue(orphanIssues.length > 0, "detects orphaned worktree");
|
|
139
|
+
assertEq(orphanIssues[0]?.unitId, "M001", "orphaned worktree unitId is M001");
|
|
137
140
|
|
|
138
141
|
const fixed = await runGSDDoctor(dir, { fix: true, isolationMode: "worktree" });
|
|
139
|
-
|
|
142
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("removed orphaned worktree")), "fix removes orphaned worktree");
|
|
140
143
|
|
|
141
144
|
// Verify worktree is gone
|
|
142
145
|
const wtList = run("git worktree list", dir);
|
|
143
|
-
|
|
144
|
-
}
|
|
146
|
+
assertTrue(!wtList.includes("milestone/M001"), "worktree no longer listed after fix");
|
|
147
|
+
}
|
|
145
148
|
} else {
|
|
149
|
+
console.log("\n=== orphaned_auto_worktree (skipped on Windows) ===");
|
|
146
150
|
}
|
|
147
151
|
|
|
148
152
|
// ─── Test 2: Stale milestone branch detection & fix ────────────────
|
|
149
153
|
// Skip on Windows: git branch glob matching and path resolution
|
|
150
154
|
// behave differently in Windows temp dirs.
|
|
151
155
|
if (process.platform !== "win32") {
|
|
152
|
-
|
|
156
|
+
console.log("\n=== stale_milestone_branch ===");
|
|
157
|
+
{
|
|
153
158
|
const dir = createRepoWithCompletedMilestone();
|
|
154
159
|
cleanups.push(dir);
|
|
155
160
|
|
|
@@ -158,21 +163,23 @@ describe('doctor-git', async () => {
|
|
|
158
163
|
|
|
159
164
|
const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
|
|
160
165
|
const staleIssues = detect.issues.filter(i => i.code === "stale_milestone_branch");
|
|
161
|
-
|
|
162
|
-
|
|
166
|
+
assertTrue(staleIssues.length > 0, "detects stale milestone branch");
|
|
167
|
+
assertEq(staleIssues[0]?.unitId, "M001", "stale branch unitId is M001");
|
|
163
168
|
|
|
164
169
|
const fixed = await runGSDDoctor(dir, { fix: true, isolationMode: "worktree" });
|
|
165
|
-
|
|
170
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("deleted stale branch")), "fix deletes stale branch");
|
|
166
171
|
|
|
167
172
|
// Verify branch is gone
|
|
168
173
|
const branches = run("git branch --list milestone/*", dir);
|
|
169
|
-
|
|
170
|
-
}
|
|
174
|
+
assertTrue(!branches.includes("milestone/M001"), "branch gone after fix");
|
|
175
|
+
}
|
|
171
176
|
} else {
|
|
177
|
+
console.log("\n=== stale_milestone_branch (skipped on Windows) ===");
|
|
172
178
|
}
|
|
173
179
|
|
|
174
180
|
// ─── Test 3: Corrupt merge state detection & fix ───────────────────
|
|
175
|
-
|
|
181
|
+
console.log("\n=== corrupt_merge_state ===");
|
|
182
|
+
{
|
|
176
183
|
const dir = createRepoWithCompletedMilestone();
|
|
177
184
|
cleanups.push(dir);
|
|
178
185
|
|
|
@@ -182,17 +189,18 @@ describe('doctor-git', async () => {
|
|
|
182
189
|
|
|
183
190
|
const detect = await runGSDDoctor(dir);
|
|
184
191
|
const mergeIssues = detect.issues.filter(i => i.code === "corrupt_merge_state");
|
|
185
|
-
|
|
192
|
+
assertTrue(mergeIssues.length > 0, "detects corrupt merge state");
|
|
186
193
|
|
|
187
194
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
188
|
-
|
|
195
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("cleaned merge state")), "fix cleans merge state");
|
|
189
196
|
|
|
190
197
|
// Verify MERGE_HEAD is gone
|
|
191
|
-
|
|
192
|
-
}
|
|
198
|
+
assertTrue(!existsSync(join(dir, ".git", "MERGE_HEAD")), "MERGE_HEAD removed after fix");
|
|
199
|
+
}
|
|
193
200
|
|
|
194
201
|
// ─── Test 4: Tracked runtime files detection & fix ─────────────────
|
|
195
|
-
|
|
202
|
+
console.log("\n=== tracked_runtime_files ===");
|
|
203
|
+
{
|
|
196
204
|
const dir = createRepoWithCompletedMilestone();
|
|
197
205
|
cleanups.push(dir);
|
|
198
206
|
|
|
@@ -205,18 +213,19 @@ describe('doctor-git', async () => {
|
|
|
205
213
|
|
|
206
214
|
const detect = await runGSDDoctor(dir);
|
|
207
215
|
const trackedIssues = detect.issues.filter(i => i.code === "tracked_runtime_files");
|
|
208
|
-
|
|
216
|
+
assertTrue(trackedIssues.length > 0, "detects tracked runtime files");
|
|
209
217
|
|
|
210
218
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
211
|
-
|
|
219
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("untracked")), "fix untracks runtime files");
|
|
212
220
|
|
|
213
221
|
// Verify file is no longer tracked
|
|
214
222
|
const tracked = run("git ls-files .gsd/activity/", dir);
|
|
215
|
-
|
|
216
|
-
}
|
|
223
|
+
assertEq(tracked, "", "runtime file untracked after fix");
|
|
224
|
+
}
|
|
217
225
|
|
|
218
226
|
// ─── Test 5: Non-git directory — graceful degradation ──────────────
|
|
219
|
-
|
|
227
|
+
console.log("\n=== non-git directory ===");
|
|
228
|
+
{
|
|
220
229
|
const dir = realpathSync(mkdtempSync(join(tmpdir(), "doc-git-test-")));
|
|
221
230
|
cleanups.push(dir);
|
|
222
231
|
|
|
@@ -227,14 +236,15 @@ describe('doctor-git', async () => {
|
|
|
227
236
|
const gitIssues = result.issues.filter(i =>
|
|
228
237
|
["orphaned_auto_worktree", "stale_milestone_branch", "corrupt_merge_state", "tracked_runtime_files"].includes(i.code)
|
|
229
238
|
);
|
|
230
|
-
|
|
239
|
+
assertEq(gitIssues.length, 0, "no git issues in non-git directory");
|
|
231
240
|
// Should not throw — reaching here means no crash
|
|
232
|
-
|
|
233
|
-
}
|
|
241
|
+
assertTrue(true, "non-git directory does not crash");
|
|
242
|
+
}
|
|
234
243
|
|
|
235
244
|
// ─── Test 6: Active worktree NOT flagged (false positive prevention) ─
|
|
236
245
|
if (process.platform !== "win32") {
|
|
237
|
-
|
|
246
|
+
console.log("\n=== active worktree safety ===");
|
|
247
|
+
{
|
|
238
248
|
const dir = createRepoWithActiveMilestone();
|
|
239
249
|
cleanups.push(dir);
|
|
240
250
|
|
|
@@ -244,9 +254,10 @@ describe('doctor-git', async () => {
|
|
|
244
254
|
|
|
245
255
|
const detect = await runGSDDoctor(dir, { isolationMode: "worktree" });
|
|
246
256
|
const orphanIssues = detect.issues.filter(i => i.code === "orphaned_auto_worktree");
|
|
247
|
-
|
|
248
|
-
}
|
|
257
|
+
assertEq(orphanIssues.length, 0, "active worktree NOT flagged as orphaned");
|
|
258
|
+
}
|
|
249
259
|
} else {
|
|
260
|
+
console.log("\n=== active worktree safety (skipped on Windows) ===");
|
|
250
261
|
}
|
|
251
262
|
|
|
252
263
|
// ─── Test 7: none-mode skips orphaned worktree check ───────────────
|
|
@@ -254,7 +265,8 @@ describe('doctor-git', async () => {
|
|
|
254
265
|
// at module load time from process.cwd(). We write the prefs file to
|
|
255
266
|
// the test runner's cwd .gsd/preferences.md and clean up afterwards.
|
|
256
267
|
if (process.platform !== "win32") {
|
|
257
|
-
|
|
268
|
+
console.log("\n=== none-mode skips orphaned worktree ===");
|
|
269
|
+
{
|
|
258
270
|
const dir = createRepoWithCompletedMilestone();
|
|
259
271
|
cleanups.push(dir);
|
|
260
272
|
|
|
@@ -264,14 +276,16 @@ describe('doctor-git', async () => {
|
|
|
264
276
|
|
|
265
277
|
const result = await runGSDDoctor(dir, { isolationMode: "none" });
|
|
266
278
|
const orphanIssues = result.issues.filter(i => i.code === "orphaned_auto_worktree");
|
|
267
|
-
|
|
268
|
-
}
|
|
279
|
+
assertEq(orphanIssues.length, 0, "none-mode: orphaned worktree NOT detected");
|
|
280
|
+
}
|
|
269
281
|
} else {
|
|
282
|
+
console.log("\n=== none-mode skips orphaned worktree (skipped on Windows) ===");
|
|
270
283
|
}
|
|
271
284
|
|
|
272
285
|
// ─── Test 8: none-mode skips stale branch check ────────────────────
|
|
273
286
|
if (process.platform !== "win32") {
|
|
274
|
-
|
|
287
|
+
console.log("\n=== none-mode skips stale branch ===");
|
|
288
|
+
{
|
|
275
289
|
const dir = createRepoWithCompletedMilestone();
|
|
276
290
|
cleanups.push(dir);
|
|
277
291
|
|
|
@@ -280,14 +294,16 @@ describe('doctor-git', async () => {
|
|
|
280
294
|
|
|
281
295
|
const result = await runGSDDoctor(dir, { isolationMode: "none" });
|
|
282
296
|
const staleIssues = result.issues.filter(i => i.code === "stale_milestone_branch");
|
|
283
|
-
|
|
284
|
-
}
|
|
297
|
+
assertEq(staleIssues.length, 0, "none-mode: stale branch NOT detected");
|
|
298
|
+
}
|
|
285
299
|
} else {
|
|
300
|
+
console.log("\n=== none-mode skips stale branch (skipped on Windows) ===");
|
|
286
301
|
}
|
|
287
302
|
|
|
288
303
|
// ─── Test: Integration branch missing ──────────────────────────────
|
|
289
304
|
if (process.platform !== "win32") {
|
|
290
|
-
|
|
305
|
+
console.log("\n=== integration_branch_missing ===");
|
|
306
|
+
{
|
|
291
307
|
const dir = createRepoWithActiveMilestone();
|
|
292
308
|
cleanups.push(dir);
|
|
293
309
|
|
|
@@ -297,20 +313,22 @@ describe('doctor-git', async () => {
|
|
|
297
313
|
|
|
298
314
|
const detect = await runGSDDoctor(dir);
|
|
299
315
|
const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
|
|
300
|
-
|
|
301
|
-
|
|
316
|
+
assertTrue(missingBranchIssues.length > 0, "detects missing integration branch");
|
|
317
|
+
assertTrue(
|
|
302
318
|
missingBranchIssues[0]?.message.includes("feat/does-not-exist"),
|
|
303
319
|
"message includes the missing branch name",
|
|
304
320
|
);
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
}
|
|
321
|
+
assertEq(missingBranchIssues[0]?.fixable, true, "integration_branch_missing is auto-fixable via fallback");
|
|
322
|
+
assertEq(missingBranchIssues[0]?.severity, "warning", "severity is warning (fallback available)");
|
|
323
|
+
}
|
|
308
324
|
} else {
|
|
325
|
+
console.log("\n=== integration_branch_missing (skipped on Windows) ===");
|
|
309
326
|
}
|
|
310
327
|
|
|
311
328
|
// ─── Test: Integration branch present — no false positive ──────────
|
|
312
329
|
if (process.platform !== "win32") {
|
|
313
|
-
|
|
330
|
+
console.log("\n=== integration_branch_missing (no false positive) ===");
|
|
331
|
+
{
|
|
314
332
|
const dir = createRepoWithActiveMilestone();
|
|
315
333
|
cleanups.push(dir);
|
|
316
334
|
|
|
@@ -320,13 +338,15 @@ describe('doctor-git', async () => {
|
|
|
320
338
|
|
|
321
339
|
const detect = await runGSDDoctor(dir);
|
|
322
340
|
const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
|
|
323
|
-
|
|
324
|
-
}
|
|
341
|
+
assertEq(missingBranchIssues.length, 0, "existing integration branch NOT flagged");
|
|
342
|
+
}
|
|
325
343
|
} else {
|
|
344
|
+
console.log("\n=== integration_branch_missing (no false positive — skipped on Windows) ===");
|
|
326
345
|
}
|
|
327
346
|
|
|
328
347
|
// ─── Test: Orphaned worktree directory ─────────────────────────────
|
|
329
|
-
|
|
348
|
+
console.log("\n=== integration_branch_missing: stale metadata with detected fallback ===");
|
|
349
|
+
{
|
|
330
350
|
const dir = createRepoWithActiveMilestone();
|
|
331
351
|
cleanups.push(dir);
|
|
332
352
|
|
|
@@ -335,26 +355,27 @@ describe('doctor-git', async () => {
|
|
|
335
355
|
|
|
336
356
|
const detect = await runGSDDoctor(dir);
|
|
337
357
|
const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
358
|
+
assertEq(missingBranchIssues.length, 1, "reports one stale integration branch issue");
|
|
359
|
+
assertEq(missingBranchIssues[0]?.severity, "warning", "stale metadata is warning when a fallback branch exists");
|
|
360
|
+
assertEq(missingBranchIssues[0]?.fixable, true, "stale metadata becomes auto-fixable when fallback exists");
|
|
361
|
+
assertTrue(
|
|
342
362
|
missingBranchIssues[0]?.message.includes("feat/does-not-exist") &&
|
|
343
363
|
missingBranchIssues[0]?.message.includes("main"),
|
|
344
364
|
"warning mentions stale recorded branch and detected fallback branch",
|
|
345
365
|
);
|
|
346
366
|
|
|
347
367
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
348
|
-
|
|
368
|
+
assertTrue(
|
|
349
369
|
fixed.fixesApplied.some(f => f.includes('updated integration branch for M001 to "main"')),
|
|
350
370
|
"doctor fix rewrites stale integration branch metadata to detected fallback branch",
|
|
351
371
|
);
|
|
352
372
|
|
|
353
373
|
const repairedMeta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
354
|
-
|
|
355
|
-
}
|
|
374
|
+
assertEq(repairedMeta.integrationBranch, "main", "metadata rewritten to detected fallback branch");
|
|
375
|
+
}
|
|
356
376
|
|
|
357
|
-
|
|
377
|
+
console.log("\n=== integration_branch_missing: stale metadata with configured fallback ===");
|
|
378
|
+
{
|
|
358
379
|
const dir = createRepoWithActiveMilestone();
|
|
359
380
|
cleanups.push(dir);
|
|
360
381
|
|
|
@@ -369,17 +390,17 @@ describe('doctor-git', async () => {
|
|
|
369
390
|
try {
|
|
370
391
|
const detect = await runGSDDoctor(dir);
|
|
371
392
|
const missingBranchIssues = detect.issues.filter(i => i.code === "integration_branch_missing");
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
393
|
+
assertEq(missingBranchIssues.length, 1, "configured fallback still reports one stale integration branch issue");
|
|
394
|
+
assertEq(missingBranchIssues[0]?.severity, "warning", "configured fallback keeps stale metadata at warning severity");
|
|
395
|
+
assertEq(missingBranchIssues[0]?.fixable, true, "configured fallback remains auto-fixable");
|
|
396
|
+
assertTrue(
|
|
376
397
|
missingBranchIssues[0]?.message.includes("feat/does-not-exist") &&
|
|
377
398
|
missingBranchIssues[0]?.message.includes("trunk"),
|
|
378
399
|
"warning mentions stale recorded branch and configured fallback branch",
|
|
379
400
|
);
|
|
380
401
|
|
|
381
402
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
382
|
-
|
|
403
|
+
assertTrue(
|
|
383
404
|
fixed.fixesApplied.some(f => f.includes('updated integration branch for M001 to "trunk"')),
|
|
384
405
|
"doctor fix rewrites stale metadata to configured fallback branch",
|
|
385
406
|
);
|
|
@@ -388,11 +409,12 @@ describe('doctor-git', async () => {
|
|
|
388
409
|
}
|
|
389
410
|
|
|
390
411
|
const repairedMeta = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
391
|
-
|
|
392
|
-
}
|
|
412
|
+
assertEq(repairedMeta.integrationBranch, "trunk", "metadata rewritten to configured fallback branch");
|
|
413
|
+
}
|
|
393
414
|
|
|
394
415
|
if (process.platform !== "win32") {
|
|
395
|
-
|
|
416
|
+
console.log("\n=== worktree_directory_orphaned ===");
|
|
417
|
+
{
|
|
396
418
|
const dir = createRepoWithActiveMilestone();
|
|
397
419
|
cleanups.push(dir);
|
|
398
420
|
|
|
@@ -403,26 +425,28 @@ describe('doctor-git', async () => {
|
|
|
403
425
|
|
|
404
426
|
const detect = await runGSDDoctor(dir);
|
|
405
427
|
const orphanDirIssues = detect.issues.filter(i => i.code === "worktree_directory_orphaned");
|
|
406
|
-
|
|
407
|
-
|
|
428
|
+
assertTrue(orphanDirIssues.length > 0, "detects orphaned worktree directory");
|
|
429
|
+
assertTrue(
|
|
408
430
|
orphanDirIssues[0]?.message.includes("orphan-feature"),
|
|
409
431
|
"message includes the orphaned directory name",
|
|
410
432
|
);
|
|
411
|
-
|
|
433
|
+
assertTrue(orphanDirIssues[0]?.fixable === true, "worktree_directory_orphaned is fixable");
|
|
412
434
|
|
|
413
435
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
414
|
-
|
|
436
|
+
assertTrue(
|
|
415
437
|
fixed.fixesApplied.some(f => f.includes("removed orphaned worktree directory")),
|
|
416
438
|
"fix removes orphaned worktree directory",
|
|
417
439
|
);
|
|
418
|
-
|
|
419
|
-
}
|
|
440
|
+
assertTrue(!existsSync(orphanDir), "orphaned directory removed after fix");
|
|
441
|
+
}
|
|
420
442
|
} else {
|
|
443
|
+
console.log("\n=== worktree_directory_orphaned (skipped on Windows) ===");
|
|
421
444
|
}
|
|
422
445
|
|
|
423
446
|
// ─── Test: Registered worktree NOT flagged as orphaned ─────────────
|
|
424
447
|
if (process.platform !== "win32") {
|
|
425
|
-
|
|
448
|
+
console.log("\n=== worktree_directory_orphaned (registered worktree not flagged) ===");
|
|
449
|
+
{
|
|
426
450
|
const dir = createRepoWithActiveMilestone();
|
|
427
451
|
cleanups.push(dir);
|
|
428
452
|
|
|
@@ -432,13 +456,15 @@ describe('doctor-git', async () => {
|
|
|
432
456
|
|
|
433
457
|
const detect = await runGSDDoctor(dir);
|
|
434
458
|
const orphanDirIssues = detect.issues.filter(i => i.code === "worktree_directory_orphaned");
|
|
435
|
-
|
|
436
|
-
}
|
|
459
|
+
assertEq(orphanDirIssues.length, 0, "registered worktree NOT flagged as orphaned");
|
|
460
|
+
}
|
|
437
461
|
} else {
|
|
462
|
+
console.log("\n=== worktree_directory_orphaned (registered worktree not flagged — skipped on Windows) ===");
|
|
438
463
|
}
|
|
439
464
|
|
|
440
465
|
// ─── Test 9: none-mode still detects corrupt merge state ───────────
|
|
441
|
-
|
|
466
|
+
console.log("\n=== none-mode keeps corrupt merge state ===");
|
|
467
|
+
{
|
|
442
468
|
const dir = createRepoWithCompletedMilestone();
|
|
443
469
|
cleanups.push(dir);
|
|
444
470
|
|
|
@@ -448,11 +474,12 @@ describe('doctor-git', async () => {
|
|
|
448
474
|
|
|
449
475
|
const result = await runGSDDoctor(dir, { isolationMode: "none" });
|
|
450
476
|
const mergeIssues = result.issues.filter(i => i.code === "corrupt_merge_state");
|
|
451
|
-
|
|
452
|
-
}
|
|
477
|
+
assertTrue(mergeIssues.length > 0, "none-mode: corrupt merge state IS detected");
|
|
478
|
+
}
|
|
453
479
|
|
|
454
480
|
// ─── Test 10: none-mode still detects tracked runtime files ────────
|
|
455
|
-
|
|
481
|
+
console.log("\n=== none-mode keeps tracked runtime files ===");
|
|
482
|
+
{
|
|
456
483
|
const dir = createRepoWithCompletedMilestone();
|
|
457
484
|
cleanups.push(dir);
|
|
458
485
|
|
|
@@ -465,12 +492,13 @@ describe('doctor-git', async () => {
|
|
|
465
492
|
|
|
466
493
|
const result = await runGSDDoctor(dir, { isolationMode: "none" });
|
|
467
494
|
const trackedIssues = result.issues.filter(i => i.code === "tracked_runtime_files");
|
|
468
|
-
|
|
469
|
-
}
|
|
495
|
+
assertTrue(trackedIssues.length > 0, "none-mode: tracked runtime files IS detected");
|
|
496
|
+
}
|
|
470
497
|
|
|
471
498
|
// ─── Test: Symlinked .gsd does not cause false orphan detection ────
|
|
472
499
|
if (process.platform !== "win32") {
|
|
473
|
-
|
|
500
|
+
console.log("\n=== worktree_directory_orphaned (symlinked .gsd not false-positive) ===");
|
|
501
|
+
{
|
|
474
502
|
const dir = createRepoWithActiveMilestone();
|
|
475
503
|
cleanups.push(dir);
|
|
476
504
|
|
|
@@ -487,14 +515,16 @@ describe('doctor-git', async () => {
|
|
|
487
515
|
|
|
488
516
|
const detect = await runGSDDoctor(dir);
|
|
489
517
|
const orphanDirIssues = detect.issues.filter(i => i.code === "worktree_directory_orphaned");
|
|
490
|
-
|
|
491
|
-
}
|
|
518
|
+
assertEq(orphanDirIssues.length, 0, "registered worktree via symlinked .gsd NOT flagged as orphaned");
|
|
519
|
+
}
|
|
492
520
|
} else {
|
|
521
|
+
console.log("\n=== worktree_directory_orphaned (symlinked .gsd — skipped on Windows) ===");
|
|
493
522
|
}
|
|
494
523
|
|
|
495
524
|
// ─── Test: worktree_branch_merged detection & fix ──────────────────
|
|
496
525
|
if (process.platform !== "win32") {
|
|
497
|
-
|
|
526
|
+
console.log("\n=== worktree_branch_merged ===");
|
|
527
|
+
{
|
|
498
528
|
const dir = createRepoWithActiveMilestone();
|
|
499
529
|
cleanups.push(dir);
|
|
500
530
|
|
|
@@ -511,21 +541,23 @@ describe('doctor-git', async () => {
|
|
|
511
541
|
|
|
512
542
|
const detect = await runGSDDoctor(dir);
|
|
513
543
|
const mergedIssues = detect.issues.filter(i => i.code === "worktree_branch_merged");
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
544
|
+
assertTrue(mergedIssues.length > 0, "detects merged worktree branch");
|
|
545
|
+
assertTrue(mergedIssues[0]?.message.includes("safe to remove"), "message says safe to remove");
|
|
546
|
+
assertTrue(mergedIssues[0]?.fixable === true, "merged worktree is fixable");
|
|
517
547
|
|
|
518
548
|
// Fix should remove the worktree
|
|
519
549
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
}
|
|
550
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("removed merged worktree")), "fix removes merged worktree");
|
|
551
|
+
assertTrue(!existsSync(wtPath), "worktree directory removed after fix");
|
|
552
|
+
}
|
|
523
553
|
} else {
|
|
554
|
+
console.log("\n=== worktree_branch_merged (skipped on Windows) ===");
|
|
524
555
|
}
|
|
525
556
|
|
|
526
557
|
// ─── Test: merged milestone/* worktree removes milestone branch ────
|
|
527
558
|
if (process.platform !== "win32") {
|
|
528
|
-
|
|
559
|
+
console.log("\n=== worktree_branch_merged (milestone branch cleanup) ===");
|
|
560
|
+
{
|
|
529
561
|
const dir = createRepoWithActiveMilestone();
|
|
530
562
|
cleanups.push(dir);
|
|
531
563
|
|
|
@@ -538,18 +570,20 @@ describe('doctor-git', async () => {
|
|
|
538
570
|
run("git merge milestone/M001 --no-edit", dir);
|
|
539
571
|
|
|
540
572
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
541
|
-
|
|
542
|
-
|
|
573
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("removed merged worktree")), "fix removes merged milestone worktree");
|
|
574
|
+
assertTrue(!existsSync(wtPath), "milestone worktree directory removed after fix");
|
|
543
575
|
|
|
544
576
|
const branches = run("git branch --list milestone/M001", dir);
|
|
545
|
-
|
|
546
|
-
}
|
|
577
|
+
assertEq(branches, "", "milestone/M001 branch deleted after merged worktree cleanup");
|
|
578
|
+
}
|
|
547
579
|
} else {
|
|
580
|
+
console.log("\n=== worktree_branch_merged (milestone branch cleanup — skipped on Windows) ===");
|
|
548
581
|
}
|
|
549
582
|
|
|
550
583
|
// ─── Test: worktree_branch_merged NOT flagged for unmerged worktree ─
|
|
551
584
|
if (process.platform !== "win32") {
|
|
552
|
-
|
|
585
|
+
console.log("\n=== worktree_branch_merged (no false positive) ===");
|
|
586
|
+
{
|
|
553
587
|
const dir = createRepoWithActiveMilestone();
|
|
554
588
|
cleanups.push(dir);
|
|
555
589
|
|
|
@@ -563,14 +597,16 @@ describe('doctor-git', async () => {
|
|
|
563
597
|
// Do NOT merge — branch is ahead of main
|
|
564
598
|
const detect = await runGSDDoctor(dir);
|
|
565
599
|
const mergedIssues = detect.issues.filter(i => i.code === "worktree_branch_merged");
|
|
566
|
-
|
|
567
|
-
}
|
|
600
|
+
assertEq(mergedIssues.length, 0, "unmerged worktree NOT flagged as merged");
|
|
601
|
+
}
|
|
568
602
|
} else {
|
|
603
|
+
console.log("\n=== worktree_branch_merged (no false positive — skipped on Windows) ===");
|
|
569
604
|
}
|
|
570
605
|
|
|
571
606
|
// ─── Test: legacy_slice_branches now fixable ───────────────────────
|
|
572
607
|
if (process.platform !== "win32") {
|
|
573
|
-
|
|
608
|
+
console.log("\n=== legacy_slice_branches (fixable) ===");
|
|
609
|
+
{
|
|
574
610
|
const dir = createRepoWithActiveMilestone();
|
|
575
611
|
cleanups.push(dir);
|
|
576
612
|
|
|
@@ -582,17 +618,18 @@ describe('doctor-git', async () => {
|
|
|
582
618
|
|
|
583
619
|
const detect = await runGSDDoctor(dir);
|
|
584
620
|
const legacyIssues = detect.issues.filter(i => i.code === "legacy_slice_branches");
|
|
585
|
-
|
|
586
|
-
|
|
621
|
+
assertTrue(legacyIssues.length > 0, "detects legacy slice branches");
|
|
622
|
+
assertTrue(legacyIssues[0]?.fixable === true, "legacy branches are fixable");
|
|
587
623
|
|
|
588
624
|
const fixed = await runGSDDoctor(dir, { fix: true });
|
|
589
|
-
|
|
625
|
+
assertTrue(fixed.fixesApplied.some(f => f.includes("legacy slice branch")), "fix deletes legacy branches");
|
|
590
626
|
|
|
591
627
|
// Verify branches are gone
|
|
592
628
|
const remaining = run("git branch --list gsd/*/*", dir);
|
|
593
|
-
|
|
594
|
-
}
|
|
629
|
+
assertEq(remaining, "gsd/quick/1-fix-typo", "quick branch preserved; legacy branches removed");
|
|
630
|
+
}
|
|
595
631
|
} else {
|
|
632
|
+
console.log("\n=== legacy_slice_branches (fixable — skipped on Windows) ===");
|
|
596
633
|
}
|
|
597
634
|
|
|
598
635
|
} finally {
|
|
@@ -600,4 +637,8 @@ describe('doctor-git', async () => {
|
|
|
600
637
|
try { rmSync(dir, { recursive: true, force: true }); } catch { /* ignore */ }
|
|
601
638
|
}
|
|
602
639
|
}
|
|
603
|
-
|
|
640
|
+
|
|
641
|
+
report();
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
main();
|