Skip to content

refactor(model-routing): centralize explicit foreground fallback policy#1

Closed
RaresKeY wants to merge 1 commit into
fix/strict-selected-modelfrom
refactor/explicit-foreground-fallback-policy
Closed

refactor(model-routing): centralize explicit foreground fallback policy#1
RaresKeY wants to merge 1 commit into
fix/strict-selected-modelfrom
refactor/explicit-foreground-fallback-policy

Conversation

@RaresKeY

Copy link
Copy Markdown
Owner

Summary

Foreground Chat, non-stream POST /api/chat, and every Agent round are strict unless the current user explicitly enables a new ordered fallback policy. When enabled, only documented availability failures may advance to an exact owner-visible endpoint/model candidate; request, authentication, authorization, unsupported-model, and configuration failures surface directly.

After a fallback produces substantive output or completes a tool call, Agent mode pins that route for the rest of the run. SSE events, per-round labels, saved history, terminal failures, token usage, and final metrics identify the route that actually answered. Failed candidate streams are closed before another route starts and on consumer cancellation.

The historical default_model_fallbacks value remains stored but has no runtime or UI connection and is never migrated into this policy. The retired silent endpoint-switch helper is removed.

Scope

In scope:

  • centralized per-user foreground_fallback_enabled and foreground_model_fallbacks policy;
  • streaming Chat, non-stream Chat, and Agent parity;
  • owner-scoped endpoint resolution and non-admin model allowlist enforcement before credentials resolve;
  • availability-only error classification;
  • multi-round route pinning and truthful provenance/accounting;
  • auth-transition isolation for flat, root ownerless, and named preferences;
  • confirmed-dead foreground routing path removal.

Out of scope:

Stack / target branch

Linked issue

Fixes odysseus-dev/odysseus#5626

Part of odysseus-dev/odysseus#5625

Type of change

Acceptance criteria covered

  • Disabled or absent policy calls only the selected route.
  • Empty explicit lists remain strict.
  • Eligible connection/read timeout, 429, and documented upstream status failures may advance.
  • Ineligible request/auth/config/model failures do not advance.
  • Named owners never inherit flat or ownerless consent across auth transitions.
  • Endpoint ownership and allowed-model checks precede credential resolution.
  • Agent fallback routes remain pinned across later tool rounds, including runtime skill activation.
  • Streaming/non-stream responses, saved history, terminal state, labels, and metrics report the actual route.
  • Candidate streams close before retry and on cancellation.
  • Legacy stored fallback data remains inert.

Validation

Focused exact-head run:

python -m pytest -q \
  tests/test_model_routes.py \
  tests/test_foreground_model_routing.py \
  tests/test_prefs_routes.py \
  tests/test_prefs_single_user_no_clobber.py \
  tests/test_llm_core_fallback.py

Result: 314 passed.

Additional exact-head checks:

  • changed Python files compile with python -m py_compile;
  • all six changed JavaScript modules pass node --check;
  • focused changed-surface review run: 487 passed;
  • independent correctness/architecture, security/owner-boundary, and adversarial failure-mode reviews found no verified P0–P3 findings at 0f0ff74f4f34121351998b066b4451124b3425e1.

Full isolated suite:

  • branch head: 4,854 passed, 12 failed, 5 skipped;
  • exact clean stack base: 4,670 passed, 12 failed, 5 skipped;
  • the 12 failing test names match exactly and are unrelated environment/baseline failures covering the missing example env file, URL joining, upload-recovery fixtures, and network-disabled web-fetch size-cap fixtures.

How to test manually

  1. With the policy absent/off, fail the selected Chat model and confirm no other endpoint is called.
  2. Enable an ordered owner-visible list, return an eligible availability failure, and confirm the next route answers with a visible fallback event and actual-route metrics.
  3. Repeat with 400/401/403/unsupported-model/configuration failures and confirm no fallback occurs.
  4. In Agent mode, let a fallback complete a tool call, then confirm every later round remains on that route and round labels/history stay accurate.
  5. Exercise POST /api/chat with the same strict, eligible, and ineligible cases.
  6. Toggle authentication around ownerless and named preference stores and confirm consent never transfers into a named owner.
  7. Delete an endpoint referenced by active root and named lists; confirm active references are removed while legacy default_model_fallbacks remains stored.

Validation gaps

No live-provider smoke or browser/screenshot validation was performed. The PR remains draft while those integration checks are pending.

@github-actions

Copy link
Copy Markdown

⚠️ PR description — action needed

The following required sections are missing or incomplete. Please update the PR description to address them:

  • Checklist — check the duplicate-search box to confirm you searched existing issues and PRs.

This comment is deleted automatically once all sections are complete.

Make foreground fallback an explicit per-user, availability-only policy shared by streaming Chat, non-stream Chat, and Agent runs.

Preserve strict defaults, owner/model and credential boundaries, pinned Agent routes, and truthful per-round provenance/accounting. Carry provider-reported model identifiers through native streaming adapters, non-stream responses, and caches, and keep legacy default_model_fallbacks as tombstoned raw storage that generic settings APIs and agent tools cannot expose or mutate.
@RaresKeY
RaresKeY force-pushed the refactor/explicit-foreground-fallback-policy branch from 12773e2 to 1d0e7cd Compare July 21, 2026 23:04
@RaresKeY

Copy link
Copy Markdown
Owner Author

Superseded by the canonical upstream draft PR odysseus-dev/odysseus#5683, which targets dev so canonical CI and repository templates apply. The source branch remains on this fork; no PR is needed here.

@RaresKeY RaresKeY closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant