feat: local-first LLM routing with reactive Opus escalation #198
Open
KofTwentyTwo wants to merge 10 commits from
feat/local-first-llm-routing into develop
pull from: feat/local-first-llm-routing
merge into: KofTwentyTwo:develop
KofTwentyTwo:develop
KofTwentyTwo:ci/secrets-historical-baseline
KofTwentyTwo:feature/security-findings-2026-10
KofTwentyTwo:dependabot/npm_and_yarn/webview/npm_and_yarn-3ac77625be
KofTwentyTwo:dependabot/npm_and_yarn/webview/packages/bus/npm_and_yarn-c86b58a346
KofTwentyTwo:dependabot/npm_and_yarn/webview/vitejs/plugin-react-6.0.2
KofTwentyTwo:dependabot/npm_and_yarn/webview/vite-8.0.13
KofTwentyTwo:dependabot/npm_and_yarn/webview/zustand-5.0.13
KofTwentyTwo:dependabot/npm_and_yarn/webview/types/node-25.9.1
KofTwentyTwo:dependabot/npm_and_yarn/webview/vitest-4.1.6
KofTwentyTwo:dependabot/github_actions/actions/setup-node-6
KofTwentyTwo:dependabot/github_actions/github/codeql-action-4
KofTwentyTwo:dependabot/github_actions/actions/checkout-6
KofTwentyTwo:dependabot/github_actions/actions/cache-5
KofTwentyTwo:dependabot/github_actions/pnpm/action-setup-6
KofTwentyTwo:docs/local-first-llm-routing-spec
KofTwentyTwo:fix/v0.2-wave-1-code-fixes
KofTwentyTwo:docs/v0.2-wave-1-doc-drift
KofTwentyTwo:docs/handoff-2026-05-14
KofTwentyTwo:docs/multi-runner-inventory
KofTwentyTwo:docs/ollama-baseline-58
KofTwentyTwo:fix/ci-env-harness-sqlite-voice-warmup
KofTwentyTwo:fix/ci-xcode-26-and-batcher-timing
KofTwentyTwo:chore/typecheck-blocking
KofTwentyTwo:fix/hud-typecheck-strict-undefined
KofTwentyTwo:wip/voice-log-menu-stash4
No Reviewers
Labels
Clear labels
area:agent
area:build
area:bus
area:devtool
area:hud
area:logging
area:mcp
area:memory
area:vision
area:voice
audit-finding
bug
carry-forward
comment-cleanup
dependencies
documentation
duplicate
enhancement
epic
good first issue
help wanted
invalid
javascript
migration
question
severity:critical
severity:high
severity:low
severity:medium
wontfix
Something isn't working
Comment / docstring cleanup per .planning/code-commenting-guide.md
Dependency updates
Improvements or additions to documentation
This issue or pull request already exists
New feature or request
Good for newcomers
Extra attention is needed
This doesn't seem right
Pull requests that update javascript code
Further information is requested
This will not be worked on
No labels
Milestone
No items
No Milestone
Projects
Clear projects
No projects
No Assignees
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: KofTwentyTwo/Jarvis#198
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Flips the default chat-turn provider from Anthropic to local Ollama (
qwen2.5-coder:32b-instruct-q8_0). If Ollama fails in any of six detectable ways, the orchestrator escalates the same turn to Claude Opus 4.7 and the HUD renders a small badge on the affected message.Implements the design spec in
docs/superpowers/specs/2026-05-14-local-first-llm-routing-design.md(PR #197) per the plan atdocs/superpowers/plans/2026-05-14-local-first-llm-routing.md. Executed via the Superpowers subagent-driven-development skill, 9 implementation tasks + 1 verification task, fresh subagent per task with two-stage review (spec compliance + code quality) after each.Behavior changes
default-config.jsonnow shipsprovider: "ollama"+escalationEnabled: true. Old configs auto-opt-in viadecodeIfPresent ?? true.Local-first (recommended)/Anthropic only/Ollama only.Detection — closed enum
OllamaFailureKindstreamTruncatedmalformedToolCalltool_calls.arguments; emitsproviderError(.malformedToolCall(reason:))on parse failureunknownToolrefusalStopReason.refusaleventconnectionFailureemptyResponsesawAnyTextDelta/sawAnyToolUseRequested; emits.emptyResponseif both false atdone:trueArchitecture notes
BusOutbound.escalatedcarries a Bus-localEscalationDecisionmirror (withBusProviderSelection,BusOllamaFailureKind), following the existingTurnRowprecedent. Translation happens inAppBusForwarderSink.escalatedThisTurnis a local var insiderunTurnLoop— resets naturally per turn, no cross-turn sticky state.streamTruncatedretry branch stays parallel to the new escalation path. DifferentLLMEventshapes (transport-mid-stream EOF vs. parsed-failure), independent budgets — they can co-occur and should not share a counter.MemoryExtractor; this PR doesn't modify it.Test plan
OllamaFailureKindTests: 6-caseallCasesround-trip + full struct equality (packages/AgentCore)PerTurnSnapshotEscalationTests: 3 tests — field round-trip,decodeIfPresentdefaulting, encode-decodefalsesurvives (packages/Config)test_default_config_resource_is_local_first— asserts shipped JSON is local-first (packages/Config)NDJSONDecoderTestsN8/N9 + 2 negative-suppression tests: malformed + empty detection (packages/AgentCore)LocalFirstEscalationTestsA/B/C: reactive fire-once, budget honored, disabled passthrough (packages/AgentCore)CodableRoundTripTests.test_roundTrip_escalated+ cross-side JSON fixture parity (packages/Bus+webview/packages/bus)BusForwarderTests: 2 escalation translation tests (packages/AgentCore)EscalationBadge.test.tsx: friendly text, testid, all 6 reasons render (webview/packages/hud)bus-dispatch.test.ts: in-flight stamp + pre-stream parked-decision attach (webview/packages/hud)ProviderModeTests: 3 mapping tests, including anthropic-true normalization (App/Tests)Non-goals
Stacked on
docs/local-first-llm-routing-spec). This PR can land independently; the spec PR adds the design doc + plan doc that explain this PR.🤖 Generated with Claude Code
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.