@opengsd/gsd-pi 1.7.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 -6
- 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 +9 -9
- 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 +9 -9
- 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 +30 -8
- package/packages/daemon/dist/cloud-config.js.map +1 -1
- package/packages/daemon/dist/cloud-config.test.js +69 -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/README.md +18 -4
- package/packages/gsd-cloud/bin/gsd-cloud.js +6 -5
- 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 +7 -5
- 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/{enWQFRY-aLTUq3wmxG2Qz → TezjdjSHBVRRr54XjAvte}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{enWQFRY-aLTUq3wmxG2Qz → TezjdjSHBVRRr54XjAvte}/_ssgManifest.js +0 -0
|
@@ -6,7 +6,13 @@ import { cpSync, existsSync, mkdirSync, readdirSync, renameSync, rmSync, statSyn
|
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
|
|
8
8
|
import { renderAllFromDb, renderRoadmapFromDb } from "./markdown-renderer.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
deleteArtifactByPath,
|
|
11
|
+
deleteArtifactsByPathPrefix,
|
|
12
|
+
getAllMilestones,
|
|
13
|
+
getArtifactsByPathPrefix,
|
|
14
|
+
getMilestoneSlices,
|
|
15
|
+
} from "./gsd-db.js";
|
|
10
16
|
import { migrateFromMarkdown } from "./md-importer.js";
|
|
11
17
|
import { countDbHierarchy } from "./migration-auto-check.js";
|
|
12
18
|
import { logWarning } from "./workflow-logger.js";
|
|
@@ -14,6 +20,7 @@ import { LAYOUT_SEGMENTS } from "./layout-policy.js";
|
|
|
14
20
|
import {
|
|
15
21
|
canonicalPhaseDirName,
|
|
16
22
|
dirIsContentBearingLegacyMilestone,
|
|
23
|
+
gsdProjectionRoot,
|
|
17
24
|
milestonesDir,
|
|
18
25
|
resolveMilestonePath,
|
|
19
26
|
} from "./paths.js";
|
|
@@ -83,6 +90,40 @@ function expectedPhaseDirs(basePath: string): string[] {
|
|
|
83
90
|
);
|
|
84
91
|
}
|
|
85
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Return the most-recent existing `.gsd-backups/migrate-<ts>/` snapshot, or null.
|
|
95
|
+
*
|
|
96
|
+
* The flat-phase migration can re-fire on later dispatches when the legacy
|
|
97
|
+
* `.gsd/milestones/` layout reappears (e.g. a marker-key mismatch re-triggers a
|
|
98
|
+
* whole-tree re-import — issue #1292). The DB was already reconciled from that
|
|
99
|
+
* tree before the backup step runs, so re-snapshotting an identical legacy tree
|
|
100
|
+
* on every dispatch only leaks a fresh `migrate-<ts>/` directory each time. When
|
|
101
|
+
* a prior snapshot already exists we reuse it as the rollback fallback instead
|
|
102
|
+
* of creating a duplicate, bounding the accumulation to one recovery copy.
|
|
103
|
+
*/
|
|
104
|
+
function existingMigrateBackup(basePath: string): string | null {
|
|
105
|
+
const backupRoot = join(basePath, ".gsd-backups");
|
|
106
|
+
if (!existsSync(backupRoot)) return null;
|
|
107
|
+
try {
|
|
108
|
+
let latest: { path: string; mtimeMs: number } | null = null;
|
|
109
|
+
for (const entry of readdirSync(backupRoot)) {
|
|
110
|
+
if (!entry.startsWith("migrate-")) continue;
|
|
111
|
+
const dirPath = join(backupRoot, entry);
|
|
112
|
+
try {
|
|
113
|
+
const st = statSync(dirPath);
|
|
114
|
+
if (!st.isDirectory()) continue;
|
|
115
|
+
if (!hasLegacyMilestoneSubdirs(dirPath)) continue;
|
|
116
|
+
if (!latest || st.mtimeMs > latest.mtimeMs) latest = { path: dirPath, mtimeMs: st.mtimeMs };
|
|
117
|
+
} catch {
|
|
118
|
+
// Non-fatal: skip unreadable entries.
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return latest?.path ?? null;
|
|
122
|
+
} catch {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
86
127
|
function hasLegacyMilestoneSubdirs(dirPath: string): boolean {
|
|
87
128
|
if (!existsSync(dirPath)) return false;
|
|
88
129
|
try {
|
|
@@ -94,10 +135,63 @@ function hasLegacyMilestoneSubdirs(dirPath: string): boolean {
|
|
|
94
135
|
}
|
|
95
136
|
}
|
|
96
137
|
|
|
138
|
+
function backupFlatProjectionIfPresent(basePath: string, phasesPath: string, backupDir: string): void {
|
|
139
|
+
if (!existsSync(phasesPath)) return;
|
|
140
|
+
const phaseBackupDir = join(backupDir, "__phases");
|
|
141
|
+
try {
|
|
142
|
+
mkdirSync(backupDir, { recursive: true });
|
|
143
|
+
if (existsSync(phaseBackupDir)) {
|
|
144
|
+
removePathWithRetries(phaseBackupDir);
|
|
145
|
+
}
|
|
146
|
+
fsOps.cpSync(phasesPath, phaseBackupDir, { recursive: true, force: true });
|
|
147
|
+
} catch (err) {
|
|
148
|
+
logWarning("migration", `flat-phase projection backup failed: ${(err as Error).message}`);
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function isInsideFlatProjectionBackup(backupDir: string, src: string): boolean {
|
|
154
|
+
const phaseBackupDir = join(backupDir, "__phases");
|
|
155
|
+
return src === phaseBackupDir || src.startsWith(`${phaseBackupDir}/`) || src.startsWith(`${phaseBackupDir}\\`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function restoreFlatProjectionFromBackup(basePath: string, backupDir: string): void {
|
|
159
|
+
const phaseBackupDir = join(backupDir, "__phases");
|
|
160
|
+
if (!existsSync(phaseBackupDir)) return;
|
|
161
|
+
const phasesPath = join(basePath, ".gsd", LAYOUT_SEGMENTS.level1);
|
|
162
|
+
try {
|
|
163
|
+
if (existsSync(phasesPath)) {
|
|
164
|
+
removePathWithRetries(phasesPath);
|
|
165
|
+
}
|
|
166
|
+
mkdirSync(join(basePath, ".gsd"), { recursive: true });
|
|
167
|
+
cpSync(phaseBackupDir, phasesPath, { recursive: true });
|
|
168
|
+
} catch (restoreErr) {
|
|
169
|
+
logWarning(
|
|
170
|
+
"migration",
|
|
171
|
+
`rollback: could not restore ${LAYOUT_SEGMENTS.level1}/ from backup: ${(restoreErr as Error).message}`,
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function pruneStaleFlatPhaseArtifactRows(basePath: string): number {
|
|
177
|
+
const projectionRoot = gsdProjectionRoot(basePath);
|
|
178
|
+
let pruned = 0;
|
|
179
|
+
for (const row of getArtifactsByPathPrefix(`${LAYOUT_SEGMENTS.level1}/`)) {
|
|
180
|
+
if (existsSync(join(projectionRoot, row.path))) continue;
|
|
181
|
+
const staleTaskPlan = row.artifact_type.toUpperCase() === "PLAN" && Boolean(row.task_id);
|
|
182
|
+
const skippedEmptyArtifact = row.full_content.trim() === "";
|
|
183
|
+
if (!staleTaskPlan && !skippedEmptyArtifact) continue;
|
|
184
|
+
deleteArtifactByPath(row.path);
|
|
185
|
+
pruned++;
|
|
186
|
+
}
|
|
187
|
+
return pruned;
|
|
188
|
+
}
|
|
189
|
+
|
|
97
190
|
function rollbackPartialMigration(
|
|
98
191
|
basePath: string,
|
|
99
192
|
backupDir: string,
|
|
100
193
|
migratingPath?: string,
|
|
194
|
+
backupCreatedThisRun = true,
|
|
101
195
|
): void {
|
|
102
196
|
// Remove the partially-written phases/ dir.
|
|
103
197
|
try {
|
|
@@ -113,7 +207,8 @@ function rollbackPartialMigration(
|
|
|
113
207
|
// preserved migrating tree (the sole surviving data source) and must never be
|
|
114
208
|
// removed here. Deleting the backup after a successful rollback keeps the gate
|
|
115
209
|
// from leaking one .gsd-backups/migrate-<ts>/ per session_start.
|
|
116
|
-
const isDisposableBackup =
|
|
210
|
+
const isDisposableBackup =
|
|
211
|
+
Boolean(backupDir) && backupDir !== migratingPath && backupCreatedThisRun;
|
|
117
212
|
const cleanupBackup = (): void => {
|
|
118
213
|
if (!isDisposableBackup || !existsSync(backupDir)) return;
|
|
119
214
|
try {
|
|
@@ -131,11 +226,16 @@ function rollbackPartialMigration(
|
|
|
131
226
|
try {
|
|
132
227
|
if (migratingPath && existsSync(migratingPath) && !existsSync(milestonesPath)) {
|
|
133
228
|
movePathWithCopyDeleteFallback(migratingPath, milestonesPath);
|
|
229
|
+
restoreFlatProjectionFromBackup(basePath, backupDir);
|
|
134
230
|
cleanupBackup();
|
|
135
231
|
return;
|
|
136
232
|
}
|
|
137
233
|
if (existsSync(backupDir)) {
|
|
138
|
-
cpSync(backupDir, milestonesPath, {
|
|
234
|
+
cpSync(backupDir, milestonesPath, {
|
|
235
|
+
recursive: true,
|
|
236
|
+
filter: (src) => !isInsideFlatProjectionBackup(backupDir, src),
|
|
237
|
+
});
|
|
238
|
+
restoreFlatProjectionFromBackup(basePath, backupDir);
|
|
139
239
|
cleanupBackup();
|
|
140
240
|
}
|
|
141
241
|
if (migratingPath && existsSync(migratingPath)) {
|
|
@@ -244,16 +344,34 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
244
344
|
}
|
|
245
345
|
|
|
246
346
|
let backupDir = migratingPath;
|
|
347
|
+
let backupCreatedThisRun = false;
|
|
247
348
|
if (!resumingInterrupted) {
|
|
248
|
-
// 2. Backup (only reached when the DB has rows and migration will proceed)
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
349
|
+
// 2. Backup (only reached when the DB has rows and migration will proceed).
|
|
350
|
+
// migrateFromMarkdown above already reconciled the legacy tree into the DB,
|
|
351
|
+
// so its content is safely persisted. If a prior successful migration
|
|
352
|
+
// already snapshotted the legacy tree, a re-fire of this gate (issue #1292:
|
|
353
|
+
// marker-key mismatch re-importing the whole tree at dispatch boundaries)
|
|
354
|
+
// must not leak a fresh .gsd-backups/migrate-<ts>/ every dispatch. Treat it
|
|
355
|
+
// as a marker-refresh re-projection: reuse the existing snapshot as the
|
|
356
|
+
// rollback fallback instead of creating a duplicate.
|
|
357
|
+
const priorBackup = existingMigrateBackup(basePath);
|
|
358
|
+
if (priorBackup) {
|
|
359
|
+
backupDir = priorBackup;
|
|
360
|
+
logWarning(
|
|
361
|
+
"migration",
|
|
362
|
+
`flat-phase migration re-fired; reusing existing backup ${priorBackup} instead of re-snapshotting (issue #1292)`,
|
|
363
|
+
);
|
|
364
|
+
} else {
|
|
365
|
+
const ts = Date.now();
|
|
366
|
+
backupDir = join(basePath, ".gsd-backups", `migrate-${ts}`);
|
|
367
|
+
try {
|
|
368
|
+
mkdirSync(join(basePath, ".gsd-backups"), { recursive: true });
|
|
369
|
+
cpSync(milestonesPath, backupDir, { recursive: true });
|
|
370
|
+
backupCreatedThisRun = true;
|
|
371
|
+
} catch (err) {
|
|
372
|
+
logWarning("migration", `flat-phase migration backup failed: ${(err as Error).message}`);
|
|
373
|
+
throw err;
|
|
374
|
+
}
|
|
257
375
|
}
|
|
258
376
|
|
|
259
377
|
if (existsSync(migratingPath)) {
|
|
@@ -269,15 +387,35 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
269
387
|
logWarning("migration", `failed to rename legacy milestones/ before render: ${(err as Error).message}`);
|
|
270
388
|
throw err;
|
|
271
389
|
}
|
|
390
|
+
} else {
|
|
391
|
+
const priorBackup = existingMigrateBackup(basePath);
|
|
392
|
+
if (priorBackup) {
|
|
393
|
+
backupDir = priorBackup;
|
|
394
|
+
} else {
|
|
395
|
+
const ts = Date.now();
|
|
396
|
+
backupDir = join(basePath, ".gsd-backups", `migrate-${ts}`);
|
|
397
|
+
try {
|
|
398
|
+
mkdirSync(join(basePath, ".gsd-backups"), { recursive: true });
|
|
399
|
+
cpSync(migratingPath, backupDir, { recursive: true });
|
|
400
|
+
backupCreatedThisRun = true;
|
|
401
|
+
} catch (err) {
|
|
402
|
+
logWarning(
|
|
403
|
+
"migration",
|
|
404
|
+
`flat-phase migration backup failed during resume: ${(err as Error).message}`,
|
|
405
|
+
);
|
|
406
|
+
throw err;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
272
409
|
}
|
|
273
410
|
|
|
274
411
|
// Clear any stale or partially-rendered flat projection before this run
|
|
275
412
|
// writes. Verification below checks the current DB render, not leftovers.
|
|
276
413
|
try {
|
|
414
|
+
backupFlatProjectionIfPresent(basePath, phasesPath, backupDir);
|
|
277
415
|
removePathWithRetries(phasesPath);
|
|
278
416
|
} catch (err) {
|
|
279
417
|
logWarning("migration", `failed to clear stale phases/ before render: ${(err as Error).message}`);
|
|
280
|
-
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
418
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
|
|
281
419
|
throw err;
|
|
282
420
|
}
|
|
283
421
|
|
|
@@ -299,7 +437,7 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
299
437
|
}
|
|
300
438
|
} catch (err) {
|
|
301
439
|
logWarning("migration", `flat-phase render failed: ${(err as Error).message}`);
|
|
302
|
-
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
440
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
|
|
303
441
|
throw err;
|
|
304
442
|
}
|
|
305
443
|
|
|
@@ -309,7 +447,7 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
309
447
|
"migration",
|
|
310
448
|
`flat-phase render had ${renderResult.errors.length} error(s): ${renderResult.errors.join("; ")}`,
|
|
311
449
|
);
|
|
312
|
-
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
450
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
|
|
313
451
|
throw new Error(
|
|
314
452
|
`flat-phase migration render failed: ${renderResult.errors.slice(0, 3).join("; ")}`,
|
|
315
453
|
);
|
|
@@ -322,7 +460,7 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
322
460
|
"migration",
|
|
323
461
|
`flat-phase migration missing ${missingPhaseDirs.length} expected phase dir(s): ${missingPhaseDirs.join(", ")}`,
|
|
324
462
|
);
|
|
325
|
-
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
463
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
|
|
326
464
|
throw new Error("flat-phase migration verification failed: missing rendered phase directories");
|
|
327
465
|
}
|
|
328
466
|
if (db.slices > 0 && renderResult.rendered === 0) {
|
|
@@ -330,17 +468,20 @@ export async function migrateToFlatPhase(basePath: string): Promise<void> {
|
|
|
330
468
|
"migration",
|
|
331
469
|
"flat-phase migration verification failed: render produced no artifacts for populated DB",
|
|
332
470
|
);
|
|
333
|
-
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
471
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
|
|
334
472
|
throw new Error("flat-phase migration verification failed: no artifacts rendered");
|
|
335
473
|
}
|
|
336
474
|
|
|
337
475
|
// 6. Verified — prune legacy artifact rows now that renderAllFromDb has
|
|
338
|
-
// re-inserted flat-phase rows for artifacts that still have files.
|
|
476
|
+
// re-inserted flat-phase rows for artifacts that still have files. Also
|
|
477
|
+
// prune flat-phase rows whose files the renderer intentionally no longer
|
|
478
|
+
// materializes, such as task PLAN files and empty-content artifacts.
|
|
339
479
|
try {
|
|
340
480
|
deleteArtifactsByPathPrefix("milestones/");
|
|
481
|
+
pruneStaleFlatPhaseArtifactRows(basePath);
|
|
341
482
|
} catch (err) {
|
|
342
483
|
logWarning("migration", `flat-phase migration could not prune legacy artifact rows: ${(err as Error).message}`);
|
|
343
|
-
rollbackPartialMigration(basePath, backupDir, migratingPath);
|
|
484
|
+
rollbackPartialMigration(basePath, backupDir, migratingPath, backupCreatedThisRun);
|
|
344
485
|
throw err;
|
|
345
486
|
}
|
|
346
487
|
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./db-decision-requirement-rows.js";
|
|
42
42
|
import { rowToGate } from "./db-gate-rows.js";
|
|
43
43
|
import { rowToArtifact, rowToMilestone, type ArtifactRow, type MilestoneRow } from "./db-milestone-artifact-rows.js";
|
|
44
|
-
import { isClosedStatus } from "./status-guards.js";
|
|
44
|
+
import { isClosedStatus, toStatus } from "./status-guards.js";
|
|
45
45
|
import { rowToSlice, rowToTask, type SliceRow, type TaskRow } from "./db-task-slice-rows.js";
|
|
46
46
|
|
|
47
47
|
// Connection ownership, lifecycle, schema/migrations and transaction
|
|
@@ -464,6 +464,11 @@ export function insertTask(t: {
|
|
|
464
464
|
preserveCompletionMetadata?: boolean;
|
|
465
465
|
}): void {
|
|
466
466
|
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
467
|
+
// Stamp completed_at for every terminal-complete alias (complete/done/closed),
|
|
468
|
+
// not just two literals — a task imported as "closed" is completed and must
|
|
469
|
+
// carry a timestamp. NOT for "skipped": a skipped task was never completed
|
|
470
|
+
// (cascade writers set its completed_at = NULL).
|
|
471
|
+
const isCompleteAlias = t.status != null && toStatus(t.status) === "complete";
|
|
467
472
|
getDbOrNull()!.prepare(
|
|
468
473
|
`INSERT INTO tasks (
|
|
469
474
|
milestone_id, slice_id, id, title, status, one_liner, narrative,
|
|
@@ -515,7 +520,7 @@ export function insertTask(t: {
|
|
|
515
520
|
":narrative": t.narrative ?? "",
|
|
516
521
|
":verification_result": t.verificationResult ?? "",
|
|
517
522
|
":duration": t.duration ?? "",
|
|
518
|
-
":completed_at":
|
|
523
|
+
":completed_at": isCompleteAlias ? new Date().toISOString() : null,
|
|
519
524
|
":blocker_discovered": t.blockerDiscovered ? 1 : 0,
|
|
520
525
|
":deviations": t.deviations ?? "",
|
|
521
526
|
":known_issues": t.knownIssues ?? "",
|
|
@@ -531,7 +536,7 @@ export function insertTask(t: {
|
|
|
531
536
|
":observability_impact": t.planning?.observabilityImpact ?? "",
|
|
532
537
|
":full_plan_md": t.planning?.fullPlanMd ?? "",
|
|
533
538
|
":sequence": t.sequence ?? 0,
|
|
534
|
-
":preserve_completion": t.preserveCompletionMetadata &&
|
|
539
|
+
":preserve_completion": t.preserveCompletionMetadata && isCompleteAlias ? 1 : 0,
|
|
535
540
|
":target_repositories": JSON.stringify(t.planning?.targetRepositories ?? []),
|
|
536
541
|
":raw_target_repositories":
|
|
537
542
|
t.planning && "targetRepositories" in t.planning
|
|
@@ -656,8 +661,8 @@ export function upsertTaskPlanning(milestoneId: string, sliceId: string, taskId:
|
|
|
656
661
|
}
|
|
657
662
|
|
|
658
663
|
|
|
659
|
-
export function updateSliceStatus(milestoneId: string, sliceId: string, status: string, completedAt?: string): void {
|
|
660
|
-
applyStatusTransition({ entity: "slice", milestoneId, sliceId, status, completedAt });
|
|
664
|
+
export function updateSliceStatus(milestoneId: string, sliceId: string, status: string, completedAt?: string, preserveCompletion?: boolean): void {
|
|
665
|
+
applyStatusTransition({ entity: "slice", milestoneId, sliceId, status, completedAt, preserveCompletion });
|
|
661
666
|
}
|
|
662
667
|
|
|
663
668
|
export function setTaskSummaryMd(milestoneId: string, sliceId: string, taskId: string, md: string): void {
|
|
@@ -820,8 +825,8 @@ function writeMilestoneStatus(milestoneId: string, status: string, completedAt?:
|
|
|
820
825
|
* advance planned milestones. They may not reopen a closed milestone; callers
|
|
821
826
|
* must use reopenMilestoneStatus(), which is reserved for gsd_milestone_reopen.
|
|
822
827
|
*/
|
|
823
|
-
export function updateMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null): void {
|
|
824
|
-
applyStatusTransition({ entity: "milestone", milestoneId, status, completedAt });
|
|
828
|
+
export function updateMilestoneStatus(milestoneId: string, status: string, completedAt?: string | null, preserveCompletion?: boolean): void {
|
|
829
|
+
applyStatusTransition({ entity: "milestone", milestoneId, status, completedAt, preserveCompletion });
|
|
825
830
|
}
|
|
826
831
|
|
|
827
832
|
/**
|
|
@@ -893,6 +898,188 @@ export function insertReplanHistory(entry: {
|
|
|
893
898
|
});
|
|
894
899
|
}
|
|
895
900
|
|
|
901
|
+
|
|
902
|
+
export type ReworkFindingSeverity = "blocking" | "advisory";
|
|
903
|
+
export type ReworkFindingStatus = "pending" | "resolved" | "deferred-with-override";
|
|
904
|
+
|
|
905
|
+
export interface ReworkBriefFindingInput {
|
|
906
|
+
findingId: string;
|
|
907
|
+
severity: ReworkFindingSeverity;
|
|
908
|
+
description: string;
|
|
909
|
+
requiredFix: string;
|
|
910
|
+
verificationCommands: string[];
|
|
911
|
+
status?: ReworkFindingStatus;
|
|
912
|
+
evidence?: string;
|
|
913
|
+
decisionRef?: string;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
export interface ReworkBriefFindingRow {
|
|
917
|
+
brief_id: string;
|
|
918
|
+
finding_id: string;
|
|
919
|
+
severity: ReworkFindingSeverity;
|
|
920
|
+
description: string;
|
|
921
|
+
required_fix: string;
|
|
922
|
+
verification_commands: string[];
|
|
923
|
+
status: ReworkFindingStatus;
|
|
924
|
+
evidence: string;
|
|
925
|
+
decision_ref: string;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
function reworkBriefIdFromTask(milestoneId: string, sliceId: string, taskId: string): string {
|
|
929
|
+
return `RB-${milestoneId}-${sliceId}-${taskId}`;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
function normalizeReworkStatus(status: unknown): ReworkFindingStatus {
|
|
933
|
+
const normalized = String(status ?? "pending");
|
|
934
|
+
if (normalized === "resolved" || normalized === "deferred-with-override") {
|
|
935
|
+
return normalized;
|
|
936
|
+
}
|
|
937
|
+
return "pending";
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
function rowToReworkFinding(row: Record<string, unknown>): ReworkBriefFindingRow {
|
|
941
|
+
let verificationCommands: string[] = [];
|
|
942
|
+
try {
|
|
943
|
+
const parsed = JSON.parse(String(row["verification_commands"] ?? "[]"));
|
|
944
|
+
verificationCommands = Array.isArray(parsed) ? parsed.map(String) : [];
|
|
945
|
+
} catch {
|
|
946
|
+
verificationCommands = [];
|
|
947
|
+
}
|
|
948
|
+
return {
|
|
949
|
+
brief_id: String(row["brief_id"] ?? ""),
|
|
950
|
+
finding_id: String(row["finding_id"] ?? ""),
|
|
951
|
+
severity: String(row["severity"] ?? "blocking") === "advisory" ? "advisory" : "blocking",
|
|
952
|
+
description: String(row["description"] ?? ""),
|
|
953
|
+
required_fix: String(row["required_fix"] ?? ""),
|
|
954
|
+
verification_commands: verificationCommands,
|
|
955
|
+
status: normalizeReworkStatus(row["status"]),
|
|
956
|
+
evidence: String(row["evidence"] ?? ""),
|
|
957
|
+
decision_ref: String(row["decision_ref"] ?? ""),
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
export function saveReworkBrief(entry: {
|
|
962
|
+
briefId?: string;
|
|
963
|
+
milestoneId: string;
|
|
964
|
+
sliceId: string;
|
|
965
|
+
taskId: string;
|
|
966
|
+
findings: ReworkBriefFindingInput[];
|
|
967
|
+
}): { briefId: string } {
|
|
968
|
+
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
969
|
+
const briefId = entry.briefId?.trim() || reworkBriefIdFromTask(entry.milestoneId, entry.sliceId, entry.taskId);
|
|
970
|
+
const now = new Date().toISOString();
|
|
971
|
+
transaction(() => {
|
|
972
|
+
getDbOrNull()!.prepare(
|
|
973
|
+
`INSERT INTO rework_briefs (id, milestone_id, slice_id, task_id, created_at, updated_at)
|
|
974
|
+
VALUES (:id, :mid, :sid, :tid, :created_at, :updated_at)
|
|
975
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
976
|
+
milestone_id = :mid,
|
|
977
|
+
slice_id = :sid,
|
|
978
|
+
task_id = :tid,
|
|
979
|
+
updated_at = :updated_at`,
|
|
980
|
+
).run({
|
|
981
|
+
":id": briefId,
|
|
982
|
+
":mid": entry.milestoneId,
|
|
983
|
+
":sid": entry.sliceId,
|
|
984
|
+
":tid": entry.taskId,
|
|
985
|
+
":created_at": now,
|
|
986
|
+
":updated_at": now,
|
|
987
|
+
});
|
|
988
|
+
getDbOrNull()!.prepare("DELETE FROM rework_brief_findings WHERE brief_id = :id").run({ ":id": briefId });
|
|
989
|
+
const stmt = getDbOrNull()!.prepare(
|
|
990
|
+
`INSERT INTO rework_brief_findings (
|
|
991
|
+
brief_id, finding_id, severity, description, required_fix, verification_commands,
|
|
992
|
+
status, evidence, decision_ref, updated_at
|
|
993
|
+
) VALUES (
|
|
994
|
+
:brief_id, :finding_id, :severity, :description, :required_fix, :verification_commands,
|
|
995
|
+
:status, :evidence, :decision_ref, :updated_at
|
|
996
|
+
)`,
|
|
997
|
+
);
|
|
998
|
+
for (const finding of entry.findings) {
|
|
999
|
+
stmt.run({
|
|
1000
|
+
":brief_id": briefId,
|
|
1001
|
+
":finding_id": finding.findingId,
|
|
1002
|
+
":severity": finding.severity,
|
|
1003
|
+
":description": finding.description,
|
|
1004
|
+
":required_fix": finding.requiredFix,
|
|
1005
|
+
":verification_commands": JSON.stringify(finding.verificationCommands),
|
|
1006
|
+
":status": finding.status ?? "pending",
|
|
1007
|
+
":evidence": finding.evidence ?? "",
|
|
1008
|
+
":decision_ref": finding.decisionRef ?? "",
|
|
1009
|
+
":updated_at": now,
|
|
1010
|
+
});
|
|
1011
|
+
}
|
|
1012
|
+
});
|
|
1013
|
+
return { briefId };
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
export function getBlockingReworkFindingsForTask(
|
|
1017
|
+
milestoneId: string,
|
|
1018
|
+
sliceId: string,
|
|
1019
|
+
taskId: string,
|
|
1020
|
+
): ReworkBriefFindingRow[] {
|
|
1021
|
+
if (!getDbOrNull()!) return [];
|
|
1022
|
+
const rows = getDbOrNull()!.prepare(
|
|
1023
|
+
`SELECT f.*
|
|
1024
|
+
FROM rework_brief_findings f
|
|
1025
|
+
JOIN rework_briefs b ON b.id = f.brief_id
|
|
1026
|
+
WHERE b.milestone_id = :mid
|
|
1027
|
+
AND b.slice_id = :sid
|
|
1028
|
+
AND b.task_id = :tid
|
|
1029
|
+
AND f.severity = 'blocking'
|
|
1030
|
+
ORDER BY b.created_at, f.finding_id`,
|
|
1031
|
+
).all({ ":mid": milestoneId, ":sid": sliceId, ":tid": taskId }) as Array<Record<string, unknown>>;
|
|
1032
|
+
return rows.map(rowToReworkFinding);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
export function getUnresolvedBlockingReworkFindingsForTask(
|
|
1036
|
+
milestoneId: string,
|
|
1037
|
+
sliceId: string,
|
|
1038
|
+
taskId: string,
|
|
1039
|
+
): ReworkBriefFindingRow[] {
|
|
1040
|
+
return getBlockingReworkFindingsForTask(milestoneId, sliceId, taskId)
|
|
1041
|
+
.filter((finding) => finding.status === "pending");
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
export function applyReworkResolutions(resolutions: Array<{
|
|
1045
|
+
milestoneId: string;
|
|
1046
|
+
sliceId: string;
|
|
1047
|
+
taskId: string;
|
|
1048
|
+
findingId: string;
|
|
1049
|
+
status: ReworkFindingStatus;
|
|
1050
|
+
evidence: string;
|
|
1051
|
+
decisionRef?: string;
|
|
1052
|
+
}>): void {
|
|
1053
|
+
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1054
|
+
const now = new Date().toISOString();
|
|
1055
|
+
const stmt = getDbOrNull()!.prepare(
|
|
1056
|
+
`UPDATE rework_brief_findings
|
|
1057
|
+
SET status = :status,
|
|
1058
|
+
evidence = :evidence,
|
|
1059
|
+
decision_ref = :decision_ref,
|
|
1060
|
+
updated_at = :updated_at
|
|
1061
|
+
WHERE finding_id = :finding_id
|
|
1062
|
+
AND brief_id IN (
|
|
1063
|
+
SELECT id FROM rework_briefs
|
|
1064
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid
|
|
1065
|
+
)`,
|
|
1066
|
+
);
|
|
1067
|
+
transaction(() => {
|
|
1068
|
+
for (const resolution of resolutions) {
|
|
1069
|
+
stmt.run({
|
|
1070
|
+
":status": resolution.status,
|
|
1071
|
+
":evidence": resolution.evidence,
|
|
1072
|
+
":decision_ref": resolution.decisionRef ?? "",
|
|
1073
|
+
":updated_at": now,
|
|
1074
|
+
":finding_id": resolution.findingId,
|
|
1075
|
+
":mid": resolution.milestoneId,
|
|
1076
|
+
":sid": resolution.sliceId,
|
|
1077
|
+
":tid": resolution.taskId,
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
|
|
896
1083
|
export function insertAssessment(entry: {
|
|
897
1084
|
path: string;
|
|
898
1085
|
milestoneId: string;
|
|
@@ -1084,52 +1271,59 @@ export function saveGateResult(g: {
|
|
|
1084
1271
|
}): void {
|
|
1085
1272
|
if (!getDbOrNull()!) throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1086
1273
|
const evaluatedAt = new Date().toISOString();
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
);
|
|
1109
|
-
|
|
1274
|
+
// Atomic: the gate verdict UPDATE and the gate_runs ledger INSERT must commit
|
|
1275
|
+
// together. As two autocommits, a crash between them records a completed gate
|
|
1276
|
+
// with no ledger row (the row Recovery Classification reads). transaction()
|
|
1277
|
+
// is re-entrant, so callers already inside a transaction are safe. The
|
|
1278
|
+
// throw-on-zero-changes stays inside so a missing gate row rolls back cleanly.
|
|
1279
|
+
transaction(() => {
|
|
1280
|
+
const result = getDbOrNull()!.prepare(
|
|
1281
|
+
`UPDATE quality_gates
|
|
1282
|
+
SET status = 'complete', verdict = :verdict, rationale = :rationale,
|
|
1283
|
+
findings = :findings, evaluated_at = :evaluated_at
|
|
1284
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND gate_id = :gid
|
|
1285
|
+
AND (task_id = :tid OR (:tid = '' AND task_id IS NULL))`,
|
|
1286
|
+
).run({
|
|
1287
|
+
":mid": g.milestoneId,
|
|
1288
|
+
":sid": g.sliceId,
|
|
1289
|
+
":gid": g.gateId,
|
|
1290
|
+
":tid": g.taskId ?? "",
|
|
1291
|
+
":verdict": g.verdict,
|
|
1292
|
+
":rationale": g.rationale,
|
|
1293
|
+
":findings": g.findings,
|
|
1294
|
+
":evaluated_at": evaluatedAt,
|
|
1295
|
+
}) as { changes?: number };
|
|
1296
|
+
|
|
1297
|
+
if ((result.changes ?? 0) === 0) {
|
|
1298
|
+
throw new GSDError(
|
|
1299
|
+
GSD_STALE_STATE,
|
|
1300
|
+
`quality gate row not found for ${g.milestoneId}/${g.sliceId}/${g.gateId}${g.taskId ? `/${g.taskId}` : ""}`,
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1110
1303
|
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1304
|
+
const outcome =
|
|
1305
|
+
g.verdict === "pass"
|
|
1306
|
+
? "pass"
|
|
1307
|
+
: g.verdict === "omitted"
|
|
1308
|
+
? "manual-attention"
|
|
1309
|
+
: "fail";
|
|
1310
|
+
insertGateRun({
|
|
1311
|
+
traceId: `quality-gate:${g.milestoneId}:${g.sliceId}`,
|
|
1312
|
+
turnId: `gate:${g.gateId}:${g.taskId ?? "slice"}`,
|
|
1313
|
+
gateId: g.gateId,
|
|
1314
|
+
gateType: "quality-gate",
|
|
1315
|
+
milestoneId: g.milestoneId,
|
|
1316
|
+
sliceId: g.sliceId,
|
|
1317
|
+
taskId: g.taskId ?? undefined,
|
|
1318
|
+
outcome,
|
|
1319
|
+
failureClass: outcome === "fail" ? "verification" : outcome === "manual-attention" ? "manual-attention" : "none",
|
|
1320
|
+
rationale: g.rationale,
|
|
1321
|
+
findings: g.findings,
|
|
1322
|
+
attempt: 1,
|
|
1323
|
+
maxAttempts: 1,
|
|
1324
|
+
retryable: false,
|
|
1325
|
+
evaluatedAt,
|
|
1326
|
+
});
|
|
1133
1327
|
});
|
|
1134
1328
|
}
|
|
1135
1329
|
|
|
@@ -1419,6 +1613,15 @@ export function deleteArtifactsByPathPrefix(prefix: string): number {
|
|
|
1419
1613
|
});
|
|
1420
1614
|
}
|
|
1421
1615
|
|
|
1616
|
+
/** List artifact rows whose paths share a DB-relative prefix. */
|
|
1617
|
+
export function getArtifactsByPathPrefix(prefix: string): ArtifactRow[] {
|
|
1618
|
+
if (!getDbOrNull()!) return [];
|
|
1619
|
+
const rows = getDbOrNull()!.prepare(
|
|
1620
|
+
"SELECT * FROM artifacts WHERE path LIKE :prefix ORDER BY path",
|
|
1621
|
+
).all({ ":prefix": `${prefix}%` });
|
|
1622
|
+
return rows.map(rowToArtifact);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1422
1625
|
/**
|
|
1423
1626
|
* Drop hierarchy rows in dependency order inside a transaction. Used by
|
|
1424
1627
|
* `gsd recover --confirm` to rebuild engine state from markdown.
|