@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
|
@@ -8,6 +8,7 @@ import { loadJsonFileOrNull } from "../json-persistence.js";
|
|
|
8
8
|
import { getIsolationMode } from "../preferences.js";
|
|
9
9
|
import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
|
|
10
10
|
import { logWarning } from "../workflow-logger.js";
|
|
11
|
+
import { acquireSyncLock, releaseSyncLock } from "../sync-lock.js";
|
|
11
12
|
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
12
13
|
import { worktreesDirs } from "../worktree-placement.js";
|
|
13
14
|
import { bashReferencesProjectRootOutsideWorktree } from "../worktree-shell-guard.js";
|
|
@@ -318,12 +319,65 @@ export function refreshWriteGateStateFromDisk(basePath) {
|
|
|
318
319
|
}
|
|
319
320
|
return currentWriteGateSnapshot(basePath);
|
|
320
321
|
}
|
|
322
|
+
const WRITE_GATE_LOCK_NAME = "write-gate.lock";
|
|
323
|
+
/**
|
|
324
|
+
* Test-only seam: fires once inside the held cross-process lock (after acquire,
|
|
325
|
+
* before the read-merge-write body) with the resolved lock root. Lets a
|
|
326
|
+
* regression test observe that a concurrent process is genuinely locked out of
|
|
327
|
+
* the critical section. Production leaves it null. Follows the repo's
|
|
328
|
+
* `_setGhAvailableForTest` naming convention.
|
|
329
|
+
*/
|
|
330
|
+
let interleaveHookForTest = null;
|
|
331
|
+
export function _setWriteGateInterleaveHookForTest(fn) {
|
|
332
|
+
interleaveHookForTest = fn;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Serialize the read-merge-write critical section across the two processes
|
|
336
|
+
* that share the snapshot file (extension host + workflow MCP child). Atomic
|
|
337
|
+
* rename prevents torn files but not lost updates: without this lock the host
|
|
338
|
+
* can read the snapshot, the child can arm a gate and persist, then the host's
|
|
339
|
+
* later persist overwrites `pendingGateId`/`activeQueuePhase` (last-writer-wins
|
|
340
|
+
* fields) and silently drops the armed HARD-BLOCK gate.
|
|
341
|
+
*
|
|
342
|
+
* Fail-OPEN by contract: if a live peer holds the lock we proceed WITHOUT it —
|
|
343
|
+
* exactly the racy-but-functional behavior that shipped before this lock — and
|
|
344
|
+
* log once. The lock shrinks the race window to ~zero; it must never block,
|
|
345
|
+
* throw, or refuse a gate mutation. The lock is skipped entirely when snapshot
|
|
346
|
+
* persistence is off (no disk file, no cross-process seam).
|
|
347
|
+
*/
|
|
348
|
+
function withWriteGateLock(basePath, fn) {
|
|
349
|
+
if (!shouldPersistWriteGateSnapshot())
|
|
350
|
+
return fn();
|
|
351
|
+
const lockRoot = resolveWriteGateSnapshotRoot(basePath);
|
|
352
|
+
// Materialize `.gsd/` (including a dangling external-state symlink target)
|
|
353
|
+
// before locking. acquireSyncLock's own mkdir does NOT follow a symlink to
|
|
354
|
+
// create its target, so without this the O_EXCL open lands on a missing
|
|
355
|
+
// parent and the lock silently fails open — leaving the seam unserialized
|
|
356
|
+
// for exactly the external-state projects that need it. This is the same
|
|
357
|
+
// directory the persist path ensures anyway.
|
|
358
|
+
try {
|
|
359
|
+
ensureWriteGateSnapshotDirectory(basePath);
|
|
360
|
+
}
|
|
361
|
+
catch { /* best-effort; acquire fails-open below */ }
|
|
362
|
+
const { acquired } = acquireSyncLock(lockRoot, 0, WRITE_GATE_LOCK_NAME);
|
|
363
|
+
if (!acquired) {
|
|
364
|
+
logWarning("intercept", "write-gate: proceeding without cross-process lock (held by live peer)", { lockRoot });
|
|
365
|
+
return fn();
|
|
366
|
+
}
|
|
367
|
+
try {
|
|
368
|
+
interleaveHookForTest?.(lockRoot);
|
|
369
|
+
return fn();
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
releaseSyncLock(lockRoot, WRITE_GATE_LOCK_NAME);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
321
375
|
/**
|
|
322
376
|
* Read-modify-write primitive for gate mutations. Reconciles the disk
|
|
323
377
|
* snapshot into memory (union merge), applies the mutation on top, then
|
|
324
|
-
* persists
|
|
325
|
-
*
|
|
326
|
-
*
|
|
378
|
+
* persists — all under the cross-process lock (withWriteGateLock). The whole
|
|
379
|
+
* sequence is synchronous, so the reconcile read doubles as the pre-persist
|
|
380
|
+
* merge of concurrent writes; there is no version field.
|
|
327
381
|
*
|
|
328
382
|
* The mutate callback sees the already-reconciled state, so policy checks
|
|
329
383
|
* (e.g. host setPending's verified-on-disk-wins guard) can live inside it
|
|
@@ -335,23 +389,25 @@ export function refreshWriteGateStateFromDisk(basePath) {
|
|
|
335
389
|
*/
|
|
336
390
|
function mutateWriteGateState(basePath, mutate, opts) {
|
|
337
391
|
const state = getWriteGateState(basePath);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
392
|
+
return withWriteGateLock(basePath, () => {
|
|
393
|
+
if (shouldPersistWriteGateSnapshot() && (opts?.reconcile ?? true)) {
|
|
394
|
+
const disk = readDiskSnapshot(basePath);
|
|
395
|
+
if (disk) {
|
|
396
|
+
mergeSnapshotIntoState(state, disk);
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
// Missing OR unparseable on disk: treat as a full reset. Keeping
|
|
400
|
+
// stale in-memory state across a corrupt snapshot would persist it
|
|
401
|
+
// back on this very mutation and defeat the documented
|
|
402
|
+
// "delete the file to clear the HARD BLOCK gate" escape hatch.
|
|
403
|
+
replaceStateFromSnapshot(state, EMPTY_SNAPSHOT);
|
|
404
|
+
}
|
|
349
405
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
406
|
+
if (mutate(state) === false)
|
|
407
|
+
return false;
|
|
408
|
+
persistWriteGateSnapshot(basePath, opts?.writer ?? defaultWriteGateWriter());
|
|
409
|
+
return true;
|
|
410
|
+
});
|
|
355
411
|
}
|
|
356
412
|
export function isDepthVerified(basePath = process.cwd()) {
|
|
357
413
|
return getWriteGateState(basePath).verifiedDepthMilestones.size > 0;
|
|
@@ -550,13 +606,15 @@ export const childWriteGateAdapter = {
|
|
|
550
606
|
};
|
|
551
607
|
function childMutate(basePath, mutate) {
|
|
552
608
|
const state = getWriteGateState(basePath);
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
609
|
+
withWriteGateLock(basePath, () => {
|
|
610
|
+
if (shouldPersistWriteGateSnapshot()) {
|
|
611
|
+
// Always-fresh: disk is the only truth for the child; discard any
|
|
612
|
+
// cross-turn in-memory residue before mutating.
|
|
613
|
+
replaceStateFromSnapshot(state, readDiskSnapshot(basePath) ?? EMPTY_SNAPSHOT);
|
|
614
|
+
}
|
|
615
|
+
mutate(state);
|
|
616
|
+
persistWriteGateSnapshot(basePath, "child");
|
|
617
|
+
});
|
|
560
618
|
}
|
|
561
619
|
/**
|
|
562
620
|
* Which adapter the module-level convenience exports (markDepthVerified,
|
|
@@ -57,19 +57,23 @@ export function notifyDiscussNeedsInteractiveMenu(ctx, reason) {
|
|
|
57
57
|
hints: DISCUSS_HINTS,
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* Hub picker for /gsd queue (reorder vs add) is unavailable.
|
|
62
|
+
*
|
|
63
|
+
* Unlike the other picker-guidance notices, /gsd queue does NOT dead-end here:
|
|
64
|
+
* the caller falls through to the add-work flow, which runs headlessly. So this
|
|
65
|
+
* notice must avoid the "did not start:" picker-failure phrasing — the headless
|
|
66
|
+
* host classifies that as a blocked dead-end (see stop-notice.ts / #1294) and
|
|
67
|
+
* would exit 10 before the add-work run starts.
|
|
68
|
+
*/
|
|
61
69
|
export function notifyQueueHubNeedsInteractiveMenu(ctx, reason) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
"/gsd queue — run from the GSD TUI to reorder pending milestones",
|
|
70
|
-
"/gsd status — see milestone order and phase",
|
|
71
|
-
],
|
|
72
|
-
});
|
|
70
|
+
ctx.ui.notify([
|
|
71
|
+
`/gsd queue reorder menu needs an interactive session (${reason}).`,
|
|
72
|
+
"Continuing headless with the add-work flow.",
|
|
73
|
+
"",
|
|
74
|
+
" • /gsd queue — run from the GSD TUI to reorder pending milestones",
|
|
75
|
+
" • /gsd status — see milestone order and phase",
|
|
76
|
+
].join("\n"), "warning");
|
|
73
77
|
}
|
|
74
78
|
/** /gsd, /gsd new-milestone, /gsd new-project wizard menus. */
|
|
75
79
|
export function notifySmartEntryNeedsInteractiveMenu(ctx, reason) {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// (drift to import). gsd-core is oblivious to this file and ignores it.
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
8
|
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
-
import { dirname, join } from "node:path";
|
|
9
|
+
import { dirname, join, isAbsolute, normalize } from "node:path";
|
|
10
10
|
/** Current marker schema version. Bump on breaking format changes + migrate. */
|
|
11
11
|
export const COMPAT_MARKER_SCHEMA = 2;
|
|
12
12
|
/** Marker returned when no marker exists yet (fresh project, first gsd-pi run). */
|
|
@@ -170,10 +170,27 @@ function isValidProjectionEntry(x) {
|
|
|
170
170
|
return false;
|
|
171
171
|
return true;
|
|
172
172
|
}
|
|
173
|
+
/**
|
|
174
|
+
* Projection-map keys are repo-relative paths under .gsd/ or .planning/.
|
|
175
|
+
* The marker is repo-controlled content, so a key must never escape its
|
|
176
|
+
* root: reject absolute paths, drive letters, backslashes, and any
|
|
177
|
+
* normalized form that starts with "..". Mirrors the write-side guard in
|
|
178
|
+
* db-writer.ts.
|
|
179
|
+
*/
|
|
180
|
+
function isSafeProjectionKey(key) {
|
|
181
|
+
if (key.length === 0 || key.includes("\\") || key.includes("\0"))
|
|
182
|
+
return false;
|
|
183
|
+
if (isAbsolute(key) || /^[A-Za-z]:/.test(key))
|
|
184
|
+
return false;
|
|
185
|
+
const norm = normalize(key);
|
|
186
|
+
return norm !== ".." && !norm.startsWith("../") && !isAbsolute(norm);
|
|
187
|
+
}
|
|
173
188
|
function isValidProjectionMap(x) {
|
|
174
189
|
if (typeof x !== "object" || x === null)
|
|
175
190
|
return false;
|
|
176
|
-
for (const v of Object.
|
|
191
|
+
for (const [k, v] of Object.entries(x)) {
|
|
192
|
+
if (!isSafeProjectionKey(k))
|
|
193
|
+
return false;
|
|
177
194
|
if (!isValidProjectionEntry(v))
|
|
178
195
|
return false;
|
|
179
196
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// - broadcast queries: WHERE target_worker IS NULL
|
|
13
13
|
// Workers should poll for both forms (their own ID + broadcasts) on each
|
|
14
14
|
// claim cycle.
|
|
15
|
-
import { _getAdapter, isDbAvailable, transaction, } from "../gsd-db.js";
|
|
15
|
+
import { _getAdapter, immediateTransaction, isDbAvailable, transaction, } from "../gsd-db.js";
|
|
16
16
|
/**
|
|
17
17
|
* Enqueue a command. Returns the new row id. Broadcast commands
|
|
18
18
|
* (targetWorker=null) will be claimed by exactly one worker — the IPC
|
|
@@ -47,7 +47,12 @@ export function claimNextCommand(workerId) {
|
|
|
47
47
|
return null;
|
|
48
48
|
const now = new Date().toISOString();
|
|
49
49
|
const db = _getAdapter();
|
|
50
|
-
|
|
50
|
+
// BEGIN IMMEDIATE: this is a read-then-write claim. Under WAL, a deferred
|
|
51
|
+
// transaction that reads first and then upgrades to a writer can fail with
|
|
52
|
+
// SQLITE_BUSY_SNAPSHOT (not retried by busy_timeout) when two workers race;
|
|
53
|
+
// taking the write lock up front serializes claimants so the loser waits
|
|
54
|
+
// and then sees the row already claimed (changes !== 1 → null).
|
|
55
|
+
return immediateTransaction(() => {
|
|
51
56
|
// Find the oldest unclaimed command targeted at this worker OR
|
|
52
57
|
// broadcast. The partial index covers both via NULL-in-B-tree.
|
|
53
58
|
const row = db.prepare(`SELECT id, target_worker, command, args_json, enqueued_at,
|
|
@@ -18,7 +18,7 @@ import { createBaseSchemaObjects } from "../db-base-schema.js";
|
|
|
18
18
|
import { createCoordinationTablesV24 } from "../db-coordination-schema.js";
|
|
19
19
|
import { createDbConnectionCache } from "../db-connection-cache.js";
|
|
20
20
|
import { backupDatabaseBeforeMigration, isMigrationBackupError } from "../db-migration-backup.js";
|
|
21
|
-
import { applyMigrationV2Artifacts, applyMigrationV3Memories, applyMigrationV4DecisionMadeBy, applyMigrationV5HierarchyTables, applyMigrationV6SliceSummaries, applyMigrationV7Dependencies, applyMigrationV8PlanningFields, applyMigrationV9Ordering, applyMigrationV10ReplanTrigger, applyMigrationV11TaskPlanning, applyMigrationV12QualityGates, applyMigrationV13HotPathIndexes, applyMigrationV14SliceDependencies, applyMigrationV15AuditTables, applyMigrationV16EscalationSource, applyMigrationV17TaskEscalation, applyMigrationV18MemorySources, applyMigrationV19MemoryFts, applyMigrationV20MemoryRelations, applyMigrationV21StructuredMemories, applyMigrationV22QualityGateRepair, applyMigrationV23MilestoneQueue, applyMigrationV26MilestoneCommitAttributions, applyMigrationV27ArtifactHash, applyMigrationV28MemoryLastHitAt, applyMigrationV29RepositoryTargets, } from "../db-migration-steps.js";
|
|
21
|
+
import { applyMigrationV2Artifacts, applyMigrationV3Memories, applyMigrationV4DecisionMadeBy, applyMigrationV5HierarchyTables, applyMigrationV6SliceSummaries, applyMigrationV7Dependencies, applyMigrationV8PlanningFields, applyMigrationV9Ordering, applyMigrationV10ReplanTrigger, applyMigrationV11TaskPlanning, applyMigrationV12QualityGates, applyMigrationV13HotPathIndexes, applyMigrationV14SliceDependencies, applyMigrationV15AuditTables, applyMigrationV16EscalationSource, applyMigrationV17TaskEscalation, applyMigrationV18MemorySources, applyMigrationV19MemoryFts, applyMigrationV20MemoryRelations, applyMigrationV21StructuredMemories, applyMigrationV22QualityGateRepair, applyMigrationV23MilestoneQueue, applyMigrationV26MilestoneCommitAttributions, applyMigrationV27ArtifactHash, applyMigrationV28MemoryLastHitAt, applyMigrationV29RepositoryTargets, applyMigrationV30ReworkBriefs, } from "../db-migration-steps.js";
|
|
22
22
|
import { isMemoriesFtsAvailableSchema, rebuildMemoriesFtsSchemaOnce, tryCreateMemoriesFtsSchema, } from "../db-memory-fts-schema.js";
|
|
23
23
|
import { createDbOpenState } from "../db-open-state.js";
|
|
24
24
|
import { createRuntimeKvTableV25 } from "../db-runtime-kv-schema.js";
|
|
@@ -55,7 +55,7 @@ const providerLoader = createSqliteProviderLoader({
|
|
|
55
55
|
nodeVersion: process.versions.node,
|
|
56
56
|
writeStderr: (message) => process.stderr.write(message),
|
|
57
57
|
});
|
|
58
|
-
export const SCHEMA_VERSION =
|
|
58
|
+
export const SCHEMA_VERSION = 30;
|
|
59
59
|
function initSchema(db, fileBacked, dbPath) {
|
|
60
60
|
const conservativeFilePragmas = fileBacked && _isLikelyWslDrvFsPathForTest(dbPath);
|
|
61
61
|
if (fileBacked)
|
|
@@ -80,19 +80,41 @@ function initSchema(db, fileBacked, dbPath) {
|
|
|
80
80
|
});
|
|
81
81
|
const existing = db.prepare("SELECT count(*) as cnt FROM schema_version").get();
|
|
82
82
|
if (existing && existing["cnt"] === 0) {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
83
|
+
// An empty schema_version table usually means a fresh install, but it can
|
|
84
|
+
// also be a legacy/truncated DB that already holds user data. Stamping
|
|
85
|
+
// that DB SCHEMA_VERSION without running migrations would mis-mark it as
|
|
86
|
+
// fully migrated and break at first query. Probe before stamping.
|
|
87
|
+
const hasData = ["milestones", "decisions", "memories"].some((t) => {
|
|
88
|
+
try {
|
|
89
|
+
const r = db.prepare(`SELECT count(*) as cnt FROM ${t}`).get();
|
|
90
|
+
return (r?.["cnt"] ?? 0) > 0;
|
|
91
|
+
}
|
|
92
|
+
catch { /* table absent on a truly fresh DB — treat as no data */
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
if (hasData) {
|
|
97
|
+
// Legacy DB with data but no version row: record the baseline so
|
|
98
|
+
// migrateSchema runs the full chain instead of stamping the current version.
|
|
99
|
+
recordSchemaVersion(db, 1);
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
createCoordinationTablesV24(db);
|
|
103
|
+
createRuntimeKvTableV25(db);
|
|
104
|
+
// Fresh install — all tables are created above with the full current schema,
|
|
105
|
+
// so it is safe to create all migration-specific indexes here. For existing
|
|
106
|
+
// databases these indexes are created inside the individual migration guards
|
|
107
|
+
// in migrateSchema() after the corresponding columns have been added.
|
|
108
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_escalation_pending ON tasks(milestone_id, slice_id, escalation_pending)");
|
|
109
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_scope ON memories(scope)");
|
|
110
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_kind ON memory_sources(kind)");
|
|
111
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_sources_scope ON memory_sources(scope)");
|
|
112
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_from ON memory_relations(from_id)");
|
|
113
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_memory_relations_to ON memory_relations(to_id)");
|
|
114
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
|
|
115
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
|
|
116
|
+
recordSchemaVersion(db, SCHEMA_VERSION);
|
|
117
|
+
}
|
|
96
118
|
}
|
|
97
119
|
db.exec("COMMIT");
|
|
98
120
|
}
|
|
@@ -143,9 +165,16 @@ function copyQualityGateRowsToRepairedTable(db) {
|
|
|
143
165
|
FROM quality_gates
|
|
144
166
|
`);
|
|
145
167
|
}
|
|
168
|
+
let _migrationFaultForTest = false;
|
|
169
|
+
/** Test-only: force migrateSchema to throw after applying its steps but before COMMIT. */
|
|
170
|
+
export function _setMigrationFaultForTest(v) { _migrationFaultForTest = v; }
|
|
146
171
|
function migrateSchema(db, dbPath) {
|
|
147
172
|
const currentVersion = getCurrentSchemaVersion(db);
|
|
148
|
-
if (currentVersion
|
|
173
|
+
if (currentVersion > SCHEMA_VERSION) {
|
|
174
|
+
throw new Error(`gsd.db schema is v${currentVersion}, newer than the v${SCHEMA_VERSION} this gsd-pi supports. ` +
|
|
175
|
+
`Update gsd-pi (npm i -g @opengsd/gsd-pi) before opening this project.`);
|
|
176
|
+
}
|
|
177
|
+
if (currentVersion === SCHEMA_VERSION)
|
|
149
178
|
return;
|
|
150
179
|
backupDatabaseBeforeMigration(db, dbPath, currentVersion, {
|
|
151
180
|
existsSync,
|
|
@@ -282,6 +311,12 @@ function migrateSchema(db, dbPath) {
|
|
|
282
311
|
applyMigrationV29RepositoryTargets(db);
|
|
283
312
|
recordSchemaVersion(db, 29);
|
|
284
313
|
}
|
|
314
|
+
if (currentVersion < 30) {
|
|
315
|
+
applyMigrationV30ReworkBriefs(db);
|
|
316
|
+
recordSchemaVersion(db, 30);
|
|
317
|
+
}
|
|
318
|
+
if (_migrationFaultForTest)
|
|
319
|
+
throw new Error("migration fault injected for test");
|
|
285
320
|
db.exec("COMMIT");
|
|
286
321
|
}
|
|
287
322
|
catch (err) {
|
|
@@ -172,7 +172,11 @@ export function skipSliceCascade(milestoneId, sliceId) {
|
|
|
172
172
|
outcome = { ok: false, reason: "slice-not-found" };
|
|
173
173
|
return;
|
|
174
174
|
}
|
|
175
|
-
|
|
175
|
+
// Reject any closed slice except "skipped" (which falls through to the
|
|
176
|
+
// wasAlreadySkipped no-op). isClosedStatus covers the "closed"/"done"
|
|
177
|
+
// aliases too — hand-picking literals here nulls a completed slice's
|
|
178
|
+
// completed_at on re-skip.
|
|
179
|
+
if (isClosedStatus(slice.status) && slice.status !== "skipped") {
|
|
176
180
|
outcome = { ok: false, reason: "slice-already-complete" };
|
|
177
181
|
return;
|
|
178
182
|
}
|
|
@@ -37,22 +37,29 @@ function requireDb() {
|
|
|
37
37
|
export function applyStatusTransition(t) {
|
|
38
38
|
const db = requireDb();
|
|
39
39
|
const completedAt = t.completedAt ?? null;
|
|
40
|
+
const preserve = t.preserveCompletion ? 1 : 0;
|
|
40
41
|
switch (t.entity) {
|
|
41
42
|
case "task":
|
|
42
|
-
db.prepare(`UPDATE tasks SET status = :status,
|
|
43
|
+
db.prepare(`UPDATE tasks SET status = :status,
|
|
44
|
+
completed_at = CASE WHEN :preserve_completion = 1 AND tasks.completed_at IS NOT NULL
|
|
45
|
+
THEN tasks.completed_at ELSE :completed_at END
|
|
43
46
|
WHERE milestone_id = :milestone_id AND slice_id = :slice_id AND id = :id`).run({
|
|
44
47
|
":status": t.status,
|
|
45
48
|
":completed_at": completedAt,
|
|
49
|
+
":preserve_completion": preserve,
|
|
46
50
|
":milestone_id": t.milestoneId,
|
|
47
51
|
":slice_id": t.sliceId,
|
|
48
52
|
":id": t.taskId,
|
|
49
53
|
});
|
|
50
54
|
return;
|
|
51
55
|
case "slice":
|
|
52
|
-
db.prepare(`UPDATE slices SET status = :status,
|
|
56
|
+
db.prepare(`UPDATE slices SET status = :status,
|
|
57
|
+
completed_at = CASE WHEN :preserve_completion = 1 AND slices.completed_at IS NOT NULL
|
|
58
|
+
THEN slices.completed_at ELSE :completed_at END
|
|
53
59
|
WHERE milestone_id = :milestone_id AND id = :id`).run({
|
|
54
60
|
":status": t.status,
|
|
55
61
|
":completed_at": completedAt,
|
|
62
|
+
":preserve_completion": preserve,
|
|
56
63
|
":milestone_id": t.milestoneId,
|
|
57
64
|
":id": t.sliceId,
|
|
58
65
|
});
|
|
@@ -63,7 +70,10 @@ export function applyStatusTransition(t) {
|
|
|
63
70
|
if (currentStatus && isClosedStatus(currentStatus) && !isClosedStatus(t.status)) {
|
|
64
71
|
throw new Error(`Cannot update closed milestone ${t.milestoneId} from ${currentStatus} to ${t.status}; use gsd_milestone_reopen for an explicit reopen.`);
|
|
65
72
|
}
|
|
66
|
-
db.prepare(`UPDATE milestones SET status = :status,
|
|
73
|
+
db.prepare(`UPDATE milestones SET status = :status,
|
|
74
|
+
completed_at = CASE WHEN :preserve_completion = 1 AND milestones.completed_at IS NOT NULL
|
|
75
|
+
THEN milestones.completed_at ELSE :completed_at END
|
|
76
|
+
WHERE id = :id`).run({ ":status": t.status, ":completed_at": completedAt, ":preserve_completion": preserve, ":id": t.milestoneId });
|
|
67
77
|
return;
|
|
68
78
|
}
|
|
69
79
|
}
|
|
@@ -221,6 +221,32 @@ export function createBaseSchemaObjects(db, hooks) {
|
|
|
221
221
|
created_at TEXT NOT NULL DEFAULT '',
|
|
222
222
|
FOREIGN KEY (milestone_id) REFERENCES milestones(id)
|
|
223
223
|
)
|
|
224
|
+
`);
|
|
225
|
+
db.exec(`
|
|
226
|
+
CREATE TABLE IF NOT EXISTS rework_briefs (
|
|
227
|
+
id TEXT PRIMARY KEY,
|
|
228
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
229
|
+
slice_id TEXT NOT NULL DEFAULT '',
|
|
230
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
231
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
232
|
+
updated_at TEXT NOT NULL DEFAULT ''
|
|
233
|
+
)
|
|
234
|
+
`);
|
|
235
|
+
db.exec(`
|
|
236
|
+
CREATE TABLE IF NOT EXISTS rework_brief_findings (
|
|
237
|
+
brief_id TEXT NOT NULL,
|
|
238
|
+
finding_id TEXT NOT NULL,
|
|
239
|
+
severity TEXT NOT NULL DEFAULT 'blocking',
|
|
240
|
+
description TEXT NOT NULL DEFAULT '',
|
|
241
|
+
required_fix TEXT NOT NULL DEFAULT '',
|
|
242
|
+
verification_commands TEXT NOT NULL DEFAULT '[]',
|
|
243
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
244
|
+
evidence TEXT NOT NULL DEFAULT '',
|
|
245
|
+
decision_ref TEXT NOT NULL DEFAULT '',
|
|
246
|
+
updated_at TEXT NOT NULL DEFAULT '',
|
|
247
|
+
PRIMARY KEY (brief_id, finding_id),
|
|
248
|
+
FOREIGN KEY (brief_id) REFERENCES rework_briefs(id)
|
|
249
|
+
)
|
|
224
250
|
`);
|
|
225
251
|
db.exec(`
|
|
226
252
|
CREATE TABLE IF NOT EXISTS assessments (
|
|
@@ -336,6 +362,8 @@ export function createBaseSchemaObjects(db, hooks) {
|
|
|
336
362
|
`);
|
|
337
363
|
db.exec("CREATE INDEX IF NOT EXISTS idx_memories_active ON memories(superseded_by)");
|
|
338
364
|
db.exec("CREATE INDEX IF NOT EXISTS idx_replan_history_milestone ON replan_history(milestone_id, created_at)");
|
|
365
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
|
|
366
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
|
|
339
367
|
db.exec("CREATE INDEX IF NOT EXISTS idx_tasks_active ON tasks(milestone_id, slice_id, status)");
|
|
340
368
|
db.exec("CREATE INDEX IF NOT EXISTS idx_slices_active ON slices(milestone_id, status)");
|
|
341
369
|
db.exec("CREATE INDEX IF NOT EXISTS idx_milestones_status ON milestones(status)");
|
|
@@ -418,3 +418,33 @@ export function applyMigrationV22QualityGateRepair(db, hooks) {
|
|
|
418
418
|
ensureColumn(db, "quality_gates", "scope", "ALTER TABLE quality_gates ADD COLUMN scope TEXT NOT NULL DEFAULT 'slice'");
|
|
419
419
|
ensureColumn(db, "assessments", "scope", "ALTER TABLE assessments ADD COLUMN scope TEXT NOT NULL DEFAULT ''");
|
|
420
420
|
}
|
|
421
|
+
export function applyMigrationV30ReworkBriefs(db) {
|
|
422
|
+
db.exec(`
|
|
423
|
+
CREATE TABLE IF NOT EXISTS rework_briefs (
|
|
424
|
+
id TEXT PRIMARY KEY,
|
|
425
|
+
milestone_id TEXT NOT NULL DEFAULT '',
|
|
426
|
+
slice_id TEXT NOT NULL DEFAULT '',
|
|
427
|
+
task_id TEXT NOT NULL DEFAULT '',
|
|
428
|
+
created_at TEXT NOT NULL DEFAULT '',
|
|
429
|
+
updated_at TEXT NOT NULL DEFAULT ''
|
|
430
|
+
)
|
|
431
|
+
`);
|
|
432
|
+
db.exec(`
|
|
433
|
+
CREATE TABLE IF NOT EXISTS rework_brief_findings (
|
|
434
|
+
brief_id TEXT NOT NULL,
|
|
435
|
+
finding_id TEXT NOT NULL,
|
|
436
|
+
severity TEXT NOT NULL DEFAULT 'blocking',
|
|
437
|
+
description TEXT NOT NULL DEFAULT '',
|
|
438
|
+
required_fix TEXT NOT NULL DEFAULT '',
|
|
439
|
+
verification_commands TEXT NOT NULL DEFAULT '[]',
|
|
440
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
441
|
+
evidence TEXT NOT NULL DEFAULT '',
|
|
442
|
+
decision_ref TEXT NOT NULL DEFAULT '',
|
|
443
|
+
updated_at TEXT NOT NULL DEFAULT '',
|
|
444
|
+
PRIMARY KEY (brief_id, finding_id),
|
|
445
|
+
FOREIGN KEY (brief_id) REFERENCES rework_briefs(id)
|
|
446
|
+
)
|
|
447
|
+
`);
|
|
448
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_rework_briefs_task ON rework_briefs(milestone_id, slice_id, task_id)");
|
|
449
|
+
db.exec("CREATE INDEX IF NOT EXISTS idx_rework_findings_status ON rework_brief_findings(brief_id, severity, status)");
|
|
450
|
+
}
|
|
@@ -12,8 +12,11 @@ export function ensureColumn(db, table, column, ddl) {
|
|
|
12
12
|
db.exec(ddl);
|
|
13
13
|
}
|
|
14
14
|
export function getCurrentSchemaVersion(db) {
|
|
15
|
+
// MAX(version) on an empty table returns a row whose value is NULL —
|
|
16
|
+
// treat that (and any non-numeric value) as version 0, not NULL-as-number.
|
|
15
17
|
const row = db.prepare("SELECT MAX(version) as v FROM schema_version").get();
|
|
16
|
-
|
|
18
|
+
const v = row?.["v"];
|
|
19
|
+
return typeof v === "number" ? v : 0;
|
|
17
20
|
}
|
|
18
21
|
export function recordSchemaVersion(db, version) {
|
|
19
22
|
db.prepare("INSERT INTO schema_version (version, applied_at) VALUES (:version, :applied_at)").run({
|
|
@@ -128,7 +128,7 @@ Diagnostics record the file path, scope (global/project), severity (error/warnin
|
|
|
128
128
|
- Two equivalent ways to set it: inline as `models.<phase>.thinking`, or as a separate `thinking:` block keyed by phase. For the same phase, the inline value wins over the block; project preferences win over global; a phase that's unset inherits via the same sibling chain as `models` (e.g. `discuss → planning`).
|
|
129
129
|
- If no thinking is configured for a phase, the session level (set via `/model`) is used, exactly as before — this is fully backward-compatible.
|
|
130
130
|
- `execute-task` (code-writing) has a measured reasoning floor of `medium`: at lower levels models stop planning edits and thrash on file re-reads. The floor applies to the session/default path. An **explicit** `execution` thinking level bypasses the floor and is honored verbatim (with a one-time advisory) — set `execution: low` deliberately if you want it.
|
|
131
|
-
- Levels a model can't support are clamped to the nearest supported level at dispatch and never sent to the provider, so a model/level mismatch never fails a unit mid-run. `xhigh` is
|
|
131
|
+
- Levels a model can't support are clamped to the nearest supported level at dispatch and never sent to the provider, so a model/level mismatch never fails a unit mid-run. `xhigh` support is model-dependent; current examples include OpenAI Codex Max models and Claude Sonnet 5 on Amazon Bedrock.
|
|
132
132
|
|
|
133
133
|
- `skill_staleness_days`: number — skills unused for this many days get deprioritized during discovery. Set to `0` to disable staleness tracking. Default: `60`.
|
|
134
134
|
|
|
@@ -482,13 +482,13 @@ Inline form — thinking pinned alongside the model:
|
|
|
482
482
|
version: 1
|
|
483
483
|
models:
|
|
484
484
|
planning:
|
|
485
|
-
model:
|
|
485
|
+
model: bedrock/global.anthropic.claude-sonnet-5
|
|
486
486
|
thinking: xhigh
|
|
487
487
|
execution:
|
|
488
|
-
model:
|
|
488
|
+
model: bedrock/global.anthropic.claude-sonnet-5
|
|
489
489
|
thinking: low # explicit → bypasses the execute-task medium floor
|
|
490
490
|
validation:
|
|
491
|
-
model:
|
|
491
|
+
model: bedrock/global.anthropic.claude-sonnet-5
|
|
492
492
|
thinking: high
|
|
493
493
|
---
|
|
494
494
|
```
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { saveFile } from "./files.js";
|
|
4
|
+
import { gsdRoot } from "./paths.js";
|
|
5
|
+
function buildDoctorHistorySummary(report, errorCount, warningCount, issueDetails) {
|
|
6
|
+
const summaryParts = [];
|
|
7
|
+
if (report.ok) {
|
|
8
|
+
summaryParts.push("Clean");
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
const counts = [];
|
|
12
|
+
if (errorCount > 0)
|
|
13
|
+
counts.push(`${errorCount} error${errorCount > 1 ? "s" : ""}`);
|
|
14
|
+
if (warningCount > 0)
|
|
15
|
+
counts.push(`${warningCount} warning${warningCount > 1 ? "s" : ""}`);
|
|
16
|
+
summaryParts.push(counts.join(", "));
|
|
17
|
+
}
|
|
18
|
+
if (report.fixesApplied.length > 0) {
|
|
19
|
+
summaryParts.push(`${report.fixesApplied.length} fixed`);
|
|
20
|
+
}
|
|
21
|
+
if (issueDetails && issueDetails.length > 0) {
|
|
22
|
+
const topIssue = issueDetails.find(i => i.severity === "error") ?? issueDetails[0];
|
|
23
|
+
summaryParts.push(topIssue.message);
|
|
24
|
+
}
|
|
25
|
+
return summaryParts.join(" · ");
|
|
26
|
+
}
|
|
27
|
+
export async function appendDoctorHistory(basePath, report) {
|
|
28
|
+
try {
|
|
29
|
+
const historyPath = join(gsdRoot(basePath), "doctor-history.jsonl");
|
|
30
|
+
const errorCount = report.issues.filter(i => i.severity === "error").length;
|
|
31
|
+
const warningCount = report.issues.filter(i => i.severity === "warning").length;
|
|
32
|
+
const issueDetails = report.issues
|
|
33
|
+
.filter(i => i.severity === "error" || i.severity === "warning")
|
|
34
|
+
.slice(0, 10) // cap to keep JSONL lines bounded
|
|
35
|
+
.map(i => ({ severity: i.severity, code: i.code, message: i.message, unitId: i.unitId }));
|
|
36
|
+
const entry = JSON.stringify({
|
|
37
|
+
ts: new Date().toISOString(),
|
|
38
|
+
ok: report.ok,
|
|
39
|
+
errors: errorCount,
|
|
40
|
+
warnings: warningCount,
|
|
41
|
+
fixes: report.fixesApplied.length,
|
|
42
|
+
codes: [...new Set(report.issues.map(i => i.code))],
|
|
43
|
+
issues: issueDetails.length > 0 ? issueDetails : undefined,
|
|
44
|
+
fixDescriptions: report.fixesApplied.length > 0 ? report.fixesApplied : undefined,
|
|
45
|
+
scope: report.scope,
|
|
46
|
+
summary: buildDoctorHistorySummary(report, errorCount, warningCount, issueDetails),
|
|
47
|
+
});
|
|
48
|
+
const existing = existsSync(historyPath) ? readFileSync(historyPath, "utf-8") : "";
|
|
49
|
+
await saveFile(historyPath, existing + entry + "\n");
|
|
50
|
+
}
|
|
51
|
+
catch { /* non-fatal */ }
|
|
52
|
+
}
|
|
53
|
+
/** Read the last N doctor history entries. Returns most-recent-first. */
|
|
54
|
+
export async function readDoctorHistory(basePath, lastN = 50) {
|
|
55
|
+
try {
|
|
56
|
+
const historyPath = join(gsdRoot(basePath), "doctor-history.jsonl");
|
|
57
|
+
if (!existsSync(historyPath))
|
|
58
|
+
return [];
|
|
59
|
+
const lines = readFileSync(historyPath, "utf-8").split("\n").filter(l => l.trim());
|
|
60
|
+
return lines.slice(-lastN).reverse().map(l => JSON.parse(l));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
}
|