gsd-pi 2.43.0 → 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/bg-shell/overlay.js +3 -0
- package/dist/resources/extensions/github-sync/sync.js +2 -1
- package/dist/resources/extensions/gsd/auto/loop.js +0 -2
- package/dist/resources/extensions/gsd/auto/phases.js +7 -12
- package/dist/resources/extensions/gsd/auto-dashboard.js +19 -18
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +34 -19
- package/dist/resources/extensions/gsd/auto-dispatch.js +36 -21
- package/dist/resources/extensions/gsd/auto-post-unit.js +128 -14
- package/dist/resources/extensions/gsd/auto-prompts.js +202 -92
- package/dist/resources/extensions/gsd/auto-recovery.js +83 -135
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/auto-supervisor.js +14 -0
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +4 -7
- package/dist/resources/extensions/gsd/auto-verification.js +5 -10
- package/dist/resources/extensions/gsd/auto-worktree.js +123 -30
- package/dist/resources/extensions/gsd/auto.js +1 -4
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +611 -0
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +28 -3
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +3 -1
- package/dist/resources/extensions/gsd/commands/handlers/ops.js +15 -1
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/resources/extensions/gsd/commands-handlers.js +1 -1
- package/dist/resources/extensions/gsd/commands-maintenance.js +78 -3
- package/dist/resources/extensions/gsd/dashboard-overlay.js +32 -31
- package/dist/resources/extensions/gsd/db-writer.js +95 -4
- package/dist/resources/extensions/gsd/dispatch-guard.js +35 -30
- package/dist/resources/extensions/gsd/doctor-checks.js +28 -11
- package/dist/resources/extensions/gsd/doctor-environment.js +28 -0
- package/dist/resources/extensions/gsd/doctor-types.js +0 -15
- package/dist/resources/extensions/gsd/doctor.js +46 -282
- package/dist/resources/extensions/gsd/file-watcher.js +5 -1
- package/dist/resources/extensions/gsd/files.js +14 -198
- package/dist/resources/extensions/gsd/git-service.js +4 -0
- package/dist/resources/extensions/gsd/gitignore.js +4 -0
- package/dist/resources/extensions/gsd/gsd-db.js +819 -197
- package/dist/resources/extensions/gsd/guided-flow.js +18 -8
- package/dist/resources/extensions/gsd/markdown-renderer.js +862 -0
- package/dist/resources/extensions/gsd/md-importer.js +182 -4
- package/dist/resources/extensions/gsd/native-git-bridge.js +10 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +14 -19
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +38 -0
- package/dist/resources/extensions/gsd/parsers-legacy.js +239 -0
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +9 -0
- package/dist/resources/extensions/gsd/preferences.js +1 -0
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +22 -9
- package/dist/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +15 -5
- package/dist/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +4 -7
- package/dist/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
- package/dist/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +6 -6
- package/dist/resources/extensions/gsd/reactive-graph.js +33 -3
- package/dist/resources/extensions/gsd/skill-health.js +3 -1
- package/dist/resources/extensions/gsd/state.js +484 -30
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +128 -0
- package/dist/resources/extensions/gsd/tools/complete-slice.js +244 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +204 -0
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +205 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +155 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +94 -0
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +152 -0
- package/dist/resources/extensions/gsd/tools/replan-slice.js +146 -0
- package/dist/resources/extensions/gsd/triage-resolution.js +17 -1
- package/dist/resources/extensions/gsd/undo.js +197 -3
- package/dist/resources/extensions/gsd/visualizer-data.js +53 -16
- package/dist/resources/extensions/gsd/workspace-index.js +63 -39
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -17
- package/dist/web/standalone/.next/build-manifest.json +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/required-server-files.json +4 -4
- package/dist/web/standalone/.next/routes-manifest.json +6 -0
- 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 +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- 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 +4 -4
- 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 +2 -2
- 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 -0
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js.nft.json +1 -0
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -0
- 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 +5 -5
- 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 +5 -5
- 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 +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- 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 -17
- package/dist/web/standalone/.next/server/chunks/229.js +3 -3
- package/dist/web/standalone/.next/server/chunks/471.js +3 -3
- package/dist/web/standalone/.next/server/functions-config-manifest.json +1 -0
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-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/alS4hoANx0TK4UVZY27da/_buildManifest.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{4024.c195dc1fdd2adbea.js → 4024.0de81b543b28b9fe.js} +2 -2
- package/dist/web/standalone/.next/static/chunks/app/_global-error/{page-d07a2c023f1aef1e.js → page-d83ba70a25a85472.js} +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/api/boot/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/input/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/resize/{route-d07a2c023f1aef1e.js → route-d83ba70a25a85472.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/switch-root/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d83ba70a25a85472.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/app-error-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/not-found-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d83ba70a25a85472.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-fa307370fcf9fb2c.js → webpack-9014b5adb127a98a.js} +1 -1
- package/dist/web/standalone/.next/static/css/8a727f372cf53002.css +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-ai/dist/models.custom.d.ts +173 -0
- package/packages/pi-ai/dist/models.custom.d.ts.map +1 -0
- package/packages/pi-ai/dist/models.custom.js +170 -0
- package/packages/pi-ai/dist/models.custom.js.map +1 -0
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.js +16 -1
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/models.test.d.ts +2 -0
- package/packages/pi-ai/dist/models.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/models.test.js +67 -0
- package/packages/pi-ai/dist/models.test.js.map +1 -0
- package/packages/pi-ai/src/models.custom.ts +172 -0
- package/packages/pi-ai/src/models.test.ts +85 -0
- package/packages/pi-ai/src/models.ts +17 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +10 -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 +21 -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 +6 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +80 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.test.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/lsp/client.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/lsp/client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/client.js +69 -21
- package/packages/pi-coding-agent/dist/core/lsp/client.js.map +1 -1
- 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/modes/interactive/components/footer.d.ts +6 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js +21 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/footer.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js +8 -15
- package/packages/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/print-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/print-mode.js +45 -34
- package/packages/pi-coding-agent/dist/modes/print-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js +7 -2
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-client.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.js +2 -1
- package/packages/pi-coding-agent/dist/modes/rpc/rpc-mode.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 +26 -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.test.ts +96 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +89 -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/lsp/client.ts +83 -21
- 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/modes/interactive/components/footer.ts +20 -0
- package/packages/pi-coding-agent/src/modes/interactive/theme/theme.ts +9 -16
- package/packages/pi-coding-agent/src/modes/print-mode.ts +42 -32
- package/packages/pi-coding-agent/src/modes/rpc/rpc-client.ts +8 -2
- package/packages/pi-coding-agent/src/modes/rpc/rpc-mode.ts +2 -1
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/pkg/dist/modes/interactive/theme/theme.d.ts +1 -1
- package/pkg/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/pkg/dist/modes/interactive/theme/theme.js +8 -15
- package/pkg/dist/modes/interactive/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/bg-shell/overlay.ts +4 -0
- package/src/resources/extensions/github-sync/sync.ts +2 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +0 -8
- package/src/resources/extensions/gsd/auto/loop.ts +0 -2
- package/src/resources/extensions/gsd/auto/phases.ts +7 -20
- package/src/resources/extensions/gsd/auto/types.ts +0 -1
- package/src/resources/extensions/gsd/auto-dashboard.ts +20 -16
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +34 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +38 -21
- package/src/resources/extensions/gsd/auto-post-unit.ts +150 -15
- package/src/resources/extensions/gsd/auto-prompts.ts +186 -103
- package/src/resources/extensions/gsd/auto-recovery.ts +77 -142
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/auto-supervisor.ts +14 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +6 -7
- package/src/resources/extensions/gsd/auto-verification.ts +4 -9
- package/src/resources/extensions/gsd/auto-worktree.ts +126 -30
- package/src/resources/extensions/gsd/auto.ts +0 -9
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +675 -4
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +31 -3
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +3 -1
- package/src/resources/extensions/gsd/commands/handlers/ops.ts +15 -1
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/commands-handlers.ts +1 -1
- package/src/resources/extensions/gsd/commands-maintenance.ts +86 -3
- package/src/resources/extensions/gsd/dashboard-overlay.ts +17 -13
- package/src/resources/extensions/gsd/db-writer.ts +105 -4
- package/src/resources/extensions/gsd/dispatch-guard.ts +32 -30
- package/src/resources/extensions/gsd/doctor-checks.ts +25 -11
- package/src/resources/extensions/gsd/doctor-environment.ts +31 -0
- package/src/resources/extensions/gsd/doctor-types.ts +0 -23
- package/src/resources/extensions/gsd/doctor.ts +45 -295
- package/src/resources/extensions/gsd/file-watcher.ts +4 -1
- package/src/resources/extensions/gsd/files.ts +16 -220
- package/src/resources/extensions/gsd/git-service.ts +4 -0
- package/src/resources/extensions/gsd/gitignore.ts +4 -0
- package/src/resources/extensions/gsd/gsd-db.ts +1157 -370
- package/src/resources/extensions/gsd/guided-flow.ts +20 -8
- package/src/resources/extensions/gsd/markdown-renderer.ts +1098 -0
- package/src/resources/extensions/gsd/md-importer.ts +211 -2
- package/src/resources/extensions/gsd/native-git-bridge.ts +12 -1
- package/src/resources/extensions/gsd/parallel-eligibility.ts +14 -18
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +43 -0
- package/src/resources/extensions/gsd/parsers-legacy.ts +271 -0
- package/src/resources/extensions/gsd/preferences-types.ts +3 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +9 -0
- package/src/resources/extensions/gsd/preferences.ts +1 -0
- package/src/resources/extensions/gsd/prompts/complete-slice.md +22 -9
- package/src/resources/extensions/gsd/prompts/discuss.md +2 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +15 -5
- package/src/resources/extensions/gsd/prompts/guided-complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-execute-task.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-plan-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-milestone.md +6 -10
- package/src/resources/extensions/gsd/prompts/plan-slice.md +4 -7
- package/src/resources/extensions/gsd/prompts/reactive-execute.md +3 -3
- package/src/resources/extensions/gsd/prompts/reassess-roadmap.md +6 -7
- package/src/resources/extensions/gsd/prompts/replan-slice.md +6 -6
- package/src/resources/extensions/gsd/reactive-graph.ts +33 -3
- package/src/resources/extensions/gsd/skill-health.ts +2 -1
- package/src/resources/extensions/gsd/state.ts +547 -29
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/atomic-task-closeout.test.ts +8 -120
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +20 -11
- 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 +600 -513
- 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 +121 -0
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +540 -668
- 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 +39 -60
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +375 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +387 -0
- 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/custom-engine-loop-integration.test.ts +0 -2
- 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 +512 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +644 -84
- 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 +192 -161
- 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 +30 -90
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +57 -80
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +55 -153
- 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 +53 -97
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +109 -149
- 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 +278 -0
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +232 -0
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +291 -390
- 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 +440 -0
- 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 -270
- 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 +643 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +0 -3
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +1161 -0
- 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 +81 -94
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +429 -0
- 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 +89 -97
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +127 -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 +548 -612
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +176 -113
- package/src/resources/extensions/gsd/tests/plan-slice-prompt.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +179 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/planning-crossval.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +139 -0
- 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-handler.test.ts +325 -0
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/replan-handler.test.ts +410 -0
- 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/roadmap-slices.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/rogue-file-detection.test.ts +296 -0
- 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/schema-v9-sequence.test.ts +176 -0
- 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 +209 -0
- 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-cost-display.test.ts +118 -0
- 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 +19 -13
- package/src/resources/extensions/gsd/tests/undo.test.ts +321 -1
- 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/validate-milestone.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +0 -142
- 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-dispatch.test.ts +12 -5
- 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/complete-milestone.ts +176 -0
- package/src/resources/extensions/gsd/tools/complete-slice.ts +300 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +245 -0
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +249 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +194 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +116 -0
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +203 -0
- package/src/resources/extensions/gsd/tools/replan-slice.ts +192 -0
- package/src/resources/extensions/gsd/triage-resolution.ts +20 -1
- package/src/resources/extensions/gsd/types.ts +50 -0
- package/src/resources/extensions/gsd/undo.ts +247 -3
- package/src/resources/extensions/gsd/visualizer-data.ts +54 -17
- package/src/resources/extensions/gsd/workspace-index.ts +64 -46
- package/dist/resources/extensions/gsd/auto-observability.js +0 -56
- package/dist/resources/extensions/gsd/observability-validator.js +0 -422
- package/dist/resources/extensions/gsd/roadmap-mutations.js +0 -110
- package/dist/web/standalone/.next/static/VvclDCW6TAWjEyLU-EYL1/_buildManifest.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-e07acdb7dd069836.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/bridge-terminal/stream/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/browse-directories/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/captures/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/cleanup/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/dev-mode/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/doctor/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/export-data/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/files/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/forensics/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/git/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/history/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/hooks/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/inspect/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/knowledge/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/live-state/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/onboarding/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/preferences/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/projects/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/recovery/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/remote-questions/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/browser/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/command/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/events/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/session/manage/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/settings-data/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/shutdown/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/skill-health/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/steer/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/input/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/resize/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/sessions/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/stream/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/terminal/upload/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/undo/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/update/route-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/api/visualizer/route-d07a2c023f1aef1e.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/app-error-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/forbidden-d07a2c023f1aef1e.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/chunks/next/dist/client/components/builtin/not-found-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/unauthorized-d07a2c023f1aef1e.js +0 -1
- package/dist/web/standalone/.next/static/css/123c0bb039697968.css +0 -1
- package/src/resources/extensions/gsd/auto-observability.ts +0 -74
- package/src/resources/extensions/gsd/observability-validator.ts +0 -456
- package/src/resources/extensions/gsd/roadmap-mutations.ts +0 -134
- package/src/resources/extensions/gsd/tests/doctor-task-done-missing-summary-slice-loop.test.ts +0 -174
- package/src/resources/extensions/gsd/tests/plan-quality-validator.test.ts +0 -474
- /package/dist/web/standalone/.next/static/{VvclDCW6TAWjEyLU-EYL1 → alS4hoANx0TK4UVZY27da}/_ssgManifest.js +0 -0
|
@@ -4,8 +4,14 @@
|
|
|
4
4
|
* Covers: squash-merge topology (one commit on main), rich commit message with
|
|
5
5
|
* slice titles, worktree cleanup, nothing-to-commit edge case, auto-push with
|
|
6
6
|
* bare remote. All tests use real git operations in temp repos.
|
|
7
|
+
*
|
|
8
|
+
* Note: execSync is used intentionally in these tests for git operations with
|
|
9
|
+
* controlled, hardcoded inputs (no user input). This is safe and necessary for
|
|
10
|
+
* testing real git behavior.
|
|
7
11
|
*/
|
|
8
12
|
|
|
13
|
+
import { describe, test, afterEach } from "node:test";
|
|
14
|
+
import assert from "node:assert/strict";
|
|
9
15
|
import { mkdtempSync, mkdirSync, writeFileSync, rmSync, existsSync, realpathSync, readFileSync } from "node:fs";
|
|
10
16
|
import { join } from "node:path";
|
|
11
17
|
import { tmpdir } from "node:os";
|
|
@@ -19,11 +25,8 @@ import {
|
|
|
19
25
|
import { getSliceBranchName } from "../worktree.ts";
|
|
20
26
|
import { nativeMergeSquash } from "../native-git-bridge.ts";
|
|
21
27
|
|
|
22
|
-
import { createTestContext } from "./test-helpers.ts";
|
|
23
|
-
|
|
24
|
-
const { assertEq, assertTrue, assertMatch, report } = createTestContext();
|
|
25
|
-
|
|
26
28
|
function run(cmd: string, cwd: string): string {
|
|
29
|
+
// Safe: all inputs are hardcoded test strings, not user input
|
|
27
30
|
return execSync(cmd, { cwd, stdio: ["ignore", "pipe", "pipe"], encoding: "utf-8" }).trim();
|
|
28
31
|
}
|
|
29
32
|
|
|
@@ -56,7 +59,6 @@ function addSliceToMilestone(
|
|
|
56
59
|
sliceTitle: string,
|
|
57
60
|
commits: Array<{ file: string; content: string; message: string }>,
|
|
58
61
|
): void {
|
|
59
|
-
// Detect worktree name for branch naming
|
|
60
62
|
const normalizedPath = wtPath.replaceAll("\\", "/");
|
|
61
63
|
const marker = "/.gsd/worktrees/";
|
|
62
64
|
const idx = normalizedPath.indexOf(marker);
|
|
@@ -72,11 +74,10 @@ function addSliceToMilestone(
|
|
|
72
74
|
}
|
|
73
75
|
run(`git checkout milestone/${milestoneId}`, wtPath);
|
|
74
76
|
run(`git merge --no-ff ${sliceBranch} -m "feat(${milestoneId}/${sliceId}): ${sliceTitle}"`, wtPath);
|
|
75
|
-
// Clean up the slice branch
|
|
76
77
|
run(`git branch -d ${sliceBranch}`, wtPath);
|
|
77
78
|
}
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
describe("auto-worktree-milestone-merge", () => {
|
|
80
81
|
const savedCwd = process.cwd();
|
|
81
82
|
const tempDirs: string[] = [];
|
|
82
83
|
|
|
@@ -86,699 +87,570 @@ async function main(): Promise<void> {
|
|
|
86
87
|
return d;
|
|
87
88
|
}
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const repo = freshRepo();
|
|
94
|
-
const wtPath = createAutoWorktree(repo, "M010");
|
|
95
|
-
|
|
96
|
-
// Add two slices with multiple commits each
|
|
97
|
-
addSliceToMilestone(repo, wtPath, "M010", "S01", "Auth module", [
|
|
98
|
-
{ file: "auth.ts", content: "export const auth = true;\n", message: "add auth" },
|
|
99
|
-
{ file: "auth-utils.ts", content: "export const hash = () => {};\n", message: "add auth utils" },
|
|
100
|
-
]);
|
|
101
|
-
addSliceToMilestone(repo, wtPath, "M010", "S02", "User dashboard", [
|
|
102
|
-
{ file: "dashboard.ts", content: "export const dash = true;\n", message: "add dashboard" },
|
|
103
|
-
{ file: "widgets.ts", content: "export const widgets = [];\n", message: "add widgets" },
|
|
104
|
-
]);
|
|
105
|
-
|
|
106
|
-
const roadmap = makeRoadmap("M010", "User management", [
|
|
107
|
-
{ id: "S01", title: "Auth module" },
|
|
108
|
-
{ id: "S02", title: "User dashboard" },
|
|
109
|
-
]);
|
|
110
|
-
|
|
111
|
-
const mainLogBefore = run("git log --oneline main", repo);
|
|
112
|
-
const mainCommitCountBefore = mainLogBefore.split("\n").length;
|
|
113
|
-
|
|
114
|
-
const result = mergeMilestoneToMain(repo, "M010", roadmap);
|
|
115
|
-
|
|
116
|
-
// Exactly one new commit on main
|
|
117
|
-
const mainLog = run("git log --oneline main", repo);
|
|
118
|
-
const mainCommitCountAfter = mainLog.split("\n").length;
|
|
119
|
-
assertEq(mainCommitCountAfter, mainCommitCountBefore + 1, "exactly one new commit on main");
|
|
120
|
-
|
|
121
|
-
// Milestone branch deleted
|
|
122
|
-
const branches = run("git branch", repo);
|
|
123
|
-
assertTrue(!branches.includes("milestone/M010"), "milestone branch deleted");
|
|
124
|
-
|
|
125
|
-
// Worktree directory removed
|
|
126
|
-
const worktreeDir = join(repo, ".gsd", "worktrees", "M010");
|
|
127
|
-
assertTrue(!existsSync(worktreeDir), "worktree directory removed");
|
|
128
|
-
|
|
129
|
-
// Module state cleared
|
|
130
|
-
assertEq(getAutoWorktreeOriginalBase(), null, "originalBase cleared after merge");
|
|
131
|
-
|
|
132
|
-
// Files from both slices present on main
|
|
133
|
-
assertTrue(existsSync(join(repo, "auth.ts")), "auth.ts on main");
|
|
134
|
-
assertTrue(existsSync(join(repo, "dashboard.ts")), "dashboard.ts on main");
|
|
135
|
-
assertTrue(existsSync(join(repo, "widgets.ts")), "widgets.ts on main");
|
|
136
|
-
|
|
137
|
-
// Result shape
|
|
138
|
-
assertTrue(result.commitMessage.length > 0, "commitMessage returned");
|
|
139
|
-
assertTrue(typeof result.pushed === "boolean", "pushed is boolean");
|
|
90
|
+
afterEach(() => {
|
|
91
|
+
process.chdir(savedCwd);
|
|
92
|
+
for (const d of tempDirs) {
|
|
93
|
+
if (existsSync(d)) rmSync(d, { recursive: true, force: true });
|
|
140
94
|
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
95
|
+
tempDirs.length = 0;
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test("basic squash merge — one commit on main", () => {
|
|
99
|
+
const repo = freshRepo();
|
|
100
|
+
const wtPath = createAutoWorktree(repo, "M010");
|
|
101
|
+
|
|
102
|
+
addSliceToMilestone(repo, wtPath, "M010", "S01", "Auth module", [
|
|
103
|
+
{ file: "auth.ts", content: "export const auth = true;\n", message: "add auth" },
|
|
104
|
+
{ file: "auth-utils.ts", content: "export const hash = () => {};\n", message: "add auth utils" },
|
|
105
|
+
]);
|
|
106
|
+
addSliceToMilestone(repo, wtPath, "M010", "S02", "User dashboard", [
|
|
107
|
+
{ file: "dashboard.ts", content: "export const dash = true;\n", message: "add dashboard" },
|
|
108
|
+
{ file: "widgets.ts", content: "export const widgets = [];\n", message: "add widgets" },
|
|
109
|
+
]);
|
|
110
|
+
|
|
111
|
+
const roadmap = makeRoadmap("M010", "User management", [
|
|
112
|
+
{ id: "S01", title: "Auth module" },
|
|
113
|
+
{ id: "S02", title: "User dashboard" },
|
|
114
|
+
]);
|
|
115
|
+
|
|
116
|
+
const mainLogBefore = run("git log --oneline main", repo);
|
|
117
|
+
const mainCommitCountBefore = mainLogBefore.split("\n").length;
|
|
118
|
+
|
|
119
|
+
const result = mergeMilestoneToMain(repo, "M010", roadmap);
|
|
120
|
+
|
|
121
|
+
const mainLog = run("git log --oneline main", repo);
|
|
122
|
+
const mainCommitCountAfter = mainLog.split("\n").length;
|
|
123
|
+
assert.strictEqual(mainCommitCountAfter, mainCommitCountBefore + 1, "exactly one new commit on main");
|
|
124
|
+
|
|
125
|
+
const branches = run("git branch", repo);
|
|
126
|
+
assert.ok(!branches.includes("milestone/M010"), "milestone branch deleted");
|
|
127
|
+
|
|
128
|
+
const worktreeDir = join(repo, ".gsd", "worktrees", "M010");
|
|
129
|
+
assert.ok(!existsSync(worktreeDir), "worktree directory removed");
|
|
130
|
+
|
|
131
|
+
assert.strictEqual(getAutoWorktreeOriginalBase(), null, "originalBase cleared after merge");
|
|
132
|
+
|
|
133
|
+
assert.ok(existsSync(join(repo, "auth.ts")), "auth.ts on main");
|
|
134
|
+
assert.ok(existsSync(join(repo, "dashboard.ts")), "dashboard.ts on main");
|
|
135
|
+
assert.ok(existsSync(join(repo, "widgets.ts")), "widgets.ts on main");
|
|
136
|
+
|
|
137
|
+
assert.ok(result.commitMessage.length > 0, "commitMessage returned");
|
|
138
|
+
assert.strictEqual(typeof result.pushed, "boolean", "pushed is boolean");
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("rich commit message format", () => {
|
|
142
|
+
const repo = freshRepo();
|
|
143
|
+
const wtPath = createAutoWorktree(repo, "M020");
|
|
144
|
+
|
|
145
|
+
addSliceToMilestone(repo, wtPath, "M020", "S01", "Core API", [
|
|
146
|
+
{ file: "api.ts", content: "export const api = true;\n", message: "add api" },
|
|
147
|
+
]);
|
|
148
|
+
addSliceToMilestone(repo, wtPath, "M020", "S02", "Error handling", [
|
|
149
|
+
{ file: "errors.ts", content: "export class AppError {}\n", message: "add errors" },
|
|
150
|
+
]);
|
|
151
|
+
addSliceToMilestone(repo, wtPath, "M020", "S03", "Logging infra", [
|
|
152
|
+
{ file: "logger.ts", content: "export const log = () => {};\n", message: "add logger" },
|
|
153
|
+
]);
|
|
154
|
+
|
|
155
|
+
const roadmap = makeRoadmap("M020", "Backend foundation", [
|
|
156
|
+
{ id: "S01", title: "Core API" },
|
|
157
|
+
{ id: "S02", title: "Error handling" },
|
|
158
|
+
{ id: "S03", title: "Logging infra" },
|
|
159
|
+
]);
|
|
160
|
+
|
|
161
|
+
const result = mergeMilestoneToMain(repo, "M020", roadmap);
|
|
162
|
+
|
|
163
|
+
assert.match(result.commitMessage, /^feat\(M020\):/, "subject has conventional commit prefix");
|
|
164
|
+
assert.ok(result.commitMessage.includes("Backend foundation"), "subject includes milestone title");
|
|
165
|
+
assert.ok(result.commitMessage.includes("- S01: Core API"), "body lists S01");
|
|
166
|
+
assert.ok(result.commitMessage.includes("- S02: Error handling"), "body lists S02");
|
|
167
|
+
assert.ok(result.commitMessage.includes("- S03: Logging infra"), "body lists S03");
|
|
168
|
+
assert.ok(result.commitMessage.includes("Branch: milestone/M020"), "body has branch metadata");
|
|
169
|
+
|
|
170
|
+
const gitMsg = run("git log -1 --format=%B main", repo).trim();
|
|
171
|
+
assert.match(gitMsg, /^feat\(M020\):/, "git commit message starts with feat(M020):");
|
|
172
|
+
assert.ok(gitMsg.includes("- S01: Core API"), "git commit body has S01");
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
test("nothing to commit — safe when no code changes (#1738, #1792)", () => {
|
|
176
|
+
const repo = freshRepo();
|
|
177
|
+
const wtPath = createAutoWorktree(repo, "M030");
|
|
178
|
+
const roadmap = makeRoadmap("M030", "Empty milestone", []);
|
|
179
|
+
|
|
180
|
+
let threw = false;
|
|
181
|
+
let errorMsg = "";
|
|
182
|
+
try {
|
|
183
|
+
mergeMilestoneToMain(repo, "M030", roadmap);
|
|
184
|
+
} catch (err: unknown) {
|
|
185
|
+
threw = true;
|
|
186
|
+
errorMsg = err instanceof Error ? err.message : String(err);
|
|
182
187
|
}
|
|
188
|
+
assert.ok(!threw, `safe empty milestone should not throw (got: ${errorMsg})`);
|
|
183
189
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const repo = freshRepo();
|
|
188
|
-
const wtPath = createAutoWorktree(repo, "M030");
|
|
189
|
-
|
|
190
|
-
// Don't add any slices/changes — milestone branch is identical to main
|
|
191
|
-
const roadmap = makeRoadmap("M030", "Empty milestone", []);
|
|
192
|
-
|
|
193
|
-
// Should NOT throw — milestone branch is identical to main, nothing to lose.
|
|
194
|
-
// The anchor check (#1792) verifies no code files differ and passes through.
|
|
195
|
-
let threw = false;
|
|
196
|
-
let errorMsg = "";
|
|
197
|
-
try {
|
|
198
|
-
mergeMilestoneToMain(repo, "M030", roadmap);
|
|
199
|
-
} catch (err: unknown) {
|
|
200
|
-
threw = true;
|
|
201
|
-
errorMsg = err instanceof Error ? err.message : String(err);
|
|
202
|
-
}
|
|
203
|
-
assertTrue(!threw, `safe empty milestone should not throw (got: ${errorMsg})`);
|
|
204
|
-
|
|
205
|
-
// Main log unchanged (only init commit)
|
|
206
|
-
const mainLog = run("git log --oneline main", repo);
|
|
207
|
-
assertEq(mainLog.split("\n").length, 1, "main still has only init commit");
|
|
208
|
-
}
|
|
190
|
+
const mainLog = run("git log --oneline main", repo);
|
|
191
|
+
assert.strictEqual(mainLog.split("\n").length, 1, "main still has only init commit");
|
|
192
|
+
});
|
|
209
193
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// prefs path (process.cwd() at import time), so temp repo prefs aren't
|
|
213
|
-
// discoverable. We verify the push mechanics work by testing that
|
|
214
|
-
// mergeMilestoneToMain successfully completes with a remote configured,
|
|
215
|
-
// then manually push to verify the remote is set up correctly.
|
|
216
|
-
console.log("\n=== auto-push with bare remote ===");
|
|
217
|
-
{
|
|
218
|
-
const repo = freshRepo();
|
|
219
|
-
|
|
220
|
-
// Set up bare remote
|
|
221
|
-
const bareDir = realpathSync(mkdtempSync(join(tmpdir(), "wt-ms-bare-")));
|
|
222
|
-
tempDirs.push(bareDir);
|
|
223
|
-
run("git init --bare", bareDir);
|
|
224
|
-
run(`git remote add origin ${bareDir}`, repo);
|
|
225
|
-
run("git push -u origin main", repo);
|
|
226
|
-
|
|
227
|
-
const wtPath = createAutoWorktree(repo, "M040");
|
|
228
|
-
|
|
229
|
-
addSliceToMilestone(repo, wtPath, "M040", "S01", "Push test", [
|
|
230
|
-
{ file: "pushed.ts", content: "export const pushed = true;\n", message: "add pushed file" },
|
|
231
|
-
]);
|
|
232
|
-
|
|
233
|
-
const roadmap = makeRoadmap("M040", "Push verification", [
|
|
234
|
-
{ id: "S01", title: "Push test" },
|
|
235
|
-
]);
|
|
236
|
-
|
|
237
|
-
const result = mergeMilestoneToMain(repo, "M040", roadmap);
|
|
238
|
-
|
|
239
|
-
// Verify merge succeeded (commit on main)
|
|
240
|
-
const mainLog = run("git log --oneline main", repo);
|
|
241
|
-
assertTrue(mainLog.includes("feat(M040)"), "milestone commit on main");
|
|
242
|
-
|
|
243
|
-
// Manually push to verify remote works
|
|
244
|
-
run("git push origin main", repo);
|
|
245
|
-
const remoteLog = run("git log --oneline main", bareDir);
|
|
246
|
-
assertTrue(remoteLog.includes("feat(M040)"), "milestone commit reachable on remote after manual push");
|
|
247
|
-
|
|
248
|
-
// Temp-repo prefs may or may not be discoverable depending on process cwd and
|
|
249
|
-
// current preference-loading behavior. The important contract is that remote
|
|
250
|
-
// push mechanics work and the returned value reflects what happened.
|
|
251
|
-
assertTrue(typeof result.pushed === "boolean", "pushed flag remains boolean");
|
|
252
|
-
}
|
|
194
|
+
test("auto-push with bare remote", () => {
|
|
195
|
+
const repo = freshRepo();
|
|
253
196
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
// Add a slice with real work
|
|
261
|
-
addSliceToMilestone(repo, wtPath, "M050", "S01", "Conflict test", [
|
|
262
|
-
{ file: "feature.ts", content: "export const feature = true;\n", message: "add feature" },
|
|
263
|
-
]);
|
|
264
|
-
|
|
265
|
-
// Modify .gsd/STATE.md on the milestone branch (simulates auto-mode state updates)
|
|
266
|
-
writeFileSync(join(wtPath, ".gsd", "STATE.md"), "# State\n\n## Updated on milestone branch\n");
|
|
267
|
-
run("git add .", wtPath);
|
|
268
|
-
run('git commit -m "chore: update state on milestone branch"', wtPath);
|
|
269
|
-
|
|
270
|
-
// Now modify .gsd/STATE.md on main too (simulates divergence)
|
|
271
|
-
run("git checkout main", repo);
|
|
272
|
-
writeFileSync(join(repo, ".gsd", "STATE.md"), "# State\n\n## Updated on main\n");
|
|
273
|
-
run("git add .", repo);
|
|
274
|
-
run('git commit -m "chore: update state on main"', repo);
|
|
275
|
-
|
|
276
|
-
// Go back to worktree for the merge
|
|
277
|
-
process.chdir(wtPath);
|
|
278
|
-
|
|
279
|
-
const roadmap = makeRoadmap("M050", "Conflict resolution", [
|
|
280
|
-
{ id: "S01", title: "Conflict test" },
|
|
281
|
-
]);
|
|
282
|
-
|
|
283
|
-
// Merge should succeed despite .gsd/STATE.md conflict — auto-resolved
|
|
284
|
-
let threw = false;
|
|
285
|
-
try {
|
|
286
|
-
const result = mergeMilestoneToMain(repo, "M050", roadmap);
|
|
287
|
-
assertTrue(result.commitMessage.includes("feat(M050)"), "merge commit created despite .gsd conflict");
|
|
288
|
-
} catch (err) {
|
|
289
|
-
threw = true;
|
|
290
|
-
}
|
|
291
|
-
assertTrue(!threw, "auto-resolves .gsd/ state file conflicts without throwing");
|
|
292
|
-
|
|
293
|
-
// Feature file should be on main
|
|
294
|
-
assertTrue(existsSync(join(repo, "feature.ts")), "feature.ts merged to main");
|
|
295
|
-
}
|
|
197
|
+
const bareDir = realpathSync(mkdtempSync(join(tmpdir(), "wt-ms-bare-")));
|
|
198
|
+
tempDirs.push(bareDir);
|
|
199
|
+
run("git init --bare", bareDir);
|
|
200
|
+
run(`git remote add origin ${bareDir}`, repo);
|
|
201
|
+
run("git push -u origin main", repo);
|
|
296
202
|
|
|
297
|
-
|
|
298
|
-
console.log("\n=== skip checkout when main already current (#757) ===");
|
|
299
|
-
{
|
|
300
|
-
const repo = freshRepo();
|
|
301
|
-
const wtPath = createAutoWorktree(repo, "M060");
|
|
302
|
-
|
|
303
|
-
addSliceToMilestone(repo, wtPath, "M060", "S01", "Skip checkout test", [
|
|
304
|
-
{ file: "skip-checkout.ts", content: "export const skip = true;\n", message: "add skip-checkout" },
|
|
305
|
-
]);
|
|
306
|
-
|
|
307
|
-
const roadmap = makeRoadmap("M060", "Skip checkout verification", [
|
|
308
|
-
{ id: "S01", title: "Skip checkout test" },
|
|
309
|
-
]);
|
|
310
|
-
|
|
311
|
-
// Verify main is already checked out at repo root (worktree default)
|
|
312
|
-
const branchAtRoot = run("git rev-parse --abbrev-ref HEAD", repo);
|
|
313
|
-
assertEq(branchAtRoot, "main", "main is already checked out at project root");
|
|
314
|
-
|
|
315
|
-
// mergeMilestoneToMain should succeed without attempting to checkout main
|
|
316
|
-
// (which would fail with "already used by worktree" error)
|
|
317
|
-
let threw = false;
|
|
318
|
-
try {
|
|
319
|
-
const result = mergeMilestoneToMain(repo, "M060", roadmap);
|
|
320
|
-
assertTrue(result.commitMessage.includes("feat(M060)"), "merge commit created");
|
|
321
|
-
} catch (err) {
|
|
322
|
-
threw = true;
|
|
323
|
-
console.error("Unexpected error:", err);
|
|
324
|
-
}
|
|
325
|
-
assertTrue(!threw, "does not fail when main is already checked out at project root");
|
|
326
|
-
|
|
327
|
-
// Verify the merge actually happened
|
|
328
|
-
assertTrue(existsSync(join(repo, "skip-checkout.ts")), "skip-checkout.ts merged to main");
|
|
329
|
-
}
|
|
203
|
+
const wtPath = createAutoWorktree(repo, "M040");
|
|
330
204
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const dir = realpathSync(mkdtempSync(join(tmpdir(), "wt-ms-master-test-")));
|
|
335
|
-
tempDirs.push(dir);
|
|
336
|
-
run("git init -b master", dir);
|
|
337
|
-
run("git config user.email test@test.com", dir);
|
|
338
|
-
run("git config user.name Test", dir);
|
|
339
|
-
writeFileSync(join(dir, "README.md"), "# master-branch repo\n");
|
|
340
|
-
mkdirSync(join(dir, ".gsd"), { recursive: true });
|
|
341
|
-
writeFileSync(join(dir, ".gsd", "STATE.md"), "# State\n");
|
|
342
|
-
run("git add .", dir);
|
|
343
|
-
run("git commit -m init", dir);
|
|
344
|
-
const defaultBranch = run("git rev-parse --abbrev-ref HEAD", dir);
|
|
345
|
-
assertEq(defaultBranch, "master", "repo is on master branch");
|
|
346
|
-
|
|
347
|
-
const wtPath = createAutoWorktree(dir, "M070");
|
|
348
|
-
addSliceToMilestone(dir, wtPath, "M070", "S01", "Master branch test", [
|
|
349
|
-
{ file: "master-feature.ts", content: "export const masterFeature = true;\n", message: "add master feature" },
|
|
350
|
-
]);
|
|
351
|
-
|
|
352
|
-
const metaFile = join(dir, ".gsd", "milestones", "M070", "M070-META.json");
|
|
353
|
-
assertTrue(!existsSync(metaFile), "no META.json — integration branch not captured");
|
|
354
|
-
|
|
355
|
-
const roadmap = makeRoadmap("M070", "Master branch milestone", [
|
|
356
|
-
{ id: "S01", title: "Master branch test" },
|
|
357
|
-
]);
|
|
358
|
-
|
|
359
|
-
let threw = false;
|
|
360
|
-
let errMsg = "";
|
|
361
|
-
try {
|
|
362
|
-
const result = mergeMilestoneToMain(dir, "M070", roadmap);
|
|
363
|
-
assertTrue(result.commitMessage.includes("feat(M070)"), "merge commit created on master");
|
|
364
|
-
} catch (err) {
|
|
365
|
-
threw = true;
|
|
366
|
-
errMsg = err instanceof Error ? err.message : String(err);
|
|
367
|
-
}
|
|
368
|
-
assertTrue(!threw, `should not throw on master-branch repo (got: ${errMsg})`);
|
|
369
|
-
|
|
370
|
-
const finalBranch = run("git rev-parse --abbrev-ref HEAD", dir);
|
|
371
|
-
assertEq(finalBranch, "master", "repo is still on master after merge");
|
|
372
|
-
assertTrue(existsSync(join(dir, "master-feature.ts")), "feature merged to master");
|
|
373
|
-
const branches = run("git branch", dir);
|
|
374
|
-
assertTrue(!branches.includes("milestone/M070"), "milestone branch deleted after merge");
|
|
375
|
-
}
|
|
205
|
+
addSliceToMilestone(repo, wtPath, "M040", "S01", "Push test", [
|
|
206
|
+
{ file: "pushed.ts", content: "export const pushed = true;\n", message: "add pushed file" },
|
|
207
|
+
]);
|
|
376
208
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
const { nativeMergeSquash } = await import("../native-git-bridge.ts");
|
|
381
|
-
const repo = freshRepo();
|
|
382
|
-
|
|
383
|
-
run("git checkout -b milestone/M070", repo);
|
|
384
|
-
writeFileSync(join(repo, "feature.ts"), "export const feature = true;\n");
|
|
385
|
-
run("git add .", repo);
|
|
386
|
-
run('git commit -m "add feature"', repo);
|
|
387
|
-
run("git checkout main", repo);
|
|
388
|
-
|
|
389
|
-
writeFileSync(join(repo, "feature.ts"), "// local dirty version\n");
|
|
390
|
-
|
|
391
|
-
const result = nativeMergeSquash(repo, "milestone/M070");
|
|
392
|
-
assertEq(result.success, false, "merge reports failure on dirty working tree");
|
|
393
|
-
assertTrue(
|
|
394
|
-
result.conflicts.includes("__dirty_working_tree__"),
|
|
395
|
-
"conflicts include __dirty_working_tree__ sentinel",
|
|
396
|
-
);
|
|
397
|
-
|
|
398
|
-
run("git checkout -- . 2>/dev/null || true", repo);
|
|
399
|
-
run("rm -f feature.ts", repo);
|
|
400
|
-
}
|
|
209
|
+
const roadmap = makeRoadmap("M040", "Push verification", [
|
|
210
|
+
{ id: "S01", title: "Push test" },
|
|
211
|
+
]);
|
|
401
212
|
|
|
402
|
-
|
|
403
|
-
console.log("\n=== #1738 bug 2: branch preserved when squash commit empty ===");
|
|
404
|
-
{
|
|
405
|
-
const repo = freshRepo();
|
|
406
|
-
const wtPath = createAutoWorktree(repo, "M080");
|
|
407
|
-
|
|
408
|
-
// Make no changes — squash will produce nothing to commit
|
|
409
|
-
const roadmap = makeRoadmap("M080", "Empty milestone", []);
|
|
410
|
-
|
|
411
|
-
// With the #1792 anchor check, empty milestones with no code changes
|
|
412
|
-
// are safe to proceed — no data to lose.
|
|
413
|
-
let threw = false;
|
|
414
|
-
let errMsg = "";
|
|
415
|
-
try {
|
|
416
|
-
mergeMilestoneToMain(repo, "M080", roadmap);
|
|
417
|
-
} catch (err: unknown) {
|
|
418
|
-
threw = true;
|
|
419
|
-
errMsg = err instanceof Error ? err.message : String(err);
|
|
420
|
-
}
|
|
421
|
-
assertTrue(!threw, `empty milestone with no code changes should not throw (got: ${errMsg})`);
|
|
422
|
-
}
|
|
213
|
+
const result = mergeMilestoneToMain(repo, "M040", roadmap);
|
|
423
214
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
{
|
|
427
|
-
const repo = freshRepo();
|
|
428
|
-
const wtPath = createAutoWorktree(repo, "M090");
|
|
429
|
-
|
|
430
|
-
addSliceToMilestone(repo, wtPath, "M090", "S01", "Sync test", [
|
|
431
|
-
{ file: "sync-test.ts", content: "export const sync = true;\n", message: "add sync-test" },
|
|
432
|
-
]);
|
|
433
|
-
|
|
434
|
-
// Simulate syncStateToProjectRoot: create untracked .gsd/ milestone files
|
|
435
|
-
const msDir = join(repo, ".gsd", "milestones", "M090", "slices", "S01");
|
|
436
|
-
mkdirSync(msDir, { recursive: true });
|
|
437
|
-
writeFileSync(join(msDir, "S01-PLAN.md"), "# synced plan\n");
|
|
438
|
-
writeFileSync(
|
|
439
|
-
join(repo, ".gsd", "milestones", "M090", "M090-ROADMAP.md"),
|
|
440
|
-
"# synced roadmap\n",
|
|
441
|
-
);
|
|
442
|
-
|
|
443
|
-
const runtimeDir = join(repo, ".gsd", "runtime", "units");
|
|
444
|
-
mkdirSync(runtimeDir, { recursive: true });
|
|
445
|
-
writeFileSync(join(runtimeDir, "unit-001.json"), '{"stale": true}');
|
|
446
|
-
|
|
447
|
-
const roadmap = makeRoadmap("M090", "Sync cleanup test", [
|
|
448
|
-
{ id: "S01", title: "Sync test" },
|
|
449
|
-
]);
|
|
450
|
-
|
|
451
|
-
let threw = false;
|
|
452
|
-
try {
|
|
453
|
-
const result = mergeMilestoneToMain(repo, "M090", roadmap);
|
|
454
|
-
assertTrue(
|
|
455
|
-
result.commitMessage.includes("feat(M090)"),
|
|
456
|
-
"#1738 merge succeeds after cleaning synced dirs",
|
|
457
|
-
);
|
|
458
|
-
} catch (err: unknown) {
|
|
459
|
-
threw = true;
|
|
460
|
-
console.error("#1738 bug 3 regression:", err);
|
|
461
|
-
}
|
|
462
|
-
assertTrue(!threw, "#1738 merge does not fail on synced .gsd/ files");
|
|
463
|
-
assertTrue(existsSync(join(repo, "sync-test.ts")), "sync-test.ts on main after merge");
|
|
464
|
-
}
|
|
215
|
+
const mainLog = run("git log --oneline main", repo);
|
|
216
|
+
assert.ok(mainLog.includes("feat(M040)"), "milestone commit on main");
|
|
465
217
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
const repo = freshRepo();
|
|
470
|
-
const wtPath = createAutoWorktree(repo, "M100");
|
|
471
|
-
|
|
472
|
-
addSliceToMilestone(repo, wtPath, "M100", "S01", "E2E test", [
|
|
473
|
-
{ file: "e2e.ts", content: "export const e2e = true;\n", message: "add e2e" },
|
|
474
|
-
]);
|
|
475
|
-
|
|
476
|
-
writeFileSync(join(repo, "e2e.ts"), "// conflicting local file\n");
|
|
477
|
-
|
|
478
|
-
const roadmap = makeRoadmap("M100", "E2E dirty tree", [
|
|
479
|
-
{ id: "S01", title: "E2E test" },
|
|
480
|
-
]);
|
|
481
|
-
|
|
482
|
-
let threw = false;
|
|
483
|
-
let errorMsg = "";
|
|
484
|
-
try {
|
|
485
|
-
mergeMilestoneToMain(repo, "M100", roadmap);
|
|
486
|
-
} catch (err: unknown) {
|
|
487
|
-
threw = true;
|
|
488
|
-
errorMsg = err instanceof Error ? err.message : String(err);
|
|
489
|
-
}
|
|
490
|
-
assertTrue(threw, "#1738 e2e: throws on dirty working tree");
|
|
491
|
-
assertTrue(
|
|
492
|
-
errorMsg.includes("dirty") || errorMsg.includes("untracked") || errorMsg.includes("overwritten"),
|
|
493
|
-
"#1738 e2e: error identifies dirty tree cause",
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
const branches = run("git branch", repo);
|
|
497
|
-
assertTrue(
|
|
498
|
-
branches.includes("milestone/M100"),
|
|
499
|
-
"#1738 e2e: milestone branch preserved on dirty tree rejection",
|
|
500
|
-
);
|
|
501
|
-
}
|
|
218
|
+
run("git push origin main", repo);
|
|
219
|
+
const remoteLog = run("git log --oneline main", bareDir);
|
|
220
|
+
assert.ok(remoteLog.includes("feat(M040)"), "milestone commit reachable on remote after manual push");
|
|
502
221
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
let threw = false;
|
|
523
|
-
let errMsg = "";
|
|
524
|
-
try {
|
|
525
|
-
mergeMilestoneToMain(repo, "M120", roadmap);
|
|
526
|
-
} catch (err) {
|
|
527
|
-
threw = true;
|
|
528
|
-
errMsg = err instanceof Error ? err.message : String(err);
|
|
529
|
-
}
|
|
530
|
-
assertTrue(threw, "throws when milestone has unanchored code changes (#1792)");
|
|
531
|
-
assertTrue(
|
|
532
|
-
errMsg.includes("code file(s) not on"),
|
|
533
|
-
"error message mentions unanchored code files (#1792)",
|
|
534
|
-
);
|
|
535
|
-
|
|
536
|
-
const branches = run("git branch", repo);
|
|
537
|
-
assertTrue(
|
|
538
|
-
branches.includes("milestone/M120"),
|
|
539
|
-
"milestone branch preserved when code is unanchored (#1792)",
|
|
540
|
-
);
|
|
541
|
-
}
|
|
222
|
+
assert.strictEqual(typeof result.pushed, "boolean", "pushed flag remains boolean");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("auto-resolve .gsd/ state file conflicts", () => {
|
|
226
|
+
const repo = freshRepo();
|
|
227
|
+
const wtPath = createAutoWorktree(repo, "M050");
|
|
228
|
+
|
|
229
|
+
addSliceToMilestone(repo, wtPath, "M050", "S01", "Conflict test", [
|
|
230
|
+
{ file: "feature.ts", content: "export const feature = true;\n", message: "add feature" },
|
|
231
|
+
]);
|
|
232
|
+
|
|
233
|
+
writeFileSync(join(wtPath, ".gsd", "STATE.md"), "# State\n\n## Updated on milestone branch\n");
|
|
234
|
+
run("git add .", wtPath);
|
|
235
|
+
run('git commit -m "chore: update state on milestone branch"', wtPath);
|
|
236
|
+
|
|
237
|
+
run("git checkout main", repo);
|
|
238
|
+
writeFileSync(join(repo, ".gsd", "STATE.md"), "# State\n\n## Updated on main\n");
|
|
239
|
+
run("git add .", repo);
|
|
240
|
+
run('git commit -m "chore: update state on main"', repo);
|
|
542
241
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
242
|
+
process.chdir(wtPath);
|
|
243
|
+
|
|
244
|
+
const roadmap = makeRoadmap("M050", "Conflict resolution", [
|
|
245
|
+
{ id: "S01", title: "Conflict test" },
|
|
246
|
+
]);
|
|
247
|
+
|
|
248
|
+
let threw = false;
|
|
249
|
+
try {
|
|
250
|
+
const result = mergeMilestoneToMain(repo, "M050", roadmap);
|
|
251
|
+
assert.ok(result.commitMessage.includes("feat(M050)"), "merge commit created despite .gsd conflict");
|
|
252
|
+
} catch (err) {
|
|
253
|
+
threw = true;
|
|
254
|
+
}
|
|
255
|
+
assert.ok(!threw, "auto-resolves .gsd/ state file conflicts without throwing");
|
|
256
|
+
assert.ok(existsSync(join(repo, "feature.ts")), "feature.ts merged to main");
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("skip checkout when main already current (#757)", () => {
|
|
260
|
+
const repo = freshRepo();
|
|
261
|
+
const wtPath = createAutoWorktree(repo, "M060");
|
|
262
|
+
|
|
263
|
+
addSliceToMilestone(repo, wtPath, "M060", "S01", "Skip checkout test", [
|
|
264
|
+
{ file: "skip-checkout.ts", content: "export const skip = true;\n", message: "add skip-checkout" },
|
|
265
|
+
]);
|
|
266
|
+
|
|
267
|
+
const roadmap = makeRoadmap("M060", "Skip checkout verification", [
|
|
268
|
+
{ id: "S01", title: "Skip checkout test" },
|
|
269
|
+
]);
|
|
270
|
+
|
|
271
|
+
const branchAtRoot = run("git rev-parse --abbrev-ref HEAD", repo);
|
|
272
|
+
assert.strictEqual(branchAtRoot, "main", "main is already checked out at project root");
|
|
273
|
+
|
|
274
|
+
let threw = false;
|
|
275
|
+
try {
|
|
276
|
+
const result = mergeMilestoneToMain(repo, "M060", roadmap);
|
|
277
|
+
assert.ok(result.commitMessage.includes("feat(M060)"), "merge commit created");
|
|
278
|
+
} catch (err) {
|
|
279
|
+
threw = true;
|
|
280
|
+
}
|
|
281
|
+
assert.ok(!threw, "does not fail when main is already checked out at project root");
|
|
282
|
+
assert.ok(existsSync(join(repo, "skip-checkout.ts")), "skip-checkout.ts merged to main");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
test("master-branch repo — no META.json, no prefs (#1668)", () => {
|
|
286
|
+
const dir = realpathSync(mkdtempSync(join(tmpdir(), "wt-ms-master-test-")));
|
|
287
|
+
tempDirs.push(dir);
|
|
288
|
+
run("git init -b master", dir);
|
|
289
|
+
run("git config user.email test@test.com", dir);
|
|
290
|
+
run("git config user.name Test", dir);
|
|
291
|
+
writeFileSync(join(dir, "README.md"), "# master-branch repo\n");
|
|
292
|
+
mkdirSync(join(dir, ".gsd"), { recursive: true });
|
|
293
|
+
writeFileSync(join(dir, ".gsd", "STATE.md"), "# State\n");
|
|
294
|
+
run("git add .", dir);
|
|
295
|
+
run("git commit -m init", dir);
|
|
296
|
+
const defaultBranch = run("git rev-parse --abbrev-ref HEAD", dir);
|
|
297
|
+
assert.strictEqual(defaultBranch, "master", "repo is on master branch");
|
|
298
|
+
|
|
299
|
+
const wtPath = createAutoWorktree(dir, "M070");
|
|
300
|
+
addSliceToMilestone(dir, wtPath, "M070", "S01", "Master branch test", [
|
|
301
|
+
{ file: "master-feature.ts", content: "export const masterFeature = true;\n", message: "add master feature" },
|
|
302
|
+
]);
|
|
303
|
+
|
|
304
|
+
const metaFile = join(dir, ".gsd", "milestones", "M070", "M070-META.json");
|
|
305
|
+
assert.ok(!existsSync(metaFile), "no META.json — integration branch not captured");
|
|
306
|
+
|
|
307
|
+
const roadmap = makeRoadmap("M070", "Master branch milestone", [
|
|
308
|
+
{ id: "S01", title: "Master branch test" },
|
|
309
|
+
]);
|
|
310
|
+
|
|
311
|
+
let threw = false;
|
|
312
|
+
let errMsg = "";
|
|
313
|
+
try {
|
|
314
|
+
const result = mergeMilestoneToMain(dir, "M070", roadmap);
|
|
315
|
+
assert.ok(result.commitMessage.includes("feat(M070)"), "merge commit created on master");
|
|
316
|
+
} catch (err) {
|
|
317
|
+
threw = true;
|
|
318
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
319
|
+
}
|
|
320
|
+
assert.ok(!threw, `should not throw on master-branch repo (got: ${errMsg})`);
|
|
321
|
+
|
|
322
|
+
const finalBranch = run("git rev-parse --abbrev-ref HEAD", dir);
|
|
323
|
+
assert.strictEqual(finalBranch, "master", "repo is still on master after merge");
|
|
324
|
+
assert.ok(existsSync(join(dir, "master-feature.ts")), "feature merged to master");
|
|
325
|
+
const branches = run("git branch", dir);
|
|
326
|
+
assert.ok(!branches.includes("milestone/M070"), "milestone branch deleted after merge");
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test("#1738 bug 1: nativeMergeSquash detects dirty working tree", async () => {
|
|
330
|
+
const { nativeMergeSquash } = await import("../native-git-bridge.ts");
|
|
331
|
+
const repo = freshRepo();
|
|
332
|
+
|
|
333
|
+
run("git checkout -b milestone/M070", repo);
|
|
334
|
+
writeFileSync(join(repo, "feature.ts"), "export const feature = true;\n");
|
|
335
|
+
run("git add .", repo);
|
|
336
|
+
run('git commit -m "add feature"', repo);
|
|
337
|
+
run("git checkout main", repo);
|
|
338
|
+
|
|
339
|
+
writeFileSync(join(repo, "feature.ts"), "// local dirty version\n");
|
|
340
|
+
|
|
341
|
+
const result = nativeMergeSquash(repo, "milestone/M070");
|
|
342
|
+
assert.strictEqual(result.success, false, "merge reports failure on dirty working tree");
|
|
343
|
+
assert.ok(
|
|
344
|
+
result.conflicts.includes("__dirty_working_tree__"),
|
|
345
|
+
"conflicts include __dirty_working_tree__ sentinel",
|
|
346
|
+
);
|
|
347
|
+
|
|
348
|
+
run("git checkout -- . 2>/dev/null || true", repo);
|
|
349
|
+
run("rm -f feature.ts", repo);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
test("#1738 bug 2: branch preserved when squash commit empty", () => {
|
|
353
|
+
const repo = freshRepo();
|
|
354
|
+
const wtPath = createAutoWorktree(repo, "M080");
|
|
355
|
+
const roadmap = makeRoadmap("M080", "Empty milestone", []);
|
|
356
|
+
|
|
357
|
+
let threw = false;
|
|
358
|
+
let errMsg = "";
|
|
359
|
+
try {
|
|
360
|
+
mergeMilestoneToMain(repo, "M080", roadmap);
|
|
361
|
+
} catch (err: unknown) {
|
|
362
|
+
threw = true;
|
|
363
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
364
|
+
}
|
|
365
|
+
assert.ok(!threw, `empty milestone with no code changes should not throw (got: ${errMsg})`);
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
test("#1738 bug 3: synced .gsd/ dirs cleaned before merge", () => {
|
|
369
|
+
const repo = freshRepo();
|
|
370
|
+
const wtPath = createAutoWorktree(repo, "M090");
|
|
371
|
+
|
|
372
|
+
addSliceToMilestone(repo, wtPath, "M090", "S01", "Sync test", [
|
|
373
|
+
{ file: "sync-test.ts", content: "export const sync = true;\n", message: "add sync-test" },
|
|
374
|
+
]);
|
|
375
|
+
|
|
376
|
+
const msDir = join(repo, ".gsd", "milestones", "M090", "slices", "S01");
|
|
377
|
+
mkdirSync(msDir, { recursive: true });
|
|
378
|
+
writeFileSync(join(msDir, "S01-PLAN.md"), "# synced plan\n");
|
|
379
|
+
writeFileSync(
|
|
380
|
+
join(repo, ".gsd", "milestones", "M090", "M090-ROADMAP.md"),
|
|
381
|
+
"# synced roadmap\n",
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
const runtimeDir = join(repo, ".gsd", "runtime", "units");
|
|
385
|
+
mkdirSync(runtimeDir, { recursive: true });
|
|
386
|
+
writeFileSync(join(runtimeDir, "unit-001.json"), '{"stale": true}');
|
|
387
|
+
|
|
388
|
+
const roadmap = makeRoadmap("M090", "Sync cleanup test", [
|
|
389
|
+
{ id: "S01", title: "Sync test" },
|
|
390
|
+
]);
|
|
391
|
+
|
|
392
|
+
let threw = false;
|
|
393
|
+
try {
|
|
394
|
+
const result = mergeMilestoneToMain(repo, "M090", roadmap);
|
|
395
|
+
assert.ok(result.commitMessage.includes("feat(M090)"), "#1738 merge succeeds after cleaning synced dirs");
|
|
396
|
+
} catch (err: unknown) {
|
|
397
|
+
threw = true;
|
|
398
|
+
}
|
|
399
|
+
assert.ok(!threw, "#1738 merge does not fail on synced .gsd/ files");
|
|
400
|
+
assert.ok(existsSync(join(repo, "sync-test.ts")), "sync-test.ts on main after merge");
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
test("#1738 e2e: dirty tree is stashed before merge (#2151)", () => {
|
|
404
|
+
const repo = freshRepo();
|
|
405
|
+
const wtPath = createAutoWorktree(repo, "M100");
|
|
406
|
+
|
|
407
|
+
addSliceToMilestone(repo, wtPath, "M100", "S01", "E2E test", [
|
|
408
|
+
{ file: "e2e.ts", content: "export const e2e = true;\n", message: "add e2e" },
|
|
409
|
+
]);
|
|
410
|
+
|
|
411
|
+
writeFileSync(join(repo, "e2e.ts"), "// conflicting local file\n");
|
|
412
|
+
|
|
413
|
+
const roadmap = makeRoadmap("M100", "E2E dirty tree", [
|
|
414
|
+
{ id: "S01", title: "E2E test" },
|
|
415
|
+
]);
|
|
416
|
+
|
|
417
|
+
// Since #2151, dirty files are stashed before the squash merge instead
|
|
418
|
+
// of causing an immediate rejection. The merge should succeed.
|
|
419
|
+
let threw = false;
|
|
420
|
+
try {
|
|
421
|
+
const result = mergeMilestoneToMain(repo, "M100", roadmap);
|
|
422
|
+
assert.ok(result.commitMessage.includes("feat(M100)"), "#2151: merge succeeds after stashing dirty files");
|
|
423
|
+
} catch {
|
|
424
|
+
threw = true;
|
|
570
425
|
}
|
|
426
|
+
assert.ok(!threw, "#2151: dirty tree no longer rejects — stash handles it");
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
test("throw on unanchored code changes after empty commit (#1792)", () => {
|
|
430
|
+
const repo = freshRepo();
|
|
431
|
+
const wtPath = createAutoWorktree(repo, "M120");
|
|
432
|
+
|
|
433
|
+
addSliceToMilestone(repo, wtPath, "M120", "S01", "Critical feature", [
|
|
434
|
+
{ file: "critical.ts", content: "export const critical = true;\n", message: "add critical feature" },
|
|
435
|
+
]);
|
|
436
|
+
|
|
437
|
+
run(`git merge milestone/M120 --no-ff -m "merge M120"`, repo);
|
|
438
|
+
run("git revert HEAD --no-edit -m 1", repo);
|
|
439
|
+
|
|
440
|
+
const roadmap = makeRoadmap("M120", "Critical milestone", [
|
|
441
|
+
{ id: "S01", title: "Critical feature" },
|
|
442
|
+
]);
|
|
443
|
+
|
|
444
|
+
let threw = false;
|
|
445
|
+
let errMsg = "";
|
|
446
|
+
try {
|
|
447
|
+
mergeMilestoneToMain(repo, "M120", roadmap);
|
|
448
|
+
} catch (err) {
|
|
449
|
+
threw = true;
|
|
450
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
451
|
+
}
|
|
452
|
+
assert.ok(threw, "throws when milestone has unanchored code changes (#1792)");
|
|
453
|
+
assert.ok(errMsg.includes("code file(s) not on"), "error message mentions unanchored code files (#1792)");
|
|
454
|
+
|
|
455
|
+
const branches = run("git branch", repo);
|
|
456
|
+
assert.ok(branches.includes("milestone/M120"), "milestone branch preserved when code is unanchored (#1792)");
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
test("safe teardown — nothing to commit, work already on main (#1792)", () => {
|
|
460
|
+
const repo = freshRepo();
|
|
461
|
+
const wtPath = createAutoWorktree(repo, "M130");
|
|
462
|
+
|
|
463
|
+
addSliceToMilestone(repo, wtPath, "M130", "S01", "Already landed", [
|
|
464
|
+
{ file: "landed.ts", content: "export const landed = true;\n", message: "add landed feature" },
|
|
465
|
+
]);
|
|
466
|
+
|
|
467
|
+
run("git merge --squash milestone/M130", repo);
|
|
468
|
+
run('git commit -m "pre-land milestone work"', repo);
|
|
469
|
+
|
|
470
|
+
const roadmap = makeRoadmap("M130", "Pre-landed milestone", [
|
|
471
|
+
{ id: "S01", title: "Already landed" },
|
|
472
|
+
]);
|
|
473
|
+
|
|
474
|
+
let threw = false;
|
|
475
|
+
let errMsg = "";
|
|
476
|
+
try {
|
|
477
|
+
mergeMilestoneToMain(repo, "M130", roadmap);
|
|
478
|
+
} catch (err) {
|
|
479
|
+
threw = true;
|
|
480
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
481
|
+
}
|
|
482
|
+
assert.ok(!threw, `safe nothing-to-commit should not throw (got: ${errMsg})`);
|
|
483
|
+
assert.ok(existsSync(join(repo, "landed.ts")), "landed.ts present on main");
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
test("stale branch ref — fast-forward before squash merge (#1846)", () => {
|
|
487
|
+
const repo = freshRepo();
|
|
488
|
+
const wtPath = createAutoWorktree(repo, "M140");
|
|
489
|
+
|
|
490
|
+
addSliceToMilestone(repo, wtPath, "M140", "S01", "Initial work", [
|
|
491
|
+
{ file: "initial.ts", content: "export const initial = true;\n", message: "add initial" },
|
|
492
|
+
]);
|
|
571
493
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
assertEq(branchRefBefore, branchRefAfter, "branch ref unchanged (stale)");
|
|
605
|
-
assertTrue(worktreeHead !== branchRefAfter, "worktree HEAD ahead of branch ref");
|
|
606
|
-
|
|
607
|
-
const roadmap = makeRoadmap("M140", "Stale ref milestone", [
|
|
608
|
-
{ id: "S01", title: "Initial work" },
|
|
609
|
-
]);
|
|
610
|
-
|
|
611
|
-
// The fix should fast-forward the branch ref to worktree HEAD before
|
|
612
|
-
// squash-merging, so ALL commits are captured.
|
|
613
|
-
let threw = false;
|
|
614
|
-
let errMsg = "";
|
|
615
|
-
try {
|
|
616
|
-
const result = mergeMilestoneToMain(repo, "M140", roadmap);
|
|
617
|
-
assertTrue(result.commitMessage.includes("feat(M140)"), "merge commit created");
|
|
618
|
-
} catch (err) {
|
|
619
|
-
threw = true;
|
|
620
|
-
errMsg = err instanceof Error ? err.message : String(err);
|
|
621
|
-
}
|
|
622
|
-
assertTrue(!threw, `should not throw with stale branch ref (got: ${errMsg})`);
|
|
623
|
-
|
|
624
|
-
// ALL files from detached HEAD commits must be on main — not just
|
|
625
|
-
// the ones from the stale branch ref
|
|
626
|
-
assertTrue(existsSync(join(repo, "initial.ts")), "initial.ts on main");
|
|
627
|
-
assertTrue(existsSync(join(repo, "feature-a.ts")), "feature-a.ts on main (#1846)");
|
|
628
|
-
assertTrue(existsSync(join(repo, "feature-b.ts")), "feature-b.ts on main (#1846)");
|
|
629
|
-
assertTrue(existsSync(join(repo, "feature-c.ts")), "feature-c.ts on main (#1846)");
|
|
494
|
+
const branchRefBefore = run("git rev-parse milestone/M140", wtPath);
|
|
495
|
+
run("git checkout --detach HEAD", wtPath);
|
|
496
|
+
|
|
497
|
+
writeFileSync(join(wtPath, "feature-a.ts"), "export const featureA = true;\n");
|
|
498
|
+
run("git add .", wtPath);
|
|
499
|
+
run('git commit -m "add feature-a"', wtPath);
|
|
500
|
+
|
|
501
|
+
writeFileSync(join(wtPath, "feature-b.ts"), "export const featureB = true;\n");
|
|
502
|
+
run("git add .", wtPath);
|
|
503
|
+
run('git commit -m "add feature-b"', wtPath);
|
|
504
|
+
|
|
505
|
+
writeFileSync(join(wtPath, "feature-c.ts"), "export const featureC = true;\n");
|
|
506
|
+
run("git add .", wtPath);
|
|
507
|
+
run('git commit -m "add feature-c"', wtPath);
|
|
508
|
+
|
|
509
|
+
const branchRefAfter = run("git rev-parse milestone/M140", wtPath);
|
|
510
|
+
const worktreeHead = run("git rev-parse HEAD", wtPath);
|
|
511
|
+
assert.strictEqual(branchRefBefore, branchRefAfter, "branch ref unchanged (stale)");
|
|
512
|
+
assert.ok(worktreeHead !== branchRefAfter, "worktree HEAD ahead of branch ref");
|
|
513
|
+
|
|
514
|
+
const roadmap = makeRoadmap("M140", "Stale ref milestone", [
|
|
515
|
+
{ id: "S01", title: "Initial work" },
|
|
516
|
+
]);
|
|
517
|
+
|
|
518
|
+
let threw = false;
|
|
519
|
+
let errMsg = "";
|
|
520
|
+
try {
|
|
521
|
+
const result = mergeMilestoneToMain(repo, "M140", roadmap);
|
|
522
|
+
assert.ok(result.commitMessage.includes("feat(M140)"), "merge commit created");
|
|
523
|
+
} catch (err) {
|
|
524
|
+
threw = true;
|
|
525
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
630
526
|
}
|
|
527
|
+
assert.ok(!threw, `should not throw with stale branch ref (got: ${errMsg})`);
|
|
528
|
+
|
|
529
|
+
assert.ok(existsSync(join(repo, "initial.ts")), "initial.ts on main");
|
|
530
|
+
assert.ok(existsSync(join(repo, "feature-a.ts")), "feature-a.ts on main (#1846)");
|
|
531
|
+
assert.ok(existsSync(join(repo, "feature-b.ts")), "feature-b.ts on main (#1846)");
|
|
532
|
+
assert.ok(existsSync(join(repo, "feature-c.ts")), "feature-c.ts on main (#1846)");
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
test("diverged worktree HEAD — throws on divergence (#1846)", () => {
|
|
536
|
+
const repo = freshRepo();
|
|
537
|
+
const wtPath = createAutoWorktree(repo, "M150");
|
|
631
538
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
let errMsg = "";
|
|
661
|
-
try {
|
|
662
|
-
mergeMilestoneToMain(repo, "M150", roadmap);
|
|
663
|
-
} catch (err) {
|
|
664
|
-
threw = true;
|
|
665
|
-
errMsg = err instanceof Error ? err.message : String(err);
|
|
666
|
-
}
|
|
667
|
-
assertTrue(threw, "throws when worktree HEAD diverged from branch ref (#1846)");
|
|
668
|
-
assertTrue(errMsg.includes("diverged"), "error message mentions divergence (#1846)");
|
|
669
|
-
|
|
670
|
-
const branches = run("git branch", repo);
|
|
671
|
-
assertTrue(branches.includes("milestone/M150"), "milestone branch preserved on divergence (#1846)");
|
|
539
|
+
addSliceToMilestone(repo, wtPath, "M150", "S01", "Base work", [
|
|
540
|
+
{ file: "base.ts", content: "export const base = true;\n", message: "add base" },
|
|
541
|
+
]);
|
|
542
|
+
|
|
543
|
+
run("git checkout --detach HEAD", wtPath);
|
|
544
|
+
writeFileSync(join(wtPath, "detached-work.ts"), "export const detached = true;\n");
|
|
545
|
+
run("git add .", wtPath);
|
|
546
|
+
run('git commit -m "detached work"', wtPath);
|
|
547
|
+
|
|
548
|
+
run("git checkout milestone/M150", repo);
|
|
549
|
+
writeFileSync(join(repo, "diverged-work.ts"), "export const diverged = true;\n");
|
|
550
|
+
run("git add .", repo);
|
|
551
|
+
run('git commit -m "diverged work on branch"', repo);
|
|
552
|
+
run("git checkout main", repo);
|
|
553
|
+
|
|
554
|
+
process.chdir(wtPath);
|
|
555
|
+
|
|
556
|
+
const roadmap = makeRoadmap("M150", "Diverged milestone", [
|
|
557
|
+
{ id: "S01", title: "Base work" },
|
|
558
|
+
]);
|
|
559
|
+
|
|
560
|
+
let threw = false;
|
|
561
|
+
let errMsg = "";
|
|
562
|
+
try {
|
|
563
|
+
mergeMilestoneToMain(repo, "M150", roadmap);
|
|
564
|
+
} catch (err) {
|
|
565
|
+
threw = true;
|
|
566
|
+
errMsg = err instanceof Error ? err.message : String(err);
|
|
672
567
|
}
|
|
568
|
+
assert.ok(threw, "throws when worktree HEAD diverged from branch ref (#1846)");
|
|
569
|
+
assert.ok(errMsg.includes("diverged"), "error message mentions divergence (#1846)");
|
|
673
570
|
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
const repo = freshRepo();
|
|
678
|
-
const wtPath = createAutoWorktree(repo, "M160");
|
|
571
|
+
const branches = run("git branch", repo);
|
|
572
|
+
assert.ok(branches.includes("milestone/M150"), "milestone branch preserved on divergence (#1846)");
|
|
573
|
+
});
|
|
679
574
|
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
575
|
+
test("#1853 bug 1: SQUASH_MSG cleaned up after successful squash-merge", () => {
|
|
576
|
+
const repo = freshRepo();
|
|
577
|
+
const wtPath = createAutoWorktree(repo, "M160");
|
|
683
578
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
579
|
+
addSliceToMilestone(repo, wtPath, "M160", "S01", "SQUASH_MSG cleanup test", [
|
|
580
|
+
{ file: "squash-cleanup.ts", content: "export const cleanup = true;\n", message: "add squash-cleanup" },
|
|
581
|
+
]);
|
|
687
582
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
583
|
+
const roadmap = makeRoadmap("M160", "SQUASH_MSG cleanup", [
|
|
584
|
+
{ id: "S01", title: "SQUASH_MSG cleanup test" },
|
|
585
|
+
]);
|
|
691
586
|
|
|
692
|
-
|
|
693
|
-
|
|
587
|
+
const squashMsgPath = join(repo, ".git", "SQUASH_MSG");
|
|
588
|
+
writeFileSync(squashMsgPath, "leftover squash message\n");
|
|
589
|
+
assert.ok(existsSync(squashMsgPath), "SQUASH_MSG planted before merge");
|
|
694
590
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
"#1853: SQUASH_MSG must not persist after successful squash-merge",
|
|
698
|
-
);
|
|
699
|
-
}
|
|
591
|
+
const result = mergeMilestoneToMain(repo, "M160", roadmap);
|
|
592
|
+
assert.ok(result.commitMessage.includes("feat(M160)"), "merge commit created");
|
|
700
593
|
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
{
|
|
704
|
-
const repo = freshRepo();
|
|
705
|
-
const wtPath = createAutoWorktree(repo, "M170");
|
|
594
|
+
assert.ok(!existsSync(squashMsgPath), "#1853: SQUASH_MSG must not persist after successful squash-merge");
|
|
595
|
+
});
|
|
706
596
|
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
597
|
+
test("#1853 bug 2: uncommitted worktree changes committed before teardown", () => {
|
|
598
|
+
const repo = freshRepo();
|
|
599
|
+
const wtPath = createAutoWorktree(repo, "M170");
|
|
710
600
|
|
|
711
|
-
|
|
601
|
+
addSliceToMilestone(repo, wtPath, "M170", "S01", "Teardown safety test", [
|
|
602
|
+
{ file: "safe-file.ts", content: "export const safe = true;\n", message: "add safe file" },
|
|
603
|
+
]);
|
|
712
604
|
|
|
713
|
-
|
|
714
|
-
{ id: "S01", title: "Teardown safety test" },
|
|
715
|
-
]);
|
|
605
|
+
writeFileSync(join(wtPath, "uncommitted-agent-code.ts"), "export const lost = true;\n");
|
|
716
606
|
|
|
717
|
-
|
|
718
|
-
|
|
607
|
+
const roadmap = makeRoadmap("M170", "Teardown safety", [
|
|
608
|
+
{ id: "S01", title: "Teardown safety test" },
|
|
609
|
+
]);
|
|
719
610
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
"#1853: uncommitted worktree code must survive teardown",
|
|
723
|
-
);
|
|
724
|
-
}
|
|
611
|
+
const result = mergeMilestoneToMain(repo, "M170", roadmap);
|
|
612
|
+
assert.ok(result.commitMessage.includes("feat(M170)"), "merge commit created");
|
|
725
613
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
// Only add .gsd/ metadata files — no actual code
|
|
733
|
-
mkdirSync(join(wtPath, ".gsd", "milestones", "M180"), { recursive: true });
|
|
734
|
-
writeFileSync(
|
|
735
|
-
join(wtPath, ".gsd", "milestones", "M180", "SUMMARY.md"),
|
|
736
|
-
"# M180 Summary\n\nThis milestone was planned but not implemented.\n",
|
|
737
|
-
);
|
|
738
|
-
run("git add .", wtPath);
|
|
739
|
-
run('git commit -m "chore: add milestone summary"', wtPath);
|
|
740
|
-
|
|
741
|
-
const roadmap = makeRoadmap("M180", "Metadata-only milestone", []);
|
|
742
|
-
|
|
743
|
-
const result = mergeMilestoneToMain(repo, "M180", roadmap);
|
|
744
|
-
assertEq(
|
|
745
|
-
result.codeFilesChanged,
|
|
746
|
-
false,
|
|
747
|
-
"#1906: codeFilesChanged must be false when only .gsd/ files were merged",
|
|
748
|
-
);
|
|
749
|
-
}
|
|
614
|
+
assert.ok(
|
|
615
|
+
existsSync(join(repo, "uncommitted-agent-code.ts")),
|
|
616
|
+
"#1853: uncommitted worktree code must survive teardown",
|
|
617
|
+
);
|
|
618
|
+
});
|
|
750
619
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
const repo = freshRepo();
|
|
755
|
-
const wtPath = createAutoWorktree(repo, "M190");
|
|
756
|
-
|
|
757
|
-
addSliceToMilestone(repo, wtPath, "M190", "S01", "Real code", [
|
|
758
|
-
{ file: "real-code.ts", content: "export const real = true;\n", message: "add real code" },
|
|
759
|
-
]);
|
|
760
|
-
|
|
761
|
-
const roadmap = makeRoadmap("M190", "Code milestone", [
|
|
762
|
-
{ id: "S01", title: "Real code" },
|
|
763
|
-
]);
|
|
764
|
-
|
|
765
|
-
const result = mergeMilestoneToMain(repo, "M190", roadmap);
|
|
766
|
-
assertEq(
|
|
767
|
-
result.codeFilesChanged,
|
|
768
|
-
true,
|
|
769
|
-
"#1906: codeFilesChanged must be true when real code files were merged",
|
|
770
|
-
);
|
|
771
|
-
assertTrue(existsSync(join(repo, "real-code.ts")), "real-code.ts merged to main");
|
|
772
|
-
}
|
|
620
|
+
test("#1906: codeFilesChanged=false when only .gsd/ metadata merged", () => {
|
|
621
|
+
const repo = freshRepo();
|
|
622
|
+
const wtPath = createAutoWorktree(repo, "M180");
|
|
773
623
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
624
|
+
mkdirSync(join(wtPath, ".gsd", "milestones", "M180"), { recursive: true });
|
|
625
|
+
writeFileSync(
|
|
626
|
+
join(wtPath, ".gsd", "milestones", "M180", "SUMMARY.md"),
|
|
627
|
+
"# M180 Summary\n\nThis milestone was planned but not implemented.\n",
|
|
628
|
+
);
|
|
629
|
+
run("git add .", wtPath);
|
|
630
|
+
run('git commit -m "chore: add milestone summary"', wtPath);
|
|
780
631
|
|
|
781
|
-
|
|
782
|
-
|
|
632
|
+
const roadmap = makeRoadmap("M180", "Metadata-only milestone", []);
|
|
633
|
+
|
|
634
|
+
const result = mergeMilestoneToMain(repo, "M180", roadmap);
|
|
635
|
+
assert.strictEqual(result.codeFilesChanged, false,
|
|
636
|
+
"#1906: codeFilesChanged must be false when only .gsd/ files were merged");
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
test("#1906: codeFilesChanged=true when real code is merged", () => {
|
|
640
|
+
const repo = freshRepo();
|
|
641
|
+
const wtPath = createAutoWorktree(repo, "M190");
|
|
642
|
+
|
|
643
|
+
addSliceToMilestone(repo, wtPath, "M190", "S01", "Real code", [
|
|
644
|
+
{ file: "real-code.ts", content: "export const real = true;\n", message: "add real code" },
|
|
645
|
+
]);
|
|
646
|
+
|
|
647
|
+
const roadmap = makeRoadmap("M190", "Code milestone", [
|
|
648
|
+
{ id: "S01", title: "Real code" },
|
|
649
|
+
]);
|
|
783
650
|
|
|
784
|
-
|
|
651
|
+
const result = mergeMilestoneToMain(repo, "M190", roadmap);
|
|
652
|
+
assert.strictEqual(result.codeFilesChanged, true,
|
|
653
|
+
"#1906: codeFilesChanged must be true when real code files were merged");
|
|
654
|
+
assert.ok(existsSync(join(repo, "real-code.ts")), "real-code.ts merged to main");
|
|
655
|
+
});
|
|
656
|
+
});
|