gsd-pi 2.78.0-dev.aeeb2ca00 → 2.78.1-dev.84a383f51
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 +7 -7
- package/dist/claude-cli-check.js +64 -37
- package/dist/cli-policy.d.ts +13 -0
- package/dist/cli-policy.js +17 -0
- package/dist/cli.js +95 -55
- package/dist/headless-query.d.ts +22 -0
- package/dist/headless-query.js +24 -4
- package/dist/headless.d.ts +10 -0
- package/dist/headless.js +16 -1
- package/dist/loader.js +7 -10
- package/dist/onboarding.d.ts +10 -0
- package/dist/onboarding.js +2 -2
- package/dist/provider-migrations.d.ts +2 -2
- package/dist/provider-migrations.js +5 -2
- package/dist/resource-loader.d.ts +5 -2
- package/dist/resource-loader.js +28 -5
- package/dist/resources/.managed-resources-content-hash +1 -0
- package/dist/resources/extensions/claude-code-cli/readiness.js +77 -45
- package/dist/resources/extensions/gsd/auto/loop.js +23 -0
- package/dist/resources/extensions/gsd/auto/phases.js +2 -2
- package/dist/resources/extensions/gsd/auto/run-unit.js +3 -1
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -4
- package/dist/resources/extensions/gsd/auto-runtime-state.js +31 -0
- package/dist/resources/extensions/gsd/auto-start.js +1 -1
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +30 -0
- package/dist/resources/extensions/gsd/auto.js +14 -5
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +14 -2
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -5
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +2 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +5 -4
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +94 -31
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +11 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +34 -8
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +38 -2
- package/dist/resources/extensions/gsd/commands/catalog.js +69 -5
- package/dist/resources/extensions/gsd/commands/handlers/core.js +22 -1
- package/dist/resources/extensions/gsd/commands-mcp-status.js +3 -1
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +10 -1
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +39 -1
- package/dist/resources/extensions/gsd/error-classifier.js +1 -1
- package/dist/resources/extensions/gsd/forensics.js +2 -2
- package/dist/resources/extensions/gsd/git-service.js +12 -5
- package/dist/resources/extensions/gsd/gsd-db.js +11 -2
- package/dist/resources/extensions/gsd/guided-flow.js +23 -23
- package/dist/resources/extensions/gsd/memory-store.js +66 -31
- package/dist/resources/extensions/gsd/milestone-id-reservation.js +36 -0
- package/dist/resources/extensions/gsd/model-router.js +114 -9
- package/dist/resources/extensions/gsd/native-git-bridge.js +7 -1
- package/dist/resources/extensions/gsd/preferences-models.js +91 -15
- package/dist/resources/extensions/gsd/preferences-types.js +2 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +32 -0
- package/dist/resources/extensions/gsd/preferences.js +5 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +23 -12
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +9 -3
- package/dist/resources/extensions/gsd/state.js +42 -0
- package/dist/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +18 -1
- package/dist/resources/extensions/gsd/visualizer-overlay.js +1 -1
- package/dist/resources/extensions/gsd/watch/header-renderer.js +3 -1
- package/dist/resources/extensions/gsd/worktree-command.js +26 -46
- package/dist/resources/extensions/gsd/worktree-session-state.js +33 -0
- package/dist/resources/extensions/mcp-client/index.js +6 -3
- package/dist/resources/extensions/slash-commands/create-extension.js +36 -22
- package/dist/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/dist/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/rtk-shared.d.ts +3 -0
- package/dist/rtk-shared.js +17 -0
- package/dist/rtk.d.ts +2 -5
- package/dist/rtk.js +3 -20
- package/dist/runtime-checks.d.ts +27 -0
- package/dist/runtime-checks.js +38 -0
- 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 +12 -12
- 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/react-loadable-manifest.json +44 -4
- 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_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 +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- 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 +1 -1
- 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/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +4 -2
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- 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 +2 -2
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- 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/server/webpack-runtime.js +1 -1
- package/dist/web/standalone/.next/static/chunks/2556.0527fea66e123b7f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/2824.08296bc2f9654698.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3026.3af53b279375f082.js +1 -0
- package/dist/web/standalone/.next/static/chunks/315.6f68ae79b67d25cf.js +1 -0
- package/dist/web/standalone/.next/static/chunks/3497.4bfc60a3b3dea717.js +1 -0
- package/dist/web/standalone/.next/static/chunks/5516.4a07c872b5c3a663.js +1 -0
- package/dist/web/standalone/.next/static/chunks/8336.31b019697882acfb.js +10 -0
- package/dist/web/standalone/.next/static/chunks/8845.c9702695e8c5a9c5.js +2 -0
- package/dist/web/standalone/.next/static/chunks/9058.01ef3a463bda88f1.js +20 -0
- package/dist/web/standalone/.next/static/chunks/9441.1081da1125d1764f.js +1 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-5b113fd32bc2a1c3.js → page-9bf2e0c50fb2ca05.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/webpack-f9f0dc45e4f3ac10.js +1 -0
- package/dist/web/standalone/package.json +2 -1
- package/dist/worktree-status-banner.d.ts +1 -0
- package/dist/worktree-status-banner.js +132 -0
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/alias-telemetry.d.ts +8 -0
- package/packages/mcp-server/dist/alias-telemetry.d.ts.map +1 -0
- package/packages/mcp-server/dist/alias-telemetry.js +30 -0
- package/packages/mcp-server/dist/alias-telemetry.js.map +1 -0
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +74 -46
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/alias-telemetry.test.ts +78 -0
- package/packages/mcp-server/src/alias-telemetry.ts +30 -0
- package/packages/mcp-server/src/workflow-tools.test.ts +26 -0
- package/packages/mcp-server/src/workflow-tools.ts +93 -58
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js +231 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.cache-breakpoint.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +48 -19
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +13 -0
- 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/dist/utils/repair-tool-json.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.js +24 -3
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +26 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/providers/anthropic-shared.cache-breakpoint.test.ts +289 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +52 -20
- package/packages/pi-ai/src/types.ts +13 -0
- package/packages/pi-ai/src/utils/repair-tool-json.ts +24 -3
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +32 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +6 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +4 -0
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +19 -2
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +18 -0
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +13 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +20 -16
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts +37 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js +49 -0
- package/packages/pi-coding-agent/dist/core/token-telemetry.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js +133 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +14 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js +78 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-cache-stability.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js +181 -0
- package/packages/pi-coding-agent/dist/tests/token-telemetry.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +7 -0
- package/packages/pi-coding-agent/src/core/messages.ts +4 -0
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +32 -2
- package/packages/pi-coding-agent/src/core/model-registry.ts +21 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +33 -15
- package/packages/pi-coding-agent/src/core/token-telemetry.ts +77 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +212 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +1 -1
- package/packages/pi-coding-agent/src/tests/system-prompt-cache-stability.test.ts +102 -0
- package/packages/pi-coding-agent/src/tests/token-telemetry.test.ts +200 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +17 -3
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts +2 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.d.ts.map +1 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js +161 -0
- package/packages/pi-tui/dist/components/__tests__/leak-fixes-runtime.test.js.map +1 -0
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +20 -3
- package/packages/pi-tui/src/components/__tests__/leak-fixes-runtime.test.ts +219 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +78 -46
- package/src/resources/extensions/gsd/auto/loop.ts +24 -2
- package/src/resources/extensions/gsd/auto/phases.ts +3 -3
- package/src/resources/extensions/gsd/auto/run-unit.ts +3 -1
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto/types.ts +1 -0
- package/src/resources/extensions/gsd/auto-recovery.ts +46 -8
- package/src/resources/extensions/gsd/auto-runtime-state.ts +51 -0
- package/src/resources/extensions/gsd/auto-start.ts +1 -1
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +2 -4
- package/src/resources/extensions/gsd/auto-worktree.ts +38 -0
- package/src/resources/extensions/gsd/auto.ts +14 -4
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +15 -13
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -7
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +2 -2
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +10 -9
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +102 -31
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +12 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +39 -8
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +39 -11
- package/src/resources/extensions/gsd/commands/catalog.ts +75 -5
- package/src/resources/extensions/gsd/commands/handlers/core.ts +22 -1
- package/src/resources/extensions/gsd/commands-mcp-status.ts +3 -1
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +15 -1
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/docs/preferences-reference.md +4 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +39 -1
- package/src/resources/extensions/gsd/doctor-types.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +1 -1
- package/src/resources/extensions/gsd/forensics.ts +2 -2
- package/src/resources/extensions/gsd/git-service.ts +13 -5
- package/src/resources/extensions/gsd/gsd-db.ts +12 -2
- package/src/resources/extensions/gsd/guided-flow.ts +25 -25
- package/src/resources/extensions/gsd/memory-store.ts +81 -28
- package/src/resources/extensions/gsd/milestone-id-reservation.ts +47 -0
- package/src/resources/extensions/gsd/model-router.ts +172 -9
- package/src/resources/extensions/gsd/native-git-bridge.ts +7 -1
- package/src/resources/extensions/gsd/preferences-models.ts +101 -15
- package/src/resources/extensions/gsd/preferences-types.ts +6 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +35 -0
- package/src/resources/extensions/gsd/preferences.ts +16 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +26 -12
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +9 -3
- package/src/resources/extensions/gsd/state.ts +42 -0
- package/src/resources/extensions/gsd/templates/PREFERENCES.md +1 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +178 -1
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/auto-session-encapsulation.test.ts +9 -5
- package/src/resources/extensions/gsd/tests/auto-supervisor.test.mjs +21 -4
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/budget-prediction.test.ts +138 -211
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +142 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +7 -4
- package/src/resources/extensions/gsd/tests/completed-at-reconcile.test.ts +89 -32
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +41 -23
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +3 -43
- package/src/resources/extensions/gsd/tests/debug-logger.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +22 -87
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +7 -118
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +18 -60
- package/src/resources/extensions/gsd/tests/doctor-orphan-milestone-4996.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +14 -76
- package/src/resources/extensions/gsd/tests/ensure-preconditions-guard-4996.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +22 -83
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +1 -63
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed-runtime.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/forensics-stuck-loops.test.ts +26 -1
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell-runtime.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/gsd-no-project-error-runtime.test.ts +81 -0
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +22 -12
- package/src/resources/extensions/gsd/tests/help-menu-coverage.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/import-done-milestones-runtime.test.ts +145 -0
- package/src/resources/extensions/gsd/tests/init-prefs-routing.test.ts +64 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/integration/token-savings.test.ts +0 -23
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +128 -0
- package/src/resources/extensions/gsd/tests/memory-tools.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/merge-self-branch-guard.test.ts +124 -0
- package/src/resources/extensions/gsd/tests/milestone-id-gap-reuse-4996.test.ts +152 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +169 -8
- package/src/resources/extensions/gsd/tests/native-git-infra-errors.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +32 -43
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +4 -10
- package/src/resources/extensions/gsd/tests/preferences.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +7 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/register-hooks-compaction-checkpoint.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +168 -19
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +23 -1
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +51 -4
- package/src/resources/extensions/gsd/tests/turn-epoch.test.ts +7 -16
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/uok-gitops-turn-action.test.ts +15 -1
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -6
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +15 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +17 -1
- package/src/resources/extensions/gsd/unit-context-manifest.ts +8 -8
- package/src/resources/extensions/gsd/visualizer-overlay.ts +1 -1
- package/src/resources/extensions/gsd/watch/header-renderer.ts +3 -1
- package/src/resources/extensions/gsd/workflow-logger.ts +1 -0
- package/src/resources/extensions/gsd/worktree-command.ts +31 -44
- package/src/resources/extensions/gsd/worktree-session-state.ts +35 -0
- package/src/resources/extensions/mcp-client/index.ts +6 -3
- package/src/resources/extensions/mcp-client/tests/global-config.test.ts +91 -0
- package/src/resources/extensions/slash-commands/create-extension.ts +38 -24
- package/src/resources/skills/create-gsd-extension/SKILL.md +9 -5
- package/src/resources/skills/create-gsd-extension/references/custom-commands.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +5 -5
- package/src/resources/skills/create-gsd-extension/references/custom-tools.md +4 -4
- package/src/resources/skills/create-gsd-extension/references/custom-ui.md +6 -6
- package/src/resources/skills/create-gsd-extension/references/events-reference.md +3 -3
- package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +1 -1
- package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +3 -3
- package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +2 -2
- package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +3 -3
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +58 -0
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +32 -12
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +0 -601
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +0 -651
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +0 -91
- package/dist/resources/extensions/gsd/tests/auto-supervisor.test.mjs +0 -53
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +0 -112
- package/dist/resources/extensions/gsd/tests/resolve-ts-hooks.mjs +0 -23
- package/dist/resources/extensions/gsd/tests/resolve-ts.mjs +0 -5
- package/dist/resources/skills/github-workflows/references/gh/tests/__init__.py +0 -0
- package/dist/resources/skills/github-workflows/references/gh/tests/test_github_project_setup.py +0 -608
- package/dist/web/standalone/.next/static/chunks/2826.e9f5195e91f9cad2.js +0 -11
- package/dist/web/standalone/.next/static/chunks/3621.fc7480022c972438.js +0 -20
- package/dist/web/standalone/.next/static/chunks/webpack-2e68521d7c82f7c2.js +0 -1
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +0 -22
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +0 -75
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{cAJH99yNS1UPbeSEiNRrV → UF5VF4F1tB0miEtJS7LyX}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { isDbAvailable, getAllMilestones } from "./gsd-db.js";
|
|
2
|
+
import {
|
|
3
|
+
getReservedMilestoneIds,
|
|
4
|
+
milestoneIdSort,
|
|
5
|
+
nextMilestoneId,
|
|
6
|
+
reserveMilestoneId,
|
|
7
|
+
} from "./milestone-ids.js";
|
|
8
|
+
import { isReusableGhostMilestone } from "./state.js";
|
|
9
|
+
|
|
10
|
+
function getDatabaseMilestoneIds(): string[] {
|
|
11
|
+
if (!isDbAvailable()) return [];
|
|
12
|
+
return getAllMilestones().map((milestone) => milestone.id);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Generate the next milestone ID, accounting for DB rows and in-process
|
|
17
|
+
* reservations, and reserve it.
|
|
18
|
+
*/
|
|
19
|
+
export function nextMilestoneIdReserved(
|
|
20
|
+
existingIds: string[],
|
|
21
|
+
uniqueEnabled: boolean,
|
|
22
|
+
basePath?: string,
|
|
23
|
+
): string {
|
|
24
|
+
const reservedIds = getReservedMilestoneIds();
|
|
25
|
+
const allIds = [
|
|
26
|
+
...new Set([
|
|
27
|
+
...existingIds,
|
|
28
|
+
...reservedIds,
|
|
29
|
+
...getDatabaseMilestoneIds(),
|
|
30
|
+
]),
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
if (basePath) {
|
|
34
|
+
const sorted = [...allIds].sort(milestoneIdSort);
|
|
35
|
+
for (const candidate of sorted) {
|
|
36
|
+
if (reservedIds.has(candidate)) continue;
|
|
37
|
+
if (isReusableGhostMilestone(basePath, candidate)) {
|
|
38
|
+
reserveMilestoneId(candidate);
|
|
39
|
+
return candidate;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const id = nextMilestoneId(allIds, uniqueEnabled);
|
|
45
|
+
reserveMilestoneId(id);
|
|
46
|
+
return id;
|
|
47
|
+
}
|
|
@@ -320,11 +320,8 @@ export function getEligibleModels(
|
|
|
320
320
|
// Exact match
|
|
321
321
|
if (availableModelIds.includes(explicitModel)) return [explicitModel];
|
|
322
322
|
// Provider-prefix-stripped match
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
const bareExplicit = explicitModel.includes("/") ? explicitModel.split("/").pop()! : explicitModel;
|
|
326
|
-
return bareAvail === bareExplicit;
|
|
327
|
-
});
|
|
323
|
+
const bareExplicit = bareModelId(explicitModel);
|
|
324
|
+
const match = availableModelIds.find(id => bareModelId(id) === bareExplicit);
|
|
328
325
|
if (match) return [match];
|
|
329
326
|
}
|
|
330
327
|
|
|
@@ -430,12 +427,38 @@ export function resolveModelForComplexity(
|
|
|
430
427
|
|
|
431
428
|
// Downgrade-only: if requested tier >= configured tier, no change
|
|
432
429
|
if (tierOrdinal(requestedTier) >= tierOrdinal(configuredTier)) {
|
|
430
|
+
// If the configured primary is directly available, use it
|
|
431
|
+
if (isModelAvailable(configuredPrimary, availableModelIds)) {
|
|
432
|
+
return {
|
|
433
|
+
modelId: configuredPrimary,
|
|
434
|
+
fallbacks: phaseConfig.fallbacks,
|
|
435
|
+
tier: requestedTier,
|
|
436
|
+
wasDowngraded: false,
|
|
437
|
+
reason: `tier ${requestedTier} >= configured ${configuredTier}`,
|
|
438
|
+
selectionMethod: "tier-only",
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Configured primary is unavailable (e.g. Anthropic model configured but
|
|
443
|
+
// running on a non-Anthropic provider). Find the best available model at
|
|
444
|
+
// the same capability tier so routing still works cross-provider.
|
|
445
|
+
const crossProviderEquivalent = findModelForTier(
|
|
446
|
+
configuredTier,
|
|
447
|
+
routingConfig,
|
|
448
|
+
availableModelIds,
|
|
449
|
+
routingConfig.cross_provider !== false,
|
|
450
|
+
);
|
|
451
|
+
|
|
433
452
|
return {
|
|
434
|
-
modelId: configuredPrimary,
|
|
435
|
-
fallbacks:
|
|
453
|
+
modelId: crossProviderEquivalent ?? configuredPrimary,
|
|
454
|
+
fallbacks: crossProviderEquivalent
|
|
455
|
+
? [...phaseConfig.fallbacks.filter(f => f !== crossProviderEquivalent), configuredPrimary]
|
|
456
|
+
: phaseConfig.fallbacks,
|
|
436
457
|
tier: requestedTier,
|
|
437
458
|
wasDowngraded: false,
|
|
438
|
-
reason:
|
|
459
|
+
reason: crossProviderEquivalent
|
|
460
|
+
? `cross-provider ${configuredTier}-tier equivalent`
|
|
461
|
+
: `tier ${requestedTier} >= configured ${configuredTier}`,
|
|
439
462
|
selectionMethod: "tier-only",
|
|
440
463
|
};
|
|
441
464
|
}
|
|
@@ -519,8 +542,131 @@ export function defaultRoutingConfig(): DynamicRoutingConfig {
|
|
|
519
542
|
};
|
|
520
543
|
}
|
|
521
544
|
|
|
545
|
+
// ─── Tier-Based Model Resolution (for profile defaults) ─────────────────────
|
|
546
|
+
|
|
547
|
+
/**
|
|
548
|
+
* Fallback-only canonical model IDs per tier. Returned when the
|
|
549
|
+
* available-model list is empty (e.g., preferences are loaded before the
|
|
550
|
+
* model registry is populated at bootstrap), or when a non-empty registry has
|
|
551
|
+
* no model at the requested tier.
|
|
552
|
+
*
|
|
553
|
+
* Precedence (resolveModelForTier):
|
|
554
|
+
* 1. configured `tier_models[tier]` (via getEligibleModels) — exact/bare match
|
|
555
|
+
* 2. cheapest available model whose tier matches `tier`
|
|
556
|
+
* 3. CANONICAL_TIER_MODELS[tier] as last-resort fallback
|
|
557
|
+
*/
|
|
558
|
+
const CANONICAL_TIER_MODELS: Record<ComplexityTier, string> = {
|
|
559
|
+
light: "claude-haiku-4-5",
|
|
560
|
+
standard: "claude-sonnet-4-6",
|
|
561
|
+
heavy: "claude-opus-4-6",
|
|
562
|
+
};
|
|
563
|
+
|
|
564
|
+
export function canonicalModelForTier(tier: ComplexityTier): string {
|
|
565
|
+
return CANONICAL_TIER_MODELS[tier];
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Single source of truth for tier-based model selection.
|
|
570
|
+
* Returns the cheapest available model whose capability tier matches `tier`,
|
|
571
|
+
* honoring `routingConfig.tier_models[tier]` when set. Returns undefined when
|
|
572
|
+
* no available model matches the tier.
|
|
573
|
+
*
|
|
574
|
+
* `crossProvider`: when false, restricts the search to models that share the
|
|
575
|
+
* canonical (Anthropic) provider for the tier. When true, any provider is
|
|
576
|
+
* eligible.
|
|
577
|
+
*/
|
|
578
|
+
function findModelForTier(
|
|
579
|
+
tier: ComplexityTier,
|
|
580
|
+
routingConfig: DynamicRoutingConfig,
|
|
581
|
+
availableModelIds: string[],
|
|
582
|
+
crossProvider: boolean,
|
|
583
|
+
): string | undefined {
|
|
584
|
+
const eligible = getEligibleModels(tier, availableModelIds, routingConfig);
|
|
585
|
+
if (eligible.length === 0) return undefined;
|
|
586
|
+
|
|
587
|
+
if (crossProvider) {
|
|
588
|
+
return eligible[0];
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
// Same-provider only: keep models whose bare ID matches a canonical
|
|
592
|
+
// Anthropic ID at this tier (i.e., a claude-* model in the tier map).
|
|
593
|
+
const sameProvider = eligible.filter(id => {
|
|
594
|
+
const bare = bareModelId(id);
|
|
595
|
+
return MODEL_CAPABILITY_TIER[bare] === tier && bare.startsWith("claude-");
|
|
596
|
+
});
|
|
597
|
+
return sameProvider[0];
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
/**
|
|
601
|
+
* Resolve a concrete model ID for a given capability tier using the
|
|
602
|
+
* available model list. Provider-agnostic: picks the best available
|
|
603
|
+
* model at the requested tier.
|
|
604
|
+
*
|
|
605
|
+
* Precedence:
|
|
606
|
+
* 1. configured `tier_models[tier]`, if provided and available
|
|
607
|
+
* 2. tier-matching model from any provider in `availableModelIds`
|
|
608
|
+
* 3. canonical Anthropic ID as a fallback only when nothing else matches
|
|
609
|
+
* (or `availableModelIds` is empty, e.g., during early bootstrap)
|
|
610
|
+
*
|
|
611
|
+
* @param tier The capability tier to resolve
|
|
612
|
+
* @param availableModelIds List of available model IDs (REQUIRED for
|
|
613
|
+
* provider-agnostic resolution; pass [] only when
|
|
614
|
+
* the model registry is genuinely unavailable)
|
|
615
|
+
* @param routingConfig Optional routing config, or legacy crossProvider boolean
|
|
616
|
+
* @param crossProvider Whether to consider models from other providers
|
|
617
|
+
*/
|
|
618
|
+
export function resolveModelForTier(
|
|
619
|
+
tier: ComplexityTier,
|
|
620
|
+
availableModelIds: string[],
|
|
621
|
+
crossProvider?: boolean,
|
|
622
|
+
): string;
|
|
623
|
+
export function resolveModelForTier(
|
|
624
|
+
tier: ComplexityTier,
|
|
625
|
+
availableModelIds: string[],
|
|
626
|
+
routingConfig?: DynamicRoutingConfig,
|
|
627
|
+
crossProvider?: boolean,
|
|
628
|
+
): string;
|
|
629
|
+
export function resolveModelForTier(
|
|
630
|
+
tier: ComplexityTier,
|
|
631
|
+
availableModelIds: string[],
|
|
632
|
+
routingConfigOrCrossProvider: DynamicRoutingConfig | boolean = defaultRoutingConfig(),
|
|
633
|
+
crossProvider?: boolean,
|
|
634
|
+
): string {
|
|
635
|
+
const routingConfig = typeof routingConfigOrCrossProvider === "boolean"
|
|
636
|
+
? defaultRoutingConfig()
|
|
637
|
+
: { ...defaultRoutingConfig(), ...routingConfigOrCrossProvider };
|
|
638
|
+
const allowCrossProvider = typeof routingConfigOrCrossProvider === "boolean"
|
|
639
|
+
? routingConfigOrCrossProvider
|
|
640
|
+
: crossProvider ?? routingConfig.cross_provider !== false;
|
|
641
|
+
|
|
642
|
+
// No available models known — return canonical fallback
|
|
643
|
+
if (availableModelIds.length === 0) {
|
|
644
|
+
return canonicalModelForTier(tier);
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
// Cross-provider tier search
|
|
648
|
+
const resolved = findModelForTier(tier, routingConfig, availableModelIds, allowCrossProvider);
|
|
649
|
+
return resolved
|
|
650
|
+
? normalizeResolvedTierModelId(resolved, tier, routingConfig)
|
|
651
|
+
: canonicalModelForTier(tier);
|
|
652
|
+
}
|
|
653
|
+
|
|
522
654
|
// ─── Internal ────────────────────────────────────────────────────────────────
|
|
523
655
|
|
|
656
|
+
/**
|
|
657
|
+
* Check whether a model ID is present in the available models list.
|
|
658
|
+
* Handles bare IDs ("claude-opus-4-6") and provider-prefixed IDs ("anthropic/claude-opus-4-6").
|
|
659
|
+
*/
|
|
660
|
+
function isModelAvailable(modelId: string, availableModelIds: string[]): boolean {
|
|
661
|
+
if (availableModelIds.includes(modelId)) return true;
|
|
662
|
+
// Strip provider prefix for comparison. Treat trailing-slash IDs ("provider/")
|
|
663
|
+
// as no-bare-ID rather than empty-string match (which would erroneously match
|
|
664
|
+
// any other "provider/" ID).
|
|
665
|
+
const bare = bareModelId(modelId);
|
|
666
|
+
if (!bare) return false;
|
|
667
|
+
return availableModelIds.some(id => bareModelId(id) === bare);
|
|
668
|
+
}
|
|
669
|
+
|
|
524
670
|
function getModelTier(modelId: string): ComplexityTier {
|
|
525
671
|
// Strip provider prefix if present
|
|
526
672
|
const bareId = bareModelId(modelId);
|
|
@@ -563,8 +709,25 @@ function getModelCost(modelId: string): number {
|
|
|
563
709
|
return 999;
|
|
564
710
|
}
|
|
565
711
|
|
|
712
|
+
function normalizeResolvedTierModelId(
|
|
713
|
+
modelId: string,
|
|
714
|
+
tier: ComplexityTier,
|
|
715
|
+
routingConfig: DynamicRoutingConfig,
|
|
716
|
+
): string {
|
|
717
|
+
const explicitModel = routingConfig.tier_models?.[tier];
|
|
718
|
+
if (explicitModel?.includes("/")) {
|
|
719
|
+
return modelId;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const bareId = bareModelId(modelId);
|
|
723
|
+
return MODEL_CAPABILITY_TIER[bareId] ? bareId : modelId;
|
|
724
|
+
}
|
|
725
|
+
|
|
566
726
|
function bareModelId(modelId: string): string {
|
|
567
|
-
|
|
727
|
+
if (!modelId.includes("/")) return modelId;
|
|
728
|
+
// .pop() never returns undefined on a non-empty string but ?? guards future
|
|
729
|
+
// refactors and avoids the misleading non-null assertion.
|
|
730
|
+
return modelId.split("/").pop() ?? modelId;
|
|
568
731
|
}
|
|
569
732
|
|
|
570
733
|
// ─── Provider-specific Tool Limits ─────────────────────────────────────────
|
|
@@ -11,6 +11,7 @@ import { join } from "node:path";
|
|
|
11
11
|
import { GSDError, GSD_GIT_ERROR } from "./errors.js";
|
|
12
12
|
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
13
13
|
import { getErrorMessage } from "./error-utils.js";
|
|
14
|
+
import { isInfrastructureError } from "./auto/infra-errors.js";
|
|
14
15
|
|
|
15
16
|
// Issue #453: keep auto-mode bookkeeping on the stable git CLI path unless a
|
|
16
17
|
// caller explicitly opts into the native helper.
|
|
@@ -846,6 +847,10 @@ export function nativeAddAllWithExclusions(basePath: string, exclusions: readonl
|
|
|
846
847
|
});
|
|
847
848
|
} catch (err: unknown) {
|
|
848
849
|
const stderr = (err as { stderr?: string })?.stderr ?? "";
|
|
850
|
+
const infraCode = isInfrastructureError(err) ?? isInfrastructureError(stderr);
|
|
851
|
+
if (infraCode) {
|
|
852
|
+
throw err;
|
|
853
|
+
}
|
|
849
854
|
// git exits 1 when pathspec exclusions reference paths already covered
|
|
850
855
|
// by .gitignore. The staging itself succeeds — only suppress that case.
|
|
851
856
|
if (stderr.includes("ignored by one of your .gitignore files")) {
|
|
@@ -860,7 +865,8 @@ export function nativeAddAllWithExclusions(basePath: string, exclusions: readonl
|
|
|
860
865
|
fallbackStageWithSymlinkedDotGsd(basePath);
|
|
861
866
|
return;
|
|
862
867
|
}
|
|
863
|
-
|
|
868
|
+
const stderrDetail = stderr.trim() ? `; stderr: ${stderr.trim()}` : "";
|
|
869
|
+
throw new GSDError(GSD_GIT_ERROR, `git add -A with exclusions failed in ${basePath}: ${getErrorMessage(err)}${stderrDetail}`);
|
|
864
870
|
}
|
|
865
871
|
}
|
|
866
872
|
|
|
@@ -10,7 +10,8 @@ import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
10
10
|
import { homedir } from "node:os";
|
|
11
11
|
import { join } from "node:path";
|
|
12
12
|
import type { DynamicRoutingConfig } from "./model-router.js";
|
|
13
|
-
import { defaultRoutingConfig } from "./model-router.js";
|
|
13
|
+
import { canonicalModelForTier, defaultRoutingConfig, resolveModelForTier } from "./model-router.js";
|
|
14
|
+
import type { ComplexityTier } from "./complexity-classifier.js";
|
|
14
15
|
import type { TokenProfile, InlineLevel } from "./types.js";
|
|
15
16
|
|
|
16
17
|
import type {
|
|
@@ -43,7 +44,7 @@ export function resolveModelForUnit(unitType: string): string | undefined {
|
|
|
43
44
|
* - Extended: `planning: { model: claude-opus-4-6, fallbacks: [glm-5, minimax-m2.5] }`
|
|
44
45
|
*/
|
|
45
46
|
export function resolveModelWithFallbacksForUnit(unitType: string): ResolvedModelConfig | undefined {
|
|
46
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
47
|
+
const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
|
|
47
48
|
if (!prefs?.preferences.models) return undefined;
|
|
48
49
|
const m = prefs.preferences.models as GSDModelConfigV2;
|
|
49
50
|
|
|
@@ -132,7 +133,7 @@ export function resolveModelWithFallbacksForUnit(unitType: string): ResolvedMode
|
|
|
132
133
|
export function resolveDefaultSessionModel(
|
|
133
134
|
sessionProvider?: string,
|
|
134
135
|
): { provider: string; id: string } | undefined {
|
|
135
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
136
|
+
const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
|
|
136
137
|
if (!prefs?.preferences.models) return undefined;
|
|
137
138
|
|
|
138
139
|
const m = prefs.preferences.models as GSDModelConfigV2;
|
|
@@ -358,22 +359,86 @@ export function resolveAutoSupervisorConfig(): AutoSupervisorConfig {
|
|
|
358
359
|
|
|
359
360
|
const VALID_TOKEN_PROFILES = new Set<TokenProfile>(["budget", "balanced", "quality", "burn-max"]);
|
|
360
361
|
|
|
362
|
+
/**
|
|
363
|
+
* Per-phase tier intentions for each token profile.
|
|
364
|
+
* Profiles express capability tiers, not model IDs. Concrete model
|
|
365
|
+
* resolution happens at runtime via resolveModelForTier() which is
|
|
366
|
+
* provider-agnostic — it picks the best available model at each tier.
|
|
367
|
+
*/
|
|
368
|
+
const PROFILE_TIER_MAP: Record<TokenProfile, Record<string, ComplexityTier>> = {
|
|
369
|
+
budget: {
|
|
370
|
+
planning: "standard",
|
|
371
|
+
research: "light",
|
|
372
|
+
execution: "standard",
|
|
373
|
+
execution_simple: "light",
|
|
374
|
+
completion: "light",
|
|
375
|
+
subagent: "light",
|
|
376
|
+
},
|
|
377
|
+
balanced: {
|
|
378
|
+
planning: "standard",
|
|
379
|
+
research: "standard",
|
|
380
|
+
execution: "standard",
|
|
381
|
+
execution_simple: "light",
|
|
382
|
+
completion: "light",
|
|
383
|
+
subagent: "light",
|
|
384
|
+
},
|
|
385
|
+
quality: {
|
|
386
|
+
planning: "heavy",
|
|
387
|
+
research: "standard",
|
|
388
|
+
execution: "standard",
|
|
389
|
+
execution_simple: "light",
|
|
390
|
+
completion: "light",
|
|
391
|
+
subagent: "standard",
|
|
392
|
+
},
|
|
393
|
+
// burn-max intentionally omits a tier map: it never writes model defaults
|
|
394
|
+
// (it preserves the user's explicit model selection), so resolveProfileDefaults
|
|
395
|
+
// skips model resolution for this profile.
|
|
396
|
+
"burn-max": {},
|
|
397
|
+
};
|
|
398
|
+
|
|
361
399
|
/**
|
|
362
400
|
* Resolve profile defaults for a given token profile tier.
|
|
363
401
|
* Returns a partial GSDPreferences that is used as the base layer --
|
|
364
402
|
* explicit user preferences always override these defaults.
|
|
403
|
+
*
|
|
404
|
+
* Model IDs are resolved from capability tiers, not hardcoded to any
|
|
405
|
+
* provider. When available models are known (runtime), the resolver picks
|
|
406
|
+
* the best match across all configured providers. When not known (e.g.,
|
|
407
|
+
* early startup), falls back to canonical Anthropic model IDs.
|
|
408
|
+
*
|
|
409
|
+
* @param profile The token profile to resolve
|
|
410
|
+
* @param availableModelIds Optional list of available model IDs for cross-provider resolution.
|
|
411
|
+
* Undefined means the registry is unavailable.
|
|
412
|
+
* @param routingConfig Optional routing config for tier model pins.
|
|
365
413
|
*/
|
|
366
|
-
export function resolveProfileDefaults(
|
|
414
|
+
export function resolveProfileDefaults(
|
|
415
|
+
profile: TokenProfile,
|
|
416
|
+
availableModelIds?: string[],
|
|
417
|
+
routingConfig: DynamicRoutingConfig = defaultRoutingConfig(),
|
|
418
|
+
): Partial<GSDPreferences> {
|
|
419
|
+
// burn-max never writes model defaults — preserve user-selected models.
|
|
420
|
+
// For the other three profiles, derive concrete model IDs from the tier map
|
|
421
|
+
// against the available-model list when the registry is provided. If callers
|
|
422
|
+
// omit the registry entirely, use canonical fallbacks explicitly.
|
|
423
|
+
const tierMap = PROFILE_TIER_MAP[profile];
|
|
424
|
+
const resolveTierModel = (tier: ComplexityTier): string => Array.isArray(availableModelIds)
|
|
425
|
+
? resolveModelForTier(tier, availableModelIds, routingConfig)
|
|
426
|
+
: canonicalModelForTier(tier);
|
|
427
|
+
const models: GSDModelConfigV2 | undefined = profile === "burn-max"
|
|
428
|
+
? undefined
|
|
429
|
+
: {
|
|
430
|
+
planning: resolveTierModel(tierMap.planning),
|
|
431
|
+
research: resolveTierModel(tierMap.research),
|
|
432
|
+
execution: resolveTierModel(tierMap.execution),
|
|
433
|
+
execution_simple: resolveTierModel(tierMap.execution_simple),
|
|
434
|
+
completion: resolveTierModel(tierMap.completion),
|
|
435
|
+
subagent: resolveTierModel(tierMap.subagent),
|
|
436
|
+
};
|
|
437
|
+
|
|
367
438
|
switch (profile) {
|
|
368
439
|
case "budget":
|
|
369
440
|
return {
|
|
370
|
-
models
|
|
371
|
-
planning: "claude-sonnet-4-5-20250514",
|
|
372
|
-
execution: "claude-sonnet-4-5-20250514",
|
|
373
|
-
execution_simple: "claude-haiku-4-5-20250414",
|
|
374
|
-
completion: "claude-haiku-4-5-20250414",
|
|
375
|
-
subagent: "claude-haiku-4-5-20250414",
|
|
376
|
-
},
|
|
441
|
+
models,
|
|
377
442
|
phases: {
|
|
378
443
|
skip_research: true,
|
|
379
444
|
skip_reassess: true,
|
|
@@ -383,9 +448,7 @@ export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPrefer
|
|
|
383
448
|
};
|
|
384
449
|
case "balanced":
|
|
385
450
|
return {
|
|
386
|
-
models
|
|
387
|
-
subagent: "claude-sonnet-4-5-20250514",
|
|
388
|
-
},
|
|
451
|
+
models,
|
|
389
452
|
phases: {
|
|
390
453
|
skip_research: true,
|
|
391
454
|
skip_reassess: true,
|
|
@@ -394,7 +457,7 @@ export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPrefer
|
|
|
394
457
|
};
|
|
395
458
|
case "quality":
|
|
396
459
|
return {
|
|
397
|
-
models
|
|
460
|
+
models,
|
|
398
461
|
phases: {
|
|
399
462
|
skip_research: true,
|
|
400
463
|
skip_slice_research: true,
|
|
@@ -420,6 +483,14 @@ export function resolveProfileDefaults(profile: TokenProfile): Partial<GSDPrefer
|
|
|
420
483
|
}
|
|
421
484
|
}
|
|
422
485
|
|
|
486
|
+
/**
|
|
487
|
+
* Get the tier intentions for a profile without resolving to model IDs.
|
|
488
|
+
* Useful for display, debugging, and testing.
|
|
489
|
+
*/
|
|
490
|
+
export function getProfileTierMap(profile: TokenProfile): Record<string, ComplexityTier> {
|
|
491
|
+
return { ...PROFILE_TIER_MAP[profile] };
|
|
492
|
+
}
|
|
493
|
+
|
|
423
494
|
/**
|
|
424
495
|
* Resolve the effective token profile from preferences.
|
|
425
496
|
* Returns "balanced" when no profile is set (D046).
|
|
@@ -465,3 +536,18 @@ export function resolveSearchProviderFromPreferences(): GSDPreferences["search_p
|
|
|
465
536
|
const prefs = loadEffectiveGSDPreferences();
|
|
466
537
|
return prefs?.preferences.search_provider;
|
|
467
538
|
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Resolve provider IDs excluded from model selection/routing.
|
|
542
|
+
* Returns a normalized, de-duplicated list.
|
|
543
|
+
*/
|
|
544
|
+
export function resolveDisabledModelProvidersFromPreferences(): string[] {
|
|
545
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
546
|
+
const raw = prefs?.preferences.disabled_model_providers;
|
|
547
|
+
if (!Array.isArray(raw)) return [];
|
|
548
|
+
return Array.from(new Set(
|
|
549
|
+
raw
|
|
550
|
+
.map((provider) => provider.trim())
|
|
551
|
+
.filter((provider) => provider.length > 0),
|
|
552
|
+
));
|
|
553
|
+
}
|
|
@@ -114,6 +114,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
114
114
|
"post_unit_hooks",
|
|
115
115
|
"pre_dispatch_hooks",
|
|
116
116
|
"dynamic_routing",
|
|
117
|
+
"disabled_model_providers",
|
|
117
118
|
"uok",
|
|
118
119
|
"token_profile",
|
|
119
120
|
"phases",
|
|
@@ -132,6 +133,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set<string>([
|
|
|
132
133
|
"service_tier",
|
|
133
134
|
"forensics_dedup",
|
|
134
135
|
"show_token_cost",
|
|
136
|
+
"min_request_interval_ms",
|
|
135
137
|
"stale_commit_threshold_minutes",
|
|
136
138
|
"context_management",
|
|
137
139
|
"experimental",
|
|
@@ -320,6 +322,8 @@ export interface GSDPreferences {
|
|
|
320
322
|
post_unit_hooks?: PostUnitHookConfig[];
|
|
321
323
|
pre_dispatch_hooks?: PreDispatchHookConfig[];
|
|
322
324
|
dynamic_routing?: DynamicRoutingConfig;
|
|
325
|
+
/** Provider IDs to exclude from /model and automatic model routing while leaving tool auth intact. */
|
|
326
|
+
disabled_model_providers?: string[];
|
|
323
327
|
/** Unified Orchestration Kernel controls (default-on, with opt-out and emergency legacy fallback). */
|
|
324
328
|
uok?: UokPreferences;
|
|
325
329
|
/** Per-model capability overrides. Deep-merged with built-in profiles for capability-aware routing (ADR-004). */
|
|
@@ -365,6 +369,8 @@ export interface GSDPreferences {
|
|
|
365
369
|
forensics_dedup?: boolean;
|
|
366
370
|
/** Opt-in: show per-prompt and cumulative session token cost in the footer. Default: false. */
|
|
367
371
|
show_token_cost?: boolean;
|
|
372
|
+
/** Proactive rate limiting: minimum milliseconds between auto-mode LLM requests. Prevents 429s on rate-limited providers. 0 = disabled (default). */
|
|
373
|
+
min_request_interval_ms?: number;
|
|
368
374
|
/**
|
|
369
375
|
* Minutes without a commit before flagging uncommitted changes as stale.
|
|
370
376
|
* When the threshold is exceeded and the working tree is dirty, doctor will
|
|
@@ -610,6 +610,27 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
610
610
|
}
|
|
611
611
|
}
|
|
612
612
|
|
|
613
|
+
// ─── Disabled Model Providers ───────────────────────────────────────
|
|
614
|
+
if (preferences.disabled_model_providers !== undefined) {
|
|
615
|
+
if (Array.isArray(preferences.disabled_model_providers)) {
|
|
616
|
+
const allStrings = preferences.disabled_model_providers.every(
|
|
617
|
+
(provider: unknown) => typeof provider === "string",
|
|
618
|
+
);
|
|
619
|
+
if (!allStrings) {
|
|
620
|
+
errors.push("disabled_model_providers must be an array of strings");
|
|
621
|
+
} else {
|
|
622
|
+
const normalized = preferences.disabled_model_providers
|
|
623
|
+
.map((provider) => provider.trim())
|
|
624
|
+
.filter((provider) => provider.length > 0);
|
|
625
|
+
if (normalized.length > 0) {
|
|
626
|
+
validated.disabled_model_providers = Array.from(new Set(normalized));
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
} else {
|
|
630
|
+
errors.push("disabled_model_providers must be an array of strings");
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
613
634
|
// ─── Context Management ──────────────────────────────────────────────
|
|
614
635
|
if (preferences.context_management !== undefined) {
|
|
615
636
|
if (typeof preferences.context_management === "object" && preferences.context_management !== null) {
|
|
@@ -1101,6 +1122,20 @@ export function validatePreferences(preferences: GSDPreferences): {
|
|
|
1101
1122
|
}
|
|
1102
1123
|
}
|
|
1103
1124
|
|
|
1125
|
+
// ─── Auto-Mode Request Interval ───────────────────────────────────
|
|
1126
|
+
if (preferences.min_request_interval_ms !== undefined) {
|
|
1127
|
+
if (
|
|
1128
|
+
typeof preferences.min_request_interval_ms === "number" &&
|
|
1129
|
+
Number.isFinite(preferences.min_request_interval_ms) &&
|
|
1130
|
+
preferences.min_request_interval_ms >= 0 &&
|
|
1131
|
+
preferences.min_request_interval_ms <= 2_147_483_647
|
|
1132
|
+
) {
|
|
1133
|
+
validated.min_request_interval_ms = Math.floor(preferences.min_request_interval_ms);
|
|
1134
|
+
} else {
|
|
1135
|
+
errors.push("min_request_interval_ms must be a non-negative number <= 2147483647");
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1104
1139
|
// ─── Experimental Features ────────────────────────────────────────
|
|
1105
1140
|
if (preferences.experimental !== undefined) {
|
|
1106
1141
|
if (typeof preferences.experimental === "object" && preferences.experimental !== null) {
|
|
@@ -89,10 +89,12 @@ export {
|
|
|
89
89
|
resolveDynamicRoutingConfig,
|
|
90
90
|
resolveAutoSupervisorConfig,
|
|
91
91
|
resolveProfileDefaults,
|
|
92
|
+
getProfileTierMap,
|
|
92
93
|
resolveEffectiveProfile,
|
|
93
94
|
resolveInlineLevel,
|
|
94
95
|
resolveContextSelection,
|
|
95
96
|
resolveSearchProviderFromPreferences,
|
|
97
|
+
resolveDisabledModelProvidersFromPreferences,
|
|
96
98
|
} from "./preferences-models.js";
|
|
97
99
|
|
|
98
100
|
// ─── Path Constants & Getters ───────────────────────────────────────────────
|
|
@@ -146,7 +148,10 @@ export function loadProjectGSDPreferences(basePath?: string): LoadedGSDPreferenc
|
|
|
146
148
|
?? loadPreferencesFile(legacyProjectPreferencesPathLowercase(basePath), "project");
|
|
147
149
|
}
|
|
148
150
|
|
|
149
|
-
export function loadEffectiveGSDPreferences(
|
|
151
|
+
export function loadEffectiveGSDPreferences(
|
|
152
|
+
basePath?: string,
|
|
153
|
+
opts?: { availableModelIds?: string[] },
|
|
154
|
+
): LoadedGSDPreferences | null {
|
|
150
155
|
const globalPreferences = loadGlobalGSDPreferences();
|
|
151
156
|
const projectPreferences = loadProjectGSDPreferences(basePath);
|
|
152
157
|
|
|
@@ -175,7 +180,11 @@ export function loadEffectiveGSDPreferences(basePath?: string): LoadedGSDPrefere
|
|
|
175
180
|
// Explicit user preferences always override profile defaults.
|
|
176
181
|
const profile = result.preferences.token_profile as TokenProfile | undefined;
|
|
177
182
|
if (profile) {
|
|
178
|
-
const profileDefaults = _resolveProfileDefaults(
|
|
183
|
+
const profileDefaults = _resolveProfileDefaults(
|
|
184
|
+
profile,
|
|
185
|
+
opts?.availableModelIds,
|
|
186
|
+
result.preferences.dynamic_routing,
|
|
187
|
+
);
|
|
179
188
|
result = {
|
|
180
189
|
...result,
|
|
181
190
|
preferences: mergePreferences(profileDefaults as GSDPreferences, result.preferences),
|
|
@@ -380,6 +389,10 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
|
|
|
380
389
|
dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
|
|
381
390
|
? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) } as DynamicRoutingConfig
|
|
382
391
|
: undefined,
|
|
392
|
+
disabled_model_providers: mergeStringLists(
|
|
393
|
+
base.disabled_model_providers,
|
|
394
|
+
override.disabled_model_providers,
|
|
395
|
+
),
|
|
383
396
|
uok: (base.uok || override.uok)
|
|
384
397
|
? {
|
|
385
398
|
enabled: override.uok?.enabled ?? base.uok?.enabled,
|
|
@@ -433,6 +446,7 @@ function mergePreferences(base: GSDPreferences, override: GSDPreferences): GSDPr
|
|
|
433
446
|
service_tier: override.service_tier ?? base.service_tier,
|
|
434
447
|
forensics_dedup: override.forensics_dedup ?? base.forensics_dedup,
|
|
435
448
|
show_token_cost: override.show_token_cost ?? base.show_token_cost,
|
|
449
|
+
min_request_interval_ms: override.min_request_interval_ms ?? base.min_request_interval_ms,
|
|
436
450
|
codebase: (base.codebase || override.codebase)
|
|
437
451
|
? {
|
|
438
452
|
...(base.codebase ?? {}),
|
|
@@ -7,14 +7,13 @@
|
|
|
7
7
|
* Templates live at prompts/ relative to this module's directory.
|
|
8
8
|
* They use {{variableName}} syntax for substitution.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* This
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* set A) can read a newer
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* that aren't read until the end of a long auto-mode run.
|
|
10
|
+
* Templates are snapshotted shortly after module init via warmCache().
|
|
11
|
+
* This keeps import/extension-registration fast while still preventing a
|
|
12
|
+
* running session from being invalidated when another `gsd` launch overwrites
|
|
13
|
+
* ~/.gsd/agent/ with newer templates via initResources(). Without caching, the
|
|
14
|
+
* in-memory extension code (which knows variable set A) can read a newer
|
|
15
|
+
* template from disk (which expects variable set B), causing a
|
|
16
|
+
* "template declares {{X}} but no value was provided" crash mid-session.
|
|
18
17
|
*/
|
|
19
18
|
|
|
20
19
|
import { readFileSync, readdirSync, existsSync } from "node:fs";
|
|
@@ -82,8 +81,8 @@ export function getTemplatesDir(): string {
|
|
|
82
81
|
return templatesDir;
|
|
83
82
|
}
|
|
84
83
|
|
|
85
|
-
// Cache all templates
|
|
86
|
-
// template versions that were on disk
|
|
84
|
+
// Cache all templates from a startup snapshot — a running session uses the
|
|
85
|
+
// template versions that were on disk near startup, immune to later overwrites.
|
|
87
86
|
const templateCache = new Map<string, string>();
|
|
88
87
|
|
|
89
88
|
/**
|
|
@@ -124,8 +123,23 @@ function warmCache(): void {
|
|
|
124
123
|
}
|
|
125
124
|
}
|
|
126
125
|
|
|
127
|
-
|
|
128
|
-
|
|
126
|
+
let warmCacheScheduled = false;
|
|
127
|
+
|
|
128
|
+
function scheduleWarmCache(): void {
|
|
129
|
+
if (warmCacheScheduled) return;
|
|
130
|
+
warmCacheScheduled = true;
|
|
131
|
+
|
|
132
|
+
const run = () => {
|
|
133
|
+
warmCache();
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const timer = setTimeout(run, 1000);
|
|
137
|
+
timer.unref?.();
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Snapshot the full prompt/template tree after import so extension startup only
|
|
141
|
+
// pays for prompts that are actually needed immediately.
|
|
142
|
+
scheduleWarmCache();
|
|
129
143
|
|
|
130
144
|
/**
|
|
131
145
|
* Load a prompt template and substitute variables.
|