@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.5c1a3ff2
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 +10 -8
- 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 +18 -49
- 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/artifact-verification.js +3 -4
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
- 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 +125 -18
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -5
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
- 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/constants.js +12 -13
- package/dist/resources/extensions/gsd/context-masker.js +97 -21
- 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 +26 -4
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -6
- package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
- package/dist/resources/extensions/gsd/git-service.js +19 -7
- package/dist/resources/extensions/gsd/gsd-db.js +187 -45
- package/dist/resources/extensions/gsd/guided-flow.js +38 -13
- package/dist/resources/extensions/gsd/markdown-renderer.js +17 -13
- package/dist/resources/extensions/gsd/md-importer.js +107 -20
- 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 +12 -17
- package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
- package/dist/resources/extensions/gsd/model-router.js +11 -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 +55 -11
- package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
- package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
- package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
- package/dist/resources/extensions/gsd/preferences-types.js +5 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
- package/dist/resources/extensions/gsd/preferences.js +17 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
- 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/skill-activation.js +17 -3
- 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/stop-notice.js +15 -1
- package/dist/resources/extensions/gsd/sync-lock.js +13 -7
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
- 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/reopen-milestone.js +14 -5
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
- package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
- 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-context-composer.js +28 -5
- 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/workflow-projections.js +2 -3
- package/dist/resources/extensions/gsd/workspace.js +2 -1
- 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 +8 -8
- 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 +8 -8
- 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/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +1 -0
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- 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 +15 -2
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +5 -5
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
- 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/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +119 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +107 -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 +25 -1
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +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 +18 -49
- 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/artifact-verification.ts +3 -8
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
- 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 +142 -16
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -10
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
- 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/constants.ts +14 -13
- package/src/resources/extensions/gsd/context-masker.ts +98 -2
- 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 +26 -4
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -5
- package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
- package/src/resources/extensions/gsd/git-service.ts +19 -6
- package/src/resources/extensions/gsd/gsd-db.ts +255 -52
- package/src/resources/extensions/gsd/guided-flow.ts +48 -12
- package/src/resources/extensions/gsd/markdown-renderer.ts +25 -21
- package/src/resources/extensions/gsd/md-importer.ts +114 -16
- 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 +12 -20
- package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
- package/src/resources/extensions/gsd/model-router.ts +12 -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 +62 -11
- package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
- package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
- package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
- package/src/resources/extensions/gsd/preferences.ts +25 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
- 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/skill-activation.ts +17 -3
- 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/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/templates/PREFERENCES.md +5 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
- 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 +362 -1
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
- package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -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/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/integration/paths.test.ts +22 -4
- package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
- 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/milestone-leases.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- 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/parallel-skill-prompt-integration.test.ts +7 -5
- 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 +29 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
- 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/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
- package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
- 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/system-context-message-routing.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -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/workflow-projections.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
- 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/reopen-milestone.ts +24 -5
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
- package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
- 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-context-composer.ts +34 -8
- 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/workflow-projections.ts +2 -3
- package/src/resources/extensions/gsd/workspace.ts +2 -1
- 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/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_ssgManifest.js +0 -0
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
// Exports: parseDecisionsTable, parseRequirementsSections, migrateFromMarkdown
|
|
6
6
|
import { readFileSync, readdirSync, existsSync, statSync } from 'node:fs';
|
|
7
7
|
import { join, basename, dirname } from 'node:path';
|
|
8
|
-
import { upsertDecision, upsertRequirement, insertArtifact, insertMilestone, insertSlice, insertTask, transaction, updateMilestoneStatus, updateSliceStatus, _getAdapter, } from './gsd-db.js';
|
|
8
|
+
import { upsertDecision, upsertRequirement, insertArtifact, insertMilestone, insertSlice, insertTask, transaction, updateMilestoneStatus, updateSliceStatus, getMilestoneSlices, getSliceTasks, _getAdapter, } from './gsd-db.js';
|
|
9
9
|
import { openWorkflowDatabasePath } from './db-workspace.js';
|
|
10
|
-
import { resolveGsdRootFile, resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, legacyMilestonesDir, gsdRoot, resolveTaskFiles, resolveMilestonePath, } from './paths.js';
|
|
10
|
+
import { resolveGsdRootFile, resolveMilestoneFile, resolveSliceFile, resolveSlicePath, resolveTasksDir, legacyMilestonesDir, gsdRoot, resolveTaskFiles, resolveTaskFile, resolveMilestonePath, } from './paths.js';
|
|
11
11
|
import { findMilestoneIds } from './guided-flow.js';
|
|
12
12
|
import { milestoneIdToPhaseNum } from './layout-policy.js';
|
|
13
13
|
import { parseRoadmap, parsePlan } from './parsers-legacy.js';
|
|
@@ -16,6 +16,26 @@ import { logWarning } from './workflow-logger.js';
|
|
|
16
16
|
// ─── DECISIONS.md Parser ───────────────────────────────────────────────────
|
|
17
17
|
const VALID_MADE_BY = new Set(['human', 'agent', 'collaborative']);
|
|
18
18
|
const IMPORT_COMPLETE_STATUSES = new Set(['complete', 'done']);
|
|
19
|
+
/**
|
|
20
|
+
* Derive the set of milestone ids a projection entry's `entities` touch. Marker
|
|
21
|
+
* entity ids are fully-qualified DB ids (`M001`, `M001/S01`, `M001/S01/T01`), so
|
|
22
|
+
* the milestone id is always the first `/`-segment — independent of the on-disk
|
|
23
|
+
* layout (legacy `milestones/<MID>/…` vs flat `phases/NN-slug/…`). The
|
|
24
|
+
* external-edit drift repairs (#027) feed this into
|
|
25
|
+
* `migrateHierarchyToDb(..., { statusAuthoritativeMilestones })` to scope status
|
|
26
|
+
* authority to exactly the milestone(s) a drifted file projects. Empty/blank
|
|
27
|
+
* entries are dropped, so an entity-less entry yields an empty set (repair then
|
|
28
|
+
* preserves DB status everywhere — fail toward the DB, not markdown).
|
|
29
|
+
*/
|
|
30
|
+
export function milestoneIdsFromEntities(entities) {
|
|
31
|
+
const ids = new Set();
|
|
32
|
+
for (const e of entities) {
|
|
33
|
+
const milestoneId = e.split('/')[0];
|
|
34
|
+
if (milestoneId)
|
|
35
|
+
ids.add(milestoneId);
|
|
36
|
+
}
|
|
37
|
+
return ids;
|
|
38
|
+
}
|
|
19
39
|
/**
|
|
20
40
|
* Completion timestamp for an entity imported as complete: the SUMMARY.md mtime
|
|
21
41
|
* when one exists (deterministic, matches the completion drift handler), else
|
|
@@ -539,11 +559,28 @@ function findFileByPrefixAndSuffix(dir, idPrefix, suffix) {
|
|
|
539
559
|
* Uses INSERT OR IGNORE for idempotency. Insert order: milestones → slices → tasks.
|
|
540
560
|
* Ghost milestones (dirs with no CONTEXT, ROADMAP, or SUMMARY) are skipped.
|
|
541
561
|
*
|
|
562
|
+
* `opts.statusAuthoritativeMilestones` narrows *status* authority. It exists for
|
|
563
|
+
* the scoped external-edit drift repair: detection knows exactly which
|
|
564
|
+
* projection file drifted, but this import walks the whole tree. Without scoping,
|
|
565
|
+
* an unrelated file that is stale from gsd-pi's own miss (a forgotten render)
|
|
566
|
+
* rides along with markdown authority it was never granted and its stale checked
|
|
567
|
+
* checkbox silently reverts a reopened slice/milestone in the DB (#027).
|
|
568
|
+
*
|
|
569
|
+
* - opts absent → full markdown authority for every milestone (initial migration,
|
|
570
|
+
* gsd-core full import, /gsd recover rebuild). Behavior is identical to before.
|
|
571
|
+
* - opts present → for a milestone NOT in the set whose DB row *already exists*,
|
|
572
|
+
* the existing DB status is preserved: the slice upsert is fed the current DB
|
|
573
|
+
* status (so a stale `complete` checkbox can't overwrite a reopened `pending`),
|
|
574
|
+
* and the complete-status backfills are skipped. Milestone rows are already
|
|
575
|
+
* protected by INSERT OR IGNORE. Rows that do not exist yet are inserted with
|
|
576
|
+
* the parsed status regardless of scope (new content is new content).
|
|
577
|
+
*
|
|
542
578
|
* Returns count of inserted hierarchy items.
|
|
543
579
|
*/
|
|
544
|
-
export function migrateHierarchyToDb(basePath) {
|
|
580
|
+
export function migrateHierarchyToDb(basePath, opts) {
|
|
545
581
|
const counts = { milestones: 0, slices: 0, tasks: 0 };
|
|
546
582
|
const milestoneIds = findMilestoneIds(basePath);
|
|
583
|
+
const statusScope = opts?.statusAuthoritativeMilestones;
|
|
547
584
|
for (const milestoneId of milestoneIds) {
|
|
548
585
|
// Check for ghost milestones — skip dirs with no meaningful content
|
|
549
586
|
const roadmapPath = resolveMilestoneFile(basePath, milestoneId, 'ROADMAP');
|
|
@@ -600,8 +637,29 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
600
637
|
boundaryMapSection = nextHeading >= 0 ? afterBm.slice(0, nextHeading).trim() : afterBm.trim();
|
|
601
638
|
}
|
|
602
639
|
}
|
|
603
|
-
//
|
|
604
|
-
|
|
640
|
+
// #027: when a status scope is supplied, a milestone outside it keeps DB
|
|
641
|
+
// status authority for rows that already exist — only the drifted file's
|
|
642
|
+
// milestone(s) may drive status closes from checkboxes. Absent scope, every
|
|
643
|
+
// milestone is authoritative (unchanged full-import behavior).
|
|
644
|
+
const milestoneStatusAuthoritative = !statusScope || statusScope.has(milestoneId);
|
|
645
|
+
// Snapshot existing slice statuses once (only needed when preserving DB
|
|
646
|
+
// authority for this milestone) so the upsert can echo them back instead of
|
|
647
|
+
// flipping an open slice closed from a stale checkbox.
|
|
648
|
+
const existingSliceStatus = new Map();
|
|
649
|
+
const existingTaskStatus = new Map();
|
|
650
|
+
if (!milestoneStatusAuthoritative) {
|
|
651
|
+
for (const s of getMilestoneSlices(milestoneId)) {
|
|
652
|
+
existingSliceStatus.set(s.id, s.status);
|
|
653
|
+
for (const t of getSliceTasks(milestoneId, s.id)) {
|
|
654
|
+
existingTaskStatus.set(`${s.id}/${t.id}`, t.status);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
// Insert milestone (FK parent — must come first). INSERT OR IGNORE: an
|
|
659
|
+
// existing milestone row is never overwritten, so DB status is already
|
|
660
|
+
// preserved for out-of-scope milestones. `inserted` tells us whether this
|
|
661
|
+
// row is new (parsed status applies) vs pre-existing (backfill gated below).
|
|
662
|
+
const milestoneInserted = insertMilestone({
|
|
605
663
|
id: milestoneId,
|
|
606
664
|
title: milestoneTitle,
|
|
607
665
|
status: milestoneStatus,
|
|
@@ -615,10 +673,14 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
615
673
|
// insertMilestone never sets completed_at; backfill it now for milestones
|
|
616
674
|
// imported as complete so the DB is internally coherent immediately after
|
|
617
675
|
// import (rather than relying on a later reconciliation pass that can't even
|
|
618
|
-
// see the drift when no SUMMARY file exists).
|
|
619
|
-
|
|
676
|
+
// see the drift when no SUMMARY file exists). #027: skip the backfill for an
|
|
677
|
+
// out-of-scope milestone that already existed — its DB status is authoritative.
|
|
678
|
+
if (IMPORT_COMPLETE_STATUSES.has(milestoneStatus) && (milestoneStatusAuthoritative || milestoneInserted)) {
|
|
620
679
|
const summaryPath = resolveMilestoneFile(basePath, milestoneId, 'SUMMARY');
|
|
621
|
-
|
|
680
|
+
// #1291: preserve an existing completion timestamp so a re-import backfills
|
|
681
|
+
// only rows that lack one, never re-stamping an already-complete milestone
|
|
682
|
+
// with the current import time. Same guard as the task path below.
|
|
683
|
+
updateMilestoneStatus(milestoneId, milestoneStatus, importCompletionTimestamp(summaryPath), true);
|
|
622
684
|
}
|
|
623
685
|
counts.milestones++;
|
|
624
686
|
// Parse roadmap for slices
|
|
@@ -635,11 +697,21 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
635
697
|
const planContent = readFileSync(planPath, 'utf-8');
|
|
636
698
|
plan = parsePlan(planContent);
|
|
637
699
|
}
|
|
700
|
+
// #027: for an out-of-scope milestone, echo the existing DB status of a
|
|
701
|
+
// slice that already exists so the upsert's `ELSE excluded.status` branch
|
|
702
|
+
// becomes a no-op instead of flipping a reopened `pending` slice back to
|
|
703
|
+
// `complete` from a stale checkbox. New slices (not yet in the DB) take the
|
|
704
|
+
// parsed status regardless of scope.
|
|
705
|
+
const sliceRowExists = existingSliceStatus.has(sliceEntry.id);
|
|
706
|
+
const sliceStatusAuthoritative = milestoneStatusAuthoritative || !sliceRowExists;
|
|
707
|
+
const effectiveSliceStatus = sliceStatusAuthoritative
|
|
708
|
+
? sliceStatus
|
|
709
|
+
: existingSliceStatus.get(sliceEntry.id);
|
|
638
710
|
insertSlice({
|
|
639
711
|
id: sliceEntry.id,
|
|
640
712
|
milestoneId: milestoneId,
|
|
641
713
|
title: sliceEntry.title,
|
|
642
|
-
status:
|
|
714
|
+
status: effectiveSliceStatus,
|
|
643
715
|
risk: sliceEntry.risk,
|
|
644
716
|
depends: (sliceEntry.depends ?? []).map(d => d.replace(/^\[|\]$/g, '')).filter(d => /^[A-Za-z0-9][A-Za-z0-9-]*$/.test(d)),
|
|
645
717
|
demo: sliceEntry.demo,
|
|
@@ -650,10 +722,14 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
650
722
|
},
|
|
651
723
|
});
|
|
652
724
|
// insertSlice never sets completed_at; backfill it for slices imported as
|
|
653
|
-
// complete (same rationale as milestones above).
|
|
654
|
-
|
|
725
|
+
// complete (same rationale as milestones above). #027: skip when preserving
|
|
726
|
+
// an out-of-scope slice's existing DB status.
|
|
727
|
+
if (IMPORT_COMPLETE_STATUSES.has(sliceStatus) && sliceStatusAuthoritative) {
|
|
655
728
|
const sliceSummary = resolveSliceFile(basePath, milestoneId, sliceEntry.id, 'SUMMARY');
|
|
656
|
-
|
|
729
|
+
// #1291: preserve an existing completion timestamp so a re-import backfills
|
|
730
|
+
// only slices that lack one, never re-stamping an already-complete slice
|
|
731
|
+
// with the current import time. Same guard as the task path below.
|
|
732
|
+
updateSliceStatus(milestoneId, sliceEntry.id, sliceStatus, importCompletionTimestamp(sliceSummary), true);
|
|
657
733
|
}
|
|
658
734
|
counts.slices++;
|
|
659
735
|
// Insert tasks from parsed plan.
|
|
@@ -686,8 +762,7 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
686
762
|
legacyTasksDir = isLegacySlice
|
|
687
763
|
? resolveTasksDir(basePath, milestoneId, sliceEntry.id)
|
|
688
764
|
: null;
|
|
689
|
-
|
|
690
|
-
taskSummaryFile = join(summaryDir, `${taskEntry.id}-SUMMARY.md`);
|
|
765
|
+
taskSummaryFile = resolveTaskFile(basePath, milestoneId, sliceEntry.id, taskEntry.id, 'SUMMARY');
|
|
691
766
|
}
|
|
692
767
|
const hasTaskSummary = taskSummaryFile !== null && existsSync(taskSummaryFile);
|
|
693
768
|
// Pre-migration consistency (legacy tasks/ layout only): if a task is
|
|
@@ -707,9 +782,9 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
707
782
|
// first execute-task. The surviving SUMMARY wins over a stale checkbox.
|
|
708
783
|
// reopen-task removes the SUMMARY, so this never re-completes an
|
|
709
784
|
// intentionally reopened task.
|
|
710
|
-
// Flat-phase summaries are phase-scoped
|
|
711
|
-
//
|
|
712
|
-
//
|
|
785
|
+
// Flat-phase summaries are phase-scoped; when a milestone has multiple
|
|
786
|
+
// slices, require the summary parent frontmatter to match so one slice's
|
|
787
|
+
// completion does not attest a sibling's same-named task.
|
|
713
788
|
let summaryAttestsCompletion = hasTaskSummary;
|
|
714
789
|
if (summaryAttestsCompletion && !isLegacySlice && roadmap.slices.length > 1 && taskSummaryFile) {
|
|
715
790
|
try {
|
|
@@ -724,12 +799,19 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
724
799
|
taskStatus = 'complete';
|
|
725
800
|
process.stderr.write(`gsd-migrate: ${milestoneId}/${sliceEntry.id}/${taskEntry.id} unchecked in plan but SUMMARY.md present — importing as complete (#1222)\n`);
|
|
726
801
|
}
|
|
802
|
+
// #027: same scope guard as slices — out-of-scope milestones echo existing
|
|
803
|
+
// DB task status so stale plan checkboxes cannot re-complete reopened tasks.
|
|
804
|
+
const taskRowExists = existingTaskStatus.has(`${sliceEntry.id}/${taskEntry.id}`);
|
|
805
|
+
const taskStatusAuthoritative = milestoneStatusAuthoritative || !taskRowExists;
|
|
806
|
+
const effectiveTaskStatus = taskStatusAuthoritative
|
|
807
|
+
? taskStatus
|
|
808
|
+
: existingTaskStatus.get(`${sliceEntry.id}/${taskEntry.id}`);
|
|
727
809
|
insertTask({
|
|
728
810
|
id: taskEntry.id,
|
|
729
811
|
sliceId: sliceEntry.id,
|
|
730
812
|
milestoneId: milestoneId,
|
|
731
813
|
title: taskEntry.title,
|
|
732
|
-
status:
|
|
814
|
+
status: effectiveTaskStatus,
|
|
733
815
|
planning: {
|
|
734
816
|
files: taskEntry.files ?? [],
|
|
735
817
|
verify: taskEntry.verify ?? '',
|
|
@@ -779,9 +861,14 @@ export function migrateHierarchyToDb(basePath) {
|
|
|
779
861
|
// checkbox (#1222); flat-phase checkboxes are authoritative without summary.
|
|
780
862
|
return summaryAttestsCompletion || (t.done && !isLegacySliceLayout);
|
|
781
863
|
});
|
|
782
|
-
|
|
864
|
+
// #027: the same close guard as the backfill above — a stale slice
|
|
865
|
+
// SUMMARY under an out-of-scope milestone must not upgrade a reopened
|
|
866
|
+
// slice to complete. New slices stay authoritative.
|
|
867
|
+
if (allTasksDone && hasSliceSummary && sliceStatusAuthoritative) {
|
|
783
868
|
if (_getAdapter()) {
|
|
784
|
-
|
|
869
|
+
// #1291: preserve an existing completion timestamp — this consistency
|
|
870
|
+
// upgrade sets a completion time only when the row lacks one.
|
|
871
|
+
updateSliceStatus(milestoneId, sliceEntry.id, 'complete', importCompletionTimestamp(sliceSummaryPath), true);
|
|
785
872
|
process.stderr.write(`gsd-migrate: ${milestoneId}/${sliceEntry.id} all tasks + slice summary complete — upgrading slice to complete\n`);
|
|
786
873
|
}
|
|
787
874
|
}
|
|
@@ -8,129 +8,14 @@
|
|
|
8
8
|
* After a successful write, offers a read-only review that audits the output
|
|
9
9
|
* for gsd-pi standards compliance.
|
|
10
10
|
*/
|
|
11
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
12
|
-
import { join, dirname } from "node:path";
|
|
13
11
|
import { gsdRoot } from "../paths.js";
|
|
14
|
-
import { fileURLToPath } from "node:url";
|
|
15
12
|
import { showNextAction } from "../../shared/tui.js";
|
|
16
13
|
import { notifyMigrateNeedsInteractiveMenu, requiresInteractiveMenu, } from "../command-feedback.js";
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { migrateFromMarkdown } from "../md-importer.js";
|
|
21
|
-
import { deriveState, invalidateStateCache } from "../state.js";
|
|
22
|
-
import { archiveLegacyPlanningDirectory, verifyMigrationProjection, writeMigrationAudit, } from "./audit.js";
|
|
23
|
-
import { assertMigrationHasSlices, assertMigrationTargetAvailable, prepareMigrationTarget, resolveMigrationPaths, restoreMigrationTarget, } from "./safety.js";
|
|
24
|
-
function assertMigrationImportMatchesPreview(imported, preview) {
|
|
25
|
-
const mismatches = [];
|
|
26
|
-
if (imported.decisions !== preview.decisions.total) {
|
|
27
|
-
mismatches.push(`decisions ${imported.decisions}/${preview.decisions.total}`);
|
|
28
|
-
}
|
|
29
|
-
if (imported.hierarchy.milestones !== preview.milestoneCount) {
|
|
30
|
-
mismatches.push(`milestones ${imported.hierarchy.milestones}/${preview.milestoneCount}`);
|
|
31
|
-
}
|
|
32
|
-
if (imported.hierarchy.slices !== preview.totalSlices) {
|
|
33
|
-
mismatches.push(`slices ${imported.hierarchy.slices}/${preview.totalSlices}`);
|
|
34
|
-
}
|
|
35
|
-
if (imported.hierarchy.tasks !== preview.totalTasks) {
|
|
36
|
-
mismatches.push(`tasks ${imported.hierarchy.tasks}/${preview.totalTasks}`);
|
|
37
|
-
}
|
|
38
|
-
if (imported.requirements !== preview.requirements.total) {
|
|
39
|
-
mismatches.push(`requirements ${imported.requirements}/${preview.requirements.total}`);
|
|
40
|
-
}
|
|
41
|
-
if (mismatches.length > 0) {
|
|
42
|
-
throw new Error(`migration DB import verification failed: ${mismatches.join(", ")}`);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
export async function importWrittenMigrationToDb(basePath, preview) {
|
|
46
|
-
const opened = await ensureDbOpen(basePath);
|
|
47
|
-
if (!opened) {
|
|
48
|
-
throw new Error(`failed to open or create the GSD database at ${basePath}`);
|
|
49
|
-
}
|
|
50
|
-
const counts = transaction(() => {
|
|
51
|
-
clearEngineHierarchy();
|
|
52
|
-
clearArtifacts();
|
|
53
|
-
clearDecisions();
|
|
54
|
-
clearRequirements();
|
|
55
|
-
const imported = migrateFromMarkdown(basePath);
|
|
56
|
-
if (preview)
|
|
57
|
-
assertMigrationImportMatchesPreview(imported, preview);
|
|
58
|
-
return imported;
|
|
59
|
-
});
|
|
60
|
-
invalidateStateCache();
|
|
61
|
-
return counts;
|
|
62
|
-
}
|
|
63
|
-
export async function assertMigrationDbReadiness(targetRoot, preview) {
|
|
64
|
-
invalidateStateCache();
|
|
65
|
-
const state = await deriveState(targetRoot);
|
|
66
|
-
const dbUnavailable = state.blockers.some((blocker) => blocker.includes("DB unavailable"));
|
|
67
|
-
if (dbUnavailable) {
|
|
68
|
-
throw new Error(`migration DB readiness failed: ${state.blockers.join("; ")}`);
|
|
69
|
-
}
|
|
70
|
-
if (state.registry.length !== preview.milestoneCount) {
|
|
71
|
-
throw new Error(`migration DB readiness failed: registry ${state.registry.length}/${preview.milestoneCount}`);
|
|
72
|
-
}
|
|
73
|
-
return {
|
|
74
|
-
phase: state.phase,
|
|
75
|
-
registry: state.registry.length,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
export async function executeMigrationWrite(sourcePath, targetRoot, project, preview, startedAt = new Date().toISOString()) {
|
|
79
|
-
const backup = prepareMigrationTarget(targetRoot);
|
|
80
|
-
try {
|
|
81
|
-
const written = await writeGSDDirectory(project, targetRoot);
|
|
82
|
-
const legacyArchive = await archiveLegacyPlanningDirectory(sourcePath, targetRoot);
|
|
83
|
-
const imported = await importWrittenMigrationToDb(targetRoot, preview);
|
|
84
|
-
const verification = await verifyMigrationProjection(targetRoot, preview);
|
|
85
|
-
verification.dbReadiness = await assertMigrationDbReadiness(targetRoot, preview);
|
|
86
|
-
const audit = await writeMigrationAudit({
|
|
87
|
-
sourcePath,
|
|
88
|
-
targetRoot,
|
|
89
|
-
backupPath: backup.backupPath,
|
|
90
|
-
preview,
|
|
91
|
-
written,
|
|
92
|
-
imported,
|
|
93
|
-
legacyArchive,
|
|
94
|
-
verification,
|
|
95
|
-
startedAt,
|
|
96
|
-
completedAt: new Date().toISOString(),
|
|
97
|
-
});
|
|
98
|
-
return { backup, written, imported, legacyArchive, verification, audit };
|
|
99
|
-
}
|
|
100
|
-
catch (err) {
|
|
101
|
-
restoreMigrationTarget(backup);
|
|
102
|
-
throw err;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
/** Format preview stats for embedding in the review prompt. */
|
|
106
|
-
function formatPreviewStats(preview) {
|
|
107
|
-
const lines = [
|
|
108
|
-
`- Decisions: ${preview.decisions.total}`,
|
|
109
|
-
`- Milestones: ${preview.milestoneCount}`,
|
|
110
|
-
`- Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
|
|
111
|
-
`- Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
|
|
112
|
-
];
|
|
113
|
-
if (preview.requirements.total > 0) {
|
|
114
|
-
lines.push(`- Requirements: ${preview.requirements.total} (${preview.requirements.validated} validated, ${preview.requirements.active} active, ${preview.requirements.deferred} deferred, ${preview.requirements.outOfScope} out of scope)`);
|
|
115
|
-
}
|
|
116
|
-
if (preview.migrationInputs) {
|
|
117
|
-
lines.push(`- Legacy inputs: ${preview.migrationInputs.milestonePhaseDirs} milestone phase dir(s), ${preview.migrationInputs.decisions} decision file(s), ${preview.migrationInputs.seeds} seed file(s)`);
|
|
118
|
-
}
|
|
119
|
-
return lines.join("\n");
|
|
120
|
-
}
|
|
121
|
-
/** Load and interpolate the review-migration prompt template. */
|
|
122
|
-
function buildReviewPrompt(sourcePath, gsdPath, preview) {
|
|
123
|
-
const promptsDir = join(dirname(fileURLToPath(import.meta.url)), "..", "prompts");
|
|
124
|
-
const templatePath = join(promptsDir, "review-migration.md");
|
|
125
|
-
let content = readFileSync(templatePath, "utf-8");
|
|
126
|
-
content = content.replaceAll("{{sourcePath}}", sourcePath);
|
|
127
|
-
content = content.replaceAll("{{gsdPath}}", gsdPath);
|
|
128
|
-
content = content.replaceAll("{{previewStats}}", formatPreviewStats(preview));
|
|
129
|
-
return content.trim();
|
|
130
|
-
}
|
|
131
|
-
/** Dispatch the review prompt to the agent. */
|
|
14
|
+
import { executeMigrationWrite } from "./execution.js";
|
|
15
|
+
import { createMigrationPlan } from "./plan.js";
|
|
16
|
+
import { buildMigrationPreviewSummary, buildReviewPrompt } from "./presentation.js";
|
|
132
17
|
function dispatchReview(pi, sourcePath, gsdPath, preview) {
|
|
133
|
-
const prompt = buildReviewPrompt(sourcePath, gsdPath, preview);
|
|
18
|
+
const prompt = buildReviewPrompt({ sourcePath, gsdPath, preview });
|
|
134
19
|
pi.sendMessage({
|
|
135
20
|
customType: "gsd-migrate-review",
|
|
136
21
|
content: prompt,
|
|
@@ -138,60 +23,32 @@ function dispatchReview(pi, sourcePath, gsdPath, preview) {
|
|
|
138
23
|
}, { triggerTurn: true });
|
|
139
24
|
}
|
|
140
25
|
export async function handleMigrate(args, ctx, pi) {
|
|
141
|
-
|
|
142
|
-
const { sourcePath, targetRoot } =
|
|
143
|
-
if (
|
|
26
|
+
const plan = await createMigrationPlan(args);
|
|
27
|
+
const { sourcePath, targetRoot } = plan;
|
|
28
|
+
if (plan.status === "missing-source") {
|
|
144
29
|
ctx.ui.notify(`Directory not found: ${sourcePath}\n\n` +
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
30
|
+
"Migration converts a .planning/ directory (from older GSD versions) into .gsd/ format.\n" +
|
|
31
|
+
"If you are starting a new project, use /gsd:new-project instead.\n" +
|
|
32
|
+
"If migrating, ensure the path contains a .planning/ directory.", "error");
|
|
148
33
|
return;
|
|
149
34
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
const warnings = validation.issues.filter((i) => i.severity === "warning");
|
|
153
|
-
const fatals = validation.issues.filter((i) => i.severity === "fatal");
|
|
154
|
-
for (const w of warnings) {
|
|
155
|
-
ctx.ui.notify(`⚠ ${w.message} (${w.file})`, "warning");
|
|
35
|
+
for (const warning of plan.warnings) {
|
|
36
|
+
ctx.ui.notify(`⚠ ${warning.message} (${warning.file})`, "warning");
|
|
156
37
|
}
|
|
157
|
-
for (const
|
|
158
|
-
ctx.ui.notify(`✖ ${
|
|
38
|
+
for (const fatal of plan.fatals) {
|
|
39
|
+
ctx.ui.notify(`✖ ${fatal.message} (${fatal.file})`, "error");
|
|
159
40
|
}
|
|
160
|
-
if (
|
|
41
|
+
if (plan.status === "invalid") {
|
|
161
42
|
ctx.ui.notify("Migration blocked — fix the fatal issues above before retrying.", "error");
|
|
162
43
|
return;
|
|
163
44
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const project = transformToGSD(parsed);
|
|
167
|
-
const preview = generatePreview(project);
|
|
168
|
-
try {
|
|
169
|
-
assertMigrationHasSlices(preview);
|
|
170
|
-
await assertMigrationTargetAvailable(targetRoot);
|
|
171
|
-
}
|
|
172
|
-
catch (err) {
|
|
173
|
-
ctx.ui.notify(err.message, "error");
|
|
45
|
+
if (plan.status === "blocked") {
|
|
46
|
+
ctx.ui.notify(plan.message, "error");
|
|
174
47
|
return;
|
|
175
48
|
}
|
|
49
|
+
const { project, preview } = plan;
|
|
176
50
|
// ── Build preview text ─────────────────────────────────────────────────────
|
|
177
|
-
const lines =
|
|
178
|
-
`Decisions: ${preview.decisions.total}`,
|
|
179
|
-
`Milestones: ${preview.milestoneCount}`,
|
|
180
|
-
`Slices: ${preview.totalSlices} (${preview.doneSlices} done — ${preview.sliceCompletionPct}%)`,
|
|
181
|
-
`Tasks: ${preview.totalTasks} (${preview.doneTasks} done — ${preview.taskCompletionPct}%)`,
|
|
182
|
-
];
|
|
183
|
-
if (preview.requirements.total > 0) {
|
|
184
|
-
lines.push(`Requirements: ${preview.requirements.total} (${preview.requirements.validated} validated, ${preview.requirements.active} active, ${preview.requirements.deferred} deferred, ${preview.requirements.outOfScope} out of scope)`);
|
|
185
|
-
}
|
|
186
|
-
if (preview.migrationInputs) {
|
|
187
|
-
lines.push(`Legacy inputs: ${preview.migrationInputs.milestonePhaseDirs} milestone phase dir(s), ${preview.migrationInputs.decisions} decision file(s), ${preview.migrationInputs.seeds} seed file(s)`);
|
|
188
|
-
}
|
|
189
|
-
const targetGsdExists = existsSync(gsdRoot(targetRoot));
|
|
190
|
-
if (targetGsdExists) {
|
|
191
|
-
lines.push("");
|
|
192
|
-
lines.push(`⚠ A .gsd directory already exists at ${gsdRoot(targetRoot)}.`);
|
|
193
|
-
lines.push("It will be backed up, deleted, and rewritten fresh before DB import.");
|
|
194
|
-
}
|
|
51
|
+
const lines = buildMigrationPreviewSummary(preview, targetRoot);
|
|
195
52
|
// ── Confirmation via showNextAction ────────────────────────────────────────
|
|
196
53
|
if (requiresInteractiveMenu(ctx, false)) {
|
|
197
54
|
notifyMigrateNeedsInteractiveMenu(ctx, "migration confirmation needs an interactive menu");
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// gsd-pi - /gsd migrate execution service.
|
|
2
|
+
// File Purpose: Write migrated .gsd files, import them into the DB, verify projection/readiness, and rollback on failure.
|
|
3
|
+
import { ensureDbOpen } from "../bootstrap/dynamic-tools.js";
|
|
4
|
+
import { closeWorkflowDatabase } from "../db-workspace.js";
|
|
5
|
+
import { clearArtifacts, clearDecisions, clearEngineHierarchy, clearRequirements, transaction } from "../gsd-db.js";
|
|
6
|
+
import { migrateFromMarkdown } from "../md-importer.js";
|
|
7
|
+
import { deriveState, invalidateStateCache } from "../state.js";
|
|
8
|
+
import { archiveLegacyPlanningDirectory, verifyMigrationProjection, writeMigrationAudit, } from "./audit.js";
|
|
9
|
+
import { prepareMigrationTarget, restoreMigrationTarget, } from "./safety.js";
|
|
10
|
+
import { writeGSDDirectory } from "./writer.js";
|
|
11
|
+
function assertMigrationImportMatchesPreview(imported, preview) {
|
|
12
|
+
const mismatches = [];
|
|
13
|
+
if (imported.decisions !== preview.decisions.total) {
|
|
14
|
+
mismatches.push(`decisions ${imported.decisions}/${preview.decisions.total}`);
|
|
15
|
+
}
|
|
16
|
+
if (imported.hierarchy.milestones !== preview.milestoneCount) {
|
|
17
|
+
mismatches.push(`milestones ${imported.hierarchy.milestones}/${preview.milestoneCount}`);
|
|
18
|
+
}
|
|
19
|
+
if (imported.hierarchy.slices !== preview.totalSlices) {
|
|
20
|
+
mismatches.push(`slices ${imported.hierarchy.slices}/${preview.totalSlices}`);
|
|
21
|
+
}
|
|
22
|
+
if (imported.hierarchy.tasks !== preview.totalTasks) {
|
|
23
|
+
mismatches.push(`tasks ${imported.hierarchy.tasks}/${preview.totalTasks}`);
|
|
24
|
+
}
|
|
25
|
+
if (imported.requirements !== preview.requirements.total) {
|
|
26
|
+
mismatches.push(`requirements ${imported.requirements}/${preview.requirements.total}`);
|
|
27
|
+
}
|
|
28
|
+
if (mismatches.length > 0) {
|
|
29
|
+
throw new Error(`migration DB import verification failed: ${mismatches.join(", ")}`);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export async function importWrittenMigrationToDb(basePath, preview) {
|
|
33
|
+
const opened = await ensureDbOpen(basePath);
|
|
34
|
+
if (!opened) {
|
|
35
|
+
throw new Error(`failed to open or create the GSD database at ${basePath}`);
|
|
36
|
+
}
|
|
37
|
+
const counts = transaction(() => {
|
|
38
|
+
clearEngineHierarchy();
|
|
39
|
+
clearArtifacts();
|
|
40
|
+
clearDecisions();
|
|
41
|
+
clearRequirements();
|
|
42
|
+
const imported = migrateFromMarkdown(basePath);
|
|
43
|
+
if (preview)
|
|
44
|
+
assertMigrationImportMatchesPreview(imported, preview);
|
|
45
|
+
return imported;
|
|
46
|
+
});
|
|
47
|
+
invalidateStateCache();
|
|
48
|
+
return counts;
|
|
49
|
+
}
|
|
50
|
+
export async function assertMigrationDbReadiness(targetRoot, preview) {
|
|
51
|
+
invalidateStateCache();
|
|
52
|
+
const state = await deriveState(targetRoot);
|
|
53
|
+
const dbUnavailable = state.blockers.some((blocker) => blocker.includes("DB unavailable"));
|
|
54
|
+
if (dbUnavailable) {
|
|
55
|
+
throw new Error(`migration DB readiness failed: ${state.blockers.join("; ")}`);
|
|
56
|
+
}
|
|
57
|
+
if (state.registry.length !== preview.milestoneCount) {
|
|
58
|
+
throw new Error(`migration DB readiness failed: registry ${state.registry.length}/${preview.milestoneCount}`);
|
|
59
|
+
}
|
|
60
|
+
return {
|
|
61
|
+
phase: state.phase,
|
|
62
|
+
registry: state.registry.length,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export async function executeMigrationWrite(sourcePath, targetRoot, project, preview, startedAt = new Date().toISOString()) {
|
|
66
|
+
const backup = prepareMigrationTarget(targetRoot);
|
|
67
|
+
try {
|
|
68
|
+
const written = await writeGSDDirectory(project, targetRoot);
|
|
69
|
+
const legacyArchive = await archiveLegacyPlanningDirectory(sourcePath, targetRoot);
|
|
70
|
+
const imported = await importWrittenMigrationToDb(targetRoot, preview);
|
|
71
|
+
const verification = await verifyMigrationProjection(targetRoot, preview);
|
|
72
|
+
verification.dbReadiness = await assertMigrationDbReadiness(targetRoot, preview);
|
|
73
|
+
const audit = await writeMigrationAudit({
|
|
74
|
+
sourcePath,
|
|
75
|
+
targetRoot,
|
|
76
|
+
backupPath: backup.backupPath,
|
|
77
|
+
preview,
|
|
78
|
+
written,
|
|
79
|
+
imported,
|
|
80
|
+
legacyArchive,
|
|
81
|
+
verification,
|
|
82
|
+
startedAt,
|
|
83
|
+
completedAt: new Date().toISOString(),
|
|
84
|
+
});
|
|
85
|
+
return { backup, written, imported, legacyArchive, verification, audit };
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
// The import transaction may have committed and the process may hold an
|
|
89
|
+
// open handle to the target gsd.db; close before the restore replaces the
|
|
90
|
+
// file on disk, and leave closed so the next open rebinds to the restored file.
|
|
91
|
+
try {
|
|
92
|
+
closeWorkflowDatabase();
|
|
93
|
+
}
|
|
94
|
+
catch { /* best-effort: restore must proceed */ }
|
|
95
|
+
restoreMigrationTarget(backup);
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// gsd-pi - /gsd migrate planning service.
|
|
2
|
+
// File Purpose: Resolve, validate, parse, transform, preview, and guard a migration before UI confirmation.
|
|
3
|
+
import { existsSync } from "node:fs";
|
|
4
|
+
import { assertMigrationHasSlices, assertMigrationTargetAvailable, resolveMigrationPaths, } from "./safety.js";
|
|
5
|
+
import { parsePlanningDirectory } from "./parser.js";
|
|
6
|
+
import { generatePreview } from "./preview.js";
|
|
7
|
+
import { transformToGSD } from "./transformer.js";
|
|
8
|
+
import { validatePlanningDirectory } from "./validator.js";
|
|
9
|
+
export function splitValidationIssues(validation) {
|
|
10
|
+
return {
|
|
11
|
+
warnings: validation.issues.filter((issue) => issue.severity === "warning"),
|
|
12
|
+
fatals: validation.issues.filter((issue) => issue.severity === "fatal"),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export async function createMigrationPlan(args, cwd = process.cwd()) {
|
|
16
|
+
const paths = resolveMigrationPaths(args, cwd);
|
|
17
|
+
if (!existsSync(paths.sourcePath)) {
|
|
18
|
+
return { status: "missing-source", ...paths };
|
|
19
|
+
}
|
|
20
|
+
const validation = await validatePlanningDirectory(paths.sourcePath);
|
|
21
|
+
const issues = splitValidationIssues(validation);
|
|
22
|
+
if (!validation.valid) {
|
|
23
|
+
return { status: "invalid", ...paths, validation, ...issues };
|
|
24
|
+
}
|
|
25
|
+
const parsed = await parsePlanningDirectory(paths.sourcePath);
|
|
26
|
+
const project = transformToGSD(parsed);
|
|
27
|
+
const preview = generatePreview(project);
|
|
28
|
+
try {
|
|
29
|
+
assertMigrationHasSlices(preview);
|
|
30
|
+
await assertMigrationTargetAvailable(paths.targetRoot);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return {
|
|
34
|
+
status: "blocked",
|
|
35
|
+
...paths,
|
|
36
|
+
validation,
|
|
37
|
+
...issues,
|
|
38
|
+
message: error instanceof Error ? error.message : String(error),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
status: "ready",
|
|
43
|
+
...paths,
|
|
44
|
+
validation,
|
|
45
|
+
...issues,
|
|
46
|
+
project,
|
|
47
|
+
preview,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -143,14 +143,14 @@ export async function writePlanningDirectory(basePath, layout) {
|
|
|
143
143
|
done: isDone,
|
|
144
144
|
});
|
|
145
145
|
if (tasks.length === 0) {
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
146
|
+
// Sketch / undecomposed slice — zero tasks. Do NOT emit an ingestible
|
|
147
|
+
// *-PLAN.md here: the reverse transform maps one GSDTask per plan file
|
|
148
|
+
// (transformer.ts mapSlice), so a placeholder would materialize a
|
|
149
|
+
// phantom "Plan NN" task and flip the slice from "needs planning" to
|
|
150
|
+
// "has a planned task", causing auto-mode to skip planning (issue #1285).
|
|
151
|
+
// The phase dir is already created (mkdirSync above) and the slice is
|
|
152
|
+
// listed in ROADMAP.md, so it round-trips with tasks = [] — the correct
|
|
153
|
+
// sketch-slice shape.
|
|
154
154
|
}
|
|
155
155
|
else {
|
|
156
156
|
for (let ti = 0; ti < tasks.length; ti++) {
|
|
@@ -174,19 +174,14 @@ export async function writePlanningDirectory(basePath, layout) {
|
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
-
// If no slices produced any phases,
|
|
178
|
-
//
|
|
177
|
+
// If no slices produced any phases, emit a single empty phase dir + ROADMAP
|
|
178
|
+
// entry so the layout stays discoverable. Do NOT write a placeholder
|
|
179
|
+
// *-PLAN.md — an ingestible plan file would round-trip into a phantom task
|
|
180
|
+
// (see the tasks.length === 0 branch above, issue #1285).
|
|
179
181
|
if (roadmapEntries.length === 0) {
|
|
180
182
|
const phaseDirName = `${pad(1)}-milestone`;
|
|
181
183
|
const phaseDir = join(root, "phases", phaseDirName);
|
|
182
184
|
mkdirSync(phaseDir, { recursive: true });
|
|
183
|
-
const planPath = join(phaseDir, `${pad(1)}-01-PLAN.md`);
|
|
184
|
-
await saveFile(planPath, formatPlanningPlan(1, 1, milestones[0].title || milestones[0].id, []));
|
|
185
|
-
paths.push(planPath);
|
|
186
|
-
projectionWrites.push({
|
|
187
|
-
relPath: toPlanningRel(planPath),
|
|
188
|
-
entities: [milestones[0].id],
|
|
189
|
-
});
|
|
190
185
|
roadmapEntries.push({ number: 1, title: milestones[0].title || milestones[0].id, done: false });
|
|
191
186
|
}
|
|
192
187
|
// Root files
|