@opengsd/gsd-pi 1.8.1 → 1.9.0-dev.5c1a3ff2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -8
- package/dist/cli.js +5 -1
- package/dist/headless-events.d.ts +2 -1
- package/dist/headless-events.js +11 -3
- package/dist/headless-milestone-readiness.d.ts +29 -0
- package/dist/headless-milestone-readiness.js +161 -0
- package/dist/headless.js +25 -2
- package/dist/print-mode-exit.d.ts +12 -0
- package/dist/print-mode-exit.js +14 -0
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +18 -49
- package/dist/resources/extensions/browser-tools/capture.js +2 -77
- package/dist/resources/extensions/browser-tools/screenshot-constraints.js +83 -0
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +17 -2
- package/dist/resources/extensions/claude-code-cli/turn-assembler.js +30 -2
- package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +16 -10
- package/dist/resources/extensions/gsd/auto-dispatch.js +74 -19
- package/dist/resources/extensions/gsd/auto-post-unit.js +4 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +125 -18
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +80 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +31 -5
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +88 -50
- package/dist/resources/extensions/gsd/command-feedback.js +16 -12
- package/dist/resources/extensions/gsd/compat/compat-marker.js +19 -2
- package/dist/resources/extensions/gsd/constants.js +12 -13
- package/dist/resources/extensions/gsd/context-masker.js +97 -21
- package/dist/resources/extensions/gsd/db/command-queue.js +7 -2
- package/dist/resources/extensions/gsd/db/engine.js +51 -16
- package/dist/resources/extensions/gsd/db/writers/cascades.js +5 -1
- package/dist/resources/extensions/gsd/db/writers/status.js +13 -3
- package/dist/resources/extensions/gsd/db-base-schema.js +28 -0
- package/dist/resources/extensions/gsd/db-migration-steps.js +30 -0
- package/dist/resources/extensions/gsd/db-schema-metadata.js +4 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +26 -4
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +3 -6
- package/dist/resources/extensions/gsd/flat-phase-migration.js +156 -21
- package/dist/resources/extensions/gsd/git-service.js +19 -7
- package/dist/resources/extensions/gsd/gsd-db.js +187 -45
- package/dist/resources/extensions/gsd/guided-flow.js +38 -13
- package/dist/resources/extensions/gsd/markdown-renderer.js +17 -13
- package/dist/resources/extensions/gsd/md-importer.js +107 -20
- package/dist/resources/extensions/gsd/migrate/command.js +19 -162
- package/dist/resources/extensions/gsd/migrate/execution.js +98 -0
- package/dist/resources/extensions/gsd/migrate/plan.js +49 -0
- package/dist/resources/extensions/gsd/migrate/planning-writer.js +12 -17
- package/dist/resources/extensions/gsd/migrate/presentation.js +64 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +2 -0
- package/dist/resources/extensions/gsd/model-router.js +11 -0
- package/dist/resources/extensions/gsd/parallel-eligibility.js +5 -4
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +28 -43
- package/dist/resources/extensions/gsd/paths.js +55 -11
- package/dist/resources/extensions/gsd/phase-anchor.js +7 -2
- package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
- package/dist/resources/extensions/gsd/planning-subagent-registry.js +25 -0
- package/dist/resources/extensions/gsd/post-execution-checks.js +4 -4
- package/dist/resources/extensions/gsd/preferences-types.js +5 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +48 -1
- package/dist/resources/extensions/gsd/preferences.js +17 -0
- package/dist/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/dist/resources/extensions/gsd/provider-payload-policy.js +16 -5
- package/dist/resources/extensions/gsd/safety/destructive-guard.js +1 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +26 -1
- package/dist/resources/extensions/gsd/safety/evidence-cross-ref.js +30 -5
- package/dist/resources/extensions/gsd/skill-activation.js +17 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +27 -13
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +13 -3
- package/dist/resources/extensions/gsd/stop-notice.js +15 -1
- package/dist/resources/extensions/gsd/sync-lock.js +13 -7
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +94 -6
- package/dist/resources/extensions/gsd/tools/plan-task.js +13 -15
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +18 -15
- package/dist/resources/extensions/gsd/tools/reopen-milestone.js +14 -5
- package/dist/resources/extensions/gsd/tools/reopen-slice.js +15 -5
- package/dist/resources/extensions/gsd/tools/reopen-task.js +16 -10
- package/dist/resources/extensions/gsd/tools/replan-task.js +128 -0
- package/dist/resources/extensions/gsd/tools/rework-brief.js +74 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +81 -0
- package/dist/resources/extensions/gsd/unit-context-composer.js +28 -5
- package/dist/resources/extensions/gsd/unit-registry.js +4 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +19 -3
- package/dist/resources/extensions/gsd/workflow-projections.js +2 -3
- package/dist/resources/extensions/gsd/workspace.js +2 -1
- package/dist/resources/extensions/gsd/worktree-state-projection.js +6 -0
- package/dist/resources/extensions/mac-tools/index.js +31 -9
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +8 -8
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/api/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/mcp-connections/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +5 -5
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +8 -8
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/8357.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-a6fb1847f67f167c.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{layout-b35cbfff38aaf4cf.js → layout-4ae2d68984392bbf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-72a856634ad14c10.js +1 -0
- package/dist/web/standalone/.next/static/chunks/{main-app-590a74400e35f685.js → main-app-90d1d8d5e5d2dc6b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-1115d46ac61b9823.js +1 -0
- package/dist/web/standalone/.next/static/css/3b1ceb7abfb9a230.css +1 -0
- package/dist/web/standalone/node_modules/@gsd/native/package.json +1 -1
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/package.json +0 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/web-mode.js +31 -3
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +12 -10
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/workflow.d.ts +14 -0
- package/packages/contracts/dist/workflow.d.ts.map +1 -1
- package/packages/contracts/dist/workflow.js +16 -0
- package/packages/contracts/dist/workflow.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/dist/cloud-config.d.ts +1 -1
- package/packages/daemon/dist/cloud-config.d.ts.map +1 -1
- package/packages/daemon/dist/cloud-config.js +5 -1
- package/packages/daemon/dist/cloud-config.js.map +1 -1
- package/packages/daemon/dist/cloud-config.test.js +51 -1
- package/packages/daemon/dist/cloud-config.test.js.map +1 -1
- package/packages/daemon/dist/local-tool-executor.d.ts.map +1 -1
- package/packages/daemon/dist/local-tool-executor.js +2 -0
- package/packages/daemon/dist/local-tool-executor.js.map +1 -1
- package/packages/daemon/package.json +6 -6
- package/packages/gsd-agent-core/dist/compaction/compaction.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/compaction/compaction.js +36 -4
- package/packages/gsd-agent-core/dist/compaction/compaction.js.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/sdk.js +1 -0
- package/packages/gsd-agent-core/dist/sdk.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/dist/cli.d.ts +5 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cli.js +160 -0
- package/packages/gsd-cloud/dist/cli.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts +19 -0
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.js +231 -0
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-config.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js +118 -0
- package/packages/gsd-cloud/dist/cloud-config.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js +37 -0
- package/packages/gsd-cloud/dist/cloud-gateway-lookup.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +35 -0
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js +258 -0
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js +88 -0
- package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts +3 -0
- package/packages/gsd-cloud/dist/cloud-token.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/cloud-token.js +37 -0
- package/packages/gsd-cloud/dist/cloud-token.js.map +1 -0
- package/packages/gsd-cloud/dist/config.d.ts +17 -0
- package/packages/gsd-cloud/dist/config.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/config.js +146 -0
- package/packages/gsd-cloud/dist/config.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts +24 -0
- package/packages/gsd-cloud/dist/device-flow.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.js +128 -0
- package/packages/gsd-cloud/dist/device-flow.js.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/device-flow.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/device-flow.test.js +155 -0
- package/packages/gsd-cloud/dist/device-flow.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/claude-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts +6 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js +15 -0
- package/packages/gsd-cloud/dist/executors/codex-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts +28 -0
- package/packages/gsd-cloud/dist/executors/executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/executor.js +11 -0
- package/packages/gsd-cloud/dist/executors/executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts +34 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js +179 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js +44 -0
- package/packages/gsd-cloud/dist/executors/gsd-pi-executor.test.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts +17 -0
- package/packages/gsd-cloud/dist/executors/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/index.js +29 -0
- package/packages/gsd-cloud/dist/executors/index.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts +36 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js +176 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.js.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js +34 -0
- package/packages/gsd-cloud/dist/executors/mcp-stdio-client.test.js.map +1 -0
- package/packages/gsd-cloud/dist/index.d.ts +7 -0
- package/packages/gsd-cloud/dist/index.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/index.js +8 -0
- package/packages/gsd-cloud/dist/index.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts +16 -0
- package/packages/gsd-cloud/dist/inject-gateway.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.js +29 -0
- package/packages/gsd-cloud/dist/inject-gateway.js.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js +41 -0
- package/packages/gsd-cloud/dist/inject-gateway.test.js.map +1 -0
- package/packages/gsd-cloud/dist/logger.d.ts +25 -0
- package/packages/gsd-cloud/dist/logger.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/logger.js +72 -0
- package/packages/gsd-cloud/dist/logger.js.map +1 -0
- package/packages/gsd-cloud/dist/types.d.ts +51 -0
- package/packages/gsd-cloud/dist/types.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/types.js +9 -0
- package/packages/gsd-cloud/dist/types.js.map +1 -0
- package/packages/gsd-cloud/package.json +3 -3
- package/packages/mcp-server/README.md +15 -2
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +5 -5
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +4 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +64 -2
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -4
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -1
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +119 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +107 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +1 -0
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +25 -1
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js +1 -1
- package/packages/pi-coding-agent/dist/core/capability-patches.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +11 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +2 -2
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +18 -49
- package/src/resources/extensions/browser-tools/capture.ts +2 -86
- package/src/resources/extensions/browser-tools/screenshot-constraints.ts +94 -0
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +18 -1
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -0
- package/src/resources/extensions/claude-code-cli/turn-assembler.ts +30 -2
- package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +16 -9
- package/src/resources/extensions/gsd/auto-dispatch.ts +86 -19
- package/src/resources/extensions/gsd/auto-post-unit.ts +4 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +142 -16
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +92 -4
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +39 -10
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +87 -53
- package/src/resources/extensions/gsd/command-feedback.ts +19 -12
- package/src/resources/extensions/gsd/compat/compat-marker.ts +21 -4
- package/src/resources/extensions/gsd/constants.ts +14 -13
- package/src/resources/extensions/gsd/context-masker.ts +98 -2
- package/src/resources/extensions/gsd/db/command-queue.ts +7 -1
- package/src/resources/extensions/gsd/db/engine.ts +53 -17
- package/src/resources/extensions/gsd/db/writers/cascades.ts +5 -1
- package/src/resources/extensions/gsd/db/writers/status.ts +25 -8
- package/src/resources/extensions/gsd/db-base-schema.ts +30 -0
- package/src/resources/extensions/gsd/db-migration-steps.ts +32 -0
- package/src/resources/extensions/gsd/db-schema-metadata.ts +4 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +26 -4
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +3 -5
- package/src/resources/extensions/gsd/flat-phase-migration.ts +160 -19
- package/src/resources/extensions/gsd/git-service.ts +19 -6
- package/src/resources/extensions/gsd/gsd-db.ts +255 -52
- package/src/resources/extensions/gsd/guided-flow.ts +48 -12
- package/src/resources/extensions/gsd/markdown-renderer.ts +25 -21
- package/src/resources/extensions/gsd/md-importer.ts +114 -16
- package/src/resources/extensions/gsd/migrate/command.ts +21 -227
- package/src/resources/extensions/gsd/migrate/execution.ts +136 -0
- package/src/resources/extensions/gsd/migrate/plan.ts +101 -0
- package/src/resources/extensions/gsd/migrate/planning-writer.ts +12 -20
- package/src/resources/extensions/gsd/migrate/presentation.ts +83 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +2 -0
- package/src/resources/extensions/gsd/model-router.ts +12 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +5 -4
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +37 -40
- package/src/resources/extensions/gsd/paths.ts +62 -11
- package/src/resources/extensions/gsd/phase-anchor.ts +8 -2
- package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
- package/src/resources/extensions/gsd/planning-subagent-registry.ts +31 -0
- package/src/resources/extensions/gsd/post-execution-checks.ts +4 -4
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +62 -0
- package/src/resources/extensions/gsd/preferences.ts +25 -0
- package/src/resources/extensions/gsd/prompts/refine-slice.md +2 -2
- package/src/resources/extensions/gsd/provider-payload-policy.ts +18 -4
- package/src/resources/extensions/gsd/safety/destructive-guard.ts +1 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +28 -1
- package/src/resources/extensions/gsd/safety/evidence-cross-ref.ts +31 -5
- package/src/resources/extensions/gsd/skill-activation.ts +17 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +30 -13
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +16 -3
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +2 -2
- package/src/resources/extensions/gsd/stop-notice.ts +18 -1
- package/src/resources/extensions/gsd/sync-lock.ts +14 -6
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +5 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/closeout-git-deferral.test.ts +96 -1
- package/src/resources/extensions/gsd/tests/command-feedback.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +362 -1
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
- package/src/resources/extensions/gsd/tests/db-engine-migrate-guards.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/destructive-confirmation.test.ts +33 -0
- package/src/resources/extensions/gsd/tests/destructive-guard.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/discuss-routing-fixes.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/evidence-cross-ref.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/evidence-xref-gsd-exec.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/external-edit-scoped-import.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +202 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/import-slice-milestone-completion-preserve.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/integration/paths.test.ts +22 -4
- package/src/resources/extensions/gsd/tests/integration-branch-meta-location.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +5 -5
- package/src/resources/extensions/gsd/tests/migrate-plan.test.ts +68 -0
- package/src/resources/extensions/gsd/tests/migrate-presentation.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/migrate-safety-audit.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/milestone-leases.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parallel-eligibility-file-overlap.test.ts +146 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/phase-anchor.test.ts +32 -4
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +26 -23
- package/src/resources/extensions/gsd/tests/planning-writer.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/post-execution-checks.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +84 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/replan-task-handler.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/rework-brief.test.ts +197 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +33 -7
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +20 -16
- package/src/resources/extensions/gsd/tests/skip-slice-cascades-tasks.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +17 -0
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +73 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/workflow-migration-gates.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/write-gate-seam.test.ts +52 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +140 -5
- package/src/resources/extensions/gsd/tools/plan-task.ts +14 -16
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +18 -17
- package/src/resources/extensions/gsd/tools/reopen-milestone.ts +24 -5
- package/src/resources/extensions/gsd/tools/reopen-slice.ts +25 -5
- package/src/resources/extensions/gsd/tools/reopen-task.ts +23 -9
- package/src/resources/extensions/gsd/tools/replan-task.ts +160 -0
- package/src/resources/extensions/gsd/tools/rework-brief.ts +91 -0
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +92 -0
- package/src/resources/extensions/gsd/types.ts +11 -0
- package/src/resources/extensions/gsd/unit-context-composer.ts +34 -8
- package/src/resources/extensions/gsd/unit-registry.ts +4 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +20 -3
- package/src/resources/extensions/gsd/workflow-projections.ts +2 -3
- package/src/resources/extensions/gsd/workspace.ts +2 -1
- package/src/resources/extensions/gsd/worktree-state-projection.ts +12 -0
- package/src/resources/extensions/mac-tools/index.ts +52 -9
- package/src/resources/extensions/mac-tools/tests/mac-screenshot-payload.test.cjs +70 -0
- package/dist/web/standalone/.next/static/chunks/app/_not-found/page-49f565245e1e4afe.js +0 -1
- package/dist/web/standalone/.next/static/chunks/app/page-bc4c723c6a19c6f0.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ec3eaffc9785ba48.js +0 -1
- package/dist/web/standalone/.next/static/css/18c2fdf261bfc1b7.css +0 -1
- /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{UaXRrOYxBpG9QBINKhZkg → 6YWV7VAPg-jqjfPswrKZb}/_ssgManifest.js +0 -0
|
@@ -7,7 +7,9 @@ import { canonicalToolName } from "../engine-hook-contract.js";
|
|
|
7
7
|
import { loadJsonFileOrNull } from "../json-persistence.js";
|
|
8
8
|
import { getIsolationMode } from "../preferences.js";
|
|
9
9
|
import { compileSubagentPermissionContract } from "../unit-context-manifest.js";
|
|
10
|
+
import { allowedPlanningDispatchAgentsList, isReadOnlyPlanningDispatchAgent, } from "../planning-subagent-registry.js";
|
|
10
11
|
import { logWarning } from "../workflow-logger.js";
|
|
12
|
+
import { acquireSyncLock, releaseSyncLock } from "../sync-lock.js";
|
|
11
13
|
import { isGsdWorktreePath, resolveWorktreeProjectRoot } from "../worktree-root.js";
|
|
12
14
|
import { worktreesDirs } from "../worktree-placement.js";
|
|
13
15
|
import { bashReferencesProjectRootOutsideWorktree } from "../worktree-shell-guard.js";
|
|
@@ -318,12 +320,65 @@ export function refreshWriteGateStateFromDisk(basePath) {
|
|
|
318
320
|
}
|
|
319
321
|
return currentWriteGateSnapshot(basePath);
|
|
320
322
|
}
|
|
323
|
+
const WRITE_GATE_LOCK_NAME = "write-gate.lock";
|
|
324
|
+
/**
|
|
325
|
+
* Test-only seam: fires once inside the held cross-process lock (after acquire,
|
|
326
|
+
* before the read-merge-write body) with the resolved lock root. Lets a
|
|
327
|
+
* regression test observe that a concurrent process is genuinely locked out of
|
|
328
|
+
* the critical section. Production leaves it null. Follows the repo's
|
|
329
|
+
* `_setGhAvailableForTest` naming convention.
|
|
330
|
+
*/
|
|
331
|
+
let interleaveHookForTest = null;
|
|
332
|
+
export function _setWriteGateInterleaveHookForTest(fn) {
|
|
333
|
+
interleaveHookForTest = fn;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Serialize the read-merge-write critical section across the two processes
|
|
337
|
+
* that share the snapshot file (extension host + workflow MCP child). Atomic
|
|
338
|
+
* rename prevents torn files but not lost updates: without this lock the host
|
|
339
|
+
* can read the snapshot, the child can arm a gate and persist, then the host's
|
|
340
|
+
* later persist overwrites `pendingGateId`/`activeQueuePhase` (last-writer-wins
|
|
341
|
+
* fields) and silently drops the armed HARD-BLOCK gate.
|
|
342
|
+
*
|
|
343
|
+
* Fail-OPEN by contract: if a live peer holds the lock we proceed WITHOUT it —
|
|
344
|
+
* exactly the racy-but-functional behavior that shipped before this lock — and
|
|
345
|
+
* log once. The lock shrinks the race window to ~zero; it must never block,
|
|
346
|
+
* throw, or refuse a gate mutation. The lock is skipped entirely when snapshot
|
|
347
|
+
* persistence is off (no disk file, no cross-process seam).
|
|
348
|
+
*/
|
|
349
|
+
function withWriteGateLock(basePath, fn) {
|
|
350
|
+
if (!shouldPersistWriteGateSnapshot())
|
|
351
|
+
return fn();
|
|
352
|
+
const lockRoot = resolveWriteGateSnapshotRoot(basePath);
|
|
353
|
+
// Materialize `.gsd/` (including a dangling external-state symlink target)
|
|
354
|
+
// before locking. acquireSyncLock's own mkdir does NOT follow a symlink to
|
|
355
|
+
// create its target, so without this the O_EXCL open lands on a missing
|
|
356
|
+
// parent and the lock silently fails open — leaving the seam unserialized
|
|
357
|
+
// for exactly the external-state projects that need it. This is the same
|
|
358
|
+
// directory the persist path ensures anyway.
|
|
359
|
+
try {
|
|
360
|
+
ensureWriteGateSnapshotDirectory(basePath);
|
|
361
|
+
}
|
|
362
|
+
catch { /* best-effort; acquire fails-open below */ }
|
|
363
|
+
const { acquired } = acquireSyncLock(lockRoot, 0, WRITE_GATE_LOCK_NAME);
|
|
364
|
+
if (!acquired) {
|
|
365
|
+
logWarning("intercept", "write-gate: proceeding without cross-process lock (held by live peer)", { lockRoot });
|
|
366
|
+
return fn();
|
|
367
|
+
}
|
|
368
|
+
try {
|
|
369
|
+
interleaveHookForTest?.(lockRoot);
|
|
370
|
+
return fn();
|
|
371
|
+
}
|
|
372
|
+
finally {
|
|
373
|
+
releaseSyncLock(lockRoot, WRITE_GATE_LOCK_NAME);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
321
376
|
/**
|
|
322
377
|
* Read-modify-write primitive for gate mutations. Reconciles the disk
|
|
323
378
|
* snapshot into memory (union merge), applies the mutation on top, then
|
|
324
|
-
* persists
|
|
325
|
-
*
|
|
326
|
-
*
|
|
379
|
+
* persists — all under the cross-process lock (withWriteGateLock). The whole
|
|
380
|
+
* sequence is synchronous, so the reconcile read doubles as the pre-persist
|
|
381
|
+
* merge of concurrent writes; there is no version field.
|
|
327
382
|
*
|
|
328
383
|
* The mutate callback sees the already-reconciled state, so policy checks
|
|
329
384
|
* (e.g. host setPending's verified-on-disk-wins guard) can live inside it
|
|
@@ -335,23 +390,25 @@ export function refreshWriteGateStateFromDisk(basePath) {
|
|
|
335
390
|
*/
|
|
336
391
|
function mutateWriteGateState(basePath, mutate, opts) {
|
|
337
392
|
const state = getWriteGateState(basePath);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
393
|
+
return withWriteGateLock(basePath, () => {
|
|
394
|
+
if (shouldPersistWriteGateSnapshot() && (opts?.reconcile ?? true)) {
|
|
395
|
+
const disk = readDiskSnapshot(basePath);
|
|
396
|
+
if (disk) {
|
|
397
|
+
mergeSnapshotIntoState(state, disk);
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
// Missing OR unparseable on disk: treat as a full reset. Keeping
|
|
401
|
+
// stale in-memory state across a corrupt snapshot would persist it
|
|
402
|
+
// back on this very mutation and defeat the documented
|
|
403
|
+
// "delete the file to clear the HARD BLOCK gate" escape hatch.
|
|
404
|
+
replaceStateFromSnapshot(state, EMPTY_SNAPSHOT);
|
|
405
|
+
}
|
|
349
406
|
}
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
407
|
+
if (mutate(state) === false)
|
|
408
|
+
return false;
|
|
409
|
+
persistWriteGateSnapshot(basePath, opts?.writer ?? defaultWriteGateWriter());
|
|
410
|
+
return true;
|
|
411
|
+
});
|
|
355
412
|
}
|
|
356
413
|
export function isDepthVerified(basePath = process.cwd()) {
|
|
357
414
|
return getWriteGateState(basePath).verifiedDepthMilestones.size > 0;
|
|
@@ -550,13 +607,15 @@ export const childWriteGateAdapter = {
|
|
|
550
607
|
};
|
|
551
608
|
function childMutate(basePath, mutate) {
|
|
552
609
|
const state = getWriteGateState(basePath);
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
610
|
+
withWriteGateLock(basePath, () => {
|
|
611
|
+
if (shouldPersistWriteGateSnapshot()) {
|
|
612
|
+
// Always-fresh: disk is the only truth for the child; discard any
|
|
613
|
+
// cross-turn in-memory residue before mutating.
|
|
614
|
+
replaceStateFromSnapshot(state, readDiskSnapshot(basePath) ?? EMPTY_SNAPSHOT);
|
|
615
|
+
}
|
|
616
|
+
mutate(state);
|
|
617
|
+
persistWriteGateSnapshot(basePath, "child");
|
|
618
|
+
});
|
|
560
619
|
}
|
|
561
620
|
/**
|
|
562
621
|
* Which adapter the module-level convenience exports (markDepthVerified,
|
|
@@ -923,29 +982,8 @@ export function shouldBlockQueueExecutionInSnapshot(snapshot, toolName, input, q
|
|
|
923
982
|
// guards.
|
|
924
983
|
const PLANNING_WRITE_TOOLS = new Set(["write", "edit", "multi_edit", "notebook_edit"]);
|
|
925
984
|
const PLANNING_SUBAGENT_TOOLS = new Set(["subagent", "task"]);
|
|
926
|
-
|
|
927
|
-
* Canonical registry for agents that planning-dispatch may consider. Unit
|
|
928
|
-
* manifests still declare per-unit subsets via ToolsPolicy.allowedSubagents.
|
|
929
|
-
*/
|
|
930
|
-
const PLANNING_DISPATCH_AGENT_REGISTRY = {
|
|
931
|
-
mnemo: { readOnlySpecialist: true },
|
|
932
|
-
scout: { readOnlySpecialist: true },
|
|
933
|
-
planner: { readOnlySpecialist: true },
|
|
934
|
-
reviewer: { readOnlySpecialist: true },
|
|
935
|
-
security: { readOnlySpecialist: true },
|
|
936
|
-
tester: { readOnlySpecialist: true },
|
|
937
|
-
};
|
|
938
|
-
export const ALLOWED_PLANNING_DISPATCH_AGENTS = new Set(Object.entries(PLANNING_DISPATCH_AGENT_REGISTRY)
|
|
939
|
-
.filter(([, metadata]) => metadata.readOnlySpecialist)
|
|
940
|
-
.map(([agentId]) => agentId));
|
|
985
|
+
export { ALLOWED_PLANNING_DISPATCH_AGENTS } from "../planning-subagent-registry.js";
|
|
941
986
|
let warnedMissingControlledDispatchAgentClasses = false;
|
|
942
|
-
function isReadOnlySpecialist(agentId) {
|
|
943
|
-
const metadata = PLANNING_DISPATCH_AGENT_REGISTRY[agentId];
|
|
944
|
-
return metadata?.readOnlySpecialist === true;
|
|
945
|
-
}
|
|
946
|
-
function allowedPlanningDispatchAgentsList() {
|
|
947
|
-
return [...ALLOWED_PLANNING_DISPATCH_AGENTS].join(", ");
|
|
948
|
-
}
|
|
949
987
|
function allowsControlledSubagentDispatch(policy) {
|
|
950
988
|
return ((policy.mode === "planning-dispatch" || policy.mode === "verification" || policy.mode === "workflow-only") &&
|
|
951
989
|
Array.isArray(policy.allowedSubagents));
|
|
@@ -1093,13 +1131,13 @@ export function shouldBlockPlanningUnit(toolName, pathOrCommand, basePath, unitT
|
|
|
1093
1131
|
if (requested.length === 0) {
|
|
1094
1132
|
return { block: false };
|
|
1095
1133
|
}
|
|
1096
|
-
const globallyDisallowed = requested.find(a => !
|
|
1134
|
+
const globallyDisallowed = requested.find(a => !isReadOnlyPlanningDispatchAgent(a));
|
|
1097
1135
|
if (globallyDisallowed) {
|
|
1098
1136
|
return planningBlock(unitType, policy.mode, `subagent dispatch of "${globallyDisallowed}" not permitted; only read-only specialists (${allowedPlanningDispatchAgentsList()}) may be dispatched from ${policy.mode} units`);
|
|
1099
1137
|
}
|
|
1100
1138
|
const disallowedByPolicy = requested.find(a => !allowed.has(a));
|
|
1101
1139
|
if (disallowedByPolicy) {
|
|
1102
|
-
return planningBlock(unitType, policy.mode, `subagent dispatch of "${disallowedByPolicy}" not permitted by ToolsPolicy.allowedSubagents; permitted agents for this unit: ${allowedSubagents.join(", ")}`);
|
|
1140
|
+
return planningBlock(unitType, policy.mode, `subagent dispatch of "${disallowedByPolicy}" not permitted by unit allowlist (ToolsPolicy.allowedSubagents/planning_subagents); permitted agents for this unit: ${allowedSubagents.join(", ")}`);
|
|
1103
1141
|
}
|
|
1104
1142
|
return { block: false };
|
|
1105
1143
|
}
|
|
@@ -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
|
}
|
|
@@ -24,36 +24,35 @@ export const CACHE_MAX = 50;
|
|
|
24
24
|
* By scoping tools to this allowlist during discuss dispatches, the grammar
|
|
25
25
|
* sent to the provider stays well under provider limits.
|
|
26
26
|
*
|
|
27
|
-
* Included tools and why
|
|
27
|
+
* Included tools and why (canonical names only — aliases are no longer
|
|
28
|
+
* advertised to models by default, see plan 035):
|
|
28
29
|
* - gsd_summary_save: writes CONTEXT.md artifacts (all discuss prompts)
|
|
29
|
-
* - gsd_save_summary: alias for above
|
|
30
30
|
* - gsd_decision_save: records decisions (discuss.md output phase)
|
|
31
|
-
* - gsd_save_decision: alias for above
|
|
32
31
|
* - gsd_plan_milestone: writes roadmap (discuss.md single/multi milestone)
|
|
33
|
-
* - gsd_milestone_plan: alias for above
|
|
34
32
|
* - gsd_milestone_generate_id: generates milestone IDs (discuss.md multi-milestone)
|
|
35
|
-
* - gsd_generate_milestone_id: alias for above
|
|
36
33
|
* - gsd_requirement_save: creates requirements during discuss
|
|
37
|
-
* - gsd_save_requirement: alias for above
|
|
38
34
|
* - gsd_requirement_update: updates requirements during discuss
|
|
39
|
-
* - gsd_update_requirement: alias for above
|
|
40
35
|
*/
|
|
41
36
|
export const DISCUSS_TOOLS_ALLOWLIST = [
|
|
42
37
|
// Context / summary writing
|
|
43
38
|
"gsd_summary_save",
|
|
44
|
-
"gsd_save_summary",
|
|
45
39
|
// Decision recording
|
|
46
40
|
"gsd_decision_save",
|
|
47
|
-
"gsd_save_decision",
|
|
48
41
|
// Milestone planning (needed for discuss.md output phase)
|
|
49
42
|
"gsd_plan_milestone",
|
|
50
|
-
"gsd_milestone_plan",
|
|
51
43
|
// Milestone ID generation (multi-milestone flow)
|
|
52
44
|
"gsd_milestone_generate_id",
|
|
53
|
-
"gsd_generate_milestone_id",
|
|
54
45
|
// Requirement updates
|
|
55
46
|
"gsd_requirement_save",
|
|
56
|
-
"gsd_save_requirement",
|
|
57
47
|
"gsd_requirement_update",
|
|
58
|
-
"gsd_update_requirement",
|
|
59
48
|
];
|
|
49
|
+
// ─── Context Injection ────────────────────────────────────────────────────────
|
|
50
|
+
/**
|
|
51
|
+
* Leading marker stamped on every buildContextMessage() output
|
|
52
|
+
* (bootstrap/system-context.ts). Single source of truth for the producer and
|
|
53
|
+
* the consumer: the provider payload policy (filterSupersededContextInjections
|
|
54
|
+
* in context-masker.ts) matches this prefix to find and dedupe injected
|
|
55
|
+
* memory/guided/forensics messages after convertToLlm strips their customType.
|
|
56
|
+
* Both sides import it from here — do not inline the literal in either module.
|
|
57
|
+
*/
|
|
58
|
+
export const GSD_CONTEXT_MESSAGE_SENTINEL = "[GSD Context Injection]";
|
|
@@ -1,22 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Observation masking for GSD auto-mode sessions.
|
|
3
|
-
*
|
|
4
|
-
* Replaces tool result content older than N turns with a placeholder.
|
|
5
|
-
* Reduces context bloat between compactions with zero LLM overhead.
|
|
6
|
-
* Preserves message ordering, roles, and all assistant/user messages.
|
|
7
|
-
*
|
|
8
|
-
* Operates on provider payloads after convertToLlm:
|
|
9
|
-
*
|
|
10
|
-
* pi-ai Message[] payloads:
|
|
11
|
-
* - toolResult messages: { role: "toolResult", content: TextContent[] }
|
|
12
|
-
* - bash results are already converted to: { role: "user", content: [{type:"text",text:"..."}] }
|
|
13
|
-
* and start with "Ran `" from bashExecutionToText.
|
|
14
|
-
*
|
|
15
|
-
* OpenAI/Codex Responses payloads:
|
|
16
|
-
* - conversation items live in `input`, not `messages`
|
|
17
|
-
* - tool results are { type: "function_call_output", output: string | content[] }
|
|
18
|
-
* - bash results are user items with input_text content starting with "Ran `"
|
|
19
|
-
*/
|
|
1
|
+
import { GSD_CONTEXT_MESSAGE_SENTINEL } from "./constants.js";
|
|
20
2
|
const MASK_PLACEHOLDER = "[result masked — within summarized history]";
|
|
21
3
|
const MASK_CONTENT_BLOCK = [{ type: "text", text: MASK_PLACEHOLDER }];
|
|
22
4
|
const RESPONSES_MASK_CONTENT_BLOCK = [{ type: "input_text", text: MASK_PLACEHOLDER }];
|
|
@@ -52,6 +34,26 @@ function findTurnBoundary(messages, keepRecentTurns) {
|
|
|
52
34
|
}
|
|
53
35
|
return 0;
|
|
54
36
|
}
|
|
37
|
+
function countRealUserTurns(messages) {
|
|
38
|
+
let count = 0;
|
|
39
|
+
for (const m of messages) {
|
|
40
|
+
if (m.role === "user" && !isBashResultUserMessage(m))
|
|
41
|
+
count++;
|
|
42
|
+
}
|
|
43
|
+
return count;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Quantizes how many recent turns stay unmasked so the boundary only moves
|
|
47
|
+
* forward once per full block of `keepRecentTurns` new turns, instead of
|
|
48
|
+
* every turn. Keeps the masked prefix byte-stable within a block, which is
|
|
49
|
+
* what lets the LLM provider's prompt cache survive across turns.
|
|
50
|
+
*/
|
|
51
|
+
function quantizedKeepTurns(totalTurns, keepRecentTurns) {
|
|
52
|
+
if (keepRecentTurns <= 0 || totalTurns < 2 * keepRecentTurns)
|
|
53
|
+
return totalTurns;
|
|
54
|
+
const maskedTurns = Math.floor((totalTurns - keepRecentTurns) / keepRecentTurns) * keepRecentTurns;
|
|
55
|
+
return totalTurns - maskedTurns;
|
|
56
|
+
}
|
|
55
57
|
/**
|
|
56
58
|
* Detect user messages that originated from bashExecution.
|
|
57
59
|
* After convertToLlm, these are {role: "user", content: [{type:"text", text:"Ran `cmd`\n..."}]}.
|
|
@@ -73,7 +75,8 @@ function isMaskableMessage(m) {
|
|
|
73
75
|
}
|
|
74
76
|
export function createObservationMask(keepRecentTurns = 8) {
|
|
75
77
|
return (messages) => {
|
|
76
|
-
const
|
|
78
|
+
const totalTurns = countRealUserTurns(messages);
|
|
79
|
+
const boundary = findTurnBoundary(messages, quantizedKeepTurns(totalTurns, keepRecentTurns));
|
|
77
80
|
if (boundary === 0)
|
|
78
81
|
return messages;
|
|
79
82
|
return messages.map((m, i) => {
|
|
@@ -104,6 +107,14 @@ function findResponsesTurnBoundary(items, keepRecentTurns) {
|
|
|
104
107
|
}
|
|
105
108
|
return 0;
|
|
106
109
|
}
|
|
110
|
+
function countResponsesRealUserTurns(items) {
|
|
111
|
+
let count = 0;
|
|
112
|
+
for (const item of items) {
|
|
113
|
+
if (item.role === "user" && !isResponsesBashResultUserItem(item))
|
|
114
|
+
count++;
|
|
115
|
+
}
|
|
116
|
+
return count;
|
|
117
|
+
}
|
|
107
118
|
/**
|
|
108
119
|
* Observation masking for OpenAI/Codex Responses API payloads.
|
|
109
120
|
*
|
|
@@ -113,7 +124,8 @@ function findResponsesTurnBoundary(items, keepRecentTurns) {
|
|
|
113
124
|
*/
|
|
114
125
|
export function createResponsesInputObservationMask(keepRecentTurns = 8) {
|
|
115
126
|
return (items) => {
|
|
116
|
-
const
|
|
127
|
+
const totalTurns = countResponsesRealUserTurns(items);
|
|
128
|
+
const boundary = findResponsesTurnBoundary(items, quantizedKeepTurns(totalTurns, keepRecentTurns));
|
|
117
129
|
if (boundary === 0)
|
|
118
130
|
return items;
|
|
119
131
|
return items.map((item, i) => {
|
|
@@ -190,3 +202,67 @@ export function truncateResponsesInputResultItems(items, maxChars = 800) {
|
|
|
190
202
|
return item;
|
|
191
203
|
});
|
|
192
204
|
}
|
|
205
|
+
// GSD injects at most one context message per turn (memory/guided/forensics —
|
|
206
|
+
// see buildContextMessage in bootstrap/system-context.ts), marked with
|
|
207
|
+
// GSD_CONTEXT_MESSAGE_SENTINEL. convertToLlm strips the distinguishing
|
|
208
|
+
// customType before the payload reaches this hook, so detection is by content
|
|
209
|
+
// prefix instead. Pre-sentinel session history lacks the sentinel, so we also
|
|
210
|
+
// match the stable *bracketed* GSD block labels those injections begin with,
|
|
211
|
+
// letting resumed sessions dedupe older memory/guided blocks.
|
|
212
|
+
//
|
|
213
|
+
// Only GSD-specific bracketed markers belong here — never generic prose. A
|
|
214
|
+
// message is dropped from the payload when it matches, so a natural-language
|
|
215
|
+
// prefix (e.g. the forensics prompt "Debug GSD itself.") could silently delete
|
|
216
|
+
// a real user message that happens to start the same way. Legacy forensics
|
|
217
|
+
// injections without memory are therefore left un-deduped by design; those
|
|
218
|
+
// with memory still match via the "[GSD Context Metadata]" wrapper.
|
|
219
|
+
const LEGACY_GSD_CONTEXT_INJECTION_PREFIXES = [
|
|
220
|
+
"[GSD Context Metadata]",
|
|
221
|
+
"[MEMORY — Critical and prompt-relevant memories from the GSD memory store]",
|
|
222
|
+
"[GSD Guided Execute Context]",
|
|
223
|
+
];
|
|
224
|
+
function isGsdContextInjectionText(text) {
|
|
225
|
+
if (typeof text !== "string")
|
|
226
|
+
return false;
|
|
227
|
+
if (text.startsWith(GSD_CONTEXT_MESSAGE_SENTINEL))
|
|
228
|
+
return true;
|
|
229
|
+
return LEGACY_GSD_CONTEXT_INJECTION_PREFIXES.some((prefix) => text.startsWith(prefix));
|
|
230
|
+
}
|
|
231
|
+
function isGsdContextInjectionMessage(m) {
|
|
232
|
+
if (m.role !== "user")
|
|
233
|
+
return false;
|
|
234
|
+
return isGsdContextInjectionText(firstTextFromContent(m.content));
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Removes every GSD context-injection user message except the latest one.
|
|
238
|
+
* Each turn re-injects a near-identical memory/guided/forensics block; left
|
|
239
|
+
* in place they duplicate verbatim across an N-turn session. Removal (not
|
|
240
|
+
* masking) — an empty placeholder still costs tokens and shifts message
|
|
241
|
+
* positions, breaking cache byte-stability. Pure function: stored history is
|
|
242
|
+
* never mutated, only the outgoing payload array.
|
|
243
|
+
*/
|
|
244
|
+
export function filterSupersededContextInjections(messages) {
|
|
245
|
+
let lastIndex = -1;
|
|
246
|
+
for (let i = 0; i < messages.length; i++) {
|
|
247
|
+
if (isGsdContextInjectionMessage(messages[i]))
|
|
248
|
+
lastIndex = i;
|
|
249
|
+
}
|
|
250
|
+
if (lastIndex === -1)
|
|
251
|
+
return messages;
|
|
252
|
+
return messages.filter((m, i) => i === lastIndex || !isGsdContextInjectionMessage(m));
|
|
253
|
+
}
|
|
254
|
+
function isResponsesGsdContextInjectionItem(item) {
|
|
255
|
+
if (item.role !== "user")
|
|
256
|
+
return false;
|
|
257
|
+
return isGsdContextInjectionText(firstTextFromContent(item.content));
|
|
258
|
+
}
|
|
259
|
+
export function filterSupersededResponsesContextInjections(items) {
|
|
260
|
+
let lastIndex = -1;
|
|
261
|
+
for (let i = 0; i < items.length; i++) {
|
|
262
|
+
if (isResponsesGsdContextInjectionItem(items[i]))
|
|
263
|
+
lastIndex = i;
|
|
264
|
+
}
|
|
265
|
+
if (lastIndex === -1)
|
|
266
|
+
return items;
|
|
267
|
+
return items.filter((item, i) => i === lastIndex || !isResponsesGsdContextInjectionItem(item));
|
|
268
|
+
}
|
|
@@ -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
|
}
|