Skip to content

feat(routing): fail over between policy candidates on retryable failures - #1281

Merged
Wibias merged 5 commits into
devfrom
feat/policy-candidate-fallback
Aug 8, 2026
Merged

feat(routing): fail over between policy candidates on retryable failures#1281
Wibias merged 5 commits into
devfrom
feat/policy-candidate-fallback

Conversation

@Wibias

@Wibias Wibias commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR adds policy-level fallback after the initially selected routing-profile candidate fails before useful output escapes.

Design constraints:

  • keep the initial policy decision trace immutable
  • record physical fallback attempts in the existing attempts[] history
  • retry only failures already classified as hop-worthy by the combo failure policy
  • never switch candidates for client cancellation or terminal invalid-request failures
  • choose the next eligible candidate deterministically by the original policy score, with original candidate order as the tie-break

TDD state

The first commit intentionally adds failing tests for the missing behavior. The implementation commit will follow after CI confirms the red state.

Scope

  • Responses execution wrapper for policy fallback
  • focused regression tests
  • no routing-profile schema changes
  • no combo behavior changes

Base inspected: dev at 3ad5bb6bd3f76f6879d84b78ea39edd3e01ec296.

Summary by CodeRabbit

  • New Features

    • Added automatic policy fallback for eligible requests after retryable pre-response failures.
    • Fallback tries suitable alternatives in ranked order while preserving the original request and policy context.
    • Retry attempts are recorded without replacing the original policy trace.
    • Fallback stops safely for terminal client errors, aborted requests, unreadable response details, or responses that have already started.
  • Tests

    • Added coverage for candidate ranking, retry behavior, request history, and fallback exclusions.

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4b23ed71-6199-40fb-b8cc-1949c794785e

📥 Commits

Reviewing files that changed from the base of the PR and between 457c336 and f8a683b.

📒 Files selected for processing (2)
  • src/server/responses/policy-fallback.ts
  • tests/routing-policy-fallback.test.ts

📝 Walkthrough

Walkthrough

The pull request adds Responses policy fallback handling. It ranks eligible policy candidates, retries retryable pre-success failures, preserves the original policy context, and avoids fallback after terminal errors, cancellation, or stream start. Tests cover these outcomes.

Changes

Policy fallback behavior

Layer / File(s) Summary
Fallback handling and candidate selection
src/server/responses/policy-fallback.ts
The fallback wrapper captures replayable JSON requests, validates policy traces, ranks eligible untried candidates, reconstructs retry requests, inspects errors, handles aborts, and restores the original route decision.
Responses facade integration
src/server/responses.ts, src/server/responses/policy-fallback.ts
The facade routes handleResponses through policy fallback and exports handleResponsesWithPolicyFallback and rankPolicyFallbackCandidates.
Fallback outcome coverage
tests/routing-policy-fallback.test.ts
Tests verify ranking, retryable 429 fallback, preserved request context, terminal 400 handling, cancellation handling, and suppression after stream start.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant handleResponses
  participant CoreHandler
  participant PolicyFallback
  Client->>handleResponses: Send replayable policy request
  handleResponses->>CoreHandler: Execute original request
  CoreHandler-->>PolicyFallback: Return retryable pre-success failure
  PolicyFallback->>PolicyFallback: Rank eligible untried candidates
  PolicyFallback->>CoreHandler: Retry with next candidate model
  CoreHandler-->>PolicyFallback: Return response
  PolicyFallback-->>Client: Return response with original policy context
Loading

Possibly related PRs

Suggested reviewers: ingwannu, lidge-jun

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: policy candidate failover on retryable failures.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/policy-candidate-fallback

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the enhancement New feature or request label Aug 8, 2026
@Wibias
Wibias marked this pull request as ready for review August 8, 2026 11:31

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/routing-policy-fallback.test.ts`:
- Around line 125-154: Expand the fallback regression coverage around
handleResponsesWithPolicyFallback with separate tests for client cancellation
and streaming failures after a non-empty output delta. In each case, simulate
the terminal condition through runCore and assert the response behavior plus
exactly one runCore invocation, preserving the no-candidate-switch behavior for
both guards.
- Around line 119-123: Extend the test around the existing response, seenModels,
and routeDecision assertions to validate logCtx.attempts. Assert two attempts in
order: provider-a/model-a with the defined candidate identity and a 429 failure,
followed by provider-b/model-b with the defined candidate identity and a
successful outcome, using the existing attempt-field names and preserving the
current fallback assertions.
🪄 Autofix

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 969e683c-3ac2-45ca-9d9d-c7703767e709

📥 Commits

Reviewing files that changed from the base of the PR and between 3ad5bb6 and 82afb71.

📒 Files selected for processing (1)
  • tests/routing-policy-fallback.test.ts

Comment thread tests/routing-policy-fallback.test.ts
Comment thread tests/routing-policy-fallback.test.ts
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

⚠️ Branch updated during autofix.

The branch was updated while autofix was in progress. Please try again.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/server/responses/policy-fallback.ts`:
- Around line 16-18: Update candidateKey and the tried initialization in the
fallback flow to include accountRef, so candidates sharing provider/model but
using different accounts remain distinct. In the retry logic around the fallback
execution path, preserve and explicitly pass the ranked candidate’s accountRef
(and corresponding codexAccountId when required) instead of re-routing only by
provider/model; verify core selection cannot replace the selected account.
🪄 Autofix

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 85dda22f-b5fb-4054-a5c3-809e537e3fbf

📥 Commits

Reviewing files that changed from the base of the PR and between 82afb71 and 457c336.

📒 Files selected for processing (2)
  • src/server/responses.ts
  • src/server/responses/policy-fallback.ts

Comment thread src/server/responses/policy-fallback.ts
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

⚠️ Branch updated during autofix.

The branch was updated while autofix was in progress. Please try again.

Wibias commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator Author

Review follow-up: the accountRef thread does not apply to live routing-profile fallback. OcxRoutingProfileConfig.candidates are provider/model targets; account choice remains inside the existing provider/account-pool layer and live policy traces do not create account-qualified policy candidates. Falling back via explicit provider/model is intentional here. The separate pool-evidence PR keeps that boundary rather than promoting account IDs into policy candidate identity.

@Wibias
Wibias merged commit 9efafaf into dev Aug 8, 2026
23 checks passed
@Wibias
Wibias deleted the feat/policy-candidate-fallback branch August 8, 2026 12:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant