@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,10 +8,31 @@
|
|
|
8
8
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
|
+
import { getProviders } from "@gsd/pi-ai";
|
|
11
12
|
import { gsdHome } from "./gsd-home.js";
|
|
12
13
|
import { canonicalModelForTier, defaultRoutingConfig, resolveModelForTier } from "./model-router.js";
|
|
13
14
|
import { clearGSDPreferencesCache, loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
|
|
14
15
|
import { getUnitPhaseChain } from "./unit-registry.js";
|
|
16
|
+
/**
|
|
17
|
+
* First-party providers shipped as bundled extensions that delegate to a
|
|
18
|
+
* vendor CLI (`authMode: "externalCli"`). They are registered into the live
|
|
19
|
+
* model registry at runtime, so they are absent from the generated `@gsd/pi-ai`
|
|
20
|
+
* catalog (`getProviders()`), but they are NOT custom: `PREFERENCES.md` can
|
|
21
|
+
* route to them, so they must defer to `PREFERENCES.md` like any other built-in
|
|
22
|
+
* provider. Without this exclusion the registry check below would classify the
|
|
23
|
+
* default `claude-code` provider (and the other CLI providers) as custom and
|
|
24
|
+
* silently skip `PREFERENCES.md` in auto-mode (#801, extends #4122).
|
|
25
|
+
*
|
|
26
|
+
* Kept in sync with the `registerProvider(...)` calls in the bundled CLI
|
|
27
|
+
* extensions (claude-code-cli, cursor-cli, google-cli). Names are lowercase for
|
|
28
|
+
* direct comparison against normalized provider ids.
|
|
29
|
+
*/
|
|
30
|
+
const BUILTIN_EXTENSION_PROVIDERS = new Set([
|
|
31
|
+
"claude-code",
|
|
32
|
+
"cursor-agent",
|
|
33
|
+
"google-gemini-cli",
|
|
34
|
+
"google-antigravity",
|
|
35
|
+
]);
|
|
15
36
|
/**
|
|
16
37
|
* Resolve which model ID to use for a given auto-mode unit type.
|
|
17
38
|
* Returns undefined if no model preference is set for this unit type.
|
|
@@ -281,9 +302,8 @@ export function resolveDefaultSessionModel(sessionProvider, basePath, availableM
|
|
|
281
302
|
return undefined;
|
|
282
303
|
}
|
|
283
304
|
/**
|
|
284
|
-
* Returns true if `provider` is
|
|
285
|
-
*
|
|
286
|
-
* proxies, etc.).
|
|
305
|
+
* Returns true if `provider` is a custom provider. Custom providers may be
|
|
306
|
+
* declared in `models.json` or registered dynamically by a Pi extension.
|
|
287
307
|
*
|
|
288
308
|
* Used by auto-mode bootstrap to decide whether the session model
|
|
289
309
|
* (set via `/gsd model`) should override `PREFERENCES.md`. Custom providers
|
|
@@ -292,13 +312,16 @@ export function resolveDefaultSessionModel(sessionProvider, basePath, availableM
|
|
|
292
312
|
* priority — otherwise auto-mode tries to start the built-in provider from
|
|
293
313
|
* PREFERENCES.md and fails with "Not logged in · Please run /login" (#4122).
|
|
294
314
|
*
|
|
295
|
-
* Reads models.json directly with a lightweight JSON parse
|
|
296
|
-
*
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
315
|
+
* Reads models.json directly with a lightweight JSON parse, then checks the
|
|
316
|
+
* live model registry for extension-registered providers that are not in the
|
|
317
|
+
* generated built-in provider catalog (`getProviders()`) and not one of the
|
|
318
|
+
* bundled external-CLI providers (`BUILTIN_EXTENSION_PROVIDERS`, e.g.
|
|
319
|
+
* `claude-code`), which register at runtime but are still built-in. Falls back
|
|
320
|
+
* to `~/.pi/agent/models.json` for parity with `resolveModelsJsonPath()`. Any
|
|
321
|
+
* read, parse, or registry error yields `false` (treat as not-custom) so
|
|
322
|
+
* bootstrap stays non-fatal.
|
|
300
323
|
*/
|
|
301
|
-
export function isCustomProvider(provider) {
|
|
324
|
+
export function isCustomProvider(provider, registry) {
|
|
302
325
|
if (!provider)
|
|
303
326
|
return false;
|
|
304
327
|
const candidates = [
|
|
@@ -319,7 +342,24 @@ export function isCustomProvider(provider) {
|
|
|
319
342
|
// Ignore — malformed models.json must not break bootstrap.
|
|
320
343
|
}
|
|
321
344
|
}
|
|
322
|
-
|
|
345
|
+
try {
|
|
346
|
+
const normalizedProvider = provider.trim().toLowerCase();
|
|
347
|
+
if (!normalizedProvider)
|
|
348
|
+
return false;
|
|
349
|
+
if (BUILTIN_EXTENSION_PROVIDERS.has(normalizedProvider))
|
|
350
|
+
return false;
|
|
351
|
+
const builtInProviders = new Set(getProviders().map((p) => p.toLowerCase()));
|
|
352
|
+
if (builtInProviders.has(normalizedProvider))
|
|
353
|
+
return false;
|
|
354
|
+
const registryModels = registry?.getAllWithDiscovered?.()
|
|
355
|
+
?? registry?.getAll?.()
|
|
356
|
+
?? registry?.getAvailable?.()
|
|
357
|
+
?? [];
|
|
358
|
+
return registryModels.some((m) => m.provider.toLowerCase() === normalizedProvider);
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
return false;
|
|
362
|
+
}
|
|
323
363
|
}
|
|
324
364
|
/**
|
|
325
365
|
* Determines the next fallback model to try when the current model fails.
|
|
@@ -61,6 +61,8 @@ export const KNOWN_PREFERENCE_KEYS = new Set([
|
|
|
61
61
|
"git",
|
|
62
62
|
"post_unit_hooks",
|
|
63
63
|
"pre_dispatch_hooks",
|
|
64
|
+
"planning_subagent_registry",
|
|
65
|
+
"planning_subagents",
|
|
64
66
|
"dynamic_routing",
|
|
65
67
|
"disabled_model_providers",
|
|
66
68
|
"uok",
|
|
@@ -134,6 +136,10 @@ export const KNOWN_UNIT_LABELS = [
|
|
|
134
136
|
"workflow-preferences", "discuss-project", "discuss-requirements",
|
|
135
137
|
"research-decision", "research-project",
|
|
136
138
|
];
|
|
139
|
+
export const CONFIGURABLE_PLANNING_SUBAGENT_UNITS = [
|
|
140
|
+
"plan-milestone",
|
|
141
|
+
"plan-slice",
|
|
142
|
+
];
|
|
137
143
|
export const SKILL_ACTIONS = new Set(["use", "prefer", "avoid"]);
|
|
138
144
|
/** The nine model-routing phase buckets. */
|
|
139
145
|
export const GSD_MODEL_PHASE_KEYS = [
|
|
@@ -9,7 +9,8 @@ import { isAbsolute } from "node:path";
|
|
|
9
9
|
import { VALID_BRANCH_NAME } from "./git-service.js";
|
|
10
10
|
import { normalizeStringArray } from "../shared/format-utils.js";
|
|
11
11
|
import { getGateIdsForTurn } from "./gate-registry.js";
|
|
12
|
-
import { KNOWN_PREFERENCE_KEYS, KNOWN_UNIT_LABELS, GSD_MODEL_PHASE_KEYS, SKILL_ACTIONS, } from "./preferences-types.js";
|
|
12
|
+
import { KNOWN_PREFERENCE_KEYS, KNOWN_UNIT_LABELS, CONFIGURABLE_PLANNING_SUBAGENT_UNITS, GSD_MODEL_PHASE_KEYS, SKILL_ACTIONS, } from "./preferences-types.js";
|
|
13
|
+
import { allowedPlanningDispatchAgentsList, isReadOnlyPlanningDispatchAgent, } from "./planning-subagent-registry.js";
|
|
13
14
|
const VALID_TOKEN_PROFILES = new Set(["budget", "balanced", "quality", "burn-max"]);
|
|
14
15
|
const VALID_THINKING_LEVELS = new Set([
|
|
15
16
|
"off",
|
|
@@ -18,6 +19,7 @@ const VALID_THINKING_LEVELS = new Set([
|
|
|
18
19
|
"medium",
|
|
19
20
|
"high",
|
|
20
21
|
"xhigh",
|
|
22
|
+
"max",
|
|
21
23
|
]);
|
|
22
24
|
const KNOWN_MODEL_PHASE_KEYS = new Set(GSD_MODEL_PHASE_KEYS);
|
|
23
25
|
const VALID_UOK_TURN_ACTIONS = new Set([
|
|
@@ -68,7 +70,7 @@ function sanitizeModelField(raw, label, errors, warnings) {
|
|
|
68
70
|
}
|
|
69
71
|
else {
|
|
70
72
|
warnings?.push(`${label} thinking "${String(obj.thinking)}" is not a valid thinking level ` +
|
|
71
|
-
`(off, minimal, low, medium, high, xhigh) — ignored`);
|
|
73
|
+
`(off, minimal, low, medium, high, xhigh, max) — ignored`);
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
return sanitized;
|
|
@@ -456,7 +458,7 @@ export function validatePreferences(preferences) {
|
|
|
456
458
|
const level = entry.thinking;
|
|
457
459
|
if (level !== undefined && !VALID_THINKING_LEVELS.has(level)) {
|
|
458
460
|
warnings.push(`models.${phase}.thinking "${String(level)}" is not a valid thinking level ` +
|
|
459
|
-
`(off, minimal, low, medium, high, xhigh) — ignored`);
|
|
461
|
+
`(off, minimal, low, medium, high, xhigh, max) — ignored`);
|
|
460
462
|
const { thinking: _ignored, ...rest } = entry;
|
|
461
463
|
// If stripping the bad thinking leaves no usable model, drop the
|
|
462
464
|
// phase entirely rather than storing a hollow `{}` / `{ provider }`
|
|
@@ -487,7 +489,7 @@ export function validatePreferences(preferences) {
|
|
|
487
489
|
}
|
|
488
490
|
if (!VALID_THINKING_LEVELS.has(level)) {
|
|
489
491
|
warnings.push(`thinking.${phase} "${String(level)}" is not a valid thinking level ` +
|
|
490
|
-
`(off, minimal, low, medium, high, xhigh) — ignored`);
|
|
492
|
+
`(off, minimal, low, medium, high, xhigh, max) — ignored`);
|
|
491
493
|
continue;
|
|
492
494
|
}
|
|
493
495
|
validatedThinking[phase] = level;
|
|
@@ -727,6 +729,86 @@ export function validatePreferences(preferences) {
|
|
|
727
729
|
validated.pre_dispatch_hooks = validPreHooks;
|
|
728
730
|
}
|
|
729
731
|
}
|
|
732
|
+
// ─── Planning Subagent Registry ──────────────────────────────────────────
|
|
733
|
+
if (preferences.planning_subagent_registry !== undefined) {
|
|
734
|
+
if (!preferences.planning_subagent_registry ||
|
|
735
|
+
typeof preferences.planning_subagent_registry !== "object" ||
|
|
736
|
+
Array.isArray(preferences.planning_subagent_registry)) {
|
|
737
|
+
errors.push("planning_subagent_registry must be an object keyed by agent id");
|
|
738
|
+
}
|
|
739
|
+
else {
|
|
740
|
+
const validRegistry = {};
|
|
741
|
+
for (const [rawAgentId, rawConfig] of Object.entries(preferences.planning_subagent_registry)) {
|
|
742
|
+
const agentId = rawAgentId.trim();
|
|
743
|
+
if (!agentId) {
|
|
744
|
+
errors.push("planning_subagent_registry includes an empty agent id");
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
748
|
+
errors.push(`planning_subagent_registry.${agentId} must be an object with read_only_specialist: true`);
|
|
749
|
+
continue;
|
|
750
|
+
}
|
|
751
|
+
const readOnlySpecialist = rawConfig.read_only_specialist;
|
|
752
|
+
if (readOnlySpecialist !== true) {
|
|
753
|
+
errors.push(`planning_subagent_registry.${agentId}.read_only_specialist must be true to classify ` +
|
|
754
|
+
`"${agentId}" as a read-only planning specialist`);
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
validRegistry[agentId] = { read_only_specialist: true };
|
|
758
|
+
}
|
|
759
|
+
if (Object.keys(validRegistry).length > 0) {
|
|
760
|
+
validated.planning_subagent_registry = validRegistry;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
// ─── Planning Subagents ─────────────────────────────────────────────────
|
|
765
|
+
if (preferences.planning_subagents !== undefined) {
|
|
766
|
+
if (!preferences.planning_subagents ||
|
|
767
|
+
typeof preferences.planning_subagents !== "object" ||
|
|
768
|
+
Array.isArray(preferences.planning_subagents)) {
|
|
769
|
+
errors.push("planning_subagents must be an object keyed by planning unit type");
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
const validUnits = new Set(CONFIGURABLE_PLANNING_SUBAGENT_UNITS);
|
|
773
|
+
const validPlanningSubagents = {};
|
|
774
|
+
for (const [unitType, rawConfig] of Object.entries(preferences.planning_subagents)) {
|
|
775
|
+
if (!validUnits.has(unitType)) {
|
|
776
|
+
errors.push(`planning_subagents unknown or unsupported unit "${unitType}" — supported units: ` +
|
|
777
|
+
`${CONFIGURABLE_PLANNING_SUBAGENT_UNITS.join(", ")}`);
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (!rawConfig || typeof rawConfig !== "object" || Array.isArray(rawConfig)) {
|
|
781
|
+
errors.push(`planning_subagents.${unitType} must be an object with an allowed array`);
|
|
782
|
+
continue;
|
|
783
|
+
}
|
|
784
|
+
const allowed = normalizeStringArray(rawConfig.allowed);
|
|
785
|
+
if (allowed.length === 0) {
|
|
786
|
+
errors.push(`planning_subagents.${unitType}.allowed must include at least one read-only planning specialist`);
|
|
787
|
+
continue;
|
|
788
|
+
}
|
|
789
|
+
const sanitizedAllowed = [];
|
|
790
|
+
for (const agentId of allowed) {
|
|
791
|
+
if (!isReadOnlyPlanningDispatchAgent(agentId, validated.planning_subagent_registry)) {
|
|
792
|
+
errors.push(`planning_subagents.${unitType}.allowed includes "${agentId}", which is not classified as a ` +
|
|
793
|
+
`read-only planning specialist. Allowed agents: ` +
|
|
794
|
+
`${allowedPlanningDispatchAgentsList(validated.planning_subagent_registry)}. ` +
|
|
795
|
+
`For custom planning agents, add planning_subagent_registry.${agentId}.read_only_specialist: true`);
|
|
796
|
+
continue;
|
|
797
|
+
}
|
|
798
|
+
sanitizedAllowed.push(agentId);
|
|
799
|
+
}
|
|
800
|
+
const dedupedAllowed = Array.from(new Set(sanitizedAllowed));
|
|
801
|
+
if (dedupedAllowed.length > 0) {
|
|
802
|
+
validPlanningSubagents[unitType] = {
|
|
803
|
+
allowed: dedupedAllowed,
|
|
804
|
+
};
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
if (Object.keys(validPlanningSubagents).length > 0) {
|
|
808
|
+
validated.planning_subagents = validPlanningSubagents;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
730
812
|
// ─── Dynamic Routing ─────────────────────────────────────────────────
|
|
731
813
|
if (preferences.dynamic_routing !== undefined) {
|
|
732
814
|
if (typeof preferences.dynamic_routing === "object" && preferences.dynamic_routing !== null) {
|
|
@@ -635,6 +635,8 @@ function mergePreferences(base, override) {
|
|
|
635
635
|
: undefined,
|
|
636
636
|
post_unit_hooks: mergePostUnitHooks(base.post_unit_hooks, override.post_unit_hooks),
|
|
637
637
|
pre_dispatch_hooks: mergePreDispatchHooks(base.pre_dispatch_hooks, override.pre_dispatch_hooks),
|
|
638
|
+
planning_subagent_registry: mergePlanningSubagentRegistry(base.planning_subagent_registry, override.planning_subagent_registry),
|
|
639
|
+
planning_subagents: mergePlanningSubagents(base.planning_subagents, override.planning_subagents),
|
|
638
640
|
dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
|
|
639
641
|
? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) }
|
|
640
642
|
: undefined,
|
|
@@ -752,6 +754,28 @@ function mergePreDispatchHooks(base, override) {
|
|
|
752
754
|
}
|
|
753
755
|
return merged.length > 0 ? merged : undefined;
|
|
754
756
|
}
|
|
757
|
+
function mergePlanningSubagents(base, override) {
|
|
758
|
+
if (!base && !override)
|
|
759
|
+
return undefined;
|
|
760
|
+
const merged = {};
|
|
761
|
+
const unitTypes = new Set([
|
|
762
|
+
...Object.keys(base ?? {}),
|
|
763
|
+
...Object.keys(override ?? {}),
|
|
764
|
+
]);
|
|
765
|
+
for (const unitType of unitTypes) {
|
|
766
|
+
const allowed = mergeStringLists(base?.[unitType]?.allowed, override?.[unitType]?.allowed);
|
|
767
|
+
if (allowed?.length) {
|
|
768
|
+
merged[unitType] = { allowed };
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
772
|
+
}
|
|
773
|
+
function mergePlanningSubagentRegistry(base, override) {
|
|
774
|
+
if (!base && !override)
|
|
775
|
+
return undefined;
|
|
776
|
+
const merged = { ...(base ?? {}), ...(override ?? {}) };
|
|
777
|
+
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
778
|
+
}
|
|
755
779
|
// ─── System Prompt Rendering ──────────────────────────────────────────────────
|
|
756
780
|
export function renderPreferencesForSystemPrompt(preferences, resolutions, options) {
|
|
757
781
|
const validated = validatePreferences(preferences);
|
|
@@ -24,18 +24,18 @@ Roadmap, slice summaries, assessments, requirements, decisions, and project cont
|
|
|
24
24
|
|
|
25
25
|
### Step 1 - Dispatch Parallel Reviewers
|
|
26
26
|
|
|
27
|
-
The Inlined Context above already preloads the evidence reviewers need — the roadmap, per-slice SUMMARY/ASSESSMENT excerpts, requirements, and verification classes. **Embed the relevant preloaded evidence directly into each reviewer's task prompt** so reviewers work from it instead of re-reading the same artifacts from disk. Each reviewer should read a full file only when its excerpt is missing, truncated, or internally inconsistent — never as a routine first step. This avoids three reviewers independently re-surveying artifacts the orchestrator already holds.
|
|
27
|
+
The Inlined Context above already preloads the evidence reviewers need — the roadmap, per-slice SUMMARY/ASSESSMENT excerpts, requirements, and verification classes. **Embed the relevant preloaded evidence directly into each reviewer's task prompt** so reviewers work from it instead of re-reading the same artifacts from disk. Each reviewer should read a full file only when its excerpt is missing, truncated, or internally inconsistent — never as a routine first step. When a reviewer needs a full artifact, use only explicit file paths from the On-demand Validation Artifacts / On-demand Milestone Context blocks or discover files with `find .gsd -type f`; never pass a phase, slice, `tasks/`, or `slices/` directory to `read` or `readFileSync`. This avoids three reviewers independently re-surveying artifacts the orchestrator already holds.
|
|
28
28
|
|
|
29
29
|
Call `subagent` with `tasks: [...]` containing ALL THREE reviewers simultaneously:
|
|
30
30
|
|
|
31
31
|
**Reviewer A - Requirements Coverage**
|
|
32
|
-
Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Use the preloaded requirements and slice SUMMARY evidence embedded in this task — do not re-read them from disk. For each requirement, mark COVERED, PARTIAL, or MISSING against that evidence. Read a full SUMMARY
|
|
32
|
+
Prompt: "Review milestone {{milestoneId}} requirements coverage. Working directory: {{workingDirectory}}. Use the preloaded requirements and slice SUMMARY evidence embedded in this task — do not re-read them from disk. For each requirement, mark COVERED, PARTIAL, or MISSING against that evidence. Read a full SUMMARY only from an explicit file path in the On-demand Validation Artifacts list, or discover candidates with `find .gsd -type f -name '*-SUMMARY.md'`; never read a directory path. Output table: Requirement | Status | Evidence. End with one-line verdict: PASS if all covered, NEEDS-ATTENTION if partials exist, FAIL if any missing."
|
|
33
33
|
|
|
34
34
|
**Reviewer B - Cross-Slice Integration**
|
|
35
|
-
Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Use the preloaded roadmap and slice SUMMARY evidence embedded in this task — do not re-read them from disk. Find the boundary map (produces/consumes contracts) in the roadmap. For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Read `{{roadmapPath}}` or a full SUMMARY only if the preloaded evidence is missing, truncated, or inconsistent. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
|
|
35
|
+
Prompt: "Review milestone {{milestoneId}} cross-slice integration. Working directory: {{workingDirectory}}. Use the preloaded roadmap and slice SUMMARY evidence embedded in this task — do not re-read them from disk. Find the boundary map (produces/consumes contracts) in the roadmap. For each boundary, confirm producer SUMMARY produced the artifact and consumer SUMMARY consumed it. Read `{{roadmapPath}}` or a full SUMMARY from the On-demand Validation Artifacts list only if the preloaded evidence is missing, truncated, or inconsistent; never read a directory path. Output table: Boundary | Producer Summary | Consumer Summary | Status. End with one-line verdict: PASS if all boundaries honored, NEEDS-ATTENTION if any gaps."
|
|
36
36
|
|
|
37
37
|
**Reviewer C - Assessment & Acceptance Criteria**
|
|
38
|
-
Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Use the preloaded milestone context, slice SUMMARY, and ASSESSMENT evidence embedded in this task — do not re-read them from disk. Read
|
|
38
|
+
Prompt: "Review milestone {{milestoneId}} assessment evidence and acceptance criteria. Working directory: {{workingDirectory}}. Use the preloaded milestone context, slice SUMMARY, and ASSESSMENT evidence embedded in this task — do not re-read them from disk. Read the milestone context from the On-demand Milestone Context file path, and read full SUMMARY or ASSESSMENT files only from explicit paths in the On-demand Validation Artifacts list, if the preloaded excerpt is missing, truncated, or inconsistent. UAT files are specs, not evidence. Verify each criterion maps to passing evidence. Then review the inlined `Verification Classes (from planning)` table. For every planned row in that table, output a `Verification Classes` table with columns `Class | Planned Check | Evidence | Verdict`. Preserve every planned non-empty class row; do not summarize, rename, combine, or omit planned classes. The first cell of each row must be exactly `Contract`, `Integration`, `Operational`, or `UAT` when that class is present in planning. If a planned class lacks evidence, still include its canonical row and mark the verdict NEEDS-ATTENTION or FAIL. If a planned browser/UAT class has no ASSESSMENT with browser/runtime actions and assertions, return NEEDS-ATTENTION. If no verification classes were planned, say that explicitly. Output sections `Acceptance Criteria` with checklist `[ ] Criterion | Evidence`, and `Verification Classes` with the table. End with one-line verdict: PASS if all criteria and classes are covered by evidence, NEEDS-ATTENTION if gaps exist."
|
|
39
39
|
|
|
40
40
|
### Step 2 - Synthesize Findings
|
|
41
41
|
|
|
@@ -85,6 +85,6 @@ If verdict is `needs-remediation`:
|
|
|
85
85
|
|
|
86
86
|
**You MUST call `gsd_validate_milestone` before finishing. Do not manually write `{{validationPath}}`.**
|
|
87
87
|
|
|
88
|
-
**File system safety:** When scanning milestone directories, use `
|
|
88
|
+
**File system safety:** When scanning milestone directories, use `find .gsd -type f` first and read only files. In flat-phase projects, `.gsd/phases/<NN>-<slug>/` is a directory, not an artifact. Never pass a directory path such as a phase directory, `tasks/`, or `slices/` directly to `read`, `readFile`, or `readFileSync`.
|
|
89
89
|
|
|
90
90
|
When done, say: "Milestone {{milestoneId}} validation complete — verdict: <verdict>." Say this exactly once — if you already said it in a prior message, do not repeat it.
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
* Provider Payload Policy - ordered shaping of provider request payloads.
|
|
3
3
|
*
|
|
4
4
|
* The order is intentional:
|
|
5
|
-
* 1.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* 1. superseded GSD context injections (memory/guided/forensics) are removed,
|
|
6
|
+
* keeping only the latest, for every mode,
|
|
7
|
+
* 2. observation budgeting masks old tool results in auto-mode,
|
|
8
|
+
* 3. display truncation caps tool-result text for every mode,
|
|
9
|
+
* 4. the protected Source Context Block is appended after truncation,
|
|
10
|
+
* 5. supported models receive the configured service tier.
|
|
9
11
|
*/
|
|
10
|
-
import { createObservationMask, createResponsesInputObservationMask, truncateContextResultMessages, truncateResponsesInputResultItems, } from "./context-masker.js";
|
|
12
|
+
import { createObservationMask, createResponsesInputObservationMask, filterSupersededContextInjections, filterSupersededResponsesContextInjections, truncateContextResultMessages, truncateResponsesInputResultItems, } from "./context-masker.js";
|
|
11
13
|
import { getSourceObservationStore, isAutoActive } from "./auto-runtime-state.js";
|
|
12
14
|
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
13
15
|
import { getEffectiveServiceTier, supportsServiceTier } from "./service-tier.js";
|
|
@@ -42,9 +44,18 @@ export function applyProviderPayloadPolicy({ payload, modelId, deps: overrides,
|
|
|
42
44
|
}
|
|
43
45
|
function applyContextManagement(payload, deps) {
|
|
44
46
|
const config = deps.loadContextManagementConfig();
|
|
47
|
+
applyContextInjectionFilter(payload);
|
|
45
48
|
applyObservationBudget(payload, config, deps.isAutoActive());
|
|
46
49
|
applyDisplayTruncation(payload, config);
|
|
47
50
|
}
|
|
51
|
+
function applyContextInjectionFilter(payload) {
|
|
52
|
+
if (Array.isArray(payload.messages)) {
|
|
53
|
+
payload.messages = filterSupersededContextInjections(payload.messages);
|
|
54
|
+
}
|
|
55
|
+
if (Array.isArray(payload.input)) {
|
|
56
|
+
payload.input = filterSupersededResponsesContextInjections(payload.input);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
48
59
|
function applyObservationBudget(payload, config, autoActive) {
|
|
49
60
|
if (!autoActive || config?.observation_masking === false)
|
|
50
61
|
return;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Copyright (c) 2026 Jeremy McSpadden <jeremy@fluxlabs.net>
|
|
7
7
|
*/
|
|
8
8
|
const DESTRUCTIVE_PATTERNS = [
|
|
9
|
-
{ pattern: /\brm\s+(
|
|
9
|
+
{ pattern: /\brm\s+((?:-(?!-)[^\s]*[rR][^\s]*|--recursive)\s+|.*\s+(?:-(?!-)[^\s]*[rR][^\s]*|--recursive)(?:\s|$))/, label: "recursive delete" },
|
|
10
10
|
{ pattern: /\bgit\s+push\s+.*--force/, label: "force push" },
|
|
11
11
|
{ pattern: /\bgit\s+push\s+-f\b/, label: "force push" },
|
|
12
12
|
{ pattern: /\bgit\s+reset\s+--hard/, label: "hard reset" },
|
|
@@ -104,11 +104,24 @@ function resolvePreferredSkillNames(prefs, visibleSkills, contextTokens, base) {
|
|
|
104
104
|
/** Skill names must be lowercase alphanumeric with hyphens — reject anything else
|
|
105
105
|
* to prevent prompt injection via crafted directory names. */
|
|
106
106
|
const SAFE_SKILL_NAME = /^[a-z0-9][a-z0-9-]*$/;
|
|
107
|
-
function
|
|
107
|
+
function escapeXml(str) {
|
|
108
|
+
return str
|
|
109
|
+
.replace(/&/g, "&")
|
|
110
|
+
.replace(/</g, "<")
|
|
111
|
+
.replace(/>/g, ">")
|
|
112
|
+
.replace(/"/g, """)
|
|
113
|
+
.replace(/'/g, "'");
|
|
114
|
+
}
|
|
115
|
+
function formatSkillActivationBlock(skillNames, skillPaths) {
|
|
108
116
|
const safe = skillNames.filter(name => SAFE_SKILL_NAME.test(name));
|
|
109
117
|
if (safe.length === 0)
|
|
110
118
|
return "";
|
|
111
|
-
const reads = safe.map(name =>
|
|
119
|
+
const reads = safe.map(name => {
|
|
120
|
+
const path = skillPaths.get(name);
|
|
121
|
+
if (path)
|
|
122
|
+
return `Read the skill file at \`${escapeXml(path)}\``;
|
|
123
|
+
return `Find '${name}' in <available_skills>, copy its <location> value, and pass that exact path to read`;
|
|
124
|
+
}).join(". ");
|
|
112
125
|
return `<skill_activation>${reads}.</skill_activation>`;
|
|
113
126
|
}
|
|
114
127
|
/**
|
|
@@ -149,6 +162,7 @@ export function buildSkillActivationBlock(params) {
|
|
|
149
162
|
const visibleSkills = loaded;
|
|
150
163
|
const manifestScopedSkills = filterSkillsByManifest(visibleSkills, params.unitType);
|
|
151
164
|
const installedNames = new Set(visibleSkills.map(skill => normalizeSkillReference(skill.name)));
|
|
165
|
+
const installedSkillPaths = new Map(visibleSkills.map(skill => [normalizeSkillReference(skill.name), skill.filePath]));
|
|
152
166
|
warnIfManifestHasMissingSkills(params.unitType, installedNames);
|
|
153
167
|
const avoided = new Set(resolvePreferenceSkillNames(prefs?.avoid_skills ?? [], params.base));
|
|
154
168
|
const matched = new Set();
|
|
@@ -196,7 +210,7 @@ export function buildSkillActivationBlock(params) {
|
|
|
196
210
|
const ordered = [...matched]
|
|
197
211
|
.filter(name => installedNames.has(name) && !avoided.has(name))
|
|
198
212
|
.sort();
|
|
199
|
-
const activationBlock = formatSkillActivationBlock(ordered);
|
|
213
|
+
const activationBlock = formatSkillActivationBlock(ordered, installedSkillPaths);
|
|
200
214
|
// Omit recommendations when the system catalog is manifest-scoped for this
|
|
201
215
|
// unit — skill names are already listed in <available_skills>.
|
|
202
216
|
let recommendationsBlock = "";
|
|
@@ -8,9 +8,81 @@
|
|
|
8
8
|
// renderAllFromDb pass re-projects; the write-time invalidation hook then
|
|
9
9
|
// refreshes the marker entry, closing the loop.
|
|
10
10
|
import { existsSync, readFileSync } from "node:fs";
|
|
11
|
-
import { join } from "node:path";
|
|
11
|
+
import { basename, join } from "node:path";
|
|
12
12
|
import { computeProjectionSha, readCompatMarker, writeCompatMarker, } from "../../compat/compat-marker.js";
|
|
13
|
+
import { _getAdapter } from "../../gsd-db.js";
|
|
13
14
|
import { logWarning } from "../../workflow-logger.js";
|
|
15
|
+
function deepestProjectionScope(entities) {
|
|
16
|
+
let best = null;
|
|
17
|
+
for (const entity of entities) {
|
|
18
|
+
const parts = entity.split("/").filter(Boolean);
|
|
19
|
+
if (parts.length === 0)
|
|
20
|
+
continue;
|
|
21
|
+
if (!best || parts.length > best.length)
|
|
22
|
+
best = parts;
|
|
23
|
+
}
|
|
24
|
+
if (!best)
|
|
25
|
+
return null;
|
|
26
|
+
return {
|
|
27
|
+
milestoneId: best[0],
|
|
28
|
+
sliceId: best[1] ?? null,
|
|
29
|
+
taskId: best[2] ?? null,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function artifactTypeFromProjectionPath(projectionPath) {
|
|
33
|
+
const name = basename(projectionPath);
|
|
34
|
+
const match = name.match(/^(?:[A-Za-z]\d+|\d+(?:-\d+)?)-(.+)\.md$/);
|
|
35
|
+
return match?.[1]?.toUpperCase() ?? null;
|
|
36
|
+
}
|
|
37
|
+
function dbProjectionMatches(projectionPath, entry, actualSha) {
|
|
38
|
+
const adapter = _getAdapter();
|
|
39
|
+
if (!adapter)
|
|
40
|
+
return false;
|
|
41
|
+
try {
|
|
42
|
+
const rows = adapter
|
|
43
|
+
.prepare("SELECT full_content FROM artifacts WHERE path = :path")
|
|
44
|
+
.all({ ":path": projectionPath });
|
|
45
|
+
const scope = deepestProjectionScope(entry.entities);
|
|
46
|
+
const artifactType = artifactTypeFromProjectionPath(projectionPath);
|
|
47
|
+
if (scope?.taskId) {
|
|
48
|
+
rows.push(...adapter
|
|
49
|
+
.prepare(`SELECT full_content
|
|
50
|
+
FROM artifacts
|
|
51
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND task_id = :tid
|
|
52
|
+
AND (:type IS NULL OR artifact_type = :type)`)
|
|
53
|
+
.all({
|
|
54
|
+
":mid": scope.milestoneId,
|
|
55
|
+
":sid": scope.sliceId,
|
|
56
|
+
":tid": scope.taskId,
|
|
57
|
+
":type": artifactType,
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
else if (scope?.sliceId) {
|
|
61
|
+
rows.push(...adapter
|
|
62
|
+
.prepare(`SELECT full_content
|
|
63
|
+
FROM artifacts
|
|
64
|
+
WHERE milestone_id = :mid AND slice_id = :sid AND task_id IS NULL
|
|
65
|
+
AND (:type IS NULL OR artifact_type = :type)`)
|
|
66
|
+
.all({
|
|
67
|
+
":mid": scope.milestoneId,
|
|
68
|
+
":sid": scope.sliceId,
|
|
69
|
+
":type": artifactType,
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
else if (scope) {
|
|
73
|
+
rows.push(...adapter
|
|
74
|
+
.prepare(`SELECT full_content
|
|
75
|
+
FROM artifacts
|
|
76
|
+
WHERE milestone_id = :mid AND slice_id IS NULL AND task_id IS NULL
|
|
77
|
+
AND (:type IS NULL OR artifact_type = :type)`)
|
|
78
|
+
.all({ ":mid": scope.milestoneId, ":type": artifactType }));
|
|
79
|
+
}
|
|
80
|
+
return rows.some((row) => computeProjectionSha(row.full_content) === actualSha);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
14
86
|
/**
|
|
15
87
|
* Detect sha drift between the marker baseline and current file contents.
|
|
16
88
|
*
|
|
@@ -21,11 +93,15 @@ import { logWarning } from "../../workflow-logger.js";
|
|
|
21
93
|
* - Sha mismatch → one record per drifted file, scoped to its recorded entities.
|
|
22
94
|
*/
|
|
23
95
|
function detectExternalMarkdownEdit(_state, ctx) {
|
|
24
|
-
const marker = readCompatMarker(ctx.basePath
|
|
96
|
+
const marker = readCompatMarker(ctx.basePath, {
|
|
97
|
+
healInvalidKeys: !ctx.dryRun,
|
|
98
|
+
quarantineInvalid: !ctx.dryRun,
|
|
99
|
+
});
|
|
25
100
|
const entries = Object.entries(marker.projections);
|
|
26
101
|
if (entries.length === 0)
|
|
27
102
|
return [];
|
|
28
103
|
const records = [];
|
|
104
|
+
let markerChanged = false;
|
|
29
105
|
for (const [projectionPath, entry] of entries) {
|
|
30
106
|
const abs = join(ctx.basePath, ".gsd", projectionPath);
|
|
31
107
|
if (!existsSync(abs))
|
|
@@ -33,6 +109,21 @@ function detectExternalMarkdownEdit(_state, ctx) {
|
|
|
33
109
|
const actual = computeProjectionSha(readFileSync(abs, "utf-8"));
|
|
34
110
|
if (actual === entry.sha)
|
|
35
111
|
continue;
|
|
112
|
+
if (dbProjectionMatches(projectionPath, entry, actual)) {
|
|
113
|
+
if (!ctx.dryRun) {
|
|
114
|
+
marker.projections[projectionPath] = {
|
|
115
|
+
sha: actual,
|
|
116
|
+
entities: entry.entities,
|
|
117
|
+
};
|
|
118
|
+
markerChanged = true;
|
|
119
|
+
logWarning("reconcile", `external-markdown-edit: refreshed stale compat marker for ${projectionPath} (expectedSha=${entry.sha}, actualSha=${actual})`);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
logWarning("reconcile", `external-markdown-edit: stale compat marker for ${projectionPath} (expectedSha=${entry.sha}, actualSha=${actual})`);
|
|
123
|
+
}
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
logWarning("reconcile", `external-markdown-edit drift for ${projectionPath} (expectedSha=${entry.sha}, actualSha=${actual})`);
|
|
36
127
|
records.push({
|
|
37
128
|
kind: "external-markdown-edit",
|
|
38
129
|
projectionPath,
|
|
@@ -41,6 +132,11 @@ function detectExternalMarkdownEdit(_state, ctx) {
|
|
|
41
132
|
entities: entry.entities,
|
|
42
133
|
});
|
|
43
134
|
}
|
|
135
|
+
if (markerChanged) {
|
|
136
|
+
marker.lastWriter = "gsd-pi";
|
|
137
|
+
marker.lastProjectedAt = new Date().toISOString();
|
|
138
|
+
writeCompatMarker(ctx.basePath, marker);
|
|
139
|
+
}
|
|
44
140
|
return records;
|
|
45
141
|
}
|
|
46
142
|
/**
|
|
@@ -55,7 +55,10 @@ function detectUnseededPlanningFiles(ctx, projections, passthrough) {
|
|
|
55
55
|
return records;
|
|
56
56
|
}
|
|
57
57
|
async function detectExternalPlanningEdit(_state, ctx) {
|
|
58
|
-
const marker = readCompatMarker(ctx.basePath
|
|
58
|
+
const marker = readCompatMarker(ctx.basePath, {
|
|
59
|
+
healInvalidKeys: !ctx.dryRun,
|
|
60
|
+
quarantineInvalid: !ctx.dryRun,
|
|
61
|
+
});
|
|
59
62
|
if (!marker.planning?.active) {
|
|
60
63
|
// Not yet activated. Activation (layout parse + DB import) is owned by
|
|
61
64
|
// capturePlanningCompatIfNeeded, called from reconcileBeforeDispatch when
|
|
@@ -9,7 +9,7 @@ import { renderRoadmapFromDb } from "../../markdown-renderer.js";
|
|
|
9
9
|
import { findMilestoneIds } from "../../milestone-ids.js";
|
|
10
10
|
import { parseRoadmap } from "../../parsers-legacy.js";
|
|
11
11
|
import { resolveMilestoneFile } from "../../paths.js";
|
|
12
|
-
import { isClosedStatus } from "../../status-guards.js";
|
|
12
|
+
import { isClosedStatus, isSkippedForDispatch } from "../../status-guards.js";
|
|
13
13
|
function arraysEqual(a, b) {
|
|
14
14
|
if (a.length !== b.length)
|
|
15
15
|
return false;
|
|
@@ -76,7 +76,10 @@ export function detectRoadmapDivergenceDrift(_state, ctx) {
|
|
|
76
76
|
for (const milestoneId of findMilestoneIds(ctx.basePath)) {
|
|
77
77
|
// Skip milestones that don't yet have a DB row — that's the
|
|
78
78
|
// unregistered-milestone drift handler's responsibility.
|
|
79
|
-
|
|
79
|
+
const milestone = getMilestone(milestoneId);
|
|
80
|
+
if (!milestone)
|
|
81
|
+
continue;
|
|
82
|
+
if (isSkippedForDispatch(milestone.status))
|
|
80
83
|
continue;
|
|
81
84
|
if (milestoneHasDivergence(ctx.basePath, milestoneId)) {
|
|
82
85
|
drifts.push({ kind: "roadmap-divergence", milestoneId });
|
|
@@ -22,6 +22,12 @@ export function formatStopNoticePrefix(reason) {
|
|
|
22
22
|
const prefix = stopNoticeKind(reason) === "blocked" ? "Auto-mode blocked" : "Auto-mode stopped";
|
|
23
23
|
return displayReason ? `${prefix} — ${displayReason}` : prefix;
|
|
24
24
|
}
|
|
25
|
+
export function formatVerdictRecordedNotice(message) {
|
|
26
|
+
return `Verdict recorded: ${message}`;
|
|
27
|
+
}
|
|
28
|
+
export function formatVerdictRejectedNotice(message) {
|
|
29
|
+
return `Verdict rejected: ${message}`;
|
|
30
|
+
}
|
|
25
31
|
// ─── Classification (headless host side) ────────────────────────────────
|
|
26
32
|
// The canonical lowercase prefixes the headless event loop recognizes in
|
|
27
33
|
// notify messages. Emitters above and ad-hoc emitters elsewhere must start
|
|
@@ -33,6 +39,8 @@ export const TERMINAL_NOTICE_PREFIXES = [
|
|
|
33
39
|
"auto-mode complete",
|
|
34
40
|
"no active milestone",
|
|
35
41
|
"auto-mode idle",
|
|
42
|
+
"verdict recorded",
|
|
43
|
+
"verdict rejected",
|
|
36
44
|
];
|
|
37
45
|
/** Manual-resolution notices emitted before auto-mode can formally pause/stop. */
|
|
38
46
|
export function isManualResolutionNotice(message) {
|
|
@@ -65,6 +73,7 @@ export function isInteractiveMenuUnavailableNotice(message) {
|
|
|
65
73
|
}
|
|
66
74
|
export function isBlockedNoticeMessage(message) {
|
|
67
75
|
return (message.includes("blocked:") ||
|
|
76
|
+
message.startsWith("verdict rejected") ||
|
|
68
77
|
(isPauseNotice(message) && !isNonBlockingPauseNotice(message)) ||
|
|
69
78
|
isManualResolutionNotice(message) ||
|
|
70
79
|
isInteractiveMenuUnavailableNotice(message));
|
|
@@ -92,6 +92,14 @@ remote_questions:
|
|
|
92
92
|
uat_dispatch:
|
|
93
93
|
post_unit_hooks: []
|
|
94
94
|
pre_dispatch_hooks: []
|
|
95
|
+
# planning_subagent_registry:
|
|
96
|
+
# my-custom-planner:
|
|
97
|
+
# read_only_specialist: true
|
|
98
|
+
# planning_subagents:
|
|
99
|
+
# plan-milestone:
|
|
100
|
+
# allowed: [scout, planner, security]
|
|
101
|
+
# plan-slice:
|
|
102
|
+
# allowed: [scout, planner, reviewer, security]
|
|
95
103
|
# language:
|
|
96
104
|
# experimental:
|
|
97
105
|
# rtk: false
|