@opengsd/gsd-pi 1.8.0 → 1.8.1-dev.897b3c90
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 +8 -3
- package/dist/cli.js +5 -1
- package/dist/headless-events.d.ts +2 -1
- package/dist/headless-events.js +11 -3
- package/dist/headless-milestone-readiness.d.ts +29 -0
- package/dist/headless-milestone-readiness.js +161 -0
- package/dist/headless.js +25 -2
- package/dist/print-mode-exit.d.ts +12 -0
- package/dist/print-mode-exit.js +14 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +16 -47
- package/dist/resources/extensions/browser-tools/capture.js +2 -77
- package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +74 -19
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +35 -1
- package/dist/resources/extensions/gsd/auto.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +78 -4
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +84 -26
- package/dist/resources/extensions/gsd/command-feedback.js +16 -12
- package/dist/resources/extensions/gsd/compat/compat-marker.js +19 -2
- package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +51 -16
- package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
- package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
- package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
- package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -4
- package/dist/resources/extensions/gsd/doctor-history.js +65 -0
- package/dist/resources/extensions/gsd/doctor-state-checks.js +509 -0
- package/dist/resources/extensions/gsd/doctor-workspace-checks.js +91 -0
- package/dist/resources/extensions/gsd/doctor.js +14 -653
- package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
- package/dist/resources/extensions/gsd/gsd-db.js +187 -45
- package/dist/resources/extensions/gsd/guided-flow.js +29 -10
- package/dist/resources/extensions/gsd/markdown-renderer.js +16 -2
- package/dist/resources/extensions/gsd/md-importer.js +109 -16
- package/dist/resources/extensions/gsd/migrate/command.js +19 -162
- package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
- package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
- package/dist/resources/extensions/gsd/migrate/planning-writer.js +20 -19
- package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
- package/dist/resources/extensions/gsd/migration-auto-check.js +4 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
- package/dist/resources/extensions/gsd/paths.js +4 -1
- package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
- package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +27 -13
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +13 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/project-md.js +54 -14
- package/dist/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.js +48 -5
- package/dist/resources/extensions/gsd/stop-notice.js +15 -1
- package/dist/resources/extensions/gsd/sync-lock.js +13 -7
- package/dist/resources/extensions/gsd/tools/complete-task.js +82 -1
- package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
- package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
- package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
- package/dist/resources/extensions/gsd/unit-registry.js +4 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
- package/dist/resources/extensions/gsd/worktree-state-projection.js +6 -0
- package/dist/resources/extensions/mac-tools/index.js +31 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +5 -5
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- 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/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/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/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/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 +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- 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 +5 -5
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
- package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- 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/package.json +0 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +31 -3
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +12 -10
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-config.d.ts +1 -1
- package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-config.js +5 -1
- package/packages/daemon/dist/cloud-config.js.map +1 -1
- package/packages/daemon/dist/cloud-config.test.js +51 -1
- package/packages/daemon/dist/cloud-config.test.js.map +1 -1
- package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
- package/packages/daemon/dist/local-tool-executor.js +2 -0
- package/packages/daemon/dist/local-tool-executor.js.map +1 -1
- package/packages/daemon/package.json +6 -6
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/dist/cli.d.ts +5 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cli.js +160 -0
- package/packages/gsd-cloud/dist/cli.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.js +231 -0
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +35 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js +258 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.js +37 -0
- package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
- package/packages/gsd-cloud/dist/config.d.ts +17 -0
- package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/config.js +146 -0
- package/packages/gsd-cloud/dist/config.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.js +128 -0
- package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
- package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.js +11 -0
- package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.js +29 -0
- package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
- package/packages/gsd-cloud/dist/index.d.ts +7 -0
- package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/index.js +8 -0
- package/packages/gsd-cloud/dist/index.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
- package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
- package/packages/gsd-cloud/dist/logger.d.ts +25 -0
- package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/logger.js +72 -0
- package/packages/gsd-cloud/dist/logger.js.map +1 -0
- package/packages/gsd-cloud/dist/types.d.ts +51 -0
- package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/types.js +9 -0
- package/packages/gsd-cloud/dist/types.js.map +1 -0
- package/packages/gsd-cloud/package.json +3 -3
- package/packages/mcp-server/README.md +8 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +60 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +54 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +19 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +16 -47
- package/src/resources/extensions/browser-tools/capture.ts +2 -86
- package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +86 -19
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +38 -1
- package/src/resources/extensions/gsd/auto.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +91 -4
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +80 -24
- package/src/resources/extensions/gsd/command-feedback.ts +19 -12
- package/src/resources/extensions/gsd/compat/compat-marker.ts +21 -4
- package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +53 -17
- package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
- package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
- package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -4
- package/src/resources/extensions/gsd/doctor-history.ts +81 -0
- package/src/resources/extensions/gsd/doctor-state-checks.ts +527 -0
- package/src/resources/extensions/gsd/doctor-workspace-checks.ts +97 -0
- package/src/resources/extensions/gsd/doctor.ts +14 -673
- package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
- package/src/resources/extensions/gsd/gsd-db.ts +255 -52
- package/src/resources/extensions/gsd/guided-flow.ts +39 -10
- package/src/resources/extensions/gsd/markdown-renderer.ts +23 -7
- package/src/resources/extensions/gsd/md-importer.ts +116 -13
- package/src/resources/extensions/gsd/migrate/command.ts +21 -227
- package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
- package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
- package/src/resources/extensions/gsd/migrate/planning-writer.ts +21 -23
- package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
- package/src/resources/extensions/gsd/migration-auto-check.ts +3 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
- package/src/resources/extensions/gsd/paths.ts +4 -1
- package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
- package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +30 -13
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +16 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/project-md.ts +67 -20
- package/src/resources/extensions/gsd/state-reconciliation/drift/sketch-flag.ts +47 -5
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
- package/src/resources/extensions/gsd/stop-notice.ts +18 -1
- package/src/resources/extensions/gsd/sync-lock.ts +14 -6
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
- package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +286 -0
- package/src/resources/extensions/gsd/tests/db-authority-regression.test.ts +76 -1
- package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/doctor-history-public-api.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/parsers-legacy-importers.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
- package/src/resources/extensions/gsd/tests/planning-writer.test.ts +47 -1
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/progressive-planning.test.ts +18 -3
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +177 -25
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +120 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
- package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
- package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
- package/src/resources/extensions/gsd/types.ts +11 -0
- package/src/resources/extensions/gsd/unit-registry.ts +4 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
- package/src/resources/extensions/gsd/worktree-state-projection.ts +12 -0
- package/src/resources/extensions/mac-tools/index.ts +52 -9
- package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
- package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
- /package/dist/web/standalone/.next/static/{seHIUVbR1mm7LfG83nWJO → TezjdjSHBVRRr54XjAvte}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{seHIUVbR1mm7LfG83nWJO → TezjdjSHBVRRr54XjAvte}/_ssgManifest.js +0 -0
|
@@ -864,6 +864,13 @@ export function getDiscussableFutureMilestones<T extends { id: string; status: s
|
|
|
864
864
|
);
|
|
865
865
|
}
|
|
866
866
|
|
|
867
|
+
function findDiscussTargetMilestone(
|
|
868
|
+
registry: GSDState["registry"],
|
|
869
|
+
milestoneId: string,
|
|
870
|
+
): GSDState["registry"][number] | undefined {
|
|
871
|
+
return registry.find((m) => m.id === milestoneId || m.id.startsWith(`${milestoneId}-`));
|
|
872
|
+
}
|
|
873
|
+
|
|
867
874
|
function getStructuredQuestionsAvailability(
|
|
868
875
|
pi: ExtensionAPI,
|
|
869
876
|
ctx: ExtensionContext | undefined,
|
|
@@ -1333,12 +1340,23 @@ export async function showDiscuss(
|
|
|
1333
1340
|
if (slash > 0) {
|
|
1334
1341
|
const mid = target.slice(0, slash);
|
|
1335
1342
|
const sid = target.slice(slash + 1);
|
|
1336
|
-
const targetMilestone = state.registry
|
|
1337
|
-
if (!targetMilestone
|
|
1338
|
-
ctx.ui.notify(
|
|
1343
|
+
const targetMilestone = findDiscussTargetMilestone(state.registry, mid);
|
|
1344
|
+
if (!targetMilestone) {
|
|
1345
|
+
ctx.ui.notify(
|
|
1346
|
+
`Milestone ${mid} was not found in the roadmap. Use /gsd new-milestone to add it, or /gsd status to see available milestones.`,
|
|
1347
|
+
"warning",
|
|
1348
|
+
);
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1351
|
+
if (targetMilestone.status === "complete") {
|
|
1352
|
+
ctx.ui.notify(`Milestone ${targetMilestone.id} is already complete.`, "info");
|
|
1339
1353
|
return;
|
|
1340
1354
|
}
|
|
1341
|
-
|
|
1355
|
+
if (targetMilestone.status === "parked") {
|
|
1356
|
+
ctx.ui.notify(`Milestone ${targetMilestone.id} is parked. Run /gsd unpark ${targetMilestone.id} to reactivate.`, "warning");
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
const slices = await loadDiscussNormSlices(basePath, targetMilestone.id);
|
|
1342
1360
|
const chosen = slices.find((s) => s.id.toUpperCase() === sid.toUpperCase());
|
|
1343
1361
|
if (!chosen) {
|
|
1344
1362
|
ctx.ui.notify(`Slice ${target} was not found in discussable slices.`, "warning");
|
|
@@ -1348,10 +1366,10 @@ export async function showDiscuss(
|
|
|
1348
1366
|
ctx.ui.notify(`Slice ${target} is already complete; nothing to discuss.`, "info");
|
|
1349
1367
|
return;
|
|
1350
1368
|
}
|
|
1351
|
-
const discussBasePath = resolveDiscussSliceBasePath(basePath,
|
|
1352
|
-
const contextFile = resolveSliceFile(discussBasePath,
|
|
1369
|
+
const discussBasePath = resolveDiscussSliceBasePath(basePath, targetMilestone.id);
|
|
1370
|
+
const contextFile = resolveSliceFile(discussBasePath, targetMilestone.id, sid, "CONTEXT");
|
|
1353
1371
|
const sqAvail = getStructuredQuestionsAvailability(pi, ctx);
|
|
1354
|
-
const prompt = await buildDiscussSlicePrompt(
|
|
1372
|
+
const prompt = await buildDiscussSlicePrompt(targetMilestone.id, sid, chosen.title, discussBasePath, {
|
|
1355
1373
|
rediscuss: !!contextFile,
|
|
1356
1374
|
structuredQuestionsAvailable: sqAvail,
|
|
1357
1375
|
});
|
|
@@ -1359,9 +1377,20 @@ export async function showDiscuss(
|
|
|
1359
1377
|
return;
|
|
1360
1378
|
}
|
|
1361
1379
|
|
|
1362
|
-
const targetMilestone = state.registry
|
|
1363
|
-
if (!targetMilestone
|
|
1364
|
-
ctx.ui.notify(
|
|
1380
|
+
const targetMilestone = findDiscussTargetMilestone(state.registry, target);
|
|
1381
|
+
if (!targetMilestone) {
|
|
1382
|
+
ctx.ui.notify(
|
|
1383
|
+
`Milestone ${target} was not found in the roadmap. Use /gsd new-milestone to add it, or /gsd status to see available milestones.`,
|
|
1384
|
+
"warning",
|
|
1385
|
+
);
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
if (targetMilestone.status === "complete") {
|
|
1389
|
+
ctx.ui.notify(`Milestone ${targetMilestone.id} is already complete.`, "info");
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
if (targetMilestone.status === "parked") {
|
|
1393
|
+
ctx.ui.notify(`Milestone ${targetMilestone.id} is parked. Run /gsd unpark ${targetMilestone.id} to reactivate.`, "warning");
|
|
1365
1394
|
return;
|
|
1366
1395
|
}
|
|
1367
1396
|
await dispatchDiscussForMilestone(ctx, pi, basePath, targetMilestone.id, targetMilestone.title, {});
|
|
@@ -1208,6 +1208,21 @@ export interface AssessmentData {
|
|
|
1208
1208
|
completedSliceId?: string;
|
|
1209
1209
|
}
|
|
1210
1210
|
|
|
1211
|
+
function existingLegacySliceAssessmentPath(
|
|
1212
|
+
basePath: string,
|
|
1213
|
+
milestoneId: string,
|
|
1214
|
+
sliceId: string,
|
|
1215
|
+
): string | null {
|
|
1216
|
+
if (!isLegacyMilestonesLayout(basePath)) return null;
|
|
1217
|
+
const legacyBase = legacyMilestonesDir(basePath);
|
|
1218
|
+
const milestoneDirName = resolveDir(legacyBase, milestoneId);
|
|
1219
|
+
if (!milestoneDirName) return null;
|
|
1220
|
+
const slicesDir = join(legacyBase, milestoneDirName, "slices");
|
|
1221
|
+
const sliceDirName = resolveDir(slicesDir, sliceId);
|
|
1222
|
+
if (!sliceDirName) return null;
|
|
1223
|
+
return join(slicesDir, sliceDirName, `${sliceId}-ASSESSMENT.md`);
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1211
1226
|
export async function renderReplanFromDb(
|
|
1212
1227
|
basePath: string,
|
|
1213
1228
|
milestoneId: string,
|
|
@@ -1258,13 +1273,14 @@ export async function renderAssessmentFromDb(
|
|
|
1258
1273
|
sliceId: string,
|
|
1259
1274
|
assessmentData: AssessmentData,
|
|
1260
1275
|
): Promise<{ assessmentPath: string; content: string }> {
|
|
1261
|
-
const absPath =
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1276
|
+
const absPath = existingLegacySliceAssessmentPath(basePath, milestoneId, sliceId)
|
|
1277
|
+
?? targetSliceFile(
|
|
1278
|
+
basePath,
|
|
1279
|
+
milestoneId,
|
|
1280
|
+
sliceId,
|
|
1281
|
+
"ASSESSMENT",
|
|
1282
|
+
getMilestone(milestoneId)?.title,
|
|
1283
|
+
);
|
|
1268
1284
|
mkdirSync(dirname(absPath), { recursive: true });
|
|
1269
1285
|
const artifactPath = toArtifactPath(absPath, basePath);
|
|
1270
1286
|
|
|
@@ -17,6 +17,8 @@ import {
|
|
|
17
17
|
transaction,
|
|
18
18
|
updateMilestoneStatus,
|
|
19
19
|
updateSliceStatus,
|
|
20
|
+
getMilestoneSlices,
|
|
21
|
+
getSliceTasks,
|
|
20
22
|
_getAdapter,
|
|
21
23
|
} from './gsd-db.js';
|
|
22
24
|
import { openWorkflowDatabasePath } from './db-workspace.js';
|
|
@@ -43,6 +45,26 @@ const VALID_MADE_BY = new Set(['human', 'agent', 'collaborative']);
|
|
|
43
45
|
|
|
44
46
|
const IMPORT_COMPLETE_STATUSES = new Set(['complete', 'done']);
|
|
45
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Derive the set of milestone ids a projection entry's `entities` touch. Marker
|
|
50
|
+
* entity ids are fully-qualified DB ids (`M001`, `M001/S01`, `M001/S01/T01`), so
|
|
51
|
+
* the milestone id is always the first `/`-segment — independent of the on-disk
|
|
52
|
+
* layout (legacy `milestones/<MID>/…` vs flat `phases/NN-slug/…`). The
|
|
53
|
+
* external-edit drift repairs (#027) feed this into
|
|
54
|
+
* `migrateHierarchyToDb(..., { statusAuthoritativeMilestones })` to scope status
|
|
55
|
+
* authority to exactly the milestone(s) a drifted file projects. Empty/blank
|
|
56
|
+
* entries are dropped, so an entity-less entry yields an empty set (repair then
|
|
57
|
+
* preserves DB status everywhere — fail toward the DB, not markdown).
|
|
58
|
+
*/
|
|
59
|
+
export function milestoneIdsFromEntities(entities: readonly string[]): Set<string> {
|
|
60
|
+
const ids = new Set<string>();
|
|
61
|
+
for (const e of entities) {
|
|
62
|
+
const milestoneId = e.split('/')[0];
|
|
63
|
+
if (milestoneId) ids.add(milestoneId);
|
|
64
|
+
}
|
|
65
|
+
return ids;
|
|
66
|
+
}
|
|
67
|
+
|
|
46
68
|
/**
|
|
47
69
|
* Completion timestamp for an entity imported as complete: the SUMMARY.md mtime
|
|
48
70
|
* when one exists (deterministic, matches the completion drift handler), else
|
|
@@ -676,15 +698,35 @@ function findFileByPrefixAndSuffix(dir: string, idPrefix: string, suffix: string
|
|
|
676
698
|
* Uses INSERT OR IGNORE for idempotency. Insert order: milestones → slices → tasks.
|
|
677
699
|
* Ghost milestones (dirs with no CONTEXT, ROADMAP, or SUMMARY) are skipped.
|
|
678
700
|
*
|
|
701
|
+
* `opts.statusAuthoritativeMilestones` narrows *status* authority. It exists for
|
|
702
|
+
* the scoped external-edit drift repair: detection knows exactly which
|
|
703
|
+
* projection file drifted, but this import walks the whole tree. Without scoping,
|
|
704
|
+
* an unrelated file that is stale from gsd-pi's own miss (a forgotten render)
|
|
705
|
+
* rides along with markdown authority it was never granted and its stale checked
|
|
706
|
+
* checkbox silently reverts a reopened slice/milestone in the DB (#027).
|
|
707
|
+
*
|
|
708
|
+
* - opts absent → full markdown authority for every milestone (initial migration,
|
|
709
|
+
* gsd-core full import, /gsd recover rebuild). Behavior is identical to before.
|
|
710
|
+
* - opts present → for a milestone NOT in the set whose DB row *already exists*,
|
|
711
|
+
* the existing DB status is preserved: the slice upsert is fed the current DB
|
|
712
|
+
* status (so a stale `complete` checkbox can't overwrite a reopened `pending`),
|
|
713
|
+
* and the complete-status backfills are skipped. Milestone rows are already
|
|
714
|
+
* protected by INSERT OR IGNORE. Rows that do not exist yet are inserted with
|
|
715
|
+
* the parsed status regardless of scope (new content is new content).
|
|
716
|
+
*
|
|
679
717
|
* Returns count of inserted hierarchy items.
|
|
680
718
|
*/
|
|
681
|
-
export function migrateHierarchyToDb(
|
|
719
|
+
export function migrateHierarchyToDb(
|
|
720
|
+
basePath: string,
|
|
721
|
+
opts?: { statusAuthoritativeMilestones?: ReadonlySet<string> },
|
|
722
|
+
): {
|
|
682
723
|
milestones: number;
|
|
683
724
|
slices: number;
|
|
684
725
|
tasks: number;
|
|
685
726
|
} {
|
|
686
727
|
const counts = { milestones: 0, slices: 0, tasks: 0 };
|
|
687
728
|
const milestoneIds = findMilestoneIds(basePath);
|
|
729
|
+
const statusScope = opts?.statusAuthoritativeMilestones;
|
|
688
730
|
|
|
689
731
|
for (const milestoneId of milestoneIds) {
|
|
690
732
|
// Check for ghost milestones — skip dirs with no meaningful content
|
|
@@ -745,8 +787,30 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
745
787
|
}
|
|
746
788
|
}
|
|
747
789
|
|
|
748
|
-
//
|
|
749
|
-
|
|
790
|
+
// #027: when a status scope is supplied, a milestone outside it keeps DB
|
|
791
|
+
// status authority for rows that already exist — only the drifted file's
|
|
792
|
+
// milestone(s) may drive status closes from checkboxes. Absent scope, every
|
|
793
|
+
// milestone is authoritative (unchanged full-import behavior).
|
|
794
|
+
const milestoneStatusAuthoritative = !statusScope || statusScope.has(milestoneId);
|
|
795
|
+
// Snapshot existing slice statuses once (only needed when preserving DB
|
|
796
|
+
// authority for this milestone) so the upsert can echo them back instead of
|
|
797
|
+
// flipping an open slice closed from a stale checkbox.
|
|
798
|
+
const existingSliceStatus = new Map<string, string>();
|
|
799
|
+
const existingTaskStatus = new Map<string, string>();
|
|
800
|
+
if (!milestoneStatusAuthoritative) {
|
|
801
|
+
for (const s of getMilestoneSlices(milestoneId)) {
|
|
802
|
+
existingSliceStatus.set(s.id, s.status);
|
|
803
|
+
for (const t of getSliceTasks(milestoneId, s.id)) {
|
|
804
|
+
existingTaskStatus.set(`${s.id}/${t.id}`, t.status);
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Insert milestone (FK parent — must come first). INSERT OR IGNORE: an
|
|
810
|
+
// existing milestone row is never overwritten, so DB status is already
|
|
811
|
+
// preserved for out-of-scope milestones. `inserted` tells us whether this
|
|
812
|
+
// row is new (parsed status applies) vs pre-existing (backfill gated below).
|
|
813
|
+
const milestoneInserted = insertMilestone({
|
|
750
814
|
id: milestoneId,
|
|
751
815
|
title: milestoneTitle,
|
|
752
816
|
status: milestoneStatus,
|
|
@@ -760,10 +824,14 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
760
824
|
// insertMilestone never sets completed_at; backfill it now for milestones
|
|
761
825
|
// imported as complete so the DB is internally coherent immediately after
|
|
762
826
|
// import (rather than relying on a later reconciliation pass that can't even
|
|
763
|
-
// see the drift when no SUMMARY file exists).
|
|
764
|
-
|
|
827
|
+
// see the drift when no SUMMARY file exists). #027: skip the backfill for an
|
|
828
|
+
// out-of-scope milestone that already existed — its DB status is authoritative.
|
|
829
|
+
if (IMPORT_COMPLETE_STATUSES.has(milestoneStatus) && (milestoneStatusAuthoritative || milestoneInserted)) {
|
|
765
830
|
const summaryPath = resolveMilestoneFile(basePath, milestoneId, 'SUMMARY');
|
|
766
|
-
|
|
831
|
+
// #1291: preserve an existing completion timestamp so a re-import backfills
|
|
832
|
+
// only rows that lack one, never re-stamping an already-complete milestone
|
|
833
|
+
// with the current import time. Same guard as the task path below.
|
|
834
|
+
updateMilestoneStatus(milestoneId, milestoneStatus, importCompletionTimestamp(summaryPath), true);
|
|
767
835
|
}
|
|
768
836
|
counts.milestones++;
|
|
769
837
|
|
|
@@ -783,11 +851,22 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
783
851
|
plan = parsePlan(planContent);
|
|
784
852
|
}
|
|
785
853
|
|
|
854
|
+
// #027: for an out-of-scope milestone, echo the existing DB status of a
|
|
855
|
+
// slice that already exists so the upsert's `ELSE excluded.status` branch
|
|
856
|
+
// becomes a no-op instead of flipping a reopened `pending` slice back to
|
|
857
|
+
// `complete` from a stale checkbox. New slices (not yet in the DB) take the
|
|
858
|
+
// parsed status regardless of scope.
|
|
859
|
+
const sliceRowExists = existingSliceStatus.has(sliceEntry.id);
|
|
860
|
+
const sliceStatusAuthoritative = milestoneStatusAuthoritative || !sliceRowExists;
|
|
861
|
+
const effectiveSliceStatus = sliceStatusAuthoritative
|
|
862
|
+
? sliceStatus
|
|
863
|
+
: existingSliceStatus.get(sliceEntry.id)!;
|
|
864
|
+
|
|
786
865
|
insertSlice({
|
|
787
866
|
id: sliceEntry.id,
|
|
788
867
|
milestoneId: milestoneId,
|
|
789
868
|
title: sliceEntry.title,
|
|
790
|
-
status:
|
|
869
|
+
status: effectiveSliceStatus,
|
|
791
870
|
risk: sliceEntry.risk,
|
|
792
871
|
depends: (sliceEntry.depends ?? []).map(d => d.replace(/^\[|\]$/g, '')).filter(d => /^[A-Za-z0-9][A-Za-z0-9-]*$/.test(d)),
|
|
793
872
|
demo: sliceEntry.demo,
|
|
@@ -798,20 +877,30 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
798
877
|
},
|
|
799
878
|
});
|
|
800
879
|
// insertSlice never sets completed_at; backfill it for slices imported as
|
|
801
|
-
// complete (same rationale as milestones above).
|
|
802
|
-
|
|
880
|
+
// complete (same rationale as milestones above). #027: skip when preserving
|
|
881
|
+
// an out-of-scope slice's existing DB status.
|
|
882
|
+
if (IMPORT_COMPLETE_STATUSES.has(sliceStatus) && sliceStatusAuthoritative) {
|
|
803
883
|
const sliceSummary = resolveSliceFile(basePath, milestoneId, sliceEntry.id, 'SUMMARY');
|
|
884
|
+
// #1291: preserve an existing completion timestamp so a re-import backfills
|
|
885
|
+
// only slices that lack one, never re-stamping an already-complete slice
|
|
886
|
+
// with the current import time. Same guard as the task path below.
|
|
804
887
|
updateSliceStatus(
|
|
805
888
|
milestoneId,
|
|
806
889
|
sliceEntry.id,
|
|
807
890
|
sliceStatus,
|
|
808
891
|
importCompletionTimestamp(sliceSummary),
|
|
892
|
+
true,
|
|
809
893
|
);
|
|
810
894
|
}
|
|
811
895
|
counts.slices++;
|
|
812
896
|
|
|
813
|
-
// Insert tasks from parsed plan
|
|
814
|
-
|
|
897
|
+
// Insert tasks from parsed plan.
|
|
898
|
+
// Sketch slices carry only a stub PLAN until refined; do not seed DB
|
|
899
|
+
// tasks from a placeholder <tasks> block (would falsely flip
|
|
900
|
+
// planning -> executing before the slice is decomposed). Once the
|
|
901
|
+
// `[sketch]` badge is removed by a real plan-slice, tasks import
|
|
902
|
+
// normally on the next pass. (#1286)
|
|
903
|
+
if (!plan || sliceEntry.isSketch) continue;
|
|
815
904
|
|
|
816
905
|
for (const taskEntry of plan.tasks) {
|
|
817
906
|
// Per K002: use 'complete' not 'done'
|
|
@@ -880,12 +969,20 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
880
969
|
);
|
|
881
970
|
}
|
|
882
971
|
|
|
972
|
+
// #027: same scope guard as slices — out-of-scope milestones echo existing
|
|
973
|
+
// DB task status so stale plan checkboxes cannot re-complete reopened tasks.
|
|
974
|
+
const taskRowExists = existingTaskStatus.has(`${sliceEntry.id}/${taskEntry.id}`);
|
|
975
|
+
const taskStatusAuthoritative = milestoneStatusAuthoritative || !taskRowExists;
|
|
976
|
+
const effectiveTaskStatus = taskStatusAuthoritative
|
|
977
|
+
? taskStatus
|
|
978
|
+
: existingTaskStatus.get(`${sliceEntry.id}/${taskEntry.id}`)!;
|
|
979
|
+
|
|
883
980
|
insertTask({
|
|
884
981
|
id: taskEntry.id,
|
|
885
982
|
sliceId: sliceEntry.id,
|
|
886
983
|
milestoneId: milestoneId,
|
|
887
984
|
title: taskEntry.title,
|
|
888
|
-
status:
|
|
985
|
+
status: effectiveTaskStatus,
|
|
889
986
|
planning: {
|
|
890
987
|
files: taskEntry.files ?? [],
|
|
891
988
|
verify: taskEntry.verify ?? '',
|
|
@@ -935,13 +1032,19 @@ export function migrateHierarchyToDb(basePath: string): {
|
|
|
935
1032
|
// checkbox (#1222); flat-phase checkboxes are authoritative without summary.
|
|
936
1033
|
return summaryAttestsCompletion || (t.done && !isLegacySliceLayout);
|
|
937
1034
|
});
|
|
938
|
-
|
|
1035
|
+
// #027: the same close guard as the backfill above — a stale slice
|
|
1036
|
+
// SUMMARY under an out-of-scope milestone must not upgrade a reopened
|
|
1037
|
+
// slice to complete. New slices stay authoritative.
|
|
1038
|
+
if (allTasksDone && hasSliceSummary && sliceStatusAuthoritative) {
|
|
939
1039
|
if (_getAdapter()) {
|
|
1040
|
+
// #1291: preserve an existing completion timestamp — this consistency
|
|
1041
|
+
// upgrade sets a completion time only when the row lacks one.
|
|
940
1042
|
updateSliceStatus(
|
|
941
1043
|
milestoneId,
|
|
942
1044
|
sliceEntry.id,
|
|
943
1045
|
'complete',
|
|
944
1046
|
importCompletionTimestamp(sliceSummaryPath),
|
|
1047
|
+
true,
|
|
945
1048
|
);
|
|
946
1049
|
process.stderr.write(
|
|
947
1050
|
`gsd-migrate: ${milestoneId}/${sliceEntry.id} all tasks + slice summary complete — upgrading slice to complete\n`,
|
|
@@ -10,198 +10,24 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import type { ExtensionAPI, ExtensionCommandContext } from "@gsd/pi-coding-agent";
|
|
13
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
14
|
-
import { join, dirname } from "node:path";
|
|
15
13
|
import { gsdRoot } from "../paths.js";
|
|
16
|
-
import { fileURLToPath } from "node:url";
|
|
17
14
|
import { showNextAction } from "../../shared/tui.js";
|
|
18
15
|
import {
|
|
19
16
|
notifyMigrateNeedsInteractiveMenu,
|
|
20
17
|
requiresInteractiveMenu,
|
|
21
18
|
} from "../command-feedback.js";
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
generatePreview,
|
|
27
|
-
writeGSDDirectory,
|
|
28
|
-
} from "./index.js";
|
|
29
|
-
|
|
30
|
-
import type { MigrationPreview, WrittenFiles } from "./writer.js";
|
|
31
|
-
import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
|
|
32
|
-
import { clearArtifacts, clearDecisions, clearRequirements, clearEngineHierarchy, transaction } from "../gsd-db.js";
|
|
33
|
-
import { migrateFromMarkdown } from "../md-importer.js";
|
|
34
|
-
import { deriveState, invalidateStateCache } from "../state.js";
|
|
35
|
-
import {
|
|
36
|
-
archiveLegacyPlanningDirectory,
|
|
37
|
-
verifyMigrationProjection,
|
|
38
|
-
writeMigrationAudit,
|
|
39
|
-
type LegacyArchiveResult,
|
|
40
|
-
type MigrationAuditResult,
|
|
41
|
-
type MigrationProjectionVerification,
|
|
42
|
-
} from "./audit.js";
|
|
43
|
-
import {
|
|
44
|
-
assertMigrationHasSlices,
|
|
45
|
-
assertMigrationTargetAvailable,
|
|
46
|
-
prepareMigrationTarget,
|
|
47
|
-
resolveMigrationPaths,
|
|
48
|
-
restoreMigrationTarget,
|
|
49
|
-
type MigrationBackup,
|
|
50
|
-
} from "./safety.js";
|
|
51
|
-
|
|
52
|
-
export type MigrationImportCounts = ReturnType<typeof migrateFromMarkdown>;
|
|
53
|
-
|
|
54
|
-
export interface MigrationExecutionResult {
|
|
55
|
-
backup: MigrationBackup;
|
|
56
|
-
written: WrittenFiles;
|
|
57
|
-
imported: MigrationImportCounts;
|
|
58
|
-
legacyArchive: LegacyArchiveResult;
|
|
59
|
-
verification: MigrationProjectionVerification;
|
|
60
|
-
audit: MigrationAuditResult;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function assertMigrationImportMatchesPreview(imported: MigrationImportCounts, preview: MigrationPreview): void {
|
|
64
|
-
const mismatches: string[] = [];
|
|
65
|
-
if (imported.decisions !== preview.decisions.total) {
|
|
66
|
-
mismatches.push(`decisions ${imported.decisions}/${preview.decisions.total}`);
|
|
67
|
-
}
|
|
68
|
-
if (imported.hierarchy.milestones !== preview.milestoneCount) {
|
|
69
|
-
mismatches.push(`milestones ${imported.hierarchy.milestones}/${preview.milestoneCount}`);
|
|
70
|
-
}
|
|
71
|
-
if (imported.hierarchy.slices !== preview.totalSlices) {
|
|
72
|
-
mismatches.push(`slices ${imported.hierarchy.slices}/${preview.totalSlices}`);
|
|
73
|
-
}
|
|
74
|
-
if (imported.hierarchy.tasks !== preview.totalTasks) {
|
|
75
|
-
mismatches.push(`tasks ${imported.hierarchy.tasks}/${preview.totalTasks}`);
|
|
76
|
-
}
|
|
77
|
-
if (imported.requirements !== preview.requirements.total) {
|
|
78
|
-
mismatches.push(`requirements ${imported.requirements}/${preview.requirements.total}`);
|
|
79
|
-
}
|
|
80
|
-
if (mismatches.length > 0) {
|
|
81
|
-
throw new Error(`migration DB import verification failed: ${mismatches.join(", ")}`);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
19
|
+
import { executeMigrationWrite, type MigrationExecutionResult } from "./execution.js";
|
|
20
|
+
import { createMigrationPlan } from "./plan.js";
|
|
21
|
+
import { buildMigrationPreviewSummary, buildReviewPrompt } from "./presentation.js";
|
|
22
|
+
import type { MigrationPreview } from "./writer.js";
|
|
84
23
|
|
|
85
|
-
export async function importWrittenMigrationToDb(
|
|
86
|
-
basePath: string,
|
|
87
|
-
preview?: MigrationPreview,
|
|
88
|
-
): Promise<MigrationImportCounts> {
|
|
89
|
-
const opened = await ensureDbOpen(basePath);
|
|
90
|
-
if (!opened) {
|
|
91
|
-
throw new Error(`failed to open or create the GSD database at ${basePath}`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
const counts = transaction(() => {
|
|
95
|
-
clearEngineHierarchy();
|
|
96
|
-
clearArtifacts();
|
|
97
|
-
clearDecisions();
|
|
98
|
-
clearRequirements();
|
|
99
|
-
const imported = migrateFromMarkdown(basePath);
|
|
100
|
-
if (preview) assertMigrationImportMatchesPreview(imported, preview);
|
|
101
|
-
return imported;
|
|
102
|
-
});
|
|
103
|
-
invalidateStateCache();
|
|
104
|
-
return counts;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export async function assertMigrationDbReadiness(
|
|
108
|
-
targetRoot: string,
|
|
109
|
-
preview: MigrationPreview,
|
|
110
|
-
): Promise<{ phase: string; registry: number }> {
|
|
111
|
-
invalidateStateCache();
|
|
112
|
-
const state = await deriveState(targetRoot);
|
|
113
|
-
const dbUnavailable = state.blockers.some((blocker) => blocker.includes("DB unavailable"));
|
|
114
|
-
if (dbUnavailable) {
|
|
115
|
-
throw new Error(`migration DB readiness failed: ${state.blockers.join("; ")}`);
|
|
116
|
-
}
|
|
117
|
-
if (state.registry.length !== preview.milestoneCount) {
|
|
118
|
-
throw new Error(`migration DB readiness failed: registry ${state.registry.length}/${preview.milestoneCount}`);
|
|
119
|
-
}
|
|
120
|
-
return {
|
|
121
|
-
phase: state.phase,
|
|
122
|
-
registry: state.registry.length,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export async function executeMigrationWrite(
|
|
127
|
-
sourcePath: string,
|
|
128
|
-
targetRoot: string,
|
|
129
|
-
project: ReturnType<typeof transformToGSD>,
|
|
130
|
-
preview: MigrationPreview,
|
|
131
|
-
startedAt: string = new Date().toISOString(),
|
|
132
|
-
): Promise<MigrationExecutionResult> {
|
|
133
|
-
const backup = prepareMigrationTarget(targetRoot);
|
|
134
|
-
|
|
135
|
-
try {
|
|
136
|
-
const written = await writeGSDDirectory(project, targetRoot);
|
|
137
|
-
const legacyArchive = await archiveLegacyPlanningDirectory(sourcePath, targetRoot);
|
|
138
|
-
const imported = await importWrittenMigrationToDb(targetRoot, preview);
|
|
139
|
-
const verification = await verifyMigrationProjection(targetRoot, preview);
|
|
140
|
-
verification.dbReadiness = await assertMigrationDbReadiness(targetRoot, preview);
|
|
141
|
-
const audit = await writeMigrationAudit({
|
|
142
|
-
sourcePath,
|
|
143
|
-
targetRoot,
|
|
144
|
-
backupPath: backup.backupPath,
|
|
145
|
-
preview,
|
|
146
|
-
written,
|
|
147
|
-
imported,
|
|
148
|
-
legacyArchive,
|
|
149
|
-
verification,
|
|
150
|
-
startedAt,
|
|
151
|
-
completedAt: new Date().toISOString(),
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
return { backup, written, imported, legacyArchive, verification, audit };
|
|
155
|
-
} catch (err) {
|
|
156
|
-
restoreMigrationTarget(backup);
|
|
157
|
-
throw err;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/** Format preview stats for embedding in the review prompt. */
|
|
162
|
-
function formatPreviewStats(preview: MigrationPreview): string {
|
|
163
|
-
const lines = [
|
|
164
|
-
`- Decisions: ${preview.decisions.total}`,
|
|
165
|
-
`- Milestones: ${preview.milestoneCount}`,
|
|
166
|
-
`- Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
|
|
167
|
-
`- Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
|
|
168
|
-
];
|
|
169
|
-
if (preview.requirements.total > 0) {
|
|
170
|
-
lines.push(
|
|
171
|
-
`- Requirements: ${preview.requirements.total} (${preview.requirements.validated} validated, ${preview.requirements.active} active, ${preview.requirements.deferred} deferred, ${preview.requirements.outOfScope} out of scope)`,
|
|
172
|
-
);
|
|
173
|
-
}
|
|
174
|
-
if (preview.migrationInputs) {
|
|
175
|
-
lines.push(`- Legacy inputs: ${preview.migrationInputs.milestonePhaseDirs} milestone phase dir(s), ${preview.migrationInputs.decisions} decision file(s), ${preview.migrationInputs.seeds} seed file(s)`);
|
|
176
|
-
}
|
|
177
|
-
return lines.join("\n");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
/** Load and interpolate the review-migration prompt template. */
|
|
181
|
-
function buildReviewPrompt(
|
|
182
|
-
sourcePath: string,
|
|
183
|
-
gsdPath: string,
|
|
184
|
-
preview: MigrationPreview,
|
|
185
|
-
): string {
|
|
186
|
-
const promptsDir = join(dirname(fileURLToPath(import.meta.url)), "..", "prompts");
|
|
187
|
-
const templatePath = join(promptsDir, "review-migration.md");
|
|
188
|
-
let content = readFileSync(templatePath, "utf-8");
|
|
189
|
-
|
|
190
|
-
content = content.replaceAll("{{sourcePath}}", sourcePath);
|
|
191
|
-
content = content.replaceAll("{{gsdPath}}", gsdPath);
|
|
192
|
-
content = content.replaceAll("{{previewStats}}", formatPreviewStats(preview));
|
|
193
|
-
|
|
194
|
-
return content.trim();
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/** Dispatch the review prompt to the agent. */
|
|
198
24
|
function dispatchReview(
|
|
199
25
|
pi: ExtensionAPI,
|
|
200
26
|
sourcePath: string,
|
|
201
27
|
gsdPath: string,
|
|
202
28
|
preview: MigrationPreview,
|
|
203
29
|
): void {
|
|
204
|
-
const prompt = buildReviewPrompt(sourcePath, gsdPath, preview);
|
|
30
|
+
const prompt = buildReviewPrompt({ sourcePath, gsdPath, preview });
|
|
205
31
|
|
|
206
32
|
pi.sendMessage(
|
|
207
33
|
{
|
|
@@ -218,34 +44,28 @@ export async function handleMigrate(
|
|
|
218
44
|
ctx: ExtensionCommandContext,
|
|
219
45
|
pi: ExtensionAPI,
|
|
220
46
|
): Promise<void> {
|
|
221
|
-
|
|
222
|
-
const { sourcePath, targetRoot } =
|
|
47
|
+
const plan = await createMigrationPlan(args);
|
|
48
|
+
const { sourcePath, targetRoot } = plan;
|
|
223
49
|
|
|
224
|
-
if (
|
|
50
|
+
if (plan.status === "missing-source") {
|
|
225
51
|
ctx.ui.notify(
|
|
226
52
|
`Directory not found: ${sourcePath}\n\n` +
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
53
|
+
"Migration converts a .planning/ directory (from older GSD versions) into .gsd/ format.\n" +
|
|
54
|
+
"If you are starting a new project, use /gsd:new-project instead.\n" +
|
|
55
|
+
"If migrating, ensure the path contains a .planning/ directory.",
|
|
230
56
|
"error",
|
|
231
57
|
);
|
|
232
58
|
return;
|
|
233
59
|
}
|
|
234
60
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const warnings = validation.issues.filter((i) => i.severity === "warning");
|
|
239
|
-
const fatals = validation.issues.filter((i) => i.severity === "fatal");
|
|
240
|
-
|
|
241
|
-
for (const w of warnings) {
|
|
242
|
-
ctx.ui.notify(`⚠ ${w.message} (${w.file})`, "warning");
|
|
61
|
+
for (const warning of plan.warnings) {
|
|
62
|
+
ctx.ui.notify(`⚠ ${warning.message} (${warning.file})`, "warning");
|
|
243
63
|
}
|
|
244
|
-
for (const
|
|
245
|
-
ctx.ui.notify(`✖ ${
|
|
64
|
+
for (const fatal of plan.fatals) {
|
|
65
|
+
ctx.ui.notify(`✖ ${fatal.message} (${fatal.file})`, "error");
|
|
246
66
|
}
|
|
247
67
|
|
|
248
|
-
if (
|
|
68
|
+
if (plan.status === "invalid") {
|
|
249
69
|
ctx.ui.notify(
|
|
250
70
|
"Migration blocked — fix the fatal issues above before retrying.",
|
|
251
71
|
"error",
|
|
@@ -253,41 +73,15 @@ export async function handleMigrate(
|
|
|
253
73
|
return;
|
|
254
74
|
}
|
|
255
75
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const project = transformToGSD(parsed);
|
|
259
|
-
const preview = generatePreview(project);
|
|
260
|
-
try {
|
|
261
|
-
assertMigrationHasSlices(preview);
|
|
262
|
-
await assertMigrationTargetAvailable(targetRoot);
|
|
263
|
-
} catch (err) {
|
|
264
|
-
ctx.ui.notify((err as Error).message, "error");
|
|
76
|
+
if (plan.status === "blocked") {
|
|
77
|
+
ctx.ui.notify(plan.message, "error");
|
|
265
78
|
return;
|
|
266
79
|
}
|
|
267
80
|
|
|
268
|
-
|
|
269
|
-
const lines: string[] = [
|
|
270
|
-
`Decisions: ${preview.decisions.total}`,
|
|
271
|
-
`Milestones: ${preview.milestoneCount}`,
|
|
272
|
-
`Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
|
|
273
|
-
`Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
|
|
274
|
-
];
|
|
81
|
+
const { project, preview } = plan;
|
|
275
82
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
`Requirements: ${preview.requirements.total} (${preview.requirements.validated} validated, ${preview.requirements.active} active, ${preview.requirements.deferred} deferred, ${preview.requirements.outOfScope} out of scope)`,
|
|
279
|
-
);
|
|
280
|
-
}
|
|
281
|
-
if (preview.migrationInputs) {
|
|
282
|
-
lines.push(`Legacy inputs: ${preview.migrationInputs.milestonePhaseDirs} milestone phase dir(s), ${preview.migrationInputs.decisions} decision file(s), ${preview.migrationInputs.seeds} seed file(s)`);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
const targetGsdExists = existsSync(gsdRoot(targetRoot));
|
|
286
|
-
if (targetGsdExists) {
|
|
287
|
-
lines.push("");
|
|
288
|
-
lines.push(`⚠ A .gsd directory already exists at ${gsdRoot(targetRoot)}.`);
|
|
289
|
-
lines.push("It will be backed up, deleted, and rewritten fresh before DB import.");
|
|
290
|
-
}
|
|
83
|
+
// ── Build preview text ─────────────────────────────────────────────────────
|
|
84
|
+
const lines = buildMigrationPreviewSummary(preview, targetRoot);
|
|
291
85
|
|
|
292
86
|
// ── Confirmation via showNextAction ────────────────────────────────────────
|
|
293
87
|
if (requiresInteractiveMenu(ctx, false)) {
|