Skip to content

fix(core): preserve routing rejection explanations - #1

Open
robinbraemer wants to merge 2 commits into
mainfrom
fix/selection-explanations
Open

fix(core): preserve routing rejection explanations#1
robinbraemer wants to merge 2 commits into
mainfrom
fix/selection-explanations

Conversation

@robinbraemer

Copy link
Copy Markdown
Member

Intent

Make codex-router the reusable routing source of truth for AgentOS without losing observability. Preserve the router's already-computed per-account ineligibility explanations in its typed NoEligibleAccountsError so AgentOS can report exact quota, health, block, and reauthentication rejection reasons without duplicating selection policy. Keep the change bounded to the Effect-based core contract and tests, preserve current routing behavior, and deliver it as a merge-ready reviewed PR with full repository checks and CI.

What Changed

  • Preserve the complete per-account CandidateExplanation array in NoEligibleAccountsError for both no-eligible selection paths.
  • Document the reusable core contract and extend selection coverage for quota, health, block, freshness, reset, and reauthentication rejection reasons.

Risk Assessment

✅ Low: The change is narrowly scoped and correctly carries the computed candidate explanations through the typed core error without altering successful routing behavior.

Testing

The missing local dependency was restored, focused selection and routing tests were exercised, the typed-error test was expanded to cover all relevant rejection categories, and a reviewer-visible JSON artifact was captured. No actionable findings remain.

Evidence: Selection explanation payload

NoEligibleAccountsError preserved 7 exact per-account rejection reasons across reauthentication, block, usage, and quota cases.

{
  "_tag": "NoEligibleAccountsError",
  "message": "No account has safe quota and health data",
  "explanations": [
    {
      "accountId": "reauth",
      "eligible": false,
      "rejection": "reauthentication_required"
    },
    {
      "accountId": "blocked",
      "eligible": false,
      "rejection": "active_block"
    },
    {
      "accountId": "unknown",
      "eligible": false,
      "rejection": "usage_unknown"
    },
    {
      "accountId": "short-exhausted",
      "eligible": false,
      "rejection": "short_headroom"
    },
    {
      "accountId": "weekly-exhausted",
      "eligible": false,
      "rejection": "weekly_headroom"
    },
    {
      "accountId": "too-old",
      "eligible": false,
      "rejection": "usage_too_old"
    },
    {
      "accountId": "expired-reset",
      "eligible": false,
      "rejection": "weekly_reset_elapsed"
    }
  ]
}

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

✅ **Review** - passed

✅ No issues found.

✅ **Test** - passed

✅ No issues found.

  • bun install --frozen-lockfile
  • bun test packages/core/test/selection.test.ts
  • bun test packages/core/test/selection.test.ts packages/core/test/routing.test.ts
  • Manual core API invocation producing NoEligibleAccountsError JSON
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

@robinbraemer
robinbraemer force-pushed the fix/selection-explanations branch from a1d0206 to b6edce3 Compare July 30, 2026 15:43
@robinbraemer
robinbraemer force-pushed the fix/selection-explanations branch from b6edce3 to 3c26867 Compare July 30, 2026 19:43
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