Title: Specific-tier fallbacks are persisted but ignored by the proxy fallback path
Summary
Specific-tier fallback chains can be configured and persisted in specificity_assignments.fallback_models, but they are not used when a specificity-routed request fails upstream.
As a result, requests matched to a specific tier (for example coding or trading) use the specific tier's primary model, but fallback behavior is taken only from the general tier assignment in the proxy path.
Why this looks like a bug
The data model, service layer, controller, and UI all support specific-tier fallbacks:
specificity_assignments.fallback_models
SpecificityService.setFallbacks(...)
SpecificityController.setFallbacks(...)
- UI for adding fallbacks on specific tiers
But in the request path:
ResolveService.resolveSpecificity(...) returns the selected model/provider/auth/specificity category, but not the specific tier's fallback_models
ProxyService.proxyRequest(...) reads fallback models only from tierService.getTiers(...) using resolved.tier
That means specific-tier fallback chains are silently ignored.
Expected behavior
If a request matched a specific tier and that route fails with a fallback-triggering status, the proxy should use:
- the specific tier's
fallback_models, if present
- otherwise the general tier fallback list
Observed behavior
Only the general tier fallback list is considered.
Minimal reproduction
- Configure a specific tier such as
coding with:
- primary model A
- fallback model B
- Leave the general tier for the resolved scorer tier with no fallback, or with a different fallback list
- Send a request that matches the
coding specific tier
- Force primary model A to fail upstream with a fallback-triggering status (for example 429)
- Observe that the proxy does not use the specific-tier fallback chain
Root cause hypothesis
ResolveService.resolveSpecificity(...) should propagate assignment.fallback_models, and ProxyService.proxyRequest(...) should prefer those fallbacks when present.
Candidate fix areas
packages/backend/src/routing/resolve/resolve.service.ts
packages/backend/src/routing/proxy/proxy.service.ts
packages/backend/src/routing/dto/resolve-response.ts
Suggested fix
- extend
ResolveResponse with fallback_models?: string[] | null
- in
resolveSpecificity(...), include fallback_models: assignment.fallback_models ?? null
- in
proxyRequest(...), use:
const fallbackModels = resolved.fallback_models ?? assignment?.fallback_models;
Suggested regression coverage
resolve.service.spec.ts
- assert that specificity resolution propagates
fallback_models
proxy.service.spec.ts
- assert that when
resolveService.resolve(...) returns a specificity-routed response with fallback_models, those models are used even if the general tier fallback list is null
Notes
This report intentionally omits local environment details, tokens, hostnames, and user-specific configuration.
Title: Specific-tier fallbacks are persisted but ignored by the proxy fallback path
Summary
Specific-tier fallback chains can be configured and persisted in
specificity_assignments.fallback_models, but they are not used when a specificity-routed request fails upstream.As a result, requests matched to a specific tier (for example
codingortrading) use the specific tier's primary model, but fallback behavior is taken only from the general tier assignment in the proxy path.Why this looks like a bug
The data model, service layer, controller, and UI all support specific-tier fallbacks:
specificity_assignments.fallback_modelsSpecificityService.setFallbacks(...)SpecificityController.setFallbacks(...)But in the request path:
ResolveService.resolveSpecificity(...)returns the selected model/provider/auth/specificity category, but not the specific tier'sfallback_modelsProxyService.proxyRequest(...)reads fallback models only fromtierService.getTiers(...)usingresolved.tierThat means specific-tier fallback chains are silently ignored.
Expected behavior
If a request matched a specific tier and that route fails with a fallback-triggering status, the proxy should use:
fallback_models, if presentObserved behavior
Only the general tier fallback list is considered.
Minimal reproduction
codingwith:codingspecific tierRoot cause hypothesis
ResolveService.resolveSpecificity(...)should propagateassignment.fallback_models, andProxyService.proxyRequest(...)should prefer those fallbacks when present.Candidate fix areas
packages/backend/src/routing/resolve/resolve.service.tspackages/backend/src/routing/proxy/proxy.service.tspackages/backend/src/routing/dto/resolve-response.tsSuggested fix
ResolveResponsewithfallback_models?: string[] | nullresolveSpecificity(...), includefallback_models: assignment.fallback_models ?? nullproxyRequest(...), use:const fallbackModels = resolved.fallback_models ?? assignment?.fallback_models;Suggested regression coverage
resolve.service.spec.tsfallback_modelsproxy.service.spec.tsresolveService.resolve(...)returns a specificity-routed response withfallback_models, those models are used even if the general tier fallback list is nullNotes
This report intentionally omits local environment details, tokens, hostnames, and user-specific configuration.