@opengsd/gsd-pi 1.9.0 → 1.10.0-dev.a5e42e99
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 -9
- package/dist/headless.js +2 -1
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/GSD-WORKFLOW.md +2 -2
- package/dist/resources/extensions/gsd/artifact-verification.js +3 -4
- package/dist/resources/extensions/gsd/auto/loop.js +24 -4
- package/dist/resources/extensions/gsd/auto/run-unit.js +19 -1
- package/dist/resources/extensions/gsd/auto/unit-phase.js +37 -5
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +14 -8
- package/dist/resources/extensions/gsd/auto-dispatch.js +2 -0
- package/dist/resources/extensions/gsd/auto-model-selection.js +1 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +102 -21
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-runtime-state.js +5 -5
- package/dist/resources/extensions/gsd/auto-start.js +30 -10
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +40 -0
- package/dist/resources/extensions/gsd/auto-verification.js +25 -12
- package/dist/resources/extensions/gsd/auto-worktree-cleanup.js +4 -0
- package/dist/resources/extensions/gsd/auto-worktree-sync.js +7 -3
- package/dist/resources/extensions/gsd/auto-worktree-teardown.js +1 -1
- package/dist/resources/extensions/gsd/auto.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +2 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +10 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +7 -26
- package/dist/resources/extensions/gsd/commands-verdict.js +10 -9
- package/dist/resources/extensions/gsd/compat/compat-marker.js +80 -5
- 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/engine.js +5 -2
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +33 -2
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +40 -12
- package/dist/resources/extensions/gsd/error-classifier.js +12 -2
- package/dist/resources/extensions/gsd/exec-sandbox.js +1 -0
- package/dist/resources/extensions/gsd/flat-phase-migration.js +12 -0
- package/dist/resources/extensions/gsd/git-service.js +19 -7
- package/dist/resources/extensions/gsd/gsd-db.js +75 -31
- package/dist/resources/extensions/gsd/guided-flow.js +11 -5
- package/dist/resources/extensions/gsd/markdown-renderer.js +5 -21
- package/dist/resources/extensions/gsd/md-importer.js +5 -6
- package/dist/resources/extensions/gsd/model-cost-table.js +6 -1
- package/dist/resources/extensions/gsd/model-router.js +16 -0
- package/dist/resources/extensions/gsd/paths.js +66 -15
- package/dist/resources/extensions/gsd/planning-subagent-policy.js +37 -0
- package/dist/resources/extensions/gsd/planning-subagent-registry.js +33 -0
- package/dist/resources/extensions/gsd/preferences-models.js +50 -10
- package/dist/resources/extensions/gsd/preferences-types.js +6 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +86 -4
- package/dist/resources/extensions/gsd/preferences.js +24 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
- 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/skill-activation.js +17 -3
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.js +98 -2
- package/dist/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.js +4 -1
- package/dist/resources/extensions/gsd/state-reconciliation/drift/roadmap.js +5 -2
- package/dist/resources/extensions/gsd/stop-notice.js +9 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +8 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +12 -5
- package/dist/resources/extensions/gsd/tools/plan-slice.js +5 -1
- 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/unit-context-composer.js +28 -5
- package/dist/resources/extensions/gsd/verification-evidence.js +5 -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 +20 -18
- package/dist/resources/extensions/ollama/ollama-chat-provider.js +2 -2
- package/dist/resources/extensions/shared/interview-ui.js +43 -6
- package/dist/resources/extensions/subagent/index.js +1 -1
- package/dist/startup-model-validation.d.ts +1 -1
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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 +1 -1
- 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 +4 -4
- 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 +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- 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/1991.js +2 -2
- package/dist/web/standalone/.next/server/chunks/2842.js +4 -4
- package/dist/web/standalone/.next/server/chunks/5124.js +1 -1
- 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/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/server.js +1 -1
- package/integrations/hermes/open_gsd_hermes/gsd_client.py +1 -1
- package/integrations/hermes/pyproject.toml +1 -1
- package/package.json +8 -6
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/dist/rpc.d.ts +1 -1
- package/packages/contracts/dist/rpc.d.ts.map +1 -1
- package/packages/contracts/dist/rpc.js +1 -1
- package/packages/contracts/dist/rpc.js.map +1 -1
- package/packages/contracts/dist/rpc.test.js +1 -1
- package/packages/contracts/dist/rpc.test.js.map +1 -1
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- 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/dist/cli/args.js +2 -2
- package/packages/gsd-agent-modes/dist/cli/args.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-autocomplete.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/gsd-cloud/README.md +21 -5
- package/packages/gsd-cloud/dist/background-cli.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/background-cli.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/background-cli.test.js +325 -0
- package/packages/gsd-cloud/dist/background-cli.test.js.map +1 -0
- package/packages/gsd-cloud/dist/cli.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cli.js +146 -16
- package/packages/gsd-cloud/dist/cli.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-config.d.ts +1 -1
- package/packages/gsd-cloud/dist/cloud-config.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-config.js +7 -1
- package/packages/gsd-cloud/dist/cloud-config.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts +7 -4
- package/packages/gsd-cloud/dist/cloud-runtime.d.ts.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.js +115 -31
- package/packages/gsd-cloud/dist/cloud-runtime.js.map +1 -1
- package/packages/gsd-cloud/dist/cloud-runtime.test.js +224 -59
- package/packages/gsd-cloud/dist/cloud-runtime.test.js.map +1 -1
- package/packages/gsd-cloud/dist/runtime-artifacts.d.ts +3 -0
- package/packages/gsd-cloud/dist/runtime-artifacts.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-artifacts.js +36 -0
- package/packages/gsd-cloud/dist/runtime-artifacts.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts +32 -0
- package/packages/gsd-cloud/dist/runtime-process.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.js +640 -0
- package/packages/gsd-cloud/dist/runtime-process.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/runtime-process.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js +543 -0
- package/packages/gsd-cloud/dist/runtime-process.test.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.d.ts +117 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.js +291 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.js.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts +2 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.d.ts.map +1 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.js +434 -0
- package/packages/gsd-cloud/dist/runtime-telemetry.test.js.map +1 -0
- package/packages/gsd-cloud/package.json +2 -2
- package/packages/mcp-server/README.md +7 -2
- package/packages/mcp-server/dist/cli-runner.d.ts +3 -0
- package/packages/mcp-server/dist/cli-runner.d.ts.map +1 -1
- package/packages/mcp-server/dist/cli-runner.js +119 -33
- package/packages/mcp-server/dist/cli-runner.js.map +1 -1
- 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.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/dist/types.d.ts +2 -2
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +187 -0
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +145 -0
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.js +18 -6
- package/packages/pi-ai/dist/models.js.map +1 -1
- package/packages/pi-ai/dist/providers/amazon-bedrock.js +3 -2
- package/packages/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +6 -1
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
- package/packages/pi-ai/dist/providers/google-vertex.js.map +1 -1
- package/packages/pi-ai/dist/providers/google.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-codex-responses.d.ts.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-completions.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +103 -0
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts +1 -1
- package/packages/pi-ai/dist/providers/openai-responses.d.ts.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/dist/providers/simple-options.d.ts +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +9 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.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-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +2 -2
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +14 -4
- 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/dist/core/skills.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +54 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/theme/theme.js +1 -0
- package/packages/pi-coding-agent/dist/theme/theme.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/dist/theme/theme.d.ts +1 -1
- package/pkg/dist/theme/theme.d.ts.map +1 -1
- package/pkg/dist/theme/theme.js +1 -0
- package/pkg/dist/theme/theme.js.map +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/GSD-WORKFLOW.md +2 -2
- package/src/resources/extensions/gsd/artifact-verification.ts +3 -8
- package/src/resources/extensions/gsd/auto/loop.ts +48 -4
- package/src/resources/extensions/gsd/auto/run-unit.ts +20 -1
- package/src/resources/extensions/gsd/auto/unit-phase.ts +41 -5
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +14 -7
- package/src/resources/extensions/gsd/auto-dispatch.ts +1 -0
- package/src/resources/extensions/gsd/auto-model-selection.ts +1 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +118 -19
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +12 -7
- package/src/resources/extensions/gsd/auto-start.ts +32 -9
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +56 -0
- package/src/resources/extensions/gsd/auto-verification.ts +46 -12
- package/src/resources/extensions/gsd/auto-worktree-cleanup.ts +4 -0
- package/src/resources/extensions/gsd/auto-worktree-sync.ts +10 -3
- package/src/resources/extensions/gsd/auto-worktree-teardown.ts +1 -1
- package/src/resources/extensions/gsd/auto.ts +20 -7
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +1 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +41 -12
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +11 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +10 -31
- package/src/resources/extensions/gsd/commands-verdict.ts +16 -9
- package/src/resources/extensions/gsd/compat/compat-marker.ts +99 -5
- 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/engine.ts +5 -2
- package/src/resources/extensions/gsd/docs/preferences-reference.md +33 -2
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +45 -11
- package/src/resources/extensions/gsd/error-classifier.ts +13 -2
- package/src/resources/extensions/gsd/exec-sandbox.ts +1 -0
- package/src/resources/extensions/gsd/flat-phase-migration.ts +14 -0
- package/src/resources/extensions/gsd/git-service.ts +19 -6
- package/src/resources/extensions/gsd/gsd-db.ts +85 -33
- package/src/resources/extensions/gsd/guided-flow.ts +11 -4
- package/src/resources/extensions/gsd/markdown-renderer.ts +5 -23
- package/src/resources/extensions/gsd/md-importer.ts +5 -5
- package/src/resources/extensions/gsd/model-cost-table.ts +14 -1
- package/src/resources/extensions/gsd/model-router.ts +17 -0
- package/src/resources/extensions/gsd/paths.ts +73 -15
- package/src/resources/extensions/gsd/planning-subagent-policy.ts +58 -0
- package/src/resources/extensions/gsd/planning-subagent-registry.ts +45 -0
- package/src/resources/extensions/gsd/preferences-models.ts +54 -10
- package/src/resources/extensions/gsd/preferences-types.ts +26 -2
- package/src/resources/extensions/gsd/preferences-validation.ts +108 -3
- package/src/resources/extensions/gsd/preferences.ts +38 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +5 -5
- 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/skill-activation.ts +17 -3
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-markdown-edit.ts +132 -2
- package/src/resources/extensions/gsd/state-reconciliation/drift/external-planning-edit.ts +4 -1
- package/src/resources/extensions/gsd/state-reconciliation/drift/roadmap.ts +4 -2
- package/src/resources/extensions/gsd/stop-notice.ts +11 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +8 -0
- package/src/resources/extensions/gsd/tests/auto-artifact-paths.test.ts +7 -7
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +74 -1
- package/src/resources/extensions/gsd/tests/before-provider-context-management.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/commands-verdict.test.ts +10 -0
- package/src/resources/extensions/gsd/tests/compat-marker.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +76 -1
- package/src/resources/extensions/gsd/tests/context-masker.test.ts +204 -8
- package/src/resources/extensions/gsd/tests/db-engine-cjs-compat.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/db-tools-alias-suppression.test.ts +62 -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/doctor-scope-db-unavailable.test.ts +147 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/external-markdown-edit.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/flat-phase-migration.test.ts +8 -9
- package/src/resources/extensions/gsd/tests/flat-phase-validation-path.test.ts +20 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +13 -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/model-cost-table.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/parallel-skill-prompt-integration.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +24 -0
- package/src/resources/extensions/gsd/tests/post-exec-retry-bypass.test.ts +38 -1
- package/src/resources/extensions/gsd/tests/preferences.test.ts +151 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +121 -1
- package/src/resources/extensions/gsd/tests/reactive-executor.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/register-hooks-loop-guard-auto.test.ts +105 -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/state-reconciliation-drift.test.ts +52 -0
- package/src/resources/extensions/gsd/tests/stop-notice.test.ts +21 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +13 -7
- package/src/resources/extensions/gsd/tests/terminated-transient.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/thinking-level-resolution.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-prompt-verification-classes.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-faults.test.ts +238 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-fixture.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-fixture.ts +141 -0
- package/src/resources/extensions/gsd/tests/workflow-authority-projection-conflict.test.ts +177 -0
- package/src/resources/extensions/gsd/tests/workflow-fault-harness.test.ts +39 -0
- package/src/resources/extensions/gsd/tests/workflow-fault-harness.ts +72 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/worktree-state-projection.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +74 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +20 -5
- package/src/resources/extensions/gsd/tools/plan-slice.ts +5 -1
- 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/unit-context-composer.ts +34 -8
- package/src/resources/extensions/gsd/verification-evidence.ts +5 -2
- 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 +21 -24
- package/src/resources/extensions/ollama/ollama-chat-provider.ts +2 -2
- package/src/resources/extensions/ollama/tests/ollama-chat-provider-think.test.ts +4 -0
- package/src/resources/extensions/shared/interview-ui.ts +47 -8
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +29 -0
- package/src/resources/extensions/subagent/index.ts +1 -1
- 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/{BE5XoklToI6lZjRzpXih8 → xwUaOqui04jIIFVsIBLiL}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{BE5XoklToI6lZjRzpXih8 → xwUaOqui04jIIFVsIBLiL}/_ssgManifest.js +0 -0
|
@@ -8,6 +8,7 @@ import { executeValidateMilestone } from "./tools/workflow-tool-executors.js";
|
|
|
8
8
|
import { ensureDbOpen } from "./bootstrap/dynamic-tools.js";
|
|
9
9
|
import { getLatestAssessmentByScope } from "./gsd-db.js";
|
|
10
10
|
import { checkpointWorkflowDatabase } from "./db-workspace.js";
|
|
11
|
+
import { formatVerdictRecordedNotice, formatVerdictRejectedNotice } from "./stop-notice.js";
|
|
11
12
|
import { VALIDATION_VERDICTS, extractVerdict, isValidMilestoneVerdict, } from "./verdict-parser.js";
|
|
12
13
|
const USAGE = 'Usage: /gsd verdict <pass|needs-attention|needs-remediation> [--milestone Mxxx] [--rationale "..."]';
|
|
13
14
|
function tokenize(raw) {
|
|
@@ -123,35 +124,35 @@ async function loadExistingValidation(basePath, milestoneId) {
|
|
|
123
124
|
}
|
|
124
125
|
export async function handleVerdict(rawArgs, ctx, basePath) {
|
|
125
126
|
if (!rawArgs.trim()) {
|
|
126
|
-
ctx.ui.notify(USAGE, "warning");
|
|
127
|
+
ctx.ui.notify(formatVerdictRejectedNotice(USAGE), "warning");
|
|
127
128
|
return;
|
|
128
129
|
}
|
|
129
130
|
const parsed = parseArgs(rawArgs);
|
|
130
131
|
if ("error" in parsed) {
|
|
131
|
-
ctx.ui.notify(`${parsed.error}\n${USAGE}
|
|
132
|
+
ctx.ui.notify(formatVerdictRejectedNotice(`${parsed.error}\n${USAGE}`), "warning");
|
|
132
133
|
return;
|
|
133
134
|
}
|
|
134
135
|
if (!parsed.verdict) {
|
|
135
|
-
ctx.ui.notify(USAGE, "warning");
|
|
136
|
+
ctx.ui.notify(formatVerdictRejectedNotice(USAGE), "warning");
|
|
136
137
|
return;
|
|
137
138
|
}
|
|
138
139
|
let milestoneId = parsed.milestoneId;
|
|
139
140
|
if (!milestoneId) {
|
|
140
141
|
const state = await deriveState(basePath);
|
|
141
142
|
if (!state.activeMilestone) {
|
|
142
|
-
ctx.ui.notify("No active milestone — pass --milestone Mxxx to target a specific milestone.", "warning");
|
|
143
|
+
ctx.ui.notify(formatVerdictRejectedNotice("No active milestone — pass --milestone Mxxx to target a specific milestone."), "warning");
|
|
143
144
|
return;
|
|
144
145
|
}
|
|
145
146
|
milestoneId = state.activeMilestone.id;
|
|
146
147
|
}
|
|
147
148
|
const existingValidation = await loadExistingValidation(basePath, milestoneId);
|
|
148
149
|
if (!existingValidation) {
|
|
149
|
-
ctx.ui.notify(`No milestone validation found for ${milestoneId}. Run /gsd auto to validate first, then retry /gsd verdict
|
|
150
|
+
ctx.ui.notify(formatVerdictRejectedNotice(`No milestone validation found for ${milestoneId}. Run /gsd auto to validate first, then retry /gsd verdict.`), "warning");
|
|
150
151
|
return;
|
|
151
152
|
}
|
|
152
153
|
const current = parseValidationFile(existingValidation.content);
|
|
153
154
|
if (parsed.verdict !== "pass" && !parsed.rationale) {
|
|
154
|
-
ctx.ui.notify(`--rationale is required when overriding to ${parsed.verdict}
|
|
155
|
+
ctx.ui.notify(formatVerdictRejectedNotice(`--rationale is required when overriding to ${parsed.verdict}.`), "warning");
|
|
155
156
|
return;
|
|
156
157
|
}
|
|
157
158
|
const verdictRationale = parsed.rationale ?? "Manually overridden via /gsd verdict";
|
|
@@ -169,17 +170,17 @@ export async function handleVerdict(rawArgs, ctx, basePath) {
|
|
|
169
170
|
}, basePath, parsed.verdict === "pass" ? { skipBrowserEvidenceGate: true } : undefined);
|
|
170
171
|
if (result.isError) {
|
|
171
172
|
const msg = result.content[0]?.type === "text" ? result.content[0].text : "Unknown error";
|
|
172
|
-
ctx.ui.notify(msg, "error");
|
|
173
|
+
ctx.ui.notify(formatVerdictRejectedNotice(msg), "error");
|
|
173
174
|
return;
|
|
174
175
|
}
|
|
175
176
|
checkpointWorkflowDatabase();
|
|
176
177
|
const prevVerdict = current.verdict ?? "unknown";
|
|
177
178
|
const effectiveVerdict = extractEffectiveVerdict(result.details, parsed.verdict);
|
|
178
179
|
if (effectiveVerdict !== parsed.verdict) {
|
|
179
|
-
ctx.ui.notify(`Milestone ${milestoneId} verdict requested: ${parsed.verdict}, effective: ${effectiveVerdict} (${existingValidation.source})
|
|
180
|
+
ctx.ui.notify(formatVerdictRecordedNotice(`Milestone ${milestoneId} verdict requested: ${parsed.verdict}, effective: ${effectiveVerdict} (${existingValidation.source})`), "warning");
|
|
180
181
|
}
|
|
181
182
|
else {
|
|
182
|
-
ctx.ui.notify(`Milestone ${milestoneId} verdict: ${prevVerdict} -> ${effectiveVerdict} (${existingValidation.source})
|
|
183
|
+
ctx.ui.notify(formatVerdictRecordedNotice(`Milestone ${milestoneId} verdict: ${prevVerdict} -> ${effectiveVerdict} (${existingValidation.source})`), "success");
|
|
183
184
|
}
|
|
184
185
|
if (effectiveVerdict === "needs-remediation") {
|
|
185
186
|
ctx.ui.notify("Follow up with /gsd dispatch reassess to add remediation slices, then re-run /gsd auto.", "info");
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
// distinguish gsd-pi's own writes (expected) from external edits made by gsd-core
|
|
6
6
|
// (drift to import). gsd-core is oblivious to this file and ignores it.
|
|
7
7
|
import { createHash } from "node:crypto";
|
|
8
|
-
import { existsSync, readFileSync, renameSync, unlinkSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
-
import { dirname, join, isAbsolute, normalize } from "node:path";
|
|
8
|
+
import { existsSync, readFileSync, realpathSync, renameSync, unlinkSync, writeFileSync, mkdirSync } from "node:fs";
|
|
9
|
+
import { dirname, join, isAbsolute, normalize, relative, resolve } 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). */
|
|
@@ -32,6 +32,35 @@ export function normalizeForHash(content) {
|
|
|
32
32
|
export function computeProjectionSha(content) {
|
|
33
33
|
return createHash("sha256").update(normalizeForHash(content)).digest("hex").slice(0, 16);
|
|
34
34
|
}
|
|
35
|
+
function normalizeRealPath(p) {
|
|
36
|
+
try {
|
|
37
|
+
return realpathSync.native(p);
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return resolve(p);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function rootRelativeKey(rootPath, absPath) {
|
|
44
|
+
const root = normalizeRealPath(rootPath);
|
|
45
|
+
const abs = normalizeRealPath(absPath);
|
|
46
|
+
const rel = relative(root, abs);
|
|
47
|
+
if (!rel || rel === ".." || rel.startsWith(`..${sepForRelative(rel)}`) || isAbsolute(rel)) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
return rel.replace(/\\/g, "/");
|
|
51
|
+
}
|
|
52
|
+
function sepForRelative(rel) {
|
|
53
|
+
return rel.includes("\\") ? "\\" : "/";
|
|
54
|
+
}
|
|
55
|
+
export function deriveCompatProjectionKey(absPath, roots) {
|
|
56
|
+
for (const root of roots) {
|
|
57
|
+
const key = rootRelativeKey(root, absPath);
|
|
58
|
+
if (key)
|
|
59
|
+
return key;
|
|
60
|
+
}
|
|
61
|
+
const fallbackRoot = roots[roots.length - 1] ?? dirname(absPath);
|
|
62
|
+
return relative(fallbackRoot, absPath).replace(/\\/g, "/");
|
|
63
|
+
}
|
|
35
64
|
/**
|
|
36
65
|
* Read & validate the marker. A missing marker → EMPTY_MARKER (treat every
|
|
37
66
|
* projection as external on next reconcile). A malformed marker is quarantined
|
|
@@ -39,7 +68,9 @@ export function computeProjectionSha(content) {
|
|
|
39
68
|
* EMPTY_MARKER. A schema-mismatch returns EMPTY_MARKER (forward-compat: refuse
|
|
40
69
|
* to act on a future format we don't understand).
|
|
41
70
|
*/
|
|
42
|
-
export function readCompatMarker(basePath) {
|
|
71
|
+
export function readCompatMarker(basePath, options = {}) {
|
|
72
|
+
const healInvalidKeys = options.healInvalidKeys ?? true;
|
|
73
|
+
const quarantineInvalid = options.quarantineInvalid ?? true;
|
|
43
74
|
const path = compatMarkerPath(basePath);
|
|
44
75
|
if (!existsSync(path))
|
|
45
76
|
return emptyMarker();
|
|
@@ -55,11 +86,16 @@ export function readCompatMarker(basePath) {
|
|
|
55
86
|
parsed = JSON.parse(raw);
|
|
56
87
|
}
|
|
57
88
|
catch {
|
|
58
|
-
|
|
89
|
+
if (quarantineInvalid)
|
|
90
|
+
quarantine(basePath, raw);
|
|
59
91
|
return emptyMarker();
|
|
60
92
|
}
|
|
93
|
+
if (healInvalidKeys && healMarkerProjectionKeys(basePath, parsed) && isValidMarker(parsed)) {
|
|
94
|
+
writeCompatMarker(basePath, parsed);
|
|
95
|
+
}
|
|
61
96
|
if (!isValidMarker(parsed)) {
|
|
62
|
-
|
|
97
|
+
if (quarantineInvalid)
|
|
98
|
+
quarantine(basePath, raw);
|
|
63
99
|
return emptyMarker();
|
|
64
100
|
}
|
|
65
101
|
// Promote older markers by defaulting absent fields. Schema 1 → 2 only adds
|
|
@@ -196,6 +232,45 @@ function isValidProjectionMap(x) {
|
|
|
196
232
|
}
|
|
197
233
|
return true;
|
|
198
234
|
}
|
|
235
|
+
function healMarkerProjectionKeys(basePath, marker) {
|
|
236
|
+
if (typeof marker !== "object" || marker === null)
|
|
237
|
+
return false;
|
|
238
|
+
const m = marker;
|
|
239
|
+
let changed = false;
|
|
240
|
+
if (typeof m.projections === "object" && m.projections !== null) {
|
|
241
|
+
changed = healProjectionMapKeys(basePath, ".gsd", m.projections) || changed;
|
|
242
|
+
}
|
|
243
|
+
const planning = m.planning;
|
|
244
|
+
if (typeof planning === "object" && planning !== null) {
|
|
245
|
+
const p = planning;
|
|
246
|
+
if (typeof p.projections === "object" && p.projections !== null) {
|
|
247
|
+
changed = healProjectionMapKeys(basePath, ".planning", p.projections) || changed;
|
|
248
|
+
}
|
|
249
|
+
if (typeof p.passthrough === "object" && p.passthrough !== null) {
|
|
250
|
+
changed = healProjectionMapKeys(basePath, ".planning", p.passthrough) || changed;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return changed;
|
|
254
|
+
}
|
|
255
|
+
function healProjectionMapKeys(basePath, rootName, map) {
|
|
256
|
+
let changed = false;
|
|
257
|
+
const root = join(basePath, rootName);
|
|
258
|
+
for (const key of Object.keys(map)) {
|
|
259
|
+
if (isSafeProjectionKey(key))
|
|
260
|
+
continue;
|
|
261
|
+
if (key.includes("\0") || isAbsolute(key) || /^[A-Za-z]:/.test(key))
|
|
262
|
+
continue;
|
|
263
|
+
const healedKey = rootRelativeKey(root, resolve(root, key));
|
|
264
|
+
if (!healedKey || !isSafeProjectionKey(healedKey))
|
|
265
|
+
continue;
|
|
266
|
+
if (!map[healedKey]) {
|
|
267
|
+
map[healedKey] = map[key];
|
|
268
|
+
}
|
|
269
|
+
delete map[key];
|
|
270
|
+
changed = true;
|
|
271
|
+
}
|
|
272
|
+
return changed;
|
|
273
|
+
}
|
|
199
274
|
function isValidPlanningMarker(x) {
|
|
200
275
|
if (typeof x !== "object" || x === null)
|
|
201
276
|
return false;
|
|
@@ -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
|
+
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
// writer layer.
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { existsSync, copyFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
13
|
-
import { dirname, join } from "node:path";
|
|
13
|
+
import { dirname, join, resolve } from "node:path";
|
|
14
14
|
import { GSDError, GSD_STALE_STATE } from "../errors.js";
|
|
15
15
|
import { logError, logWarning } from "../workflow-logger.js";
|
|
16
16
|
import { createDbAdapter } from "../db-adapter.js";
|
|
@@ -31,7 +31,10 @@ function getGsdRequire() {
|
|
|
31
31
|
if (_gsdRequire !== undefined)
|
|
32
32
|
return _gsdRequire;
|
|
33
33
|
try {
|
|
34
|
-
|
|
34
|
+
// Next.js may emit this module into a CommonJS chunk. Avoid ESM-only module
|
|
35
|
+
// metadata syntax here; it is a hard parse error there.
|
|
36
|
+
const packageRoot = process.env.GSD_WEB_PACKAGE_ROOT || process.env.GSD_PKG_ROOT || process.cwd();
|
|
37
|
+
_gsdRequire = createRequire(resolve(packageRoot, "package.json"));
|
|
35
38
|
}
|
|
36
39
|
catch {
|
|
37
40
|
_gsdRequire = null;
|
|
@@ -124,11 +124,11 @@ Diagnostics record the file path, scope (global/project), severity (error/warnin
|
|
|
124
124
|
- `validation` — used for gate evaluation, roadmap reassessment, milestone validation, and doc rewrites. Falls back to `planning` if unset.
|
|
125
125
|
- `uat` — used for UAT runs. Falls back to `completion` if unset.
|
|
126
126
|
|
|
127
|
-
- `thinking`: per-phase reasoning effort (ADR-026), separate from `models`. Same phase keys as `models`. Values: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`. Thinking travels with the model — model choice and reasoning effort are independent controls, so you can run one model across phases at different reasoning levels.
|
|
127
|
+
- `thinking`: per-phase reasoning effort (ADR-026), separate from `models`. Same phase keys as `models`. Values: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Thinking travels with the model — model choice and reasoning effort are independent controls, so you can run one model across phases at different reasoning levels.
|
|
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` support
|
|
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` and `max` support are model-dependent; current examples include `gpt-5.6-sol`, `gpt-5.6-terra`, and `gpt-5.6-luna`, which advertise both.
|
|
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
|
|
|
@@ -357,6 +357,37 @@ In `"parent"` mode, slice/task `targetRepositories` default to the declared chil
|
|
|
357
357
|
- `"replace"` requires `prompt`.
|
|
358
358
|
- `"skip"` is valid with no additional fields.
|
|
359
359
|
|
|
360
|
+
- `planning_subagent_registry`: object — optional classification for custom planning agents. Each key is an agent id and must set:
|
|
361
|
+
- `read_only_specialist`: boolean — set to `true` to classify the custom agent as safe for planning dispatch.
|
|
362
|
+
|
|
363
|
+
- `planning_subagents`: object — project-local widening for read-only planning subagent dispatch. Supported unit keys are `plan-milestone` and `plan-slice`; each has:
|
|
364
|
+
- `allowed`: string[] — additional planning-safe agents for that unit.
|
|
365
|
+
|
|
366
|
+
Agents must be built-in read-only planning specialists (`mnemo`, `scout`, `planner`, `reviewer`, `security`, or `tester`) or registered in `planning_subagent_registry` with `read_only_specialist: true`. The write gate still blocks source writes outside `.gsd/**`, unrestricted bash, stale subagent calls without agent identities, agents outside the read-only registry, and agents not listed for the active unit.
|
|
367
|
+
|
|
368
|
+
Example:
|
|
369
|
+
|
|
370
|
+
```yaml
|
|
371
|
+
planning_subagent_registry:
|
|
372
|
+
my-custom-planner:
|
|
373
|
+
read_only_specialist: true
|
|
374
|
+
|
|
375
|
+
planning_subagents:
|
|
376
|
+
plan-milestone:
|
|
377
|
+
allowed:
|
|
378
|
+
- scout
|
|
379
|
+
- planner
|
|
380
|
+
- my-custom-planner
|
|
381
|
+
- security
|
|
382
|
+
plan-slice:
|
|
383
|
+
allowed:
|
|
384
|
+
- scout
|
|
385
|
+
- planner
|
|
386
|
+
- my-custom-planner
|
|
387
|
+
- reviewer
|
|
388
|
+
- security
|
|
389
|
+
```
|
|
390
|
+
|
|
360
391
|
**Known unit types for `before`/`after`:** `research-milestone`, `plan-milestone`, `research-slice`, `plan-slice`, `execute-task`, `complete-slice`, `replan-slice`, `reassess-roadmap`, `run-uat`.
|
|
361
392
|
|
|
362
393
|
- `experimental`: opt-in experimental features. All features here are **off by default** — you must explicitly set each one to `true` to enable it. Features in this block may change or be removed without a deprecation cycle while in experimental status. Keys:
|
|
@@ -3,7 +3,7 @@ import { isAbsolute, join, relative, sep } from "node:path";
|
|
|
3
3
|
import { deleteArtifactByPath, getAllMilestones, getMilestoneSlices, getSliceTasks, isDbAvailable, isMemoriesFtsAvailable, repairTaskCompletionFromSummary, _getAdapter, } from "./gsd-db.js";
|
|
4
4
|
import { MEMORIES_FTS_REBUILT_KEY } from "./db-memory-fts-schema.js";
|
|
5
5
|
import { isAfter, latestExplicitReopenAt } from "./milestone-reopen-events.js";
|
|
6
|
-
import {
|
|
6
|
+
import { gsdProjectionRoot, gsdRoot, resolveGsdPathContract, resolveMilestoneFile, resolveSliceFile, resolveTaskFile, } from "./paths.js";
|
|
7
7
|
import { deriveState } from "./state.js";
|
|
8
8
|
import { isClosedStatus } from "./status-guards.js";
|
|
9
9
|
import { workflowEventLogPath } from "./workflow-event-ledger.js";
|
|
@@ -13,6 +13,7 @@ import { parseRoadmapSlices } from "./roadmap-slices.js";
|
|
|
13
13
|
import { parsePlan } from "./parsers-legacy.js";
|
|
14
14
|
import { parseSummary } from "./files.js";
|
|
15
15
|
import { LAYOUT_SEGMENTS } from "./layout-policy.js";
|
|
16
|
+
import { resolveCanonicalMilestoneRoot } from "./worktree-manager.js";
|
|
16
17
|
const USER_AUTHORED_ARTIFACT_TYPES = new Set(["CONTEXT", "RESEARCH"]);
|
|
17
18
|
function escapeRegExp(value) {
|
|
18
19
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -58,9 +59,27 @@ function reportCheckboxDbStatusDivergence(issues, basePath, filePath, scope, uni
|
|
|
58
59
|
fixable: false,
|
|
59
60
|
});
|
|
60
61
|
}
|
|
62
|
+
function bareDuplicateMilestoneId(milestoneId) {
|
|
63
|
+
const match = milestoneId.match(/^(M\d{3})-[a-z0-9]{6}$/i);
|
|
64
|
+
return match?.[1]?.toUpperCase() ?? null;
|
|
65
|
+
}
|
|
66
|
+
function checkboxDbStatusMilestoneIds(basePath, milestoneIds) {
|
|
67
|
+
if (!hasFlatPhaseLayout(basePath))
|
|
68
|
+
return milestoneIds;
|
|
69
|
+
// Flat-phase directories are keyed by phase number. A restored
|
|
70
|
+
// M003-xxxxxx row alongside M003 is a stale duplicate for the same
|
|
71
|
+
// phases/03-* projection, so checking both can compare DB status against two
|
|
72
|
+
// competing PLAN files and report a persistent false divergence.
|
|
73
|
+
const allIds = new Set(milestoneIds.map((id) => id.toUpperCase()));
|
|
74
|
+
return milestoneIds.filter((milestoneId) => {
|
|
75
|
+
const bareId = bareDuplicateMilestoneId(milestoneId);
|
|
76
|
+
return !bareId || !allIds.has(bareId);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
61
79
|
function checkProjectionCheckboxDbStatus(basePath, milestoneIds, issues) {
|
|
62
80
|
for (const milestoneId of milestoneIds) {
|
|
63
|
-
const
|
|
81
|
+
const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, milestoneId);
|
|
82
|
+
const roadmapPath = resolveMilestoneFile(artifactBasePath, milestoneId, "ROADMAP");
|
|
64
83
|
const slices = getMilestoneSlices(milestoneId);
|
|
65
84
|
if (roadmapPath && existsSync(roadmapPath)) {
|
|
66
85
|
try {
|
|
@@ -78,7 +97,7 @@ function checkProjectionCheckboxDbStatus(basePath, milestoneIds, issues) {
|
|
|
78
97
|
}
|
|
79
98
|
}
|
|
80
99
|
for (const slice of slices) {
|
|
81
|
-
const planPath = resolveSliceFile(
|
|
100
|
+
const planPath = resolveSliceFile(artifactBasePath, milestoneId, slice.id, "PLAN");
|
|
82
101
|
if (!planPath || !existsSync(planPath))
|
|
83
102
|
continue;
|
|
84
103
|
try {
|
|
@@ -117,7 +136,7 @@ function isClearedByMilestoneShellProjectionFlush(basePath, issue, reRenderedMil
|
|
|
117
136
|
function artifactExistsOnDisk(basePath, artifactPath, row) {
|
|
118
137
|
return resolveArtifactDiskPath(basePath, artifactPath, row) !== null;
|
|
119
138
|
}
|
|
120
|
-
function resolveLiteralArtifactDiskPath(basePath, artifactPath) {
|
|
139
|
+
function resolveLiteralArtifactDiskPath(basePath, artifactPath, row) {
|
|
121
140
|
const relativeArtifactPath = artifactPathRelativeToGsd(artifactPath);
|
|
122
141
|
if (isAbsolute(relativeArtifactPath)) {
|
|
123
142
|
return existsSync(relativeArtifactPath) ? relativeArtifactPath : null;
|
|
@@ -127,6 +146,16 @@ function resolveLiteralArtifactDiskPath(basePath, artifactPath) {
|
|
|
127
146
|
if (isPathInside(root, candidate) && existsSync(candidate))
|
|
128
147
|
return candidate;
|
|
129
148
|
}
|
|
149
|
+
if (row?.milestone_id) {
|
|
150
|
+
const artifactBasePath = resolveCanonicalMilestoneRoot(basePath, row.milestone_id);
|
|
151
|
+
if (artifactBasePath !== basePath) {
|
|
152
|
+
for (const root of [gsdProjectionRoot(artifactBasePath), gsdRoot(artifactBasePath)]) {
|
|
153
|
+
const candidate = join(root, relativeArtifactPath);
|
|
154
|
+
if (isPathInside(root, candidate) && existsSync(candidate))
|
|
155
|
+
return candidate;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
130
159
|
return null;
|
|
131
160
|
}
|
|
132
161
|
function relativeToGsdRoot(basePath, diskPath) {
|
|
@@ -152,11 +181,8 @@ function resolveFlatPhaseArtifactDiskPath(basePath, row) {
|
|
|
152
181
|
if (!artifactType)
|
|
153
182
|
return null;
|
|
154
183
|
if (row.slice_id && row.task_id) {
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
return null;
|
|
158
|
-
const candidate = join(phaseDir, buildTaskFileName(row.task_id, artifactType));
|
|
159
|
-
return existsSync(candidate) ? candidate : null;
|
|
184
|
+
const candidate = resolveTaskFile(basePath, row.milestone_id, row.slice_id, row.task_id, artifactType);
|
|
185
|
+
return candidate && isFlatPhaseDiskPath(basePath, candidate) ? candidate : null;
|
|
160
186
|
}
|
|
161
187
|
const candidate = row.slice_id
|
|
162
188
|
? resolveSliceFile(basePath, row.milestone_id, row.slice_id, artifactType)
|
|
@@ -169,7 +195,7 @@ function resolveArtifactDiskPath(basePath, artifactPath, row) {
|
|
|
169
195
|
if (flatPath)
|
|
170
196
|
return flatPath;
|
|
171
197
|
}
|
|
172
|
-
return resolveLiteralArtifactDiskPath(basePath, artifactPath);
|
|
198
|
+
return resolveLiteralArtifactDiskPath(basePath, artifactPath, row);
|
|
173
199
|
}
|
|
174
200
|
function taskExistsInPlan(basePath, milestoneId, sliceId, taskId) {
|
|
175
201
|
const planPath = resolveSliceFile(basePath, milestoneId, sliceId, "PLAN");
|
|
@@ -325,7 +351,9 @@ function staleMilestonesArtifactRowFixable(basePath, row, artifactRows) {
|
|
|
325
351
|
}
|
|
326
352
|
function stalePhasesArtifactRowFixable(basePath, row, artifactRows) {
|
|
327
353
|
const issuePath = artifactPathRelativeToGsd(row.path);
|
|
328
|
-
return issuePath.startsWith(`${LAYOUT_SEGMENTS.level1}/`) &&
|
|
354
|
+
return issuePath.startsWith(`${LAYOUT_SEGMENTS.level1}/`) &&
|
|
355
|
+
(hasPresentFlatPhaseReplacement(basePath, row, artifactRows) ||
|
|
356
|
+
hasPresentMilestonesReplacement(basePath, row, artifactRows));
|
|
329
357
|
}
|
|
330
358
|
function staleArtifactRowFixable(basePath, row, artifactRows) {
|
|
331
359
|
return staleMilestonesArtifactRowFixable(basePath, row, artifactRows) ||
|
|
@@ -661,7 +689,7 @@ export async function checkEngineHealth(basePath, issues, fixesApplied, options)
|
|
|
661
689
|
// block doctor.
|
|
662
690
|
try {
|
|
663
691
|
if (isDbAvailable()) {
|
|
664
|
-
checkProjectionCheckboxDbStatus(basePath, getAllMilestones().map((milestone) => milestone.id), issues);
|
|
692
|
+
checkProjectionCheckboxDbStatus(basePath, checkboxDbStatusMilestoneIds(basePath, getAllMilestones().map((milestone) => milestone.id)), issues);
|
|
665
693
|
}
|
|
666
694
|
}
|
|
667
695
|
catch {
|
|
@@ -38,8 +38,12 @@ const NETWORK_RE = /network|ECONNRESET|ETIMEDOUT|ECONNREFUSED|socket hang up|web
|
|
|
38
38
|
// transient errors so auto-mode can retry with reduced budget or fall back to a larger-context model.
|
|
39
39
|
// See: https://github.com/open-gsd/gsd-pi/issues/4528
|
|
40
40
|
const SERVER_RE = /internal(?: server)?[ _-]?error|server[ _-]?error|500|502|503|overloaded|server_error|api_error|service.?unavailable|context (?:window|length) exceed|context window exceed/i;
|
|
41
|
+
// Provider adapters throw this when an upstream stop reason reaches Pi before
|
|
42
|
+
// the adapter knows how to map it. Keep the match scoped so plain "unknown"
|
|
43
|
+
// runtime errors still pause for inspection instead of being retried forever.
|
|
44
|
+
const PROVIDER_STOP_REASON_RE = /unhandled stop reason:\s*(?:abort|unknown)\b/i;
|
|
41
45
|
// ECONNRESET/ECONNREFUSED are in NETWORK_RE (same-model retry first).
|
|
42
|
-
const CONNECTION_RE = /terminated|connection.?(?:refused|error)|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
|
|
46
|
+
const CONNECTION_RE = /terminated|\babort\b|connection.?(?:refused|error)|other side closed|EPIPE|network.?(?:is\s+)?unavailable|stream_exhausted(?:_without_result)?/i;
|
|
43
47
|
// Catch-all for V8 JSON.parse errors: all modern variants end with "in JSON at position \d+".
|
|
44
48
|
// This eliminates the need to enumerate every error message variant individually.
|
|
45
49
|
const STREAM_RE = /in JSON at position \d+|Unexpected end of JSON|SyntaxError.*JSON/i;
|
|
@@ -72,7 +76,7 @@ const UNSUPPORTED_MODEL_SCOPE_RE = /\b(?:account|plan|tier|subscription)\b/i;
|
|
|
72
76
|
* 3. Network (ECONNRESET, ETIMEDOUT, socket hang up, fetch failed, dns)
|
|
73
77
|
* 4. Stream truncation (malformed JSON from mid-stream cut)
|
|
74
78
|
* 5. Server (500/502/503, overloaded, server_error)
|
|
75
|
-
* 6. Connection (terminated, ECONNREFUSED, EPIPE, other side closed)
|
|
79
|
+
* 6. Connection (terminated, abort/unknown stop reason, ECONNREFUSED, EPIPE, other side closed)
|
|
76
80
|
* 7. Model error (400 invalid argument / payload rejected for this model)
|
|
77
81
|
* 8. Unknown
|
|
78
82
|
*/
|
|
@@ -124,6 +128,12 @@ export function classifyError(errorMsg, retryAfterMs) {
|
|
|
124
128
|
const delayMs = resetMatch ? Number(resetMatch[1]) * 1000 : 60_000;
|
|
125
129
|
return { kind: "rate-limit", retryAfterMs: delayMs };
|
|
126
130
|
}
|
|
131
|
+
// Provider stop-reason adapter gaps are usually request/stream failures from
|
|
132
|
+
// the current model. Treat the scoped adapter message as fallback-eligible,
|
|
133
|
+
// but keep generic unknown errors on the indefinite pause path.
|
|
134
|
+
if (PROVIDER_STOP_REASON_RE.test(errorMsg)) {
|
|
135
|
+
return { kind: "connection", retryAfterMs: retryAfterMs ?? 15_000 };
|
|
136
|
+
}
|
|
127
137
|
// 3. Network errors — same-model retry candidate
|
|
128
138
|
if (NETWORK_RE.test(errorMsg)) {
|
|
129
139
|
// Exclude if also matches permanent signals (already handled above for
|