gsd-pi 2.43.0-next.8 → 2.44.0-dev.0b97ffd
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -12
- package/dist/cli.js +13 -1
- package/dist/help-text.js +24 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +21 -8
- package/dist/resources/extensions/gsd/auto-prompts.js +130 -51
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +16 -2
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +34 -10
- package/dist/resources/extensions/gsd/markdown-renderer.js +7 -5
- package/dist/resources/extensions/gsd/reactive-graph.js +13 -2
- package/dist/resources/extensions/gsd/skill-health.js +3 -1
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +2 -11
- package/dist/resources/extensions/gsd/tools/plan-slice.js +2 -10
- package/dist/resources/extensions/gsd/visualizer-data.js +45 -13
- package/dist/resources/extensions/gsd/workspace-index.js +46 -15
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +5 -5
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
- package/dist/web/standalone/.next/server/chunks/229.js +1 -1
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-f2a7482d42a5614b.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/page-b9367c5ae13b99c6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-2f2ee7b85712c2bd.js → main-app-fdab67f7802d7832.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +4 -4
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +3 -3
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +11 -34
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +6 -8
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/branch-summarization.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js +4 -4
- package/packages/pi-coding-agent/dist/core/compaction-orchestrator.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +18 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js +2 -3
- package/packages/pi-coding-agent/dist/core/fallback-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js +12 -2
- package/packages/pi-coding-agent/dist/core/fallback-resolver.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts +38 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js +192 -0
- package/packages/pi-coding-agent/dist/core/lifecycle-hooks.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +255 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +40 -3
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/package-commands.d.ts +25 -0
- package/packages/pi-coding-agent/dist/core/package-commands.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.js +253 -0
- package/packages/pi-coding-agent/dist/core/package-commands.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.js +225 -0
- package/packages/pi-coding-agent/dist/core/package-commands.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +4 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +3 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/main.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/main.js +11 -199
- package/packages/pi-coding-agent/dist/main.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +13 -37
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/compaction/branch-summarization.ts +2 -2
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +3 -3
- package/packages/pi-coding-agent/src/core/compaction-orchestrator.ts +4 -4
- package/packages/pi-coding-agent/src/core/extensions/index.ts +5 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +23 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/extensions/types.ts +44 -0
- package/packages/pi-coding-agent/src/core/fallback-resolver.test.ts +15 -2
- package/packages/pi-coding-agent/src/core/fallback-resolver.ts +2 -3
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/lifecycle-hooks.ts +274 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +288 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +39 -3
- package/packages/pi-coding-agent/src/core/package-commands.test.ts +240 -0
- package/packages/pi-coding-agent/src/core/package-commands.ts +310 -0
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/sdk.ts +4 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/index.ts +7 -0
- package/packages/pi-coding-agent/src/main.ts +11 -232
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/pkg/package.json +1 -1
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +22 -7
- package/src/resources/extensions/gsd/auto-prompts.ts +109 -42
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +16 -3
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +28 -10
- package/src/resources/extensions/gsd/markdown-renderer.ts +7 -5
- package/src/resources/extensions/gsd/reactive-graph.ts +12 -2
- package/src/resources/extensions/gsd/skill-health.ts +2 -1
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
- package/src/resources/extensions/gsd/tests/auto-stash-merge.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
- package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
- package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
- package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
- package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
- package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
- package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
- package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +1 -18
- package/src/resources/extensions/gsd/tools/plan-slice.ts +1 -15
- package/src/resources/extensions/gsd/visualizer-data.ts +46 -14
- package/src/resources/extensions/gsd/workspace-index.ts +49 -18
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/layout-745c6ed5fea5fb06.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-801b53eff6e83579.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-e6255954dccfcf0a.js +0 -1
- /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{drUWS0zys9uepCfCwecJv → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
resolveGsdRootFile, relGsdRootFile, resolveRuntimeFile,
|
|
17
17
|
} from "./paths.js";
|
|
18
18
|
import { resolveSkillDiscoveryMode, resolveInlineLevel, loadEffectiveGSDPreferences, resolveAllSkillReferences } from "./preferences.js";
|
|
19
|
+
import { parseRoadmap } from "./parsers-legacy.js";
|
|
19
20
|
import type { GSDState, InlineLevel } from "./types.js";
|
|
20
21
|
import type { GSDPreferences } from "./preferences.js";
|
|
21
22
|
import { getLoadedSkills, type Skill } from "@gsd/pi-coding-agent";
|
|
@@ -183,14 +184,30 @@ export async function inlineDependencySummaries(
|
|
|
183
184
|
const { isDbAvailable, getSlice } = await import("./gsd-db.js");
|
|
184
185
|
if (isDbAvailable()) {
|
|
185
186
|
const slice = getSlice(mid, sid);
|
|
186
|
-
if (
|
|
187
|
-
|
|
187
|
+
if (slice) {
|
|
188
|
+
if (slice.depends.length === 0) return "- (no dependencies)";
|
|
189
|
+
depends = slice.depends as string[];
|
|
190
|
+
}
|
|
191
|
+
// If slice not found in DB, fall through to file-based parsing
|
|
188
192
|
}
|
|
189
193
|
} catch { /* fall through */ }
|
|
190
194
|
|
|
191
|
-
// If DB didn't provide depends,
|
|
195
|
+
// If DB didn't provide depends, fall back to roadmap parsing
|
|
192
196
|
if (!depends) {
|
|
193
|
-
|
|
197
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
198
|
+
if (roadmapPath) {
|
|
199
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
200
|
+
if (roadmapContent) {
|
|
201
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
202
|
+
const slice = parsed.slices.find(s => s.id === sid);
|
|
203
|
+
if (slice && slice.depends.length > 0) {
|
|
204
|
+
depends = slice.depends;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (!depends) {
|
|
209
|
+
return "- (no dependencies)";
|
|
210
|
+
}
|
|
194
211
|
}
|
|
195
212
|
|
|
196
213
|
const sections: string[] = [];
|
|
@@ -684,29 +701,44 @@ export async function getDependencyTaskSummaryPaths(
|
|
|
684
701
|
export async function checkNeedsReassessment(
|
|
685
702
|
base: string, mid: string, state: GSDState,
|
|
686
703
|
): Promise<{ sliceId: string } | null> {
|
|
687
|
-
// DB primary path
|
|
688
|
-
let completedSliceIds: string[] = [];
|
|
689
|
-
let hasIncomplete = false;
|
|
704
|
+
// DB primary path — fall through to file-based when DB has no data for this milestone
|
|
690
705
|
try {
|
|
691
706
|
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
692
707
|
if (isDbAvailable()) {
|
|
693
708
|
const slices = getMilestoneSlices(mid);
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
709
|
+
if (slices.length > 0) {
|
|
710
|
+
const completedSliceIds = slices.filter(s => s.status === "complete").map(s => s.id);
|
|
711
|
+
const hasIncomplete = slices.some(s => s.status !== "complete");
|
|
712
|
+
if (completedSliceIds.length === 0 || !hasIncomplete) return null;
|
|
713
|
+
const lastCompleted = completedSliceIds[completedSliceIds.length - 1];
|
|
714
|
+
const assessmentFile = resolveSliceFile(base, mid, lastCompleted, "ASSESSMENT");
|
|
715
|
+
const hasAssessment = !!(assessmentFile && await loadFile(assessmentFile));
|
|
716
|
+
if (hasAssessment) return null;
|
|
717
|
+
const summaryFile = resolveSliceFile(base, mid, lastCompleted, "SUMMARY");
|
|
718
|
+
const hasSummary = !!(summaryFile && await loadFile(summaryFile));
|
|
719
|
+
if (!hasSummary) return null;
|
|
720
|
+
return { sliceId: lastCompleted };
|
|
721
|
+
}
|
|
705
722
|
}
|
|
706
723
|
} catch { /* fall through */ }
|
|
707
724
|
|
|
708
|
-
//
|
|
709
|
-
|
|
725
|
+
// File-based fallback using roadmap checkboxes
|
|
726
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
727
|
+
if (!roadmapPath) return null;
|
|
728
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
729
|
+
if (!roadmapContent) return null;
|
|
730
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
731
|
+
const fileCompletedIds = parsed.slices.filter(s => s.done).map(s => s.id);
|
|
732
|
+
const fileHasIncomplete = parsed.slices.some(s => !s.done);
|
|
733
|
+
if (fileCompletedIds.length === 0 || !fileHasIncomplete) return null;
|
|
734
|
+
const lastDone = fileCompletedIds[fileCompletedIds.length - 1];
|
|
735
|
+
const assessFile = resolveSliceFile(base, mid, lastDone, "ASSESSMENT");
|
|
736
|
+
const hasAssess = !!(assessFile && await loadFile(assessFile));
|
|
737
|
+
if (hasAssess) return null;
|
|
738
|
+
const summFile = resolveSliceFile(base, mid, lastDone, "SUMMARY");
|
|
739
|
+
const hasSumm = !!(summFile && await loadFile(summFile));
|
|
740
|
+
if (!hasSumm) return null;
|
|
741
|
+
return { sliceId: lastDone };
|
|
710
742
|
}
|
|
711
743
|
|
|
712
744
|
/**
|
|
@@ -723,34 +755,57 @@ export async function checkNeedsReassessment(
|
|
|
723
755
|
export async function checkNeedsRunUat(
|
|
724
756
|
base: string, mid: string, state: GSDState, prefs: GSDPreferences | undefined,
|
|
725
757
|
): Promise<{ sliceId: string; uatType: UatType } | null> {
|
|
726
|
-
// DB primary path
|
|
758
|
+
// DB primary path — fall through to file-based when DB has no data for this milestone
|
|
727
759
|
try {
|
|
728
760
|
const { isDbAvailable, getMilestoneSlices } = await import("./gsd-db.js");
|
|
729
761
|
if (isDbAvailable()) {
|
|
730
762
|
const slices = getMilestoneSlices(mid);
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
763
|
+
if (slices.length > 0) {
|
|
764
|
+
const completedSlices = slices.filter(s => s.status === "complete");
|
|
765
|
+
const incompleteSlices = slices.filter(s => s.status !== "complete");
|
|
766
|
+
if (completedSlices.length === 0) return null;
|
|
767
|
+
if (incompleteSlices.length === 0) return null;
|
|
768
|
+
if (!prefs?.uat_dispatch) return null;
|
|
769
|
+
const lastCompleted = completedSlices[completedSlices.length - 1];
|
|
770
|
+
const sid = lastCompleted.id;
|
|
771
|
+
const uatFile = resolveSliceFile(base, mid, sid, "UAT");
|
|
772
|
+
if (!uatFile) return null;
|
|
773
|
+
const uatContent = await loadFile(uatFile);
|
|
774
|
+
if (!uatContent) return null;
|
|
775
|
+
const uatResultFile = resolveSliceFile(base, mid, sid, "UAT-RESULT");
|
|
776
|
+
if (uatResultFile) {
|
|
777
|
+
const hasResult = !!(await loadFile(uatResultFile));
|
|
778
|
+
if (hasResult) return null;
|
|
779
|
+
}
|
|
780
|
+
const uatType = extractUatType(uatContent) ?? "artifact-driven";
|
|
781
|
+
return { sliceId: sid, uatType };
|
|
746
782
|
}
|
|
747
|
-
const uatType = extractUatType(uatContent) ?? "artifact-driven";
|
|
748
|
-
return { sliceId: sid, uatType };
|
|
749
783
|
}
|
|
750
784
|
} catch { /* fall through */ }
|
|
751
785
|
|
|
752
|
-
//
|
|
753
|
-
return null;
|
|
786
|
+
// File-based fallback using roadmap checkboxes
|
|
787
|
+
if (!prefs?.uat_dispatch) return null;
|
|
788
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
789
|
+
if (!roadmapPath) return null;
|
|
790
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
791
|
+
if (!roadmapContent) return null;
|
|
792
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
793
|
+
const completedFileSlices = parsed.slices.filter(s => s.done);
|
|
794
|
+
const incompleteFileSlices = parsed.slices.filter(s => !s.done);
|
|
795
|
+
if (completedFileSlices.length === 0 || incompleteFileSlices.length === 0) return null;
|
|
796
|
+
const lastCompletedFile = completedFileSlices[completedFileSlices.length - 1];
|
|
797
|
+
const uatSid = lastCompletedFile.id;
|
|
798
|
+
const uatFileFb = resolveSliceFile(base, mid, uatSid, "UAT");
|
|
799
|
+
if (!uatFileFb) return null;
|
|
800
|
+
const uatContentFb = await loadFile(uatFileFb);
|
|
801
|
+
if (!uatContentFb) return null;
|
|
802
|
+
const uatResultFb = resolveSliceFile(base, mid, uatSid, "UAT-RESULT");
|
|
803
|
+
if (uatResultFb) {
|
|
804
|
+
const hasResultFb = !!(await loadFile(uatResultFb));
|
|
805
|
+
if (hasResultFb) return null;
|
|
806
|
+
}
|
|
807
|
+
const uatTypeFb = extractUatType(uatContentFb) ?? "artifact-driven";
|
|
808
|
+
return { sliceId: uatSid, uatType: uatTypeFb };
|
|
754
809
|
}
|
|
755
810
|
|
|
756
811
|
// ─── Prompt Builders ──────────────────────────────────────────────────────
|
|
@@ -1207,7 +1262,13 @@ export async function buildCompleteMilestonePrompt(
|
|
|
1207
1262
|
sliceIds = getMilestoneSlices(mid).map(s => s.id);
|
|
1208
1263
|
}
|
|
1209
1264
|
} catch { /* fall through */ }
|
|
1210
|
-
//
|
|
1265
|
+
// File-based fallback: parse roadmap for slice IDs when DB has no data
|
|
1266
|
+
if (sliceIds.length === 0 && roadmapPath) {
|
|
1267
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
1268
|
+
if (roadmapContent) {
|
|
1269
|
+
sliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1211
1272
|
const seenSlices = new Set<string>();
|
|
1212
1273
|
for (const sid of sliceIds) {
|
|
1213
1274
|
if (seenSlices.has(sid)) continue;
|
|
@@ -1267,7 +1328,13 @@ export async function buildValidateMilestonePrompt(
|
|
|
1267
1328
|
valSliceIds = getMilestoneSlices(mid).map(s => s.id);
|
|
1268
1329
|
}
|
|
1269
1330
|
} catch { /* fall through */ }
|
|
1270
|
-
//
|
|
1331
|
+
// File-based fallback: parse roadmap for slice IDs when DB has no data
|
|
1332
|
+
if (valSliceIds.length === 0 && roadmapPath) {
|
|
1333
|
+
const roadmapContent = await loadFile(roadmapPath);
|
|
1334
|
+
if (roadmapContent) {
|
|
1335
|
+
valSliceIds = parseRoadmap(roadmapContent).slices.map(s => s.id);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1271
1338
|
const seenValSlices = new Set<string>();
|
|
1272
1339
|
for (const sid of valSliceIds) {
|
|
1273
1340
|
if (seenValSlices.has(sid)) continue;
|
|
@@ -551,6 +551,20 @@ export async function bootstrapAutoSession(
|
|
|
551
551
|
}
|
|
552
552
|
}
|
|
553
553
|
|
|
554
|
+
// Gate: abort bootstrap if the DB file exists but the provider is
|
|
555
|
+
// still unavailable after both open attempts above. Without this,
|
|
556
|
+
// auto-mode starts but every gsd_task_complete / gsd_slice_complete
|
|
557
|
+
// call returns "db_unavailable", triggering artifact-retry which
|
|
558
|
+
// re-dispatches the same task — producing an infinite loop (#2419).
|
|
559
|
+
if (existsSync(gsdDbPath) && !isDbAvailable()) {
|
|
560
|
+
ctx.ui.notify(
|
|
561
|
+
"SQLite database exists but failed to open. Auto-mode cannot proceed without a working database provider. " +
|
|
562
|
+
"Check for corrupt gsd.db or missing native SQLite bindings.",
|
|
563
|
+
"error",
|
|
564
|
+
);
|
|
565
|
+
return releaseLockAndReturn();
|
|
566
|
+
}
|
|
567
|
+
|
|
554
568
|
// Initialize metrics
|
|
555
569
|
initMetrics(s.basePath);
|
|
556
570
|
|
|
@@ -1006,7 +1006,14 @@ export function mergeMilestoneToMain(
|
|
|
1006
1006
|
.filter(s => s.status === "complete")
|
|
1007
1007
|
.map(s => ({ id: s.id, title: s.title }));
|
|
1008
1008
|
}
|
|
1009
|
-
//
|
|
1009
|
+
// Fallback: parse roadmap content when DB is unavailable
|
|
1010
|
+
if (completedSlices.length === 0 && roadmapContent) {
|
|
1011
|
+
const sliceRe = /- \[x\] \*\*(\w+):\s*(.+?)\*\*/gi;
|
|
1012
|
+
let m: RegExpExecArray | null;
|
|
1013
|
+
while ((m = sliceRe.exec(roadmapContent)) !== null) {
|
|
1014
|
+
completedSlices.push({ id: m[1], title: m[2] });
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1010
1017
|
|
|
1011
1018
|
// 3. chdir to original base
|
|
1012
1019
|
const previousCwd = process.cwd();
|
|
@@ -1037,8 +1044,14 @@ export function mergeMilestoneToMain(
|
|
|
1037
1044
|
|
|
1038
1045
|
// 6. Build rich commit message
|
|
1039
1046
|
const dbMilestone = getMilestone(milestoneId);
|
|
1040
|
-
|
|
1041
|
-
(dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim()
|
|
1047
|
+
let milestoneTitle =
|
|
1048
|
+
(dbMilestone?.title ?? "").replace(/^M\d+:\s*/, "").trim();
|
|
1049
|
+
// Fallback: parse title from roadmap content header (e.g. "# M020: Backend foundation")
|
|
1050
|
+
if (!milestoneTitle && roadmapContent) {
|
|
1051
|
+
const titleMatch = roadmapContent.match(new RegExp(`^#\\s+${milestoneId}:\\s*(.+)`, "m"));
|
|
1052
|
+
if (titleMatch) milestoneTitle = titleMatch[1].trim();
|
|
1053
|
+
}
|
|
1054
|
+
milestoneTitle = milestoneTitle || milestoneId;
|
|
1042
1055
|
const subject = `feat(${milestoneId}): ${milestoneTitle}`;
|
|
1043
1056
|
let body = "";
|
|
1044
1057
|
if (completedSlices.length > 0) {
|
|
@@ -188,6 +188,14 @@ export async function handleWorkflowCommand(trimmed: string, ctx: ExtensionComma
|
|
|
188
188
|
return true;
|
|
189
189
|
}
|
|
190
190
|
if (trimmed === "quick" || trimmed.startsWith("quick ")) {
|
|
191
|
+
if (isAutoActive()) {
|
|
192
|
+
ctx.ui.notify(
|
|
193
|
+
"/gsd quick cannot run while auto-mode is active.\n" +
|
|
194
|
+
"Stop auto-mode first with /gsd stop, then run /gsd quick.",
|
|
195
|
+
"error",
|
|
196
|
+
);
|
|
197
|
+
return true;
|
|
198
|
+
}
|
|
191
199
|
await handleQuick(trimmed.replace(/^quick\s*/, "").trim(), ctx, pi);
|
|
192
200
|
return true;
|
|
193
201
|
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import { resolveMilestoneFile } from "./paths.js";
|
|
4
4
|
import { findMilestoneIds } from "./guided-flow.js";
|
|
5
5
|
import { isDbAvailable, getMilestoneSlices } from "./gsd-db.js";
|
|
6
|
+
import { parseRoadmap } from "./parsers-legacy.js";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
6
8
|
|
|
7
9
|
const SLICE_DISPATCH_TYPES = new Set([
|
|
8
10
|
"research-slice",
|
|
@@ -34,18 +36,34 @@ export function getPriorSliceCompletionBlocker(
|
|
|
34
36
|
if (resolveMilestoneFile(base, mid, "PARKED")) continue;
|
|
35
37
|
if (resolveMilestoneFile(base, mid, "SUMMARY")) continue;
|
|
36
38
|
|
|
37
|
-
// Normalised slice list from DB
|
|
39
|
+
// Normalised slice list from DB or file fallback
|
|
38
40
|
type NormSlice = { id: string; done: boolean; depends: string[] };
|
|
41
|
+
let slices: NormSlice[] | null = null;
|
|
39
42
|
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
if (isDbAvailable()) {
|
|
44
|
+
const rows = getMilestoneSlices(mid);
|
|
45
|
+
if (rows.length > 0) {
|
|
46
|
+
slices = rows.map((r) => ({
|
|
47
|
+
id: r.id,
|
|
48
|
+
done: r.status === "complete",
|
|
49
|
+
depends: r.depends ?? [],
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (!slices) {
|
|
54
|
+
// File-based fallback: parse roadmap checkboxes
|
|
55
|
+
const roadmapPath = resolveMilestoneFile(base, mid, "ROADMAP");
|
|
56
|
+
if (!roadmapPath) continue;
|
|
57
|
+
let roadmapContent: string;
|
|
58
|
+
try { roadmapContent = readFileSync(roadmapPath, "utf-8"); } catch { continue; }
|
|
59
|
+
const parsed = parseRoadmap(roadmapContent);
|
|
60
|
+
if (parsed.slices.length === 0) continue;
|
|
61
|
+
slices = parsed.slices.map((s) => ({
|
|
62
|
+
id: s.id,
|
|
63
|
+
done: s.done,
|
|
64
|
+
depends: s.depends ?? [],
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
49
67
|
|
|
50
68
|
if (mid !== targetMid) {
|
|
51
69
|
const incomplete = slices.find((slice) => !slice.done);
|
|
@@ -933,12 +933,14 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
|
|
|
933
933
|
|
|
934
934
|
for (const entry of staleEntries) {
|
|
935
935
|
if (repairedPaths.has(entry.path)) continue;
|
|
936
|
+
// Normalize path separators for cross-platform regex matching
|
|
937
|
+
const normPath = entry.path.replace(/\\/g, "/");
|
|
936
938
|
|
|
937
939
|
try {
|
|
938
940
|
// Determine repair action from the reason
|
|
939
941
|
if (entry.reason.includes("in roadmap")) {
|
|
940
942
|
// Roadmap checkbox mismatch — extract milestone ID from path
|
|
941
|
-
const milestoneMatch =
|
|
943
|
+
const milestoneMatch = normPath.match(/milestones\/([^/]+)\//);
|
|
942
944
|
if (milestoneMatch) {
|
|
943
945
|
const ok = await renderRoadmapCheckboxes(basePath, milestoneMatch[1]);
|
|
944
946
|
if (ok) {
|
|
@@ -948,7 +950,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
|
|
|
948
950
|
}
|
|
949
951
|
} else if (entry.reason.includes("in plan")) {
|
|
950
952
|
// Plan checkbox mismatch — extract milestone + slice IDs from path
|
|
951
|
-
const pathMatch =
|
|
953
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
|
|
952
954
|
if (pathMatch) {
|
|
953
955
|
const ok = await renderPlanCheckboxes(basePath, pathMatch[1], pathMatch[2]);
|
|
954
956
|
if (ok) {
|
|
@@ -958,7 +960,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
|
|
|
958
960
|
}
|
|
959
961
|
} else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^T\d+/)) {
|
|
960
962
|
// Missing task summary — extract IDs from path
|
|
961
|
-
const pathMatch =
|
|
963
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\/tasks\//);
|
|
962
964
|
const taskMatch = entry.reason.match(/^(T\d+)/);
|
|
963
965
|
if (pathMatch && taskMatch) {
|
|
964
966
|
const ok = await renderTaskSummary(basePath, pathMatch[1], pathMatch[2], taskMatch[1]);
|
|
@@ -969,7 +971,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
|
|
|
969
971
|
}
|
|
970
972
|
} else if (entry.reason.includes("SUMMARY.md missing") && entry.reason.match(/^S\d+/)) {
|
|
971
973
|
// Missing slice summary — extract IDs from path
|
|
972
|
-
const pathMatch =
|
|
974
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
|
|
973
975
|
if (pathMatch) {
|
|
974
976
|
const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
|
|
975
977
|
if (ok) {
|
|
@@ -979,7 +981,7 @@ export async function repairStaleRenders(basePath: string): Promise<number> {
|
|
|
979
981
|
}
|
|
980
982
|
} else if (entry.reason.includes("UAT.md missing")) {
|
|
981
983
|
// Missing slice UAT — renderSliceSummary handles both SUMMARY + UAT
|
|
982
|
-
const pathMatch =
|
|
984
|
+
const pathMatch = normPath.match(/milestones\/([^/]+)\/slices\/([^/]+)\//);
|
|
983
985
|
if (pathMatch) {
|
|
984
986
|
const ok = await renderSliceSummary(basePath, pathMatch[1], pathMatch[2]);
|
|
985
987
|
if (ok) {
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import type { TaskIO, DerivedTaskNode, ReactiveExecutionState } from "./types.js";
|
|
13
13
|
import { loadFile, parseTaskPlanIO } from "./files.js";
|
|
14
14
|
import { isDbAvailable, getSliceTasks } from "./gsd-db.js";
|
|
15
|
+
import { parsePlan } from "./parsers-legacy.js";
|
|
15
16
|
import { resolveTasksDir, resolveTaskFiles } from "./paths.js";
|
|
16
17
|
import { join } from "node:path";
|
|
17
18
|
import { loadJsonFileOrNull, saveJsonFile } from "./json-persistence.js";
|
|
@@ -205,8 +206,17 @@ export async function loadSliceTaskIO(
|
|
|
205
206
|
} catch { /* fall through */ }
|
|
206
207
|
|
|
207
208
|
if (!taskEntries) {
|
|
208
|
-
//
|
|
209
|
-
|
|
209
|
+
// File-based fallback: parse slice plan for task entries
|
|
210
|
+
const parsed = parsePlan(planContent);
|
|
211
|
+
if (parsed.tasks.length > 0) {
|
|
212
|
+
taskEntries = parsed.tasks.map(t => ({
|
|
213
|
+
id: t.id,
|
|
214
|
+
title: t.title,
|
|
215
|
+
done: t.done,
|
|
216
|
+
}));
|
|
217
|
+
} else {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
210
220
|
}
|
|
211
221
|
|
|
212
222
|
const tDir = resolveTasksDir(basePath, mid, sid);
|
|
@@ -283,7 +283,8 @@ export function computeStaleAvoidList(
|
|
|
283
283
|
staleDays?: number,
|
|
284
284
|
): string[] {
|
|
285
285
|
const ledger = loadLedgerFromDisk(basePath);
|
|
286
|
-
|
|
286
|
+
if (!ledger) return [];
|
|
287
|
+
const units = ledger.units.filter(u => u.skills && u.skills.length > 0);
|
|
287
288
|
const stale = detectStaleSkills(units, staleDays ?? DEFAULT_STALE_DAYS);
|
|
288
289
|
const avoidSet = new Set(currentAvoidList);
|
|
289
290
|
|
|
@@ -130,119 +130,119 @@ test("auto-loop 'all milestones complete' path merges before stopping (#962)", (
|
|
|
130
130
|
|
|
131
131
|
// ─── Integration: single milestone completes → merged to main ────────────────
|
|
132
132
|
|
|
133
|
-
test("single milestone worktree is merged to main when all complete (#962)", () => {
|
|
133
|
+
test("single milestone worktree is merged to main when all complete (#962)", (t) => {
|
|
134
134
|
const savedCwd = process.cwd();
|
|
135
135
|
let tempDir = "";
|
|
136
136
|
|
|
137
|
-
|
|
138
|
-
tempDir = createTempRepo();
|
|
139
|
-
|
|
140
|
-
// Set up a single milestone
|
|
141
|
-
createMilestoneArtifacts(tempDir, "M001");
|
|
142
|
-
run("git add .", tempDir);
|
|
143
|
-
run('git commit -m "add milestone"', tempDir);
|
|
144
|
-
|
|
145
|
-
// Create worktree and simulate work
|
|
146
|
-
const wt = createAutoWorktree(tempDir, "M001");
|
|
147
|
-
assert.ok(isInAutoWorktree(tempDir), "should be in auto-worktree");
|
|
148
|
-
|
|
149
|
-
writeFileSync(join(wt, "feature.ts"), "export const feature = true;\n");
|
|
150
|
-
run("git add .", wt);
|
|
151
|
-
run('git commit -m "feat(M001): add feature"', wt);
|
|
152
|
-
|
|
153
|
-
// Simulate the fix: merge before stopping (what the "all complete" path now does)
|
|
154
|
-
const roadmapPath = join(
|
|
155
|
-
tempDir,
|
|
156
|
-
".gsd",
|
|
157
|
-
"milestones",
|
|
158
|
-
"M001",
|
|
159
|
-
"M001-ROADMAP.md",
|
|
160
|
-
);
|
|
161
|
-
const roadmapContent = readFileSync(roadmapPath, "utf-8");
|
|
162
|
-
const mergeResult = mergeMilestoneToMain(tempDir, "M001", roadmapContent);
|
|
163
|
-
|
|
164
|
-
// Verify work is on main
|
|
165
|
-
assert.ok(
|
|
166
|
-
existsSync(join(tempDir, "feature.ts")),
|
|
167
|
-
"feature.ts should be on main after merge",
|
|
168
|
-
);
|
|
169
|
-
assert.equal(process.cwd(), tempDir, "cwd restored to project root");
|
|
170
|
-
assert.ok(!isInAutoWorktree(tempDir), "no longer in auto-worktree");
|
|
171
|
-
assert.equal(getAutoWorktreeOriginalBase(), null, "originalBase cleared");
|
|
172
|
-
|
|
173
|
-
// Verify milestone branch was cleaned up
|
|
174
|
-
const branches = run("git branch", tempDir);
|
|
175
|
-
assert.ok(
|
|
176
|
-
!branches.includes("milestone/M001"),
|
|
177
|
-
"milestone branch should be deleted",
|
|
178
|
-
);
|
|
179
|
-
|
|
180
|
-
// Verify squash commit on main
|
|
181
|
-
const log = run("git log --oneline -3", tempDir);
|
|
182
|
-
assert.ok(
|
|
183
|
-
log.includes("M001"),
|
|
184
|
-
"squash commit on main should reference M001",
|
|
185
|
-
);
|
|
186
|
-
|
|
187
|
-
assert.ok(mergeResult.commitMessage.length > 0, "commit message returned");
|
|
188
|
-
} finally {
|
|
137
|
+
t.after(() => {
|
|
189
138
|
process.chdir(savedCwd);
|
|
190
139
|
if (tempDir && existsSync(tempDir)) {
|
|
191
|
-
|
|
140
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
192
141
|
}
|
|
193
|
-
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
tempDir = createTempRepo();
|
|
145
|
+
|
|
146
|
+
// Set up a single milestone
|
|
147
|
+
createMilestoneArtifacts(tempDir, "M001");
|
|
148
|
+
run("git add .", tempDir);
|
|
149
|
+
run('git commit -m "add milestone"', tempDir);
|
|
150
|
+
|
|
151
|
+
// Create worktree and simulate work
|
|
152
|
+
const wt = createAutoWorktree(tempDir, "M001");
|
|
153
|
+
assert.ok(isInAutoWorktree(tempDir), "should be in auto-worktree");
|
|
154
|
+
|
|
155
|
+
writeFileSync(join(wt, "feature.ts"), "export const feature = true;\n");
|
|
156
|
+
run("git add .", wt);
|
|
157
|
+
run('git commit -m "feat(M001): add feature"', wt);
|
|
158
|
+
|
|
159
|
+
// Simulate the fix: merge before stopping (what the "all complete" path now does)
|
|
160
|
+
const roadmapPath = join(
|
|
161
|
+
tempDir,
|
|
162
|
+
".gsd",
|
|
163
|
+
"milestones",
|
|
164
|
+
"M001",
|
|
165
|
+
"M001-ROADMAP.md",
|
|
166
|
+
);
|
|
167
|
+
const roadmapContent = readFileSync(roadmapPath, "utf-8");
|
|
168
|
+
const mergeResult = mergeMilestoneToMain(tempDir, "M001", roadmapContent);
|
|
169
|
+
|
|
170
|
+
// Verify work is on main
|
|
171
|
+
assert.ok(
|
|
172
|
+
existsSync(join(tempDir, "feature.ts")),
|
|
173
|
+
"feature.ts should be on main after merge",
|
|
174
|
+
);
|
|
175
|
+
assert.equal(process.cwd(), tempDir, "cwd restored to project root");
|
|
176
|
+
assert.ok(!isInAutoWorktree(tempDir), "no longer in auto-worktree");
|
|
177
|
+
assert.equal(getAutoWorktreeOriginalBase(), null, "originalBase cleared");
|
|
178
|
+
|
|
179
|
+
// Verify milestone branch was cleaned up
|
|
180
|
+
const branches = run("git branch", tempDir);
|
|
181
|
+
assert.ok(
|
|
182
|
+
!branches.includes("milestone/M001"),
|
|
183
|
+
"milestone branch should be deleted",
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
// Verify squash commit on main
|
|
187
|
+
const log = run("git log --oneline -3", tempDir);
|
|
188
|
+
assert.ok(
|
|
189
|
+
log.includes("M001"),
|
|
190
|
+
"squash commit on main should reference M001",
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
assert.ok(mergeResult.commitMessage.length > 0, "commit message returned");
|
|
194
194
|
});
|
|
195
195
|
|
|
196
196
|
// ─── Integration: last of multiple milestones completes → merged ─────────────
|
|
197
197
|
|
|
198
|
-
test("last milestone worktree is merged when it's the final one (#962)", () => {
|
|
198
|
+
test("last milestone worktree is merged when it's the final one (#962)", (t) => {
|
|
199
199
|
const savedCwd = process.cwd();
|
|
200
200
|
let tempDir = "";
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
tempDir = createTempRepo();
|
|
204
|
-
|
|
205
|
-
// Set up two milestones
|
|
206
|
-
createMilestoneArtifacts(tempDir, "M001");
|
|
207
|
-
createMilestoneArtifacts(tempDir, "M002");
|
|
208
|
-
run("git add .", tempDir);
|
|
209
|
-
run('git commit -m "add milestones"', tempDir);
|
|
210
|
-
|
|
211
|
-
// Complete M001 first (merge it)
|
|
212
|
-
const wt1 = createAutoWorktree(tempDir, "M001");
|
|
213
|
-
writeFileSync(join(wt1, "m001-work.ts"), "export const m001 = true;\n");
|
|
214
|
-
run("git add .", wt1);
|
|
215
|
-
run('git commit -m "feat(M001): m001 work"', wt1);
|
|
216
|
-
const roadmap1 = readFileSync(
|
|
217
|
-
join(tempDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
218
|
-
"utf-8",
|
|
219
|
-
);
|
|
220
|
-
mergeMilestoneToMain(tempDir, "M001", roadmap1);
|
|
221
|
-
|
|
222
|
-
// Now complete M002 (the LAST milestone — this is the #962 scenario)
|
|
223
|
-
const wt2 = createAutoWorktree(tempDir, "M002");
|
|
224
|
-
writeFileSync(join(wt2, "m002-work.ts"), "export const m002 = true;\n");
|
|
225
|
-
run("git add .", wt2);
|
|
226
|
-
run('git commit -m "feat(M002): m002 work"', wt2);
|
|
227
|
-
const roadmap2 = readFileSync(
|
|
228
|
-
join(tempDir, ".gsd", "milestones", "M002", "M002-ROADMAP.md"),
|
|
229
|
-
"utf-8",
|
|
230
|
-
);
|
|
231
|
-
mergeMilestoneToMain(tempDir, "M002", roadmap2);
|
|
232
|
-
|
|
233
|
-
// Both features should now be on main
|
|
234
|
-
assert.ok(existsSync(join(tempDir, "m001-work.ts")), "M001 work on main");
|
|
235
|
-
assert.ok(existsSync(join(tempDir, "m002-work.ts")), "M002 work on main");
|
|
236
|
-
assert.ok(!isInAutoWorktree(tempDir), "not in worktree after final merge");
|
|
237
|
-
|
|
238
|
-
// Both milestone branches should be cleaned up
|
|
239
|
-
const branches = run("git branch", tempDir);
|
|
240
|
-
assert.ok(!branches.includes("milestone/M001"), "M001 branch deleted");
|
|
241
|
-
assert.ok(!branches.includes("milestone/M002"), "M002 branch deleted");
|
|
242
|
-
} finally {
|
|
202
|
+
t.after(() => {
|
|
243
203
|
process.chdir(savedCwd);
|
|
244
204
|
if (tempDir && existsSync(tempDir)) {
|
|
245
|
-
|
|
205
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
246
206
|
}
|
|
247
|
-
}
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
tempDir = createTempRepo();
|
|
210
|
+
|
|
211
|
+
// Set up two milestones
|
|
212
|
+
createMilestoneArtifacts(tempDir, "M001");
|
|
213
|
+
createMilestoneArtifacts(tempDir, "M002");
|
|
214
|
+
run("git add .", tempDir);
|
|
215
|
+
run('git commit -m "add milestones"', tempDir);
|
|
216
|
+
|
|
217
|
+
// Complete M001 first (merge it)
|
|
218
|
+
const wt1 = createAutoWorktree(tempDir, "M001");
|
|
219
|
+
writeFileSync(join(wt1, "m001-work.ts"), "export const m001 = true;\n");
|
|
220
|
+
run("git add .", wt1);
|
|
221
|
+
run('git commit -m "feat(M001): m001 work"', wt1);
|
|
222
|
+
const roadmap1 = readFileSync(
|
|
223
|
+
join(tempDir, ".gsd", "milestones", "M001", "M001-ROADMAP.md"),
|
|
224
|
+
"utf-8",
|
|
225
|
+
);
|
|
226
|
+
mergeMilestoneToMain(tempDir, "M001", roadmap1);
|
|
227
|
+
|
|
228
|
+
// Now complete M002 (the LAST milestone — this is the #962 scenario)
|
|
229
|
+
const wt2 = createAutoWorktree(tempDir, "M002");
|
|
230
|
+
writeFileSync(join(wt2, "m002-work.ts"), "export const m002 = true;\n");
|
|
231
|
+
run("git add .", wt2);
|
|
232
|
+
run('git commit -m "feat(M002): m002 work"', wt2);
|
|
233
|
+
const roadmap2 = readFileSync(
|
|
234
|
+
join(tempDir, ".gsd", "milestones", "M002", "M002-ROADMAP.md"),
|
|
235
|
+
"utf-8",
|
|
236
|
+
);
|
|
237
|
+
mergeMilestoneToMain(tempDir, "M002", roadmap2);
|
|
238
|
+
|
|
239
|
+
// Both features should now be on main
|
|
240
|
+
assert.ok(existsSync(join(tempDir, "m001-work.ts")), "M001 work on main");
|
|
241
|
+
assert.ok(existsSync(join(tempDir, "m002-work.ts")), "M002 work on main");
|
|
242
|
+
assert.ok(!isInAutoWorktree(tempDir), "not in worktree after final merge");
|
|
243
|
+
|
|
244
|
+
// Both milestone branches should be cleaned up
|
|
245
|
+
const branches = run("git branch", tempDir);
|
|
246
|
+
assert.ok(!branches.includes("milestone/M001"), "M001 branch deleted");
|
|
247
|
+
assert.ok(!branches.includes("milestone/M002"), "M002 branch deleted");
|
|
248
248
|
});
|