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
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Storage layer for auto-learned project memories. Follows context-store.ts patterns.
|
|
4
4
|
// All functions degrade gracefully: return empty results when DB unavailable, never throw.
|
|
5
|
-
import { isDbAvailable, _getAdapter, transaction, insertMemoryRow, rewriteMemoryId, updateMemoryContentRow, incrementMemoryHitCount, supersedeMemoryRow, markMemoryUnitProcessed, decayMemoriesBefore, supersedeLowestRankedMemories, deleteMemoryEmbedding, deleteMemoryRelationsFor, } from './gsd-db.js';
|
|
5
|
+
import { isDbAvailable, _getAdapter, transaction, isInTransaction, insertMemoryRow, rewriteMemoryId, updateMemoryContentRow, incrementMemoryHitCount, supersedeMemoryRow, markMemoryUnitProcessed, decayMemoriesBefore, supersedeLowestRankedMemories, deleteMemoryEmbedding, deleteMemoryRelationsFor, } from './gsd-db.js';
|
|
6
6
|
import { createMemoryRelation, isValidRelation } from './memory-relations.js';
|
|
7
|
+
import { logWarning } from './workflow-logger.js';
|
|
7
8
|
// ─── Category Display Order ─────────────────────────────────────────────────
|
|
8
9
|
const CATEGORY_PRIORITY = {
|
|
9
10
|
gotcha: 0,
|
|
@@ -367,7 +368,13 @@ export function nextMemoryId() {
|
|
|
367
368
|
* Insert a new memory with a race-safe auto-assigned ID.
|
|
368
369
|
* Uses AUTOINCREMENT seq to derive the ID after insert, avoiding
|
|
369
370
|
* the read-then-write race in concurrent scenarios (e.g. worktrees).
|
|
370
|
-
* Returns the assigned ID, or null
|
|
371
|
+
* Returns the assigned ID, or null when the DB is unavailable.
|
|
372
|
+
*
|
|
373
|
+
* Throws on genuine SQL errors (corruption, missing tables, constraint
|
|
374
|
+
* violations) so callers can surface the underlying message instead of
|
|
375
|
+
* collapsing the failure to a generic "create_failed". See issue #4967 —
|
|
376
|
+
* the previous bare-catch swallowed "database disk image is malformed"
|
|
377
|
+
* errors, leaving the memory subsystem broken without any signal.
|
|
371
378
|
*/
|
|
372
379
|
export function createMemory(fields) {
|
|
373
380
|
if (!isDbAvailable())
|
|
@@ -376,35 +383,57 @@ export function createMemory(fields) {
|
|
|
376
383
|
if (!adapter)
|
|
377
384
|
return null;
|
|
378
385
|
try {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
return realId;
|
|
403
|
-
}
|
|
404
|
-
catch {
|
|
405
|
-
return null;
|
|
386
|
+
return transaction(() => doCreateMemory(adapter, fields));
|
|
387
|
+
}
|
|
388
|
+
catch (err) {
|
|
389
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
390
|
+
// Targeted recovery: a malformed memory store can sometimes be rebuilt
|
|
391
|
+
// by VACUUM. Skip when inside a transaction — SQLite refuses VACUUM
|
|
392
|
+
// there and a secondary throw would mask the real fault.
|
|
393
|
+
if (message.toLowerCase().includes('malformed') && !isInTransaction()) {
|
|
394
|
+
try {
|
|
395
|
+
adapter.prepare('VACUUM').run();
|
|
396
|
+
const recoveryMessage = 'recovered malformed memory store via VACUUM';
|
|
397
|
+
process.stderr.write(`memory-store: ${recoveryMessage}\n`);
|
|
398
|
+
logWarning('memory-store', recoveryMessage);
|
|
399
|
+
return transaction(() => doCreateMemory(adapter, fields));
|
|
400
|
+
}
|
|
401
|
+
catch (retryErr) {
|
|
402
|
+
const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
|
|
403
|
+
logWarning('memory-store', `VACUUM recovery for memory store failed: ${retryMsg}`);
|
|
404
|
+
// Surface the *original* malformed error — it's the actionable signal.
|
|
405
|
+
throw err;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
throw err;
|
|
406
409
|
}
|
|
407
410
|
}
|
|
411
|
+
function doCreateMemory(adapter, fields) {
|
|
412
|
+
const now = new Date().toISOString();
|
|
413
|
+
// Insert with a temporary placeholder ID — seq is auto-assigned
|
|
414
|
+
const placeholder = `_TMP_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
415
|
+
insertMemoryRow({
|
|
416
|
+
id: placeholder,
|
|
417
|
+
category: fields.category,
|
|
418
|
+
content: fields.content,
|
|
419
|
+
confidence: fields.confidence ?? 0.8,
|
|
420
|
+
sourceUnitType: fields.source_unit_type ?? null,
|
|
421
|
+
sourceUnitId: fields.source_unit_id ?? null,
|
|
422
|
+
createdAt: now,
|
|
423
|
+
updatedAt: now,
|
|
424
|
+
scope: fields.scope ?? 'project',
|
|
425
|
+
tags: fields.tags ?? [],
|
|
426
|
+
structuredFields: fields.structuredFields ?? null,
|
|
427
|
+
});
|
|
428
|
+
// Derive the real ID from the assigned seq (SELECT is still fine via adapter)
|
|
429
|
+
const row = adapter.prepare('SELECT seq FROM memories WHERE id = :id').get({ ':id': placeholder });
|
|
430
|
+
if (!row)
|
|
431
|
+
return placeholder; // fallback — should not happen
|
|
432
|
+
const seq = row['seq'];
|
|
433
|
+
const realId = `MEM${String(seq).padStart(3, '0')}`;
|
|
434
|
+
rewriteMemoryId(placeholder, realId);
|
|
435
|
+
return realId;
|
|
436
|
+
}
|
|
408
437
|
/**
|
|
409
438
|
* Update a memory's content and optionally its confidence.
|
|
410
439
|
*/
|
|
@@ -591,8 +620,14 @@ export function applyMemoryActions(actions, unitType, unitId) {
|
|
|
591
620
|
enforceMemoryCap();
|
|
592
621
|
});
|
|
593
622
|
}
|
|
594
|
-
catch {
|
|
595
|
-
//
|
|
623
|
+
catch (err) {
|
|
624
|
+
// Non-fatal — the transaction has rolled back. We log a warning so a
|
|
625
|
+
// degraded memory subsystem (e.g. malformed store, missing tables) is
|
|
626
|
+
// visible to forensics instead of silently dropping every CREATE — see
|
|
627
|
+
// issue #4967, where this swallow combined with createMemory's bare
|
|
628
|
+
// catch hid SQLite corruption from the auto-mode flow entirely.
|
|
629
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
630
|
+
logWarning('memory-store', `applyMemoryActions failed (memory subsystem degraded): ${message}`);
|
|
596
631
|
}
|
|
597
632
|
}
|
|
598
633
|
// ─── LINK action ────────────────────────────────────────────────────────────
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isDbAvailable, getAllMilestones } from "./gsd-db.js";
|
|
2
|
+
import { getReservedMilestoneIds, milestoneIdSort, nextMilestoneId, reserveMilestoneId, } from "./milestone-ids.js";
|
|
3
|
+
import { isReusableGhostMilestone } from "./state.js";
|
|
4
|
+
function getDatabaseMilestoneIds() {
|
|
5
|
+
if (!isDbAvailable())
|
|
6
|
+
return [];
|
|
7
|
+
return getAllMilestones().map((milestone) => milestone.id);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Generate the next milestone ID, accounting for DB rows and in-process
|
|
11
|
+
* reservations, and reserve it.
|
|
12
|
+
*/
|
|
13
|
+
export function nextMilestoneIdReserved(existingIds, uniqueEnabled, basePath) {
|
|
14
|
+
const reservedIds = getReservedMilestoneIds();
|
|
15
|
+
const allIds = [
|
|
16
|
+
...new Set([
|
|
17
|
+
...existingIds,
|
|
18
|
+
...reservedIds,
|
|
19
|
+
...getDatabaseMilestoneIds(),
|
|
20
|
+
]),
|
|
21
|
+
];
|
|
22
|
+
if (basePath) {
|
|
23
|
+
const sorted = [...allIds].sort(milestoneIdSort);
|
|
24
|
+
for (const candidate of sorted) {
|
|
25
|
+
if (reservedIds.has(candidate))
|
|
26
|
+
continue;
|
|
27
|
+
if (isReusableGhostMilestone(basePath, candidate)) {
|
|
28
|
+
reserveMilestoneId(candidate);
|
|
29
|
+
return candidate;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const id = nextMilestoneId(allIds, uniqueEnabled);
|
|
34
|
+
reserveMilestoneId(id);
|
|
35
|
+
return id;
|
|
36
|
+
}
|
|
@@ -228,11 +228,8 @@ export function getEligibleModels(tier, availableModelIds, routingConfig) {
|
|
|
228
228
|
if (availableModelIds.includes(explicitModel))
|
|
229
229
|
return [explicitModel];
|
|
230
230
|
// Provider-prefix-stripped match
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
const bareExplicit = explicitModel.includes("/") ? explicitModel.split("/").pop() : explicitModel;
|
|
234
|
-
return bareAvail === bareExplicit;
|
|
235
|
-
});
|
|
231
|
+
const bareExplicit = bareModelId(explicitModel);
|
|
232
|
+
const match = availableModelIds.find(id => bareModelId(id) === bareExplicit);
|
|
236
233
|
if (match)
|
|
237
234
|
return [match];
|
|
238
235
|
}
|
|
@@ -323,12 +320,31 @@ export function resolveModelForComplexity(classification, phaseConfig, routingCo
|
|
|
323
320
|
}
|
|
324
321
|
// Downgrade-only: if requested tier >= configured tier, no change
|
|
325
322
|
if (tierOrdinal(requestedTier) >= tierOrdinal(configuredTier)) {
|
|
323
|
+
// If the configured primary is directly available, use it
|
|
324
|
+
if (isModelAvailable(configuredPrimary, availableModelIds)) {
|
|
325
|
+
return {
|
|
326
|
+
modelId: configuredPrimary,
|
|
327
|
+
fallbacks: phaseConfig.fallbacks,
|
|
328
|
+
tier: requestedTier,
|
|
329
|
+
wasDowngraded: false,
|
|
330
|
+
reason: `tier ${requestedTier} >= configured ${configuredTier}`,
|
|
331
|
+
selectionMethod: "tier-only",
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
// Configured primary is unavailable (e.g. Anthropic model configured but
|
|
335
|
+
// running on a non-Anthropic provider). Find the best available model at
|
|
336
|
+
// the same capability tier so routing still works cross-provider.
|
|
337
|
+
const crossProviderEquivalent = findModelForTier(configuredTier, routingConfig, availableModelIds, routingConfig.cross_provider !== false);
|
|
326
338
|
return {
|
|
327
|
-
modelId: configuredPrimary,
|
|
328
|
-
fallbacks:
|
|
339
|
+
modelId: crossProviderEquivalent ?? configuredPrimary,
|
|
340
|
+
fallbacks: crossProviderEquivalent
|
|
341
|
+
? [...phaseConfig.fallbacks.filter(f => f !== crossProviderEquivalent), configuredPrimary]
|
|
342
|
+
: phaseConfig.fallbacks,
|
|
329
343
|
tier: requestedTier,
|
|
330
344
|
wasDowngraded: false,
|
|
331
|
-
reason:
|
|
345
|
+
reason: crossProviderEquivalent
|
|
346
|
+
? `cross-provider ${configuredTier}-tier equivalent`
|
|
347
|
+
: `tier ${requestedTier} >= configured ${configuredTier}`,
|
|
332
348
|
selectionMethod: "tier-only",
|
|
333
349
|
};
|
|
334
350
|
}
|
|
@@ -404,7 +420,84 @@ export function defaultRoutingConfig() {
|
|
|
404
420
|
hooks: true,
|
|
405
421
|
};
|
|
406
422
|
}
|
|
423
|
+
// ─── Tier-Based Model Resolution (for profile defaults) ─────────────────────
|
|
424
|
+
/**
|
|
425
|
+
* Fallback-only canonical model IDs per tier. Returned when the
|
|
426
|
+
* available-model list is empty (e.g., preferences are loaded before the
|
|
427
|
+
* model registry is populated at bootstrap), or when a non-empty registry has
|
|
428
|
+
* no model at the requested tier.
|
|
429
|
+
*
|
|
430
|
+
* Precedence (resolveModelForTier):
|
|
431
|
+
* 1. configured `tier_models[tier]` (via getEligibleModels) — exact/bare match
|
|
432
|
+
* 2. cheapest available model whose tier matches `tier`
|
|
433
|
+
* 3. CANONICAL_TIER_MODELS[tier] as last-resort fallback
|
|
434
|
+
*/
|
|
435
|
+
const CANONICAL_TIER_MODELS = {
|
|
436
|
+
light: "claude-haiku-4-5",
|
|
437
|
+
standard: "claude-sonnet-4-6",
|
|
438
|
+
heavy: "claude-opus-4-6",
|
|
439
|
+
};
|
|
440
|
+
export function canonicalModelForTier(tier) {
|
|
441
|
+
return CANONICAL_TIER_MODELS[tier];
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Single source of truth for tier-based model selection.
|
|
445
|
+
* Returns the cheapest available model whose capability tier matches `tier`,
|
|
446
|
+
* honoring `routingConfig.tier_models[tier]` when set. Returns undefined when
|
|
447
|
+
* no available model matches the tier.
|
|
448
|
+
*
|
|
449
|
+
* `crossProvider`: when false, restricts the search to models that share the
|
|
450
|
+
* canonical (Anthropic) provider for the tier. When true, any provider is
|
|
451
|
+
* eligible.
|
|
452
|
+
*/
|
|
453
|
+
function findModelForTier(tier, routingConfig, availableModelIds, crossProvider) {
|
|
454
|
+
const eligible = getEligibleModels(tier, availableModelIds, routingConfig);
|
|
455
|
+
if (eligible.length === 0)
|
|
456
|
+
return undefined;
|
|
457
|
+
if (crossProvider) {
|
|
458
|
+
return eligible[0];
|
|
459
|
+
}
|
|
460
|
+
// Same-provider only: keep models whose bare ID matches a canonical
|
|
461
|
+
// Anthropic ID at this tier (i.e., a claude-* model in the tier map).
|
|
462
|
+
const sameProvider = eligible.filter(id => {
|
|
463
|
+
const bare = bareModelId(id);
|
|
464
|
+
return MODEL_CAPABILITY_TIER[bare] === tier && bare.startsWith("claude-");
|
|
465
|
+
});
|
|
466
|
+
return sameProvider[0];
|
|
467
|
+
}
|
|
468
|
+
export function resolveModelForTier(tier, availableModelIds, routingConfigOrCrossProvider = defaultRoutingConfig(), crossProvider) {
|
|
469
|
+
const routingConfig = typeof routingConfigOrCrossProvider === "boolean"
|
|
470
|
+
? defaultRoutingConfig()
|
|
471
|
+
: { ...defaultRoutingConfig(), ...routingConfigOrCrossProvider };
|
|
472
|
+
const allowCrossProvider = typeof routingConfigOrCrossProvider === "boolean"
|
|
473
|
+
? routingConfigOrCrossProvider
|
|
474
|
+
: crossProvider ?? routingConfig.cross_provider !== false;
|
|
475
|
+
// No available models known — return canonical fallback
|
|
476
|
+
if (availableModelIds.length === 0) {
|
|
477
|
+
return canonicalModelForTier(tier);
|
|
478
|
+
}
|
|
479
|
+
// Cross-provider tier search
|
|
480
|
+
const resolved = findModelForTier(tier, routingConfig, availableModelIds, allowCrossProvider);
|
|
481
|
+
return resolved
|
|
482
|
+
? normalizeResolvedTierModelId(resolved, tier, routingConfig)
|
|
483
|
+
: canonicalModelForTier(tier);
|
|
484
|
+
}
|
|
407
485
|
// ─── Internal ────────────────────────────────────────────────────────────────
|
|
486
|
+
/**
|
|
487
|
+
* Check whether a model ID is present in the available models list.
|
|
488
|
+
* Handles bare IDs ("claude-opus-4-6") and provider-prefixed IDs ("anthropic/claude-opus-4-6").
|
|
489
|
+
*/
|
|
490
|
+
function isModelAvailable(modelId, availableModelIds) {
|
|
491
|
+
if (availableModelIds.includes(modelId))
|
|
492
|
+
return true;
|
|
493
|
+
// Strip provider prefix for comparison. Treat trailing-slash IDs ("provider/")
|
|
494
|
+
// as no-bare-ID rather than empty-string match (which would erroneously match
|
|
495
|
+
// any other "provider/" ID).
|
|
496
|
+
const bare = bareModelId(modelId);
|
|
497
|
+
if (!bare)
|
|
498
|
+
return false;
|
|
499
|
+
return availableModelIds.some(id => bareModelId(id) === bare);
|
|
500
|
+
}
|
|
408
501
|
function getModelTier(modelId) {
|
|
409
502
|
// Strip provider prefix if present
|
|
410
503
|
const bareId = bareModelId(modelId);
|
|
@@ -443,8 +536,20 @@ function getModelCost(modelId) {
|
|
|
443
536
|
// Unknown cost — assume expensive to avoid routing to unknown cheap models
|
|
444
537
|
return 999;
|
|
445
538
|
}
|
|
539
|
+
function normalizeResolvedTierModelId(modelId, tier, routingConfig) {
|
|
540
|
+
const explicitModel = routingConfig.tier_models?.[tier];
|
|
541
|
+
if (explicitModel?.includes("/")) {
|
|
542
|
+
return modelId;
|
|
543
|
+
}
|
|
544
|
+
const bareId = bareModelId(modelId);
|
|
545
|
+
return MODEL_CAPABILITY_TIER[bareId] ? bareId : modelId;
|
|
546
|
+
}
|
|
446
547
|
function bareModelId(modelId) {
|
|
447
|
-
|
|
548
|
+
if (!modelId.includes("/"))
|
|
549
|
+
return modelId;
|
|
550
|
+
// .pop() never returns undefined on a non-empty string but ?? guards future
|
|
551
|
+
// refactors and avoids the misleading non-null assertion.
|
|
552
|
+
return modelId.split("/").pop() ?? modelId;
|
|
448
553
|
}
|
|
449
554
|
// ─── Provider-specific Tool Limits ─────────────────────────────────────────
|
|
450
555
|
/**
|
|
@@ -10,6 +10,7 @@ import { join } from "node:path";
|
|
|
10
10
|
import { GSDError, GSD_GIT_ERROR } from "./errors.js";
|
|
11
11
|
import { GIT_NO_PROMPT_ENV } from "./git-constants.js";
|
|
12
12
|
import { getErrorMessage } from "./error-utils.js";
|
|
13
|
+
import { isInfrastructureError } from "./auto/infra-errors.js";
|
|
13
14
|
// Issue #453: keep auto-mode bookkeeping on the stable git CLI path unless a
|
|
14
15
|
// caller explicitly opts into the native helper.
|
|
15
16
|
const NATIVE_GSD_GIT_ENABLED = process.env.GSD_ENABLE_NATIVE_GSD_GIT === "1";
|
|
@@ -695,6 +696,10 @@ export function nativeAddAllWithExclusions(basePath, exclusions) {
|
|
|
695
696
|
}
|
|
696
697
|
catch (err) {
|
|
697
698
|
const stderr = err?.stderr ?? "";
|
|
699
|
+
const infraCode = isInfrastructureError(err) ?? isInfrastructureError(stderr);
|
|
700
|
+
if (infraCode) {
|
|
701
|
+
throw err;
|
|
702
|
+
}
|
|
698
703
|
// git exits 1 when pathspec exclusions reference paths already covered
|
|
699
704
|
// by .gitignore. The staging itself succeeds — only suppress that case.
|
|
700
705
|
if (stderr.includes("ignored by one of your .gitignore files")) {
|
|
@@ -709,7 +714,8 @@ export function nativeAddAllWithExclusions(basePath, exclusions) {
|
|
|
709
714
|
fallbackStageWithSymlinkedDotGsd(basePath);
|
|
710
715
|
return;
|
|
711
716
|
}
|
|
712
|
-
|
|
717
|
+
const stderrDetail = stderr.trim() ? `; stderr: ${stderr.trim()}` : "";
|
|
718
|
+
throw new GSDError(GSD_GIT_ERROR, `git add -A with exclusions failed in ${basePath}: ${getErrorMessage(err)}${stderrDetail}`);
|
|
713
719
|
}
|
|
714
720
|
}
|
|
715
721
|
/**
|
|
@@ -8,7 +8,7 @@
|
|
|
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 { defaultRoutingConfig } from "./model-router.js";
|
|
11
|
+
import { canonicalModelForTier, defaultRoutingConfig, resolveModelForTier } from "./model-router.js";
|
|
12
12
|
import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
|
|
13
13
|
/**
|
|
14
14
|
* Resolve which model ID to use for a given auto-mode unit type.
|
|
@@ -27,7 +27,7 @@ export function resolveModelForUnit(unitType) {
|
|
|
27
27
|
* - Extended: `planning: { model: claude-opus-4-6, fallbacks: [glm-5, minimax-m2.5] }`
|
|
28
28
|
*/
|
|
29
29
|
export function resolveModelWithFallbacksForUnit(unitType) {
|
|
30
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
30
|
+
const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
|
|
31
31
|
if (!prefs?.preferences.models)
|
|
32
32
|
return undefined;
|
|
33
33
|
const m = prefs.preferences.models;
|
|
@@ -110,7 +110,7 @@ export function resolveModelWithFallbacksForUnit(unitType) {
|
|
|
110
110
|
* configured.
|
|
111
111
|
*/
|
|
112
112
|
export function resolveDefaultSessionModel(sessionProvider) {
|
|
113
|
-
const prefs = loadEffectiveGSDPreferences();
|
|
113
|
+
const prefs = loadEffectiveGSDPreferences(undefined, { availableModelIds: [] });
|
|
114
114
|
if (!prefs?.preferences.models)
|
|
115
115
|
return undefined;
|
|
116
116
|
const m = prefs.preferences.models;
|
|
@@ -323,22 +323,80 @@ export function resolveAutoSupervisorConfig() {
|
|
|
323
323
|
}
|
|
324
324
|
// ─── Token Profile Resolution ─────────────────────────────────────────────
|
|
325
325
|
const VALID_TOKEN_PROFILES = new Set(["budget", "balanced", "quality", "burn-max"]);
|
|
326
|
+
/**
|
|
327
|
+
* Per-phase tier intentions for each token profile.
|
|
328
|
+
* Profiles express capability tiers, not model IDs. Concrete model
|
|
329
|
+
* resolution happens at runtime via resolveModelForTier() which is
|
|
330
|
+
* provider-agnostic — it picks the best available model at each tier.
|
|
331
|
+
*/
|
|
332
|
+
const PROFILE_TIER_MAP = {
|
|
333
|
+
budget: {
|
|
334
|
+
planning: "standard",
|
|
335
|
+
research: "light",
|
|
336
|
+
execution: "standard",
|
|
337
|
+
execution_simple: "light",
|
|
338
|
+
completion: "light",
|
|
339
|
+
subagent: "light",
|
|
340
|
+
},
|
|
341
|
+
balanced: {
|
|
342
|
+
planning: "standard",
|
|
343
|
+
research: "standard",
|
|
344
|
+
execution: "standard",
|
|
345
|
+
execution_simple: "light",
|
|
346
|
+
completion: "light",
|
|
347
|
+
subagent: "light",
|
|
348
|
+
},
|
|
349
|
+
quality: {
|
|
350
|
+
planning: "heavy",
|
|
351
|
+
research: "standard",
|
|
352
|
+
execution: "standard",
|
|
353
|
+
execution_simple: "light",
|
|
354
|
+
completion: "light",
|
|
355
|
+
subagent: "standard",
|
|
356
|
+
},
|
|
357
|
+
// burn-max intentionally omits a tier map: it never writes model defaults
|
|
358
|
+
// (it preserves the user's explicit model selection), so resolveProfileDefaults
|
|
359
|
+
// skips model resolution for this profile.
|
|
360
|
+
"burn-max": {},
|
|
361
|
+
};
|
|
326
362
|
/**
|
|
327
363
|
* Resolve profile defaults for a given token profile tier.
|
|
328
364
|
* Returns a partial GSDPreferences that is used as the base layer --
|
|
329
365
|
* explicit user preferences always override these defaults.
|
|
366
|
+
*
|
|
367
|
+
* Model IDs are resolved from capability tiers, not hardcoded to any
|
|
368
|
+
* provider. When available models are known (runtime), the resolver picks
|
|
369
|
+
* the best match across all configured providers. When not known (e.g.,
|
|
370
|
+
* early startup), falls back to canonical Anthropic model IDs.
|
|
371
|
+
*
|
|
372
|
+
* @param profile The token profile to resolve
|
|
373
|
+
* @param availableModelIds Optional list of available model IDs for cross-provider resolution.
|
|
374
|
+
* Undefined means the registry is unavailable.
|
|
375
|
+
* @param routingConfig Optional routing config for tier model pins.
|
|
330
376
|
*/
|
|
331
|
-
export function resolveProfileDefaults(profile) {
|
|
377
|
+
export function resolveProfileDefaults(profile, availableModelIds, routingConfig = defaultRoutingConfig()) {
|
|
378
|
+
// burn-max never writes model defaults — preserve user-selected models.
|
|
379
|
+
// For the other three profiles, derive concrete model IDs from the tier map
|
|
380
|
+
// against the available-model list when the registry is provided. If callers
|
|
381
|
+
// omit the registry entirely, use canonical fallbacks explicitly.
|
|
382
|
+
const tierMap = PROFILE_TIER_MAP[profile];
|
|
383
|
+
const resolveTierModel = (tier) => Array.isArray(availableModelIds)
|
|
384
|
+
? resolveModelForTier(tier, availableModelIds, routingConfig)
|
|
385
|
+
: canonicalModelForTier(tier);
|
|
386
|
+
const models = profile === "burn-max"
|
|
387
|
+
? undefined
|
|
388
|
+
: {
|
|
389
|
+
planning: resolveTierModel(tierMap.planning),
|
|
390
|
+
research: resolveTierModel(tierMap.research),
|
|
391
|
+
execution: resolveTierModel(tierMap.execution),
|
|
392
|
+
execution_simple: resolveTierModel(tierMap.execution_simple),
|
|
393
|
+
completion: resolveTierModel(tierMap.completion),
|
|
394
|
+
subagent: resolveTierModel(tierMap.subagent),
|
|
395
|
+
};
|
|
332
396
|
switch (profile) {
|
|
333
397
|
case "budget":
|
|
334
398
|
return {
|
|
335
|
-
models
|
|
336
|
-
planning: "claude-sonnet-4-5-20250514",
|
|
337
|
-
execution: "claude-sonnet-4-5-20250514",
|
|
338
|
-
execution_simple: "claude-haiku-4-5-20250414",
|
|
339
|
-
completion: "claude-haiku-4-5-20250414",
|
|
340
|
-
subagent: "claude-haiku-4-5-20250414",
|
|
341
|
-
},
|
|
399
|
+
models,
|
|
342
400
|
phases: {
|
|
343
401
|
skip_research: true,
|
|
344
402
|
skip_reassess: true,
|
|
@@ -348,9 +406,7 @@ export function resolveProfileDefaults(profile) {
|
|
|
348
406
|
};
|
|
349
407
|
case "balanced":
|
|
350
408
|
return {
|
|
351
|
-
models
|
|
352
|
-
subagent: "claude-sonnet-4-5-20250514",
|
|
353
|
-
},
|
|
409
|
+
models,
|
|
354
410
|
phases: {
|
|
355
411
|
skip_research: true,
|
|
356
412
|
skip_reassess: true,
|
|
@@ -359,7 +415,7 @@ export function resolveProfileDefaults(profile) {
|
|
|
359
415
|
};
|
|
360
416
|
case "quality":
|
|
361
417
|
return {
|
|
362
|
-
models
|
|
418
|
+
models,
|
|
363
419
|
phases: {
|
|
364
420
|
skip_research: true,
|
|
365
421
|
skip_slice_research: true,
|
|
@@ -384,6 +440,13 @@ export function resolveProfileDefaults(profile) {
|
|
|
384
440
|
};
|
|
385
441
|
}
|
|
386
442
|
}
|
|
443
|
+
/**
|
|
444
|
+
* Get the tier intentions for a profile without resolving to model IDs.
|
|
445
|
+
* Useful for display, debugging, and testing.
|
|
446
|
+
*/
|
|
447
|
+
export function getProfileTierMap(profile) {
|
|
448
|
+
return { ...PROFILE_TIER_MAP[profile] };
|
|
449
|
+
}
|
|
387
450
|
/**
|
|
388
451
|
* Resolve the effective token profile from preferences.
|
|
389
452
|
* Returns "balanced" when no profile is set (D046).
|
|
@@ -428,3 +491,16 @@ export function resolveSearchProviderFromPreferences() {
|
|
|
428
491
|
const prefs = loadEffectiveGSDPreferences();
|
|
429
492
|
return prefs?.preferences.search_provider;
|
|
430
493
|
}
|
|
494
|
+
/**
|
|
495
|
+
* Resolve provider IDs excluded from model selection/routing.
|
|
496
|
+
* Returns a normalized, de-duplicated list.
|
|
497
|
+
*/
|
|
498
|
+
export function resolveDisabledModelProvidersFromPreferences() {
|
|
499
|
+
const prefs = loadEffectiveGSDPreferences();
|
|
500
|
+
const raw = prefs?.preferences.disabled_model_providers;
|
|
501
|
+
if (!Array.isArray(raw))
|
|
502
|
+
return [];
|
|
503
|
+
return Array.from(new Set(raw
|
|
504
|
+
.map((provider) => provider.trim())
|
|
505
|
+
.filter((provider) => provider.length > 0)));
|
|
506
|
+
}
|
|
@@ -61,6 +61,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set([
|
|
|
61
61
|
"post_unit_hooks",
|
|
62
62
|
"pre_dispatch_hooks",
|
|
63
63
|
"dynamic_routing",
|
|
64
|
+
"disabled_model_providers",
|
|
64
65
|
"uok",
|
|
65
66
|
"token_profile",
|
|
66
67
|
"phases",
|
|
@@ -79,6 +80,7 @@ export const KNOWN_PREFERENCE_KEYS = new Set([
|
|
|
79
80
|
"service_tier",
|
|
80
81
|
"forensics_dedup",
|
|
81
82
|
"show_token_cost",
|
|
83
|
+
"min_request_interval_ms",
|
|
82
84
|
"stale_commit_threshold_minutes",
|
|
83
85
|
"context_management",
|
|
84
86
|
"experimental",
|
|
@@ -620,6 +620,26 @@ export function validatePreferences(preferences) {
|
|
|
620
620
|
errors.push("dynamic_routing must be an object");
|
|
621
621
|
}
|
|
622
622
|
}
|
|
623
|
+
// ─── Disabled Model Providers ───────────────────────────────────────
|
|
624
|
+
if (preferences.disabled_model_providers !== undefined) {
|
|
625
|
+
if (Array.isArray(preferences.disabled_model_providers)) {
|
|
626
|
+
const allStrings = preferences.disabled_model_providers.every((provider) => typeof provider === "string");
|
|
627
|
+
if (!allStrings) {
|
|
628
|
+
errors.push("disabled_model_providers must be an array of strings");
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
const normalized = preferences.disabled_model_providers
|
|
632
|
+
.map((provider) => provider.trim())
|
|
633
|
+
.filter((provider) => provider.length > 0);
|
|
634
|
+
if (normalized.length > 0) {
|
|
635
|
+
validated.disabled_model_providers = Array.from(new Set(normalized));
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
else {
|
|
640
|
+
errors.push("disabled_model_providers must be an array of strings");
|
|
641
|
+
}
|
|
642
|
+
}
|
|
623
643
|
// ─── Context Management ──────────────────────────────────────────────
|
|
624
644
|
if (preferences.context_management !== undefined) {
|
|
625
645
|
if (typeof preferences.context_management === "object" && preferences.context_management !== null) {
|
|
@@ -1153,6 +1173,18 @@ export function validatePreferences(preferences) {
|
|
|
1153
1173
|
errors.push("show_token_cost must be a boolean");
|
|
1154
1174
|
}
|
|
1155
1175
|
}
|
|
1176
|
+
// ─── Auto-Mode Request Interval ───────────────────────────────────
|
|
1177
|
+
if (preferences.min_request_interval_ms !== undefined) {
|
|
1178
|
+
if (typeof preferences.min_request_interval_ms === "number" &&
|
|
1179
|
+
Number.isFinite(preferences.min_request_interval_ms) &&
|
|
1180
|
+
preferences.min_request_interval_ms >= 0 &&
|
|
1181
|
+
preferences.min_request_interval_ms <= 2_147_483_647) {
|
|
1182
|
+
validated.min_request_interval_ms = Math.floor(preferences.min_request_interval_ms);
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
errors.push("min_request_interval_ms must be a non-negative number <= 2147483647");
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1156
1188
|
// ─── Experimental Features ────────────────────────────────────────
|
|
1157
1189
|
if (preferences.experimental !== undefined) {
|
|
1158
1190
|
if (typeof preferences.experimental === "object" && preferences.experimental !== null) {
|
|
@@ -35,7 +35,7 @@ export function resolveSkillStalenessDays(basePath) {
|
|
|
35
35
|
return prefs?.preferences.skill_staleness_days ?? 60;
|
|
36
36
|
}
|
|
37
37
|
// ─── Re-exports: models ─────────────────────────────────────────────────────
|
|
38
|
-
export { resolveModelForUnit, resolveModelWithFallbacksForUnit, getNextFallbackModel, isTransientNetworkError, validateModelId, updatePreferencesModels, resolveDynamicRoutingConfig, resolveAutoSupervisorConfig, resolveProfileDefaults, resolveEffectiveProfile, resolveInlineLevel, resolveContextSelection, resolveSearchProviderFromPreferences, } from "./preferences-models.js";
|
|
38
|
+
export { resolveModelForUnit, resolveModelWithFallbacksForUnit, getNextFallbackModel, isTransientNetworkError, validateModelId, updatePreferencesModels, resolveDynamicRoutingConfig, resolveAutoSupervisorConfig, resolveProfileDefaults, getProfileTierMap, resolveEffectiveProfile, resolveInlineLevel, resolveContextSelection, resolveSearchProviderFromPreferences, resolveDisabledModelProvidersFromPreferences, } from "./preferences-models.js";
|
|
39
39
|
// ─── Path Constants & Getters ───────────────────────────────────────────────
|
|
40
40
|
function gsdHome() {
|
|
41
41
|
return process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
@@ -76,7 +76,7 @@ export function loadProjectGSDPreferences(basePath) {
|
|
|
76
76
|
return loadPreferencesFile(projectPreferencesPath(basePath), "project")
|
|
77
77
|
?? loadPreferencesFile(legacyProjectPreferencesPathLowercase(basePath), "project");
|
|
78
78
|
}
|
|
79
|
-
export function loadEffectiveGSDPreferences(basePath) {
|
|
79
|
+
export function loadEffectiveGSDPreferences(basePath, opts) {
|
|
80
80
|
const globalPreferences = loadGlobalGSDPreferences();
|
|
81
81
|
const projectPreferences = loadProjectGSDPreferences(basePath);
|
|
82
82
|
if (!globalPreferences && !projectPreferences)
|
|
@@ -105,7 +105,7 @@ export function loadEffectiveGSDPreferences(basePath) {
|
|
|
105
105
|
// Explicit user preferences always override profile defaults.
|
|
106
106
|
const profile = result.preferences.token_profile;
|
|
107
107
|
if (profile) {
|
|
108
|
-
const profileDefaults = _resolveProfileDefaults(profile);
|
|
108
|
+
const profileDefaults = _resolveProfileDefaults(profile, opts?.availableModelIds, result.preferences.dynamic_routing);
|
|
109
109
|
result = {
|
|
110
110
|
...result,
|
|
111
111
|
preferences: mergePreferences(profileDefaults, result.preferences),
|
|
@@ -293,6 +293,7 @@ function mergePreferences(base, override) {
|
|
|
293
293
|
dynamic_routing: (base.dynamic_routing || override.dynamic_routing)
|
|
294
294
|
? { ...(base.dynamic_routing ?? {}), ...(override.dynamic_routing ?? {}) }
|
|
295
295
|
: undefined,
|
|
296
|
+
disabled_model_providers: mergeStringLists(base.disabled_model_providers, override.disabled_model_providers),
|
|
296
297
|
uok: (base.uok || override.uok)
|
|
297
298
|
? {
|
|
298
299
|
enabled: override.uok?.enabled ?? base.uok?.enabled,
|
|
@@ -346,6 +347,7 @@ function mergePreferences(base, override) {
|
|
|
346
347
|
service_tier: override.service_tier ?? base.service_tier,
|
|
347
348
|
forensics_dedup: override.forensics_dedup ?? base.forensics_dedup,
|
|
348
349
|
show_token_cost: override.show_token_cost ?? base.show_token_cost,
|
|
350
|
+
min_request_interval_ms: override.min_request_interval_ms ?? base.min_request_interval_ms,
|
|
349
351
|
codebase: (base.codebase || override.codebase)
|
|
350
352
|
? {
|
|
351
353
|
...(base.codebase ?? {}),
|