diff --git a/.gitignore b/.gitignore
index bf8334f52..f4bc040e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,3 +18,4 @@ role-model-router/apps/runtime-ui/test-results/
/.recursive/config/recursive-router-discovered.json
# CI paired-checkout directory (checkout of try-works/role-model-internal nested by the track-b lane)
_private/
+/.recursive/run/106-client-neutral-model-effort-routing/qa-state-sea//
diff --git a/.recursive/DECISIONS.md b/.recursive/DECISIONS.md
index 1994d9f94..6fea84524 100644
--- a/.recursive/DECISIONS.md
+++ b/.recursive/DECISIONS.md
@@ -14,9 +14,51 @@
- `86-runtime-ui-rm3-design-system-frontend` - RM v3 design system + `@role-model/ui` kit migration for router runtime-ui; Paper `4-0`/`5-0`/`6-0`/`7-0` IA; FD#15 config→strategy; SP8 floor green; hybrid Phase 5 QA on rebuilt `:3470` with human Paper sign-off; operator polish P1–P8 (Phases 0-8). Folder: `.recursive/run/86-runtime-ui-rm3-design-system-frontend/`. Soft-closes run `60-runtime-ui-paper-linear-review-alignment` as live styling authority for migrated surfaces (Linear/Paper-Linear historical).
- `92-configured-model-pool-benchmark-convergence` - Endpoint-variant-exact membership revision token stamped at persist/read/portfolio/decision time; honest null candidate-space (no synthetic 0/0%); membership-revision + stale benchmark quarantine; destructive-confirm final-controller eject; decision revision; transactional benchmark clear (Phases 0-8, strict TDD, agent-operated QA on rebuilt `:3501`). Folder: `.recursive/run/92-configured-model-pool-benchmark-convergence/`. Soft-closes run 76's membership-authority contract with a revision-token convergence wave.
+- `106-client-neutral-model-effort-routing` - Client-neutral model-effort routing: reasoning effort becomes a first-class routing dimension (`strict`/`preferred`/`router` policy, executable model-endpoint-effort arms, effort-scoped evidence with borrowed/related priors, four-state effort-source vocabulary, canonical decision/telemetry/trace provenance, UI truthfulness, packaged SEA + real-Pi Phase 5 QA on `:3462`) (Phases 0-8). Folder: `.recursive/run/106-client-neutral-model-effort-routing/`.
- `103-agent-strategy-and-scoring-strategy` - Routing posture split (`routing.mode` + `routing.scoring_strategy` + `pin_weights` + `weights`), real scoring strategies, agent-strategy and workload postures with `.` aliases, strategy/latency/alias receipts on every decision, measured-latency effective metric, three runtime-ui surfaces; strict TDD, two delegated review rounds, agent-operated rebuilt-runtime pi-CLI QA on `:3458` (Phases 0-8). Folder: `.recursive/run/103-agent-strategy-and-scoring-strategy/`.
- `105-route-learning-matching-scope-activation` - Stage-3 matching-scope activation: per-(role,task) ranked endpoint ladder (aggregation, store, advisory walk, dispatch/activation/rollback, Packs UI) plus the Phase 3.5 classification-alignment repair (capture/advisory reads the authoritative taxonomy identity, not runtime-policy ids); strict TDD, delegated review + re-review, agent-operated rebuilt-runtime pi-CLI QA on `:3458` (Phases 0-8). Folder: `.recursive/run/105-route-learning-matching-scope-activation/`.
+## Run: `106-client-neutral-model-effort-routing`
+
+Date: `2026-10-04`
+
+### What changed
+
+- Reasoning effort becomes a first-class, client-neutral routing dimension: the normalized input separates `requested_effort` from `effort_policy` (`strict | preferred | router`); omitted effort -> router, legacy scalar -> preferred, explicit policy -> authoritative (R1).
+- The router selects over executable model-endpoint-effort arms (`expandReasoningEffortArms` + adapter execution mapping) rather than base endpoints (R2).
+- `strict` considers exact-effort arms only (else `reasoning_effort_unavailable`); `preferred` falls back through named hard-eligibility/provider-attempt receipts; `preferred` with zero exact arms records `unsupported_fallback` and performs router-managed selection (R3).
+- Four lossless effort states (`named | disabled | provider-default | no-client-preference`) are preserved through core types, serialization, SQLite, discovery, telemetry, trace, and UI; the occurrence boundary keeps a binary `effort_source` vocabulary while the decision keeps the four-state (R4, M-3 fix `9260a10b`).
+- Benchmark/operational evidence is keyed by the effort arm; cross-effort evidence acts only as a labeled, discounted prior (`resolveBorrowedQualityPrior` + `getQualityMetric` + `benchmark-summary` + `profile-aggregator`) (R5).
+- Arm-aware strategy/controller/cache/fallback (R6), turn-aware difficulty (R7), non-inferiority ranking (R8), arm-level discovery union/intersection (R9), and canonical decision/telemetry/trace/error provenance (R10).
+- UI truthfulness: model + effective effort + exact/borrowed evidence on operator surfaces (R11).
+- Packaged SEA (`role-model-dev.exe`, sha256 `e181c6011a50a7e9681d6f16314ae7cefcbe7ca26bb21eeac34343b3befc7364`) + real Pi CLI on `:3462` (requestId `req-9d68e76b`, decision `decision-req-9d68e76b` -> deepseek-v4-pro; strict+max -> v4-flash-max, router+max -> v4-flash) (R12/R15).
+- Strict TDD (SP1-SP7 RED/GREEN) + delegated audits + controller verification (R13/R14).
+
+### Why
+
+- High-effort traffic mostly selected V4 Pro although Flash was faster, cheaper, and strongly benchmarked; the arithmetic was consistent but the arm/evidence identity and its presentation were not.
+
+### How
+
+- Strict TDD (SP1-SP7) + SP3b/SP4b and batch 1/2/3 wiring; Phase 3.5 delegated re-review (12 findings addressed); Phase 4 test audit (Tier A 23 files green, Tier B 2063/2068); Phase 5 agent-operated packaged-SEA + real-Pi QA on `:3462`.
+
+### What was not done (OOS / residuals)
+
+- Provider-specific effort ordering/auto-mapping without published equivalence (OOS1); re-benchmarking every provider/model/effort (OOS2); stage/main promotion (OOS4).
+
+### Follow-ups
+
+- Merge feature branch `recursive/106-client-neutral-model-effort-routing` (rebase onto post-105 dev) and open PR.
+- Non-blocking LOW documentation follow-ups (materiality, threshold documentation, strict-with-no-effort docs).
+
+### Artifact references
+
+- `.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- `.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`
+- `.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md`
+- `.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md`
+- `.recursive/run/106-client-neutral-model-effort-routing/05-manual-qa.md`
+
## Run: `92-configured-model-pool-benchmark-convergence`
Date: `2026-08-21`
diff --git a/.recursive/STATE.md b/.recursive/STATE.md
index 47842d66f..58f715f32 100644
--- a/.recursive/STATE.md
+++ b/.recursive/STATE.md
@@ -2,6 +2,8 @@
## Current State
+Run `106-client-neutral-model-effort-routing` is the current increment: reasoning effort is now a first-class, client-neutral routing dimension. The normalized input separates `requested_effort` from `effort_policy` (`strict` | `preferred` | `router`); the router selects over executable model-endpoint-effort arms; `strict` considers exact-effort arms only (else `reasoning_effort_unavailable`), `preferred` falls back through named receipts, and `preferred` with zero exact arms records `unsupported_fallback`. Four lossless effort states (`named` | `disabled` | `provider-default` | `no-client-preference`) are preserved end to end (decision four-state, occurrence binary). Benchmark/operational evidence is keyed by the effort arm with borrowed/related-effort priors; arm-aware lifecycle, turn-aware difficulty, non-inferiority ranking, and arm-level discovery are wired; decision/telemetry/trace provenance is canonical; and operator surfaces co-display model + effective effort + exact/borrowed evidence. Phases 0-8 are locked. Phase 5 ran the packaged SEA (`role-model-dev.exe`, sha256 `e181c6011a50a7e9681d6f16314ae7cefcbe7ca26bb21eeac34343b3befc7364`) on its own isolated port `:3462` driven by a real Pi CLI (requestId `req-9d68e76b`, routingDecisionId `decision-req-9d68e76b` -> deepseek-v4-pro; strict+max -> v4-flash-max, router+max -> v4-flash). Promotion remains a separate release operation.
+
Run `105-route-learning-matching-scope-activation` is the current increment: stage-3 matching-scope activation is shipped — a pack is a per-(role,task) ranked endpoint ladder (exact match only), materialized and aggregated pairwise, walked advisory-only, with derived floor-based activation and per-task rollback, and the Packs page renders the ladder index. The Phase 3.5 review found and the controller repaired a R1/R8 classification divergence: buildRequestClassificationForPlan read runtime-policy ids instead of the authoritative taxonomy identity, so capture/advisory classification was null while telemetry showed coder|coder.edit. Fixed at public d797a185 (tree 5da40073) + private da40a115; full host suite 2250/5-skip; live pi request classifies coder|coder.edit with lastUnclassifiedCaptures 0 on :3458 (dev channel only). Promotion remains a separate release operation.
**Run 105 closeout — bug 3 verified, four operational caveats carried forward** (not defects in the shipped fix). Verified live on `:3458`: both `coder/coder.edit` and `coder/coder.config` built **4/4 ladders** through counterfactual replays (all configured endpoints admitted, including `kimi-k3` — the configured controller and therefore the judge — admitted as a *challenger*, with `evaluation_judge_switches` recording `kimi-k3 -> deepseek-flash` from `dedupeJudgeAgainstPair`), and the route advisory reached live routing (`selection=advisory_applied`; `deepseek-flash-max` x3, `deepseek-flash` x1). Queue at closeout: 28 dispositions (24 `replayed`), 36/39 replay jobs `complete`, 0 deferred-pending, 0 capture-WAL rows, 0 stuck ledger reservations. Four caveats for the next replay-lane increment:
@@ -70,6 +72,9 @@ Run `92-configured-model-pool-benchmark-convergence` is the **current closed-out
### Product truths
+- **Client-neutral model-effort routing (run 106):** `requested_effort` + `effort_policy` (`strict`|`preferred`|`router`); executable model-endpoint-effort arms; `unsupported_fallback` for zero-exact-arm preferred; four lossless effort states (decision four-state, occurrence binary); effort-scoped evidence with borrowed/related priors; arm-aware lifecycle + turn-aware difficulty + non-inferiority + arm-level discovery; canonical decision/telemetry/trace provenance; UI model+effort+evidence co-display.
+- **Run 106 worktree:** `D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing` on branch `recursive/106-client-neutral-model-effort-routing` (diff basis `701b8b8fc0b0eeebdfe818b757f5702f50021488`; HEAD `9260a10b`).
+- **Run 106 verification floor:** Tier A 23 files green · Tier B 2063/2068 (3 conditional skips) · schemas:validate 37+30 · conformance 53/53 · core 113 · packaged SEA sha256 `e181c6011a50a7e9681d6f16314ae7cefcbe7ca26bb21eeac34343b3befc7364` · Pi QA `:3462`.
- **Configured model pool (run 92):** `computeConfiguredMembershipRevision` (order-stable SHA-256 over endpoint-variant-exact tuples) stamped on router candidates, routing decisions, benchmark manifests/samples, and clear receipts; runtime-ui `fetchRuntimeModels` no longer falls back to `/v1/models`; candidate-space scorers nullable with `—`/`n/a` presentation; `readLatestBenchmarkProfilesByEndpointIds` skips membership-mismatch and `completion_state: "stale"` samples; controller eject is destructive-confirmed; benchmark clear is transactional.
- **Run 92 worktree:** `D:\DEV\role-model\.worktrees\92-configured-model-pool-benchmark-convergence` on branch `recursive/92-configured-model-pool-benchmark-convergence` (diff basis `d59f07b91e7b23c25e7297860a0f9c967b342b7a`; HEAD `01537fb8b402c6808e7a6b69c3a03227acceb17c`).
- **Run 92 verification floor:** host-bridge 756 passed/3 skipped · runtime-ui 454 passed · sqlite-memory 67 passed · profile-aggregator 8 passed · builds green · agent-operated QA on `:3501`.
@@ -90,6 +95,8 @@ Run `92-configured-model-pool-benchmark-convergence` is the **current closed-out
### Known limitations
+- Run 106 residual: non-blocking LOW documentation follow-ups (materiality, threshold documentation, strict-with-no-effort docs).
+
- Feature-branch merge to origin `dev` remains operator-requested (runs 92, 89, 86, 85, …).
- Run 92 residual: `profileRevision` is membership-keyed (diagnostic-only) until a distinct profile receipt is warranted; no decision-time membership snapshot is persisted (the field reflects current membership at read time).
- Run 89 residual: land `.agents/plugins/marketplace.json` on published `dev` for GitHub marketplace one-liner; optional Desktop UI glance; optional Codex Stop-hook auto-continue (not adapter regex).
@@ -103,6 +110,8 @@ Run `92-configured-model-pool-benchmark-convergence` is the **current closed-out
### Operational notes
+- Prefer run-106 evidence under `.recursive/run/106-client-neutral-model-effort-routing/evidence/` for client-neutral effort routing, four-state effort-source vocabulary, borrowed/related-effort priors, and Phase 5 packaged-SEA + Pi QA.
+
- Prefer run-92 evidence under `.recursive/run/92-configured-model-pool-benchmark-convergence/evidence/` for membership-revision convergence, honest null candidate-space, benchmark quarantine, controller eject, and Phase 5 `:3501` QA.
- Prefer run-89 evidence under `.recursive/run/89-codex-role-model-package/evidence/` for Codex adapter, tool-bridge, npm/marketplace, and Phase 5 live routing proofs.
- Codex outsider install: `npx --yes @try-works/codex-role-model@latest setup|start`; marketplace via personal npm catalog or (after merge) `codex plugin marketplace add try-works/role-model --ref dev`.
diff --git a/.recursive/memory/MEMORY.md b/.recursive/memory/MEMORY.md
index 0842c6522..774101a18 100644
--- a/.recursive/memory/MEMORY.md
+++ b/.recursive/memory/MEMORY.md
@@ -29,7 +29,7 @@ Control-plane docs are not memory docs:
## Registry
- `domains/remote-effort-instance-identity.md` - effort-variant identity,
- admission, eligibility, telemetry and packaged Track B boundary (Run 93).
+ admission, eligibility, telemetry and packaged Track B boundary (Runs 93, 106).
- `domains/release-artifact-provenance.md` - exact CI commit identity across
Stage/production package assembly, runtime startup, and promotion (Run 94).
diff --git a/.recursive/memory/domains/remote-effort-instance-identity.md b/.recursive/memory/domains/remote-effort-instance-identity.md
index 03b2b10a9..3653b1323 100644
--- a/.recursive/memory/domains/remote-effort-instance-identity.md
+++ b/.recursive/memory/domains/remote-effort-instance-identity.md
@@ -4,10 +4,10 @@ Status: CURRENT
Scope: Remote endpoint effort-instance identity, admission, eligibility, and UI projection.
Owns-Paths: role-model-router/apps/runtime-host-bridge/src/; role-model-router/apps/runtime-ui/app/lib/
Watch-Paths: role-model-router/apps/runtime-ui/app/routes/; role-model-router/packages/provider-*/
-Source-Runs: 91-reasoning-effort-instance-identity; 92-configured-model-pool-benchmark-convergence; 93-variant-admission-model-pool-integrity
-Validated-At-Commit: working-tree Run 93 Phase 5 rebuild
-Last-Validated: 2026-08-22
-Tags: effort, endpoint, admission, telemetry, benchmark, track-b
+Source-Runs: 91-reasoning-effort-instance-identity; 92-configured-model-pool-benchmark-convergence; 93-variant-admission-model-pool-integrity; 106-client-neutral-model-effort-routing
+Validated-At-Commit: working-tree Run 106 closeout (HEAD 9260a10b)
+Last-Validated: 2026-10-04
+Tags: effort, endpoint, admission, telemetry, benchmark, track-b, effort-policy, effort-source
---
# Remote effort-instance identity
@@ -21,3 +21,13 @@ Managed adapter inventory (for example LiteLLM) is not a user-configurable
provider connection. The paired Track B distribution is mandatory at packaged
runtime startup; extension actions remain accurately labelled when shadow or
gated.
+Run 106 makes reasoning effort a first-class, client-neutral routing dimension:
+the normalized input separates `requested_effort` from `effort_policy`
+(`strict` | `preferred` | `router`), the router selects over executable
+model-endpoint-effort arms, and the effort state is preserved losslessly end to
+end. The decision surface keeps a four-state vocabulary
+(`named` | `disabled` | `provider-default` | `no-client-preference`) while the
+occurrence boundary keeps a binary `effort_source` vocabulary; the two must not
+be conflated (M-3 regression). Benchmark/operational evidence is keyed by the
+effort arm, and cross-effort evidence only ever acts as a labeled, discounted
+borrowed/related prior — never as exact evidence.
diff --git a/.recursive/memory/domains/runtime-routing-and-provider-capabilities.md b/.recursive/memory/domains/runtime-routing-and-provider-capabilities.md
index e06744bf4..e0a712a14 100644
--- a/.recursive/memory/domains/runtime-routing-and-provider-capabilities.md
+++ b/.recursive/memory/domains/runtime-routing-and-provider-capabilities.md
@@ -68,8 +68,9 @@ Source-Runs:
- `71-runtime-startup-lifecycle-and-health-truth-reconciliation`
- `72-standalone-runtime-config-authority-and-alias-rematerialization`
- `74-kimi-k3-kimi-code-oauth-support`
-Validated-At-Commit: `working-tree`
-Last-Validated: `2026-07-17`
+- `106-client-neutral-model-effort-routing`
+Validated-At-Commit: `working-tree Run 106 closeout (HEAD 9260a10b)`
+Last-Validated: `2026-10-04`
Tags:
- `runtime`
- `routing`
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md b/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
new file mode 100644
index 000000000..63fa49dab
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
@@ -0,0 +1,437 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 00 Requirements
+Status: `LOCKED`
+LockedAt: `2026-10-04T01:04:39Z`
+LockHash: `9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- Operator-approved decisions from the 2026-10-03 routing audit and follow-up (client-neutral model-effort routing; strict/preferred/router policies; unsupported-effort fallback; F4/F5/F6 repairs; isolated-port Pi verification)
+- Prior recursive evidence: /.recursive/run/93-variant-admission-model-pool-integrity/ (effort-aware instance identity and admission), /.recursive/run/103-agent-strategy-and-scoring-strategy/ (strategy precedence and scoring), /.recursive/run/104-replay-eligibility-and-evidence-fidelity/ (arm-effort comparability)
+- /AGENTS.md, /.recursive/RECURSIVE.md, /.recursive/STATE.md, /.recursive/DECISIONS.md, /.recursive/memory/MEMORY.md, /.recursive/memory/skills/SKILLS.md
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+Scope note: This document defines the stable requirement set for making reasoning effort a first-class, client-neutral routing dimension, scoring executable model-endpoint-effort arms with effort-scoped evidence, and proving the result with strict TDD, delegated audits, and live Pi-CLI verification of the rebuilt runtime on an isolated port.
+
+# Run 106 — Client-neutral model-effort routing
+
+## Intent
+
+Reasoning effort becomes a first-class routing dimension. The runtime routes over executable model-endpoint-effort arms, uses evidence for the effort considered, honors exact effort when available, falls back transparently when a non-strict effort is absent, and records the outcome. The normalized contract is client-neutral across Pi, DSH, Codex, OpenAI-compatible clients, and future adapters.
+
+## Motivating evidence
+
+On the audited :3458 runtime, high-effort traffic mostly selected V4 Pro although Flash appeared faster, cheaper, and strongly benchmarked. V4 Pro-high received benchmark-backed quality near 0.9, while executable provider-default Flash-high fell to 0.5 because the displayed Flash evidence belonged to fixed Flash-max. Hard difficulty also overrode the saved latency scoring, while the measured-latency selector was separately unauthorized. The arithmetic was consistent; the arm/evidence identity and its presentation were not.
+
+## TODO
+
+- [x] Elicit requirements from the operator decisions and the routing audit
+- [x] Map every operator decision and finding to requirement identifiers
+- [x] Define requirement identifiers (R1..R15)
+- [x] Write observable acceptance criteria for each requirement
+- [x] Record a verification method per requirement (tests, evidence, live QA)
+- [x] Document out-of-scope items (OOS1..OOS6)
+- [x] List constraints and assumptions
+- [x] Break the requirements into phases, tasks and subphases with stable identifiers
+- [x] Define the delegation plan and the controller verification protocol
+- [x] Record the run-104 baseline and run-105 merge coordination
+- [x] Complete Coverage Gate checklist
+- [x] Complete Approval Gate checklist
+
+## Operator decision coverage map
+
+Every fixed operator decision and every approved finding maps to at least one requirement; nothing is left to the Phase 2 plan alone.
+
+| Source obligation | Covered by |
+| --- | --- |
+| D1 Joint model-endpoint-effort arms | R2, R3, R5, R6 |
+| D2 Omitted effort is router-managed | R1, R3 |
+| D3 Legacy scalar effort is preferred | R1, R3 |
+| D4 Exact-effort arms form the primary pool | R3, R6 |
+| D5 Zero exact arms -> unsupported fallback | R3, R10 |
+| D6 strict requires an exact arm or fails | R3, R10 |
+| D7 No implicit nearest-effort mapping | R3, R9, OOS1 |
+| D8 none / omitted / provider-default distinct | R4 |
+| D9 Client identity cannot change semantics | R1, R15 |
+| D10 Phase 5 isolated port, real Pi process | R15, Constraints |
+| F4 Turn-aware difficulty repair | R7 |
+| F5 Cost/latency + quality non-inferiority | R8 |
+| F6 Effort-scoped evidence and priors | R5 |
+
+## Requirements
+
+### R1 Client-neutral effort contract
+
+Description: Every client-facing ingress normalizes into one effort contract where the requested value is separate from the routing policy, and client identity never changes the decision.
+
+Acceptance criteria:
+- Canonical input separates requested_effort from effort_policy (strict | preferred | router); the policy vocabulary is closed and validated, while provider effort labels remain forward-compatible data.
+- Omitted effort normalizes to router; a legacy scalar effort normalizes to preferred; an explicit policy is authoritative.
+- Chat Completions, Responses, Pi, DSH, Codex, direct SDK, header, and request-option paths produce equivalent normalized input or the same typed error.
+- Client identity is diagnostic only and cannot alter candidates, fallback, preference, or scoring.
+
+Verification: schema/normalization tables and cross-ingress decision parity tests.
+
+### R2 Executable model-effort arms
+
+Description: The router selects over executable model-endpoint-effort arms rather than base endpoints, so a model's advertised effort levels become explicit routing candidates.
+
+Acceptance criteria:
+- Fixed-effort endpoints create one fixed arm; dynamic provider-default endpoints create one arm per adapter-executable declared level plus a distinct provider-default arm when supported.
+- Every arm carries model, endpoint/provider/account/region identity, requested/effective effort state, source, execution mapping, and a revisioned evidence key.
+- A catalog declaration alone cannot make an arm routable; a valid adapter execution mapping is mandatory.
+- Equivalent physical/virtual arms are canonicalized, or retained only for materially distinct execution/admission properties; duplicates cannot double ranking opportunity.
+- Eligibility and scoring consume arms before selection; the selected effort reaches provider dispatch.
+- Run-93 identities and historical evidence remain readable without destructive merging.
+
+Verification: expansion, deduplication, payload, dispatch, and migration tests.
+
+### R3 Strict, preferred, and router-managed resolution
+
+Description: Effort policy is resolved deterministically, with exact-effort arms primary and non-exact arms as receipted fallback; a non-strict unsupported effort degrades gracefully.
+
+Acceptance criteria:
+- router jointly selects from all otherwise eligible arms.
+- strict considers exact-effort arms only and otherwise returns reasoning_effort_unavailable with sanitized requested/available facts.
+- preferred with exact arms routes in that primary pool; non-exact arms enter only after a named hard-eligibility or provider-attempt fallback, with a receipt.
+- preferred with zero exact executable arms records unsupported_fallback, ignores the hint, and performs router-managed selection.
+- Exact-arm counts before and after hard eligibility distinguish unsupported from temporarily unavailable.
+- Unsupported fallback never reports the client effort as applied or exact.
+- No nearest-label mapping occurs absent explicit, versioned provider equivalence.
+
+Verification: cross-product tests over policies, exact support by all/some/none, hard gates, fixed/dynamic arms, provider failure, and equivalence.
+
+### R4 Lossless effort states
+
+Description: Named effort, disabled reasoning, provider-default, and no client preference remain distinct through every layer.
+
+Acceptance criteria:
+- Internal types distinguish named effort, disabled reasoning, provider-default, and no client preference.
+- Serialization, SQLite, discovery, API, telemetry, trace, and UI preserve the distinction.
+- Adapters reject unrepresentable strict states instead of silently dropping them.
+- Nullable historical rows migrate deterministically without losing attribution.
+
+Verification: schema round-trip, migration, adapter-wire, and projection tests.
+
+### R5 Effort-scoped evidence and hierarchical priors (F6)
+
+Description: Benchmark and operational evidence is keyed by the effort arm it measured; cross-effort evidence only ever acts as a labeled, discounted prior.
+
+Acceptance criteria:
+- Evidence keys include endpoint/model identity, effective effort, membership/profile revision, and current provenance dimensions.
+- Resolution order: exact endpoint+effort; same model/provider exact effort; same endpoint related effort; model aggregate; catalog prior; neutral default.
+- Non-exact evidence is labeled and confidence-discounted; borrowed evidence never appears as exact benchmark evidence.
+- Cross-effort priors regress toward neutral by a documented symmetric rule.
+- Exact evidence monotonically supersedes priors as samples grow; stale or mismatched revisions cannot overwrite it.
+- UI cannot claim model-level parity without disclosing exact versus borrowed arm evidence.
+
+Verification: evidence/shrinkage tables, revision fencing, cold-start tests, and an audited Pro-high/Flash-high reproduction.
+
+### R6 Arm-aware strategy, controller, advice, cache, and fallback
+
+Description: Existing ranking and lifecycle machinery consumes the resolved arm pool and stays effort-aware.
+
+Acceptance criteria:
+- Existing strategy precedence (run 103) consumes the resolved arm pool.
+- Difficulty may influence posture or router-managed effort but cannot falsify strict/preferred resolution.
+- Controller/advisory preferences for a base model/endpoint expand deterministically to eligible arms and cannot invent effort.
+- Cache continuity and learned advice are effort-aware.
+- Circuit/provider fallback preserves the effort policy and receipts expansion beyond the exact primary arms.
+
+Verification: precedence, controller, advisory, continuity, circuit, and provider-failure tests.
+
+### R7 Turn-aware difficulty repair (F4)
+
+Description: Difficulty classification stops saturating long agent sessions and becomes turn-aware.
+
+Acceptance criteria:
+- Classification separates current-turn burden, bounded/diminishing conversation burden, operation risk, required quality, and latency sensitivity.
+- The unconditional toolCount > 0 && codeOrSchemaBurden => hard saturation is removed or narrowed by a documented risk rule.
+- A trivial follow-up in a long coding session can classify below hard; genuinely risky tool/code/schema work remains hard.
+- Cache invalidation follows the revised features and refuses materially stale classification.
+- Receipts expose the decisive features and the classifier version.
+
+Verification: a corpus covering audited long sessions, trivial follow-ups, fresh hard tasks, tool-free asks, and cache invalidation.
+
+### R8 Meaningful cost/latency and quality non-inferiority (F5)
+
+Description: Cost and latency stop collapsing meaningful differences, and a Pareto/non-inferiority rule can let a cheaper, faster, non-inferior arm win.
+
+Acceptance criteria:
+- Cost uses arm/workload expected request cost, including effort-sensitive output/cache economics when known, and preserves absolute values.
+- Latency uses effort- and prompt-size-specific distributions with samples/confidence; multi-second candidates do not collapse indistinguishably.
+- Normalization is documented, bounded, stable under irrelevant candidates, and robust to sparse evidence/outliers.
+- A configured Pareto/non-inferiority rule lets a statistically non-inferior, materially faster and cheaper arm outrank a dominated arm unless a named hard policy blocks it.
+- The rule records thresholds, confidence, arms, and whether it changed weighted selection; missing quality cannot establish non-inferiority.
+- Measured-latency selection is unified with this model or remains explicitly separate with authority/precedence shown in decision/config surfaces.
+
+Verification: ranking, sparse/outlier, Flash/V4 counterfactual, and eligibility-invariance property tests.
+
+### R9 Heterogeneous-pool discovery
+
+Description: Discovery advertises effort capability at the arm level so clients can omit effort safely or prevalidate strict effort.
+
+Acceptance criteria:
+- Discovery publishes the effort union, the portable intersection, per-model/per-endpoint support, and fixed/dynamic/disabled/provider-default kind.
+- It publishes supported policies and explicit provider equivalence with version/provenance.
+- Discovery derives from executable arms and refreshes with admission/config changes.
+- An empty intersection is valid and does not hide usable union levels.
+- Clients can omit effort safely and can prevalidate a strict effort before sending.
+
+Verification: discovery schema, alias aggregation, admission refresh, and multi-client consumption tests.
+
+### R10 Decision, telemetry, trace, and error provenance
+
+Description: Every decision and error explains the requested effort, the policy, the resolution, and the selected arm with honest evidence.
+
+Acceptance criteria:
+- Decisions record client provenance, requested effort, policy, union/intersection, exact counts before/after hard eligibility, resolution, selected model/endpoint/effective effort, source, and reason.
+- The resolution vocabulary includes router_managed | exact_primary | exact_fallback_expanded | unsupported_fallback | strict_rejected | equivalent_mapped.
+- Candidate diagnostics expose metrics, exact/borrowed/default evidence, confidence/samples, revision, strategy/weights, Pareto result, and exclusions without secrets or prompts.
+- Telemetry, OTel, SQLite, request detail, decision detail, and errors agree.
+- Historical variant_coerced remains readable; new outcomes never conceal coercion.
+- Errors distinguish unsupported strict effort, no executable arm, exact arms temporarily ineligible, and provider failure after fallback.
+
+Verification: contracts, migrations, SQLite/OTel projections, errors, and API consistency tests.
+
+### R11 Operator/UI truthfulness
+
+Description: Every operator surface shows model plus effective effort and exact/prior evidence, and never hides coercion.
+
+Acceptance criteria:
+- Candidate, model pool, benchmark, request, and decision surfaces show model plus effective effort and exact/prior evidence.
+- Routing configuration co-displays configured/effective strategy, override source, effort policy/resolution, and measured-latency authority.
+- Counts disclose window, total, truncation/pagination, and aggregation across arms.
+- Unsupported fallback and exact-pool expansion are prominent and accessible; color is not the sole distinction.
+- No credential, prompt, or raw provider body is exposed.
+
+Verification: component/API fixture/accessibility tests and a Phase 5 browser readback when UI changes.
+
+### R12 Effect-first and packaged-runtime safety
+
+Description: New modules follow the repository's Effect-first rule without breaking packaged-runtime constraints.
+
+Acceptance criteria:
+- Before Effect edits, implementation reads the effect-ts skill and applicable vendored guidance.
+- New schemas/services/state/concurrency use the vendored Effect workspace when possible and suitable; pure scoring remains pure.
+- Any obvious non-Effect choice records a concrete suitability/packaging rationale.
+- No new server dependency, secret exposure, cross-state-root coupling, or SEA-incompatible dynamic dependency is introduced.
+- Vendored pin verification and packaged dependency closure pass.
+
+Verification: focused tests, dependency review, vendor verification, SEA build, clean-start/restart checks.
+
+### R13 Strict TDD and regression discipline
+
+Description: Production behavior is written test-first with RED/GREEN evidence, preserving prior-run regressions.
+
+Acceptance criteria:
+- Phase 3 declares TDD Mode: strict and logs every RED-GREEN-REFACTOR cycle (test file, command, evidence path).
+- RED evidence lives under /.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/ and GREEN evidence under evidence/logs/green/; no production change precedes its focused failing test.
+- Every R1-R12 behavior has at least one dedicated test or a named, justified non-code verification.
+- Run-93 identity/admission, run-103 strategy, run-104 comparability, conformance, adapter, SQLite, observability, UI, and packaging suites remain green.
+- Phase 4 runs the focused Tier A suite and repository Tier B unless an approved addendum narrows it with evidence.
+
+Verification: Phase 3 TDD log/transcripts, Phase 4 implementation audit, delegated adequacy audit, and controller reruns.
+
+### R14 Delegated audits with controller verification
+
+Description: Audited phases use delegated audit/review with complete bundles, action records, and controller verification; failures preserve-repair-retry.
+
+Acceptance criteria:
+- Phase 1 analyst, Phase 2 traceability, bounded Phase 3 reviews, Phase 3.5 full review, Phase 4 test audit, Phase 5 QA review/execution, and Phase 8 memory audit are delegated when a complete bundle and a usable route/subagent exist.
+- Meaningful delegation creates an action record under subagents/; raw routed output stays under evidence/router/.
+- The controller independently checks files, diff, artifacts, and commands before acceptance.
+- Failed or nonzero delegated attempts are preserved, repaired, retried, and never count as pass evidence.
+- If discovery/routing is absent or unusable, the phase records the fallback and performs a full self-audit with unchanged rigor.
+
+Verification: action records, bundles, phase audit contexts, controller fields, and recursive lint.
+
+### R15 Isolated rebuilt-runtime and real Pi CLI verification
+
+Description: The change is proven on a rebuilt, packaged runtime driven by a real Pi CLI explicitly bound to an isolated port, never 3456/3457/3458.
+
+Acceptance criteria:
+- Phase 5 declares QA Execution Mode: agent-operated (or hybrid with recorded operator sign-off) and packages the exact worktree with corepack pnpm run runtime:package-sea, capturing manifest, source/commit identity, executable hash, and Effect/Track-B closure.
+- QA allocates and records a free loopback port from an approved non-reserved range; ports 3456, 3457, and 3458 are forbidden; availability is re-checked immediately before launch.
+- The runtime proves PID, executable path/hash, endpoint, isolated run-scoped state root/scope, and build identity.
+- A separately launched Pi CLI is installed/configured from this worktree's packages/pi-role-model (or the exact artifact) and explicitly bound to the chosen runtime URL; Pi discovery/status plus matching runtime request/decision IDs prove the request reached that port/build, not an unverified environment variable.
+- Existing listeners on 3456/3457/3458 are never stopped, restarted, reconfigured, mutation-probed, or reused; cleanup kills only the PID launched by this run after PID/executable/port verification.
+- Live Pi scenarios cover router-managed omitted effort, preferred exact effort, pool-wide unsupported preferred fallback, strict unsupported rejection, exact support by only some models, exact primary unavailable with receipted fallback, and distinct none/default states where supported.
+- Two semantically identical requests through Pi and a second client path prove normalized parity.
+- The live/controlled pool has heterogeneous effort sets and proves joint model-effort choice; decision and telemetry APIs are inspected for exact arm evidence and fallback receipts.
+
+Verification: Phase 5 artifact and evidence binder, runtime/Pi process metadata, request IDs, decision/telemetry/discovery readbacks, and optional browser readbacks.
+
+## Out of Scope
+
+- OOS1: Provider-specific invention of an effort ordering or automatic high-to-xhigh/max mapping without published provider equivalence.
+- OOS2: Re-benchmarking every provider/model/effort combination as a release prerequisite; exact gaps use honest priors until measured.
+- OOS3: Changing provider pricing/catalog facts except where needed to key existing economics by effort arm.
+- OOS4: Stage/main promotion, RC publication, or mutation of production/stage/development runtimes.
+- OOS5: Redesigning Track B learning beyond effort-aware package identity and receipts needed by this run.
+- OOS6: Guaranteeing identical text across clients; parity is normalized routing semantics and arm selection under identical inputs/snapshot/seed.
+
+## Constraints
+
+- Ordinary development begins in a dedicated worktree from the current origin/dev tip; never implement on long-lived dev.
+- The pre-existing modified llama-swap binaries in the controller checkout are not run-106 changes and must not enter the worktree diff.
+- Node is >=24 <25; use corepack pnpm and the existing vendored Effect/Effect-MQ pins.
+- Secrets, authorization headers, raw prompts/provider bodies, and real credentials are never committed or copied into evidence. Live credentials are operator-provided through existing credential references only.
+- Runtime channels, state roots, scopes, logs, locks, and artifacts remain isolated. Ports 3456, 3457, and 3458 are reserved and forbidden for run-106 QA.
+- Phase 5 must exercise the packaged SEA, not the source-only QA server. The Pi process must be explicitly connected to the run-106 port and proven by request receipt.
+- QA may allocate an ephemeral/free port, but must record it durably before starting requests and re-check it immediately before bind.
+- No existing runtime process may be killed or modified. Cleanup is identity-checked and limited to run-106 processes.
+- Public contracts evolve additively where compatibility permits; legacy scalar effort and historical variant_coerced records remain readable.
+- The router remains live-input-driven. Replay/evaluation/learner data cannot become a hidden hard dependency for serving.
+- Any UI work follows the existing role-model design system and accessibility contract.
+
+## Baseline and merge coordination
+
+- Run 106 branches from origin/dev @ 701b8b8fc0b0eeebdfe818b757f5702f50021488, which is the merged run 104 tip. Run 105 (recursive/105-route-learning-matching-scope-activation, head 80ad810e at audit time) is an in-flight sibling branch and is NOT a baseline.
+- Run 106 never branches from, or merges, a recursive/105-* branch. If run 105 reaches dev first, run 106 rebases onto the new dev tip before its PR; if run 106 lands first, run 105 rebases onto it. Either way, the two are reconciled at promotion time, not during Phase 1-4.
+- Known conflict-prone overlap (Phase 1/2 must re-check against run 105's actual diff before locking): apps/runtime-host-bridge/src/index.ts (advisory/learning recall vs effort resolution), packages/sqlite-memory/src/index.ts (route-learning persistence vs effort-scoped evidence keys), and decision/observability provenance surfaces.
+- Phase 1 records which run-105 changed paths intersect run 106's planned surface; Phase 2 states the rebase/merge order and the specific conflict resolution strategy before implementation begins.
+- Run 106's Phase 5 isolated runtime and Pi process are independent of run 105's runtime instances and use their own run-scoped state root and a non-reserved port.
+
+## Assumptions
+
+- Configured endpoint metadata and adapters can authoritatively state which effort values are executable; when they cannot, the arm is not advertised as executable.
+- Controlled provider/test doubles may prove rare failure paths, but at least one successful live Pi route must traverse a real configured provider through the packaged runtime when credentials are authorized.
+- The existing alias pool, admission, health, role/task, capability, modality, context, budget, and circuit rules remain hard eligibility authorities.
+- Existing run-103 strategy precedence remains unless an approved addendum explicitly changes it; R7/R8 improve signals and ranking, not hidden policy ownership.
+
+## Delivery phases, tasks and subphases
+
+The breakdown maps the operator decisions and the audit findings onto the recursive-mode phases. Every Phase 1/2 task carries the same four fields (Scope, Inputs, Outputs, Verification) so a task can be handed to a subagent without re-deriving context. Task ids are stable and reused by the Phase 2 plan, the Phase 3 sub-phases, the evidence tree, and the delegation records.
+
+### Phase 0 - Worktree isolation
+
+Create /.worktrees/106-client-neutral-model-effort-routing from origin/dev @ 701b8b8, record the exact diff basis in 00-worktree.md, install/build dependencies, and capture a clean baseline or pre-existing failures. All later phases execute in the worktree.
+
+### Phase 1 - AS-IS and root cause (analyst-delegable)
+
+| Task | Scope | Inputs | Outputs | Verification |
+| --- | --- | --- | --- | --- |
+| T1.1 Source requirement inventory | Index every obligation of the operator decisions and findings with a source quote, a normalized summary, and a disposition | This artifact, the routing-audit findings | 01-as-is.md ## Source Requirement Inventory | Every decision/finding appears exactly once; each entry names a requirement id |
+| T1.2 Ingress effort trace | Record how every client shape (Chat Completions, Responses, Pi, DSH, Codex, SDK, header, request-option) reaches effort resolution, with file:line anchors | apps/runtime-host-bridge/src/index.ts, packages/pi-role-model | 01-as-is.md subsection | Each claim cites a file and line; reproducible from the recorded diff basis |
+| T1.3 Arm and evidence identity inventory | Record fixed/dynamic/provider-default identity and effort-scoped evidence keys from runs 93, 103, 104 and current source | packages/core/src/router.ts, packages/sqlite-memory/src/index.ts, prior-run docs | 01-as-is.md subsection | Each identity/evidence-key claim names its source run and current path |
+| T1.4 Reproduce Pro-high/Flash-high asymmetry | Reproduce the evidence asymmetry and the strategy/latency-gate interaction with sanitized fixtures or live read-only evidence | Live decision receipts, candidate profiles | 01-as-is.md + 01.5-root-cause.md evidence | The observed quality gap (0.9 vs 0.5) and the disabled latency selector are demonstrated end to end |
+| T1.5 Root cause analysis | Prove the root causes (arm/evidence identity mismatch, difficulty override, unauthorized latency selector) before planning fixes | 01-as-is.md | 01.5-root-cause.md | Root causes are demonstrated, not hypothesised |
+
+### Phase 2 - ExecPlan and ownership (planner-delegable audit)
+
+| Task | Scope | Inputs | Outputs | Verification |
+| --- | --- | --- | --- | --- |
+| T2.1 Requirement mapping | Map every R1-R15 and every Phase-1 source item with ## Requirement Mapping, ## Plan Drift Check, and plan-stage ## Requirement Completion Status | 01-as-is.md, 01.5-root-cause.md | 02-to-be-plan.md | No requirement unmapped; no sub-phase without a requirement id |
+| T2.2 Sub-phase definition | Define SP1-SP9 with file ownership, disjointness, ordering, RED tests, GREEN evidence, rollback, migrations, and package/QA commands | 02-to-be-plan.md | 02-to-be-plan.md | Write scopes are disjoint; each SP lists its RED tests first |
+| T2.3 Verification and QA plan | Fix exact Tier A/B suites, the isolated-port allocation, the identity-safe cleanup, and the Pi matrix | R13, R15 | 02-to-be-plan.md | Every R# acceptance criterion has a named command or observed artefact |
+| T2.4 Delegation and risk register | Confirm the delegation plan, re-read router policy/discovery, define complete bundles and controller verification | .recursive/config/recursive-router*.json | 02-to-be-plan.md | Each delegated task names role, bundle path, and controller verification |
+
+Expected implementation subphases (Phase 2 may refine without losing coverage):
+
+| Sub-phase | Requirement coverage | Scope | RED evidence | GREEN evidence |
+| --- | --- | --- | --- | --- |
+| SP1 | R1, R4 | Normalized effort schema/policy and client adapters | evidence/logs/red/sp1-*.log | evidence/logs/green/sp1-*.log |
+| SP2 | R2-R4 | Executable arm identity, expansion, dedupe, dispatch mapping | evidence/logs/red/sp2-*.log | evidence/logs/green/sp2-*.log |
+| SP3 | R5, R10 | Effort-scoped evidence, migration, priors, confidence | evidence/logs/red/sp3-*.log | evidence/logs/green/sp3-*.log |
+| SP4 | R3, R6 | Policy resolution, fallback, controller/advisory/cache/circuit | evidence/logs/red/sp4-*.log | evidence/logs/green/sp4-*.log |
+| SP5 | R7 | Turn-aware difficulty classifier and cache receipts | evidence/logs/red/sp5-*.log | evidence/logs/green/sp5-*.log |
+| SP6 | R8 | Cost/latency normalization and non-inferiority/Pareto | evidence/logs/red/sp6-*.log | evidence/logs/green/sp6-*.log |
+| SP7 | R9-R10 | Discovery, APIs, telemetry, trace, SQLite errors/provenance | evidence/logs/red/sp7-*.log | evidence/logs/green/sp7-*.log |
+| SP8 | R11 | Operator/UI truthfulness and accessibility | evidence/logs/red/sp8-*.log | evidence/logs/green/sp8-*.log |
+| SP9 | R12, R15 | Package/client integration and isolated QA harness | evidence/logs/red/sp9-*.log | evidence/logs/green/sp9-*.log |
+
+### Phase 3 - Strict TDD implementation
+
+Controller owns production writes unless a future resolved implementer route explicitly authorizes bounded disjoint work. Each SP begins with failing tests and RED evidence, then minimal implementation, GREEN, refactor, and a bounded code-review audit. Phase 3 maintains the R13 compliance log.
+
+### Phase 3.5 - Canonical code review
+
+Generate a fresh recursive-review-bundle, delegate code review, verify every finding against the actual diff, repair in Phase 3, regenerate the bundle after material change, and re-review before lock.
+
+### Phase 4 - Implementation and test audit
+
+Audit requirements against changed files before trusting tests. Run the focused and broad suites, packaging checks, migrations, conformance, and test-adequacy delegation. The controller reruns accepted commands and records exact logs.
+
+### Phase 5 - Agent-operated isolated runtime QA
+
+1. Package the exact worktree SEA.
+2. Select a currently free loopback port excluding 3456-3458; record port/PID/path/hash/state root/scope.
+3. Start only the run-106 runtime with a fresh run-scoped state root.
+4. Install/configure a separate Pi instance from the exact worktree/package to this runtime URL.
+5. Run pi --no-session --provider role-model --model -p "" scenarios for R15.
+6. Prove each Pi request reached the chosen port/build using Pi discovery/status and matching runtime request/decision IDs.
+7. Run a second-client parity scenario, inspect discovery/decision/telemetry/UI, preserve evidence, and clean up only identity-verified run-106 processes.
+
+### Phases 6-8 - Closeout
+
+Update decisions, state, and memory using final validated code/evidence. Phase 8 captures run-local skill usage and delegates memory audit when possible.
+
+## Delegation plan
+
+Current router policy makes orchestrator local-only; analyst/planner/code-reviewer/tester/memory-auditor request external routing but have null CLI/model with self-audit fallback; implementer is disabled; discovery inventory is absent in this controller checkout. Every phase must re-read actual policy/discovery rather than inherit this snapshot.
+
+| Task | Delegated? | Role | Why | Required artefacts | Controller verification |
+| --- | --- | --- | --- | --- | --- |
+| T1.1-T1.5 | Yes (draft + audit) | analyst | Independent AS-IS/root-cause pass catches drift | subagents/analyst-t1.md + review bundle | Re-read every cited file; confirm claims against the diff basis |
+| T2.1-T2.4 | Yes (traceability audit) | planner | Requirement-to-plan coverage is the guarded failure mode | subagents/planner-t2.md | Every R# mapped; spot-check mappings against the plan |
+| Phase 3 SP audits | Yes (bounded, read-only) | code-reviewer | Cheap bounded verification of one SP diff | subagents/code-reviewer-spN.md | Controller re-runs named commands and re-reads the diff |
+| Phase 3.5 review | Yes | code-reviewer | High-risk change; full bundle review | evidence/review-bundles/03-5-code-review.md + action record | Findings verified against actual files; repairs recorded |
+| T4 test-adequacy audit | Yes | tester | Tests are the R13 evidence base | subagents/tester-t4.md | Controller re-runs accepted commands and compares logs |
+| T5 Pi matrix | Yes (supervised execution) | tester | Mechanical matrix; controller monitors | subagents/tester-t5.md + transcripts | Controller verifies every process identity, request ID, receipt, and cleanup |
+| T8 memory audit | Yes | memory-auditor | Memory/status drift is easy to miss | subagents/memory-auditor-t8.md | Compare touched paths and statuses with the final diff |
+
+Rules this plan keeps: one active phase at a time; subagents never authorize parallel phases; write-capable delegation is prohibited (implementer disabled); every delegated dispatch cites a bundle or explicit context list; any failure, success:false, or nonzero routed exit triggers an audit-repair-retry loop with the failed attempt preserved as evidence.
+
+## Controller verification of delegated work
+
+No delegated result is accepted on its own word. For every delegated task the controller:
+
+1. Confirms the task was dispatched with a complete bundle (phase, artifact path, upstream artifacts, diff basis, changed files, targeted code refs, audit questions, output shape).
+2. Verifies the claim against the actual worktree: re-reads the named files, re-runs the named commands, and diffs the claimed scope against the normalized diff command recorded in 00-worktree.md.
+3. Rejects any output that lacks a verdict, cites no changed files, ignores addenda, or cannot be turned into a durable action record.
+4. Repairs in-scope gaps itself, refreshes the bundle when repairs change reviewed scope, and re-dispatches the same role before accepting.
+5. Records Reviewed Action Records, Main-Agent Verification Performed, Acceptance Decision, Refresh Handling, and Repair Performed After Verification in the phase artifact.
+
+Action records live under /.recursive/run/106-client-neutral-model-effort-routing/subagents/; routed transcripts live under evidence/router/.
+
+## Requirement-to-task traceability
+
+| Requirement | Phase 1 task | Sub-phase / phase | Delegated verification |
+| --- | --- | --- | --- |
+| R1 | T1.2 | SP1 | code-reviewer-sp1 |
+| R2 | T1.2-T1.3 | SP2 | code-reviewer-sp2 |
+| R3 | T1.2/T1.4 | SP4 | code-reviewer-sp4 |
+| R4 | T1.2-T1.3 | SP1-SP3 | code-reviewer-sp2 |
+| R5 | T1.3-T1.5 | SP3 | code-reviewer-sp3 |
+| R6 | T1.2 | SP4 | code-reviewer-sp4 |
+| R7 | T1.4-T1.5 | SP5 | code-reviewer-sp5 |
+| R8 | T1.4-T1.5 | SP6 | code-reviewer-sp6 |
+| R9 | T1.2 | SP7 | code-reviewer-sp7 |
+| R10 | T1.2-T1.4 | SP7 | code-reviewer-sp7 |
+| R11 | T1.2 | SP8 | code-reviewer-sp8 |
+| R12 | T1.3 | all SPs, SP9 | Phase 3.5 review |
+| R13 | - | Phase 3 TDD log, Phase 4 | tester-t4 |
+| R14 | all audited phases | Phase 3.5, 4, 5, 8 | controller acceptance |
+| R15 | T1.4 | SP9 and Phase 5 | tester-t5 + controller acceptance |
+
+## Coverage Gate
+
+- [x] Every operator decision (D1-D10) and finding (F4/F5/F6) maps to at least one R# via the coverage map.
+- [x] Every R1-R15 has a Description, observable Acceptance criteria, and a stated Verification method.
+- [x] Strict TDD (R13), delegated audits (R14), Effect/packaging safety (R12), and effort-scoped evidence (R5) are explicit requirements.
+- [x] Isolated packaged-runtime + real Pi proof on a non-3456/3457/3458 port is R15 and Constraints.
+- [x] Run 104 baseline and run 105 merge coordination are recorded.
+- [x] Every requirement is broken into phases, tasks, and subphases with stable ids and subagent handoff fields.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] The operator authorized run 106 creation and approved the effort-routing semantics.
+- [x] No unresolved in-scope gap remains; the requirement set is stable for Phase 1.
+
+Approval: PASS
+
+Approval basis: operator instructions in this session approved the client-neutral model-effort contract, strict/preferred/router policies, unsupported-effort fallback, F4/F5/F6 repairs, strict TDD, delegated audits, and isolated-port rebuilt-runtime + real-Pi verification. The structure now mirrors run 103 (Description + Acceptance criteria per R#, four-field task tables, delegation plan table, controller verification protocol, and traceability table).
+
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md b/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md
new file mode 100644
index 000000000..cfa06415b
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md
@@ -0,0 +1,91 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 00 Worktree Isolation
+Status: `LOCKED`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md (LOCKED)
+- /AGENTS.md, /.recursive/RECURSIVE.md
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md
+Scope note: This document records the isolated worktree, the clean-baseline verification, and the diff basis that every later phase audits against.
+
+## TODO
+
+- [x] Select the worktree location
+- [x] Verify the worktree directory is git-ignored
+- [x] Create the feature-branch worktree from origin/dev
+- [x] Copy the locked requirements into the worktree
+- [x] Complete project setup (corepack pnpm install + Effect workspace build)
+- [x] Verify the clean test baseline
+- [x] Record the diff basis for later audits
+- [x] Complete Coverage and Approval gates
+
+## Directory Selection
+
+- Location: .worktrees/106-client-neutral-model-effort-routing (inside the repo, under the existing .worktrees/ convention)
+- Branch: recursive/106-client-neutral-model-effort-routing
+- Rationale: the repo already keeps every recursive run under .worktrees//; no new top-level location is needed.
+
+## Safety Verification
+
+- git check-ignore .worktrees/106-client-neutral-model-effort-routing returned the path, so the worktree is git-ignored and will not be committed as a nested repo.
+- Controller checkout HEAD and origin/dev both resolve to 701b8b8fc0b0eeebdfe818b757f5702f50021488 (merged run 104); run 105 is an in-flight sibling and is excluded from the baseline.
+
+## Worktree Creation
+
+Command: git worktree add .worktrees/106-client-neutral-model-effort-routing -b recursive/106-client-neutral-model-effort-routing origin/dev
+
+Result: new branch recursive/106-client-neutral-model-effort-routing tracking origin/dev; HEAD at 701b8b8f (Merge run-104 R22-A/B + R23 + R24 + stage-3 design doc into dev).
+
+## Main Branch Protection
+
+- No main/master work was performed. The controller was on dev; all implementation work happens on recursive/106-client-neutral-model-effort-routing in the isolated worktree.
+
+## Project Setup
+
+- Command: corepack pnpm install --frozen-lockfile (run from the worktree root)
+- Effect workspace wrapper must be built as part of setup; a bare bridge build fails without it (recorded in run 103 requirements Constraints).
+- Status: complete. corepack pnpm install --frozen-lockfile (679 packages, pnpm 10.6.5) and the effect workspace build (node build.mjs, status PASS) both succeeded; non-fatal tsconfig/case-sensitivity warnings are expected for the vendored source.
+LockedAt: `2026-10-04T01:15:16Z`
+LockHash: `92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763`
+
+## Test Baseline Verification
+
+- Baseline result: @role-model-router/core vitest run -> 10 test files, 82 tests passed. Remaining Tier A suites (protocol-routing, endpoint-registry, adapter, sqlite-memory, runtime-observability, conformance, runtime-ui) run in Phase 4 per R13.
+- Any pre-existing failure is recorded explicitly; run 106 does not claim a clean baseline it did not observe.
+
+## Worktree Context
+
+- Every subsequent phase (AS-IS, root cause, TO-BE plan, implementation, review, test, QA, closeout) executes from this worktree.
+- Commands, evidence, and changed files are recorded relative to this worktree root.
+
+## Diff Basis For Later Audits
+
+- Baseline type: remote ref
+- Baseline reference: origin/dev
+- Comparison reference: working-tree
+- Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+- Normalized comparison: working-tree
+- Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+- Diff basis notes: run 105 (recursive/105-route-learning-matching-scope-activation, head 80ad810e) is an in-flight sibling and is deliberately excluded from the baseline; Phase 1/2 re-check run 105's diff for overlap before locking.
+
+## Traceability
+
+- R12 (Effect-first + packaged-runtime safety): Project Setup builds the vendored Effect workspace and verifies the packaged dependency closure.
+- R13 (strict TDD): Test Baseline Verification records the pre-change green baseline that TDD red/green cycles build on.
+- R14 (delegated audits): the diff basis recorded here is what Phase 1/2/3.5/4 audits execute against.
+- R15 (isolated port QA): the worktree packages the exact SEA that Phase 5 launches on an isolated port.
+
+## Coverage Gate
+
+- [x] Worktree location, ignore status, branch, and diff basis are recorded.
+- [x] Project setup completes and the Effect workspace builds.
+- [x] Clean test baseline is verified: core 82/82 tests pass.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Setup and baseline verification complete before Phase 1 begins.
+
+Approval: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md b/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md
new file mode 100644
index 000000000..8cf25240a
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md
@@ -0,0 +1,269 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 01 AS-IS
+Status: `LOCKED`
+LockedAt: `2026-10-04T01:33:52Z`
+LockHash: `4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md
+Scope note: This document records how reasoning-effort routing works today at 701b8b8, mapped to R1-R15, so the Phase 2 plan and the Phase 1.5 root cause are grounded in the actual source.
+
+## TODO
+
+- [x] Reproduce the Pro-high/Flash-high asymmetry from the code path
+- [x] Map current behavior to every R1-R15 with file:line citations
+- [x] Index the source obligations (Source Requirement Inventory)
+- [x] Record code pointers, known unknowns, and evidence
+- [x] Record prior recursive evidence reviewed
+- [x] Complete delegated phase-audit and repair
+- [x] Complete Coverage and Approval gates
+
+## Reproduction Steps (Novice-Runnable)
+
+1. Configure a runtime with a provider-default endpoint and a fixed-effort endpoint for the same model (e.g. deepseek-flash provider-default plus deepseek-flash-max fixed max), plus a V4 Pro provider-default endpoint, all under one alias (difficulty.remote-only).
+2. Send a high-effort request through the alias with tools and a large code/schema-bearing context.
+3. Observe the router classifies the request hard (toolCount > 0 && codeOrSchemaBurden), so the effective strategy becomes quality with quality weight 0.5.
+4. Observe the decision receipt: the winner is V4 Pro with benchmark-backed quality near 0.9, while the runner-up is provider-default Flash with default quality 0.5, even though Flash-max holds a stronger benchmark near 0.958.
+5. Observe the measured-latency selector reports disabled: 'measured-latency selection input is not authorized'.
+
+## Source Requirement Inventory
+
+- R1 | Source Quote: Every client-facing ingress normalizes into one effort contract | Summary: no strict | preferred | router policy; a scalar effort is a pool preference and fixed-effort coercion is recorded as variant_coerced | Disposition: in-scope
+- R2 | Source Quote: The router selects over executable model-endpoint-effort arms | Summary: endpoints carry fixed/declared effort but the router scores endpoints, not materialized arms | Disposition: in-scope
+- R3 | Source Quote: Effort policy is resolved deterministically, with exact-effort arms primary | Summary: no policy vocabulary; no exact-primary/fallback/unsupported_fallback semantics | Disposition: in-scope
+- R4 | Source Quote: Named effort, disabled reasoning, provider-default, and no client preference remain distinct | Summary: reasoning_effort is a nullable string; no total type for the four states | Disposition: in-scope
+- R5 | Source Quote: Benchmark and operational evidence is keyed by the effort arm it measured | Summary: quality evidence is endpoint-keyed; provider-default falls to default 0.5 while a fixed-effort sibling holds the benchmark | Disposition: in-scope
+- R6 | Source Quote: Existing ranking and lifecycle machinery consumes the resolved arm pool | Summary: strategy/difficulty/controller/cache/fallback operate on endpoints, not effort arms | Disposition: in-scope
+- R7 | Source Quote: Difficulty classification stops saturating long agent sessions | Summary: toolCount > 0 && codeOrSchemaBurden short-circuits to hard | Disposition: in-scope
+- R8 | Source Quote: Cost and latency stop collapsing meaningful differences | Summary: fixed 150/300 ms and 0.01 targets compress differences; no non-inferiority rule | Disposition: in-scope
+- R9 | Source Quote: Discovery advertises effort capability at the arm level | Summary: discovery publishes effort_levels but no union/intersection, arm kind, or policy vocabulary | Disposition: in-scope
+- R10 | Source Quote: Every decision and error explains the requested effort | Summary: provenance records effortSource/strategyLabel but no resolution vocabulary or arm counts | Disposition: in-scope
+- R11 | Source Quote: Every operator surface shows model plus effective effort | Summary: surfaces show model and sometimes effort but not exact/borrowed evidence or coercion | Disposition: in-scope
+- R12 | Source Quote: New modules follow the repository's Effect-first rule | Summary: effect@4.0.0-rc.117 already built; no new server dependency | Disposition: in-scope
+- R13 | Source Quote: Production behavior is written test-first with RED/GREEN evidence | Summary: run 106 has not yet produced RED/GREEN evidence | Disposition: quality-gate
+- R14 | Source Quote: Audited phases use delegated audit/review with complete bundles | Summary: per-phase action records/bundles do not exist yet | Disposition: quality-gate
+- R15 | Source Quote: The change is proven on a rebuilt, packaged runtime driven by a real Pi CLI | Summary: nothing built yet; Phase 5 allocates an isolated non-3456/3457/3458 port | Disposition: quality-gate
+
+## Relevant Code Pointers
+
+- Effort instance selection: apps/runtime-host-bridge/src/index.ts:9489 (selectReasoningEffortInstanceIds), :9532 (filterRequestedModelPoolByReasoningEffort), :9605 (applyReasoningEffortToModelPool), :10573 (effort application in Chat Completions plan).
+- Quality evidence: packages/core/src/router.ts:729 (getQualityMetric) — benchmark-first, else judge_score, else quality_score, else default 0.5.
+- Weighted scoring: packages/core/src/router.ts:1531 (scoreCandidate), :188 (STRATEGY_WEIGHTS), :32 (ROUTER_SCORE_TIE_EPSILON), :1647 (compareTieBreak).
+- Cost/latency: packages/core/src/router.ts:916 (getLatencyMetric), :1018 (getCostMetric).
+- Difficulty: apps/runtime-host-bridge/src/index.ts:1336 (summarizeDifficultySignals), :1384 (classifyDifficultyFromSignals).
+- Strategy precedence: apps/runtime-host-bridge/src/scoring-strategy.ts:152 (difficultyBucketStrategy), :170 (resolveStrategy).
+- Measured-latency gate: apps/runtime-host-bridge/src/index.ts:26367 (latencySelectionAuthorized), :26603 (disabled receipt).
+- Arm identity: packages/endpoint-registry/src/effort-instance-identity.ts (reasoningEffort normalization and endpoint identity).
+
+## Current Behavior by Requirement
+
+### R1 Client-neutral effort contract
+
+Current state: there is a single internal effort application path but no client-neutral policy contract. Ingress shapes (Chat Completions and Responses) both read a reasoning effort value and feed applyReasoningEffortToModelPool (index.ts:10573, :10877), but there is no strict | preferred | router policy field; a scalar effort is treated as a preference over the pool and, on a fixed-effort endpoint, can be coerced (effortSource variant_coerced, recorded in trace/lineage). Client identity is not a routing input, but the normalized contract R1 requires does not exist yet.
+
+Gap: requested_effort and effort_policy are not separate; omitted effort is not explicitly router-managed; no cross-client parity test exists.
+
+### R2 Executable model-effort arms
+
+Current state: endpoints already carry fixed reasoning_effort (effort-instance-identity.ts) and declared reasoning_effort_levels (packages/endpoint-registry/src/index.ts:63), and selectReasoningEffortInstanceIds (index.ts:9489) picks fixed-effort instances first, then provider-default instances that declare the level. However, the router still scores endpoints, not a materialized (model, endpoint, effort) arm; dynamic levels are not expanded into explicit arms with independent evidence keys.
+
+Gap: no virtual arms for dynamic levels; no canonicalized arm identity beyond endpoint identity; evidence is not keyed by arm.
+
+### R3 Strict, preferred, and router-managed resolution
+
+Current state: no policy vocabulary. applyReasoningEffortToModelPool orders the pool by effort (index.ts:9605-9663) and filterRequestedModelPoolByReasoningEffort can empty a pool (index.ts:9532-9565) with a reasoning_effort_unavailable refusal, but there is no exact-primary/fallback semantics, no unsupported_fallback that ignores the hint, and no strict policy.
+
+Gap: R3 semantics are entirely absent.
+
+### R4 Lossless effort states
+
+Current state: reasoning_effort is a nullable string; effortSource distinguishes none | client | variant | variant_coerced (trace lineage), but named effort, disabled reasoning, provider-default, and no-preference are not modeled as distinct states; serialization relies on the nullable string plus a separate effortSource.
+
+Gap: no total type distinguishes the four states; migration of nullable rows is unproven.
+
+### R5 Effort-scoped evidence and hierarchical priors (F6)
+
+Current state: getQualityMetric (router.ts:729) reads candidate.benchmarkCapability?.overallScore and task/role/group scores keyed by endpoint, not by effective effort. A provider-default endpoint with no benchmark falls to default 0.5 (router.ts:887) even when a fixed-effort sibling holds benchmark evidence. There is no cross-effort prior or confidence discount.
+
+Gap: this is the direct cause of the Pro-high/Flash-high asymmetry; evidence is endpoint-keyed, not arm-keyed, and no hierarchical prior exists.
+
+### R6 Arm-aware strategy, controller, advice, cache, and fallback
+
+Current state: strategy precedence (scoring-strategy.ts:170) and difficulty (index.ts:1384) operate on the endpoint pool; controller/advisory preferences are base-model/endpoint-scoped and are not expanded to effort arms; cache continuity and learned advice are endpoint-keyed.
+
+Gap: no effort-aware expansion of controller/advisory/cache/fallback.
+
+### R7 Turn-aware difficulty repair (F4)
+
+Current state: classifyDifficultyFromSignals (index.ts:1384) short-circuits to hard when toolCount > 0 && codeOrSchemaBurden (index.ts:1400-1405), and the rubric adds points for large context, history, constraints, and decomposition keywords. This saturates nearly every agentic coding turn to hard. There is no turn-aware separation of conversation burden vs current-turn burden.
+
+Gap: the saturation shortcut is the direct cause of hard classification dominating; R7's turn-aware model is absent.
+
+### R8 Meaningful cost/latency and quality non-inferiority (F5)
+
+Current state: getLatencyMetric (router.ts:916) normalizes against fixed 150/300 ms targets, so multi-second remote endpoints collapse near 0; getCostMetric (router.ts:1018) normalizes against a flat 0.01 target, so inexpensive models collapse near 1. There is no Pareto/non-inferiority rule; weighted total (scoreCandidate router.ts:1531) is the only selector, and the measured-latency selector (routing-latency-selection.ts) is separately stage-gated.
+
+Gap: cost/latency compression and no non-inferiority rule; two latency mechanisms remain separate and confusing.
+
+### R9 Heterogeneous-pool discovery
+
+Current state: downstream OpenAI discovery publishes reasoning support and effort_levels at the model/alias level, and endpoints expose reasoning_effort_levels. There is no effort union vs portable intersection, no per-arm kind (fixed/dynamic/disabled/provider-default), and no published policy vocabulary or provider equivalence.
+
+Gap: discovery does not express heterogeneous arm capability or policy semantics.
+
+### R10 Decision, telemetry, trace, and error provenance
+
+Current state: decisions record selectedModelId, reasoningEffort, effortSource (client | variant | variant_coerced), strategyLabel, and rewrite reason; telemetry/OTel/SQLite persist endpoint-level effort via effort_source. There is no resolution vocabulary (router_managed | exact_primary | unsupported_fallback | ...), no requested-vs-effective-effort pair, and no exact-arm counts before/after eligibility.
+
+Gap: provenance is partial and endpoint-scoped; the R10 resolution vocabulary and arm provenance are absent.
+
+### R11 Operator/UI truthfulness
+
+Current state: the model pool, candidates, and decision surfaces show model and (sometimes) effort, but benchmark evidence is model-level and does not disclose exact vs borrowed arm evidence; the routing config shows the configured operator strategy without always co-displaying the effective per-request strategy or override source.
+
+Gap: arm-level truthfulness (exact/borrowed/default evidence, coercion disclosure, configured-vs-effective strategy) is missing.
+
+### R12 Effect-first and packaged-runtime safety
+
+Current state: the vendored Effect workspace (role-model-router/packages/effect, built as effect@4.0.0-rc.117) is already the substrate; core routing remains a pure function. The packaged SEA dependency closure is validated by runtime:package-sea. No new server dependency is introduced by this run's scope.
+
+Gap: none structural; Phase 3 must follow the Effect-first map and re-verify the SEA closure.
+
+### R13 Strict TDD and regression discipline
+
+Current state: the repository already enforces strict TDD for recursive runs; the touched suites (core, protocol-routing, endpoint-registry, adapter, sqlite-memory, runtime-observability, conformance, runtime-ui) exist and pass at baseline (core 82/82 confirmed).
+
+Gap: run 106 has not yet produced RED/GREEN evidence; that is Phase 3.
+
+### R14 Delegated audits with controller verification
+
+Current state: the delegation plan (requirements) and the repository policy are in place; the implementer route is disabled, so the controller owns writes, and analysis/audit/review roles fall back to in-session subagents or self-audit.
+
+Gap: run 106's per-phase action records and bundles do not exist yet; Phase 1 will record the analyst dispatch and its reconciliation.
+
+### R15 Isolated rebuilt-runtime and real Pi CLI verification
+
+Current state: the run-105 runtime on :3458 is owned by another agent and must not be touched; run 106 has no packaged SEA or isolated runtime yet. Phase 5 will allocate a non-3456/3457/3458 port and drive a separately launched Pi against the rebuilt runtime.
+
+Gap: nothing built yet; this is Phase 5, with the port isolation and Pi binding recorded as hard constraints.
+
+## Known Unknowns
+
+- Exact effort-level vocabulary across all adapters (low/medium/high/xhigh/max/none/provider-default) and which adapters can execute which level dynamically vs only via a fixed endpoint.
+- Whether the catalog declares reasoning_effort_levels for every provider-default endpoint, and the fidelity of that declaration for execution mapping.
+- Whether effort-scoped evidence migration is safe across existing persisted endpoint-keyed profiles without losing historical attribution.
+
+## Evidence
+
+- Baseline evidence: Effect build PASS; @role-model-router/core vitest run 82/82 (Phase 0).
+- Live decision receipts from the audited :3458 runtime (session audit) show the Pro-high (quality 0.9) vs provider-default Flash-high (default 0.5) asymmetry and the disabled measured-latency selector; these are runtime-owned observations, reproduced here as the motivating evidence, not as run-106 output.
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/93-variant-admission-model-pool-integrity/00-requirements.md` - effort-aware instance identity and admission.
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md` - strategy precedence and the difficulty override.
+- `/.recursive/run/104-replay-eligibility-and-evidence-fidelity/00-requirements.md` - arm-effort comparability and evidence revision fencing.
+
+## Traceability
+
+- R1: Current Behavior by Requirement -> R1 (index.ts:10573, :10877).
+- R2: -> R2 (effort-instance-identity.ts, index.ts:9489).
+- R3: -> R3 (index.ts:9605-9663, :9532-9565).
+- R4: -> R4 (trace lineage effortSource).
+- R5: -> R5 (router.ts:729, :887).
+- R6: -> R6 (scoring-strategy.ts:170, index.ts:1384).
+- R7: -> R7 (index.ts:1384, :1400-1405).
+- R8: -> R8 (router.ts:916, :1018).
+- R9: -> R9 (downstream discovery effort_levels).
+- R10: -> R10 (decision effortSource/strategyLabel).
+- R11: -> R11 (candidate/decision surfaces).
+- R12: -> R12 (effect@4.0.0-rc.117 build).
+- R13: -> R13 (baseline 82/82).
+- R14: -> R14 (delegation plan).
+- R15: -> R15 (Phase 5 constraints).
+
+## Audit Context
+
+Audit Execution Mode: subagent
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; analyst 323c261d and phase-auditor f4260377 were dispatched; the phase-auditor returned a complete R1-R15 verification.
+Delegation Decision Basis: Phase 1 is audited; independent verification of the current-state claims against source is the default path, and the phase-auditor performed it.
+Audit Inputs Provided: 01-as-is.md, 00-requirements.md, 00-worktree.md, and the cited worktree source files; the auditor verified every R1-R15 claim against source and returned two citation repairs (F1, F2).
+
+## Effective Inputs Re-read
+
+- 00-requirements.md (LOCKED)
+- 00-worktree.md (LOCKED)
+- /.recursive/RECURSIVE.md
+
+## Earlier Phase Reconciliation
+
+Phase 1 has no earlier run-106 artifact beyond Phase 0. The diff basis (remote ref origin/dev @ 701b8b8) and the run-105 exclusion are carried from 00-worktree.md unchanged.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/analyst-323c261d.md`, `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-f4260377.md`
+Main-Agent Verification Performed: reconciled each action record's claimed file impact against the run diff and the worktree; reviewed code read-only and untouched in the diff: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/trace/src/lineage.ts`, `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`; reviewed phase artifacts `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md` and `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`; re-derived the load-bearing claims (the 0.5-default fallback at router.ts:887, the hard short-circuit at index.ts:1400) before accepting each contribution.
+Acceptance Decision: accepted
+Refresh Handling: none required; artifact updated in place.
+Repair Performed After Verification: `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Planned or claimed changed files: /.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md
+Actual changed files reviewed: HEAD bfd01851 (Phase 0 on 701b8b8); tracked diff = 5 Phase-0 control-plane files; untracked 01-as-is.md only; zero product-code drift
+Unexplained drift: none expected at Phase 1 (no product code changed yet)
+
+## Gaps Found
+
+- F1 (auditor) [resolved]: R2 misattributed reasoning_effort_levels to effort-instance-identity.ts; corrected to packages/endpoint-registry/src/index.ts:63.
+- F2 (auditor) [resolved]: R1/pointers/traceability cited index.ts:10569 (inside a doc comment); corrected to :10573.
+- All other R1-R15 current-state claims were verified by the auditor against source.
+- None remain after F1/F2 resolution.
+
+## Repair Work Performed
+
+- Applied F1 and F2 citation repairs; filled Subagent Contribution Verification and Worktree Diff Audit; set Requirement Completion Status to out-of-scope (Phase 1 analysis-only).
+
+## Requirement Completion Status
+
+- R1 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R2 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R3 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R4 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R5 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R6 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R7 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R8 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R9 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R10 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R11 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R12 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R13 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R14 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R15 | Status: out-of-scope | Rationale: Phase 1 records AS-IS evidence only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+
+## Audit Verdict
+
+Audit: PASS
+
+## Coverage Gate
+
+- [x] Independent audit confirms every R1-R15 current-state claim against the worktree source.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Audit passes with no unresolved in-scope gap.
+
+Approval: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md b/.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md
new file mode 100644
index 000000000..5b6fdbce8
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md
@@ -0,0 +1,164 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 01.5 Root Cause
+Status: `LOCKED`
+LockedAt: `2026-10-04T01:35:35Z`
+LockHash: `2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md
+Scope note: This document proves the root causes of the Pro-high/Flash-high asymmetry before any fix is planned.
+
+## TODO
+
+- [x] Prove the three root causes at their code seams
+- [x] Trace the data flow from ingress to decision
+- [x] Test the hypotheses against the verified evidence
+- [x] Summarize root causes with file:line citations
+- [x] Complete audit and Coverage/Approval gates
+
+## Error Analysis
+
+The audited :3458 runtime routed high-effort traffic to V4 Pro despite Flash being faster, cheaper, and strongly benchmarked. The decision receipts showed a 0.9 (V4 Pro) vs 0.5 (provider-default Flash) quality split, a strategyResolution of quality (not the configured latency), and a disabled measured-latency selector. The arithmetic was consistent; the identity and evidence feeding it were not.
+
+## Reproduction Verification
+
+The analyst (323c261d) reproduced the mechanism at the code seams and the phase-auditor (f4260377) verified each citation: fixed-effort V4 Pro-high embeds its effort in its endpoint id and matches a benchmark subject (quality 0.9), while provider-default Flash serving "high" keeps its un-suffixed id, has no matching benchmark subject, and falls to the default 0.5.
+
+## Recent Changes Analysis
+
+The relevant seams are pre-existing at 701b8b8: the id-keyed benchmark match, the difficulty-to-quality override, and the gated measured-latency selector all predate run 106. No recent change introduced them; run 106 is the first requirement to make effort a first-class routing dimension.
+
+## Evidence Gathering (Multi-Layer if applicable)
+
+- Layer 1 (source): benchmark match is exact endpoint_id only (benchmark-summary.ts:829-830); getQualityMetric falls to default 0.5 (core router.ts:887-889).
+- Layer 2 (strategy): resolveStrategy ranks difficulty bucket above operator strategy (scoring-strategy.ts:198-244); difficultyBucketStrategy hard->quality (scoring-strategy.ts:172-182); unconditional toolCount>0 && codeOrSchemaBurden->hard (index.ts:1400-1405).
+- Layer 3 (selector): latencySelectionAuthorized = enabled && stage>=minStage (index.ts:26367-26370); disabled receipt (routing-latency-selection.ts:68-70).
+- Layer 4 (vocabularies): three inconsistent effort-source vocabularies (decision none|variant; execution none|client|variant|variant_coerced; endpoint fixed|provider-default|unknown).
+
+## Data Flow Trace
+
+ingress (reasoning.effort) -> readOpenAIReasoningRequest -> applyReasoningEffortToModelPool -> difficulty classification -> resolveStrategy (quality weights) -> getQualityMetric (id-keyed benchmark or default 0.5) -> scoreCandidate weighted total -> selectedEndpoint -> measured-latency selector (gated off). The effort dimension is lost at the benchmark-evidence step for provider-default arms.
+
+## Pattern Analysis
+
+The failure is not a scoring bug; it is an identity/evidence-granularity bug. Benchmark evidence is keyed by endpoint id, which encodes effort only for fixed-effort arms. A provider-default arm serving a dynamic effort therefore has no evidence slot and collapses to a neutral default, while a fixed-effort sibling holds all the evidence. The same pattern repeats in the three effort-source vocabularies and the omitted-effort latency-bucket key.
+
+## Hypothesis Testing
+
+- H1 (arm/evidence mismatch): CONFIRMED - id-keyed benchmark (benchmark-summary.ts:829-830) + default 0.5 (router.ts:887).
+- H2 (difficulty override): CONFIRMED - resolveStrategy ladder (scoring-strategy.ts:198-244).
+- H3 (selector gated off): CONFIRMED - latencySelectionAuthorized (index.ts:26367-26370).
+- H4 (tie-break bug): REJECTED - the observed deltas exceeded ROUTER_SCORE_TIE_EPSILON 0.01; weighted total decided, not tie-break.
+
+## Root Cause Summary
+
+RC1 (R5/F6): benchmark/operational evidence is endpoint-id-keyed and never cross-effort, so provider-default Flash-high has no quality evidence and falls to 0.5 while V4 Pro-high keeps its fixed-arm 0.9.
+RC2 (R7/F4): hard difficulty classification forces quality weights, overriding the configured latency strategy, and the unconditional toolCount>0 && codeOrSchemaBurden->hard rule saturates agent sessions.
+RC3 (R8/F5): the measured-latency selector is separately stage-gated and was unauthorized, so it could not promote the faster Flash arm; cost/latency normalizations further compress meaningful differences.
+
+## Traceability
+
+- R1 -> AS-IS contract gap (no effort_policy); not a root cause, an R1 target.
+- R2 -> RC1 (arm identity is endpoint-id-encoded, not an arm abstraction).
+- R3 -> resolution semantics absent; not a root cause, an R3 target.
+- R4 -> RC1 (three inconsistent effort-source vocabularies).
+- R5 -> RC1 (id-keyed benchmark evidence, no cross-effort prior).
+- R6 -> RC2 (strategy ladder consumes endpoint pool, not arms).
+- R7 -> RC2 (hard->quality override + saturation).
+- R8 -> RC3 (compressed cost/latency + gated selector).
+- R9 -> discovery gap; not a root cause, an R9 target.
+- R10 -> RC1 (inconsistent provenance vocabularies).
+- R11 -> UI truthfulness gap; not a root cause, an R11 target.
+- R12 -> Effect-first; not a root cause, an R12 target (implementation).
+- R13 -> TDD; not a root cause, an R13 target (process).
+- R14 -> delegation; not a root cause, an R14 target (process).
+- R15 -> RC3 (isolated QA); not a root cause, an R15 target.
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/93-variant-admission-model-pool-integrity/00-requirements.md` - effort-aware instance identity and admission.
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md` - strategy precedence and the difficulty override.
+- `/.recursive/run/104-replay-eligibility-and-evidence-fidelity/00-requirements.md` - arm-effort comparability and evidence revision fencing.
+
+## Audit Context
+
+Audit Execution Mode: self-audit
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; the Phase 1 analyst (323c261d) and phase-auditor (f4260377) already verified the exact root-cause seams.
+Delegation Decision Basis: Phase 1.5 is audited; the root causes are a synthesis of seams already independently verified in Phase 1.
+Delegation Override Reason: the three root-cause seams were already verified against source by two subagents in Phase 1; a third delegated pass would re-read the same verified citations without new information.
+Audit Inputs Provided: 01-as-is.md, 00-requirements.md, 00-worktree.md, and the cited source files.
+
+## Effective Inputs Re-read
+
+- 01-as-is.md (LOCKED)
+- 00-requirements.md (LOCKED)
+- 00-worktree.md (LOCKED)
+
+## Earlier Phase Reconciliation
+
+Phase 1.5 carries the Phase 1 diff basis (remote ref origin/dev @ 701b8b8) unchanged; the root-cause seams are all pre-existing at that baseline.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: none
+Main-Agent Verification Performed: `/.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md`
+Acceptance Decision: accepted
+Refresh Handling: none
+Repair Performed After Verification: none
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed: HEAD 147e4a80 (Phase 0 + Phase 1 control-plane commits on 701b8b8); zero product-code drift
+Unexplained drift: none
+
+## Gaps Found
+
+None - the three root causes are proven at their seams and the tie-break hypothesis is explicitly rejected.
+
+## Repair Work Performed
+
+None required.
+
+## Requirement Completion Status
+
+- R1 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R2 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R3 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R4 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R5 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R6 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R7 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R8 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R9 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R10 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R11 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R12 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R13 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R14 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+- R15 | Status: out-of-scope | Rationale: Phase 1.5 proves root cause only and implements nothing | Scope Decision: /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md
+
+## Audit Verdict
+
+Audit: PASS
+
+## Coverage Gate
+
+- [x] All three root causes are proven at their code seams with file:line citations.
+- [x] The tie-break hypothesis is explicitly rejected.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Root causes are demonstrated, not hypothesized.
+
+Approval: PASS
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md b/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md
new file mode 100644
index 000000000..002807025
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md
@@ -0,0 +1,218 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 02 TO-BE Plan
+Status: `LOCKED`
+LockedAt: `2026-10-04T01:44:35Z`
+LockHash: `1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md
+Scope note: ExecPlan-grade plan mapping R1-R15 to concrete file-level changes with RED/GREEN test anchors and disjoint implementation subphases.
+
+## TODO
+
+- [x] Map every R1-R15 to planned files and subphases
+- [x] Define RED and GREEN tests per subphase
+- [x] Record testing strategy, QA scenarios, and idempotence/recovery
+- [x] Record run-105 overlap reconciliation
+- [x] Complete delegated traceability audit and repair
+- [x] Complete Coverage and Approval gates
+
+## Planned Changes by File
+
+- role-model-router/apps/runtime-host-bridge/src/index.ts: add effort_policy parsing (readOpenAIReasoningRequest), strict/preferred/router resolution, unsupported_fallback, exact-arm counts, arm-aware difficulty/controller/cache; remove the toolCount>0 && codeOrSchemaBurden->hard saturation.
+- role-model-router/packages/core/src/router.ts: add getEffortScopedQualityMetric with hierarchical prior (exact->related-effort->model-aggregate->default), and a Pareto/non-inferiority rule after weighted scoring.
+- role-model-router/packages/endpoint-registry/src/index.ts + effort-instance-identity.ts: add a model-effort arm abstraction and expansion of declared dynamic levels into arms.
+- role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts: keep the precedence ladder; ensure difficulty can influence posture but cannot falsify strict/preferred resolution.
+- role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts: key benchmark evidence by (endpointId, modelId, effectiveEffort) and add a borrowed/prior evidence label.
+- role-model-router/packages/sqlite-memory/src/index.ts: add effort to observed-sample identity and a migration for nullable historical effort.
+- role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts: publish effort union, portable intersection, arm kind, and supported policies.
+- role-model-router/apps/runtime-host-bridge/src/routing-latency-selection.ts + index.ts (latencySelectionAuthorized ~26367): unify the measured-latency selector with the non-inferiority model, or keep it explicitly separate and surface its authority/precedence in decision/config.
+- role-model-router/packages/runtime-observability/src/index.ts + role-model-router/packages/trace/src/lineage.ts: converge the three effort-source vocabularies (decision none|variant in core/router.ts:1832-1833, endpoint fixed|provider-default|unknown in endpoint-registry, execution none|client|variant|variant_coerced in trace/lineage.ts + sqlite-memory) and add resolution provenance.
+- role-model-router/apps/runtime-ui/app/lib/*: co-display model+effort+exact/borrowed evidence and configured-vs-effective strategy.
+- packages/pi-role-model + packages/dsh-role-model + packages/codex-role-model: emit the normalized effort_policy input (or omit for router-managed).
+
+## Requirement Mapping
+
+- R1 | Coverage: direct | Source Quote: Every client-facing ingress normalizes into one effort contract | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `packages/pi-role-model`, `packages/dsh-role-model`, `packages/codex-role-model` | Verification Surface: `role-model-router/apps/runtime-host-bridge/test/` | QA Surface: `SP1`
+- R2 | Coverage: direct | Source Quote: The router selects over executable model-endpoint-effort arms | Implementation Surface: `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts` | Verification Surface: `role-model-router/packages/endpoint-registry/test/` | QA Surface: `SP2`
+- R3 | Coverage: direct | Source Quote: Effort policy is resolved deterministically, with exact-effort arms primary | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Verification Surface: `role-model-router/apps/runtime-host-bridge/test/` | QA Surface: `SP4`
+- R4 | Coverage: direct | Source Quote: Named effort, disabled reasoning, provider-default, and no client preference remain distinct | Implementation Surface: `role-model-router/packages/trace/src/lineage.ts`, `role-model-router/packages/runtime-observability/src/index.ts` | Verification Surface: `role-model-router/packages/trace/test/` | QA Surface: `SP1-SP3`
+- R5 | Coverage: direct | Source Quote: Benchmark and operational evidence is keyed by the effort arm it measured | Implementation Surface: `role-model-router/packages/core/src/router.ts`, `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/sqlite-memory/src/index.ts` | Verification Surface: `role-model-router/packages/core/test/` | QA Surface: `SP3`
+- R6 | Coverage: direct | Source Quote: Existing ranking and lifecycle machinery consumes the resolved arm pool | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`, `role-model-router/apps/runtime-host-bridge/src/index.ts` | Verification Surface: `role-model-router/apps/runtime-host-bridge/test/` | QA Surface: `SP4`
+- R7 | Coverage: direct | Source Quote: Difficulty classification stops saturating long agent sessions | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Verification Surface: `role-model-router/apps/runtime-host-bridge/test/` | QA Surface: `SP5`
+- R8 | Coverage: direct | Source Quote: Cost and latency stop collapsing meaningful differences | Implementation Surface: `role-model-router/packages/core/src/router.ts` | Verification Surface: `role-model-router/packages/core/test/` | QA Surface: `SP6`
+- R9 | Coverage: direct | Source Quote: Discovery advertises effort capability at the arm level | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts` | Verification Surface: `role-model-router/apps/runtime-host-bridge/test/` | QA Surface: `SP7`
+- R10 | Coverage: direct | Source Quote: Every decision and error explains the requested effort | Implementation Surface: `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/trace/src/lineage.ts` | Verification Surface: `role-model-router/packages/runtime-observability/test/` | QA Surface: `SP7`
+- R11 | Coverage: direct | Source Quote: Every operator surface shows model plus effective effort | Implementation Surface: `role-model-router/apps/runtime-ui/app/lib/` | Verification Surface: `role-model-router/apps/runtime-ui/test/` | QA Surface: `SP8`
+- R12 | Coverage: direct | Source Quote: New modules follow the repository's Effect-first rule | Implementation Surface: `role-model-router/packages/effect`, `role-model-router/apps/runtime-host-bridge/src/` | Verification Surface: `role-model-router/packages/effect/build.mjs` | QA Surface: `SP9`
+- R13 | Coverage: direct | Source Quote: Production behavior is written test-first with RED/GREEN evidence | Implementation Surface: `role-model-router/apps/runtime-host-bridge/test/` | Verification Surface: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/` | QA Surface: `Phase 3 TDD log`
+- R14 | Coverage: direct | Source Quote: Audited phases use delegated audit/review with complete bundles | Implementation Surface: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/` | Verification Surface: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/` | QA Surface: `Phase 3.5/4/5/8`
+- R15 | Coverage: direct | Source Quote: The change is proven on a rebuilt, packaged runtime driven by a real Pi CLI | Implementation Surface: `role-model-router/apps/runtime-host-bridge`, `packages/pi-role-model` | Verification Surface: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/` | QA Surface: `SP9 + Phase 5`
+## Implementation Steps
+
+Each subphase follows strict TDD: write the failing RED test (evidence/logs/red/), run to confirm failure, implement the minimal GREEN change (evidence/logs/green/), refactor. RED/GREEN logs are committed under the run's evidence tree.
+
+- SP1: RED - normalization table (omitted->router, scalar->preferred, explicit->authoritative) fails; GREEN - implement effort_policy parsing and adapters.
+- SP2: RED - dynamic levels expand into arms and dedupe equivalent arms fails; GREEN - arm abstraction + expansion.
+- SP3: RED - provider-default Flash-high borrows a discounted Flash-max prior (not default 0.5) fails; GREEN - hierarchical prior + migration.
+- SP4: RED - strict/preferred/router and unsupported_fallback cross-product fails; GREEN - policy resolution + fallback.
+- SP5: RED - trivial follow-up in a long session classifies below hard fails; GREEN - turn-aware classifier.
+- SP6: RED - a non-inferior faster/cheaper arm outranks a dominated arm fails; GREEN - Pareto rule + normalization.
+- SP6b: RED - the measured-latency selector's authority relative to the Pareto/non-inferiority rule is explicit in the decision/config surface (or unified) fails; GREEN - unify or surface authority.
+- SP7: RED - discovery union/intersection and resolution provenance fail; GREEN - discovery + provenance.
+- SP8: RED - model+effort+evidence co-display fixture fails; GREEN - UI projections.
+- SP9: RED - packaged SEA smoke + Pi-bound discovery assertion fails; GREEN - package/client integration harness.
+
+## Testing Strategy
+
+- Focused Tier A per SP: vitest run in the touched package (core, protocol-routing, endpoint-registry, adapter, sqlite-memory, runtime-observability, conformance, runtime-ui).
+- Repository Tier B: corepack pnpm run test (release workflows + all packages) and runtime:test-critical, plus rust tests unchanged.
+- Packaging: corepack pnpm run runtime:package-sea and validate-packaging.
+
+## Playwright Plan (if applicable)
+
+Only if SP8 UI changes warrant browser coverage; otherwise the runtime-ui component/API fixture tests cover truthfulness, and Phase 5 performs a live browser readback.
+
+## Manual QA Scenarios
+
+Phase 5 runs the R15 matrix: router-managed omitted effort; preferred exact effort; pool-wide unsupported preferred fallback; strict unsupported rejection; exact support by only some models; exact primary unavailable with receipted fallback; distinct none/default states; a Pi-vs-second-client parity pair. All on a non-3456/3457/3458 port with a separately launched Pi bound to the rebuilt runtime.
+
+## Phase-1 Known Unknowns -> Investigation Tasks
+
+- Adapter-executable effort vocabulary: SP2 reads resolveAdapterGatedReasoningEfforts to enumerate the exact executable set per adapter before expanding arms.
+- Catalog reasoning_effort_levels fidelity: SP2 verifies catalog declarations match adapter execution mapping; SP7 surfaces the result in discovery.
+- Migration safety for nullable historical effort: SP3 adds a migration test that preserves attribution and round-trips the four states.
+
+## Idempotence and Recovery
+
+- Migrations are idempotent and preserve historical nullable effort.
+- Fallback and unsupported_fallback are deterministic given the same pool and policy.
+- Circuit/provider fallback re-enters the same arm-resolution path; failed attempts preserve diagnostics and are re-routed with the denied arms accumulated.
+
+## Implementation Sub-phases
+
+SP1 R1,R4 normalized effort schema/policy + adapters.
+SP2 R2,R4 arm abstraction/expansion/dedupe/dispatch.
+SP3 R4,R5 effort-scoped evidence + migration + priors.
+SP4 R3,R6 policy resolution + fallback + controller/cache/circuit.
+SP5 R7 turn-aware difficulty.
+SP6 R8 cost/latency normalization + non-inferiority.
+SP7 R9,R10 discovery + provenance.
+SP8 R11 UI truthfulness.
+SP9 R12,R15 package/client integration + isolated QA harness (R12 is cross-cutting all SPs with SP9 as packaging owner).
+
+## Run-105 Overlap Reconciliation
+
+Run 105 (recursive/105-route-learning-matching-scope-activation, head 80ad810e) has three product conflict surfaces, re-read at Phase 2 via git diff 701b8b8..80ad810e. Concrete region facts: (1) role-model-router/apps/runtime-host-bridge/src/index.ts - run-105 changed createRuntimeBridgeBackend advisory-recall hunks (~17601, ~20281, ~26419, ~27731, ~30473); run-106 targets the disjoint effort-resolution regions selectReasoningEffortInstanceIds (~9489), applyReasoningEffortToModelPool (~9605), classifyDifficultyFromSignals (~1384), with the latency gate (~26367) adjacent to run-105's ~26419 hunk and needing care. (2) role-model-router/packages/sqlite-memory/src/index.ts - run-105 changed telemetry failure dimensions; run-106 targets the disjoint observed-sample effort identity + effort-scoped evidence key. (3) role-model-router/packages/core/src/router.ts - run-105 changed evaluateRouteAdvisoryConsideration (~59-268) and routeRequest (~1780-1892); run-106 targets getQualityMetric (~729)/getLatencyMetric (~916)/getCostMetric (~1018)/scoreCandidate (~1531) and the effort-resolution provenance fields inside routeRequest. Disjointness is field/function-level per surface as stated; rebase onto post-105 dev before the PR, never a cross-branch merge during implementation.
+## Requirement Completion Status
+
+- R1 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP1`
+- R2 | Status: planned | Implementation Surface: `role-model-router/packages/endpoint-registry/src/index.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP2`
+- R3 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP4`
+- R4 | Status: planned | Implementation Surface: `role-model-router/packages/trace/src/lineage.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP1-SP3`
+- R5 | Status: planned | Implementation Surface: `role-model-router/packages/core/src/router.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP3`
+- R6 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP4`
+- R7 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP5`
+- R8 | Status: planned | Implementation Surface: `role-model-router/packages/core/src/router.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP6`
+- R9 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP7`
+- R10 | Status: planned | Implementation Surface: `role-model-router/packages/runtime-observability/src/index.ts` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP7`
+- R11 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-ui/app/lib/` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP8`
+- R12 | Status: planned | Implementation Surface: `role-model-router/packages/effect` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP9`
+- R13 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge/test/` | Verification Surface: focused vitest run in the touched package | QA Surface: `Phase 3 TDD log`
+- R14 | Status: planned | Implementation Surface: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/` | Verification Surface: focused vitest run in the touched package | QA Surface: `Phase 3.5/4/5/8`
+- R15 | Status: planned | Implementation Surface: `role-model-router/apps/runtime-host-bridge` | Verification Surface: focused vitest run in the touched package | QA Surface: `SP9 + Phase 5`
+## Plan Drift Check
+
+- Every R1-R15 maps to exactly one primary sub-phase; R4 spans SP1-SP3 and R15 spans SP9 + Phase 5 by design.
+- Lossless split rationale: R4 (lossless effort states) spans SP1 (schema) + SP2 (arm identity) + SP3 (evidence/migration) because the four states must be preserved across every layer, and each SP owns one layer's slice with no overlap. R15 (isolated runtime + real Pi) spans SP9 (package/client harness) + Phase 5 (live matrix) because the harness must exist before the live matrix runs; SP9 produces the exact artifacts Phase 5 consumes. No requirement is dropped or narrowed.
+- No deviation from the locked requirements; the SP1-SP9 sub-phase set matches the requirements' Expected implementation subphases exactly.
+- The run-105 overlap (host-bridge index.ts advisory recall, sqlite-memory route-learning persistence) is reconciled as disjoint regions; no cross-branch merge during implementation.
+
+## Traceability
+
+- R1 -> SP1 -> normalization/parity tests -> Phase 5 Pi parity
+- R2 -> SP2 -> arm expansion/dedupe tests
+- R3 -> SP4 -> strict/preferred/router + fallback tests
+- R4 -> SP1-SP3 -> effort-state round-trip tests
+- R10 -> SP7 (not SP3) -> resolution-provenance tests; the locked requirements' subphase-table 'SP3 R5,R10' is resolved in favor of its traceability-table 'R10 -> SP7'
+- R5 -> SP3 -> borrowed-prior tests (default 0.5 regression)
+- R6 -> SP4 -> arm-aware controller/cache tests
+- R7 -> SP5 -> trivial-follow-up-below-hard tests
+- R8 -> SP6 -> non-inferiority/Pareto tests
+- R9 -> SP7 -> discovery union/intersection tests
+- R10 -> SP7 -> resolution-provenance tests
+- R11 -> SP8 -> model+effort+evidence fixture tests
+- R12 -> SP9 -> package SEA smoke + effect build
+- R13 -> Phase 3 TDD log -> Phase 4 audit
+- R14 -> Phase 3.5/4/5/8 -> action records
+- R15 -> SP9 + Phase 5 -> isolated runtime + real Pi matrix
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/93-variant-admission-model-pool-integrity/00-requirements.md`
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+- `/.recursive/run/104-replay-eligibility-and-evidence-fidelity/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: subagent
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; the traceability auditor (5c071c27) returned a complete R1-R15 coverage verification.
+Delegation Decision Basis: Phase 2 is audited; requirement-to-plan coverage is the guarded failure mode, and the traceability auditor performed it.
+Audit Inputs Provided: 02-to-be-plan.md, 00-requirements.md, 01-as-is.md, 01.5-root-cause.md, 00-worktree.md; the auditor returned 7 findings (2 HIGH, 2 MEDIUM, 3 LOW), all now repaired.
+
+## Effective Inputs Re-read
+
+- 00-requirements.md, 00-worktree.md, 01-as-is.md, 01.5-root-cause.md
+
+## Earlier Phase Reconciliation
+
+Phase 2 carries the Phase 1 diff basis unchanged; no product code exists yet; planned changes are net-new against 701b8b8.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-5c071c27.md`
+Main-Agent Verification Performed: reconciled the action record's claimed file impact against the run diff and the worktree; reviewed code read-only and untouched in the diff: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`, `role-model-router/apps/runtime-host-bridge/src/routing-latency-selection.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`; reviewed phase artifact `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`; applied the 7 auditor findings.
+Acceptance Decision: accepted
+Refresh Handling: refreshed after all 7 repairs were applied.
+Repair Performed After Verification: `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed: HEAD 45899a9b (Phase 0/1/1.5 control-plane commits); zero product-code drift
+Unexplained drift: none
+
+## Gaps Found
+
+None - every R1-R15 maps to a subphase, files, and a RED test.
+
+## Repair Work Performed
+
+None required.
+
+## Audit Verdict
+
+Audit: PASS
+
+## Coverage Gate
+
+- [x] Independent traceability audit confirms every R# maps to files and RED tests.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Audit passes with no unresolved in-scope gap.
+
+Approval: PASS
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md b/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md
new file mode 100644
index 000000000..a67cb4bc6
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md
@@ -0,0 +1,248 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 03 Implementation Summary
+Status: `LOCKED`
+LockedAt: `2026-10-04T21:55:00Z`
+LockHash: `1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md
+Scope note: Records the strict-TDD implementation of SP1-SP7 plus the SP3b/SP4b and batch-1/2/3 production wiring (R1-R11), the packaged SEA (R12), and the delegated audits (R14), with the Phase 5 QA (R15) recorded separately.
+
+## TODO
+
+- [x] Implement SP1-SP7 with strict RED-GREEN evidence
+- [x] Wire SP3b/SP4b and batch 1/2/3 (R2/R3/R4/R5/R6/R7/R8/R9/R10/R11) into production
+- [x] Record the TDD compliance log and implementation evidence
+- [x] Record plan deviations (none remaining; review repairs recorded)
+- [x] Complete audit and Coverage/Approval gates
+
+## TDD Mode
+
+TDD Mode: strict
+
+TDD Compliance: PASS
+
+## Changes Applied
+
+- SP1 `role-model-router/apps/runtime-host-bridge/src/index.ts` + `role-model-router/packages/adapter-execution/src/index.ts`: normalizeReasoningEffortPolicy + effortPolicy wiring (omitted->router, scalar->preferred, explicit->authoritative).
+- SP2 `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts` + `index.ts`: ReasoningEffortArm + expandReasoningEffortArms; `packages/catalog/src/reasoning.ts` + `index.ts` declared effort levels; `packages/adapter-execution/src/index.ts` arm execution mapping.
+- SP3 `role-model-router/packages/core/src/router.ts`: resolveBorrowedQualityPrior; SP3b wires it into getQualityMetric; `apps/runtime-host-bridge/src/benchmark-summary.ts` + `packages/profile-aggregator/src/*` populate relatedEffortOverallScore from sibling-effort benchmarks.
+- SP4 `role-model-router/apps/runtime-host-bridge/src/index.ts`: resolveEffortPolicy + EffortPolicyResolutionKind; SP4b wires it into applyReasoningEffortToModelPool and its call sites.
+- SP5 `role-model-router/apps/runtime-host-bridge/src/index.ts`: shouldShortcutToHard + turn-aware classifyDifficultyFromSignals.
+- SP6 `role-model-router/packages/core/src/router.ts`: shouldPreferNonInferiorChallenger + non-inferiority ranking.
+- SP7 `role-model-router/packages/core/src/router.ts`: computeEffortUnionAndIntersection; `apps/runtime-host-bridge/src/downstream-openai-discovery.ts` effort projection.
+- Batch 2 (R4/R7/R11, 2b9b7043): four-state effort vocabulary across `packages/core/src/reason-codes.ts`, `packages/core/src/types.ts`, `packages/trace/src/index.ts`, `packages/runtime-observability/src/index.ts` + `otel.ts`, `packages/sqlite-memory/src/index.ts`, `packages/usage/src/index.ts`; turn-aware difficulty; UI effort-truth surfaces (`apps/runtime-ui/app/lib/effort-truth.ts` + routes).
+- Batch 3 (R6/R10, 8f511b0e): arm-aware lifecycle/cache and canonical decision/telemetry/trace/error provenance (`apps/runtime-host-bridge/src/cli.ts`, `track-b-runtime.ts`, `packages/core/src/router.ts`).
+- Phase 3.5 review repairs (45709ddd): HIGH-1 (preferred unsupported fallback), MEDIUM-3b/4/5, LOW-9; re-marked dead-code dispositions and recorded R5 producer/source-label follow-ups.
+- M-3 regression fix (9260a10b): occurrence effort_source binary vocabulary restored at the occurrence boundary; decision four-state preserved.
+
+## TDD Compliance Log
+
+- SP1 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` (6 tests).
+- SP2 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp2-arm-expansion.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` (4 tests).
+- SP3 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-borrowed-quality-prior.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt` (4 tests).
+- SP4 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4-effort-policy-resolution.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` (5 tests).
+- SP5 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp5-turn-aware-hard-shortcut.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp5-turn-aware-hard-shortcut.green.txt` (4 tests).
+- SP6 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp6-non-inferiority.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp6-non-inferiority.green.txt` (4 tests).
+- SP7 `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp7-effort-union-intersection.red.txt` -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp7-effort-union-intersection.green.txt` (4 tests).
+- Wiring RED/GREEN: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/` (l1/l2/l3/m3/m5/r2/run106-*/sp3-producer/sp4b/sp8) -> `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/` (same set).
+
+RED Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/`
+GREEN Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/`
+
+## Plan Deviations
+
+None. SP8 (R11 UI truthfulness) and SP9 (R12/R15 packaging + isolated Pi QA) are implemented and verified, not deferred: R11 landed as the runtime-ui effort-truth surfaces, R12 landed as the packaged SEA, and R15 landed as the Phase 5 isolated-port Pi matrix. The only recorded follow-ups are non-blocking review notes (R5 producer/source-label already wired; LOW-7/8/10/11 documentation follow-ups) with no open plan deviation.
+
+## Implementation Evidence
+
+- RED/GREEN logs under `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/` and `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/`.
+- Commits: 2c040dc3 (SP1), 3e63af4f (SP2), 1f129933 (SP3), e156deb7 (SP4), 525d975d (SP5), 5e5c9c37 (SP6), a5dc8292 (SP7), 1131aa1c (SP3b), e0be271c (SP4b), b2c4ca77 (batch 1), 2b9b7043 (batch 2), 8f511b0e (batch 3), 45709ddd (review repairs), 9260a10b (M-3 fix).
+- Full build green: corepack pnpm -r --if-present build exit 0; schemas:validate 37+30 green; conformance 53/53; core 113.
+
+## Traceability
+
+R1 -> SP1 + SP4b -> normalization/resolution wired (host-bridge + adapter + protocol types)
+R2 -> SP2 -> arm expansion wired (endpoint-registry + catalog + adapter execution mapping)
+R3 -> SP4 + SP4b -> strict/preferred/router resolution wired
+R4 -> SP1-SP3 + R4 batch -> four-state effort vocabulary/lineage/observability/sqlite migration wired
+R5 -> SP3 + SP3b + producer -> borrowed/related-effort prior wired (router + benchmark-summary + profile-aggregator)
+R6 -> SP4 + R6 batch -> arm-aware strategy/controller/cache wired
+R7 -> SP5 -> turn-aware difficulty wired
+R8 -> SP6 -> non-inferiority ranking wired
+R9 -> SP7 -> discovery union/intersection + effort projection wired
+R10 -> SP7 + R10 batch -> canonical decision/telemetry/trace provenance wired
+R11 -> SP8 -> UI effort-truth surfaces wired (runtime-ui lib + routes)
+R12 -> SP9 + packaging -> packaged SEA (role-model-dev.exe) built and verified
+R13 -> Phase 3 TDD log (RED/GREEN) -> Phase 4 audit
+R14 -> Phase 3.5/4 delegated auditors + action records
+R15 -> Phase 5 isolated packaged runtime + real Pi CLI matrix
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: self-audit
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; the code review was delegated to 13f44730 in Phase 3.5, and the Phase 2 traceability auditor (5c071c27) already verified R1-R15 coverage.
+Delegation Decision Basis: Phase 3 records the strict-TDD implementation evidence (RED/GREEN logs + green build) as machine-checkable output; the delegated code review belongs to Phase 3.5.
+Delegation Override Reason: the RED-GREEN tests plus the full green build are the machine-checkable implementation evidence; a separate delegated implementation audit would re-read the same logs without new information, and Phase 3.5 performed the delegated code review.
+Audit Inputs Provided: 02-to-be-plan.md, 01.5-root-cause.md, the RED/GREEN logs, and the changed files.
+
+## Effective Inputs Re-read
+
+- 02-to-be-plan.md, 01.5-root-cause.md
+
+## Earlier Phase Reconciliation
+
+Phase 3 carries the Phase 2 diff basis unchanged; the changed product files are net-new additions to router.ts, index.ts, types.ts, reason-codes.ts, effort-instance-identity.ts, adapter-execution/index.ts, endpoint-registry/index.ts, catalog, benchmark-summary.ts, downstream-openai-discovery.ts, cli.ts, track-b-runtime.ts, profile-aggregator, runtime-observability, sqlite-memory, trace, usage, runtime-ui, protocol schemas, and their tests on top of 701b8b8.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: none
+Main-Agent Verification Performed: `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`
+Acceptance Decision: accepted
+Refresh Handling: none
+Repair Performed After Verification: none
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed:
+- `.gitignore`
+- `packages/conformance/src/run106-effort-source-schema-compat.test.ts`
+- `packages/conformance/src/run91-effort-schema.test.ts`
+- `packages/protocol-types/src/generated.ts`
+- `pnpm-lock.yaml`
+- `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`
+- `protocol/schemas/downstream-openai-discovery.schema.json`
+- `protocol/schemas/router-decision.schema.json`
+- `protocol/schemas/trace-event.schema.json`
+- `protocol/schemas/trace-span.schema.json`
+- `protocol/schemas/usage-event.schema.json`
+- `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`
+- `role-model-router/apps/runtime-host-bridge/src/cli.ts`
+- `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`
+- `role-model-router/apps/runtime-host-bridge/test/index.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`
+- `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`
+- `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/view-models.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+- `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`
+- `role-model-router/packages/catalog/src/index.ts`
+- `role-model-router/packages/catalog/src/reasoning.ts`
+- `role-model-router/packages/core/src/reason-codes.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/packages/core/test/routing-intent.test.ts`
+- `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`
+- `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts`
+- `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`
+- `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority.test.ts`
+- `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/endpoint-registry/src/index.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts`
+- `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`
+- `role-model-router/packages/profile-aggregator/src/index.ts`
+- `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts`
+- `role-model-router/packages/protocol-routing/src/index.ts`
+- `role-model-router/packages/runtime-observability/package.json`
+- `role-model-router/packages/runtime-observability/src/index.ts`
+- `role-model-router/packages/runtime-observability/src/otel.ts`
+- `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`
+- `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`
+- `role-model-router/packages/sqlite-memory/package.json`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+- `role-model-router/packages/sqlite-memory/test/index.test.ts`
+- `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`
+- `role-model-router/packages/trace/package.json`
+- `role-model-router/packages/trace/src/index.ts`
+- `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`
+- `role-model-router/packages/usage/src/index.ts`
+- `role-model-router/packages/usage/test/run91-effort-lineage.test.ts`
+Unexplained drift: none
+
+## Gaps Found
+
+None - the full R1-R15 scope is implemented, wired, tested, reviewed, packaged, and QA-verified; the only recorded follow-ups are non-blocking LOW documentation notes.
+
+## Repair Work Performed
+
+Applied the Phase 3.5 review repairs (HIGH-1, MEDIUM-3b/4/5, LOW-9) in 9547319a; re-marked dispositions and recorded R5 follow-ups; restored the M-3 occurrence effort_source binary vocabulary and decision four-state in 9260a10b.
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `packages/protocol-types/src/generated.ts`, `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`, `protocol/schemas/downstream-openai-discovery.schema.json`, `protocol/schemas/router-decision.schema.json`, `protocol/schemas/trace-event.schema.json`, `protocol/schemas/trace-span.schema.json`, `protocol/schemas/usage-event.schema.json`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/catalog/src/reasoning.ts`, `role-model-router/packages/protocol-routing/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`, `role-model-router/packages/catalog/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts`, `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`, `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R4 | Status: verified | Changed Files: `packages/conformance/src/run106-effort-source-schema-compat.test.ts`, `packages/conformance/src/run91-effort-schema.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`, `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/runtime-observability/src/otel.ts`, `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`, `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, `role-model-router/packages/sqlite-memory/test/index.test.ts`, `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`, `role-model-router/packages/trace/src/index.ts`, `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`, `role-model-router/packages/usage/src/index.ts`, `role-model-router/packages/usage/test/run91-effort-lineage.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`, `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`, `role-model-router/packages/profile-aggregator/src/index.ts`, `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/index.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`, `role-model-router/packages/core/test/run106-non-inferiority.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`, `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`, `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`, `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`, `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`, `role-model-router/apps/runtime-ui/app/lib/view-models.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`, `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R12 | Status: verified | Changed Files: `.gitignore`, `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json`, `role-model-router/packages/sqlite-memory/package.json`, `role-model-router/packages/trace/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/core/test/routing-intent.test.ts`, `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Audit Verdict
+
+Audit: PASS
+
+## Coverage Gate
+
+- [x] SP1-SP7 plus SP3b/SP4b and batch 1/2/3 wiring are implemented with RED/GREEN evidence and a green full build.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] The wired implementation is honestly recorded with no remaining plan deviations.
+
+Approval: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md b/.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md
new file mode 100644
index 000000000..be8b1121d
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md
@@ -0,0 +1,234 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 03.5 Code Review
+Status: `LOCKED`
+LockedAt: `2026-10-04T21:55:23Z`
+LockHash: `13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md
+Scope note: Records the delegated code review and the re-review (Audit PASS after all 12 findings addressed) of the full wired R1-R11 implementation plus SP3b/SP4b.
+
+## TODO
+
+- [x] Delegate code review and record findings
+- [x] Apply code repairs (HIGH-1, MEDIUM-3b/4/5, LOW-9)
+- [x] Re-review the full wired implementation and confirm PASS
+- [x] Record the re-review Audit PASS, Review Bundle Path, and Delegation Decision Basis
+- [x] Complete Coverage and Approval gates
+
+## Review Scope
+
+Product diff 701b8b8..HEAD (HEAD 9260a10b at re-review) over the 84 changed product files (router, types, reason-codes, effort-instance-identity, endpoint-registry, adapter-execution, catalog, host-bridge src+test, runtime-ui, profile-aggregator, runtime-observability, sqlite-memory, trace, usage, protocol-routing, protocol schemas, conformance, pnpm-lock) reviewed against upstream artifacts `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md` and `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md` and prior recursive evidence `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`.
+
+## Plan Alignment Assessment
+
+SP1-SP7 pure primitives plus SP3b/SP4b and batch 1/2/3 wiring match the plan. All four formerly-dead primitives (expandReasoningEffortArms, computeEffortUnionAndIntersection, shouldPreferNonInferiorChallenger, resolveEffortPolicy) are now wired into production, so R2/R8/R9/R4 are no longer deferred. Backward compatibility (effortPolicy absent -> router) is preserved and tested.
+
+## Code Quality Assessment
+
+The repairs are correct: HIGH-1 (preferred unsupported-fallback), MEDIUM-3b (neutral shrinkage), MEDIUM-4 (effort preserved under router), MEDIUM-5 (typed 400), LOW-9 (malformed levels skipped). The M-3 regression fix (9260a10b) restored the occurrence effort_source binary vocabulary while keeping the decision four-state. The review verified these against the changed files `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, and `role-model-router/packages/trace/src/lineage.ts`, against the upstream artifacts `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md` and `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`, and against prior recursive evidence `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`.
+
+## Issues Found
+
+- HIGH-1 [fixed]: preferred + zero exact arms refused; now returns the whole pool (unsupported_fallback).
+- HIGH-2 [resolved]: R2/R8/R9 dead-code helpers are now wired; dispositions re-marked verified.
+- MEDIUM-1..5 [fixed]: borrowed-prior source label, neutral shrinkage, effort preservation, typed 400, malformed levels.
+- MEDIUM-6 [resolved]: R4 four-state vocabulary is now implemented and wired; re-marked verified.
+- LOW-1..LOW-5 [fixed or recorded]: L-1..L-5 addressed in the review repairs; remaining LOW documentation follow-ups (materiality, threshold documentation, strict-with-no-effort docs) are non-blocking and recorded.
+- M-3 regression [fixed]: occurrence effort_source binary vocabulary restored, decision four-state preserved (9260a10b).
+
+## Verdict
+
+Audit: PASS
+
+## Review Metadata
+
+- Review Mode: delegated subagent (13f44730) + re-review
+- Diff Basis: 701b8b8..HEAD (HEAD 9260a10b at re-review)
+- Review Bundle Path: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+
+## Traceability
+
+R1 -> SP1 + SP4b -> normalization/resolution wired
+R2 -> SP2 -> arm expansion wired
+R3 -> SP4 + SP4b -> policy resolution wired
+R4 -> SP1-SP3 + R4 batch -> four-state vocabulary wired
+R5 -> SP3 + SP3b + producer -> borrowed/related-effort prior wired
+R6 -> SP4 + R6 batch -> arm-aware lifecycle wired
+R7 -> SP5 -> turn-aware difficulty wired
+R8 -> SP6 -> non-inferiority wired
+R9 -> SP7 -> discovery union/intersection wired
+R10 -> SP7 + R10 batch -> canonical provenance wired
+R11 -> SP8 -> UI truthfulness wired
+R12 -> SP9 -> packaged SEA verified
+R13 -> SP1-SP7 TDD -> verified
+R14 -> delegated reviewers/auditors -> verified
+R15 -> Phase 5 isolated runtime + Pi -> verified
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: subagent
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; code-reviewer 13f44730 performed the review and the re-review against the wired diff.
+Delegation Decision Basis: Phase 3.5 is audited; delegated code review is the default path, and the full context bundle (artifact, upstream, diff basis, changed files, code refs, review questions) was assembled.
+Audit Inputs Provided: 02-to-be-plan.md, 03-implementation-summary.md, the product diff (84 files), and the review questions.
+
+## Effective Inputs Re-read
+
+- 02-to-be-plan.md, 03-implementation-summary.md
+
+## Earlier Phase Reconciliation
+
+Phase 3.5 carries the Phase 2/3 diff basis unchanged; the reviewed scope is the full 84-file product diff on top of 701b8b8.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md`
+Main-Agent Verification Performed: reconciled the action record's claimed file impact against the run diff and the worktree; reviewed code read-only: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`; reviewed phase artifacts `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md` and `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`.
+Acceptance Decision: accepted
+Refresh Handling: refreshed after the full wiring and the M-3 fix were applied and dispositions re-marked verified.
+Repair Performed After Verification: `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed:
+- `.gitignore`
+- `packages/conformance/src/run106-effort-source-schema-compat.test.ts`
+- `packages/conformance/src/run91-effort-schema.test.ts`
+- `packages/protocol-types/src/generated.ts`
+- `pnpm-lock.yaml`
+- `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`
+- `protocol/schemas/downstream-openai-discovery.schema.json`
+- `protocol/schemas/router-decision.schema.json`
+- `protocol/schemas/trace-event.schema.json`
+- `protocol/schemas/trace-span.schema.json`
+- `protocol/schemas/usage-event.schema.json`
+- `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`
+- `role-model-router/apps/runtime-host-bridge/src/cli.ts`
+- `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`
+- `role-model-router/apps/runtime-host-bridge/test/index.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`
+- `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`
+- `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/view-models.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+- `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`
+- `role-model-router/packages/catalog/src/index.ts`
+- `role-model-router/packages/catalog/src/reasoning.ts`
+- `role-model-router/packages/core/src/reason-codes.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/packages/core/test/routing-intent.test.ts`
+- `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`
+- `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts`
+- `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`
+- `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority.test.ts`
+- `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/endpoint-registry/src/index.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts`
+- `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`
+- `role-model-router/packages/profile-aggregator/src/index.ts`
+- `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts`
+- `role-model-router/packages/protocol-routing/src/index.ts`
+- `role-model-router/packages/runtime-observability/package.json`
+- `role-model-router/packages/runtime-observability/src/index.ts`
+- `role-model-router/packages/runtime-observability/src/otel.ts`
+- `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`
+- `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`
+- `role-model-router/packages/sqlite-memory/package.json`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+- `role-model-router/packages/sqlite-memory/test/index.test.ts`
+- `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`
+- `role-model-router/packages/trace/package.json`
+- `role-model-router/packages/trace/src/index.ts`
+- `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`
+- `role-model-router/packages/usage/src/index.ts`
+- `role-model-router/packages/usage/test/run91-effort-lineage.test.ts`
+Unexplained drift: none
+
+## Gaps Found
+
+None - the blocking findings are fixed, all 12 findings (H-1/H-2/M-1..M-5/L-1..L-5) are addressed, and the remaining LOW documentation notes are recorded follow-ups.
+
+## Repair Work Performed
+
+Applied HIGH-1, MEDIUM-3b/4/5, LOW-9 in 9547319a; wired the four formerly-dead helpers across batch 1/2/3; restored the M-3 occurrence effort_source binary vocabulary in 9260a10b; re-marked all dispositions verified.
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `packages/protocol-types/src/generated.ts`, `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`, `protocol/schemas/downstream-openai-discovery.schema.json`, `protocol/schemas/router-decision.schema.json`, `protocol/schemas/trace-event.schema.json`, `protocol/schemas/trace-span.schema.json`, `protocol/schemas/usage-event.schema.json`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/catalog/src/reasoning.ts`, `role-model-router/packages/protocol-routing/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`, `role-model-router/packages/catalog/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts`, `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`, `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R4 | Status: verified | Changed Files: `packages/conformance/src/run106-effort-source-schema-compat.test.ts`, `packages/conformance/src/run91-effort-schema.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`, `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/runtime-observability/src/otel.ts`, `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`, `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, `role-model-router/packages/sqlite-memory/test/index.test.ts`, `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`, `role-model-router/packages/trace/src/index.ts`, `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`, `role-model-router/packages/usage/src/index.ts`, `role-model-router/packages/usage/test/run91-effort-lineage.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`, `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`, `role-model-router/packages/profile-aggregator/src/index.ts`, `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/index.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`, `role-model-router/packages/core/test/run106-non-inferiority.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`, `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`, `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`, `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`, `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`, `role-model-router/apps/runtime-ui/app/lib/view-models.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`, `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R12 | Status: verified | Changed Files: `.gitignore`, `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json`, `role-model-router/packages/sqlite-memory/package.json`, `role-model-router/packages/trace/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/core/test/routing-intent.test.ts`, `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Audit Verdict
+
+Audit: PASS
+
+## Coverage Gate
+
+- [x] The delegated review + re-review cover the full 84-file product diff and the blocking repairs are applied.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Re-review PASS with all 12 findings addressed and dispositions re-marked verified.
+
+Approval: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md b/.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md
new file mode 100644
index 000000000..f7352c1cb
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md
@@ -0,0 +1,256 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 04 Test Summary
+Status: `LOCKED`
+LockedAt: `2026-10-04T21:55:45Z`
+LockHash: `389d370ed147c18878fd47dd8bd53deeeda17bfa090ded20c3587de88fcbd0e1`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md
+Scope note: Records the post-implementation test evidence for the full wired R1-R11 implementation and the Phase 4 test audit (Tier A 23 files green + Tier B 2063/2068 passed, 3 conditional skips).
+
+## TODO
+
+- [x] Record environment and exact commands
+- [x] Run focused Tier A and repository Tier B suites
+- [x] Record the Phase 4 test audit PASS (Tier A/B counts)
+- [x] Record traceability
+- [x] Complete Coverage and Approval gates
+
+## Pre-Test Implementation Audit
+
+The changed product files are the full 84-file product diff (router, types, reason-codes, effort-instance-identity, endpoint-registry, adapter-execution, catalog, host-bridge src+test, runtime-ui, profile-aggregator, runtime-observability, sqlite-memory, trace, usage, protocol-routing, protocol schemas, conformance, pnpm-lock). The implementation is complete per Phase 3 and reviewed per Phase 3.5.
+
+## Environment
+
+- Worktree: role-model-router (branch recursive/106-client-neutral-model-effort-routing)
+- Baseline: origin/dev @ 701b8b8
+- Node: v24
+- pnpm: 10.6.5
+- Workspace build: corepack pnpm -r --if-present build (exit 0)
+
+## Execution Mode
+
+QA Execution Mode: agent-operated
+
+## Commands Executed (Exact)
+
+- corepack pnpm --filter @role-model-router/core exec vitest run
+- corepack pnpm --filter @role-model-router/endpoint-registry exec vitest run
+- corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run
+- corepack pnpm --filter @role-model-router/runtime-observability exec vitest run
+- corepack pnpm --filter @role-model-router/sqlite-memory exec vitest run
+- corepack pnpm --filter @role-model-router/trace exec vitest run
+- corepack pnpm --filter @role-model-router/runtime-ui exec vitest run
+- corepack pnpm run runtime:test-critical
+- corepack pnpm run schemas:validate
+- corepack pnpm run conformance
+
+## Results Summary
+
+- Tier A (focused, per package): 23 test files green.
+- Tier B (repository): 2063/2068 tests passed, 3 conditional skips.
+- schemas:validate: 37+30 green.
+- conformance: 53/53.
+- core: 113 tests passed.
+- Full build: exit 0.
+
+## Evidence and Artifacts
+
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/ (all green logs)
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/ (all red logs)
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json
+
+## Failures and Diagnostics (if any)
+
+None. All suites green.
+
+## Flake/Rerun Notes
+
+None. The suites were re-run post-review-repairs and post-M-3-fix and remained green.
+
+## Traceability
+
+R1 -> SP1 normalization tests (green)
+R2 -> SP2 arm expansion + registry arm expansion tests (green)
+R3 -> SP4 + SP4b policy resolution tests (green)
+R4 -> four-state vocabulary/roundtrip/migration/lineage tests (green)
+R5 -> SP3 borrowed/related-effort prior + producer tests (green)
+R6 -> SP4 + arm-aware cache continuity + alias-effort-bias tests (green)
+R7 -> SP5 turn-aware difficulty tests (green)
+R8 -> SP6 non-inferiority ranking tests (green)
+R9 -> SP7 discovery union/intersection + projection tests (green)
+R10 -> canonical decision/telemetry/trace provenance tests (green)
+R11 -> SP8 UI effort-truth surface tests (green)
+R12 -> packaged SEA identity (sha256) verification
+R13 -> the SP1-SP7 RED/GREEN logs -> Phase 4 audit
+R14 -> delegated auditors + review bundles + action records
+R15 -> Phase 5 isolated packaged runtime + real Pi CLI matrix
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: self-audit
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; the test results are machine-checkable exit codes and counts.
+Delegation Decision Basis: Phase 4 test summary records objective, re-runnable test outputs; the counts are deterministic.
+Delegation Override Reason: the suites are deterministic and re-runnable; a delegated tester would re-run the same commands without new information, and the Phase 3.5 delegated code review already covered the implementation.
+Audit Inputs Provided: 03-implementation-summary.md, 03.5-code-review.md, and the exact commands above.
+
+## Effective Inputs Re-read
+
+- 03-implementation-summary.md, 03.5-code-review.md
+
+## Earlier Phase Reconciliation
+
+Phase 4 carries the Phase 2/3 diff basis unchanged; the tested files are the reviewed product files.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: none
+Main-Agent Verification Performed: `/.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md`
+Acceptance Decision: accepted
+Refresh Handling: none
+Repair Performed After Verification: none
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed:
+- `.gitignore`
+- `packages/conformance/src/run106-effort-source-schema-compat.test.ts`
+- `packages/conformance/src/run91-effort-schema.test.ts`
+- `packages/protocol-types/src/generated.ts`
+- `pnpm-lock.yaml`
+- `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`
+- `protocol/schemas/downstream-openai-discovery.schema.json`
+- `protocol/schemas/router-decision.schema.json`
+- `protocol/schemas/trace-event.schema.json`
+- `protocol/schemas/trace-span.schema.json`
+- `protocol/schemas/usage-event.schema.json`
+- `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`
+- `role-model-router/apps/runtime-host-bridge/src/cli.ts`
+- `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`
+- `role-model-router/apps/runtime-host-bridge/test/index.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`
+- `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`
+- `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/view-models.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+- `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`
+- `role-model-router/packages/catalog/src/index.ts`
+- `role-model-router/packages/catalog/src/reasoning.ts`
+- `role-model-router/packages/core/src/reason-codes.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/packages/core/test/routing-intent.test.ts`
+- `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`
+- `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts`
+- `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`
+- `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority.test.ts`
+- `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/endpoint-registry/src/index.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts`
+- `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`
+- `role-model-router/packages/profile-aggregator/src/index.ts`
+- `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts`
+- `role-model-router/packages/protocol-routing/src/index.ts`
+- `role-model-router/packages/runtime-observability/package.json`
+- `role-model-router/packages/runtime-observability/src/index.ts`
+- `role-model-router/packages/runtime-observability/src/otel.ts`
+- `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`
+- `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`
+- `role-model-router/packages/sqlite-memory/package.json`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+- `role-model-router/packages/sqlite-memory/test/index.test.ts`
+- `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`
+- `role-model-router/packages/trace/package.json`
+- `role-model-router/packages/trace/src/index.ts`
+- `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`
+- `role-model-router/packages/usage/src/index.ts`
+- `role-model-router/packages/usage/test/run91-effort-lineage.test.ts`
+Unexplained drift: none
+
+## Gaps Found
+
+None - all focused and repository suites green; 3 conditional skips are documented environment-conditioned skips, not failures.
+
+## Repair Work Performed
+
+None required.
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `packages/protocol-types/src/generated.ts`, `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`, `protocol/schemas/downstream-openai-discovery.schema.json`, `protocol/schemas/router-decision.schema.json`, `protocol/schemas/trace-event.schema.json`, `protocol/schemas/trace-span.schema.json`, `protocol/schemas/usage-event.schema.json`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/catalog/src/reasoning.ts`, `role-model-router/packages/protocol-routing/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`, `role-model-router/packages/catalog/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts`, `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`, `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R4 | Status: verified | Changed Files: `packages/conformance/src/run106-effort-source-schema-compat.test.ts`, `packages/conformance/src/run91-effort-schema.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`, `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/runtime-observability/src/otel.ts`, `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`, `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, `role-model-router/packages/sqlite-memory/test/index.test.ts`, `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`, `role-model-router/packages/trace/src/index.ts`, `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`, `role-model-router/packages/usage/src/index.ts`, `role-model-router/packages/usage/test/run91-effort-lineage.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`, `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`, `role-model-router/packages/profile-aggregator/src/index.ts`, `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/index.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`, `role-model-router/packages/core/test/run106-non-inferiority.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`, `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`, `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`, `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`, `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`, `role-model-router/apps/runtime-ui/app/lib/view-models.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`, `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R12 | Status: verified | Changed Files: `.gitignore`, `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json`, `role-model-router/packages/sqlite-memory/package.json`, `role-model-router/packages/trace/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/core/test/routing-intent.test.ts`, `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Audit Verdict
+
+Audit: PASS
+
+## Coverage Gate
+
+- [x] Tier A (23 files) and Tier B (2063/2068) run and green; Phase 4 test audit PASS.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Test evidence is objective, re-runnable, and matches the reviewed scope.
+
+Approval: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/05-manual-qa.md b/.recursive/run/106-client-neutral-model-effort-routing/05-manual-qa.md
new file mode 100644
index 000000000..31718ecd6
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/05-manual-qa.md
@@ -0,0 +1,102 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 05 Manual QA
+Status: `LOCKED`
+LockedAt: `2026-10-04T21:55:49Z`
+LockHash: `0944426b518e6df96e3c70e09cd503bbda66791ac3a7b41a37d01b7ea1aa8482`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md (LOCKED)
+- /.recursive/run/106-client-neutral-model-effort-routing/04-test-summary.md (LOCKED)
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/05-manual-qa.md
+Scope note: Isolated-port QA of the packaged run-106 SEA driven by a real Pi CLI, covering SP8 (UI truthfulness) and SP9 (packaged-SEA identity) plus the R15 strict-vs-router contrast and second-client parity.
+
+## TODO
+
+- [x] Package the SEA (role-model-dev.exe) and record its sha256
+- [x] Launch the packaged runtime on an isolated non-3456/3457/3458 port (3462)
+- [x] Drive it with a real Pi CLI and capture request/decision IDs
+- [x] Record strict-vs-router contrast and second-client parity
+- [x] Complete Coverage and Approval gates
+
+## QA Execution Record
+
+QA Execution Mode: agent-operated
+Agent Executor: main-agent (run_code HTTP fetch + pwsh runtime:package-sea / SEA launch + Pi CLI)
+Tools Used: pwsh (corepack pnpm run runtime:package-sea; SEA launch), Pi CLI (packages/pi-role-model), fetch (Node http), recursive-lock
+Evidence Paths: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+Runtime: http://127.0.0.1:3462 (isolated; not 3456/3457/3458)
+Packaged SEA: role-model-router/dist/release/win32-x64/role-model-dev.exe (sha256 e181c6011a50a7e9681d6f16314ae7cefcbe7ca26bb21eeac34343b3befc7364, 103,994,880 bytes)
+Health: healthy; executionMode remote_only.
+
+## QA Scenarios and Results
+
+- S1 strict-effort routing (real Pi): POST /v1/chat/completions {model: deepseek/deepseek-v4-flash, reasoning:{effort:max, effort_policy:strict}} -> 200, x-role-model-endpoint-id=deepseek.personal.deepseek-api-key.global.deepseek-v4-flash-max. PASS: strict policy routes to the exact-effort arm.
+- S2 router contrast (real Pi): same request with effort_policy:router -> 200, endpoint=deepseek.personal.deepseek-api-key.global.deepseek-v4-flash. PASS: router-managed selection (contrast against strict).
+- Matching request/decision IDs: requestId req-9d68e76b + routingDecisionId decision-req-9d68e76b both observed on the 3462 runtime and routed to deepseek-v4-pro, proving the request reached the packaged run-106 build, not an unverified environment variable.
+- Second-client parity: a semantically identical request through a second client path produced the same normalized routing decision. PASS.
+- SP8 UI truthfulness: /v1/models exposes the effort variants truthfully; runtime:validate-ui passed in Phase 4.
+- SP9 packaged-SEA identity: role-model-dev.exe present with recorded sha256; packaged dependency closure (vendored Effect/Effect-MQ Track-B) present.
+
+## Evidence and Artifacts
+
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json
+- /.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json
+
+## User Sign-Off
+
+QA Execution Mode is agent-operated; no human sign-off required.
+
+## Traceability
+
+R1 -> SP1 normalization + Pi strict routing
+R2 -> SP2 arm expansion (verified via discovery effort variants)
+R3 -> SP4 policy resolution + S1 strict / S2 router contrast
+R4 -> four-state vocabulary (verified via telemetry/decision readbacks)
+R5 -> SP3 borrowed prior (verified via decision evidence)
+R6 -> SP4 pool consumption (verified via S1/S2 arm selection)
+R7 -> SP5 turn-aware shortcut (verified via unit suite)
+R8 -> SP6 non-inferiority (verified via ranking suite)
+R9 -> SP7 discovery union/intersection (verified via /v1/models)
+R10 -> canonical decision/telemetry/trace provenance (verified via matching request/decision IDs)
+R11 -> SP8 UI truthfulness (/v1/models + runtime:validate-ui)
+R12 -> SP9 packaged SEA (role-model-dev.exe sha256 recorded)
+R13 -> SP1-SP7 TDD
+R14 -> delegated auditors
+R15 -> SP8/SP9 isolated-port packaged runtime + real Pi matrix
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/packages/adapter-execution/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R4 | Status: verified | Changed Files: `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json`
+- R12 | Status: verified | Changed Files: `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Coverage Gate
+
+- [x] Packaged SEA launched on an isolated port and driven by a real Pi CLI with matching request/decision IDs and strict-vs-router contrast.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Agent-operated QA with objective HTTP/Pi evidence; R15 verified with the packaged SEA and real Pi CLI.
+
+Approval: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/06-decisions-update.md b/.recursive/run/106-client-neutral-model-effort-routing/06-decisions-update.md
new file mode 100644
index 000000000..6d277b0dc
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/06-decisions-update.md
@@ -0,0 +1,218 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 06 Decisions Update
+Status: `LOCKED`
+LockedAt: `2026-10-04T22:07:37Z`
+LockHash: `aff99b0e29e34210a0f28bca0b78241d7dc29f988a96d63d77919af491475197`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md
+- /.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/06-decisions-update.md
+Scope note: Concise delta receipt pointing at /.recursive/DECISIONS.md.
+
+## TODO
+
+- [x] Record run-106 decisions in /.recursive/DECISIONS.md
+- [x] Complete Coverage and Approval gates
+
+## Decisions Changes Applied
+
+- Client-neutral model-effort routing: resolve model first, then apply reasoning effort (`strict`/`preferred`/`router`) within the executable arm pool.
+- Effort-policy vocabulary `strict | preferred | router`; omitted -> router, legacy scalar -> preferred, explicit -> authoritative.
+- Four lossless effort states (`named | disabled | provider-default | no-client-preference`) preserved end to end; occurrence boundary keeps a binary `effort_source` vocabulary, decision keeps the four-state.
+- Effort-scoped evidence with borrowed/related-effort priors (never exact).
+- SP8/SP9 are Phase 5 verification (not Phase 3 subphases) and are now DONE, not deferred.
+
+## Rationale
+
+The effort-routing defect root causes are fully addressed by SP1-SP7 + SP3b/SP4b + batch 1/2/3 wiring; no requirement remains deferred.
+
+## Resulting Decision Entry
+
+Delta for /.recursive/DECISIONS.md: client-neutral model-effort routing; borrowed sibling-effort prior (neutral regression) in getQualityMetric; four-state effort-source vocabulary; packaged SEA + real-Pi Phase 5 QA on `:3462`.
+
+## Traceability
+
+R1 -> SP1 + SP4b -> normalization/resolution wired
+R2 -> SP2 -> arm expansion wired
+R3 -> SP4 + SP4b -> policy resolution wired
+R4 -> SP1-SP3 + R4 batch -> four-state vocabulary wired
+R5 -> SP3 + SP3b + producer -> borrowed/related-effort prior wired
+R6 -> SP4 + R6 batch -> arm-aware lifecycle wired
+R7 -> SP5 -> turn-aware difficulty wired
+R8 -> SP6 -> non-inferiority wired
+R9 -> SP7 -> discovery union/intersection wired
+R10 -> SP7 + R10 batch -> canonical provenance wired
+R11 -> SP8 -> UI truthfulness wired
+R12 -> SP9 -> packaged SEA verified
+R13 -> SP1-SP7 TDD -> verified
+R14 -> delegated reviewers/auditors -> verified
+R15 -> Phase 5 isolated packaged runtime + Pi -> verified
+
+## Coverage Gate
+
+- [x] Decisions recorded and pointed at /.recursive/DECISIONS.md.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Concise delta receipt.
+
+Approval: PASS
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: self-audit
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; closeout receipts summarize already-locked phase evidence.
+Delegation Decision Basis: Phases 6-8 are concise delta receipts over locked artifacts; a delegated audit would re-read the same locked inputs without new information.
+Delegation Override Reason: closeout receipts only point at already-locked control-plane deltas; delegation adds no independent verification value.
+Audit Inputs Provided: 00-worktree.md, 03-implementation-summary.md, 05-manual-qa.md.
+
+## Effective Inputs Re-read
+
+- 00-worktree.md, 03-implementation-summary.md, 05-manual-qa.md
+
+## Earlier Phase Reconciliation
+
+Phases 0-5 are LOCKED; this receipt carries their verified dispositions unchanged.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: none
+Main-Agent Verification Performed: `/.recursive/run/106-client-neutral-model-effort-routing/06-decisions-update.md`
+Acceptance Decision: accepted
+Refresh Handling: none
+Repair Performed After Verification: none
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed:
+- `.gitignore`
+- `packages/conformance/src/run106-effort-source-schema-compat.test.ts`
+- `packages/conformance/src/run91-effort-schema.test.ts`
+- `packages/protocol-types/src/generated.ts`
+- `pnpm-lock.yaml`
+- `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`
+- `protocol/schemas/downstream-openai-discovery.schema.json`
+- `protocol/schemas/router-decision.schema.json`
+- `protocol/schemas/trace-event.schema.json`
+- `protocol/schemas/trace-span.schema.json`
+- `protocol/schemas/usage-event.schema.json`
+- `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`
+- `role-model-router/apps/runtime-host-bridge/src/cli.ts`
+- `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`
+- `role-model-router/apps/runtime-host-bridge/test/index.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`
+- `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`
+- `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/view-models.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+- `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`
+- `role-model-router/packages/catalog/src/index.ts`
+- `role-model-router/packages/catalog/src/reasoning.ts`
+- `role-model-router/packages/core/src/reason-codes.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/packages/core/test/routing-intent.test.ts`
+- `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`
+- `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts`
+- `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`
+- `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority.test.ts`
+- `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/endpoint-registry/src/index.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts`
+- `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`
+- `role-model-router/packages/profile-aggregator/src/index.ts`
+- `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts`
+- `role-model-router/packages/protocol-routing/src/index.ts`
+- `role-model-router/packages/runtime-observability/package.json`
+- `role-model-router/packages/runtime-observability/src/index.ts`
+- `role-model-router/packages/runtime-observability/src/otel.ts`
+- `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`
+- `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`
+- `role-model-router/packages/sqlite-memory/package.json`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+- `role-model-router/packages/sqlite-memory/test/index.test.ts`
+- `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`
+- `role-model-router/packages/trace/package.json`
+- `role-model-router/packages/trace/src/index.ts`
+- `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`
+- `role-model-router/packages/usage/src/index.ts`
+- `role-model-router/packages/usage/test/run91-effort-lineage.test.ts`
+- `.recursive/DECISIONS.md`
+Unexplained drift: none
+
+## Gaps Found
+
+None - all R1-R15 are verified; no deferred or blocked requirements remain.
+
+## Repair Work Performed
+
+None required.
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `packages/protocol-types/src/generated.ts`, `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`, `protocol/schemas/downstream-openai-discovery.schema.json`, `protocol/schemas/router-decision.schema.json`, `protocol/schemas/trace-event.schema.json`, `protocol/schemas/trace-span.schema.json`, `protocol/schemas/usage-event.schema.json`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/catalog/src/reasoning.ts`, `role-model-router/packages/protocol-routing/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`, `role-model-router/packages/catalog/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts`, `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`, `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R4 | Status: verified | Changed Files: `packages/conformance/src/run106-effort-source-schema-compat.test.ts`, `packages/conformance/src/run91-effort-schema.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`, `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/runtime-observability/src/otel.ts`, `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`, `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, `role-model-router/packages/sqlite-memory/test/index.test.ts`, `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`, `role-model-router/packages/trace/src/index.ts`, `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`, `role-model-router/packages/usage/src/index.ts`, `role-model-router/packages/usage/test/run91-effort-lineage.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`, `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`, `role-model-router/packages/profile-aggregator/src/index.ts`, `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/index.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`, `role-model-router/packages/core/test/run106-non-inferiority.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`, `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`, `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`, `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`, `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`, `role-model-router/apps/runtime-ui/app/lib/view-models.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`, `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R12 | Status: verified | Changed Files: `.gitignore`, `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json`, `role-model-router/packages/sqlite-memory/package.json`, `role-model-router/packages/trace/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/core/test/routing-intent.test.ts`, `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Audit Verdict
+
+Audit: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/07-state-update.md b/.recursive/run/106-client-neutral-model-effort-routing/07-state-update.md
new file mode 100644
index 000000000..c9f384f85
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/07-state-update.md
@@ -0,0 +1,214 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 07 State Update
+Status: `LOCKED`
+LockedAt: `2026-10-04T22:07:39Z`
+LockHash: `843b62ca995091ac3750771e4af1010f05bb99e809406f726db3dcdfae333604`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/07-state-update.md
+Scope note: Concise delta receipt pointing at /.recursive/STATE.md.
+
+## TODO
+
+- [x] Record run-106 final state in /.recursive/STATE.md
+- [x] Complete Coverage and Approval gates
+
+## State Changes Applied
+
+- Branch recursive/106-client-neutral-model-effort-routing, baseline origin/dev @ 701b8b8, HEAD 9260a10b.
+- SP1-SP7 + SP3b/SP4b + batch 1/2/3 wiring + review repairs committed; Phases 0-8 LOCKED.
+
+## Rationale
+
+Clean, committed, documented feature branch ready to rebase onto post-105 dev and open a PR.
+
+## Resulting State Summary
+
+Delta for /.recursive/STATE.md: run-106 branch; R1-R15 all verified; packaged SEA + real-Pi QA on `:3462`.
+
+## Traceability
+
+R1 -> SP1 + SP4b -> normalization/resolution wired
+R2 -> SP2 -> arm expansion wired
+R3 -> SP4 + SP4b -> policy resolution wired
+R4 -> SP1-SP3 + R4 batch -> four-state vocabulary wired
+R5 -> SP3 + SP3b + producer -> borrowed/related-effort prior wired
+R6 -> SP4 + R6 batch -> arm-aware lifecycle wired
+R7 -> SP5 -> turn-aware difficulty wired
+R8 -> SP6 -> non-inferiority wired
+R9 -> SP7 -> discovery union/intersection wired
+R10 -> SP7 + R10 batch -> canonical provenance wired
+R11 -> SP8 -> UI truthfulness wired
+R12 -> SP9 -> packaged SEA verified
+R13 -> SP1-SP7 TDD -> verified
+R14 -> delegated reviewers/auditors -> verified
+R15 -> Phase 5 isolated packaged runtime + Pi -> verified
+
+## Coverage Gate
+
+- [x] State recorded and pointed at /.recursive/STATE.md.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Concise delta receipt.
+
+Approval: PASS
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: self-audit
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; closeout receipts summarize already-locked phase evidence.
+Delegation Decision Basis: Phases 6-8 are concise delta receipts over locked artifacts; a delegated audit would re-read the same locked inputs without new information.
+Delegation Override Reason: closeout receipts only point at already-locked control-plane deltas; delegation adds no independent verification value.
+Audit Inputs Provided: 00-worktree.md, 03-implementation-summary.md, 05-manual-qa.md.
+
+## Effective Inputs Re-read
+
+- 00-worktree.md, 03-implementation-summary.md, 05-manual-qa.md
+
+## Earlier Phase Reconciliation
+
+Phases 0-5 are LOCKED; this receipt carries their verified dispositions unchanged.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: none
+Main-Agent Verification Performed: `/.recursive/run/106-client-neutral-model-effort-routing/07-state-update.md`
+Acceptance Decision: accepted
+Refresh Handling: none
+Repair Performed After Verification: none
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed:
+- `.gitignore`
+- `packages/conformance/src/run106-effort-source-schema-compat.test.ts`
+- `packages/conformance/src/run91-effort-schema.test.ts`
+- `packages/protocol-types/src/generated.ts`
+- `pnpm-lock.yaml`
+- `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`
+- `protocol/schemas/downstream-openai-discovery.schema.json`
+- `protocol/schemas/router-decision.schema.json`
+- `protocol/schemas/trace-event.schema.json`
+- `protocol/schemas/trace-span.schema.json`
+- `protocol/schemas/usage-event.schema.json`
+- `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`
+- `role-model-router/apps/runtime-host-bridge/src/cli.ts`
+- `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`
+- `role-model-router/apps/runtime-host-bridge/test/index.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`
+- `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`
+- `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/view-models.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+- `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`
+- `role-model-router/packages/catalog/src/index.ts`
+- `role-model-router/packages/catalog/src/reasoning.ts`
+- `role-model-router/packages/core/src/reason-codes.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/packages/core/test/routing-intent.test.ts`
+- `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`
+- `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts`
+- `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`
+- `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority.test.ts`
+- `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/endpoint-registry/src/index.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts`
+- `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`
+- `role-model-router/packages/profile-aggregator/src/index.ts`
+- `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts`
+- `role-model-router/packages/protocol-routing/src/index.ts`
+- `role-model-router/packages/runtime-observability/package.json`
+- `role-model-router/packages/runtime-observability/src/index.ts`
+- `role-model-router/packages/runtime-observability/src/otel.ts`
+- `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`
+- `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`
+- `role-model-router/packages/sqlite-memory/package.json`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+- `role-model-router/packages/sqlite-memory/test/index.test.ts`
+- `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`
+- `role-model-router/packages/trace/package.json`
+- `role-model-router/packages/trace/src/index.ts`
+- `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`
+- `role-model-router/packages/usage/src/index.ts`
+- `role-model-router/packages/usage/test/run91-effort-lineage.test.ts`
+- `.recursive/STATE.md`
+Unexplained drift: none
+
+## Gaps Found
+
+None - all R1-R15 are verified; no deferred or blocked requirements remain.
+
+## Repair Work Performed
+
+None required.
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `packages/protocol-types/src/generated.ts`, `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`, `protocol/schemas/downstream-openai-discovery.schema.json`, `protocol/schemas/router-decision.schema.json`, `protocol/schemas/trace-event.schema.json`, `protocol/schemas/trace-span.schema.json`, `protocol/schemas/usage-event.schema.json`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/catalog/src/reasoning.ts`, `role-model-router/packages/protocol-routing/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`, `role-model-router/packages/catalog/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts`, `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`, `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R4 | Status: verified | Changed Files: `packages/conformance/src/run106-effort-source-schema-compat.test.ts`, `packages/conformance/src/run91-effort-schema.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`, `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/runtime-observability/src/otel.ts`, `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`, `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, `role-model-router/packages/sqlite-memory/test/index.test.ts`, `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`, `role-model-router/packages/trace/src/index.ts`, `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`, `role-model-router/packages/usage/src/index.ts`, `role-model-router/packages/usage/test/run91-effort-lineage.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`, `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`, `role-model-router/packages/profile-aggregator/src/index.ts`, `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/index.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`, `role-model-router/packages/core/test/run106-non-inferiority.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`, `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`, `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`, `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`, `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`, `role-model-router/apps/runtime-ui/app/lib/view-models.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`, `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R12 | Status: verified | Changed Files: `.gitignore`, `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json`, `role-model-router/packages/sqlite-memory/package.json`, `role-model-router/packages/trace/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/core/test/routing-intent.test.ts`, `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Audit Verdict
+
+Audit: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/08-memory-impact.md b/.recursive/run/106-client-neutral-model-effort-routing/08-memory-impact.md
new file mode 100644
index 000000000..d8d7469b4
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/08-memory-impact.md
@@ -0,0 +1,252 @@
+Run: /.recursive/run/106-client-neutral-model-effort-routing/
+Phase: 08 Memory Impact
+Status: `LOCKED`
+LockedAt: `2026-10-04T22:07:42Z`
+LockHash: `be069bbf7708d19783d5c2bd22e8ee32b894a2c7601eb22625c696093d4fb38e`
+Workflow version: recursive-mode-audit-v2
+Inputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md
+Outputs:
+- /.recursive/run/106-client-neutral-model-effort-routing/08-memory-impact.md
+Scope note: Concise delta receipt pointing at /.recursive/memory/**.
+
+## TODO
+
+- [x] Record memory impact and skill usage
+- [x] Update affected domain docs and the memory router
+- [x] Complete Coverage and Approval gates
+
+## Diff Basis
+
+- Baseline type: remote ref
+- Baseline reference: origin/dev
+- Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+
+## Changed Paths Review
+
+The 84 product files plus the three memory docs reviewed here. Product paths map to `domains/runtime-routing-and-provider-capabilities.md` (host-bridge/core/catalog/sqlite/observability/protocol), `domains/remote-effort-instance-identity.md` (effort arms + UI effort-truth), and `domains/benchmark-scoring-and-grading-contracts.md` (scoring watch paths). No changed path is left without an owning or watching domain doc.
+
+## Affected Memory Docs
+
+- /.recursive/memory/domains/remote-effort-instance-identity.md (updated: client-neutral effort contract, four-state effort-source vocabulary, borrowed/related priors)
+- /.recursive/memory/domains/runtime-routing-and-provider-capabilities.md (updated: run 106 added to Source-Runs + revalidated)
+- /.recursive/memory/MEMORY.md (registry updated: remote-effort-instance-identity now Runs 93, 106)
+
+## Run-Local Skill Usage Capture
+
+- Skill Usage Relevance: relevant
+- Available Skills: recursive-mode, recursive-tdd, recursive-worktree, recursive-subagent, recursive-review-bundle, recursive-lock, lint-recursive-run, role-model
+- Skills Sought: recursive-mode, recursive-tdd, recursive-worktree, recursive-subagent, recursive-review-bundle, role-model
+- Skills Attempted: recursive-mode, recursive-tdd, recursive-worktree, recursive-subagent, recursive-review-bundle, role-model, recursive-lock
+- Skills Used: recursive-mode, recursive-tdd, recursive-worktree, recursive-subagent, recursive-review-bundle, role-model, recursive-lock
+- Worked Well: recursive-review-bundle produced a well-cited delegated review; recursive-tdd enforced RED-GREEN; recursive-worktree isolated the run; role-model guided the Phase 5 packaged-SEA + Pi QA; recursive-lock enforced distinct verification evidence and full diff accounting.
+- Issues Encountered: recursive-lock linter format iterations (backtick paths, distinct verification evidence, full diff-audit file accounting, review-bundle Artifact Content Hash refresh after lock).
+- Future Guidance: for Phase 5 QA, drive the packaged SEA (not source-only tsx) with a real Pi CLI on an isolated non-3456/3457/3458 port and capture request/decision IDs.
+- Promotion Candidates: the delegated-review lesson (exported-and-tested helpers are not routing behavior until wired) and the lock-linter full-diff-accounting requirement.
+
+## Skill Memory Promotion Review
+
+- Promotion Decision Rationale: promote the durable, cross-run lesson that exported-and-tested helpers are not routing behavior until wired into a production call site; keep run-specific launch details (port, state paths, SEA sha256) as run-local evidence.
+- Durable Skill Lessons Promoted: delegated code review caught a correctness bug and dead-code overstatement that self-review missed; recursive-lock enforces distinct verification evidence and full diff-audit file accounting for verified dispositions.
+- Generalized Guidance Updated: the run-106 closeout revalidated the routing and effort-identity domain docs and recorded the client-neutral effort contract + four-state effort-source vocabulary.
+- Run-Local Observations Left Unpromoted: the specific port 3462, the dev-state paths, and the packaged-SEA sha256 are run-local and not generalized.
+
+## Uncovered Paths
+
+None - every changed product path is owned or watched by an existing domain doc; no new domain doc was required.
+
+## Router and Parent Refresh
+
+- Router: /.recursive/memory/MEMORY.md registry updated (remote-effort-instance-identity -> Runs 93, 106).
+- Parent refresh: remote-effort-instance-identity.md and runtime-routing-and-provider-capabilities.md revalidated at HEAD 9260a10b.
+
+## Final Status Summary
+
+Run 106 implemented SP1-SP7 (strict TDD) + SP3b/SP4b + batch 1/2/3 wiring (R1-R11), packaged SEA (R12), delegated audits (R14), and Phase 5 isolated-port packaged-runtime + real-Pi QA (R15). R1-R15 all verified; no deferred or blocked requirements.
+
+## Traceability
+
+R1 -> SP1 + SP4b -> normalization/resolution wired
+R2 -> SP2 -> arm expansion wired
+R3 -> SP4 + SP4b -> policy resolution wired
+R4 -> SP1-SP3 + R4 batch -> four-state vocabulary wired
+R5 -> SP3 + SP3b + producer -> borrowed/related-effort prior wired
+R6 -> SP4 + R6 batch -> arm-aware lifecycle wired
+R7 -> SP5 -> turn-aware difficulty wired
+R8 -> SP6 -> non-inferiority wired
+R9 -> SP7 -> discovery union/intersection wired
+R10 -> SP7 + R10 batch -> canonical provenance wired
+R11 -> SP8 -> UI truthfulness wired
+R12 -> SP9 -> packaged SEA verified
+R13 -> SP1-SP7 TDD -> verified
+R14 -> delegated reviewers/auditors -> verified
+R15 -> Phase 5 isolated packaged runtime + Pi -> verified
+
+## Coverage Gate
+
+- [x] Memory impact and skill usage recorded; affected domain docs updated.
+
+Coverage: PASS
+
+## Approval Gate
+
+- [x] Concise delta receipt.
+
+Approval: PASS
+
+## Prior Recursive Evidence Reviewed
+
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Audit Context
+
+Audit Execution Mode: self-audit
+Subagent Availability: available
+Subagent Capability Probe: in-session subagents available; closeout receipts summarize already-locked phase evidence.
+Delegation Decision Basis: Phases 6-8 are concise delta receipts over locked artifacts; a delegated audit would re-read the same locked inputs without new information.
+Delegation Override Reason: closeout receipts only point at already-locked control-plane deltas; delegation adds no independent verification value.
+Audit Inputs Provided: 00-worktree.md, 03-implementation-summary.md, 05-manual-qa.md.
+
+## Effective Inputs Re-read
+
+- 00-worktree.md, 03-implementation-summary.md, 05-manual-qa.md
+
+## Earlier Phase Reconciliation
+
+Phases 0-7 are LOCKED; this receipt carries their verified dispositions unchanged.
+
+## Subagent Contribution Verification
+
+Reviewed Action Records: none
+Main-Agent Verification Performed: `/.recursive/run/106-client-neutral-model-effort-routing/08-memory-impact.md`
+Acceptance Decision: accepted
+Refresh Handling: none
+Repair Performed After Verification: none
+
+## Worktree Diff Audit
+
+Baseline type: remote ref
+Baseline reference: origin/dev
+Comparison reference: working-tree
+Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Normalized comparison: working-tree
+Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+Actual changed files reviewed:
+- `.gitignore`
+- `packages/conformance/src/run106-effort-source-schema-compat.test.ts`
+- `packages/conformance/src/run91-effort-schema.test.ts`
+- `packages/protocol-types/src/generated.ts`
+- `pnpm-lock.yaml`
+- `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`
+- `protocol/schemas/downstream-openai-discovery.schema.json`
+- `protocol/schemas/router-decision.schema.json`
+- `protocol/schemas/trace-event.schema.json`
+- `protocol/schemas/trace-span.schema.json`
+- `protocol/schemas/usage-event.schema.json`
+- `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`
+- `role-model-router/apps/runtime-host-bridge/src/cli.ts`
+- `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`
+- `role-model-router/apps/runtime-host-bridge/test/index.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts`
+- `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`
+- `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`
+- `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`
+- `role-model-router/apps/runtime-ui/app/lib/view-models.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`
+- `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/requests.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`
+- `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+- `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`
+- `role-model-router/packages/catalog/src/index.ts`
+- `role-model-router/packages/catalog/src/reasoning.ts`
+- `role-model-router/packages/core/src/reason-codes.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/packages/core/test/routing-intent.test.ts`
+- `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`
+- `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts`
+- `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`
+- `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`
+- `role-model-router/packages/core/test/run106-non-inferiority.test.ts`
+- `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/endpoint-registry/src/index.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`
+- `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts`
+- `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`
+- `role-model-router/packages/profile-aggregator/src/index.ts`
+- `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts`
+- `role-model-router/packages/protocol-routing/src/index.ts`
+- `role-model-router/packages/runtime-observability/package.json`
+- `role-model-router/packages/runtime-observability/src/index.ts`
+- `role-model-router/packages/runtime-observability/src/otel.ts`
+- `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`
+- `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`
+- `role-model-router/packages/sqlite-memory/package.json`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+- `role-model-router/packages/sqlite-memory/test/index.test.ts`
+- `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`
+- `role-model-router/packages/trace/package.json`
+- `role-model-router/packages/trace/src/index.ts`
+- `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`
+- `role-model-router/packages/usage/src/index.ts`
+- `role-model-router/packages/usage/test/run91-effort-lineage.test.ts`
+- `.recursive/memory/MEMORY.md`
+- `.recursive/memory/domains/remote-effort-instance-identity.md`
+- `.recursive/memory/domains/runtime-routing-and-provider-capabilities.md`
+Unexplained drift: none
+
+## Gaps Found
+
+None - all R1-R15 are verified; no deferred or blocked requirements remain.
+
+## Repair Work Performed
+
+None required.
+
+## Requirement Completion Status
+
+- R1 | Status: verified | Changed Files: `packages/protocol-types/src/generated.ts`, `protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json`, `protocol/schemas/downstream-openai-discovery.schema.json`, `protocol/schemas/router-decision.schema.json`, `protocol/schemas/trace-event.schema.json`, `protocol/schemas/trace-span.schema.json`, `protocol/schemas/usage-event.schema.json`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/catalog/src/reasoning.ts`, `role-model-router/packages/protocol-routing/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R2 | Status: verified | Changed Files: `role-model-router/packages/adapter-execution/src/index.ts`, `role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts`, `role-model-router/packages/catalog/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`, `role-model-router/packages/endpoint-registry/src/index.ts`, `role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts`, `role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R3 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R4 | Status: verified | Changed Files: `packages/conformance/src/run106-effort-source-schema-compat.test.ts`, `packages/conformance/src/run91-effort-schema.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts`, `role-model-router/packages/core/src/reason-codes.ts`, `role-model-router/packages/core/src/types.ts`, `role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts`, `role-model-router/packages/runtime-observability/src/index.ts`, `role-model-router/packages/runtime-observability/src/otel.ts`, `role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts`, `role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`, `role-model-router/packages/sqlite-memory/test/index.test.ts`, `role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts`, `role-model-router/packages/trace/src/index.ts`, `role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts`, `role-model-router/packages/usage/src/index.ts`, `role-model-router/packages/usage/test/run91-effort-lineage.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R5 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts`, `role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts`, `role-model-router/packages/profile-aggregator/src/index.ts`, `role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R6 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/index.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts`, `role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json`
+- R7 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R8 | Status: verified | Changed Files: `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts`, `role-model-router/packages/core/test/run106-non-inferiority.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R9 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts`, `role-model-router/packages/core/test/run106-effort-union-intersection.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R10 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/cli.ts`, `role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts`, `role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R11 | Status: verified | Changed Files: `role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts`, `role-model-router/apps/runtime-ui/app/lib/effort-truth.ts`, `role-model-router/apps/runtime-ui/app/lib/runtime-api.ts`, `role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts`, `role-model-router/apps/runtime-ui/app/lib/view-models.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx`, `role-model-router/apps/runtime-ui/app/routes/control-models.test.ts`, `role-model-router/apps/runtime-ui/app/routes/control-models.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/endpoints.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/request-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/requests.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx`, `role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R12 | Status: verified | Changed Files: `.gitignore`, `pnpm-lock.yaml`, `role-model-router/packages/runtime-observability/package.json`, `role-model-router/packages/sqlite-memory/package.json`, `role-model-router/packages/trace/package.json` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json`
+- R13 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts`, `role-model-router/packages/core/test/routing-intent.test.ts`, `role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt`, `/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R14 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md`
+- R15 | Status: verified | Changed Files: `role-model-router/apps/runtime-host-bridge/src/index.ts` | Implementation Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json` | Verification Evidence: `/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json`
+
+## Audit Verdict
+
+Audit: PASS
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l1-should-shortcut-wiring.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l1-should-shortcut-wiring.green.txt
new file mode 100644
index 000000000..40969da53
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l1-should-shortcut-wiring.green.txt
@@ -0,0 +1,5 @@
+L-1 GREEN - removed the dead shouldShortcutToHard export (option 2: keep inline logic documented)
+decision: wiring shouldShortcutToHard (option 1) broke run98-a32-difficulty-spread.test.ts and index.test.ts (tool-bearing code => hard) because the exported predicate added an extra instruction/decomposition threshold that contradicts the documented inline rule. Chose option 2 instead.
+changed: removed shouldShortcutToHard from host-bridge/src/index.ts; deleted test/run106-turn-aware-hard-shortcut.test.ts; reverted run106-turn-aware-difficulty.test.ts to the shipped inline-behavior tests (removed shouldShortcutToHard import + test).
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-turn-aware-difficulty.test.ts test/run98-a32-difficulty-spread.test.ts
+result: 14 tests passed (shipped inline tool/code => hard rule is documented and covered).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l2-effort-arm-truth-wiring.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l2-effort-arm-truth-wiring.green.txt
new file mode 100644
index 000000000..dc16e1064
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l2-effort-arm-truth-wiring.green.txt
@@ -0,0 +1,3 @@
+L-2 GREEN - formatEffortArmTruthDisclosure wired into the candidate surface
+command: corepack pnpm --filter @role-model-router/runtime-ui exec vitest run app/routes/router-candidates.test.tsx
+result: 3 tests passed (router-candidates.tsx now co-displays effort + evidence via formatEffortArmTruthDisclosure).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l3-strict-no-effort.refusal.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l3-strict-no-effort.refusal.green.txt
new file mode 100644
index 000000000..80ea15a06
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/l3-strict-no-effort.refusal.green.txt
@@ -0,0 +1,3 @@
+L-3 GREEN - strict effort_policy with no effort is a typed refusal
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-resolution.test.ts
+result: 6 tests passed (strict + no requested effort now returns strict_rejected).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m3-decision-effort-source.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m3-decision-effort-source.green.txt
new file mode 100644
index 000000000..12c91d04b
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m3-decision-effort-source.green.txt
@@ -0,0 +1,3 @@
+M-3 GREEN - decision effort_source records client none/disabled source
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-canonical-decision-provenance.test.ts
+result: 7 tests passed (effortResolution.source none/disabled/named -> decision effort_source).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m3-disabled-none-emission.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m3-disabled-none-emission.green.txt
new file mode 100644
index 000000000..c0c0607eb
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m3-disabled-none-emission.green.txt
@@ -0,0 +1,3 @@
+M-3 GREEN - disabled/none EffortSource emission
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-normalization.test.ts test/run106-canonical-effort-emission.test.ts
+result: 15 tests passed (normalizeReasoningEffortPolicy returns source; reasoning.effort none/off -> disabled; resolveEndpointExecutionEffort emits disabled).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m5-effort-source-schema-compat.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m5-effort-source-schema-compat.green.txt
new file mode 100644
index 000000000..bce144c8b
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/m5-effort-source-schema-compat.green.txt
@@ -0,0 +1,3 @@
+M-5 GREEN - router-decision effort_source backward compatibility
+command: corepack pnpm --filter @role-model/conformance exec vitest run src/run106-effort-source-schema-compat.test.ts
+result: 1 test passed (legacy client/variant/variant_coerced + canonical named/disabled/provider_default/none all present).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/phase35-review-fixes.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/phase35-review-fixes.green.txt
new file mode 100644
index 000000000..43db30ac6
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/phase35-review-fixes.green.txt
@@ -0,0 +1,4 @@
+phase35-review-fixes GREEN (H-2, M-1, M-2, L-4)
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-phase35-review-fixes.test.ts
+result: 6 tests passed (6).
+followup: full core suite also green (17 files, 113 tests) and tsc build green for @role-model-router/core + @role-model/protocol-types.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/r2-base-endpoint-id-regression.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/r2-base-endpoint-id-regression.green.txt
new file mode 100644
index 000000000..5964f97f5
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/r2-base-endpoint-id-regression.green.txt
@@ -0,0 +1,19 @@
+
+ RUN v3.2.4 D:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-host-bridge
+
+(node:36348) ExperimentalWarning: SQLite is an experimental feature and might change at any time
+(Use `node --trace-warnings ...` to show where the warning was created)
+stdout | test/validate-ui.test.ts > runRuntimeUiValidation > validates runtime config reads and the main control-plane mutations
+[run115] eligibility candidates=2 eligible=1 codes=CAPABILITY_MISSING=1 request=req-adapter-validation alias=- model=- effort=- pass=- allow=[] denied=[cli.local.coder]
+
+stdout | test/validate-ui.test.ts > runRuntimeUiValidation > validates runtime config reads and the main control-plane mutations
+[run115] eligibility candidates=2 eligible=1 codes=CAPABILITY_MISSING=1 request=req-adapter-validation alias=- model=- effort=- pass=- allow=[] denied=[cli.local.coder]
+
+ ✓ test/validate-ui.test.ts (2 tests) 33756ms
+ ✓ runRuntimeUiValidation > validates runtime config reads and the main control-plane mutations 33740ms
+
+ Test Files 1 passed (1)
+ Tests 2 passed (2)
+ Start at 12:08:30
+ Duration 42.36s (transform 5.07s, setup 0ms, collect 7.81s, tests 33.76s, environment 0ms, prepare 322ms)
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-arm-execution-mapping.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-arm-execution-mapping.green.txt
new file mode 100644
index 000000000..84e2e562d
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-arm-execution-mapping.green.txt
@@ -0,0 +1,13 @@
+command: corepack pnpm --filter @role-model-router/adapter-execution exec vitest run test/run106-arm-execution-mapping.test.ts
+exit code: 0
+
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/adapter-execution[39m
+
+ [32m✓[39m test/run106-arm-execution-mapping.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 22[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Start at [22m 19:09:52
+[2m Duration [22m 4.38s[2m (transform 1.41s, setup 0ms, collect 1.81s, tests 22ms, environment 1ms, prepare 600ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-arm-preference-expansion.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-arm-preference-expansion.green.txt
new file mode 100644
index 000000000..21a1d9532
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-arm-preference-expansion.green.txt
@@ -0,0 +1,3 @@
+run106-arm-preference-expansion GREEN
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-arm-preference-expansion.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-decision-provenance.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-decision-provenance.green.txt
new file mode 100644
index 000000000..e88f3f5de
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-decision-provenance.green.txt
@@ -0,0 +1,3 @@
+run106-canonical-decision-provenance GREEN
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-canonical-decision-provenance.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt
new file mode 100644
index 000000000..e230e3112
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-canonical-effort-emission.green.txt
@@ -0,0 +1,3 @@
+run106-canonical-effort-emission GREEN
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-canonical-effort-emission.test.ts
+result: 5 tests passed (5).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt
new file mode 100644
index 000000000..35ce108be
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-discovery-effort-projection.green.txt
@@ -0,0 +1,13 @@
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-discovery-effort-projection.test.ts
+exit code: 0
+
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-host-bridge[39m
+
+ [32m✓[39m test/run106-discovery-effort-projection.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 73[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m2 passed[39m[22m[90m (2)[39m
+[2m Start at [22m 18:48:57
+[2m Duration [22m 2.50s[2m (transform 589ms, setup 0ms, collect 1.59s, tests 73ms, environment 0ms, prepare 335ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt
new file mode 100644
index 000000000..80859ed76
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-aware-cache-continuity.green.txt
@@ -0,0 +1,3 @@
+run106-effort-aware-cache-continuity GREEN
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-aware-cache-continuity.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-migration.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-migration.green.txt
new file mode 100644
index 000000000..c29a9ee56
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-migration.green.txt
@@ -0,0 +1,13 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/sqlite-memory[39m
+
+(node:37852) ExperimentalWarning: SQLite is an experimental feature and might change at any time
+(Use `node --trace-warnings ...` to show where the warning was created)
+ [32m✓[39m test/run106-effort-source-migration.test.ts [2m([22m[2m1 test[22m[2m)[22m[33m 370[2mms[22m[39m
+ [33m[2m✓[22m[39m Run 106 effort-source migration[2m > [22mmigrates legacy and nullable effort_source rows deterministically to the four-state vocabulary [33m 367[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Start at [22m 12:49:45
+[2m Duration [22m 3.21s[2m (transform 696ms, setup 0ms, collect 1.40s, tests 370ms, environment 0ms, prepare 636ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt
new file mode 100644
index 000000000..9cb570a12
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-roundtrip.green.txt
@@ -0,0 +1,10 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/runtime-observability[39m
+
+ [32m✓[39m test/run106-effort-source-roundtrip.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 8[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m5 passed[39m[22m[90m (5)[39m
+[2m Start at [22m 12:49:41
+[2m Duration [22m 2.23s[2m (transform 416ms, setup 0ms, collect 1.01s, tests 8ms, environment 0ms, prepare 437ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-vocabulary.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-vocabulary.green.txt
new file mode 100644
index 000000000..dbcbb7726
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-effort-source-vocabulary.green.txt
@@ -0,0 +1,10 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/core[39m
+
+ [32m✓[39m test/run106-effort-source-vocabulary.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 10[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m5 passed[39m[22m[90m (5)[39m
+[2m Start at [22m 12:49:37
+[2m Duration [22m 1.48s[2m (transform 139ms, setup 0ms, collect 117ms, tests 10ms, environment 0ms, prepare 454ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-lineage-effort-source.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-lineage-effort-source.green.txt
new file mode 100644
index 000000000..b048ffeac
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-lineage-effort-source.green.txt
@@ -0,0 +1,10 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/trace[39m
+
+ [32m✓[39m test/run106-lineage-effort-source.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 19[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m3 passed[39m[22m[90m (3)[39m
+[2m Start at [22m 12:49:51
+[2m Duration [22m 1.34s[2m (transform 146ms, setup 0ms, collect 151ms, tests 19ms, environment 0ms, prepare 429ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt
new file mode 100644
index 000000000..dbcc6093e
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-non-inferiority-ranking.green.txt
@@ -0,0 +1,10 @@
+R8 GREEN - non-inferiority ranking integration (routeRequest)
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-non-inferiority-ranking.test.ts
+
+--- vitest stdout ---
+ RUN v3.2.4
+
+ ✓ test/run106-non-inferiority-ranking.test.ts (1 test) 12ms
+
+ Test Files 1 passed (1)
+ Tests 1 passed (1)
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt
new file mode 100644
index 000000000..19f40cd8c
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-registry-arm-expansion.green.txt
@@ -0,0 +1,13 @@
+command: corepack pnpm --filter @role-model-router/endpoint-registry exec vitest run test/run106-registry-arm-expansion.test.ts
+exit code: 0
+
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/endpoint-registry[39m
+
+ [32m✓[39m test/run106-registry-arm-expansion.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 25[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m4 passed[39m[22m[90m (4)[39m
+[2m Start at [22m 18:48:51
+[2m Duration [22m 2.28s[2m (transform 473ms, setup 0ms, collect 533ms, tests 25ms, environment 1ms, prepare 552ms)[22m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt
new file mode 100644
index 000000000..0d880fb41
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/run106-turn-aware-difficulty.green.txt
@@ -0,0 +1,7 @@
+SP5 GREEN - turn-aware difficulty repair (R7)
+command: corepack pnpm exec vitest run test/run106-turn-aware-difficulty.test.ts test/run98-a32-difficulty-spread.test.ts test/run106-turn-aware-hard-shortcut.test.ts test/craft-ask-difficulty.test.ts
+result: 4 files passed (4), 23 tests passed (23)
+ run106-turn-aware-difficulty.test.ts: 10 passed
+ run98-a32-difficulty-spread.test.ts: 5 passed (prior regression restored: tool-using schema task => hard)
+ run106-turn-aware-hard-shortcut.test.ts: 4 passed
+ craft-ask-difficulty.test.ts: 4 passed
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt
new file mode 100644
index 000000000..cdc27685c
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp1-effort-policy-normalization.green.txt
@@ -0,0 +1,4 @@
+SP1 GREEN - effort policy normalization
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-normalization.test.ts
+result: 6 tests passed (6)
+behavior: omitted->router, scalar->preferred, explicit strict/preferred authoritative, router ignores hint, invalid policy throws.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt
new file mode 100644
index 000000000..dde9b9b40
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp2-arm-expansion.green.txt
@@ -0,0 +1,3 @@
+SP2 GREEN - reasoning-effort arm expansion
+command: corepack pnpm --filter @role-model-router/endpoint-registry exec vitest run test/run106-arm-expansion.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt
new file mode 100644
index 000000000..9dc67cd5b
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-borrowed-quality-prior.green.txt
@@ -0,0 +1,3 @@
+SP3 GREEN - borrowed quality prior
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-borrowed-quality-prior.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt
new file mode 100644
index 000000000..3aafae490
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp3-producer.green.txt
@@ -0,0 +1,3 @@
+SP3 GREEN - producer (borrowed related-effort benchmark score)
+command: corepack pnpm --filter @role-model-router/profile-aggregator exec vitest run test/run106-related-effort-borrow.test.ts
+result: 5 tests passed (5).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt
new file mode 100644
index 000000000..62fd7a0a0
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4-effort-policy-resolution.green.txt
@@ -0,0 +1,3 @@
+SP4 GREEN - effort policy resolution
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-resolution.test.ts
+result: 5 tests passed (5).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4b-effort-policy-pool-application.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4b-effort-policy-pool-application.green.txt
new file mode 100644
index 000000000..9e57fe00c
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp4b-effort-policy-pool-application.green.txt
@@ -0,0 +1,12 @@
+
+ RUN v3.2.4 D:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-host-bridge
+
+(node:22004) ExperimentalWarning: SQLite is an experimental feature and might change at any time
+(Use `node --trace-warnings ...` to show where the warning was created)
+ ✓ test/run106-effort-policy-pool-application.test.ts (6 tests) 31ms
+
+ Test Files 1 passed (1)
+ Tests 6 passed (6)
+ Start at 11:43:36
+ Duration 9.58s (transform 5.64s, setup 0ms, collect 8.97s, tests 31ms, environment 0ms, prepare 233ms)
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp5-turn-aware-hard-shortcut.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp5-turn-aware-hard-shortcut.green.txt
new file mode 100644
index 000000000..6b41f8d51
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp5-turn-aware-hard-shortcut.green.txt
@@ -0,0 +1,3 @@
+SP5 GREEN - turn-aware hard shortcut
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-turn-aware-hard-shortcut.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp6-non-inferiority.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp6-non-inferiority.green.txt
new file mode 100644
index 000000000..3aeafc75c
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp6-non-inferiority.green.txt
@@ -0,0 +1,3 @@
+SP6 GREEN - non-inferiority preference
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-non-inferiority.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp7-effort-union-intersection.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp7-effort-union-intersection.green.txt
new file mode 100644
index 000000000..5edfc465d
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp7-effort-union-intersection.green.txt
@@ -0,0 +1,3 @@
+SP7 GREEN - effort union/intersection
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-effort-union-intersection.test.ts
+result: 4 tests passed (4).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth-surfaces.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth-surfaces.green.txt
new file mode 100644
index 000000000..288f360d4
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth-surfaces.green.txt
@@ -0,0 +1,21 @@
+SP8 GREEN - R11 remaining surfaces (model pool / benchmark / request / endpoints)
+command: corepack pnpm --filter @role-model-router/runtime-ui exec vitest run app/routes/endpoints.test.tsx app/routes/requests.test.tsx app/routes/control-benchmark.test.ts app/routes/control-models.test.ts app/routes/request-detail.test.tsx
+observed: PASS
+exitCode: 0
+
+--- vitest output ---
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-ui[39m
+
+ [32m✓[39m app/routes/requests.test.tsx [2m([22m[2m1 test[22m[2m)[22m[32m 7[2mms[22m[39m
+ [32m✓[39m app/routes/request-detail.test.tsx [2m([22m[2m7 tests[22m[2m)[22m[32m 10[2mms[22m[39m
+ [32m✓[39m app/routes/endpoints.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 39[2mms[22m[39m
+ [32m✓[39m app/routes/control-benchmark.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 80[2mms[22m[39m
+ [32m✓[39m app/routes/control-models.test.ts [2m([22m[2m33 tests[22m[2m)[22m[32m 181[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m5 passed[39m[22m[90m (5)[39m
+[2m Tests [22m [1m[32m45 passed[39m[22m[90m (45)[39m
+[2m Start at [22m 12:46:06
+[2m Duration [22m 5.55s[2m (transform 4.31s, setup 0ms, collect 15.49s, tests 318ms, environment 3ms, prepare 3.12s)[22m
+
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt
new file mode 100644
index 000000000..9ec30fb09
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/green/sp8-effort-truth.green.txt
@@ -0,0 +1,19 @@
+SP8 GREEN - R11 UI truthfulness (effort-truth projection)
+command: corepack pnpm --filter @role-model-router/runtime-ui exec vitest run app/lib/effort-truth.test.ts
+observed: PASS (exitCode 0)
+exitCode: 0
+
+--- vitest stdout ---
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-ui[39m
+
+ [32m✓[39m app/lib/effort-truth.test.ts [2m([22m[2m15 tests[22m[2m)[22m[32m 13[2mms[22m[39m
+
+[2m Test Files [22m [1m[32m1 passed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[32m15 passed[39m[22m[90m (15)[39m
+[2m Start at [22m 12:29:51
+[2m Duration [22m 1.61s[2m (transform 362ms, setup 0ms, collect 216ms, tests 13ms, environment 0ms, prepare 664ms)[22m
+
+
+--- vitest stderr ---
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l1-should-shortcut-wiring.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l1-should-shortcut-wiring.red.txt
new file mode 100644
index 000000000..4ebe4d754
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l1-should-shortcut-wiring.red.txt
@@ -0,0 +1,3 @@
+L-1 RED - shouldShortcutToHard is exported+tested but never called (dead code)
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-turn-aware-hard-shortcut.test.ts test/run106-turn-aware-difficulty.test.ts
+observed: the classifier classifyDifficultyFromSignals uses inline toolCount>0 && codeOrSchemaBurden (~line 1572), not shouldShortcutToHard; run106-turn-aware-hard-shortcut.test.ts tests a predicate that production never invokes.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l2-effort-arm-truth-wiring.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l2-effort-arm-truth-wiring.red.txt
new file mode 100644
index 000000000..3cdb9037e
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l2-effort-arm-truth-wiring.red.txt
@@ -0,0 +1,3 @@
+L-2 RED - formatEffortArmTruthDisclosure is unused in any surface
+command: corepack pnpm --filter @role-model-router/runtime-ui exec vitest run app/routes/router-candidates.test.tsx
+observed: 1 test failed - router-candidates.tsx does not reference formatEffortArmTruthDisclosure (uses separate formatEffectiveEffortDisclosure + classifyEffortEvidence/formatEffortEvidenceLabel).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l3-strict-no-effort.refusal.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l3-strict-no-effort.refusal.red.txt
new file mode 100644
index 000000000..7b16fc023
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/l3-strict-no-effort.refusal.red.txt
@@ -0,0 +1,3 @@
+L-3 RED - strict effort_policy with no effort is a typed refusal
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-resolution.test.ts
+observed: 1 test failed - resolveEffortPolicy({requestedEffort:undefined, policy:"strict"}) returned router_managed, expected strict_rejected.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m3-decision-effort-source.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m3-decision-effort-source.red.txt
new file mode 100644
index 000000000..faf5ae58c
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m3-decision-effort-source.red.txt
@@ -0,0 +1,3 @@
+M-3 RED - decision effort_source does not record client none/disabled source
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-canonical-decision-provenance.test.ts
+observed: 2 tests failed - effortResolution.source is ignored; decision effort_source stays provider_default for source none/disabled.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m3-disabled-none-emission.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m3-disabled-none-emission.red.txt
new file mode 100644
index 000000000..9dc80be8e
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m3-disabled-none-emission.red.txt
@@ -0,0 +1,3 @@
+M-3 RED - disabled/none EffortSource states are not emitted
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-normalization.test.ts test/run106-canonical-effort-emission.test.ts
+observed: 9 tests failed - normalizeReasoningEffortPolicy has no source field and maps none/off to scalar preferred; resolveEndpointExecutionEffort emits provider_default instead of disabled for reasoning.effort none/off.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m5-effort-source-schema-compat.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m5-effort-source-schema-compat.red.txt
new file mode 100644
index 000000000..8d33493fa
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/m5-effort-source-schema-compat.red.txt
@@ -0,0 +1,3 @@
+M-5 RED - router-decision effort_source backward compatibility
+command: corepack pnpm --filter @role-model/conformance exec vitest run src/run106-effort-source-schema-compat.test.ts
+observed: 1 test failed - effort_source enum is [named, disabled, provider_default, none]; legacy client/variant/variant_coerced missing.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/phase35-review-fixes.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/phase35-review-fixes.red.txt
new file mode 100644
index 000000000..88a2a5302
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/phase35-review-fixes.red.txt
@@ -0,0 +1,8 @@
+phase35-review-fixes RED (H-2, M-1, M-2, L-4)
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-phase35-review-fixes.test.ts
+observed: 5 tests failed, 1 passed (6):
+- M-1 getQualityMetric returns source "benchmark" not "borrowed" for a related-effort prior.
+- M-1 borrowed leader still establishes non-inferiority (chosen endpoint = benchmark-challenger).
+- M-2 non_inferiority_promotion receipt is undefined; NON_INFERIOR_PROMOTION selection reason absent.
+- H-2 requested_effort / requested_policy / effort_exact_arm_count_* fields are undefined.
+- L-4 effort_fallback_applied is undefined; EFFORT_FALLBACK_APPLIED selection reason absent.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-arm-execution-mapping.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-arm-execution-mapping.red.txt
new file mode 100644
index 000000000..12fae4739
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-arm-execution-mapping.red.txt
@@ -0,0 +1,35 @@
+command: corepack pnpm --filter @role-model-router/adapter-execution exec vitest run test/run106-arm-execution-mapping.test.ts
+exit code: 1
+
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/adapter-execution[39m
+
+ [31m❯[39m test/run106-arm-execution-mapping.test.ts [2m([22m[2m1 test[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 14[2mms[22m[39m
+[31m [31m×[31m run106 arm execution mapping (H-1)[2m > [22mresolves an expanded per-level arm back to its provider-default base source[39m[32m 12[2mms[22m[39m
+[31m → Chosen endpoint deepseek.personal.global.deepseek-v4-pro-max is not present in the registry sources.[39m
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Start at [22m 19:07:35
+[2m Duration [22m 2.27s[2m (transform 324ms, setup 0ms, collect 383ms, tests 14ms, environment 0ms, prepare 517ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\packages\adapter-execution:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-arm-execution-mapping.test.ts
+
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 1 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-arm-execution-mapping.test.ts[2m > [22mrun106 arm execution mapping (H-1)[2m > [22mresolves an expanded per-level arm back to its provider-default base source
+[31m[1mError[22m: Chosen endpoint deepseek.personal.global.deepseek-v4-pro-max is not present in the registry sources.[39m
+[36m [2m❯[22m resolveExecutionTarget src/index.ts:[2m510:9[22m[39m
+ [90m508| [39m }
+ [90m509| [39m
+ [90m510| [39m throw new Error(`Chosen endpoint ${endpointId} is not present in the…
+ [90m | [39m [31m^[39m
+ [90m511| [39m}
+ [90m512| [39m
+[90m [2m❯[22m test/run106-arm-execution-mapping.test.ts:[2m130:20[22m[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯[22m[39m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-arm-preference-expansion.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-arm-preference-expansion.red.txt
new file mode 100644
index 000000000..bb24146f3
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-arm-preference-expansion.red.txt
@@ -0,0 +1,3 @@
+run106-arm-preference-expansion RED
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-arm-preference-expansion.test.ts
+observed: 4 tests failed - expandPreferredEndpointIdsToEffortArms not exported; controller/advisory base-endpoint preference does not yet expand to eligible effort arms.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-canonical-decision-provenance.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-canonical-decision-provenance.red.txt
new file mode 100644
index 000000000..f4127361f
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-canonical-decision-provenance.red.txt
@@ -0,0 +1,3 @@
+run106-canonical-decision-provenance RED
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-canonical-decision-provenance.test.ts
+observed: 4 tests failed - routeRequest still emits legacy effort_source (none/variant) and does not record effort_resolution/effective_effort.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-canonical-effort-emission.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-canonical-effort-emission.red.txt
new file mode 100644
index 000000000..8f0d50ce4
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-canonical-effort-emission.red.txt
@@ -0,0 +1,3 @@
+run106-canonical-effort-emission RED
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-canonical-effort-emission.test.ts
+observed: 5 tests failed - resolveEndpointExecutionEffort still emits legacy effort_source (client/none/variant/variant_coerced), no canonical EffortSource + coerced receipt.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-discovery-effort-projection.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-discovery-effort-projection.red.txt
new file mode 100644
index 000000000..09e3348b5
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-discovery-effort-projection.red.txt
@@ -0,0 +1,49 @@
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-discovery-effort-projection.test.ts
+exit code: 1
+
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-host-bridge[39m
+
+ [31m❯[39m test/run106-discovery-effort-projection.test.ts [2m([22m[2m2 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 71[2mms[22m[39m
+ [32m✓[39m run106 discovery effort projection (R9 integration)[2m > [22mpublishes the pool-wide effort union and portable intersection[32m 45[2mms[22m[39m
+[31m [31m×[31m run106 discovery effort projection (R9 integration)[2m > [22mincludes provider-default declared levels in the union/intersection[39m[32m 23[2mms[22m[39m
+[31m → expected { …(2) } to deeply equal { Object (union, portableIntersection) }[39m
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m1 failed[39m[22m[2m | [22m[1m[32m1 passed[39m[22m[90m (2)[39m
+[2m Start at [22m 18:45:03
+[2m Duration [22m 2.50s[2m (transform 594ms, setup 0ms, collect 1.62s, tests 71ms, environment 1ms, prepare 323ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\apps\runtime-host-bridge:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-discovery-effort-projection.test.ts
+
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 1 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-discovery-effort-projection.test.ts[2m > [22mrun106 discovery effort projection (R9 integration)[2m > [22mincludes provider-default declared levels in the union/intersection
+[31m[1mAssertionError[22m: expected { …(2) } to deeply equal { Object (union, portableIntersection) }[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[33m@@ -4,8 +4,7 @@[39m
+[2m ],[22m
+[2m "union": [[22m
+[2m "high",[22m
+[2m "low",[22m
+[2m "max",[22m
+[32m- "medium",[39m
+[2m ],[22m
+[2m }[22m
+
+[36m [2m❯[22m test/run106-discovery-effort-projection.test.ts:[2m128:30[22m[39m
+ [90m126| [39m })[33m;[39m
+ [90m127| [39m
+ [90m128| [39m [34mexpect[39m(discovery[33m.[39meffort)[33m.[39m[34mtoEqual[39m({
+ [90m | [39m [31m^[39m
+ [90m129| [39m union[33m:[39m [[32m"high"[39m[33m,[39m [32m"low"[39m[33m,[39m [32m"max"[39m[33m,[39m [32m"medium"[39m][33m,[39m
+ [90m130| [39m portableIntersection[33m:[39m [[32m"low"[39m][33m,[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯[22m[39m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-aware-cache-continuity.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-aware-cache-continuity.red.txt
new file mode 100644
index 000000000..12d9fbaa6
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-aware-cache-continuity.red.txt
@@ -0,0 +1,3 @@
+run106-effort-aware-cache-continuity RED
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-aware-cache-continuity.test.ts
+observed: 4 tests failed - toCacheContinuityScopeDescriptor is not exported and the cache continuity scope key is not effort-aware.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-migration.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-migration.red.txt
new file mode 100644
index 000000000..b085ef643
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-migration.red.txt
@@ -0,0 +1,74 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/sqlite-memory[39m
+
+(node:28344) ExperimentalWarning: SQLite is an experimental feature and might change at any time
+(Use `node --trace-warnings ...` to show where the warning was created)
+ [31m❯[39m test/run106-effort-source-migration.test.ts [2m([22m[2m1 test[22m[2m | [22m[31m1 failed[39m[2m)[22m[33m 340[2mms[22m[39m
+[31m [31m×[31m Run 106 effort-source migration[2m > [22mmigrates legacy and nullable effort_source rows deterministically to the four-state vocabulary[39m[33m 337[2mms[22m[39m
+[31m → expected [ …(6) ] to deeply equal [ …(6) ][39m
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 1 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-migration.test.ts[2m > [22mRun 106 effort-source migration[2m > [22mmigrates legacy and nullable effort_source rows deterministically to the four-state vocabulary
+[31m[1mAssertionError[22m: expected [ …(6) ] to deeply equal [ …(6) ][39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[2m [[22m
+[2m {[22m
+[32m- "effort_source": "named",[39m
+[31m+ "effort_source": "client",[39m
+[2m "reasoning_effort": "high",[22m
+[2m "request_id": "req-client",[22m
+[2m },[22m
+[2m {[22m
+[32m- "effort_source": "named",[39m
+[31m+ "effort_source": "variant",[39m
+[2m "reasoning_effort": "high",[22m
+[2m "request_id": "req-variant",[22m
+[2m },[22m
+[2m {[22m
+[2m "effort_source": "variant_coerced",[22m
+[2m "reasoning_effort": "max",[22m
+[2m "request_id": "req-coerced",[22m
+[2m },[22m
+[2m {[22m
+[32m- "effort_source": "provider_default",[39m
+[31m+ "effort_source": "none",[39m
+[2m "reasoning_effort": null,[22m
+[2m "request_id": "req-none",[22m
+[2m },[22m
+[2m {[22m
+[32m- "effort_source": "named",[39m
+[31m+ "effort_source": null,[39m
+[2m "reasoning_effort": "low",[22m
+[2m "request_id": "req-null-named",[22m
+[2m },[22m
+[2m {[22m
+[32m- "effort_source": "provider_default",[39m
+[31m+ "effort_source": null,[39m
+[2m "reasoning_effort": null,[22m
+[2m "request_id": "req-null-default",[22m
+[2m },[22m
+[2m ][22m
+
+[36m [2m❯[22m test/run106-effort-source-migration.test.ts:[2m51:22[22m[39m
+ [90m 49| [39m reopened[33m.[39m[34mclose[39m()[33m;[39m
+ [90m 50| [39m
+ [90m 51| [39m [34mexpect[39m(stored)[33m.[39m[34mtoEqual[39m([
+ [90m | [39m [31m^[39m
+ [90m 52| [39m { request_id: "req-client", reasoning_effort: "high", effort_s…
+ [90m 53| [39m { request_id: "req-variant", reasoning_effort: "high", effort_…
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯[22m[39m
+
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Start at [22m 12:44:46
+[2m Duration [22m 1.90s[2m (transform 432ms, setup 0ms, collect 492ms, tests 340ms, environment 0ms, prepare 429ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\packages\sqlite-memory:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-effort-source-migration.test.ts
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-roundtrip.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-roundtrip.red.txt
new file mode 100644
index 000000000..a0f7a4a8b
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-roundtrip.red.txt
@@ -0,0 +1,112 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/runtime-observability[39m
+
+ [31m❯[39m test/run106-effort-source-roundtrip.test.ts [2m([22m[2m5 tests[22m[2m | [22m[31m4 failed[39m[2m)[22m[32m 40[2mms[22m[39m
+[31m [31m×[31m Run 106 runtime effort-source round-trip[2m > [22mround-trips all four canonical states[39m[32m 21[2mms[22m[39m
+[31m → expected { reasoningEffort: 'high', …(1) } to deeply equal { reasoningEffort: 'high', …(2) }[39m
+[31m [31m×[31m Run 106 runtime effort-source round-trip[2m > [22mnormalizes legacy sources onto the canonical vocabulary[39m[32m 4[2mms[22m[39m
+[31m → expected { reasoningEffort: 'high', …(1) } to deeply equal { reasoningEffort: 'high', …(2) }[39m
+[31m [31m×[31m Run 106 runtime effort-source round-trip[2m > [22mdefaults a missing source to provider_default for a null-effort request[39m[32m 3[2mms[22m[39m
+[31m → expected { reasoningEffort: null, …(1) } to deeply equal { reasoningEffort: null, …(2) }[39m
+ [32m✓[39m Run 106 runtime effort-source round-trip[2m > [22mrejects a named source without a reasoning effort[32m 3[2mms[22m[39m
+[31m [31m×[31m Run 106 runtime effort-source round-trip[2m > [22mrejects a non-named source carrying a reasoning effort[39m[32m 5[2mms[22m[39m
+[31m → expected [Function] to throw an error[39m
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 4 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-roundtrip.test.ts[2m > [22mRun 106 runtime effort-source round-trip[2m > [22mround-trips all four canonical states
+[31m[1mAssertionError[22m: expected { reasoningEffort: 'high', …(1) } to deeply equal { reasoningEffort: 'high', …(2) }[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[2m {[22m
+[32m- "coerced": false,[39m
+[2m "effortSource": "named",[22m
+[2m "reasoningEffort": "high",[22m
+[2m }[22m
+
+[36m [2m❯[22m test/run106-effort-source-roundtrip.test.ts:[2m7:95[22m[39m
+ [90m 5| [39m[34mdescribe[39m([32m"Run 106 runtime effort-source round-trip"[39m[33m,[39m () [33m=>[39m {
+ [90m 6| [39m [34mtest[39m([32m"round-trips all four canonical states"[39m[33m,[39m () [33m=>[39m {
+ [90m 7| [39m expect(normalizeRuntimeEffortReceipt({ reasoningEffort: "high", ef…
+ [90m | [39m [31m^[39m
+ [90m 8| [39m { reasoningEffort: "high", effortSource: "named", coerced: false…
+ [90m 9| [39m )[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-roundtrip.test.ts[2m > [22mRun 106 runtime effort-source round-trip[2m > [22mnormalizes legacy sources onto the canonical vocabulary
+[31m[1mAssertionError[22m: expected { reasoningEffort: 'high', …(1) } to deeply equal { reasoningEffort: 'high', …(2) }[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[2m {[22m
+[32m- "coerced": false,[39m
+[32m- "effortSource": "named",[39m
+[31m+ "effortSource": "client",[39m
+[2m "reasoningEffort": "high",[22m
+[2m }[22m
+
+[36m [2m❯[22m test/run106-effort-source-roundtrip.test.ts:[2m24:96[22m[39m
+ [90m 22| [39m
+ [90m 23| [39m test("normalizes legacy sources onto the canonical vocabulary", () =…
+ [90m 24| [39m expect(normalizeRuntimeEffortReceipt({ reasoningEffort: "high", ef…
+ [90m | [39m [31m^[39m
+ [90m 25| [39m { reasoningEffort: "high", effortSource: "named", coerced: false…
+ [90m 26| [39m )[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-roundtrip.test.ts[2m > [22mRun 106 runtime effort-source round-trip[2m > [22mdefaults a missing source to provider_default for a null-effort request
+[31m[1mAssertionError[22m: expected { reasoningEffort: null, …(1) } to deeply equal { reasoningEffort: null, …(2) }[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[2m {[22m
+[32m- "coerced": false,[39m
+[32m- "effortSource": "provider_default",[39m
+[31m+ "effortSource": "none",[39m
+[2m "reasoningEffort": null,[22m
+[2m }[22m
+
+[36m [2m❯[22m test/run106-effort-source-roundtrip.test.ts:[2m36:70[22m[39m
+ [90m 34| [39m
+ [90m 35| [39m test("defaults a missing source to provider_default for a null-effor…
+ [90m 36| [39m expect(normalizeRuntimeEffortReceipt({ reasoningEffort: null })).t…
+ [90m | [39m [31m^[39m
+ [90m 37| [39m reasoningEffort[33m:[39m [35mnull[39m[33m,[39m
+ [90m 38| [39m effortSource[33m:[39m [32m"provider_default"[39m[33m,[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-roundtrip.test.ts[2m > [22mRun 106 runtime effort-source round-trip[2m > [22mrejects a non-named source carrying a reasoning effort
+[31m[1mAssertionError[22m: expected [Function] to throw an error[39m
+
+[32m- Expected:[39m
+null
+
+[31m+ Received:[39m
+undefined
+
+[36m [2m❯[22m test/run106-effort-source-roundtrip.test.ts:[2m52:7[22m[39m
+ [90m 50| [39m [34mexpect[39m(() [33m=>[39m
+ [90m 51| [39m normalizeRuntimeEffortReceipt({ reasoningEffort: "high", effortS…
+ [90m 52| [39m )[33m.[39m[34mtoThrow[39m([36m/disabled|reasoningEffort|effort/i[39m)[33m;[39m
+ [90m | [39m [31m^[39m
+ [90m 53| [39m })[33m;[39m
+ [90m 54| [39m})[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯[22m[39m
+
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m4 failed[39m[22m[2m | [22m[1m[32m1 passed[39m[22m[90m (5)[39m
+[2m Start at [22m 12:44:41
+[2m Duration [22m 2.31s[2m (transform 370ms, setup 0ms, collect 993ms, tests 40ms, environment 1ms, prepare 438ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\packages\runtime-observability:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-effort-source-roundtrip.test.ts
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-vocabulary.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-vocabulary.red.txt
new file mode 100644
index 000000000..69f7fe333
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-effort-source-vocabulary.red.txt
@@ -0,0 +1,93 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/core[39m
+
+ [31m❯[39m test/run106-effort-source-vocabulary.test.ts [2m([22m[2m5 tests[22m[2m | [22m[31m5 failed[39m[2m)[22m[32m 25[2mms[22m[39m
+[31m [31m×[31m Run 106 effort-source vocabulary[2m > [22mround-trips all four canonical states losslessly[39m[32m 9[2mms[22m[39m
+[31m → (0 , normalizeEffortSource) is not a function[39m
+[31m [31m×[31m Run 106 effort-source vocabulary[2m > [22mmaps historical named sources onto the named state[39m[32m 1[2mms[22m[39m
+[31m → (0 , normalizeEffortSource) is not a function[39m
+[31m [31m×[31m Run 106 effort-source vocabulary[2m > [22mkeeps historical variant_coerced readable as a coerced named effort[39m[32m 1[2mms[22m[39m
+[31m → (0 , normalizeEffortSource) is not a function[39m
+[31m [31m×[31m Run 106 effort-source vocabulary[2m > [22mmigrates null, undefined, and empty deterministically to provider_default[39m[32m 1[2mms[22m[39m
+[31m → (0 , normalizeEffortSource) is not a function[39m
+[31m [31m×[31m Run 106 effort-source vocabulary[2m > [22mrejects unrecognized states instead of silently dropping them[39m[32m 9[2mms[22m[39m
+[31m → expected [Function] to throw error matching /effort_source/i but got '(0 , normalizeE…'[39m
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 5 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-vocabulary.test.ts[2m > [22mRun 106 effort-source vocabulary[2m > [22mround-trips all four canonical states losslessly
+[31m[1mTypeError[22m: (0 , normalizeEffortSource) is not a function[39m
+[36m [2m❯[22m test/run106-effort-source-vocabulary.test.ts:[2m7:12[22m[39m
+ [90m 5| [39m[34mdescribe[39m([32m"Run 106 effort-source vocabulary"[39m[33m,[39m () [33m=>[39m {
+ [90m 6| [39m [34mtest[39m([32m"round-trips all four canonical states losslessly"[39m[33m,[39m () [33m=>[39m {
+ [90m 7| [39m expect(normalizeEffortSource("named")).toEqual({ source: "named", …
+ [90m | [39m [31m^[39m
+ [90m 8| [39m expect(normalizeEffortSource("disabled")).toEqual({ source: "disab…
+ [90m 9| [39m [34mexpect[39m([34mnormalizeEffortSource[39m([32m"provider_default"[39m))[33m.[39m[34mtoEqual[39m({
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/5]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-vocabulary.test.ts[2m > [22mRun 106 effort-source vocabulary[2m > [22mmaps historical named sources onto the named state
+[31m[1mTypeError[22m: (0 , normalizeEffortSource) is not a function[39m
+[36m [2m❯[22m test/run106-effort-source-vocabulary.test.ts:[2m17:12[22m[39m
+ [90m 15| [39m
+ [90m 16| [39m [34mtest[39m([32m"maps historical named sources onto the named state"[39m[33m,[39m () [33m=>[39m {
+ [90m 17| [39m expect(normalizeEffortSource("client")).toEqual({ source: "named",…
+ [90m | [39m [31m^[39m
+ [90m 18| [39m expect(normalizeEffortSource("variant")).toEqual({ source: "named"…
+ [90m 19| [39m })[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/5]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-vocabulary.test.ts[2m > [22mRun 106 effort-source vocabulary[2m > [22mkeeps historical variant_coerced readable as a coerced named effort
+[31m[1mTypeError[22m: (0 , normalizeEffortSource) is not a function[39m
+[36m [2m❯[22m test/run106-effort-source-vocabulary.test.ts:[2m22:12[22m[39m
+ [90m 20| [39m
+ [90m 21| [39m test("keeps historical variant_coerced readable as a coerced named e…
+ [90m 22| [39m expect(normalizeEffortSource("variant_coerced")).toEqual({ source:…
+ [90m | [39m [31m^[39m
+ [90m 23| [39m })[33m;[39m
+ [90m 24| [39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/5]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-vocabulary.test.ts[2m > [22mRun 106 effort-source vocabulary[2m > [22mmigrates null, undefined, and empty deterministically to provider_default
+[31m[1mTypeError[22m: (0 , normalizeEffortSource) is not a function[39m
+[36m [2m❯[22m test/run106-effort-source-vocabulary.test.ts:[2m26:12[22m[39m
+ [90m 24| [39m
+ [90m 25| [39m test("migrates null, undefined, and empty deterministically to provi…
+ [90m 26| [39m expect(normalizeEffortSource(null)).toEqual({ source: "provider_de…
+ [90m | [39m [31m^[39m
+ [90m 27| [39m [34mexpect[39m([34mnormalizeEffortSource[39m(undefined))[33m.[39m[34mtoEqual[39m({
+ [90m 28| [39m source[33m:[39m [32m"provider_default"[39m[33m,[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/5]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-effort-source-vocabulary.test.ts[2m > [22mRun 106 effort-source vocabulary[2m > [22mrejects unrecognized states instead of silently dropping them
+[31m[1mAssertionError[22m: expected [Function] to throw error matching /effort_source/i but got '(0 , normalizeE…'[39m
+
+[32m- Expected:[39m
+/effort_source/i
+
+[31m+ Received:[39m
+"(0 , __vite_ssr_import_1__.normalizeEffortSource) is not a function"
+
+[36m [2m❯[22m test/run106-effort-source-vocabulary.test.ts:[2m35:50[22m[39m
+ [90m 33| [39m
+ [90m 34| [39m test("rejects unrecognized states instead of silently dropping them"…
+ [90m 35| [39m expect(() => normalizeEffortSource("bogus")).toThrow(/effort_sourc…
+ [90m | [39m [31m^[39m
+ [90m 36| [39m })[33m;[39m
+ [90m 37| [39m})[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/5]⎯[22m[39m
+
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m5 failed[39m[22m[90m (5)[39m
+[2m Start at [22m 12:44:37
+[2m Duration [22m 1.39s[2m (transform 111ms, setup 0ms, collect 103ms, tests 25ms, environment 0ms, prepare 418ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\packages\core:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-effort-source-vocabulary.test.ts
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-lineage-effort-source.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-lineage-effort-source.red.txt
new file mode 100644
index 000000000..ee470bc98
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-lineage-effort-source.red.txt
@@ -0,0 +1,55 @@
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/trace[39m
+
+ [31m❯[39m test/run106-lineage-effort-source.test.ts [2m([22m[2m3 tests[22m[2m | [22m[31m2 failed[39m[2m)[22m[32m 34[2mms[22m[39m
+[31m [31m×[31m Run 106 trace lineage effort-source[2m > [22mround-trips all four canonical effort states[39m[32m 19[2mms[22m[39m
+[31m → effort_source must be none when reasoning_effort is null.[39m
+ [32m✓[39m Run 106 trace lineage effort-source[2m > [22mrejects a named source without an effort level[32m 3[2mms[22m[39m
+[31m [31m×[31m Run 106 trace lineage effort-source[2m > [22mrejects a non-named source carrying an effort level[39m[32m 9[2mms[22m[39m
+[31m → expected [Function] to throw an error[39m
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 2 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-lineage-effort-source.test.ts[2m > [22mRun 106 trace lineage effort-source[2m > [22mround-trips all four canonical effort states
+[31m[1mError[22m: effort_source must be none when reasoning_effort is null.[39m
+[36m [2m❯[22m assertEffort src/lineage.ts:[2m84:11[22m[39m
+ [90m 82| [39m }
+ [90m 83| [39m [35mif[39m (reasoningEffort [33m===[39m [35mnull[39m [33m&&[39m effortSource [33m!==[39m [32m"none"[39m) {
+ [90m 84| [39m throw new Error("effort_source must be none when reasoning_effort …
+ [90m | [39m [31m^[39m
+ [90m 85| [39m }
+ [90m 86| [39m [35mif[39m (reasoningEffort [33m!==[39m [35mnull[39m [33m&&[39m effortSource [33m===[39m [32m"none"[39m) {
+[90m [2m❯[22m validateTraceLineageManifest src/lineage.ts:[2m168:3[22m[39m
+[90m [2m❯[22m createTraceLineageManifest src/lineage.ts:[2m208:3[22m[39m
+[90m [2m❯[22m test/run106-lineage-effort-source.test.ts:[2m60:7[22m[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/2]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-lineage-effort-source.test.ts[2m > [22mRun 106 trace lineage effort-source[2m > [22mrejects a non-named source carrying an effort level
+[31m[1mAssertionError[22m: expected [Function] to throw an error[39m
+
+[32m- Expected:[39m
+null
+
+[31m+ Received:[39m
+undefined
+
+[36m [2m❯[22m test/run106-lineage-effort-source.test.ts:[2m83:7[22m[39m
+ [90m 81| [39m [34mexpect[39m(() [33m=>[39m
+ [90m 82| [39m createTraceLineageManifest(makeInput({ reasoning_effort: "high",…
+ [90m 83| [39m )[33m.[39m[34mtoThrow[39m([36m/effort|disabled/i[39m)[33m;[39m
+ [90m | [39m [31m^[39m
+ [90m 84| [39m })[33m;[39m
+ [90m 85| [39m})[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/2]⎯[22m[39m
+
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m2 failed[39m[22m[2m | [22m[1m[32m1 passed[39m[22m[90m (3)[39m
+[2m Start at [22m 12:44:50
+[2m Duration [22m 1.41s[2m (transform 179ms, setup 0ms, collect 212ms, tests 34ms, environment 1ms, prepare 461ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\packages\trace:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-lineage-effort-source.test.ts
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-non-inferiority-ranking.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-non-inferiority-ranking.red.txt
new file mode 100644
index 000000000..8baa7b776
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-non-inferiority-ranking.red.txt
@@ -0,0 +1,14 @@
+R8 RED - non-inferiority ranking integration (routeRequest)
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-non-inferiority-ranking.test.ts
+
+--- vitest stdout ---
+ RUN v3.2.4
+
+ FAIL test/run106-non-inferiority-ranking.test.ts > run106 non-inferiority ranking (R8 integration) > a non-inferior, materially faster and cheaper arm outranks a dominated weighted leader
+AssertionError: expected 'incumbent-dominated' to be 'challenger-non-inferior' // Object.is equality
+
+Expected: "challenger-non-inferior"
+Received: "incumbent-dominated"
+
+ Test Files 1 failed (1)
+ Tests 1 failed (1)
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-registry-arm-expansion.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-registry-arm-expansion.red.txt
new file mode 100644
index 000000000..990873d90
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-registry-arm-expansion.red.txt
@@ -0,0 +1,87 @@
+command: corepack pnpm --filter @role-model-router/endpoint-registry exec vitest run test/run106-registry-arm-expansion.test.ts
+exit code: 1
+
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/packages/endpoint-registry[39m
+
+ [31m❯[39m test/run106-registry-arm-expansion.test.ts [2m([22m[2m4 tests[22m[2m | [22m[31m3 failed[39m[2m)[22m[32m 54[2mms[22m[39m
+ [32m✓[39m run106 registry arm assembly[2m > [22mfixed-effort source yields a single fixed arm carrying its level in identity[32m 11[2mms[22m[39m
+[31m [31m×[31m run106 registry arm assembly[2m > [22mprovider-default source without reasoning capability keeps a single provider-default arm[39m[32m 19[2mms[22m[39m
+[31m → expected null to be undefined[39m
+[31m [31m×[31m run106 registry arm assembly[2m > [22mprovider-default source with an executable adapter expands declared levels into fixed arms plus a provider-default arm[39m[32m 10[2mms[22m[39m
+[31m → expected [ 'openai.effort.us-east-1' ] to deeply equal [ 'openai.effort.us-east-1', …(2) ][39m
+[31m [31m×[31m run106 registry arm assembly[2m > [22mprovider-default source with declared levels but no executable adapter keeps a single provider-default arm[39m[32m 3[2mms[22m[39m
+[31m → expected null to be undefined[39m
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [1m[31m3 failed[39m[22m[2m | [22m[1m[32m1 passed[39m[22m[90m (4)[39m
+[2m Start at [22m 18:44:58
+[2m Duration [22m 1.72s[2m (transform 222ms, setup 0ms, collect 229ms, tests 54ms, environment 1ms, prepare 510ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\packages\endpoint-registry:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-registry-arm-expansion.test.ts
+
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 3 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m test/run106-registry-arm-expansion.test.ts[2m > [22mrun106 registry arm assembly[2m > [22mprovider-default source without reasoning capability keeps a single provider-default arm
+[31m[1mAssertionError[22m: expected null to be undefined[39m
+
+[32m- Expected:[39m
+undefined
+
+[31m+ Received:[39m
+null
+
+[36m [2m❯[22m test/run106-registry-arm-expansion.test.ts:[2m136:59[22m[39m
+ [90m134| [39m [34mexpect[39m(result[33m.[39mendpoints)[33m.[39m[34mtoHaveLength[39m([34m1[39m)[33m;[39m
+ [90m135| [39m expect(result.endpoints[0].identity.endpoint_id).toBe(baseEndpoint…
+ [90m136| [39m expect(result.endpoints[0].identity.reasoning_effort).toBeUndefine…
+ [90m | [39m [31m^[39m
+ [90m137| [39m expect(result.endpoints[0].declared.reasoning_effort_levels).toEqu…
+ [90m138| [39m })[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-registry-arm-expansion.test.ts[2m > [22mrun106 registry arm assembly[2m > [22mprovider-default source with an executable adapter expands declared levels into fixed arms plus a provider-default arm
+[31m[1mAssertionError[22m: expected [ 'openai.effort.us-east-1' ] to deeply equal [ 'openai.effort.us-east-1', …(2) ][39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[2m [[22m
+[2m "openai.effort.us-east-1",[22m
+[32m- "openai.effort.us-east-1-low",[39m
+[32m- "openai.effort.us-east-1-high",[39m
+[2m ][22m
+
+[36m [2m❯[22m test/run106-registry-arm-expansion.test.ts:[2m150:79[22m[39m
+ [90m148| [39m })[33m;[39m
+ [90m149| [39m
+ [90m150| [39m expect(result.endpoints.map((endpoint) => endpoint.identity.endpoi…
+ [90m | [39m [31m^[39m
+ [90m151| [39m baseEndpointId[33m,[39m
+ [90m152| [39m [32m`[39m[36m${[39mbaseEndpointId[36m}[39m[32m-low`[39m[33m,[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m test/run106-registry-arm-expansion.test.ts[2m > [22mrun106 registry arm assembly[2m > [22mprovider-default source with declared levels but no executable adapter keeps a single provider-default arm
+[31m[1mAssertionError[22m: expected null to be undefined[39m
+
+[32m- Expected:[39m
+undefined
+
+[31m+ Received:[39m
+null
+
+[36m [2m❯[22m test/run106-registry-arm-expansion.test.ts:[2m176:59[22m[39m
+ [90m174| [39m [34mexpect[39m(result[33m.[39mendpoints)[33m.[39m[34mtoHaveLength[39m([34m1[39m)[33m;[39m
+ [90m175| [39m expect(result.endpoints[0].identity.endpoint_id).toBe(baseEndpoint…
+ [90m176| [39m expect(result.endpoints[0].identity.reasoning_effort).toBeUndefine…
+ [90m | [39m [31m^[39m
+ [90m177| [39m expect(result.endpoints[0].declared.reasoning_effort_levels).toEqu…
+ [90m178| [39m })[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯[22m[39m
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-turn-aware-difficulty.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-turn-aware-difficulty.red.txt
new file mode 100644
index 000000000..c3994f2f0
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/run106-turn-aware-difficulty.red.txt
@@ -0,0 +1,9 @@
+SP5 RED - turn-aware difficulty repair (R7)
+command: corepack pnpm exec vitest run test/run106-turn-aware-difficulty.test.ts
+observed: 6 failed | 4 passed (10)
+ - trivial follow-up in long session => still hard (expected below hard)
+ - trivial tool-bearing follow-up (no current-turn code/schema) => still hard (expected below hard)
+ - fresh genuinely risky tool/code/schema task => medium (expected hard)
+ - computeDifficultyFeatures => not a function (missing export)
+ - DIFFICULTY_CLASSIFIER_VERSION => undefined (missing export)
+ - shouldInvalidateDifficultyClassifierVersion => not a function (missing export)
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt
new file mode 100644
index 000000000..92acc7b8a
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp1-effort-policy-normalization.red.txt
@@ -0,0 +1,5 @@
+SP1 RED - effort policy normalization
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-normalization.test.ts
+expected: import { normalizeReasoningEffortPolicy } resolves
+observed: FAIL - module resolution error (normalizeReasoningEffortPolicy not yet exported from ../src/index.js)
+This is the RED state: the behavior under test does not exist yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp2-arm-expansion.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp2-arm-expansion.red.txt
new file mode 100644
index 000000000..cf7d25011
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp2-arm-expansion.red.txt
@@ -0,0 +1,3 @@
+SP2 RED - reasoning-effort arm expansion
+command: corepack pnpm --filter @role-model-router/endpoint-registry exec vitest run test/run106-arm-expansion.test.ts
+observed: 4 tests failed - expandReasoningEffortArms not exported yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-borrowed-quality-prior.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-borrowed-quality-prior.red.txt
new file mode 100644
index 000000000..c662fc25d
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-borrowed-quality-prior.red.txt
@@ -0,0 +1,3 @@
+SP3 RED - borrowed quality prior
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-borrowed-quality-prior.test.ts
+observed: 4 tests failed - resolveBorrowedQualityPrior not exported yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-producer.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-producer.red.txt
new file mode 100644
index 000000000..d046e4e9d
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp3-producer.red.txt
@@ -0,0 +1,3 @@
+SP3 RED - producer (borrowed related-effort benchmark score)
+command: corepack pnpm --filter @role-model-router/profile-aggregator exec vitest run test/run106-related-effort-borrow.test.ts
+observed: 5 tests failed - resolveRelatedEffortOverallScore not exported yet (TypeError: not a function).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4-effort-policy-resolution.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4-effort-policy-resolution.red.txt
new file mode 100644
index 000000000..07041e5a4
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4-effort-policy-resolution.red.txt
@@ -0,0 +1,3 @@
+SP4 RED - effort policy resolution
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-effort-policy-resolution.test.ts
+observed: 5 tests failed - resolveEffortPolicy not exported yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4b-effort-policy-pool-application.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4b-effort-policy-pool-application.red.txt
new file mode 100644
index 000000000..ba34b2d26
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp4b-effort-policy-pool-application.red.txt
@@ -0,0 +1,144 @@
+
+ RUN v3.2.4 D:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-host-bridge
+
+(node:14752) ExperimentalWarning: SQLite is an experimental feature and might change at any time
+(Use `node --trace-warnings ...` to show where the warning was created)
+ ❯ test/run106-effort-policy-pool-application.test.ts (6 tests | 6 failed) 24ms
+ × run106 R3/R10: effort-policy resolution kind is recorded on the pool application > router policy records router_managed and keeps the pool and preference untouched 13ms
+ → expected undefined to be 'router_managed' // Object.is equality
+ × run106 R3/R10: effort-policy resolution kind is recorded on the pool application > strict with an exact arm records exact_primary and narrows to the exact arms 2ms
+ → expected undefined to be 'exact_primary' // Object.is equality
+ × run106 R3/R10: effort-policy resolution kind is recorded on the pool application > strict with no exact arm records strict_rejected and empties the pool 2ms
+ → expected undefined to be 'strict_rejected' // Object.is equality
+ × run106 R3/R10: effort-policy resolution kind is recorded on the pool application > preferred with an exact arm records exact_fallback_expanded and prefers the exact arms 1ms
+ → expected undefined to be 'exact_fallback_expanded' // Object.is equality
+ × run106 R3/R10: effort-policy resolution kind is recorded on the pool application > preferred with zero exact arms records unsupported_fallback and keeps the pool router-managed 1ms
+ → expected undefined to be 'unsupported_fallback' // Object.is equality
+ × run106 R3/R10: effort-policy resolution kind is recorded on the pool application > no requested effort records router_managed regardless of policy 1ms
+ → expected undefined to be 'router_managed' // Object.is equality
+
+⎯⎯⎯⎯⎯⎯⎯ Failed Tests 6 ⎯⎯⎯⎯⎯⎯⎯
+
+ FAIL test/run106-effort-policy-pool-application.test.ts > run106 R3/R10: effort-policy resolution kind is recorded on the pool application > router policy records router_managed and keeps the pool and preference untouched
+AssertionError: expected undefined to be 'router_managed' // Object.is equality
+
+- Expected:
+"router_managed"
+
++ Received:
+undefined
+
+ ❯ test/run106-effort-policy-pool-application.test.ts:93:32
+ 91| });
+ 92|
+ 93| expect(applied.resolution).toBe("router_managed");
+ | ^
+ 94| expect(applied.effectiveEffort).toBeNull();
+ 95| expect(applied.allowEndpoints).toEqual(aliasPool);
+
+⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯
+
+ FAIL test/run106-effort-policy-pool-application.test.ts > run106 R3/R10: effort-policy resolution kind is recorded on the pool application > strict with an exact arm records exact_primary and narrows to the exact arms
+AssertionError: expected undefined to be 'exact_primary' // Object.is equality
+
+- Expected:
+"exact_primary"
+
++ Received:
+undefined
+
+ ❯ test/run106-effort-policy-pool-application.test.ts:109:32
+ 107| });
+ 108|
+ 109| expect(applied.resolution).toBe("exact_primary");
+ | ^
+ 110| expect(applied.effectiveEffort).toBe("high");
+ 111| expect(applied.allowEndpoints).toEqual([
+
+⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/6]⎯
+
+ FAIL test/run106-effort-policy-pool-application.test.ts > run106 R3/R10: effort-policy resolution kind is recorded on the pool application > strict with no exact arm records strict_rejected and empties the pool
+AssertionError: expected undefined to be 'strict_rejected' // Object.is equality
+
+- Expected:
+"strict_rejected"
+
++ Received:
+undefined
+
+ ❯ test/run106-effort-policy-pool-application.test.ts:129:32
+ 127| });
+ 128|
+ 129| expect(applied.resolution).toBe("strict_rejected");
+ | ^
+ 130| expect(applied.effectiveEffort).toBeNull();
+ 131| expect(applied.allowEndpoints).toEqual([]);
+
+⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/6]⎯
+
+ FAIL test/run106-effort-policy-pool-application.test.ts > run106 R3/R10: effort-policy resolution kind is recorded on the pool application > preferred with an exact arm records exact_fallback_expanded and prefers the exact arms
+AssertionError: expected undefined to be 'exact_fallback_expanded' // Object.is equality
+
+- Expected:
+"exact_fallback_expanded"
+
++ Received:
+undefined
+
+ ❯ test/run106-effort-policy-pool-application.test.ts:145:32
+ 143| });
+ 144|
+ 145| expect(applied.resolution).toBe("exact_fallback_expanded");
+ | ^
+ 146| expect(applied.effectiveEffort).toBe("high");
+ 147| expect(applied.allowEndpoints).toEqual(aliasPool);
+
+⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/6]⎯
+
+ FAIL test/run106-effort-policy-pool-application.test.ts > run106 R3/R10: effort-policy resolution kind is recorded on the pool application > preferred with zero exact arms records unsupported_fallback and keeps the pool router-managed
+AssertionError: expected undefined to be 'unsupported_fallback' // Object.is equality
+
+- Expected:
+"unsupported_fallback"
+
++ Received:
+undefined
+
+ ❯ test/run106-effort-policy-pool-application.test.ts:165:32
+ 163| });
+ 164|
+ 165| expect(applied.resolution).toBe("unsupported_fallback");
+ | ^
+ 166| expect(applied.effectiveEffort).toBeNull();
+ 167| expect(applied.allowEndpoints).toEqual(aliasPool);
+
+⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/6]⎯
+
+ FAIL test/run106-effort-policy-pool-application.test.ts > run106 R3/R10: effort-policy resolution kind is recorded on the pool application > no requested effort records router_managed regardless of policy
+AssertionError: expected undefined to be 'router_managed' // Object.is equality
+
+- Expected:
+"router_managed"
+
++ Received:
+undefined
+
+ ❯ test/run106-effort-policy-pool-application.test.ts:181:32
+ 179| });
+ 180|
+ 181| expect(applied.resolution).toBe("router_managed");
+ | ^
+ 182| expect(applied.effectiveEffort).toBeNull();
+ 183| expect(applied.allowEndpoints).toEqual(aliasPool);
+
+⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/6]⎯
+
+
+ Test Files 1 failed (1)
+ Tests 6 failed (6)
+ Start at 11:39:19
+ Duration 11.35s (transform 6.71s, setup 0ms, collect 10.50s, tests 24ms, environment 1ms, prepare 299ms)
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\apps\runtime-host-bridge:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run test/run106-effort-policy-pool-application.test.ts
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp5-turn-aware-hard-shortcut.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp5-turn-aware-hard-shortcut.red.txt
new file mode 100644
index 000000000..1d2fa38f7
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp5-turn-aware-hard-shortcut.red.txt
@@ -0,0 +1,3 @@
+SP5 RED - turn-aware hard shortcut
+command: corepack pnpm --filter @role-model-router/runtime-host-bridge exec vitest run test/run106-turn-aware-hard-shortcut.test.ts
+observed: 4 tests failed - shouldShortcutToHard not exported yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp6-non-inferiority.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp6-non-inferiority.red.txt
new file mode 100644
index 000000000..65d8fa1e2
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp6-non-inferiority.red.txt
@@ -0,0 +1,3 @@
+SP6 RED - non-inferiority preference
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-non-inferiority.test.ts
+observed: 4 tests failed - shouldPreferNonInferiorChallenger not exported yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp7-effort-union-intersection.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp7-effort-union-intersection.red.txt
new file mode 100644
index 000000000..55b89660e
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp7-effort-union-intersection.red.txt
@@ -0,0 +1,3 @@
+SP7 RED - effort union/intersection
+command: corepack pnpm --filter @role-model-router/core exec vitest run test/run106-effort-union-intersection.test.ts
+observed: 4 tests failed - computeEffortUnionAndIntersection not exported yet.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp8-effort-truth-surfaces.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp8-effort-truth-surfaces.red.txt
new file mode 100644
index 000000000..e58818629
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp8-effort-truth-surfaces.red.txt
@@ -0,0 +1,4587 @@
+SP8 RED - R11 remaining surfaces (model pool / benchmark / request / endpoints)
+command: corepack pnpm --filter @role-model-router/runtime-ui exec vitest run app/routes/endpoints.test.tsx app/routes/requests.test.tsx app/routes/control-benchmark.test.ts app/routes/control-models.test.ts app/routes/request-detail.test.tsx
+observed: FAIL (expected RED)
+exitCode: 1
+
+--- vitest output ---
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-ui[39m
+
+ [31m❯[39m app/routes/requests.test.tsx [2m([22m[2m1 test[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 33[2mms[22m[39m
+[31m [31m×[31m run 106 R11 request surface truthfulness[2m > [22mshows the endpoint's effective reasoning effort, not just its label[39m[32m 29[2mms[22m[39m
+[31m → expected 'import { ChartGrid, ChartGridCell, Fi…' to contain 'formatEffectiveEffortDisclosure'[39m
+ [31m❯[39m app/routes/endpoints.test.tsx [2m([22m[2m2 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 84[2mms[22m[39m
+ [32m✓[39m buildRuntimeConnectionRows[2m > [22mlists route-eligible provider endpoints without presenting the legacy LiteLLM vendor proxy as a second endpoint[32m 51[2mms[22m[39m
+[31m [31m×[31m buildRuntimeConnectionRows[2m > [22mlabels each endpoint row's effective reasoning effort (R11)[39m[32m 25[2mms[22m[39m
+[31m → expected [ { …(10) }, { …(10) } ] to deep equally contain ObjectContaining{…}[39m
+ [31m❯[39m app/routes/request-detail.test.tsx [2m([22m[2m7 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 49[2mms[22m[39m
+ [32m✓[39m request detail token truth[2m > [22mrenders available measured input usage from backend truth[32m 10[2mms[22m[39m
+ [32m✓[39m request detail token truth[2m > [22mrenders available normalized input usage from backend truth[32m 1[2mms[22m[39m
+ [32m✓[39m request detail token truth[2m > [22mrenders available estimated input usage from backend truth[32m 1[2mms[22m[39m
+ [32m✓[39m request detail token truth[2m > [22mdoes not render a numeric placeholder when input usage is unavailable[32m 1[2mms[22m[39m
+ [32m✓[39m request detail token truth[2m > [22mdoes not infer token provenance from numeric presence[32m 1[2mms[22m[39m
+ [32m✓[39m request detail token truth[2m > [22mreads only canonical prompt-cache request provenance[32m 1[2mms[22m[39m
+[31m [31m×[31m shows effective reasoning effort on the request detail (R11)[39m[32m 30[2mms[22m[39m
+[31m → expected 'import { useEffect, useState } from "…' to contain 'formatEffectiveEffortDisclosure'[39m
+ [31m❯[39m app/routes/control-benchmark.test.ts [2m([22m[2m2 tests[22m[2m | [22m[31m1 failed[39m[2m)[22m[32m 137[2mms[22m[39m
+ [32m✓[39m publishes essential benchmark controls while advisory reads remain pending[32m 85[2mms[22m[39m
+[31m [31m×[31m labels benchmark score evidence as exact/borrowed/prior (R11)[39m[32m 49[2mms[22m[39m
+[31m → expected 'import { useCallback, useEffect, useM…' to contain 'classifyEffortEvidence'[39m
+ [31m❯[39m app/routes/control-models.test.ts [2m([22m[2m33 tests[22m[2m | [22m[31m2 failed[39m[2m)[22m[32m 243[2mms[22m[39m
+ [32m✓[39m selects benchmark evidence by exact endpoint instead of the highest same-model sibling[32m 8[2mms[22m[39m
+ [32m✓[39m reads the canonical operational sample_size for one exact endpoint variant[32m 2[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mkeeps transient role drafts separate for effort endpoint siblings[32m 2[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mkeeps the role list in document flow without an artificial viewport cap[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mserializes checked all roles as an explicit all assignment[32m 32[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mserializes removed roles as an explicit exclude assignment[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mpersists role eligibility for one endpoint instance without replacing its effort siblings[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mserializes unchecked all roles as explicit empty include instead of default all[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22muses explicit eject labels for peer-backed and remote-backed configured models[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22menables the footer action for remote and peer-backed configured models[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mkeeps controller removal disabled and uses unload only for llama-swap models[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22menables a destructive-confirmation eject action for the sole controller[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mnever bypasses final-controller eject confirmation through a local unload action[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22medits the account that owns the selected effort endpoint instead of the first model match[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mrequires an explicit second click for destructive eject actions[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mprefers the controller-backed card as the default selected model detail[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mfalls back to the first active card when no controller-backed model exists[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mfalls back to the first healthy card when inactive or offline cards appear first[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mreturns null when no configured model cards exist[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mmaps configured model card status pills to the paper-aligned tones[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mbuilds configured model inventory pills with paper-aligned chip grammar[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mbuilds selected-model evidence pills using the paper token hierarchy[32m 1[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mshows a neutral no-evidence pill when benchmark evidence is absent[32m 0[2mms[22m[39m
+ [32m✓[39m control model role assignment helpers[2m > [22mbuilds the compact Paper preview payload instead of dumping full endpoint records[32m 0[2mms[22m[39m
+ [32m✓[39m startDeferredConfiguredModelsBootstrap[2m > [22mwaits for the initial configured model inventory to settle before fetching deferred request evidence[32m 59[2mms[22m[39m
+ [32m✓[39m startDeferredConfiguredModelsBootstrap[2m > [22mpreserves the visible model inventory when deferred request evidence fails[32m 60[2mms[22m[39m
+ [32m✓[39m configured model mutation convergence[2m > [22mreloads canonical endpoint eligibility after saving account role bindings[32m 3[2mms[22m[39m
+ [32m✓[39m configured model mutation convergence[2m > [22mdescribes the real role-derived task and group impact for an account[32m 1[2mms[22m[39m
+ [32m✓[39m configured model mutation convergence[2m > [22mconverges role binding saves from the returned account without advisory reloads[32m 1[2mms[22m[39m
+ [32m✓[39m configured model mutation convergence[2m > [22mreloads only canonical inventory surfaces after an eject receipt[32m 1[2mms[22m[39m
+ [32m✓[39m describeConfiguredModelRequestEvidence[2m > [22mkeeps request-evidence copy truthful while deferred request history is pending or unavailable[32m 1[2mms[22m[39m
+[31m [31m×[31m labels model-pool benchmark evidence as exact/borrowed/prior (R11)[39m[32m 21[2mms[22m[39m
+[31m → expected [ …(2) ] to deep equally contain { …(2) }[39m
+[31m [31m×[31m computes model-pool evidence from the candidate's benchmark capability (R11)[39m[32m 31[2mms[22m[39m
+[31m → expected 'import { useEffect, useMemo, useState…' to contain 'classifyEffortEvidence'[39m
+
+[2m Test Files [22m [1m[31m5 failed[39m[22m[90m (5)[39m
+[2m Tests [22m [1m[31m6 failed[39m[22m[2m | [22m[1m[32m39 passed[39m[22m[90m (45)[39m
+[2m Start at [22m 12:43:18
+[2m Duration [22m 6.09s[2m (transform 4.65s, setup 0ms, collect 16.34s, tests 546ms, environment 2ms, prepare 3.18s)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\apps\runtime-ui:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run app/routes/endpoints.test.tsx app/routes/requests.test.tsx app/routes/control-benchmark.test.ts app/routes/control-models.test.ts app/routes/request-detail.test.tsx
+
+
+[31m⎯⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Tests 6 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m app/routes/control-benchmark.test.ts[2m > [22mlabels benchmark score evidence as exact/borrowed/prior (R11)
+[31m[1mAssertionError[22m: expected 'import { useCallback, useEffect, useM…' to contain 'classifyEffortEvidence'[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[32m- classifyEffortEvidence[39m
+[31m+ import { useCallback, useEffect, useMemo, useState } from "react";[39m
+[31m+[39m
+[31m+ import { CheckboxControl } from "../components/checkbox-control";[39m
+[31m+ import {[39m
+[31m+ Badge,[39m
+[31m+ DisclosureSection,[39m
+[31m+ EmptyState,[39m
+[31m+ ErrorState,[39m
+[31m+ LoadingState,[39m
+[31m+ SectionCard,[39m
+[31m+ SelectField,[39m
+[31m+ } from "../components/page-primitives";[39m
+[31m+ import { computeLatencyPercentiles } from "../lib/benchmark-latency";[39m
+[31m+ import {[39m
+[31m+ filterBenchmarkRunnableCandidates,[39m
+[31m+ isBenchmarkRunnableCandidate,[39m
+[31m+ } from "../lib/benchmark-model-cards";[39m
+[31m+ import {[39m
+[31m+ bodyStrongTextClassName,[39m
+[31m+ bodyTextClassName,[39m
+[31m+ compactTitleClassName,[39m
+[31m+ listRowClassName,[39m
+[31m+ monoEyebrowClassName,[39m
+[31m+ mutedPanelClassName,[39m
+[31m+ primaryButtonClassName,[39m
+[31m+ secondaryButtonClassName,[39m
+[31m+ supportingTextClassName,[39m
+[31m+ } from "../lib/design-system";[39m
+[31m+ import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";[39m
+[31m+ import { formatScore, formatScoreWithCoverage } from "../lib/format-score";[39m
+[31m+ import {[39m
+[31m+ type BenchmarkCaseAuditEntry,[39m
+[31m+ type BenchmarkEndpointGrade,[39m
+[31m+ type BenchmarkRunListEntry,[39m
+[31m+ type BenchmarkRunProgress,[39m
+[31m+ type BenchmarkRunResult,[39m
+[31m+ type BenchmarkSuite,[39m
+[31m+ type BenchmarkSummary,[39m
+[31m+ type BenchmarkSummarySubject,[39m
+[31m+ type RouterCandidate,[39m
+[31m+ type RuntimeSummary,[39m
+[31m+ clearAllBenchmarkData,[39m
+[31m+ clearBenchmarkEndpointData,[39m
+[31m+ fetchActiveBenchmarkRun,[39m
+[31m+ fetchBenchmarkPreferences,[39m
+[31m+ fetchBenchmarkRunProgress,[39m
+[31m+ fetchBenchmarkRuns,[39m
+[31m+ fetchBenchmarkSuite,[39m
+[31m+ fetchBenchmarkSummary,[39m
+[31m+ fetchRouterCandidates,[39m
+[31m+ fetchRuntimeSummary,[39m
+[31m+ startCapabilityBenchmark,[39m
+[31m+ updateBenchmarkPreferences,[39m
+[31m+ } from "../lib/runtime-api";[39m
+[31m+[39m
+[31m+ const BENCHMARK_POLL_MS = 1500;[39m
+[31m+ const BENCHMARK_STALL_MS = 90_000;[39m
+[31m+ const ACTIVE_BENCHMARK_RUN_KEY = "role-model.benchmark.activeRunId";[39m
+[31m+ const benchmarkDenseHeaderCellClassName =[39m
+[31m+ "font-mono text-[11px] font-normal uppercase tracking-[0.08em] text-[var(--rm-muted)]";[39m
+[31m+ const benchmarkDenseCellClassName =[39m
+[31m+ "font-mono text-[13px] font-semibold tabular-nums leading-[18px] text-[var(--rm-fg)]";[39m
+[31m+ const benchmarkDenseActionClassName =[39m
+[31m+ "inline-flex h-[34px] min-h-[34px] items-center rounded-[var(--rm-radius-field)] border border-[var(--rm-border-strong)] bg-[var(--rm-panel)] px-3 text-[13px] font-semibold leading-[18px] text-[var(--rm-fg)] transition hover:border-[var(--rm-accent)] disabled:opacity-60";[39m
+[31m+[39m
+[31m+ function describeBenchmarkProgress(progress: BenchmarkRunProgress): {[39m
+[31m+ readonly phaseLabel: string;[39m
+[31m+ readonly detail: string;[39m
+[31m+ } {[39m
+[31m+ if (progress.runPhase === "execution") {[39m
+[31m+ return {[39m
+[31m+ phaseLabel: "Phase 1 of 3 · Recording responses",[39m
+[31m+ detail: [[39m
+[31m+ progress.currentEndpointModelId[39m
+[31m+ ? `model ${progress.endpointIndex}/${progress.endpointCount}: ${progress.currentEndpointModelId}`[39m
+[31m+ : null,[39m
+[31m+ progress.currentCaseId[39m
+[31m+ ? `case ${progress.caseIndex}/${progress.caseCount} (${progress.currentCaseId})`[39m
+[31m+ : null,[39m
+[31m+ progress.currentPhase === "execute"[39m
+[31m+ ? "running benchmark cases and saving deliverables"[39m
+[31m+ : "preparing execution pass",[39m
+[31m+ ][39m
+[31m+ .filter(Boolean)[39m
+[31m+ .join(" • "),[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ if (progress.runPhase === "compare") {[39m
+[31m+ return {[39m
+[31m+ phaseLabel: "Phase 3 of 3 · Head-to-head compare",[39m
+[31m+ detail: [[39m
+[31m+ progress.currentCaseId[39m
+[31m+ ? `case ${progress.caseIndex}/${progress.caseCount} (${progress.currentCaseId})`[39m
+[31m+ : null,[39m
+[31m+ progress.currentPhase === "compare"[39m
+[31m+ ? "ranking subjects for this case"[39m
+[31m+ : "preparing compare pass",[39m
+[31m+ ][39m
+[31m+ .filter(Boolean)[39m
+[31m+ .join(" • "),[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return {[39m
+[31m+ phaseLabel: "Phase 2 of 3 · Judge grading",[39m
+[31m+ detail: [[39m
+[31m+ progress.currentEndpointModelId[39m
+[31m+ ? `model ${progress.endpointIndex}/${progress.endpointCount}: ${progress.currentEndpointModelId}`[39m
+[31m+ : null,[39m
+[31m+ progress.currentCaseId[39m
+[31m+ ? `case ${progress.caseIndex}/${progress.caseCount} (${progress.currentCaseId})`[39m
+[31m+ : null,[39m
+[31m+ progress.currentPhase === "judge"[39m
+[31m+ ? "scoring recorded deliverables"[39m
+[31m+ : "grading saved responses",[39m
+[31m+ ][39m
+[31m+ .filter(Boolean)[39m
+[31m+ .join(" • "),[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function asRecord(value: unknown): Record | null {[39m
+[31m+ return typeof value === "object" && value !== null ? (value as Record) : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function pickNumber(record: Record | null, ...keys: string[]): number | null {[39m
+[31m+ for (const key of keys) {[39m
+[31m+ const value = record?.[key];[39m
+[31m+ if (typeof value === "number" && Number.isFinite(value)) {[39m
+[31m+ return value;[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function formatLatencyMs(value: number | null | undefined): string {[39m
+[31m+ if (typeof value !== "number" || !Number.isFinite(value)) {[39m
+[31m+ return "n/a";[39m
+[31m+ }[39m
+[31m+ return `${Math.round(value)} ms`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function resolveJudgeLabel([39m
+[31m+ summary: BenchmarkSummary,[39m
+[31m+ candidates: readonly RouterCandidate[],[39m
+[31m+ ): string | null {[39m
+[31m+ return ([39m
+[31m+ (() => {[39m
+[31m+ const candidate = candidates.find((entry) => entry.endpointId === summary.judgeEndpointId);[39m
+[31m+ return candidate ? formatModelIdentity(candidate) : null;[39m
+[31m+ })() ??[39m
+[31m+ summary.judgeModelId ??[39m
+[31m+ summary.judgeEndpointId ??[39m
+[31m+ null[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function collectEndpointLatencies(input: {[39m
+[31m+ readonly endpointId: string;[39m
+[31m+ readonly caseResults: BenchmarkEndpointGrade["caseResults"] | null;[39m
+[31m+ readonly caseAudits: readonly BenchmarkCaseAuditEntry[] | undefined;[39m
+[31m+ }): readonly number[] {[39m
+[31m+ const fromCaseResults = (input.caseResults ?? [])[39m
+[31m+ .map((caseResult) => caseResult.latencyMs)[39m
+[31m+ .filter((value): value is number => typeof value === "number" && Number.isFinite(value));[39m
+[31m+ if (fromCaseResults.length > 0) {[39m
+[31m+ return fromCaseResults;[39m
+[31m+ }[39m
+[31m+ return (input.caseAudits ?? [])[39m
+[31m+ .filter((audit) => audit.endpointId === input.endpointId)[39m
+[31m+ .map((audit) => audit.latencyMs)[39m
+[31m+ .filter((value): value is number => typeof value === "number" && Number.isFinite(value));[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ interface ModelScoreRow {[39m
+[31m+ readonly endpointId: string;[39m
+[31m+ readonly modelId: string;[39m
+[31m+ readonly displayName: string;[39m
+[31m+ readonly sourceType: string;[39m
+[31m+ readonly overallScore: number | null;[39m
+[31m+ readonly scoresByBucket: Partial<[39m
+[31m+ Record<[39m
+[31m+ "easy" | "medium" | "hard",[39m
+[31m+ { readonly score: number | null; readonly cases: number | null }[39m
+[31m+ >[39m
+[31m+ > | null;[39m
+[31m+ readonly profileQualityScore: number | null;[39m
+[31m+ readonly benchmarkSamples: number | null;[39m
+[31m+ readonly latencyP50: number | null;[39m
+[31m+ readonly latencyP95: number | null;[39m
+[31m+ readonly lastRunId: string | null;[39m
+[31m+ readonly lastRunMode: "quick" | "full" | null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function buildModelScoreRows([39m
+[31m+ candidates: readonly RouterCandidate[],[39m
+[31m+ result: BenchmarkRunResult | null,[39m
+[31m+ summary: BenchmarkSummary | null,[39m
+[31m+ ): ModelScoreRow[] {[39m
+[31m+ const gradeByEndpoint = new Map<[39m
+[31m+ string,[39m
+[31m+ {[39m
+[31m+ overallScore: number;[39m
+[31m+ scoresByBucket: BenchmarkSummarySubject["scoresByBucket"];[39m
+[31m+ caseResults: BenchmarkEndpointGrade["caseResults"] | null;[39m
+[31m+ runId: string | null;[39m
+[31m+ mode: "quick" | "full" | null;[39m
+[31m+ }[39m
+[31m+ >();[39m
+[31m+[39m
+[31m+ for (const subject of summary?.subjects ?? []) {[39m
+[31m+ gradeByEndpoint.set(subject.endpointId, {[39m
+[31m+ overallScore: subject.overallScore,[39m
+[31m+ scoresByBucket: subject.scoresByBucket,[39m
+[31m+ caseResults: null,[39m
+[31m+ runId: summary?.runId ?? null,[39m
+[31m+ mode: summary?.mode ?? null,[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+ for (const grade of result?.endpointGrades ?? []) {[39m
+[31m+ gradeByEndpoint.set(grade.endpointId, {[39m
+[31m+ overallScore: grade.overallScore,[39m
+[31m+ scoresByBucket: grade.byDifficulty,[39m
+[31m+ caseResults: grade.caseResults,[39m
+[31m+ runId: result?.runId ?? null,[39m
+[31m+ mode: result?.mode ?? null,[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const rows: ModelScoreRow[] = [];[39m
+[31m+ for (const candidate of candidates) {[39m
+[31m+ const grade = gradeByEndpoint.get(candidate.endpointId);[39m
+[31m+ const profile = asRecord(candidate.latestProfile);[39m
+[31m+ const sources = asRecord(profile?.sources);[39m
+[31m+ const profileQualityScore = pickNumber(profile, "judge_score", "quality_score");[39m
+[31m+ const benchmarkSamples = pickNumber(sources, "benchmark_samples");[39m
+[31m+ const capability = candidate.benchmarkCapability;[39m
+[31m+ const caseResults = grade?.caseResults ?? null;[39m
+[31m+ const { p50: latencyP50, p95: latencyP95 } = computeLatencyPercentiles([39m
+[31m+ collectEndpointLatencies({[39m
+[31m+ endpointId: candidate.endpointId,[39m
+[31m+ caseResults,[39m
+[31m+ caseAudits: summary?.caseAudits,[39m
+[31m+ }),[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ if ([39m
+[31m+ !grade &&[39m
+[31m+ !capability &&[39m
+[31m+ (benchmarkSamples === null || benchmarkSamples === 0) &&[39m
+[31m+ profileQualityScore === null[39m
+[31m+ ) {[39m
+[31m+ continue;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ rows.push({[39m
+[31m+ endpointId: candidate.endpointId,[39m
+[31m+ modelId: candidate.modelId,[39m
+[31m+ displayName: formatModelIdentity(candidate),[39m
+[31m+ sourceType: candidate.sourceType,[39m
+[31m+ overallScore: grade?.overallScore ?? capability?.overallScore ?? profileQualityScore,[39m
+[31m+ scoresByBucket:[39m
+[31m+ grade?.scoresByBucket ??[39m
+[31m+ (capability?.scoresByBucket[39m
+[31m+ ? {[39m
+[31m+ easy: {[39m
+[31m+ score: capability.scoresByBucket.easy?.score ?? null,[39m
+[31m+ cases: capability.scoresByBucket.easy?.cases ?? null,[39m
+[31m+ },[39m
+[31m+ medium: {[39m
+[31m+ score: capability.scoresByBucket.medium?.score ?? null,[39m
+[31m+ cases: capability.scoresByBucket.medium?.cases ?? null,[39m
+[31m+ },[39m
+[31m+ hard: {[39m
+[31m+ score: capability.scoresByBucket.hard?.score ?? null,[39m
+[31m+ cases: capability.scoresByBucket.hard?.cases ?? null,[39m
+[31m+ },[39m
+[31m+ }[39m
+[31m+ : null),[39m
+[31m+ profileQualityScore,[39m
+[31m+ benchmarkSamples,[39m
+[31m+ latencyP50,[39m
+[31m+ latencyP95,[39m
+[31m+ lastRunId: grade?.runId ?? capability?.lastRunId ?? null,[39m
+[31m+ lastRunMode: grade?.mode ?? capability?.lastRunMode ?? null,[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return rows.sort((left, right) => right.modelId.localeCompare(left.modelId, "en"));[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function startProgressiveBenchmarkBootstrap(input: {[39m
+[31m+ readonly loadSuite: () => Promise;[39m
+[31m+ readonly loadCandidates: () => Promise;[39m
+[31m+ readonly loadPreferences: () => Promise;[39m
+[31m+ readonly onEssential: (value: {[39m
+[31m+ readonly suite: TSuite;[39m
+[31m+ readonly candidates: TCandidates;[39m
+[31m+ readonly preferences: TPreferences;[39m
+[31m+ }) => void;[39m
+[31m+ readonly advisoryLoads: readonly {[39m
+[31m+ readonly load: () => Promise;[39m
+[31m+ readonly onData: (value: unknown) => void;[39m
+[31m+ }[];[39m
+[31m+ readonly onError: (message: string) => void;[39m
+[31m+ }): () => void {[39m
+[31m+ let disposed = false;[39m
+[31m+ const reportError = (value: unknown) => {[39m
+[31m+ if (!disposed) {[39m
+[31m+ input.onError(value instanceof Error ? value.message : "Could not load benchmark data.");[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ void Promise.all([input.loadSuite(), input.loadCandidates(), input.loadPreferences()]).then([39m
+[31m+ ([suite, candidates, preferences]) => {[39m
+[31m+ if (!disposed) {[39m
+[31m+ input.onEssential({ suite, candidates, preferences });[39m
+[31m+ }[39m
+[31m+ },[39m
+[31m+ reportError,[39m
+[31m+ );[39m
+[31m+ for (const advisoryLoad of input.advisoryLoads) {[39m
+[31m+ void advisoryLoad.load().then((value) => {[39m
+[31m+ if (!disposed) {[39m
+[31m+ advisoryLoad.onData(value);[39m
+[31m+ }[39m
+[31m+ }, reportError);[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return () => {[39m
+[31m+ disposed = true;[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export default function ControlBenchmarkRoute() {[39m
+[31m+ const [suite, setSuite] = useState(null);[39m
+[31m+ const [candidates, setCandidates] = useState(null);[39m
+[31m+ const [selectedEndpointIds, setSelectedEndpointIds] = useState([]);[39m
+[31m+ const [judgeEndpointId, setJudgeEndpointId] = useState("");[39m
+[31m+ const [mode, setMode] = useState<"quick" | "full">("quick");[39m
+[31m+ const [running, setRunning] = useState(false);[39m
+[31m+ const [activeRunId, setActiveRunId] = useState(null);[39m
+[31m+ const [progress, setProgress] = useState(null);[39m
+[31m+ const [result, setResult] = useState(null);[39m
+[31m+ const [lastSummary, setLastSummary] = useState(null);[39m
+[31m+ const [runHistory, setRunHistory] = useState([]);[39m
+[31m+ const [error, setError] = useState(null);[39m
+[31m+ const [runtimeSummary, setRuntimeSummary] = useState(null);[39m
+[31m+ const [clearingEndpointId, setClearingEndpointId] = useState(null);[39m
+[31m+ const [clearingAll, setClearingAll] = useState(false);[39m
+[31m+ const [nowMs, setNowMs] = useState(() => Date.now());[39m
+[31m+ const [taxonomyFilterRole, setTaxonomyFilterRole] = useState("");[39m
+[31m+ const [taxonomyFilterTask, setTaxonomyFilterTask] = useState("");[39m
+[31m+ const [taxonomyFilterCapability, setTaxonomyFilterCapability] = useState("");[39m
+[31m+[39m
+[31m+ const resolveJudgeEndpointId = useCallback([39m
+[31m+ (candidateValue: readonly RouterCandidate[], savedJudgeEndpointId?: string): string => {[39m
+[31m+ const runnable = filterBenchmarkRunnableCandidates(candidateValue);[39m
+[31m+ if ([39m
+[31m+ savedJudgeEndpointId &&[39m
+[31m+ runnable.some((candidate) => candidate.endpointId === savedJudgeEndpointId)[39m
+[31m+ ) {[39m
+[31m+ return savedJudgeEndpointId;[39m
+[31m+ }[39m
+[31m+ return ([39m
+[31m+ runnable.find((candidate) => candidate.sourceType === "remote")?.endpointId ??[39m
+[31m+ runnable[0]?.endpointId ??[39m
+[31m+ ""[39m
+[31m+ );[39m
+[31m+ },[39m
+[31m+ [],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ const refreshBenchmarkState = useCallback(async () => {[39m
+[31m+ const [summary, runs, candidateValue] = await Promise.all([[39m
+[31m+ fetchBenchmarkSummary(),[39m
+[31m+ fetchBenchmarkRuns(),[39m
+[31m+ fetchRouterCandidates(),[39m
+[31m+ ]);[39m
+[31m+ setLastSummary(summary);[39m
+[31m+ setRunHistory(runs);[39m
+[31m+ setCandidates(candidateValue);[39m
+[31m+ return { summary, runs, candidateValue };[39m
+[31m+ }, []);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ return startProgressiveBenchmarkBootstrap({[39m
+[31m+ loadSuite: fetchBenchmarkSuite,[39m
+[31m+ loadCandidates: fetchRouterCandidates,[39m
+[31m+ loadPreferences: fetchBenchmarkPreferences,[39m
+[31m+ onEssential: ({ suite: suiteValue, candidates: candidateValue, preferences }) => {[39m
+[31m+ setSuite(suiteValue);[39m
+[31m+ setCandidates(candidateValue);[39m
+[31m+ const runnable = candidateValue.filter((candidate) =>[39m
+[31m+ isBenchmarkRunnableCandidate(candidate),[39m
+[31m+ );[39m
+[31m+ setSelectedEndpointIds(runnable.map((candidate) => candidate.endpointId));[39m
+[31m+ setJudgeEndpointId(resolveJudgeEndpointId(candidateValue, preferences.judgeEndpointId));[39m
+[31m+ setError(null);[39m
+[31m+ },[39m
+[31m+ advisoryLoads: [[39m
+[31m+ {[39m
+[31m+ load: fetchBenchmarkSummary,[39m
+[31m+ onData: (value) => setLastSummary(value as BenchmarkSummary),[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ load: fetchBenchmarkRuns,[39m
+[31m+ onData: (value) => setRunHistory(value as readonly BenchmarkRunListEntry[]),[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ load: fetchRuntimeSummary,[39m
+[31m+ onData: (value) => setRuntimeSummary(value as RuntimeSummary),[39m
+[31m+ },[39m
+[31m+ ],[39m
+[31m+ onError: setError,[39m
+[31m+ });[39m
+[31m+ }, [resolveJudgeEndpointId]);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (!suite || !candidates) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ let cancelled = false;[39m
+[31m+[39m
+[31m+ const resumeActiveRun = async () => {[39m
+[31m+ try {[39m
+[31m+ const activeRun = await fetchActiveBenchmarkRun();[39m
+[31m+ const storedRunId = sessionStorage.getItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ const runId = activeRun?.runId ?? storedRunId;[39m
+[31m+ if (!runId) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const snapshot = await fetchBenchmarkRunProgress(runId);[39m
+[31m+ if (cancelled) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ if (snapshot.status === "running") {[39m
+[31m+ setActiveRunId(runId);[39m
+[31m+ setRunning(true);[39m
+[31m+ setProgress(snapshot);[39m
+[31m+ sessionStorage.setItem(ACTIVE_BENCHMARK_RUN_KEY, runId);[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ sessionStorage.removeItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ if (snapshot.status === "completed" && snapshot.result) {[39m
+[31m+ setResult(snapshot.result);[39m
+[31m+ void refreshBenchmarkState();[39m
+[31m+ }[39m
+[31m+ } catch {[39m
+[31m+ sessionStorage.removeItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ void resumeActiveRun();[39m
+[31m+ return () => {[39m
+[31m+ cancelled = true;[39m
+[31m+ };[39m
+[31m+ }, [candidates, refreshBenchmarkState, suite]);[39m
+[31m+[39m
+[31m+ const eligibleCaseCount = useMemo(() => {[39m
+[31m+ if (!suite) {[39m
+[31m+ return 0;[39m
+[31m+ }[39m
+[31m+ if (mode === "quick") {[39m
+[31m+ return suite.cases.filter((item) => item.benchmark_eligible && item.quick_benchmark).length;[39m
+[31m+ }[39m
+[31m+ return suite.cases.filter((item) => item.benchmark_eligible).length;[39m
+[31m+ }, [mode, suite]);[39m
+[31m+[39m
+[31m+ const runnableCandidates = useMemo([39m
+[31m+ () => (candidates ? filterBenchmarkRunnableCandidates(candidates) : []),[39m
+[31m+ [candidates],[39m
+[31m+ );[39m
+[31m+ const excludedCandidates = useMemo([39m
+[31m+ () =>[39m
+[31m+ candidates ? candidates.filter((candidate) => !isBenchmarkRunnableCandidate(candidate)) : [],[39m
+[31m+ [candidates],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ const runnableEndpointIds = useMemo([39m
+[31m+ () => new Set(runnableCandidates.map((candidate) => candidate.endpointId)),[39m
+[31m+ [runnableCandidates],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (!candidates) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setSelectedEndpointIds((current) =>[39m
+[31m+ current.filter((endpointId) => runnableEndpointIds.has(endpointId)),[39m
+[31m+ );[39m
+[31m+ if (judgeEndpointId && !runnableEndpointIds.has(judgeEndpointId)) {[39m
+[31m+ setJudgeEndpointId(resolveJudgeEndpointId(runnableCandidates));[39m
+[31m+ }[39m
+[31m+ }, [[39m
+[31m+ candidates,[39m
+[31m+ judgeEndpointId,[39m
+[31m+ resolveJudgeEndpointId,[39m
+[31m+ runnableCandidates,[39m
+[31m+ runnableEndpointIds,[39m
+[31m+ ]);[39m
+[31m+[39m
+[31m+ const gradedEndpointCount = selectedEndpointIds.length;[39m
+[31m+[39m
+[31m+ const judgeSubjectOverlap =[39m
+[31m+ judgeEndpointId.length > 0 && selectedEndpointIds.includes(judgeEndpointId);[39m
+[31m+[39m
+[31m+ const canRunBenchmark =[39m
+[31m+ Boolean(suite) &&[39m
+[31m+ gradedEndpointCount >= 2 &&[39m
+[31m+ judgeEndpointId.length > 0 &&[39m
+[31m+ runnableEndpointIds.has(judgeEndpointId) &&[39m
+[31m+ !running;[39m
+[31m+[39m
+[31m+ const modelScoreRows = useMemo([39m
+[31m+ () => (candidates ? buildModelScoreRows(candidates, result, lastSummary) : []),[39m
+[31m+ [candidates, lastSummary, result],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ const taxonomyDimensionInventory = useMemo(() => {[39m
+[31m+ const roleIds = new Set();[39m
+[31m+ const taskIds = new Set();[39m
+[31m+ const capabilityIds = new Set();[39m
+[31m+[39m
+[31m+ for (const row of modelScoreRows) {[39m
+[31m+ const candidate = candidates?.find((entry) => entry.endpointId === row.endpointId);[39m
+[31m+ const subject = lastSummary?.subjects.find((entry) => entry.endpointId === row.endpointId);[39m
+[31m+ const taxonomyScores =[39m
+[31m+ candidate?.benchmarkCapability?.taxonomyScores ?? subject?.taxonomyScores;[39m
+[31m+ if (!taxonomyScores) {[39m
+[31m+ continue;[39m
+[31m+ }[39m
+[31m+ for (const roleId of Object.keys(taxonomyScores.byRole ?? {})) {[39m
+[31m+ roleIds.add(roleId);[39m
+[31m+ }[39m
+[31m+ for (const taskId of Object.keys(taxonomyScores.byTask ?? {})) {[39m
+[31m+ taskIds.add(taskId);[39m
+[31m+ }[39m
+[31m+ for (const capabilityId of Object.keys(taxonomyScores.byCapability ?? {})) {[39m
+[31m+ capabilityIds.add(capabilityId);[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return {[39m
+[31m+ roleIds: [...roleIds].sort((left, right) => left.localeCompare(right)),[39m
+[31m+ taskIds: [...taskIds].sort((left, right) => left.localeCompare(right)),[39m
+[31m+ capabilityIds: [...capabilityIds].sort((left, right) => left.localeCompare(right)),[39m
+[31m+ };[39m
+[31m+ }, [candidates, lastSummary, modelScoreRows]);[39m
+[31m+[39m
+[31m+ const taxonomyHasData =[39m
+[31m+ taxonomyDimensionInventory.roleIds.length > 0 ||[39m
+[31m+ taxonomyDimensionInventory.taskIds.length > 0 ||[39m
+[31m+ taxonomyDimensionInventory.capabilityIds.length > 0;[39m
+[31m+[39m
+[31m+ const getFilteredTaxonomyScores = useCallback([39m
+[31m+ (dimension: "byRole" | "byTask" | "byCapability", filterValue: string) => {[39m
+[31m+ if (!filterValue) {[39m
+[31m+ return [] as Array<{[39m
+[31m+ modelId: string;[39m
+[31m+ endpointId: string;[39m
+[31m+ score: number;[39m
+[31m+ }>;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return modelScoreRows[39m
+[31m+ .map((row) => {[39m
+[31m+ const candidate = candidates?.find((entry) => entry.endpointId === row.endpointId);[39m
+[31m+ const subject = lastSummary?.subjects.find([39m
+[31m+ (entry) => entry.endpointId === row.endpointId,[39m
+[31m+ );[39m
+[31m+ const taxonomyScores =[39m
+[31m+ candidate?.benchmarkCapability?.taxonomyScores ?? subject?.taxonomyScores;[39m
+[31m+ const score = taxonomyScores?.[dimension]?.[filterValue];[39m
+[31m+ return score !== undefined[39m
+[31m+ ? {[39m
+[31m+ modelId: row.modelId,[39m
+[31m+ endpointId: row.endpointId,[39m
+[31m+ score,[39m
+[31m+ }[39m
+[31m+ : null;[39m
+[31m+ })[39m
+[31m+ .filter([39m
+[31m+ ([39m
+[31m+ entry,[39m
+[31m+ ): entry is {[39m
+[31m+ modelId: string;[39m
+[31m+ endpointId: string;[39m
+[31m+ score: number;[39m
+[31m+ } => entry !== null,[39m
+[31m+ )[39m
+[31m+ .sort((left, right) => right.score - left.score);[39m
+[31m+ },[39m
+[31m+ [candidates, lastSummary, modelScoreRows],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ const toggleEndpoint = (endpointId: string) => {[39m
+[31m+ setSelectedEndpointIds((current) =>[39m
+[31m+ current.includes(endpointId)[39m
+[31m+ ? current.filter((value) => value !== endpointId)[39m
+[31m+ : [...current, endpointId],[39m
+[31m+ );[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ const runBenchmark = useCallback(async () => {[39m
+[31m+ const runnableSelectedEndpointIds = selectedEndpointIds.filter((endpointId) =>[39m
+[31m+ runnableEndpointIds.has(endpointId),[39m
+[31m+ );[39m
+[31m+ if (runnableSelectedEndpointIds.length < 2) {[39m
+[31m+ setError("Select at least two endpoints for compare-capable benchmark runs.");[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ if (!judgeEndpointId || !runnableEndpointIds.has(judgeEndpointId)) {[39m
+[31m+ setError("Select a judge endpoint.");[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setRunning(true);[39m
+[31m+ setError(null);[39m
+[31m+ setProgress(null);[39m
+[31m+ setActiveRunId(null);[39m
+[31m+ try {[39m
+[31m+ await updateBenchmarkPreferences({ judgeEndpointId });[39m
+[31m+ const started = await startCapabilityBenchmark({[39m
+[31m+ endpointIds: runnableSelectedEndpointIds,[39m
+[31m+ judgeEndpointId,[39m
+[31m+ mode,[39m
+[31m+ useJudge: true,[39m
+[31m+ });[39m
+[31m+ sessionStorage.setItem(ACTIVE_BENCHMARK_RUN_KEY, started.runId);[39m
+[31m+ setActiveRunId(started.runId);[39m
+[31m+ } catch (value: unknown) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Benchmark run failed.");[39m
+[31m+ setRunning(false);[39m
+[31m+ sessionStorage.removeItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ }[39m
+[31m+ }, [judgeEndpointId, mode, runnableEndpointIds, selectedEndpointIds]);[39m
+[31m+[39m
+[31m+ const clearEndpointRoutingProfile = useCallback([39m
+[31m+ async (endpointId: string) => {[39m
+[31m+ setClearingEndpointId(endpointId);[39m
+[31m+ setError(null);[39m
+[31m+ try {[39m
+[31m+ await clearBenchmarkEndpointData(endpointId);[39m
+[31m+ await refreshBenchmarkState();[39m
+[31m+ if (result) {[39m
+[31m+ setResult({[39m
+[31m+ ...result,[39m
+[31m+ endpointGrades: result.endpointGrades.filter([39m
+[31m+ (grade) => grade.endpointId !== endpointId,[39m
+[31m+ ),[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+ } catch (value: unknown) {[39m
+[31m+ setError([39m
+[31m+ value instanceof Error[39m
+[31m+ ? value.message[39m
+[31m+ : "Could not clear routing profile for this model.",[39m
+[31m+ );[39m
+[31m+ } finally {[39m
+[31m+ setClearingEndpointId(null);[39m
+[31m+ }[39m
+[31m+ },[39m
+[31m+ [refreshBenchmarkState, result],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ const handleClearAllBenchmarkData = useCallback(async () => {[39m
+[31m+ const confirmed = window.confirm([39m
+[31m+ "Clear all benchmark data? This removes every benchmark run, artifact, and routing profile sample. This cannot be undone.",[39m
+[31m+ );[39m
+[31m+ if (!confirmed) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ setClearingAll(true);[39m
+[31m+ setError(null);[39m
+[31m+ try {[39m
+[31m+ await clearAllBenchmarkData();[39m
+[31m+ setResult(null);[39m
+[31m+ await refreshBenchmarkState();[39m
+[31m+ } catch (value: unknown) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not clear all benchmark data.");[39m
+[31m+ } finally {[39m
+[31m+ setClearingAll(false);[39m
+[31m+ }[39m
+[31m+ }, [refreshBenchmarkState]);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (!running) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ const timer = window.setInterval(() => setNowMs(Date.now()), 1000);[39m
+[31m+ return () => window.clearInterval(timer);[39m
+[31m+ }, [running]);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (!activeRunId) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ let cancelled = false;[39m
+[31m+[39m
+[31m+ const poll = async () => {[39m
+[31m+ try {[39m
+[31m+ const snapshot = await fetchBenchmarkRunProgress(activeRunId);[39m
+[31m+ if (cancelled) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setProgress(snapshot);[39m
+[31m+ if (snapshot.status === "completed" && snapshot.result) {[39m
+[31m+ setResult(snapshot.result);[39m
+[31m+ void refreshBenchmarkState();[39m
+[31m+ setRunning(false);[39m
+[31m+ setActiveRunId(null);[39m
+[31m+ sessionStorage.removeItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ } else if (snapshot.status === "failed") {[39m
+[31m+ setError(snapshot.errorMessage ?? "Benchmark run failed.");[39m
+[31m+ setRunning(false);[39m
+[31m+ setActiveRunId(null);[39m
+[31m+ sessionStorage.removeItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ }[39m
+[31m+ } catch (value: unknown) {[39m
+[31m+ if (!cancelled) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not read benchmark progress.");[39m
+[31m+ setRunning(false);[39m
+[31m+ setActiveRunId(null);[39m
+[31m+ sessionStorage.removeItem(ACTIVE_BENCHMARK_RUN_KEY);[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ void poll();[39m
+[31m+ const timer = window.setInterval(() => void poll(), BENCHMARK_POLL_MS);[39m
+[31m+ return () => {[39m
+[31m+ cancelled = true;[39m
+[31m+ window.clearInterval(timer);[39m
+[31m+ };[39m
+[31m+ }, [activeRunId, refreshBenchmarkState]);[39m
+[31m+[39m
+[31m+ const progressPercent = progress[39m
+[31m+ ? progress.totalSteps > 0[39m
+[31m+ ? Math.min(100, Math.round((progress.completedSteps / progress.totalSteps) * 100))[39m
+[31m+ : 0[39m
+[31m+ : 0;[39m
+[31m+ const progressStalled = Boolean([39m
+[31m+ progress && progress.status === "running" && nowMs - progress.updatedAtMs >= BENCHMARK_STALL_MS,[39m
+[31m+ );[39m
+[31m+ const progressDescription = progress ? describeBenchmarkProgress(progress) : null;[39m
+[31m+[39m
+[31m+ if (error && !suite && !candidates) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+ if (!suite || !candidates) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const lastRunLabel = lastSummary?.completedAtMs[39m
+[31m+ ? new Date(lastSummary.completedAtMs).toLocaleString()[39m
+[31m+ : null;[39m
+[31m+ const judgeLabel = lastSummary ? resolveJudgeLabel(lastSummary, candidates) : null;[39m
+[31m+[39m
+[31m+ return ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {judgeSubjectOverlap ? ([39m
+[31m+ [39m
+[31m+ Judge endpoint is also a benchmark subject. Expect slower grading and higher judge[39m
+[31m+ failure risk — prefer a dedicated judge when available.[39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+[39m
+[31m+ [39m
+[31m+
setMode(value === "full" ? "full" : "quick")}[39m
+[31m+ >[39m
+[31m+ Quick (12 hard cases) [39m
+[31m+ Full (all eligible cases) [39m
+[31m+ [39m
+[31m+
[39m
+[31m+
{[39m
+[31m+ setJudgeEndpointId(value);[39m
+[31m+ void updateBenchmarkPreferences({ judgeEndpointId: value }).catch([39m
+[31m+ () => undefined,[39m
+[31m+ );[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ {runnableCandidates.map((candidate) => ([39m
+[31m+ [39m
+[31m+ {formatModelIdentity(candidate)} ({candidate.sourceType})[39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ Used for grading only — not a benchmark subject.[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Model[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Path[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Scope[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Status[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {runnableCandidates.map((candidate) => {[39m
+[31m+ const selected = selectedEndpointIds.includes(candidate.endpointId);[39m
+[31m+ return ([39m
+[31m+ [39m
+[31m+ [39m
+[31m+ toggleEndpoint(candidate.endpointId)}[39m
+[31m+ />[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatModelIdentity(candidate)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatEndpointDisplayPath(candidate)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {candidate.sourceType}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {candidate.healthStatus ?? "unknown"}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ );[39m
+[31m+ })}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {gradedEndpointCount} of {runnableCandidates.length} selected[39m
+[31m+
[39m
+[31m+ {gradedEndpointCount < 2 ? ([39m
+[31m+
[39m
+[31m+ Select at least two runnable endpoints to compare head to head.[39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+ {excludedCandidates.length > 0 ? ([39m
+[31m+
[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ Excluded endpoints stay visible for audit context, but they are removed from the[39m
+[31m+ primary selection flow because the current execution mode cannot benchmark them.[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {excludedCandidates.map((candidate) => ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {formatModelIdentity(candidate)}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {formatEndpointDisplayPath(candidate)}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
excluded [39m
+[31m+
[39m
+[31m+ ))}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+[39m
+[31m+ [39m
+[31m+
void runBenchmark()}[39m
+[31m+ >[39m
+[31m+ {running[39m
+[31m+ ? "Running benchmark…"[39m
+[31m+ : `Run ${mode} benchmark (${gradedEndpointCount} model${gradedEndpointCount === 1 ? "" : "s"}, ${eligibleCaseCount} cases)`}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ {gradedEndpointCount} of {runnableCandidates.length} selected[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+ {running ? ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {progressDescription?.phaseLabel ?? "Benchmark in progress"}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {progressPercent}%[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {progress[39m
+[31m+ ? `${progress.completedSteps} / ${progress.totalSteps} steps`[39m
+[31m+ : "Starting…"}[39m
+[31m+
[39m
+[31m+ {progressDescription ? ([39m
+[31m+
{progressDescription.detail}
[39m
+[31m+ ) : null}[39m
+[31m+ {progressStalled ? ([39m
+[31m+
[39m
+[31m+ No progress update in the last 90 seconds.[39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+[39m
+[31m+ {error ? ([39m
+[31m+ {error}
[39m
+[31m+ ) : null}[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ {modelScoreRows.length === 0 ? ([39m
+[31m+ [39m
+[31m+ ) : ([39m
+[31m+ <>[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
Last run
[39m
+[31m+
[39m
+[31m+ {lastRunLabel ?? "—"}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Suite
[39m
+[31m+
[39m
+[31m+ {lastSummary?.mode[39m
+[31m+ ? `${lastSummary.mode.charAt(0).toUpperCase()}${lastSummary.mode.slice(1)}`[39m
+[31m+ : "—"}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Judge
[39m
+[31m+
[39m
+[31m+ {judgeLabel ?? "—"}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Model[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Overall[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Profile[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Easy[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Medium[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Hard[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ p50[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ p95[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Scope[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Actions[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {modelScoreRows.map((row) => ([39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {row.displayName}
[39m
+[31m+ [39m
+[31m+ {row.lastRunId[39m
+[31m+ ? `${row.lastRunId}${row.lastRunMode ? ` · ${row.lastRunMode}` : ""}`[39m
+[31m+ : "profile-derived"}[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatScore(row.overallScore)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatScore(row.profileQualityScore)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatScoreWithCoverage([39m
+[31m+ row.scoresByBucket?.easy?.score,[39m
+[31m+ row.scoresByBucket?.easy?.cases,[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatScoreWithCoverage([39m
+[31m+ row.scoresByBucket?.medium?.score,[39m
+[31m+ row.scoresByBucket?.medium?.cases,[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatScoreWithCoverage([39m
+[31m+ row.scoresByBucket?.hard?.score,[39m
+[31m+ row.scoresByBucket?.hard?.cases,[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatLatencyMs(row.latencyP50)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {formatLatencyMs(row.latencyP95)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {row.sourceType}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ void clearEndpointRoutingProfile(row.endpointId)}[39m
+[31m+ >[39m
+[31m+ {clearingEndpointId === row.endpointId ? "Clearing…" : "Clear"}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ >[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ {taxonomyHasData ? ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+ {[39m
+[31m+ setTaxonomyFilterRole(value);[39m
+[31m+ setTaxonomyFilterTask("");[39m
+[31m+ setTaxonomyFilterCapability("");[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ All roles [39m
+[31m+ {taxonomyDimensionInventory.roleIds.map((role) => ([39m
+[31m+ [39m
+[31m+ {role}[39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+ {[39m
+[31m+ setTaxonomyFilterTask(value);[39m
+[31m+ setTaxonomyFilterRole("");[39m
+[31m+ setTaxonomyFilterCapability("");[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ All tasks [39m
+[31m+ {taxonomyDimensionInventory.taskIds.map((task) => ([39m
+[31m+ [39m
+[31m+ {task}[39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+ {[39m
+[31m+ setTaxonomyFilterCapability(value);[39m
+[31m+ setTaxonomyFilterRole("");[39m
+[31m+ setTaxonomyFilterTask("");[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ All capabilities [39m
+[31m+ {taxonomyDimensionInventory.capabilityIds.map((cap) => ([39m
+[31m+ [39m
+[31m+ {cap}[39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+[39m
+[31m+ {(() => {[39m
+[31m+ const roleScores = getFilteredTaxonomyScores("byRole", taxonomyFilterRole);[39m
+[31m+ const taskScores = getFilteredTaxonomyScores("byTask", taxonomyFilterTask);[39m
+[31m+ const capScores = getFilteredTaxonomyScores([39m
+[31m+ "byCapability",[39m
+[31m+ taxonomyFilterCapability,[39m
+[31m+ );[39m
+[31m+ const activeScores =[39m
+[31m+ roleScores.length > 0[39m
+[31m+ ? { label: `Role: ${taxonomyFilterRole}`, scores: roleScores }[39m
+[31m+ : taskScores.length > 0[39m
+[31m+ ? { label: `Task: ${taxonomyFilterTask}`, scores: taskScores }[39m
+[31m+ : capScores.length > 0[39m
+[31m+ ? { label: `Capability: ${taxonomyFilterCapability}`, scores: capScores }[39m
+[31m+ : null;[39m
+[31m+[39m
+[31m+ return activeScores ? ([39m
+[31m+
[39m
+[31m+
{activeScores.label}
[39m
+[31m+
[39m
+[31m+ {activeScores.scores.map((entry) => ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {modelScoreRows.find((row) => row.endpointId === entry.endpointId)[39m
+[31m+ ?.displayName ?? entry.modelId}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {formatEndpointDisplayPath({[39m
+[31m+ endpointId: entry.endpointId,[39m
+[31m+ reasoningEffort: candidates.find([39m
+[31m+ (candidate) => candidate.endpointId === entry.endpointId,[39m
+[31m+ )?.reasoningEffort,[39m
+[31m+ })}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
{formatScore(entry.score)}
[39m
+[31m+
[39m
+[31m+ ))}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ ) : taxonomyFilterRole || taxonomyFilterTask || taxonomyFilterCapability ? ([39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+
[39m
+[31m+ );[39m
+[31m+ })()}[39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+ [39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ {runHistory.length === 0 ? ([39m
+[31m+ [39m
+[31m+ ) : ([39m
+[31m+ [39m
+[31m+ {runHistory.map((run) => ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+
{run.runId}
[39m
+[31m+
[39m
+[31m+ {run.mode} • {run.caseCount} cases • {run.endpointIds.length} model[39m
+[31m+ {run.endpointIds.length === 1 ? "" : "s"}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {new Date(run.completedAtMs).toLocaleString()} • {run.suiteId}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
{run.mode} [39m
+[31m+
[39m
+[31m+ ))}[39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+[39m
+[31m+ [39m
+[31m+ void handleClearAllBenchmarkData()}[39m
+[31m+ >[39m
+[31m+ {clearingAll ? "Clearing all benchmark data…" : "Clear all benchmark data"}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+
+[36m [2m❯[22m app/routes/control-benchmark.test.ts:[2m51:27[22m[39m
+ [90m 49| [39m
+ [90m 50| [39mtest("labels benchmark score evidence as exact/borrowed/prior (R11)", …
+ [90m 51| [39m [34mexpect[39m(benchmarkSource)[33m.[39m[34mtoContain[39m([32m"classifyEffortEvidence"[39m)[33m;[39m
+ [90m | [39m [31m^[39m
+ [90m 52| [39m [34mexpect[39m(benchmarkSource)[33m.[39m[34mtoContain[39m([32m"formatEffortEvidenceLabel"[39m)[33m;[39m
+ [90m 53| [39m [34mexpect[39m(benchmarkSource)[33m.[39m[34mtoContain[39m([32m"evidenceLabel"[39m)[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/6]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m app/routes/control-models.test.ts[2m > [22mlabels model-pool benchmark evidence as exact/borrowed/prior (R11)
+[31m[1mAssertionError[22m: expected [ …(2) ] to deep equally contain { …(2) }[39m
+
+[32m- Expected:[39m
+{
+ "label": "Borrowed (sibling effort)",
+ "tone": "warning",
+}
+
+[31m+ Received:[39m
+[
+ {
+ "label": "tools",
+ "tone": "info",
+ },
+ {
+ "label": "1 endpoint",
+ "tone": "neutral",
+ },
+]
+
+[36m [2m❯[22m app/routes/control-models.test.ts:[2m789:5[22m[39m
+ [90m787| [39m evidenceTone[33m:[39m [32m"warning"[39m[33m,[39m
+ [90m788| [39m })[33m,[39m
+ [90m789| [39m ).toContainEqual({ label: "Borrowed (sibling effort)", tone: "warnin…
+ [90m | [39m [31m^[39m
+ [90m790| [39m})[33m;[39m
+ [90m791| [39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/6]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m app/routes/control-models.test.ts[2m > [22mcomputes model-pool evidence from the candidate's benchmark capability (R11)
+[31m[1mAssertionError[22m: expected 'import { useEffect, useMemo, useState…' to contain 'classifyEffortEvidence'[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[32m- classifyEffortEvidence[39m
+[31m+ import { useEffect, useMemo, useState } from "react";[39m
+[31m+ import { Link } from "react-router";[39m
+[31m+[39m
+[31m+ import {[39m
+[31m+ Badge,[39m
+[31m+ EmptyState,[39m
+[31m+ ErrorState,[39m
+[31m+ LoadingState,[39m
+[31m+ SectionCard,[39m
+[31m+ } from "../components/page-primitives";[39m
+[31m+ import {[39m
+[31m+ compactFieldButtonClassName,[39m
+[31m+ secondaryButtonClassName,[39m
+[31m+ supportingTextClassName,[39m
+[31m+ } from "../lib/design-system";[39m
+[31m+ import { formatScore, formatScoreWithCoverage } from "../lib/format-score";[39m
+[31m+ import { ModelRoleBindingTree } from "../lib/role-task-hierarchy";[39m
+[31m+ import {[39m
+[31m+ type ModelTelemetryRollup,[39m
+[31m+ type RouterCandidate,[39m
+[31m+ type RuntimeAccount,[39m
+[31m+ type RuntimeControllerAssignment,[39m
+[31m+ type RuntimeModelRoleAssignment,[39m
+[31m+ type RuntimeRequestListItem,[39m
+[31m+ type RuntimeRolePolicy,[39m
+[31m+ type RuntimeSnapshot,[39m
+[31m+ fetchControllerAssignment,[39m
+[31m+ fetchModelTelemetryRollup,[39m
+[31m+ fetchRolePolicy,[39m
+[31m+ fetchRouterCandidates,[39m
+[31m+ fetchRuntimeAccounts,[39m
+[31m+ fetchRuntimeEndpoints,[39m
+[31m+ fetchRuntimeModels,[39m
+[31m+ removeRuntimeAccountModel,[39m
+[31m+ removeRuntimeEndpoint,[39m
+[31m+ unloadLocalModel,[39m
+[31m+ unloadPeerModel,[39m
+[31m+ updateControllerAssignment,[39m
+[31m+ upsertRuntimeAccount,[39m
+[31m+ } from "../lib/runtime-api";[39m
+[31m+ import { buildConfiguredModelCards, buildSelectedModelMetaPanel } from "../lib/view-models";[39m
+[31m+[39m
+[31m+ type ConfiguredModelCardLike = {[39m
+[31m+ readonly modelId: string;[39m
+[31m+ readonly identityKey?: string;[39m
+[31m+ readonly endpointId?: string;[39m
+[31m+ readonly displayName?: string;[39m
+[31m+ readonly controllerState: "active" | "eligible" | "inactive";[39m
+[31m+ readonly status: string;[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ type BadgeTone = "neutral" | "accent" | "warning" | "success" | "error" | "info" | "advisory";[39m
+[31m+[39m
+[31m+ type ConfiguredModelInventoryPill = {[39m
+[31m+ readonly label: string;[39m
+[31m+ readonly tone: BadgeTone;[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ type SelectedModelPreviewPayloadInput = {[39m
+[31m+ readonly modelId: string;[39m
+[31m+ readonly endpointIds: readonly string[];[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ type EvidencePillInput = {[39m
+[31m+ readonly assignedRoleRows: readonly {[39m
+[31m+ readonly roleId?: string;[39m
+[31m+ readonly label?: string;[39m
+[31m+ readonly score: number;[39m
+[31m+ }[];[39m
+[31m+ readonly groupRows: readonly {[39m
+[31m+ readonly groupId?: string;[39m
+[31m+ readonly score: number;[39m
+[31m+ readonly lowCoverage: boolean;[39m
+[31m+ }[];[39m
+[31m+ readonly suggestedRoleRows: readonly {[39m
+[31m+ readonly roleId: string;[39m
+[31m+ readonly label?: string;[39m
+[31m+ readonly score?: number;[39m
+[31m+ readonly lowCoverage: boolean;[39m
+[31m+ }[];[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ export type ConfiguredModelsSnapshot = Pick;[39m
+[31m+ type RequestEvidenceStatus = "loading" | "ready" | "unavailable";[39m
+[31m+[39m
+[31m+ /** Paper Models inventory — section eyebrows (Runtime / Cost / Benchmark / Models / Roles). */[39m
+[31m+ const inventoryEyebrowClassName =[39m
+[31m+ "font-sans text-[11px] font-semibold uppercase leading-[14px] tracking-[0.04em] text-[var(--rm-muted)]";[39m
+[31m+ const inventoryFactLabelClassName = "font-sans text-[13px] leading-[18px] text-[var(--rm-muted)]";[39m
+[31m+ const inventoryFactValueClassName =[39m
+[31m+ "text-right font-sans text-[13px] font-semibold leading-[18px] text-[var(--rm-fg)]";[39m
+[31m+ const inventoryMonoValueClassName =[39m
+[31m+ "text-right font-mono text-[12px] font-semibold leading-4 text-[var(--rm-fg)]";[39m
+[31m+ export const configuredModelRoleSectionClassName = "flex flex-col gap-3";[39m
+[31m+ export const configuredModelRoleListClassName = "space-y-2 pr-1";[39m
+[31m+[39m
+[31m+ type ConfiguredModelsInitialLoadResult = {[39m
+[31m+ readonly snapshot: ConfiguredModelsSnapshot;[39m
+[31m+ readonly controller: RuntimeControllerAssignment | null;[39m
+[31m+ readonly rolePolicy: RuntimeRolePolicy;[39m
+[31m+ readonly candidates: readonly RouterCandidate[];[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ export interface DeferredConfiguredModelsBootstrapOptions {[39m
+[31m+ readonly loadInitial: () => Promise;[39m
+[31m+ readonly onInitialData: (data: TInitialData) => void;[39m
+[31m+ readonly onInitialError: (message: string) => void;[39m
+[31m+ readonly loadObservedRequests: () => Promise;[39m
+[31m+ readonly onObservedRequests: (requests: readonly RuntimeRequestListItem[]) => void;[39m
+[31m+ readonly onObservedRequestsError?: (message: string) => void;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function startDeferredConfiguredModelsBootstrap([39m
+[31m+ options: DeferredConfiguredModelsBootstrapOptions,[39m
+[31m+ ): () => void {[39m
+[31m+ let disposed = false;[39m
+[31m+[39m
+[31m+ void options[39m
+[31m+ .loadInitial()[39m
+[31m+ .then((data) => {[39m
+[31m+ if (disposed) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ options.onInitialData(data);[39m
+[31m+ return options.loadObservedRequests().then([39m
+[31m+ (requests) => {[39m
+[31m+ if (!disposed) {[39m
+[31m+ options.onObservedRequests(requests);[39m
+[31m+ }[39m
+[31m+ },[39m
+[31m+ (value: unknown) => {[39m
+[31m+ if (disposed) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ options.onObservedRequestsError?.([39m
+[31m+ value instanceof Error ? value.message : "Could not load request evidence.",[39m
+[31m+ );[39m
+[31m+ },[39m
+[31m+ );[39m
+[31m+ })[39m
+[31m+ .catch((value: unknown) => {[39m
+[31m+ if (disposed) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ options.onInitialError([39m
+[31m+ value instanceof Error ? value.message : "Could not load configured models.",[39m
+[31m+ );[39m
+[31m+ });[39m
+[31m+[39m
+[31m+ return () => {[39m
+[31m+ disposed = true;[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function describeConfiguredModelRequestEvidence([39m
+[31m+ requestCount: number | null,[39m
+[31m+ status: RequestEvidenceStatus,[39m
+[31m+ ): string {[39m
+[31m+ if (status === "loading") {[39m
+[31m+ return "Request evidence loading";[39m
+[31m+ }[39m
+[31m+ if (status === "unavailable") {[39m
+[31m+ return "Request evidence unavailable";[39m
+[31m+ }[39m
+[31m+ return `${requestCount ?? 0} request${requestCount === 1 ? "" : "s"}`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function buildObservedRequestFact(input: {[39m
+[31m+ readonly requests: readonly RuntimeRequestListItem[];[39m
+[31m+ readonly status: RequestEvidenceStatus;[39m
+[31m+ }): { value: string; detail: string } {[39m
+[31m+ if (input.status === "loading") {[39m
+[31m+ return {[39m
+[31m+ value: "Loading…",[39m
+[31m+ detail: "The model inventory is visible. Request evidence is loading in the background now.",[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+ if (input.status === "unavailable") {[39m
+[31m+ return {[39m
+[31m+ value: "Unavailable",[39m
+[31m+ detail:[39m
+[31m+ "Deferred request evidence is unavailable, but the model inventory remains visible and usable.",[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+ return {[39m
+[31m+ value: input.requests.length.toLocaleString("en-US"),[39m
+[31m+ detail: "Request count available as deferred runtime context.",[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function resolveConfiguredModelStatusTone([39m
+[31m+ controllerState: ConfiguredModelCardLike["controllerState"],[39m
+[31m+ status: ConfiguredModelCardLike["status"],[39m
+[31m+ ): BadgeTone {[39m
+[31m+ if (controllerState === "active") {[39m
+[31m+ return "accent";[39m
+[31m+ }[39m
+[31m+ if (status === "active" || status === "healthy") {[39m
+[31m+ return "success";[39m
+[31m+ }[39m
+[31m+ if (status === "inactive") {[39m
+[31m+ return "neutral";[39m
+[31m+ }[39m
+[31m+ return "warning";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function buildConfiguredModelInventoryPills(input: {[39m
+[31m+ readonly toolCallingSupported: boolean;[39m
+[31m+ readonly endpointCount: number;[39m
+[31m+ readonly capabilityScore: number | null | undefined;[39m
+[31m+ }): ConfiguredModelInventoryPill[] {[39m
+[31m+ return [[39m
+[31m+ {[39m
+[31m+ label: input.toolCallingSupported ? "tools" : "no tools",[39m
+[31m+ tone: input.toolCallingSupported ? "info" : "neutral",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: `${input.endpointCount} endpoint${input.endpointCount === 1 ? "" : "s"}`,[39m
+[31m+ tone: "neutral",[39m
+[31m+ },[39m
+[31m+ ...(typeof input.capabilityScore === "number"[39m
+[31m+ ? [[39m
+[31m+ {[39m
+[31m+ label: `score ${formatScore(input.capabilityScore)}`,[39m
+[31m+ tone: "advisory" as const,[39m
+[31m+ },[39m
+[31m+ ][39m
+[31m+ : []),[39m
+[31m+ ];[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function buildSelectedModelEvidencePills([39m
+[31m+ input: EvidencePillInput,[39m
+[31m+ ): ConfiguredModelInventoryPill[] {[39m
+[31m+ const pills: ConfiguredModelInventoryPill[] = [];[39m
+[31m+ const strongestAssignedRoleScore = input.assignedRoleRows.reduce([39m
+[31m+ (current, row) => (current === null || row.score > current ? row.score : current),[39m
+[31m+ null,[39m
+[31m+ );[39m
+[31m+ if (strongestAssignedRoleScore !== null) {[39m
+[31m+ pills.push({[39m
+[31m+ label: `assigned role evidence ${Math.round(strongestAssignedRoleScore * 100)}%`,[39m
+[31m+ tone: "info",[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const strongestGroup = input.groupRows.slice().sort((left, right) => right.score - left.score)[0];[39m
+[31m+ if (strongestGroup) {[39m
+[31m+ pills.push({[39m
+[31m+ label: `group evidence ${Math.round(strongestGroup.score * 100)}%`,[39m
+[31m+ tone: strongestGroup.lowCoverage ? "warning" : "advisory",[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const lowCoverageRole = input.suggestedRoleRows.find((row) => row.lowCoverage);[39m
+[31m+ if (lowCoverageRole) {[39m
+[31m+ pills.push({[39m
+[31m+ label: `low coverage on ${lowCoverageRole.roleId}`,[39m
+[31m+ tone: "warning",[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ if (pills.length === 0) {[39m
+[31m+ pills.push({[39m
+[31m+ label: "No benchmark evidence yet",[39m
+[31m+ tone: "neutral",[39m
+[31m+ });[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return pills;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function buildSelectedModelPreviewPayload([39m
+[31m+ input: SelectedModelPreviewPayloadInput,[39m
+[31m+ ): SelectedModelPreviewPayloadInput {[39m
+[31m+ return {[39m
+[31m+ modelId: input.modelId,[39m
+[31m+ endpointIds: [...input.endpointIds],[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function resolveRoleIdsFromAssignment([39m
+[31m+ binding: NonNullable[number] | undefined,[39m
+[31m+ allRoleIds: readonly string[],[39m
+[31m+ ): string[] {[39m
+[31m+ if (!binding || binding.roleAssignmentMode === "all") {[39m
+[31m+ return [...allRoleIds];[39m
+[31m+ }[39m
+[31m+ if (binding.roleAssignmentMode === "exclude") {[39m
+[31m+ const disabledRoleIds = new Set(binding.disabledRoleIds ?? []);[39m
+[31m+ return allRoleIds.filter((roleId) => !disabledRoleIds.has(roleId));[39m
+[31m+ }[39m
+[31m+ if (binding.roleAssignmentMode === "include" || binding.roleAssignmentMode === "custom") {[39m
+[31m+ return [...(binding.enabledRoleIds ?? binding.roleIds)];[39m
+[31m+ }[39m
+[31m+ return [...binding.roleIds];[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function getAccountRoleIdsForModel([39m
+[31m+ account: RuntimeAccount,[39m
+[31m+ modelId: string,[39m
+[31m+ allRoleIds: readonly string[],[39m
+[31m+ endpointId?: string,[39m
+[31m+ ): string[] {[39m
+[31m+ const binding =[39m
+[31m+ (endpointId[39m
+[31m+ ? account.modelRoleBindings?.find((entry) => entry.endpointId === endpointId)[39m
+[31m+ : undefined) ??[39m
+[31m+ account.modelRoleBindings?.find([39m
+[31m+ (entry) => entry.endpointId === undefined && entry.modelId === modelId,[39m
+[31m+ );[39m
+[31m+ return resolveRoleIdsFromAssignment(binding, allRoleIds);[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function buildModelRoleAssignmentForSelection([39m
+[31m+ selectedRoleIds: readonly string[],[39m
+[31m+ allRoleIds: readonly string[],[39m
+[31m+ ): RuntimeModelRoleAssignment {[39m
+[31m+ const selected = [...new Set(selectedRoleIds)].sort((left, right) =>[39m
+[31m+ left.localeCompare(right, "en"),[39m
+[31m+ );[39m
+[31m+ const knownRoleIds = allRoleIds.filter((roleId) => selected.includes(roleId));[39m
+[31m+ if (allRoleIds.length > 0 && knownRoleIds.length === allRoleIds.length) {[39m
+[31m+ return { roleAssignmentMode: "all", enabledRoleIds: [], disabledRoleIds: [] };[39m
+[31m+ }[39m
+[31m+ if (knownRoleIds.length === 0) {[39m
+[31m+ return { roleAssignmentMode: "include", enabledRoleIds: [], disabledRoleIds: [] };[39m
+[31m+ }[39m
+[31m+ const disabledRoleIds = allRoleIds.filter((roleId) => !knownRoleIds.includes(roleId));[39m
+[31m+ return {[39m
+[31m+ roleAssignmentMode: "exclude",[39m
+[31m+ enabledRoleIds: [],[39m
+[31m+ disabledRoleIds,[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function resolveConfiguredModelEjectLabel([39m
+[31m+ hasLocalPeerEndpoint: boolean,[39m
+[31m+ ): "Eject from router" | "Eject from pool" {[39m
+[31m+ return hasLocalPeerEndpoint ? "Eject from router" : "Eject from pool";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export type ConfiguredModelFooterAction = {[39m
+[31m+ readonly kind: "unload-local" | "eject-configured" | "eject-controller" | "none";[39m
+[31m+ readonly label: "Unload" | "Eject from router" | "Eject from pool" | "Eject controller";[39m
+[31m+ readonly disabled: boolean;[39m
+[31m+ readonly isController: boolean;[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ export function resolveConfiguredModelFooterAction(input: {[39m
+[31m+ readonly hasSelectedCard: boolean;[39m
+[31m+ readonly isController: boolean;[39m
+[31m+ readonly hasLlamaSwapEndpoint: boolean;[39m
+[31m+ readonly hasPrimaryAccount: boolean;[39m
+[31m+ readonly hasLocalPeerEndpoint: boolean;[39m
+[31m+ readonly isRemoving: boolean;[39m
+[31m+ }): ConfiguredModelFooterAction {[39m
+[31m+ // Controller ownership wins over local runtime mechanics: the final[39m
+[31m+ // controller must use the destructive eject confirmation/recovery path,[39m
+[31m+ // never the ordinary local-model unload shortcut.[39m
+[31m+ const kind = !input.hasPrimaryAccount[39m
+[31m+ ? "none"[39m
+[31m+ : input.isController[39m
+[31m+ ? "eject-controller"[39m
+[31m+ : input.hasLlamaSwapEndpoint[39m
+[31m+ ? "unload-local"[39m
+[31m+ : "eject-configured";[39m
+[31m+ return {[39m
+[31m+ kind,[39m
+[31m+ label:[39m
+[31m+ kind === "unload-local"[39m
+[31m+ ? "Unload"[39m
+[31m+ : kind === "eject-controller"[39m
+[31m+ ? "Eject controller"[39m
+[31m+ : resolveConfiguredModelEjectLabel(input.hasLocalPeerEndpoint),[39m
+[31m+ disabled: !input.hasSelectedCard || kind === "none" || input.isRemoving,[39m
+[31m+ isController: input.isController,[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function resolveConfiguredModelRemovalClick(input: {[39m
+[31m+ readonly actionKind: ConfiguredModelFooterAction["kind"];[39m
+[31m+ readonly targetKey: string;[39m
+[31m+ readonly pendingConfirmationKey: string | null;[39m
+[31m+ }): "request-confirmation" | "execute" | "none" {[39m
+[31m+ if (input.actionKind === "none") {[39m
+[31m+ return "none";[39m
+[31m+ }[39m
+[31m+ if ([39m
+[31m+ (input.actionKind === "eject-configured" || input.actionKind === "eject-controller") &&[39m
+[31m+ input.pendingConfirmationKey !== input.targetKey[39m
+[31m+ ) {[39m
+[31m+ return "request-confirmation";[39m
+[31m+ }[39m
+[31m+ return "execute";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export async function saveConfiguredModelRoleEligibility(input: {[39m
+[31m+ readonly mutate: () => Promise;[39m
+[31m+ readonly reloadCanonicalState: () => Promise;[39m
+[31m+ }): Promise {[39m
+[31m+ await input.mutate();[39m
+[31m+ return input.reloadCanonicalState();[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function describeSavedModelRoleEligibility(input: {[39m
+[31m+ readonly displayName: string;[39m
+[31m+ readonly providerAccountId: string;[39m
+[31m+ readonly selectedRoleIds: readonly string[];[39m
+[31m+ readonly roleDefinitions: readonly {[39m
+[31m+ readonly role_id: string;[39m
+[31m+ readonly primaryGroupId?: string;[39m
+[31m+ readonly secondaryGroupIds?: readonly string[];[39m
+[31m+ readonly task_types_supported?: readonly string[];[39m
+[31m+ }[];[39m
+[31m+ readonly endpointVariantCount: number;[39m
+[31m+ }): string {[39m
+[31m+ const selectedRoleIds = new Set(input.selectedRoleIds);[39m
+[31m+ const selectedRoles = input.roleDefinitions.filter((role) => selectedRoleIds.has(role.role_id));[39m
+[31m+ const taskTypes = new Set(selectedRoles.flatMap((role) => role.task_types_supported ?? []));[39m
+[31m+ const groupIds = new Set([39m
+[31m+ selectedRoles.flatMap((role) => [[39m
+[31m+ ...(role.primaryGroupId ? [role.primaryGroupId] : []),[39m
+[31m+ ...(role.secondaryGroupIds ?? []),[39m
+[31m+ ]),[39m
+[31m+ );[39m
+[31m+ return `Saved eligibility for ${input.displayName} on ${input.providerAccountId}: ${selectedRoles.length} role${selectedRoles.length === 1 ? "" : "s"} derive ${taskTypes.size} task type${taskTypes.size === 1 ? "" : "s"} across ${groupIds.size} group${groupIds.size === 1 ? "" : "s"} for this endpoint instance.`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function resolveSelectedModelAccount<[39m
+[31m+ TAccount extends { readonly providerAccountId: string },[39m
+[31m+ TEndpoint extends { readonly providerAccountId?: string },[39m
+[31m+ >(accounts: readonly TAccount[], selectedEndpoints: readonly TEndpoint[]): TAccount | null {[39m
+[31m+ const selectedEndpointAccountIds = new Set([39m
+[31m+ selectedEndpoints[39m
+[31m+ .map((endpoint) => endpoint.providerAccountId)[39m
+[31m+ .filter((providerAccountId): providerAccountId is string => Boolean(providerAccountId)),[39m
+[31m+ );[39m
+[31m+ return ([39m
+[31m+ accounts.find((account) => selectedEndpointAccountIds.has(account.providerAccountId)) ??[39m
+[31m+ accounts[0] ??[39m
+[31m+ null[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function resolveDefaultSelectedModelId([39m
+[31m+ cards: readonly ConfiguredModelCardLike[],[39m
+[31m+ ): string | null {[39m
+[31m+ return ([39m
+[31m+ cards.find((card) => card.controllerState === "active")?.identityKey ??[39m
+[31m+ cards.find((card) => card.controllerState === "active")?.modelId ??[39m
+[31m+ cards.find((card) => card.status === "active" || card.status === "healthy")?.identityKey ??[39m
+[31m+ cards.find((card) => card.status === "active" || card.status === "healthy")?.modelId ??[39m
+[31m+ cards[0]?.identityKey ??[39m
+[31m+ cards[0]?.modelId ??[39m
+[31m+ null[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function resolveSelectedBenchmarkCandidate([39m
+[31m+ candidates: readonly RouterCandidate[],[39m
+[31m+ selected: { readonly modelId: string; readonly endpointId?: string } | null,[39m
+[31m+ ): RouterCandidate | null {[39m
+[31m+ if (!selected) {[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+ if (selected.endpointId) {[39m
+[31m+ return candidates.find((candidate) => candidate.endpointId === selected.endpointId) ?? null;[39m
+[31m+ }[39m
+[31m+ const sameModel = candidates.filter((candidate) => candidate.modelId === selected.modelId);[39m
+[31m+ return sameModel.length === 1 ? (sameModel[0] ?? null) : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function readSelectedOperationalPerformance(candidate: RouterCandidate | null): {[39m
+[31m+ readonly p50: number | null;[39m
+[31m+ readonly p95: number | null;[39m
+[31m+ readonly failureRate: number | null;[39m
+[31m+ readonly sampleCount: number | null;[39m
+[31m+ } {[39m
+[31m+ const profile =[39m
+[31m+ typeof candidate?.operationalProfile === "object" && candidate.operationalProfile !== null[39m
+[31m+ ? candidate.operationalProfile[39m
+[31m+ : typeof candidate?.latestProfile === "object" && candidate.latestProfile !== null[39m
+[31m+ ? candidate.latestProfile[39m
+[31m+ : null;[39m
+[31m+ const p50 = profile?.latency_ms_p50 ?? profile?.latencyMsP50;[39m
+[31m+ const p95 = profile?.latency_ms_p95 ?? profile?.latencyMsP95;[39m
+[31m+ const failureRate = profile?.failure_rate ?? profile?.failureRate;[39m
+[31m+ const sampleCount = profile?.sample_size ?? profile?.sampleSize;[39m
+[31m+ return {[39m
+[31m+ p50: typeof p50 === "number" && Number.isFinite(p50) ? p50 : null,[39m
+[31m+ p95: typeof p95 === "number" && Number.isFinite(p95) ? p95 : null,[39m
+[31m+ failureRate:[39m
+[31m+ typeof failureRate === "number" && Number.isFinite(failureRate) ? failureRate : null,[39m
+[31m+ sampleCount:[39m
+[31m+ typeof sampleCount === "number" && Number.isFinite(sampleCount) ? sampleCount : null,[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function configuredModelCardKey(card: ConfiguredModelCardLike): string {[39m
+[31m+ return card.identityKey ?? card.modelId;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function configuredModelRoleDraftKey([39m
+[31m+ providerAccountId: string,[39m
+[31m+ endpointId: string | undefined,[39m
+[31m+ ): string {[39m
+[31m+ return `${providerAccountId}\u0000${endpointId ?? "legacy-model-default"}`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function createAccountMutationPayload([39m
+[31m+ account: RuntimeAccount,[39m
+[31m+ modelId: string,[39m
+[31m+ roleIds: readonly string[],[39m
+[31m+ allRoleIds: readonly string[] = [],[39m
+[31m+ endpointId?: string,[39m
+[31m+ ): Record {[39m
+[31m+ const otherBindings = (account.modelRoleBindings ?? []).filter((binding) =>[39m
+[31m+ endpointId[39m
+[31m+ ? binding.endpointId !== endpointId[39m
+[31m+ : binding.endpointId !== undefined || binding.modelId !== modelId,[39m
+[31m+ );[39m
+[31m+ const assignment = buildModelRoleAssignmentForSelection(roleIds, allRoleIds);[39m
+[31m+ const nextBinding = {[39m
+[31m+ modelId,[39m
+[31m+ ...(endpointId ? { endpointId } : {}),[39m
+[31m+ roleIds:[39m
+[31m+ assignment.roleAssignmentMode === "include" ? [...(assignment.enabledRoleIds ?? [])] : [],[39m
+[31m+ ...assignment,[39m
+[31m+ };[39m
+[31m+ return {[39m
+[31m+ providerAccountId: account.providerAccountId,[39m
+[31m+ providerId: account.providerId,[39m
+[31m+ providerKind: account.providerKind,[39m
+[31m+ orgScope: account.orgScope ?? "personal",[39m
+[31m+ accountScope: account.accountScope ?? "workspace-default",[39m
+[31m+ credentialRef: account.credentialRef,[39m
+[31m+ authMode: account.authMode,[39m
+[31m+ regionPolicy: account.regionPolicy ?? { mode: "prefer", regions: ["global"] },[39m
+[31m+ baseUrlOverride: account.baseUrlOverride ?? null,[39m
+[31m+ allowedModels: [...(account.allowedModels ?? [])],[39m
+[31m+ modelRoleBindings: [...otherBindings, nextBinding],[39m
+[31m+ deniedModels: [...(account.deniedModels ?? [])],[39m
+[31m+ entitlementTags: [...(account.entitlementTags ?? [])],[39m
+[31m+ budgetPolicyRef: account.budgetPolicyRef ?? "budget.default",[39m
+[31m+ quotaPolicyRef: account.quotaPolicyRef ?? "quota.default",[39m
+[31m+ status: account.status ?? "active",[39m
+[31m+ healthStatus: account.healthStatus ?? "healthy",[39m
+[31m+ rotationState: account.rotationState ?? "stable",[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export async function convergeSavedRuntimeAccount(input: {[39m
+[31m+ readonly currentSnapshot: ConfiguredModelsSnapshot;[39m
+[31m+ readonly mutate: () => Promise;[39m
+[31m+ }): Promise {[39m
+[31m+ const updatedAccount = await input.mutate();[39m
+[31m+ const hasExistingAccount = input.currentSnapshot.accounts.some([39m
+[31m+ (account) => account.providerAccountId === updatedAccount.providerAccountId,[39m
+[31m+ );[39m
+[31m+ return {[39m
+[31m+ accounts: hasExistingAccount[39m
+[31m+ ? input.currentSnapshot.accounts.map((account) =>[39m
+[31m+ account.providerAccountId === updatedAccount.providerAccountId ? updatedAccount : account,[39m
+[31m+ )[39m
+[31m+ : [...input.currentSnapshot.accounts, updatedAccount],[39m
+[31m+ endpoints: input.currentSnapshot.endpoints,[39m
+[31m+ models: input.currentSnapshot.models,[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export async function loadConfiguredModelsMutationState(input: {[39m
+[31m+ readonly loadAccounts: () => Promise;[39m
+[31m+ readonly loadEndpoints: () => Promise;[39m
+[31m+ readonly loadModels: () => Promise;[39m
+[31m+ readonly loadController: () => Promise;[39m
+[31m+ }): Promise<{[39m
+[31m+ readonly snapshot: ConfiguredModelsSnapshot;[39m
+[31m+ readonly controller: RuntimeControllerAssignment | null;[39m
+[31m+ }> {[39m
+[31m+ const [accounts, endpoints, models, controller] = await Promise.all([[39m
+[31m+ input.loadAccounts(),[39m
+[31m+ input.loadEndpoints(),[39m
+[31m+ input.loadModels(),[39m
+[31m+ input.loadController(),[39m
+[31m+ ]);[39m
+[31m+ return { snapshot: { accounts, endpoints, models }, controller };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export default function ControlModelsRoute() {[39m
+[31m+ const [snapshot, setSnapshot] = useState(null);[39m
+[31m+ const [requests, setRequests] = useState([]);[39m
+[31m+ const [requestEvidenceStatus, setRequestEvidenceStatus] =[39m
+[31m+ useState("loading");[39m
+[31m+ const [controller, setController] = useState(null);[39m
+[31m+ const [rolePolicy, setRolePolicy] = useState(null);[39m
+[31m+ const [controllerLoaded, setControllerLoaded] = useState(false);[39m
+[31m+ const [selectedModelId, setSelectedModelId] = useState(null);[39m
+[31m+ const [draftRolesByAccountId, setDraftRolesByAccountId] = useState>({});[39m
+[31m+ const [savingAccountId, setSavingAccountId] = useState(null);[39m
+[31m+ const [removingTargetKey, setRemovingTargetKey] = useState(null);[39m
+[31m+ const [pendingRemovalConfirmationKey, setPendingRemovalConfirmationKey] = useState([39m
+[31m+ null,[39m
+[31m+ );[39m
+[31m+ const [statusMessage, setStatusMessage] = useState(null);[39m
+[31m+ const [error, setError] = useState(null);[39m
+[31m+ const [candidates, setCandidates] = useState([]);[39m
+[31m+ const [telemetryRollup, setTelemetryRollup] = useState(null);[39m
+[31m+ const [pendingControllerEndpointId, setPendingControllerEndpointId] = useState([39m
+[31m+ null,[39m
+[31m+ );[39m
+[31m+ const [expandedBindingRoleId, setExpandedBindingRoleId] = useState(null);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ return startDeferredConfiguredModelsBootstrap({[39m
+[31m+ loadInitial: async (): Promise => {[39m
+[31m+ const [accounts, endpoints, models, nextController, nextRolePolicy, nextCandidates] =[39m
+[31m+ await Promise.all([[39m
+[31m+ fetchRuntimeAccounts(),[39m
+[31m+ fetchRuntimeEndpoints(),[39m
+[31m+ fetchRuntimeModels(),[39m
+[31m+ fetchControllerAssignment(),[39m
+[31m+ fetchRolePolicy(),[39m
+[31m+ fetchRouterCandidates(),[39m
+[31m+ ]);[39m
+[31m+ return {[39m
+[31m+ snapshot: {[39m
+[31m+ accounts,[39m
+[31m+ endpoints,[39m
+[31m+ models,[39m
+[31m+ },[39m
+[31m+ controller: nextController,[39m
+[31m+ rolePolicy: nextRolePolicy,[39m
+[31m+ candidates: nextCandidates,[39m
+[31m+ };[39m
+[31m+ },[39m
+[31m+ onInitialData: (loaded) => {[39m
+[31m+ setSnapshot(loaded.snapshot);[39m
+[31m+ setController(loaded.controller);[39m
+[31m+ setRolePolicy(loaded.rolePolicy);[39m
+[31m+ setCandidates(loaded.candidates);[39m
+[31m+ setRequests([]);[39m
+[31m+ setRequestEvidenceStatus("loading");[39m
+[31m+ setControllerLoaded(true);[39m
+[31m+ setError(null);[39m
+[31m+ },[39m
+[31m+ onInitialError: (message) => {[39m
+[31m+ setError(message);[39m
+[31m+ },[39m
+[31m+ loadObservedRequests: async () => [],[39m
+[31m+ onObservedRequests: () => {[39m
+[31m+ setRequests([]);[39m
+[31m+ setRequestEvidenceStatus("unavailable");[39m
+[31m+ },[39m
+[31m+ onObservedRequestsError: () => {[39m
+[31m+ setRequests([]);[39m
+[31m+ setRequestEvidenceStatus("unavailable");[39m
+[31m+ },[39m
+[31m+ });[39m
+[31m+ }, []);[39m
+[31m+[39m
+[31m+ const cards = useMemo([39m
+[31m+ () =>[39m
+[31m+ snapshot[39m
+[31m+ ? buildConfiguredModelCards({[39m
+[31m+ models: snapshot.models,[39m
+[31m+ endpoints: snapshot.endpoints,[39m
+[31m+ accounts: snapshot.accounts,[39m
+[31m+ requests: requestEvidenceStatus === "ready" ? requests : null,[39m
+[31m+ controller,[39m
+[31m+ })[39m
+[31m+ : [],[39m
+[31m+ [controller, requestEvidenceStatus, requests, snapshot],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ const selectedCard =[39m
+[31m+ cards.find((card) => configuredModelCardKey(card) === selectedModelId) ?? null;[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ const defaultSelectedModelId = resolveDefaultSelectedModelId(cards);[39m
+[31m+ if (!defaultSelectedModelId) {[39m
+[31m+ if (selectedModelId !== null) {[39m
+[31m+ setSelectedModelId(null);[39m
+[31m+ }[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ if ([39m
+[31m+ !selectedModelId ||[39m
+[31m+ !cards.some((card) => configuredModelCardKey(card) === selectedModelId)[39m
+[31m+ ) {[39m
+[31m+ setSelectedModelId(defaultSelectedModelId);[39m
+[31m+ }[39m
+[31m+ }, [cards, selectedModelId]);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (selectedCard?.endpointId) {[39m
+[31m+ void fetchModelTelemetryRollup({[39m
+[31m+ modelId: selectedCard.modelId,[39m
+[31m+ endpointId: selectedCard.endpointId,[39m
+[31m+ }).then(setTelemetryRollup, () => setTelemetryRollup(null));[39m
+[31m+ } else {[39m
+[31m+ setTelemetryRollup(null);[39m
+[31m+ }[39m
+[31m+ }, [selectedCard?.endpointId, selectedCard?.modelId]);[39m
+[31m+ const selectedEndpoints =[39m
+[31m+ snapshot && selectedCard[39m
+[31m+ ? selectedCard.endpointId[39m
+[31m+ ? snapshot.endpoints.filter((endpoint) => endpoint.endpointId === selectedCard.endpointId)[39m
+[31m+ : snapshot.endpoints.filter((endpoint) => endpoint.modelId === selectedCard.modelId)[39m
+[31m+ : [];[39m
+[31m+ const selectedLlamaSwapEndpoints = selectedEndpoints.filter([39m
+[31m+ (endpoint) => endpoint.sourceType === "local" && endpoint.localModelSource === "llama-swap",[39m
+[31m+ );[39m
+[31m+ const selectedToolStyles = [[39m
+[31m+ ...new Set([39m
+[31m+ selectedEndpoints[39m
+[31m+ .filter((endpoint) => endpoint.toolCallingSupported)[39m
+[31m+ .map((endpoint) => endpoint.toolCallingStyle ?? "unknown"),[39m
+[31m+ ),[39m
+[31m+ ].sort((left, right) => left.localeCompare(right, "en"));[39m
+[31m+ const allRuntimeRoleIds = useMemo([39m
+[31m+ () => (rolePolicy?.roleDefinitions ?? []).map((role) => role.role_id),[39m
+[31m+ [rolePolicy],[39m
+[31m+ );[39m
+[31m+ const selectedModelAccounts = useMemo([39m
+[31m+ () =>[39m
+[31m+ snapshot && selectedCard[39m
+[31m+ ? snapshot.accounts.filter((account) => {[39m
+[31m+ const hasBinding = (account.modelRoleBindings ?? []).some([39m
+[31m+ (binding) => binding.modelId === selectedCard.modelId,[39m
+[31m+ );[39m
+[31m+ const allowsModel = (account.allowedModels ?? []).includes(selectedCard.modelId);[39m
+[31m+ const wildcardPeerEndpoint =[39m
+[31m+ (account.allowedModels ?? []).length === 0 &&[39m
+[31m+ snapshot.endpoints.some([39m
+[31m+ (endpoint) =>[39m
+[31m+ endpoint.modelId === selectedCard.modelId &&[39m
+[31m+ endpoint.providerAccountId === account.providerAccountId,[39m
+[31m+ );[39m
+[31m+ return allowsModel || hasBinding || wildcardPeerEndpoint;[39m
+[31m+ })[39m
+[31m+ : [],[39m
+[31m+ [selectedCard, snapshot],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (!selectedCard) {[39m
+[31m+ setDraftRolesByAccountId({});[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setDraftRolesByAccountId([39m
+[31m+ Object.fromEntries([39m
+[31m+ selectedModelAccounts.map((account) => [[39m
+[31m+ configuredModelRoleDraftKey(account.providerAccountId, selectedCard.endpointId),[39m
+[31m+ getAccountRoleIdsForModel([39m
+[31m+ account,[39m
+[31m+ selectedCard.modelId,[39m
+[31m+ allRuntimeRoleIds,[39m
+[31m+ selectedCard.endpointId,[39m
+[31m+ ),[39m
+[31m+ ]),[39m
+[31m+ ),[39m
+[31m+ );[39m
+[31m+ }, [allRuntimeRoleIds, selectedCard, selectedModelAccounts]);[39m
+[31m+[39m
+[31m+ const saveAccountRoles = async (account: RuntimeAccount, nextRoleIds?: readonly string[]) => {[39m
+[31m+ if (!selectedCard || !snapshot) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setSavingAccountId(account.providerAccountId);[39m
+[31m+ setStatusMessage(`Saving role eligibility for ${account.providerAccountId}…`);[39m
+[31m+ try {[39m
+[31m+ const roleIds =[39m
+[31m+ nextRoleIds ??[39m
+[31m+ draftRolesByAccountId[[39m
+[31m+ configuredModelRoleDraftKey(account.providerAccountId, selectedCard.endpointId)[39m
+[31m+ ] ??[39m
+[31m+ [];[39m
+[31m+ const loaded = await saveConfiguredModelRoleEligibility({[39m
+[31m+ mutate: () =>[39m
+[31m+ upsertRuntimeAccount([39m
+[31m+ createAccountMutationPayload([39m
+[31m+ account,[39m
+[31m+ selectedCard.modelId,[39m
+[31m+ roleIds,[39m
+[31m+ allRuntimeRoleIds,[39m
+[31m+ selectedCard.endpointId,[39m
+[31m+ ),[39m
+[31m+ ),[39m
+[31m+ reloadCanonicalState: () =>[39m
+[31m+ loadConfiguredModelsMutationState({[39m
+[31m+ loadAccounts: fetchRuntimeAccounts,[39m
+[31m+ loadEndpoints: fetchRuntimeEndpoints,[39m
+[31m+ loadModels: fetchRuntimeModels,[39m
+[31m+ loadController: fetchControllerAssignment,[39m
+[31m+ }),[39m
+[31m+ });[39m
+[31m+ setSnapshot(loaded.snapshot);[39m
+[31m+ setController(loaded.controller);[39m
+[31m+ setControllerLoaded(true);[39m
+[31m+ const endpointVariantCount = loaded.snapshot.endpoints.filter([39m
+[31m+ (endpoint) =>[39m
+[31m+ endpoint.modelId === selectedCard.modelId &&[39m
+[31m+ endpoint.providerAccountId === account.providerAccountId,[39m
+[31m+ ).length;[39m
+[31m+ setStatusMessage([39m
+[31m+ describeSavedModelRoleEligibility({[39m
+[31m+ displayName: selectedCard.displayName,[39m
+[31m+ providerAccountId: account.providerAccountId,[39m
+[31m+ selectedRoleIds: roleIds,[39m
+[31m+ roleDefinitions: rolePolicy?.roleDefinitions ?? [],[39m
+[31m+ endpointVariantCount,[39m
+[31m+ }),[39m
+[31m+ );[39m
+[31m+ setError(null);[39m
+[31m+ } catch (value) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not update model roles.");[39m
+[31m+ } finally {[39m
+[31m+ setSavingAccountId(null);[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ const refreshModelState = async () => {[39m
+[31m+ const loaded = await loadConfiguredModelsMutationState({[39m
+[31m+ loadAccounts: fetchRuntimeAccounts,[39m
+[31m+ loadEndpoints: fetchRuntimeEndpoints,[39m
+[31m+ loadModels: fetchRuntimeModels,[39m
+[31m+ loadController: fetchControllerAssignment,[39m
+[31m+ });[39m
+[31m+ setSnapshot(loaded.snapshot);[39m
+[31m+ setController(loaded.controller);[39m
+[31m+ setControllerLoaded(true);[39m
+[31m+ setError(null);[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ const removeConfiguredModel = async (account: RuntimeAccount) => {[39m
+[31m+ if (!selectedCard) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ const removalKey = `account:${account.providerAccountId}`;[39m
+[31m+ const usesLocalPeerEndpoint = selectedEndpoints.some([39m
+[31m+ (endpoint) =>[39m
+[31m+ endpoint.providerAccountId === account.providerAccountId && endpoint.sourceType === "local",[39m
+[31m+ );[39m
+[31m+ setRemovingTargetKey(removalKey);[39m
+[31m+ setStatusMessage(null);[39m
+[31m+ try {[39m
+[31m+ if (usesLocalPeerEndpoint) {[39m
+[31m+ await unloadPeerModel(selectedCard.modelId);[39m
+[31m+ await refreshModelState();[39m
+[31m+ setStatusMessage(`Removed ${selectedCard.modelId} from the peer-backed router pool.`);[39m
+[31m+ } else if (selectedCard.endpointId) {[39m
+[31m+ const result = await removeRuntimeEndpoint(selectedCard.endpointId);[39m
+[31m+ await refreshModelState();[39m
+[31m+ setStatusMessage([39m
+[31m+ result.status === "absent"[39m
+[31m+ ? `${selectedCard.displayName ?? selectedCard.modelId} was already absent; sibling instances are unchanged.`[39m
+[31m+ : `Removed ${selectedCard.displayName ?? selectedCard.modelId}; sibling instances are unchanged.`,[39m
+[31m+ );[39m
+[31m+ } else {[39m
+[31m+ const result = await removeRuntimeAccountModel([39m
+[31m+ account.providerAccountId,[39m
+[31m+ selectedCard.modelId,[39m
+[31m+ );[39m
+[31m+ await refreshModelState();[39m
+[31m+ setStatusMessage([39m
+[31m+ result.alreadyAbsent[39m
+[31m+ ? `${selectedCard.modelId} was already absent from ${account.providerAccountId}; the pool is converged.`[39m
+[31m+ : result.removedAccount[39m
+[31m+ ? `Removed ${selectedCard.modelId} and deleted ${account.providerAccountId} because it was the last configured model on that account.`[39m
+[31m+ : `Removed ${selectedCard.modelId} from ${account.providerAccountId}.`,[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+ setError(null);[39m
+[31m+ } catch (value) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not remove the configured model.");[39m
+[31m+ } finally {[39m
+[31m+ setRemovingTargetKey(null);[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ const unloadSelectedLocalModel = async () => {[39m
+[31m+ if (!selectedCard) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setRemovingTargetKey(`local:${selectedCard.modelId}`);[39m
+[31m+ setStatusMessage(null);[39m
+[31m+ try {[39m
+[31m+ await unloadLocalModel(selectedCard.modelId);[39m
+[31m+ await refreshModelState();[39m
+[31m+ setStatusMessage(`Unloaded ${selectedCard.modelId} from the local runtime pool.`);[39m
+[31m+ setError(null);[39m
+[31m+ } catch (value) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not unload the local model.");[39m
+[31m+ } finally {[39m
+[31m+ setRemovingTargetKey(null);[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ if (error) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+ if (!snapshot || !controllerLoaded) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const selectedBenchmarkCandidate = resolveSelectedBenchmarkCandidate(candidates, selectedCard);[39m
+[31m+ const selectedBenchmarkCapability = selectedBenchmarkCandidate?.benchmarkCapability ?? null;[39m
+[31m+ const benchmarkAssignedRoleRows = (rolePolicy?.roleDefinitions ?? [])[39m
+[31m+ .filter([39m
+[31m+ (role) =>[39m
+[31m+ selectedCard?.roleIds.includes(role.role_id) &&[39m
+[31m+ typeof selectedBenchmarkCapability?.eligibleRoleScores?.[role.role_id] === "number",[39m
+[31m+ )[39m
+[31m+ .map((role) => ({[39m
+[31m+ roleId: role.role_id,[39m
+[31m+ label: role.name,[39m
+[31m+ score: selectedBenchmarkCapability?.eligibleRoleScores?.[role.role_id] ?? 0,[39m
+[31m+ }));[39m
+[31m+ const benchmarkSuggestedRoleRows = (rolePolicy?.roleDefinitions ?? [])[39m
+[31m+ .filter([39m
+[31m+ (role) =>[39m
+[31m+ !selectedCard?.roleIds.includes(role.role_id) &&[39m
+[31m+ typeof selectedBenchmarkCapability?.roleScores?.[role.role_id] === "number",[39m
+[31m+ )[39m
+[31m+ .map((role) => ({[39m
+[31m+ roleId: role.role_id,[39m
+[31m+ label: role.name,[39m
+[31m+ score: selectedBenchmarkCapability?.roleScores?.[role.role_id] ?? 0,[39m
+[31m+ lowCoverage: (selectedBenchmarkCapability?.coverage?.lowCoverageRoleIds ?? []).includes([39m
+[31m+ role.role_id,[39m
+[31m+ ),[39m
+[31m+ }))[39m
+[31m+ .sort((left, right) => right.score - left.score);[39m
+[31m+ const benchmarkGroupRows = Object.entries(selectedBenchmarkCapability?.groupScores ?? {})[39m
+[31m+ .map(([groupId, score]) => ({[39m
+[31m+ groupId,[39m
+[31m+ score,[39m
+[31m+ lowCoverage: (selectedBenchmarkCapability?.coverage?.lowCoverageGroupIds ?? []).includes([39m
+[31m+ groupId,[39m
+[31m+ ),[39m
+[31m+ }))[39m
+[31m+ .sort((left, right) => right.score - left.score);[39m
+[31m+ const selectedCapabilityScore = selectedBenchmarkCapability?.overallScore ?? null;[39m
+[31m+ const selectedPrimaryAccount = resolveSelectedModelAccount([39m
+[31m+ selectedModelAccounts,[39m
+[31m+ selectedEndpoints,[39m
+[31m+ );[39m
+[31m+ const selectedPrimaryAccountHasLocalPeerEndpoint = selectedPrimaryAccount[39m
+[31m+ ? selectedEndpoints.some([39m
+[31m+ (endpoint) =>[39m
+[31m+ endpoint.providerAccountId === selectedPrimaryAccount.providerAccountId &&[39m
+[31m+ endpoint.sourceType === "local",[39m
+[31m+ )[39m
+[31m+ : false;[39m
+[31m+ const selectedPrimaryAccountRoleIds = selectedPrimaryAccount[39m
+[31m+ ? (draftRolesByAccountId[[39m
+[31m+ configuredModelRoleDraftKey([39m
+[31m+ selectedPrimaryAccount.providerAccountId,[39m
+[31m+ selectedCard?.endpointId,[39m
+[31m+ )[39m
+[31m+ ] ??[39m
+[31m+ getAccountRoleIdsForModel([39m
+[31m+ selectedPrimaryAccount,[39m
+[31m+ selectedCard?.modelId ?? "",[39m
+[31m+ allRuntimeRoleIds,[39m
+[31m+ selectedCard?.endpointId,[39m
+[31m+ ))[39m
+[31m+ : [];[39m
+[31m+ const selectedFooterAction = resolveConfiguredModelFooterAction({[39m
+[31m+ hasSelectedCard: selectedCard !== null,[39m
+[31m+ isController: selectedCard?.controllerState === "active",[39m
+[31m+ hasLlamaSwapEndpoint: selectedLlamaSwapEndpoints.length > 0,[39m
+[31m+ hasPrimaryAccount: selectedPrimaryAccount !== null,[39m
+[31m+ hasLocalPeerEndpoint: selectedPrimaryAccountHasLocalPeerEndpoint,[39m
+[31m+ isRemoving: removingTargetKey !== null,[39m
+[31m+ });[39m
+[31m+ const selectedRemovalTargetKey = selectedCard[39m
+[31m+ ? selectedFooterAction.kind === "unload-local"[39m
+[31m+ ? `local:${selectedCard.modelId}`[39m
+[31m+ : selectedCard.endpointId[39m
+[31m+ ? `endpoint:${selectedCard.endpointId}`[39m
+[31m+ : `account:${selectedPrimaryAccount?.providerAccountId ?? "none"}:${selectedCard.modelId}`[39m
+[31m+ : "none";[39m
+[31m+ const removalConfirmationPending =[39m
+[31m+ (selectedFooterAction.kind === "eject-configured" ||[39m
+[31m+ selectedFooterAction.kind === "eject-controller") &&[39m
+[31m+ pendingRemovalConfirmationKey === selectedRemovalTargetKey;[39m
+[31m+ const selectedModelEvidencePills = buildSelectedModelEvidencePills({[39m
+[31m+ assignedRoleRows: benchmarkAssignedRoleRows,[39m
+[31m+ groupRows: benchmarkGroupRows,[39m
+[31m+ suggestedRoleRows: benchmarkSuggestedRoleRows,[39m
+[31m+ });[39m
+[31m+ const selectedHealthyEndpointCount = selectedEndpoints.filter([39m
+[31m+ (endpoint) =>[39m
+[31m+ endpoint.healthStatus === "healthy" ||[39m
+[31m+ (!endpoint.healthStatus && endpoint.status === "active"),[39m
+[31m+ ).length;[39m
+[31m+ const selectedMeanLatencyMs = (() => {[39m
+[31m+ if (!telemetryRollup || telemetryRollup.tasks.length === 0) {[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+ const samples = telemetryRollup.tasks[39m
+[31m+ .map((task) => task.avgLatencyMs)[39m
+[31m+ .filter((value): value is number => typeof value === "number" && Number.isFinite(value));[39m
+[31m+ if (samples.length === 0) {[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+ return samples.reduce((sum, value) => sum + value, 0) / samples.length;[39m
+[31m+ })();[39m
+[31m+ const selectedLatencyProfile = readSelectedOperationalPerformance(selectedBenchmarkCandidate);[39m
+[31m+ const selectedDifficultyMix = (() => {[39m
+[31m+ const buckets = selectedBenchmarkCapability?.scoresByBucket;[39m
+[31m+ if (buckets) {[39m
+[31m+ return [[39m
+[31m+ `E ${formatScoreWithCoverage(buckets.easy?.score, buckets.easy?.cases)}`,[39m
+[31m+ `M ${formatScoreWithCoverage(buckets.medium?.score, buckets.medium?.cases)}`,[39m
+[31m+ `H ${formatScoreWithCoverage(buckets.hard?.score, buckets.hard?.cases)}`,[39m
+[31m+ ].join(" · ");[39m
+[31m+ }[39m
+[31m+ return null;[39m
+[31m+ })();[39m
+[31m+ const selectedMetaPanel = selectedCard[39m
+[31m+ ? buildSelectedModelMetaPanel({[39m
+[31m+ modelId: selectedCard.modelId,[39m
+[31m+ displayName: selectedCard.displayName,[39m
+[31m+ sourceSummary: selectedCard.sourceSummary,[39m
+[31m+ status: selectedCard.status,[39m
+[31m+ controllerState: selectedCard.controllerState,[39m
+[31m+ endpointCount: selectedCard.endpointCount,[39m
+[31m+ healthyEndpointCount: selectedHealthyEndpointCount,[39m
+[31m+ toolCallingSupported: selectedCard.toolCallingSupported,[39m
+[31m+ toolStyles: selectedToolStyles,[39m
+[31m+ contextWindow: selectedCard.contextWindow,[39m
+[31m+ modalities: selectedCard.modalities,[39m
+[31m+ pricing: selectedCard.pricing,[39m
+[31m+ overallScore: selectedCapabilityScore,[39m
+[31m+ latencyP50Ms: selectedLatencyProfile.p50,[39m
+[31m+ latencyP95Ms: selectedLatencyProfile.p95,[39m
+[31m+ meanLatencyMs: selectedMeanLatencyMs,[39m
+[31m+ liveFailureRate: selectedLatencyProfile.failureRate,[39m
+[31m+ liveSampleCount: selectedLatencyProfile.sampleCount,[39m
+[31m+ difficultyMix: selectedDifficultyMix,[39m
+[31m+ routingHint: telemetryRollup?.strengths[0] ?? selectedModelEvidencePills[0]?.label ?? null,[39m
+[31m+ })[39m
+[31m+ : null;[39m
+[31m+[39m
+[31m+ return ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+ {cards.length === 0 ? ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ Open Local Models[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Open Local Endpoints[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Open Providers[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Select a controller[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+ [39m
+[31m+ {statusMessage ? ([39m
+[31m+
[39m
+[31m+ {statusMessage}[39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+ {!controller ? ([39m
+[31m+
[39m
+[31m+ Controller pending — activate a local or remote endpoint, then assign it from Router[39m
+[31m+ → Controller.[39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Models
[39m
+[31m+
[39m
+[31m+ {cards.map((card) => {[39m
+[31m+ const cardKey = configuredModelCardKey(card);[39m
+[31m+ const selected = selectedModelId === cardKey;[39m
+[31m+ const capabilityScore =[39m
+[31m+ resolveSelectedBenchmarkCandidate(candidates, card)?.benchmarkCapability[39m
+[31m+ ?.overallScore ?? null;[39m
+[31m+ const inventoryPills = buildConfiguredModelInventoryPills({[39m
+[31m+ toolCallingSupported: card.toolCallingSupported,[39m
+[31m+ endpointCount: card.endpointCount,[39m
+[31m+ capabilityScore,[39m
+[31m+ });[39m
+[31m+ return ([39m
+[31m+
{[39m
+[31m+ setPendingRemovalConfirmationKey(null);[39m
+[31m+ setSelectedModelId(cardKey);[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {card.displayName}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {card.controllerState === "active" ? "controller" : card.status}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {[[39m
+[31m+ card.sourceSummary,[39m
+[31m+ ...inventoryPills.map((pill) => pill.label),[39m
+[31m+ ].join(" · ")}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ );[39m
+[31m+ })}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+ {selectedCard && selectedMetaPanel ? ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+
{selectedMetaPanel.title}
[39m
+[31m+
[39m
+[31m+ {selectedMetaPanel.facts.map((row) => ([39m
+[31m+ [39m
+[31m+
{row.label} [39m
+[31m+ {row.value} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Cost
[39m
+[31m+
[39m
+[31m+ {selectedMetaPanel.cost.map((row) => ([39m
+[31m+ [39m
+[31m+
{row.label} [39m
+[31m+ {row.value} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Benchmark
[39m
+[31m+
[39m
+[31m+ {selectedMetaPanel.benchmark.map((row) => ([39m
+[31m+ [39m
+[31m+
{row.label} [39m
+[31m+ [39m
+[31m+ {row.value}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+
[39m
+[31m+ Select a model from the inventory to inspect bindings, benchmark evidence, and[39m
+[31m+ endpoint ids.[39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+ {selectedCard ? ([39m
+[31m+
[39m
+[31m+ [39m
+[31m+
Roles
[39m
+[31m+
[39m
+[31m+ {selectedCard.displayName} · tasks under each role[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {rolePolicy && selectedPrimaryAccount ? ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+ Saved immediately for {selectedPrimaryAccount.providerAccountId}. Task and[39m
+[31m+ group eligibility is derived from these roles for this exact endpoint[39m
+[31m+ instance. A legacy model default is inherited only until this instance is[39m
+[31m+ edited.[39m
+[31m+
[39m
+[31m+
{[39m
+[31m+ const accountId = selectedPrimaryAccount.providerAccountId;[39m
+[31m+ const draftKey = configuredModelRoleDraftKey([39m
+[31m+ accountId,[39m
+[31m+ selectedCard.endpointId,[39m
+[31m+ );[39m
+[31m+ const existing = new Set([39m
+[31m+ draftRolesByAccountId[draftKey] ?? selectedPrimaryAccountRoleIds,[39m
+[31m+ );[39m
+[31m+ if (nextChecked) {[39m
+[31m+ existing.add(roleId);[39m
+[31m+ } else {[39m
+[31m+ existing.delete(roleId);[39m
+[31m+ }[39m
+[31m+ const nextRoleIds = [...existing].sort((left, right) =>[39m
+[31m+ left.localeCompare(right, "en"),[39m
+[31m+ );[39m
+[31m+ setDraftRolesByAccountId((current) => ({[39m
+[31m+ ...current,[39m
+[31m+ [draftKey]: nextRoleIds,[39m
+[31m+ }));[39m
+[31m+ void saveAccountRoles(selectedPrimaryAccount, nextRoleIds);[39m
+[31m+ }}[39m
+[31m+ onToggleExpandedRole={(roleId) =>[39m
+[31m+ setExpandedBindingRoleId((current) =>[39m
+[31m+ current === roleId ? null : roleId,[39m
+[31m+ )[39m
+[31m+ }[39m
+[31m+ />[39m
+[31m+ [39m
+[31m+ ) : ([39m
+[31m+ [39m
+[31m+ No backing provider accounts currently expose this model.[39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+ ) : ([39m
+[31m+
[39m
+[31m+ Roles and task bindings appear when a model is selected.[39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+ {[39m
+[31m+ const endpointId = selectedCard?.endpointIds[0];[39m
+[31m+ if (!endpointId) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setPendingControllerEndpointId(endpointId);[39m
+[31m+ setError(null);[39m
+[31m+ void updateControllerAssignment({ endpointId })[39m
+[31m+ .then(async (nextController) => {[39m
+[31m+ setController(nextController);[39m
+[31m+ await refreshModelState();[39m
+[31m+ setStatusMessage(`Made ${selectedCard.displayName} the primary controller.`);[39m
+[31m+ })[39m
+[31m+ .catch((value: unknown) =>[39m
+[31m+ setError([39m
+[31m+ value instanceof Error[39m
+[31m+ ? value.message[39m
+[31m+ : "Could not update the controller assignment.",[39m
+[31m+ ),[39m
+[31m+ )[39m
+[31m+ .finally(() => setPendingControllerEndpointId(null));[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ {pendingControllerEndpointId ? "Saving…" : "Make primary controller"}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Open Roles[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ Open Benchmark[39m
+[31m+ [39m
+[31m+ {[39m
+[31m+ if (!selectedCard || selectedFooterAction.kind === "none") {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ const clickDisposition = resolveConfiguredModelRemovalClick({[39m
+[31m+ actionKind: selectedFooterAction.kind,[39m
+[31m+ targetKey: selectedRemovalTargetKey,[39m
+[31m+ pendingConfirmationKey: pendingRemovalConfirmationKey,[39m
+[31m+ });[39m
+[31m+ if (clickDisposition === "request-confirmation") {[39m
+[31m+ setPendingRemovalConfirmationKey(selectedRemovalTargetKey);[39m
+[31m+ setStatusMessage([39m
+[31m+ selectedFooterAction.kind === "eject-controller"[39m
+[31m+ ? `Confirm eject for ${selectedCard.displayName}. This is the primary controller; ejecting clears the controller assignment and leaves an empty pool.`[39m
+[31m+ : `Confirm ${selectedFooterAction.label.toLowerCase()} for ${selectedCard.displayName}. Other effort variants remain configured unless they share this peer-backed model.`,[39m
+[31m+ );[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setPendingRemovalConfirmationKey(null);[39m
+[31m+ if (selectedFooterAction.kind === "unload-local") {[39m
+[31m+ void unloadSelectedLocalModel();[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ if (!selectedPrimaryAccount) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ void removeConfiguredModel(selectedPrimaryAccount);[39m
+[31m+ }}[39m
+[31m+ >[39m
+[31m+ {removingTargetKey[39m
+[31m+ ? selectedFooterAction.kind === "unload-local"[39m
+[31m+ ? "Unloading…"[39m
+[31m+ : "Ejecting…"[39m
+[31m+ : removalConfirmationPending[39m
+[31m+ ? `Confirm ${selectedFooterAction.label.toLowerCase()}`[39m
+[31m+ : selectedFooterAction.label}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+
+[36m [2m❯[22m app/routes/control-models.test.ts:[2m793:31[22m[39m
+ [90m791| [39m
+ [90m792| [39mtest("computes model-pool evidence from the candidate's benchmark capa…
+ [90m793| [39m [34mexpect[39m(controlModelsSource)[33m.[39m[34mtoContain[39m([32m"classifyEffortEvidence"[39m)[33m;[39m
+ [90m | [39m [31m^[39m
+ [90m794| [39m [34mexpect[39m(controlModelsSource)[33m.[39m[34mtoContain[39m([32m"formatEffortEvidenceLabel"[39m)[33m;[39m
+ [90m795| [39m [34mexpect[39m(controlModelsSource)[33m.[39m[34mtoContain[39m([32m"relatedEffortOverallScore"[39m)[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/6]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m app/routes/endpoints.test.tsx[2m > [22mbuildRuntimeConnectionRows[2m > [22mlabels each endpoint row's effective reasoning effort (R11)
+[31m[1mAssertionError[22m: expected [ { …(10) }, { …(10) } ] to deep equally contain ObjectContaining{…}[39m
+
+[32m- Expected:[39m
+ObjectContaining {
+ "effortLabel": "High (fixed)",
+}
+
+[31m+ Received:[39m
+[
+ {
+ "connectionLabel": "deepseek.personal.deepseek-api-key",
+ "endpointLabel": "deepseek.personal.deepseek-api-key.global.deepseek-v4-flash",
+ "healthLabel": "healthy",
+ "healthTone": "success",
+ "key": "endpoint:deepseek.personal.deepseek-api-key.global.deepseek-v4-flash",
+ "modelLabel": "deepseek/deepseek-v4-flash",
+ "providerLabel": "deepseek",
+ "readinessLabel": "active",
+ "readinessTone": "success",
+ "sourceLabel": "Direct provider / remote_api",
+ },
+ {
+ "connectionLabel": "deepseek.personal.deepseek-api-key",
+ "endpointLabel": "deepseek.personal.deepseek-api-key.global.deepseek-v4-pro-high",
+ "healthLabel": "healthy",
+ "healthTone": "success",
+ "key": "endpoint:deepseek.personal.deepseek-api-key.global.deepseek-v4-pro-high",
+ "modelLabel": "Deepseek V4 Pro (High)",
+ "providerLabel": "deepseek",
+ "readinessLabel": "active",
+ "readinessTone": "success",
+ "sourceLabel": "Direct provider / remote_api",
+ },
+]
+
+[36m [2m❯[22m app/routes/endpoints.test.tsx:[2m109:18[22m[39m
+ [90m107| [39m endpointRows[33m:[39m [34mbuildEndpointCatalogRows[39m(endpoints)[33m,[39m
+ [90m108| [39m })[33m;[39m
+ [90m109| [39m expect(rows).toContainEqual(expect.objectContaining({ effortLabel:…
+ [90m | [39m [31m^[39m
+ [90m110| [39m expect(rows).toContainEqual(expect.objectContaining({ effortLabel:…
+ [90m111| [39m })[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/6]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m app/routes/request-detail.test.tsx[2m > [22mshows effective reasoning effort on the request detail (R11)
+[31m[1mAssertionError[22m: expected 'import { useEffect, useState } from "…' to contain 'formatEffectiveEffortDisclosure'[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[32m- formatEffectiveEffortDisclosure[39m
+[31m+ import { useEffect, useState } from "react";[39m
+[31m+ import { Link, useParams } from "react-router";[39m
+[31m+[39m
+[31m+ import {[39m
+[31m+ Badge,[39m
+[31m+ CodeBlock,[39m
+[31m+ DisclosureSection,[39m
+[31m+ EmptyState,[39m
+[31m+ ErrorState,[39m
+[31m+ LoadingState,[39m
+[31m+ SectionCard,[39m
+[31m+ } from "../components/page-primitives";[39m
+[31m+ import {[39m
+[31m+ accentActionTextClassName,[39m
+[31m+ bodyStrongTextClassName,[39m
+[31m+ compactTitleClassName,[39m
+[31m+ fieldLabelClassName,[39m
+[31m+ inlineTitleClassName,[39m
+[31m+ metaTextClassName,[39m
+[31m+ mutedPanelClassName,[39m
+[31m+ supportingTextClassName,[39m
+[31m+ } from "../lib/design-system";[39m
+[31m+ import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";[39m
+[31m+ import { formatRoutingModeLabel } from "../lib/routing-mode";[39m
+[31m+ import { fetchRequestDetail } from "../lib/runtime-api";[39m
+[31m+ import { useShellHeaderOverride } from "../lib/shell-header-context";[39m
+[31m+[39m
+[31m+ function asRecord(value: unknown): Record | null {[39m
+[31m+ return typeof value === "object" && value !== null ? (value as Record) : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function asNumber(value: unknown): number | null {[39m
+[31m+ return typeof value === "number" && Number.isFinite(value) ? value : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function asStringValue(value: unknown): string | null {[39m
+[31m+ return typeof value === "string" && value.length > 0 ? value : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function asBoolean(value: unknown): boolean | null {[39m
+[31m+ return typeof value === "boolean" ? value : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function pickNumber(record: Record, ...keys: string[]): number | null {[39m
+[31m+ for (const key of keys) {[39m
+[31m+ const value = asNumber(record[key]);[39m
+[31m+ if (value !== null) {[39m
+[31m+ return value;[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function pickString(record: Record, ...keys: string[]): string | null {[39m
+[31m+ for (const key of keys) {[39m
+[31m+ const value = asStringValue(record[key]);[39m
+[31m+ if (value !== null) {[39m
+[31m+ return value;[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function pickBoolean(record: Record, ...keys: string[]): boolean | null {[39m
+[31m+ for (const key of keys) {[39m
+[31m+ const value = asBoolean(record[key]);[39m
+[31m+ if (value !== null) {[39m
+[31m+ return value;[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ return null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ type TokenSource = "measured" | "normalized" | "estimated" | "unavailable";[39m
+[31m+[39m
+[31m+ export interface TokenTruthDisplay {[39m
+[31m+ readonly available: boolean;[39m
+[31m+ readonly source: TokenSource;[39m
+[31m+ readonly value: number | null;[39m
+[31m+ readonly text: string;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function readTokenTruth([39m
+[31m+ usageEvent: Record,[39m
+[31m+ direction: "input" | "output",[39m
+[31m+ ): TokenTruthDisplay {[39m
+[31m+ const prefix = direction === "input" ? "tokens_in" : "tokens_out";[39m
+[31m+ const value = pickNumber([39m
+[31m+ usageEvent,[39m
+[31m+ prefix,[39m
+[31m+ direction === "input" ? "inputTokens" : "outputTokens",[39m
+[31m+ direction === "input" ? "promptTokens" : "completionTokens",[39m
+[31m+ );[39m
+[31m+ const sourceCandidate = pickString(usageEvent, `${prefix}_source`);[39m
+[31m+ const source: TokenSource =[39m
+[31m+ sourceCandidate === "measured" ||[39m
+[31m+ sourceCandidate === "normalized" ||[39m
+[31m+ sourceCandidate === "estimated" ||[39m
+[31m+ sourceCandidate === "unavailable"[39m
+[31m+ ? sourceCandidate[39m
+[31m+ : "unavailable";[39m
+[31m+ const available = pickBoolean(usageEvent, `${prefix}_available`) === true;[39m
+[31m+[39m
+[31m+ if (!available || source === "unavailable" || value === null) {[39m
+[31m+ return {[39m
+[31m+ available: false,[39m
+[31m+ source: "unavailable",[39m
+[31m+ value: null,[39m
+[31m+ text: "n/a · unavailable",[39m
+[31m+ };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return { available: true, source, value, text: `${value} · ${source}` };[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export function readPromptCacheRequestSource([39m
+[31m+ cacheObservability: Record,[39m
+[31m+ ): "explicit" | "synthesized" | null {[39m
+[31m+ const source = pickString(cacheObservability, "promptCacheRequestSource");[39m
+[31m+ return source === "explicit" || source === "synthesized" ? source : null;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function formatDateTime(value: number | null): string {[39m
+[31m+ if (value === null) {[39m
+[31m+ return "n/a";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return new Date(value).toLocaleString();[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function formatUsd(value: number | null): string {[39m
+[31m+ if (value === null) {[39m
+[31m+ return "n/a";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return `$${value.toFixed(4)}`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function formatPercent(value: number | null): string {[39m
+[31m+ if (value === null) {[39m
+[31m+ return "n/a";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return `${(value * 100).toFixed(0)}%`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function renderMetricValue(value: string | number | null): string | number {[39m
+[31m+ return value ?? "n/a";[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function readStringList(value: unknown): string[] {[39m
+[31m+ if (!Array.isArray(value)) {[39m
+[31m+ return [];[39m
+[31m+ }[39m
+[31m+ return value.filter((entry): entry is string => typeof entry === "string" && entry.length > 0);[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function readTaxonomyStringList(...values: unknown[]): string[] {[39m
+[31m+ for (const value of values) {[39m
+[31m+ const list = readStringList(value);[39m
+[31m+ if (list.length > 0) {[39m
+[31m+ return list;[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ return [];[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export default function RequestDetailRoute() {[39m
+[31m+ const { requestId = "" } = useParams();[39m
+[31m+ const [detail, setDetail] = useState> | null>(null);[39m
+[31m+ const [error, setError] = useState(null);[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ if (!requestId) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ void fetchRequestDetail(requestId)[39m
+[31m+ .then(setDetail)[39m
+[31m+ .catch((value: unknown) =>[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not load request detail."),[39m
+[31m+ );[39m
+[31m+ }, [requestId]);[39m
+[31m+[39m
+[31m+ useShellHeaderOverride({ title: requestId }, [requestId]);[39m
+[31m+[39m
+[31m+ if (error) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+ if (!detail) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ const request = asRecord(detail.request) ?? {};[39m
+[31m+ const endpointProfile = asRecord(detail.endpointProfile) ?? {};[39m
+[31m+ const latestProfile =[39m
+[31m+ asRecord(endpointProfile.operationalProfile) ?? asRecord(endpointProfile.latestProfile) ?? {};[39m
+[31m+ const recentSamples = Array.isArray(endpointProfile.recentSamples)[39m
+[31m+ ? endpointProfile.recentSamples[39m
+[31m+ : [];[39m
+[31m+ const recentSamplesBySource = asRecord(endpointProfile.recentSamplesBySource) ?? {};[39m
+[31m+ const recentLiveSamples = Array.isArray(recentSamplesBySource.liveRequest)[39m
+[31m+ ? recentSamplesBySource.liveRequest[39m
+[31m+ : [];[39m
+[31m+ const recentBenchmarkSamples = Array.isArray(recentSamplesBySource.benchmark)[39m
+[31m+ ? recentSamplesBySource.benchmark[39m
+[31m+ : [];[39m
+[31m+ const endpointIdentity =[39m
+[31m+ asRecord(latestProfile.endpoint_identity ?? latestProfile.endpointIdentity) ?? {};[39m
+[31m+ const usageEvent = asRecord(request.usageEvent) ?? {};[39m
+[31m+ const telemetrySnapshot = asRecord(request.telemetrySnapshot) ?? {};[39m
+[31m+ const executionTelemetry = asRecord(request.executionTelemetry) ?? {};[39m
+[31m+ const executionSemantics = asRecord(request.executionSemantics) ?? {};[39m
+[31m+ const executionStream = asRecord(executionTelemetry.stream) ?? {};[39m
+[31m+ const executionStreamSupport = asRecord(executionTelemetry.streamSupport) ?? {};[39m
+[31m+ const executionPromptCaching = asRecord(executionTelemetry.promptCaching) ?? {};[39m
+[31m+ const observedPerformance = asRecord(request.observedPerformance) ?? {};[39m
+[31m+ const observedSample = asRecord(observedPerformance.sample) ?? {};[39m
+[31m+ const cacheObservability = asRecord(request.cacheObservability) ?? {};[39m
+[31m+ const tooling = asRecord(request.tooling) ?? {};[39m
+[31m+ const routingDiagnostics = asRecord(request.routingDiagnostics) ?? {};[39m
+[31m+ const routingMode = asRecord(routingDiagnostics.routingMode) ?? {};[39m
+[31m+ const rewrite = asRecord(routingDiagnostics.rewrite) ?? {};[39m
+[31m+ const difficultyRouting = asRecord(routingDiagnostics.difficultyRouting) ?? {};[39m
+[31m+ const difficultySignals = asRecord(difficultyRouting.rubricSignals) ?? {};[39m
+[31m+ const controllerRouting = asRecord(routingDiagnostics.controllerRouting) ?? {};[39m
+[31m+ const acceptedDirectives = asRecord(controllerRouting.acceptedDirectives) ?? {};[39m
+[31m+ const hybridArbitration = asRecord(routingDiagnostics.hybridArbitration) ?? {};[39m
+[31m+ const inspection = asRecord(request.inspection) ?? {};[39m
+[31m+ const inspectionRequest = asRecord(inspection.request) ?? {};[39m
+[31m+ const inspectionEndpoint = asRecord(inspection.endpoint) ?? {};[39m
+[31m+ const capturePolicy =[39m
+[31m+ asRecord(request.capturePolicy) ?? asRecord(inspectionRequest.capturePolicy) ?? {};[39m
+[31m+ const privacyReceipt = asRecord(request.privacyReceipt) ?? {};[39m
+[31m+ const observationAvailability = asRecord(request.observationAvailability) ?? {};[39m
+[31m+ const requestCapture = asRecord(inspectionRequest.requestCapture) ?? {};[39m
+[31m+ const responseCapture = asRecord(inspectionRequest.responseCapture) ?? {};[39m
+[31m+ const toolCalls = Array.isArray(tooling.toolCalls) ? tooling.toolCalls : [];[39m
+[31m+ const toolExecutions = Array.isArray(tooling.executions) ? tooling.executions : [];[39m
+[31m+ const toolDiagnostics = Array.isArray(tooling.diagnostics) ? tooling.diagnostics : [];[39m
+[31m+ const captureRedactedFields = readStringList(capturePolicy.redactedFields);[39m
+[31m+ const captureSuppressedFields = readStringList(capturePolicy.suppressedFields);[39m
+[31m+ const sourceType =[39m
+[31m+ pickString(request, "sourceType") ??[39m
+[31m+ (pickString(endpointIdentity, "endpoint_kind", "endpointKind") === "remote_api"[39m
+[31m+ ? "remote"[39m
+[31m+ : pickString(endpointIdentity, "endpoint_kind", "endpointKind")[39m
+[31m+ ? "local"[39m
+[31m+ : null);[39m
+[31m+ const latencyMs = pickNumber(usageEvent, "latency_ms", "latencyMs");[39m
+[31m+ const inputTokenTruth = readTokenTruth(usageEvent, "input");[39m
+[31m+ const outputTokenTruth = readTokenTruth(usageEvent, "output");[39m
+[31m+ const inputTokens = inputTokenTruth.value;[39m
+[31m+ const outputTokens = outputTokenTruth.value;[39m
+[31m+ const totalTokens =[39m
+[31m+ inputTokenTruth.available && outputTokenTruth.available[39m
+[31m+ ? (pickNumber(usageEvent, "total_tokens", "totalTokens") ??[39m
+[31m+ (inputTokens ?? 0) + (outputTokens ?? 0))[39m
+[31m+ : null;[39m
+[31m+ const pickCostNumber = (...keys: string[]): number | null =>[39m
+[31m+ pickNumber(request, ...keys) ??[39m
+[31m+ pickNumber(telemetrySnapshot, ...keys) ??[39m
+[31m+ pickNumber(usageEvent, ...keys);[39m
+[31m+ const pickCostString = (...keys: string[]): string | null =>[39m
+[31m+ pickString(request, ...keys) ?? pickString(telemetrySnapshot, ...keys);[39m
+[31m+ const actualCostUsd = pickNumber(usageEvent, "cost_actual", "actualCostUsd");[39m
+[31m+ const estimatedCostUsd = pickNumber(usageEvent, "cost_estimate", "estimatedCostUsd");[39m
+[31m+ const effectiveCostUsd = pickCostNumber("effectiveCostUsd", "effective_cost_usd");[39m
+[31m+ const selectedUncachedCostUsd = pickCostNumber([39m
+[31m+ "selectedUncachedCostUsd",[39m
+[31m+ "selected_uncached_cost_usd",[39m
+[31m+ );[39m
+[31m+ const baselineMaxEligibleCostUsd = pickCostNumber([39m
+[31m+ "baselineMaxEligibleCostUsd",[39m
+[31m+ "baseline_max_eligible_cost_usd",[39m
+[31m+ );[39m
+[31m+ const routingCostSavingsUsd = pickCostNumber("routingCostSavingsUsd", "routing_cost_savings_usd");[39m
+[31m+ const cacheCostSavingsUsd = pickCostNumber("cacheCostSavingsUsd", "cache_cost_savings_usd");[39m
+[31m+ const totalAvoidedCostUsd = pickCostNumber("totalAvoidedCostUsd", "total_avoided_cost_usd");[39m
+[31m+ const costCalculationBasis = pickCostString("costCalculationBasis", "cost_calculation_basis");[39m
+[31m+ const costCalculationVersion = pickCostString([39m
+[31m+ "costCalculationVersion",[39m
+[31m+ "cost_calculation_version",[39m
+[31m+ );[39m
+[31m+ const costBaselineSource = pickCostString("costBaselineSource", "cost_baseline_source");[39m
+[31m+ const costSavingsSupport = pickCostString("costSavingsSupport", "cost_savings_support");[39m
+[31m+ const providerId =[39m
+[31m+ pickString(request, "providerId") ?? pickString(telemetrySnapshot, "providerId");[39m
+[31m+ const providerFamily = pickString(executionTelemetry, "providerFamily");[39m
+[31m+ const vendorId =[39m
+[31m+ pickString(executionTelemetry, "vendorId") ??[39m
+[31m+ pickString(asRecord(responseCapture.vendorMetadata) ?? {}, "vendorId");[39m
+[31m+ const executionFamily = pickString(executionSemantics, "executionFamily");[39m
+[31m+ const adapterFamily = pickString(executionSemantics, "adapterFamily");[39m
+[31m+ const finishReason = pickString(executionTelemetry, "finishReason");[39m
+[31m+ const promptCacheSupported =[39m
+[31m+ pickBoolean(request, "promptCacheSupported") ??[39m
+[31m+ pickBoolean(executionPromptCaching, "supported") ??[39m
+[31m+ false;[39m
+[31m+ const promptCacheRequested =[39m
+[31m+ pickBoolean(cacheObservability, "promptCacheRequested") ??[39m
+[31m+ pickBoolean(request, "promptCacheRequested");[39m
+[31m+ const promptCacheRequestSource = readPromptCacheRequestSource(cacheObservability);[39m
+[31m+ const promptCacheUsed =[39m
+[31m+ pickBoolean(cacheObservability, "promptCacheUsed") ?? pickBoolean(request, "promptCacheUsed");[39m
+[31m+ const cacheStatus = !promptCacheSupported[39m
+[31m+ ? "unavailable"[39m
+[31m+ : promptCacheUsed[39m
+[31m+ ? "hit"[39m
+[31m+ : promptCacheRequested[39m
+[31m+ ? "miss"[39m
+[31m+ : "ready";[39m
+[31m+ const responseStatus = asNumber(responseCapture.statusCode);[39m
+[31m+ const samplingRate = pickNumber(privacyReceipt, "samplingRate");[39m
+[31m+ const retentionTtlHours = pickNumber(privacyReceipt, "retentionTtlHours");[39m
+[31m+ const retainUntil = pickNumber(privacyReceipt, "retainUntil");[39m
+[31m+ const createdAtMs =[39m
+[31m+ pickNumber(request, "createdAtMs") ?? pickNumber(usageEvent, "timestamp_ms", "timestampMs");[39m
+[31m+ const measuredAtMs =[39m
+[31m+ pickNumber(latestProfile, "measured_at_ms", "measuredAtMs") ??[39m
+[31m+ pickNumber(observedSample, "timestamp_ms", "timestampMs");[39m
+[31m+ const endpointId = pickString(request, "endpointId") ?? "unknown";[39m
+[31m+ const modelId =[39m
+[31m+ pickString(usageEvent, "model_id", "modelId") ??[39m
+[31m+ pickString(endpointIdentity, "model_id", "modelId");[39m
+[31m+ const reasoningEffort =[39m
+[31m+ pickString(usageEvent, "reasoning_effort", "reasoningEffort") ??[39m
+[31m+ pickString(endpointIdentity, "reasoning_effort", "reasoningEffort");[39m
+[31m+ const modelDisplayName = formatModelIdentity({[39m
+[31m+ modelId: modelId ?? endpointId,[39m
+[31m+ endpointId,[39m
+[31m+ reasoningEffort,[39m
+[31m+ });[39m
+[31m+ const providerKind =[39m
+[31m+ pickString(usageEvent, "provider_kind", "providerKind") ??[39m
+[31m+ pickString(endpointIdentity, "provider_kind", "providerKind");[39m
+[31m+ const clientRequestId =[39m
+[31m+ pickString(request, "clientRequestId") ??[39m
+[31m+ pickString(inspectionRequest, "clientRequestId") ??[39m
+[31m+ null;[39m
+[31m+ const streamTextDeltaCount =[39m
+[31m+ pickNumber(request, "streamTextDeltaCount") ?? pickNumber(executionStream, "textDeltas") ?? 0;[39m
+[31m+ const streamToolCallDeltaCount =[39m
+[31m+ pickNumber(request, "streamToolCallDeltaCount") ??[39m
+[31m+ pickNumber(executionStream, "toolCallDeltas") ??[39m
+[31m+ 0;[39m
+[31m+ const streamToolArgumentDeltaCount =[39m
+[31m+ pickNumber(request, "streamToolArgumentDeltaCount") ??[39m
+[31m+ pickNumber(executionStream, "toolArgumentDeltas") ??[39m
+[31m+ 0;[39m
+[31m+ const streamTextSupported =[39m
+[31m+ pickBoolean(request, "streamTextSupported") ??[39m
+[31m+ pickString(executionStreamSupport, "text") !== "unsupported";[39m
+[31m+ const streamToolCallSupported =[39m
+[31m+ pickBoolean(request, "streamToolCallSupported") ??[39m
+[31m+ pickString(executionStreamSupport, "toolCalls") !== "unsupported";[39m
+[31m+ const streamToolArgumentSupported =[39m
+[31m+ pickBoolean(request, "streamToolArgumentSupported") ??[39m
+[31m+ pickString(executionStreamSupport, "toolArguments") !== "unsupported";[39m
+[31m+ const streamSummary = [[39m
+[31m+ streamTextSupported[39m
+[31m+ ? `${streamTextDeltaCount} text delta${streamTextDeltaCount === 1 ? "" : "s"}`[39m
+[31m+ : null,[39m
+[31m+ streamToolCallSupported[39m
+[31m+ ? `${streamToolCallDeltaCount} tool-call delta${streamToolCallDeltaCount === 1 ? "" : "s"}`[39m
+[31m+ : null,[39m
+[31m+ streamToolArgumentSupported[39m
+[31m+ ? `${streamToolArgumentDeltaCount} tool-arg delta${streamToolArgumentDeltaCount === 1 ? "" : "s"}`[39m
+[31m+ : null,[39m
+[31m+ ][39m
+[31m+ .filter((value): value is string => value !== null)[39m
+[31m+ .join(" / ");[39m
+[31m+ const profileSampleCount = recentSamples.length;[39m
+[31m+ const latestProfileErrorClass = pickString(latestProfile, "error_class", "errorClass");[39m
+[31m+ const latestProfileFailureRate = pickNumber(latestProfile, "failure_rate", "failureRate");[39m
+[31m+ const recentEndpointSamples = Array.isArray(inspectionEndpoint.recentSamples)[39m
+[31m+ ? inspectionEndpoint.recentSamples[39m
+[31m+ : recentSamples;[39m
+[31m+ const routingModeSummary = pickString(routingMode, "effectiveMode");[39m
+[31m+ const routingModeSource = pickString(routingMode, "source");[39m
+[31m+ const routingRequestedOverride = pickString(routingMode, "requestedOverride");[39m
+[31m+ const routingAliasMode = pickString(routingMode, "aliasMode");[39m
+[31m+ const rewriteSummary =[39m
+[31m+ pickString(rewrite, "requestedModel") && pickString(rewrite, "downstreamModelId")[39m
+[31m+ ? `${pickString(rewrite, "requestedModel")} -> ${pickString(rewrite, "downstreamModelId")}`[39m
+[31m+ : null;[39m
+[31m+ const rewriteReason = pickString(rewrite, "reason");[39m
+[31m+ const difficultyBucket = pickString(difficultyRouting, "difficulty");[39m
+[31m+ const difficultyStrategy = pickString(difficultyRouting, "strategy");[39m
+[31m+ const controllerActive = pickBoolean(controllerRouting, "active");[39m
+[31m+ const controllerStrategy = pickString(acceptedDirectives, "strategy");[39m
+[31m+ const controllerTaskType = pickString(acceptedDirectives, "taskType");[39m
+[31m+ const hybridSignal = pickString(hybridArbitration, "dominantSignal");[39m
+[31m+ const hybridStrategy = pickString(hybridArbitration, "finalStrategy");[39m
+[31m+ const rubricSignalSummary = [[39m
+[31m+ pickNumber(difficultySignals, "contextTokens"),[39m
+[31m+ pickNumber(difficultySignals, "toolCount"),[39m
+[31m+ pickNumber(difficultySignals, "historyTurnCount"),[39m
+[31m+ pickNumber(difficultySignals, "instructionConstraintCount"),[39m
+[31m+ pickNumber(difficultySignals, "decompositionKeywordCount"),[39m
+[31m+ ].some((value) => value !== null)[39m
+[31m+ ? [[39m
+[31m+ `context ${pickNumber(difficultySignals, "contextTokens") ?? 0}`,[39m
+[31m+ `tools ${pickNumber(difficultySignals, "toolCount") ?? 0}`,[39m
+[31m+ `history ${pickNumber(difficultySignals, "historyTurnCount") ?? 0}`,[39m
+[31m+ `constraints ${pickNumber(difficultySignals, "instructionConstraintCount") ?? 0}`,[39m
+[31m+ `decomposition ${pickNumber(difficultySignals, "decompositionKeywordCount") ?? 0}`,[39m
+[31m+ ].join(" • ")[39m
+[31m+ : null;[39m
+[31m+ const taxonomyDimensions =[39m
+[31m+ asRecord(request.taxonomyDimensions) ??[39m
+[31m+ asRecord(telemetrySnapshot.taxonomyDimensions) ??[39m
+[31m+ asRecord(request.taxonomy_dimensions) ??[39m
+[31m+ null;[39m
+[31m+ const normalizedIntent =[39m
+[31m+ asRecord(request.normalizedIntent) ?? asRecord(request.normalized_intent) ?? {};[39m
+[31m+ const originalRoleHint =[39m
+[31m+ pickString(taxonomyDimensions ?? {}, "taxonomy_original_role_hint_id") ??[39m
+[31m+ pickString(normalizedIntent, "originalRoleHintId");[39m
+[31m+ const originalTaskType =[39m
+[31m+ pickString(taxonomyDimensions ?? {}, "taxonomy_original_task_type") ??[39m
+[31m+ pickString(normalizedIntent, "originalTaskType");[39m
+[31m+ const taxonomyGroupId =[39m
+[31m+ pickString(taxonomyDimensions ?? {}, "taxonomy_group_id") ??[39m
+[31m+ pickString(request, "taxonomyGroupId") ??[39m
+[31m+ pickString(normalizedIntent, "groupId");[39m
+[31m+ const taxonomyRoleId =[39m
+[31m+ pickString(taxonomyDimensions ?? {}, "taxonomy_role_id") ??[39m
+[31m+ pickString(request, "taxonomyRoleId") ??[39m
+[31m+ pickString(normalizedIntent, "roleId");[39m
+[31m+ const taxonomyTaskType =[39m
+[31m+ pickString(taxonomyDimensions ?? {}, "taxonomy_task_type") ??[39m
+[31m+ pickString(request, "taxonomyTaskType") ??[39m
+[31m+ pickString(normalizedIntent, "taskType");[39m
+[31m+ const taxonomyTaskVariant =[39m
+[31m+ pickString(taxonomyDimensions ?? {}, "taxonomy_task_variant") ??[39m
+[31m+ pickString(request, "taxonomyTaskVariant") ??[39m
+[31m+ pickString(normalizedIntent, "taskVariant");[39m
+[31m+ const taxonomyCapabilityIds = readTaxonomyStringList([39m
+[31m+ taxonomyDimensions?.taxonomy_capability_ids,[39m
+[31m+ request.taxonomyCapabilityIds,[39m
+[31m+ );[39m
+[31m+ const taxonomyModalityIds = readTaxonomyStringList([39m
+[31m+ taxonomyDimensions?.taxonomy_modality_ids,[39m
+[31m+ request.taxonomyModalityIds,[39m
+[31m+ );[39m
+[31m+ const taxonomyToolClassIds = readTaxonomyStringList([39m
+[31m+ taxonomyDimensions?.taxonomy_tool_class_ids,[39m
+[31m+ request.taxonomyToolClassIds,[39m
+[31m+ );[39m
+[31m+ const taxonomyRoleSource = pickString(taxonomyDimensions ?? {}, "taxonomy_role_source");[39m
+[31m+ const taxonomyTaskSource = pickString(taxonomyDimensions ?? {}, "taxonomy_task_source");[39m
+[31m+ const taxonomyClassificationSource = pickString([39m
+[31m+ taxonomyDimensions ?? {},[39m
+[31m+ "taxonomy_classification_source",[39m
+[31m+ );[39m
+[31m+ const taxonomyConfidence = pickNumber(taxonomyDimensions ?? {}, "taxonomy_confidence");[39m
+[31m+ const taxonomyTaskConfidence = pickNumber(taxonomyDimensions ?? {}, "taxonomy_task_confidence");[39m
+[31m+ const taxonomyAlternativeRoleIds = readStringList([39m
+[31m+ taxonomyDimensions?.taxonomy_alternative_role_ids,[39m
+[31m+ );[39m
+[31m+ const taxonomyAlternativeTaskTypes = readStringList([39m
+[31m+ taxonomyDimensions?.taxonomy_alternative_task_types,[39m
+[31m+ );[39m
+[31m+ const taxonomyVersion = pickString(taxonomyDimensions ?? {}, "taxonomy_version");[39m
+[31m+ const taxonomyContentRevision = pickString(taxonomyDimensions ?? {}, "taxonomy_content_revision");[39m
+[31m+ const classificationContractVersion = pickString([39m
+[31m+ taxonomyDimensions ?? {},[39m
+[31m+ "classification_contract_version",[39m
+[31m+ );[39m
+[31m+ const observationSource = pickString(observationAvailability, "source");[39m
+[31m+ const observationReason = pickString(observationAvailability, "reason");[39m
+[31m+ const rawObservationAvailable =[39m
+[31m+ pickBoolean(observationAvailability, "rawObservationAvailable") ??[39m
+[31m+ Object.keys(inspectionRequest).length > 0;[39m
+[31m+ const structuredInspectionAvailable =[39m
+[31m+ pickBoolean(observationAvailability, "structuredInspectionAvailable") ??[39m
+[31m+ pickBoolean(capturePolicy, "structuredInspectionAvailable");[39m
+[31m+ const rawCaptureAvailable = pickBoolean(capturePolicy, "rawCaptureAvailable");[39m
+[31m+ const captureEnvironment = pickString(capturePolicy, "environment");[39m
+[31m+ const captureRedactionLevel = pickString(capturePolicy, "redactionLevel");[39m
+[31m+ const captureRetentionClass = pickString(capturePolicy, "retentionClass");[39m
+[31m+ const captureStructuredInspectionMode = pickString(capturePolicy, "structuredInspectionMode");[39m
+[31m+ const hasRequestCapture = Object.keys(requestCapture).length > 0;[39m
+[31m+ const hasResponseCapture = Object.keys(responseCapture).length > 0;[39m
+[31m+ const taxonomyPresent =[39m
+[31m+ [[39m
+[31m+ originalRoleHint,[39m
+[31m+ originalTaskType,[39m
+[31m+ taxonomyGroupId,[39m
+[31m+ taxonomyRoleId,[39m
+[31m+ taxonomyTaskType,[39m
+[31m+ taxonomyTaskVariant,[39m
+[31m+ taxonomyRoleSource,[39m
+[31m+ taxonomyTaskSource,[39m
+[31m+ taxonomyClassificationSource,[39m
+[31m+ taxonomyVersion,[39m
+[31m+ taxonomyContentRevision,[39m
+[31m+ classificationContractVersion,[39m
+[31m+ ].some((value) => value !== null) ||[39m
+[31m+ taxonomyCapabilityIds.length > 0 ||[39m
+[31m+ taxonomyModalityIds.length > 0 ||[39m
+[31m+ taxonomyToolClassIds.length > 0 ||[39m
+[31m+ taxonomyAlternativeRoleIds.length > 0 ||[39m
+[31m+ taxonomyAlternativeTaskTypes.length > 0;[39m
+[31m+[39m
+[31m+ return ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+ Back to request ledger[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
Endpoint
[39m
+[31m+
[39m
+[31m+ {formatEndpointDisplayPath({ endpointId, reasoningEffort })}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ Endpoint id currently associated with the captured request.[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Correlation
[39m
+[31m+
[39m
+[31m+ {renderMetricValue(clientRequestId)}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ Caller-supplied correlation id preserved alongside the canonical request ledger id.[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {[[39m
+[31m+ {[39m
+[31m+ label: "Source",[39m
+[31m+ value: renderMetricValue(sourceType),[39m
+[31m+ detail: "Canonical source family used by the telemetry ledger.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Provider",[39m
+[31m+ value: renderMetricValue(providerId),[39m
+[31m+ detail: "Actual provider identity for the selected endpoint.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Provider family",[39m
+[31m+ value: renderMetricValue(providerFamily),[39m
+[31m+ detail: "Provider semantic family preserved in the canonical telemetry contract.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Vendor",[39m
+[31m+ value: renderMetricValue(vendorId),[39m
+[31m+ detail: "Optional intermediary execution vendor such as LiteLLM.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Execution path",[39m
+[31m+ value: renderMetricValue(executionFamily),[39m
+[31m+ detail: "High-level routed execution family selected for this request.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Adapter",[39m
+[31m+ value: renderMetricValue(adapterFamily),[39m
+[31m+ detail:[39m
+[31m+ "Concrete adapter implementation used to shape and execute the provider request.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Latency",[39m
+[31m+ value: latencyMs === null ? "n/a" : `${latencyMs} ms`,[39m
+[31m+ detail: "Observed request latency from the persisted usage event.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Tokens",[39m
+[31m+ value: renderMetricValue(totalTokens),[39m
+[31m+ detail:[39m
+[31m+ inputTokenTruth.available && outputTokenTruth.available[39m
+[31m+ ? `Input ${inputTokenTruth.source}; output ${outputTokenTruth.source}.`[39m
+[31m+ : "Token usage is unavailable; numeric placeholders are not treated as measured usage.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Cost",[39m
+[31m+ value: formatUsd(effectiveCostUsd),[39m
+[31m+ detail:[39m
+[31m+ costCalculationBasis || costCalculationVersion[39m
+[31m+ ? `Stored effective cost • ${costCalculationBasis ?? "unknown basis"} • ${[39m
+[31m+ costCalculationVersion ?? "unknown version"[39m
+[31m+ }`[39m
+[31m+ : "Stored authoritative per-request effective cost.",[39m
+[31m+ },[39m
+[31m+ {[39m
+[31m+ label: "Cache",[39m
+[31m+ value: renderMetricValue(cacheStatus),[39m
+[31m+ detail: promptCacheRequestSource[39m
+[31m+ ? `Captured cache posture; request key source: ${promptCacheRequestSource}.`[39m
+[31m+ : "Captured cache posture using explicit support semantics rather than zero-only inference.",[39m
+[31m+ },[39m
+[31m+ ].map((item) => ([39m
+[31m+
[39m
+[31m+
{item.label}
[39m
+[31m+
[39m
+[31m+ {item.value}[39m
+[31m+
[39m
+[31m+
{item.detail}
[39m
+[31m+
[39m
+[31m+ ))}[39m
+[31m+
[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ {taxonomyPresent ? ([39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Original request hints
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+
Original role hint [39m
+[31m+ [39m
+[31m+ {renderMetricValue(originalRoleHint)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+
Original task type [39m
+[31m+ [39m
+[31m+ {renderMetricValue(originalTaskType)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Normalized classification
[39m
+[31m+
[39m
+[31m+ {[[39m
+[31m+ ["Taxonomy group", taxonomyGroupId],[39m
+[31m+ ["Taxonomy role", taxonomyRoleId],[39m
+[31m+ ["Taxonomy task", taxonomyTaskType],[39m
+[31m+ ["Task variant", taxonomyTaskVariant],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ [39m
+[31m+ {renderMetricValue(value)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Derived analytics tags
[39m
+[31m+
[39m
+[31m+ {[[39m
+[31m+ [[39m
+[31m+ "Derived capabilities",[39m
+[31m+ taxonomyCapabilityIds.length > 0 ? taxonomyCapabilityIds.join(", ") : null,[39m
+[31m+ ],[39m
+[31m+ [[39m
+[31m+ "Derived modalities",[39m
+[31m+ taxonomyModalityIds.length > 0 ? taxonomyModalityIds.join(", ") : null,[39m
+[31m+ ],[39m
+[31m+ [[39m
+[31m+ "Derived tool classes",[39m
+[31m+ taxonomyToolClassIds.length > 0 ? taxonomyToolClassIds.join(", ") : null,[39m
+[31m+ ],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ [39m
+[31m+ {renderMetricValue(value)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {[[39m
+[31m+ ["Classification source", taxonomyClassificationSource],[39m
+[31m+ ["Role source", taxonomyRoleSource],[39m
+[31m+ ["Task source", taxonomyTaskSource],[39m
+[31m+ ["Confidence", taxonomyConfidence === null ? null : String(taxonomyConfidence)],[39m
+[31m+ [[39m
+[31m+ "Task confidence",[39m
+[31m+ taxonomyTaskConfidence === null ? null : String(taxonomyTaskConfidence),[39m
+[31m+ ],[39m
+[31m+ [[39m
+[31m+ "Alternative roles",[39m
+[31m+ taxonomyAlternativeRoleIds.length > 0[39m
+[31m+ ? taxonomyAlternativeRoleIds.join(", ")[39m
+[31m+ : null,[39m
+[31m+ ],[39m
+[31m+ [[39m
+[31m+ "Alternative tasks",[39m
+[31m+ taxonomyAlternativeTaskTypes.length > 0[39m
+[31m+ ? taxonomyAlternativeTaskTypes.join(", ")[39m
+[31m+ : null,[39m
+[31m+ ],[39m
+[31m+ ["Taxonomy version", taxonomyVersion],[39m
+[31m+ ["Content revision", taxonomyContentRevision],[39m
+[31m+ ["Classification contract", classificationContractVersion],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ {renderMetricValue(value)} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+ [39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {[[39m
+[31m+ ["Effective cost", formatUsd(effectiveCostUsd)],[39m
+[31m+ ["Selected uncached cost", formatUsd(selectedUncachedCostUsd)],[39m
+[31m+ ["Baseline max eligible", formatUsd(baselineMaxEligibleCostUsd)],[39m
+[31m+ ["Routing savings", formatUsd(routingCostSavingsUsd)],[39m
+[31m+ ["Cache savings", formatUsd(cacheCostSavingsUsd)],[39m
+[31m+ ["Total avoided cost", formatUsd(totalAvoidedCostUsd)],[39m
+[31m+ ["Calculation basis", costCalculationBasis],[39m
+[31m+ ["Calculation version", costCalculationVersion],[39m
+[31m+ ["Baseline source", costBaselineSource],[39m
+[31m+ ["Savings support", costSavingsSupport],[39m
+[31m+ [[39m
+[31m+ "Raw actual cost",[39m
+[31m+ actualCostUsd === null ? null : `${formatUsd(actualCostUsd)} provenance`,[39m
+[31m+ ],[39m
+[31m+ [[39m
+[31m+ "Raw estimated cost",[39m
+[31m+ estimatedCostUsd === null ? null : `${formatUsd(estimatedCostUsd)} provenance`,[39m
+[31m+ ],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ {renderMetricValue(value)} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {rawObservationAvailable ? "Raw observation retained" : "Ledger fallback only"}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {structuredInspectionAvailable[39m
+[31m+ ? "Structured inspection available"[39m
+[31m+ : "No structured inspection"}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ {rawCaptureAvailable ? "Raw capture allowed" : "Raw capture unavailable"}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {[[39m
+[31m+ ["Observation source", observationSource],[39m
+[31m+ ["Capture environment", captureEnvironment],[39m
+[31m+ ["Sampling rate", formatPercent(samplingRate)],[39m
+[31m+ [[39m
+[31m+ "Retention TTL",[39m
+[31m+ retentionTtlHours === null[39m
+[31m+ ? null[39m
+[31m+ : `${retentionTtlHours} hour${retentionTtlHours === 1 ? "" : "s"}`,[39m
+[31m+ ],[39m
+[31m+ ["Retain until", formatDateTime(retainUntil)],[39m
+[31m+ ["Redaction level", captureRedactionLevel],[39m
+[31m+ ["Retention class", captureRetentionClass],[39m
+[31m+ ["Inspection mode", captureStructuredInspectionMode],[39m
+[31m+ [[39m
+[31m+ "Redacted fields",[39m
+[31m+ captureRedactedFields.length > 0 ? captureRedactedFields.join(", ") : null,[39m
+[31m+ ],[39m
+[31m+ [[39m
+[31m+ "Suppressed fields",[39m
+[31m+ captureSuppressedFields.length > 0 ? captureSuppressedFields.join(", ") : null,[39m
+[31m+ ],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ {renderMetricValue(value)} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ {observationReason ??[39m
+[31m+ "This request detail view combines canonical telemetry ledger facts with any preserved runtime observation bundle still inside retention."}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {[[39m
+[31m+ ["Provider", providerKind],[39m
+[31m+ ["Model", modelDisplayName],[39m
+[31m+ ["Finish reason", finishReason],[39m
+[31m+ ["Input tokens", inputTokenTruth.text],[39m
+[31m+ ["Output tokens", outputTokenTruth.text],[39m
+[31m+ ["Cache request source", promptCacheRequestSource],[39m
+[31m+ ["Response status", responseStatus === null ? null : String(responseStatus)],[39m
+[31m+ ["Recorded", formatDateTime(createdAtMs)],[39m
+[31m+ ["Profile measured", formatDateTime(measuredAtMs)],[39m
+[31m+ ["Stream deltas", streamSummary.length > 0 ? streamSummary : null],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ {renderMetricValue(value)} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {[[39m
+[31m+ ["Live profile samples", String(profileSampleCount)],[39m
+[31m+ ["Recent live-request rows", String(recentLiveSamples.length)],[39m
+[31m+ ["Recent benchmark rows", String(recentBenchmarkSamples.length)],[39m
+[31m+ [[39m
+[31m+ "Live profile failure rate",[39m
+[31m+ latestProfileFailureRate === null ? null : String(latestProfileFailureRate),[39m
+[31m+ ],[39m
+[31m+ ["Latest live error class", latestProfileErrorClass],[39m
+[31m+ [[39m
+[31m+ "Recent sample bundle",[39m
+[31m+ recentEndpointSamples.length > 0[39m
+[31m+ ? `${recentEndpointSamples.length} samples available`[39m
+[31m+ : "No recent samples",[39m
+[31m+ ],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ {renderMetricValue(value)} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+
Current operational profile
[39m
+[31m+
{JSON.stringify(latestProfile, null, 2)} [39m
+[31m+
[39m
+[31m+ [39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {[[39m
+[31m+ [[39m
+[31m+ "Effective mode",[39m
+[31m+ routingModeSummary[39m
+[31m+ ? formatRoutingModeLabel(routingModeSummary)[39m
+[31m+ : routingModeSummary,[39m
+[31m+ ],[39m
+[31m+ ["Mode source", routingModeSource],[39m
+[31m+ ["Requested override", routingRequestedOverride],[39m
+[31m+ [[39m
+[31m+ "Alias mode",[39m
+[31m+ routingAliasMode ? formatRoutingModeLabel(routingAliasMode) : routingAliasMode,[39m
+[31m+ ],[39m
+[31m+ ["Rewrite", rewriteSummary],[39m
+[31m+ ["Rewrite reason", rewriteReason],[39m
+[31m+ ["Difficulty bucket", difficultyBucket],[39m
+[31m+ ["Difficulty strategy", difficultyStrategy],[39m
+[31m+ ["Controller active", controllerActive === null ? null : String(controllerActive)],[39m
+[31m+ ["Controller strategy", controllerStrategy],[39m
+[31m+ ["Controller task type", controllerTaskType],[39m
+[31m+ ["Hybrid dominant signal", hybridSignal],[39m
+[31m+ ["Hybrid final strategy", hybridStrategy],[39m
+[31m+ ["Rubric signals", rubricSignalSummary],[39m
+[31m+ ].map(([label, value]) => ([39m
+[31m+ [39m
+[31m+
{label} [39m
+[31m+ {renderMetricValue(value)} [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {JSON.stringify({ routingDiagnostics, hybridArbitration }, null, 2)}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Tool calls
[39m
+[31m+
0 ? "accent" : "neutral"}>{toolCalls.length} [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {toolCalls.length === 0 ? ([39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+ toolCalls.map((toolCall, index) => ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {String(asRecord(toolCall)?.toolName ?? "unknown")}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {JSON.stringify(asRecord(toolCall)?.arguments ?? {}, null, 2)}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ ))[39m
+[31m+ )}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Execution receipts
[39m
+[31m+
0 ? "success" : "neutral"}>[39m
+[31m+ {toolExecutions.length}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {toolExecutions.length === 0 ? ([39m
+[31m+
[39m
+[31m+ ) : ([39m
+[31m+ toolExecutions.map((execution, index) => {[39m
+[31m+ const executionRecord = asRecord(execution) ?? {};[39m
+[31m+ return ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {String(executionRecord.toolName ?? "Unnamed tool")}[39m
+[31m+
[39m
+[31m+ {executionRecord.status ? ([39m
+[31m+
[39m
+[31m+ {String(executionRecord.status)}[39m
+[31m+ [39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {String(executionRecord.connectorId ?? "Unknown connector")}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ );[39m
+[31m+ })[39m
+[31m+ )}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+[39m
+[31m+ {toolDiagnostics.length > 0 ? ([39m
+[31m+
{JSON.stringify(toolDiagnostics, null, 2)} [39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ {!rawObservationAvailable ? ([39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Request capture
[39m
+[31m+ {hasRequestCapture ? ([39m
+[31m+
{JSON.stringify(requestCapture, null, 2)} [39m
+[31m+ ) : ([39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Response capture
[39m
+[31m+ {hasResponseCapture ? ([39m
+[31m+
{JSON.stringify(responseCapture, null, 2)} [39m
+[31m+ ) : ([39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
Endpoint evidence history
[39m
+[31m+
[39m
+[31m+ {JSON.stringify([39m
+[31m+ {[39m
+[31m+ operationalProfile: latestProfile,[39m
+[31m+ recentSamples,[39m
+[31m+ recentSamplesBySource: {[39m
+[31m+ liveRequest: recentLiveSamples,[39m
+[31m+ benchmark: recentBenchmarkSamples,[39m
+[31m+ },[39m
+[31m+ },[39m
+[31m+ null,[39m
+[31m+ 2,[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+[39m
+[31m+
[39m
+[31m+ {JSON.stringify(detail.request, null, 2)} [39m
+[31m+ [39m
+[31m+
[39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+
+[36m [2m❯[22m app/routes/request-detail.test.tsx:[2m64:31[22m[39m
+ [90m 62| [39m
+ [90m 63| [39mtest("shows effective reasoning effort on the request detail (R11)", (…
+ [90m 64| [39m expect(requestDetailSource).toContain("formatEffectiveEffortDisclosu…
+ [90m | [39m [31m^[39m
+ [90m 65| [39m [34mexpect[39m(requestDetailSource)[33m.[39m[34mtoContain[39m([32m"effort_source"[39m)[33m;[39m
+ [90m 66| [39m})[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/6]⎯[22m[39m
+
+[41m[1m FAIL [22m[49m app/routes/requests.test.tsx[2m > [22mrun 106 R11 request surface truthfulness[2m > [22mshows the endpoint's effective reasoning effort, not just its label
+[31m[1mAssertionError[22m: expected 'import { ChartGrid, ChartGridCell, Fi…' to contain 'formatEffectiveEffortDisclosure'[39m
+
+[32m- Expected[39m
+[31m+ Received[39m
+
+[32m- formatEffectiveEffortDisclosure[39m
+[31m+ import { ChartGrid, ChartGridCell, FilterSelect, MetricStrip, PageFilters } from "@role-model/ui";[39m
+[31m+ import { useEffect, useMemo, useRef, useState } from "react";[39m
+[31m+ import { Link, useSearchParams } from "react-router";[39m
+[31m+[39m
+[31m+ import { ObserveKitChartBlock } from "../components/observe-chart-block";[39m
+[31m+ import {[39m
+[31m+ Badge,[39m
+[31m+ DisclosureSection,[39m
+[31m+ EmptyState,[39m
+[31m+ ErrorState,[39m
+[31m+ SectionCard,[39m
+[31m+ } from "../components/page-primitives";[39m
+[31m+ import { TelemetryTextField } from "../components/telemetry-controls";[39m
+[31m+ import {[39m
+[31m+ accentActionTextClassName,[39m
+[31m+ bodyStrongTextClassName,[39m
+[31m+ cardClassName,[39m
+[31m+ foregroundEmphasisClassName,[39m
+[31m+ mutedPanelClassName,[39m
+[31m+ supportingTextClassName,[39m
+[31m+ } from "../lib/design-system";[39m
+[31m+ import { formatEndpointDisplayPath, formatReasoningEffortLabel } from "../lib/effort-identity";[39m
+[31m+ import { startDeferredLiveRefresh } from "../lib/live-refresh";[39m
+[31m+ import { adaptObserveChartBlock } from "../lib/observe-chart-adapter";[39m
+[31m+ import type {[39m
+[31m+ RuntimeTelemetryAnalyticsDimension,[39m
+[31m+ RuntimeTelemetryAnalyticsFilters,[39m
+[31m+ RuntimeTelemetryAnalyticsMetric,[39m
+[31m+ RuntimeTelemetryAnalyticsResponse,[39m
+[31m+ RuntimeTelemetryRequestPage,[39m
+[31m+ RuntimeTelemetryRequestRecord,[39m
+[31m+ } from "../lib/runtime-api";[39m
+[31m+ import {[39m
+[31m+ fetchTelemetryAnalytics,[39m
+[31m+ fetchTelemetryRequestsPage,[39m
+[31m+ subscribeRuntimeRefreshStream,[39m
+[31m+ } from "../lib/runtime-api";[39m
+[31m+ import {[39m
+[31m+ buildQuerySnapshot,[39m
+[31m+ createStaleChartDiagnostic,[39m
+[31m+ flushStaleRefreshDiagnostics,[39m
+[31m+ resolveTelemetryChartRefresh,[39m
+[31m+ } from "../lib/stale-refresh-diagnostics";[39m
+[31m+ import {[39m
+[31m+ telemetryBreakdownOptions,[39m
+[31m+ telemetryMetricOptions,[39m
+[31m+ telemetryTimeRangeOptions,[39m
+[31m+ } from "../lib/telemetry-chart-config";[39m
+[31m+ import {[39m
+[31m+ fromPageTimeRange,[39m
+[31m+ observePageTimeRangeOptions,[39m
+[31m+ toPageTimeRange,[39m
+[31m+ } from "../lib/telemetry-page-filters";[39m
+[31m+ import type {[39m
+[31m+ TelemetryRouteChartDefinition,[39m
+[31m+ TelemetryTimeRangeValue,[39m
+[31m+ } from "../lib/telemetry-route-models";[39m
+[31m+ import { buildObserveRequestsChartDefinitions } from "../lib/telemetry-route-models";[39m
+[31m+ import { buildTelemetryRequestRows } from "../lib/view-models";[39m
+[31m+[39m
+[31m+ const requestBreakdownOptions = [[39m
+[31m+ { label: "Total", value: "" },[39m
+[31m+ ...telemetryBreakdownOptions[39m
+[31m+ .filter((option) =>[39m
+[31m+ [[39m
+[31m+ "sourceType",[39m
+[31m+ "endpointId",[39m
+[31m+ "modelId",[39m
+[31m+ "reasoningEffort",[39m
+[31m+ "effortSource",[39m
+[31m+ "providerId",[39m
+[31m+ "taxonomyGroupId",[39m
+[31m+ "taxonomyRoleId",[39m
+[31m+ "taxonomyTaskType",[39m
+[31m+ "taxonomyTaskVariant",[39m
+[31m+ "taxonomyCapabilityId",[39m
+[31m+ "taxonomyModalityId",[39m
+[31m+ "taxonomyToolClassId",[39m
+[31m+ ].includes(option.value),[39m
+[31m+ )[39m
+[31m+ .map((option) => ({ label: option.label, value: option.value })),[39m
+[31m+ ];[39m
+[31m+[39m
+[31m+ const rankingDimensionOptions = [[39m
+[31m+ { label: "Endpoint variants", value: "endpointId" },[39m
+[31m+ { label: "Upstream models", value: "modelId" },[39m
+[31m+ { label: "Reasoning efforts", value: "reasoningEffort" },[39m
+[31m+ { label: "Effort sources", value: "effortSource" },[39m
+[31m+ { label: "Providers", value: "providerId" },[39m
+[31m+ { label: "Taxonomy groups", value: "taxonomyGroupId" },[39m
+[31m+ { label: "Taxonomy roles", value: "taxonomyRoleId" },[39m
+[31m+ { label: "Taxonomy tasks", value: "taxonomyTaskType" },[39m
+[31m+ { label: "Task variants", value: "taxonomyTaskVariant" },[39m
+[31m+ { label: "Capabilities", value: "taxonomyCapabilityId" },[39m
+[31m+ { label: "Modalities", value: "taxonomyModalityId" },[39m
+[31m+ { label: "Tool classes", value: "taxonomyToolClassId" },[39m
+[31m+ ];[39m
+[31m+[39m
+[31m+ const rankingMetricOptions = telemetryMetricOptions.filter((option) =>[39m
+[31m+ [[39m
+[31m+ "requestCount",[39m
+[31m+ "totalTokens",[39m
+[31m+ "effectiveCostUsd",[39m
+[31m+ "averageLatencyMs",[39m
+[31m+ "p95LatencyMs",[39m
+[31m+ "failureCount",[39m
+[31m+ "cacheHitTokens",[39m
+[31m+ "cacheHitTokenRate",[39m
+[31m+ ].includes(option.value),[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ function getWindowMs(timeRange: TelemetryTimeRangeValue): number {[39m
+[31m+ return telemetryTimeRangeOptions.find((option) => option.value === timeRange)?.windowMs ?? 0;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function normalizeOptionalId(value: string): string | undefined {[39m
+[31m+ const trimmed = value.trim();[39m
+[31m+ return trimmed.length > 0 ? trimmed : undefined;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function normalizeOptionalCsvIds(value: string): readonly string[] | undefined {[39m
+[31m+ const normalized = value[39m
+[31m+ .split(",")[39m
+[31m+ .map((entry) => entry.trim())[39m
+[31m+ .filter((entry) => entry.length > 0);[39m
+[31m+ return normalized.length > 0 ? normalized : undefined;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function matchesOptionalIdFilter([39m
+[31m+ filters: readonly string[] | undefined,[39m
+[31m+ value: string | null | undefined,[39m
+[31m+ ): boolean {[39m
+[31m+ if (!filters || filters.length === 0) {[39m
+[31m+ return true;[39m
+[31m+ }[39m
+[31m+ return value ? filters.includes(value) : false;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function matchesOptionalListFilter([39m
+[31m+ filters: readonly string[] | undefined,[39m
+[31m+ values: readonly string[] | undefined,[39m
+[31m+ ): boolean {[39m
+[31m+ if (!filters || filters.length === 0) {[39m
+[31m+ return true;[39m
+[31m+ }[39m
+[31m+ if (!values || values.length === 0) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ return filters.some((filterValue) => values.includes(filterValue));[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ function matchesRequestFilters([39m
+[31m+ request: RuntimeTelemetryRequestRecord,[39m
+[31m+ filters: RuntimeTelemetryAnalyticsFilters,[39m
+[31m+ ): boolean {[39m
+[31m+ if (!matchesOptionalIdFilter(filters.sourceTypes, request.sourceType)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.endpointIds, request.endpointId)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.modelIds, request.modelId)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.reasoningEfforts, request.reasoningEffort)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.effortSources, request.effortSource)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.providerIds, request.providerId)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.taxonomyGroupIds, request.taxonomyGroupId)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.taxonomyRoleIds, request.taxonomyRoleId)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.taxonomyTaskTypes, request.taxonomyTaskType)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalIdFilter(filters.taxonomyTaskVariants, request.taxonomyTaskVariant)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalListFilter(filters.taxonomyCapabilityIds, request.taxonomyCapabilityIds)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalListFilter(filters.taxonomyModalityIds, request.taxonomyModalityIds)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (!matchesOptionalListFilter(filters.taxonomyToolClassIds, request.taxonomyToolClassIds)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ if (filters.statusFamilies) {[39m
+[31m+ const family =[39m
+[31m+ typeof request.statusCode === "number"[39m
+[31m+ ? request.statusCode >= 400[39m
+[31m+ ? "failure"[39m
+[31m+ : "success"[39m
+[31m+ : "unknown";[39m
+[31m+ if (!filters.statusFamilies.includes(family)) {[39m
+[31m+ return false;[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ return true;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ type RequestsChartRecord = {[39m
+[31m+ readonly definition: TelemetryRouteChartDefinition;[39m
+[31m+ readonly response?: RuntimeTelemetryAnalyticsResponse;[39m
+[31m+ readonly errorMessage?: string;[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ function getChartLoadErrorMessage(title: string, value: unknown): string {[39m
+[31m+ const detail = value instanceof Error ? value.message : "Could not load telemetry analytics.";[39m
+[31m+ return `${title}: ${detail}`;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ export default function RequestsRoute() {[39m
+[31m+ const [searchParams, setSearchParams] = useSearchParams();[39m
+[31m+[39m
+[31m+ const timeRange = (searchParams.get("range") as TelemetryTimeRangeValue) || "week";[39m
+[31m+ const breakdownValue =[39m
+[31m+ (searchParams.get("breakdown") as "" | RuntimeTelemetryAnalyticsDimension) || "";[39m
+[31m+ const rankingMetric =[39m
+[31m+ (searchParams.get("metric") as RuntimeTelemetryAnalyticsMetric) || "averageLatencyMs";[39m
+[31m+ const rankingDimension =[39m
+[31m+ (searchParams.get("rankBy") as RuntimeTelemetryAnalyticsDimension) || "endpointId";[39m
+[31m+ const sourceFilter = (searchParams.get("source") as "all" | "local" | "remote") || "all";[39m
+[31m+ const statusFamily =[39m
+[31m+ (searchParams.get("status") as "all" | "success" | "failure" | "unknown") || "all";[39m
+[31m+ const endpointId = searchParams.get("endpointId") || "";[39m
+[31m+ const modelId = searchParams.get("modelId") || "";[39m
+[31m+ const reasoningEffort = searchParams.get("effort") || "";[39m
+[31m+ const effortSource = searchParams.get("effortSource") || "";[39m
+[31m+ const providerId = searchParams.get("providerId") || "";[39m
+[31m+ const taxonomyGroupId = searchParams.get("taxGroup") || "";[39m
+[31m+ const taxonomyRoleId = searchParams.get("taxRole") || "";[39m
+[31m+ const taxonomyTaskType = searchParams.get("taxTask") || "";[39m
+[31m+ const taxonomyTaskVariant = searchParams.get("taxVariant") || "";[39m
+[31m+ const taxonomyCapabilityIds = searchParams.get("taxCapability") || "";[39m
+[31m+ const taxonomyModalityIds = searchParams.get("taxModality") || "";[39m
+[31m+ const taxonomyToolClassIds = searchParams.get("taxTool") || "";[39m
+[31m+ const [requests, setRequests] = useState([]);[39m
+[31m+ const [requestPage, setRequestPage] = useState(null);[39m
+[31m+ const [charts, setCharts] = useState([]);[39m
+[31m+ const chartsRef = useRef([]);[39m
+[31m+ const [error, setError] = useState(null);[39m
+[31m+ const [loading, setLoading] = useState(true);[39m
+[31m+ const [refreshing, setRefreshing] = useState(false);[39m
+[31m+ const [staleCharts, setStaleCharts] = useState([]);[39m
+[31m+[39m
+[31m+ const updateParam = (key: string, value: string) => {[39m
+[31m+ setSearchParams((prev) => {[39m
+[31m+ const next = new URLSearchParams(prev);[39m
+[31m+ if (value) {[39m
+[31m+ next.set(key, value);[39m
+[31m+ } else {[39m
+[31m+ next.delete(key);[39m
+[31m+ }[39m
+[31m+ return next;[39m
+[31m+ });[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ const filters = useMemo(() => {[39m
+[31m+ const normalizedEndpointId = normalizeOptionalId(endpointId);[39m
+[31m+ const normalizedModelId = normalizeOptionalId(modelId);[39m
+[31m+ const normalizedReasoningEfforts = normalizeOptionalCsvIds(reasoningEffort);[39m
+[31m+ const normalizedEffortSources = normalizeOptionalCsvIds(effortSource);[39m
+[31m+ const normalizedProviderId = normalizeOptionalId(providerId);[39m
+[31m+ const normalizedTaxonomyGroupId = normalizeOptionalId(taxonomyGroupId);[39m
+[31m+ const normalizedTaxonomyRoleId = normalizeOptionalId(taxonomyRoleId);[39m
+[31m+ const normalizedTaxonomyTaskType = normalizeOptionalId(taxonomyTaskType);[39m
+[31m+ const normalizedTaxonomyTaskVariant = normalizeOptionalId(taxonomyTaskVariant);[39m
+[31m+ const normalizedTaxonomyCapabilityIds = normalizeOptionalCsvIds(taxonomyCapabilityIds);[39m
+[31m+ const normalizedTaxonomyModalityIds = normalizeOptionalCsvIds(taxonomyModalityIds);[39m
+[31m+ const normalizedTaxonomyToolClassIds = normalizeOptionalCsvIds(taxonomyToolClassIds);[39m
+[31m+ return {[39m
+[31m+ ...(sourceFilter === "all" ? {} : { sourceTypes: [sourceFilter] }),[39m
+[31m+ ...(statusFamily === "all" ? {} : { statusFamilies: [statusFamily] }),[39m
+[31m+ ...(normalizedEndpointId ? { endpointIds: [normalizedEndpointId] } : {}),[39m
+[31m+ ...(normalizedModelId ? { modelIds: [normalizedModelId] } : {}),[39m
+[31m+ ...(normalizedReasoningEfforts ? { reasoningEfforts: normalizedReasoningEfforts } : {}),[39m
+[31m+ ...(normalizedEffortSources ? { effortSources: normalizedEffortSources } : {}),[39m
+[31m+ ...(normalizedProviderId ? { providerIds: [normalizedProviderId] } : {}),[39m
+[31m+ ...(normalizedTaxonomyGroupId ? { taxonomyGroupIds: [normalizedTaxonomyGroupId] } : {}),[39m
+[31m+ ...(normalizedTaxonomyRoleId ? { taxonomyRoleIds: [normalizedTaxonomyRoleId] } : {}),[39m
+[31m+ ...(normalizedTaxonomyTaskType ? { taxonomyTaskTypes: [normalizedTaxonomyTaskType] } : {}),[39m
+[31m+ ...(normalizedTaxonomyTaskVariant[39m
+[31m+ ? { taxonomyTaskVariants: [normalizedTaxonomyTaskVariant] }[39m
+[31m+ : {}),[39m
+[31m+ ...(normalizedTaxonomyCapabilityIds[39m
+[31m+ ? { taxonomyCapabilityIds: normalizedTaxonomyCapabilityIds }[39m
+[31m+ : {}),[39m
+[31m+ ...(normalizedTaxonomyModalityIds[39m
+[31m+ ? { taxonomyModalityIds: normalizedTaxonomyModalityIds }[39m
+[31m+ : {}),[39m
+[31m+ ...(normalizedTaxonomyToolClassIds[39m
+[31m+ ? { taxonomyToolClassIds: normalizedTaxonomyToolClassIds }[39m
+[31m+ : {}),[39m
+[31m+ } satisfies RuntimeTelemetryAnalyticsFilters;[39m
+[31m+ }, [[39m
+[31m+ endpointId,[39m
+[31m+ effortSource,[39m
+[31m+ modelId,[39m
+[31m+ providerId,[39m
+[31m+ reasoningEffort,[39m
+[31m+ sourceFilter,[39m
+[31m+ statusFamily,[39m
+[31m+ taxonomyCapabilityIds,[39m
+[31m+ taxonomyGroupId,[39m
+[31m+ taxonomyModalityIds,[39m
+[31m+ taxonomyRoleId,[39m
+[31m+ taxonomyTaskType,[39m
+[31m+ taxonomyTaskVariant,[39m
+[31m+ taxonomyToolClassIds,[39m
+[31m+ ]);[39m
+[31m+[39m
+[31m+ const hasAdvancedFilters =[39m
+[31m+ endpointId.trim().length > 0 ||[39m
+[31m+ modelId.trim().length > 0 ||[39m
+[31m+ reasoningEffort.trim().length > 0 ||[39m
+[31m+ effortSource.trim().length > 0 ||[39m
+[31m+ providerId.trim().length > 0 ||[39m
+[31m+ statusFamily !== "all" ||[39m
+[31m+ taxonomyGroupId.trim().length > 0 ||[39m
+[31m+ taxonomyRoleId.trim().length > 0 ||[39m
+[31m+ taxonomyTaskType.trim().length > 0 ||[39m
+[31m+ taxonomyTaskVariant.trim().length > 0 ||[39m
+[31m+ taxonomyCapabilityIds.trim().length > 0 ||[39m
+[31m+ taxonomyModalityIds.trim().length > 0 ||[39m
+[31m+ taxonomyToolClassIds.trim().length > 0;[39m
+[31m+[39m
+[31m+ const breakdown = breakdownValue === "" ? null : breakdownValue;[39m
+[31m+[39m
+[31m+ useEffect(() => {[39m
+[31m+ let disposed = false;[39m
+[31m+[39m
+[31m+ const load = async (background = false) => {[39m
+[31m+ if (!background) {[39m
+[31m+ setLoading(true);[39m
+[31m+ } else {[39m
+[31m+ setRefreshing(true);[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ try {[39m
+[31m+ const definitions = buildObserveRequestsChartDefinitions({[39m
+[31m+ timeRange,[39m
+[31m+ breakdown,[39m
+[31m+ rankingMetric,[39m
+[31m+ rankingDimension,[39m
+[31m+ filters,[39m
+[31m+ });[39m
+[31m+ const [nextRequests, chartResults] = await Promise.all([[39m
+[31m+ fetchTelemetryRequestsPage({[39m
+[31m+ limit: 200,[39m
+[31m+ windowMs: getWindowMs(timeRange),[39m
+[31m+ filters,[39m
+[31m+ }),[39m
+[31m+ Promise.allSettled([39m
+[31m+ definitions.map((definition) => fetchTelemetryAnalytics(definition.query)),[39m
+[31m+ ),[39m
+[31m+ ]);[39m
+[31m+ if (disposed) {[39m
+[31m+ return;[39m
+[31m+ }[39m
+[31m+ setRequestPage(nextRequests);[39m
+[31m+ setRequests(nextRequests.items);[39m
+[31m+ const resolvedCharts = resolveTelemetryChartRefresh({[39m
+[31m+ background,[39m
+[31m+ chartResults,[39m
+[31m+ createDiagnostic: (definition, reason) =>[39m
+[31m+ createStaleChartDiagnostic({[39m
+[31m+ routeId: "requests",[39m
+[31m+ chartTitle: definition.title,[39m
+[31m+ querySnapshot: buildQuerySnapshot(breakdown, timeRange),[39m
+[31m+ error: reason,[39m
+[31m+ }),[39m
+[31m+ definitions,[39m
+[31m+ getErrorMessage: getChartLoadErrorMessage,[39m
+[31m+ previousCharts: chartsRef.current,[39m
+[31m+ });[39m
+[31m+ chartsRef.current = resolvedCharts.charts;[39m
+[31m+ setCharts(resolvedCharts.charts);[39m
+[31m+ setStaleCharts(resolvedCharts.staleChartTitles);[39m
+[31m+ flushStaleRefreshDiagnostics();[39m
+[31m+ setError(null);[39m
+[31m+ } catch (value) {[39m
+[31m+ if (!disposed) {[39m
+[31m+ setError(value instanceof Error ? value.message : "Could not load telemetry analytics.");[39m
+[31m+ }[39m
+[31m+ } finally {[39m
+[31m+ if (!disposed) {[39m
+[31m+ setLoading(false);[39m
+[31m+ setRefreshing(false);[39m
+[31m+ }[39m
+[31m+ }[39m
+[31m+ };[39m
+[31m+[39m
+[31m+ const dispose = startDeferredLiveRefresh({[39m
+[31m+ load,[39m
+[31m+ subscribe: (onEvent) => subscribeRuntimeRefreshStream(onEvent),[39m
+[31m+ });[39m
+[31m+[39m
+[31m+ return () => {[39m
+[31m+ disposed = true;[39m
+[31m+ dispose();[39m
+[31m+ };[39m
+[31m+ }, [breakdown, filters, rankingDimension, rankingMetric, timeRange]);[39m
+[31m+[39m
+[31m+ const filteredRequests = useMemo([39m
+[31m+ () => requests.filter((request) => matchesRequestFilters(request, filters)),[39m
+[31m+ [filters, requests],[39m
+[31m+ );[39m
+[31m+ const ledgerRows = useMemo(() => buildTelemetryRequestRows(filteredRequests), [filteredRequests]);[39m
+[31m+ const chartBlocks = useMemo([39m
+[31m+ () =>[39m
+[31m+ charts.map((chart) =>[39m
+[31m+ adaptObserveChartBlock(chart.definition, {[39m
+[31m+ response: chart.response,[39m
+[31m+ errorMessage: chart.errorMessage,[39m
+[31m+ loading: loading && charts.length === 0,[39m
+[31m+ }),[39m
+[31m+ ),[39m
+[31m+ [charts, loading],[39m
+[31m+ );[39m
+[31m+[39m
+[31m+ if (error) {[39m
+[31m+ return ;[39m
+[31m+ }[39m
+[31m+[39m
+[31m+ return ([39m
+[31m+ [39m
+[31m+ {staleCharts.length > 0 ? ([39m
+[31m+
[39m
+[31m+ [39m
+[31m+ Some charts may be using cached data from a previous refresh.[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ ({staleCharts.length} chart{staleCharts.length !== 1 ? "s" : ""})[39m
+[31m+ [39m
+[31m+
[39m
+[31m+ ) : null}[39m
+[31m+[39m
+[31m+
updateParam("range", fromPageTimeRange(value))}[39m
+[31m+ trailing={[39m
+[31m+ [39m
+[31m+ updateParam("breakdown", value)}[39m
+[31m+ options={requestBreakdownOptions}[39m
+[31m+ value={breakdownValue}[39m
+[31m+ />[39m
+[31m+ updateParam("source", value)}[39m
+[31m+ options={[[39m
+[31m+ { label: "All sources", value: "all" },[39m
+[31m+ { label: "Local only", value: "local" },[39m
+[31m+ { label: "Remote only", value: "remote" },[39m
+[31m+ ]}[39m
+[31m+ value={sourceFilter}[39m
+[31m+ />[39m
+[31m+ updateParam("metric", value)}[39m
+[31m+ options={rankingMetricOptions}[39m
+[31m+ value={rankingMetric}[39m
+[31m+ />[39m
+[31m+ updateParam("rankBy", value)}[39m
+[31m+ options={rankingDimensionOptions}[39m
+[31m+ value={rankingDimension}[39m
+[31m+ />[39m
+[31m+
[39m
+[31m+ }[39m
+[31m+ />[39m
+[31m+[39m
+[31m+ [39m
+[31m+ [39m
+[31m+
[39m
+[31m+ updateParam("endpointId", value)}[39m
+[31m+ placeholder="Filter a specific endpoint id"[39m
+[31m+ value={endpointId}[39m
+[31m+ />[39m
+[31m+ updateParam("modelId", value)}[39m
+[31m+ placeholder="Filter a specific model id"[39m
+[31m+ value={modelId}[39m
+[31m+ />[39m
+[31m+ updateParam("providerId", value)}[39m
+[31m+ placeholder="Filter a specific provider id"[39m
+[31m+ value={providerId}[39m
+[31m+ />[39m
+[31m+ updateParam("status", value)}[39m
+[31m+ options={[[39m
+[31m+ { label: "All statuses", value: "all" },[39m
+[31m+ { label: "Success only", value: "success" },[39m
+[31m+ { label: "Failure only", value: "failure" },[39m
+[31m+ { label: "Unknown only", value: "unknown" },[39m
+[31m+ ]}[39m
+[31m+ value={statusFamily}[39m
+[31m+ />[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ updateParam("effort", value)}[39m
+[31m+ placeholder="Comma-separated values, e.g. high,max"[39m
+[31m+ value={reasoningEffort}[39m
+[31m+ />[39m
+[31m+ updateParam("effortSource", value)}[39m
+[31m+ placeholder="Comma-separated values, e.g. variant,client"[39m
+[31m+ value={effortSource}[39m
+[31m+ />[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ updateParam("taxGroup", value)}[39m
+[31m+ placeholder="e.g. engineering"[39m
+[31m+ value={taxonomyGroupId}[39m
+[31m+ />[39m
+[31m+ updateParam("taxRole", value)}[39m
+[31m+ placeholder="e.g. coder"[39m
+[31m+ value={taxonomyRoleId}[39m
+[31m+ />[39m
+[31m+ updateParam("taxTask", value)}[39m
+[31m+ placeholder="e.g. coder.review"[39m
+[31m+ value={taxonomyTaskType}[39m
+[31m+ />[39m
+[31m+ updateParam("taxVariant", value)}[39m
+[31m+ placeholder="e.g. deep-audit"[39m
+[31m+ value={taxonomyTaskVariant}[39m
+[31m+ />[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ updateParam("taxCapability", value)}[39m
+[31m+ placeholder="Comma-separated capability ids"[39m
+[31m+ value={taxonomyCapabilityIds}[39m
+[31m+ />[39m
+[31m+ updateParam("taxModality", value)}[39m
+[31m+ placeholder="Comma-separated modality ids"[39m
+[31m+ value={taxonomyModalityIds}[39m
+[31m+ />[39m
+[31m+ updateParam("taxTool", value)}[39m
+[31m+ placeholder="Comma-separated tool class ids"[39m
+[31m+ value={taxonomyToolClassIds}[39m
+[31m+ />[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ [39m
+[31m+[39m
+[31m+ [39m
+[31m+ {chartBlocks.map((block) => ([39m
+[31m+ [39m
+[31m+ [39m
+[31m+ [39m
+[31m+ ))}[39m
+[31m+ [39m
+[31m+[39m
+[31m+ [39m
+[31m+ {loading && charts.length === 0 ? ([39m
+[31m+ [39m
+[31m+ ) : ledgerRows.length === 0 ? ([39m
+[31m+ [39m
+[31m+ ) : ([39m
+[31m+ [39m
+[31m+ {ledgerRows.map((request) => {[39m
+[31m+ const sourceKey = request.sourceLabel.toLowerCase();[39m
+[31m+ return ([39m
+[31m+
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+
{request.requestId}
[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ {sourceKey === "local" || sourceKey === "remote"[39m
+[31m+ ? sourceKey[39m
+[31m+ : request.sourceLabel}[39m
+[31m+ [39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+[39m
+[31m+
[39m
+[31m+ [39m
+[31m+ Observe · Open detail[39m
+[31m+ [39m
+[31m+ {request.routingDecisionLabel !== "n/a" ? ([39m
+[31m+ [39m
+[31m+ Router · Open detail[39m
+[31m+ [39m
+[31m+ ) : null}[39m
+[31m+
[39m
+[31m+
[39m
+[31m+ );[39m
+[31m+ })}[39m
+[31m+
[39m
+[31m+ )}[39m
+[31m+ [39m
+[31m+ [39m
+[31m+ );[39m
+[31m+ }[39m
+[31m+[39m
+
+[36m [2m❯[22m app/routes/requests.test.tsx:[2m9:20[22m[39m
+ [90m 7| [39m[34mdescribe[39m([32m"run 106 R11 request surface truthfulness"[39m[33m,[39m () [33m=>[39m {
+ [90m 8| [39m test("shows the endpoint's effective reasoning effort, not just its …
+ [90m 9| [39m [34mexpect[39m(source)[33m.[39m[34mtoContain[39m([32m"formatEffectiveEffortDisclosure"[39m)[33m;[39m
+ [90m | [39m [31m^[39m
+ [90m 10| [39m expect(source).not.toContain("formatReasoningEffortLabel(request.r…
+ [90m 11| [39m })[33m;[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/6]⎯[22m[39m
+
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp8-effort-truth.red.txt b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp8-effort-truth.red.txt
new file mode 100644
index 000000000..dd2425ea3
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/logs/red/sp8-effort-truth.red.txt
@@ -0,0 +1,39 @@
+SP8 RED - R11 UI truthfulness (effort-truth projection)
+command: corepack pnpm --filter @role-model-router/runtime-ui exec vitest run app/lib/effort-truth.test.ts
+observed: module ./effort-truth not implemented yet (failing RED).
+exitCode: 1
+
+--- vitest stdout ---
+
+[1m[46m RUN [49m[22m [36mv3.2.4 [39m[90mD:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-ui[39m
+
+
+[2m Test Files [22m [1m[31m1 failed[39m[22m[90m (1)[39m
+[2m Tests [22m [2mno tests[22m
+[2m Start at [22m 12:27:21
+[2m Duration [22m 1.83s[2m (transform 85ms, setup 0ms, collect 0ms, tests 0ms, environment 0ms, prepare 624ms)[22m
+
+undefined
+D:\DEV\role-model\.worktrees\106-client-neutral-model-effort-routing\role-model-router\apps\runtime-ui:
+ ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL Command failed with exit code 1: vitest run app/lib/effort-truth.test.ts
+
+--- vitest stderr ---
+
+[31m⎯⎯⎯⎯⎯⎯[39m[1m[41m Failed Suites 1 [49m[22m[31m⎯⎯⎯⎯⎯⎯⎯[39m
+
+[41m[1m FAIL [22m[49m app/lib/effort-truth.test.ts[2m [ app/lib/effort-truth.test.ts ][22m
+[31m[1mError[22m: Cannot find module './effort-truth' imported from 'D:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts'[39m
+[36m [2m❯[22m app/lib/effort-truth.test.ts:[2m3:1[22m[39m
+ [90m 1| [39m[35mimport[39m { describe[33m,[39m expect[33m,[39m test } [35mfrom[39m [32m"vitest"[39m[33m;[39m
+ [90m 2| [39m
+ [90m 3| [39m[35mimport[39m {
+ [90m | [39m[31m^[39m
+ [90m 4| [39m [33mEFFORT_EVIDENCE_LABELS[39m[33m,[39m
+ [90m 5| [39m [33mEFFORT_RESOLUTION_LABELS[39m[33m,[39m
+
+[31m[1mCaused by: Error[22m: Failed to load url ./effort-truth (resolved id: ./effort-truth) in D:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing/role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts. Does the file exist?[39m
+[90m [2m❯[22m loadAndTransform ../../../node_modules/.pnpm/vite@7.3.2_@types+node@22.1_d71bf8265f9610ce90201e170d5dc2b8/node_modules/vite/dist/node/chunks/config.js:[2m22663:33[22m[39m
+
+[31m[2m⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯[22m[39m
+
+
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json
new file mode 100644
index 000000000..09cd59e6f
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-packaged-sea.json
@@ -0,0 +1,11 @@
+{
+ "packagedSea": {
+ "executable": "role-model-router/dist/release/win32-x64/role-model-dev.exe",
+ "sha256": "e181c6011a50a7e9681d6f16314ae7cefcbe7ca26bb21eeac34343b3befc7364",
+ "bytes": 103994880,
+ "launcher": "role-model-router/dist/release/win32-x64/role-model-dev-launcher.exe",
+ "launcherSha256": "63f46d2f2736f17c1ddedfcd59911d60a9554fc9b3442dc13fc0adffdd09ebe7",
+ "builtFrom": "701b8b8..9260a10b",
+ "trackBClosure": "vendored Effect/Effect-MQ closure present"
+ }
+}
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json
new file mode 100644
index 000000000..b4e2601fc
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-pi-routing-trace.json
@@ -0,0 +1,47 @@
+{
+ "piRoutingTrace": {
+ "port": 3462,
+ "isolated": true,
+ "notIn": [
+ 3456,
+ 3457,
+ 3458
+ ],
+ "requestId": "req-9d68e76b",
+ "routingDecisionId": "decision-req-9d68e76b",
+ "routedModel": "deepseek-v4-pro",
+ "scenarios": [
+ {
+ "id": "S1-strict-max",
+ "request": {
+ "model": "deepseek/deepseek-v4-flash",
+ "reasoning": {
+ "effort": "max",
+ "effort_policy": "strict"
+ }
+ },
+ "result": {
+ "status": 200,
+ "endpointId": "deepseek.personal.deepseek-api-key.global.deepseek-v4-flash-max",
+ "verdict": "PASS - strict policy routed to the exact-effort arm"
+ }
+ },
+ {
+ "id": "S2-router-max",
+ "request": {
+ "model": "deepseek/deepseek-v4-flash",
+ "reasoning": {
+ "effort": "max",
+ "effort_policy": "router"
+ }
+ },
+ "result": {
+ "status": 200,
+ "endpointId": "deepseek.personal.deepseek-api-key.global.deepseek-v4-flash",
+ "verdict": "PASS - router-managed selection"
+ }
+ }
+ ],
+ "secondClientParity": "PASS - a semantically identical request through a second client path produced the same normalized routing decision"
+ }
+}
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json
new file mode 100644
index 000000000..44207b394
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-routing-scenarios.json
@@ -0,0 +1,54 @@
+{
+ "scenarios": [
+ {
+ "id": "S1-strict-effort-routing",
+ "request": {
+ "model": "deepseek/deepseek-v4-flash",
+ "reasoning": {
+ "effort": "max",
+ "effort_policy": "strict"
+ }
+ },
+ "result": {
+ "status": 200,
+ "routeEndpointId": "deepseek.personal.deepseek-api-key.global.deepseek-v4-flash-max",
+ "decisionId": "decision-req-0fb33bd6-691e-4b62-b812-2c490455fe71",
+ "verdict": "PASS - strict policy routed to the exact-effort arm"
+ }
+ },
+ {
+ "id": "S2-router-contrast",
+ "request": {
+ "model": "deepseek/deepseek-v4-flash",
+ "reasoning": {
+ "effort": "max",
+ "effort_policy": "router"
+ }
+ },
+ "result": {
+ "status": "timeout(30s)",
+ "verdict": "secondary - router policy exercised the multi-candidate measured-latency selector (separate concern from effort routing)"
+ }
+ },
+ {
+ "id": "S3-preferred-contrast",
+ "request": {
+ "model": "deepseek/deepseek-v4-flash",
+ "reasoning": {
+ "effort": "max",
+ "effort_policy": "preferred"
+ }
+ },
+ "result": {
+ "status": 503,
+ "code": "endpoint_temporarily_unavailable",
+ "verdict": "secondary - cooldown after S2 failure"
+ }
+ }
+ ],
+ "health": {
+ "version": "0.0.14-734-gb1d9344e",
+ "status": "healthy",
+ "executionMode": "remote_only"
+ }
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json
new file mode 100644
index 000000000..b0e1914d9
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/qa/05-qa-runtime-launch.json
@@ -0,0 +1,27 @@
+{
+ "runtimeLaunch": {
+ "host": "127.0.0.1",
+ "port": 3461,
+ "isolated": true,
+ "notIn": [
+ 3456,
+ 3457,
+ 3458
+ ],
+ "status": "listening",
+ "repoRoot": "D:/DEV/role-model/.worktrees/106-client-neutral-model-effort-routing",
+ "scopeId": "runtime",
+ "stateRoot": "C:/Users/erikb/AppData/Local/role-model-runtime-dev",
+ "launchCmd": "corepack pnpm --filter @role-model-router/runtime-host-bridge exec tsx src/cli-entry.ts --repo-root --runtime-state-root C:/Users/erikb/AppData/Local/role-model-runtime-dev --scope-id runtime --unified-runtime-config C:/Users/erikb/AppData/Local/role-model-runtime-dev/runtime-config.yaml --host 127.0.0.1 --port 3461"
+ },
+ "discovery": {
+ "contractVersion": "role-model.downstream.openai.v1",
+ "providerId": "role-model-runtime",
+ "baseUrl": "http://127.0.0.1:3461",
+ "modelsCount": 23,
+ "effortVariants": [
+ "deepseek.personal.deepseek-api-key.global.deepseek-v4-flash-max",
+ "deepseek.personal.deepseek-api-key.global.deepseek-v4-pro-max"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/00-requirements-audit.md b/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/00-requirements-audit.md
new file mode 100644
index 000000000..9e1934837
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/00-requirements-audit.md
@@ -0,0 +1,71 @@
+# Run 106 Phase 0 requirements audit bundle
+
+Phase: `00 Requirements`
+Artifact: `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+Role: phase-auditor / traceability-auditor
+Artifact state: DRAFT, 417 lines, read back after write
+
+## Upstream artifacts to reread
+
+- `/.recursive/RECURSIVE.md`
+- `/AGENTS.md`
+- `/.recursive/STATE.md`
+- `/.recursive/DECISIONS.md`
+- `/.recursive/memory/MEMORY.md`
+- `/.recursive/memory/skills/SKILLS.md`
+- `/.recursive/run/93-variant-admission-model-pool-integrity/00-requirements.md`
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+- `/.recursive/run/104-replay-eligibility-and-evidence-fidelity/00-requirements.md`
+
+Relevant addenda: none for run 106.
+
+## Diff basis and changed files
+
+- Baseline type: current controller checkout, requirements-only pre-worktree phase
+- Baseline/normalized baseline: `HEAD` / `701b8b8fc0b0eeebdfe818b757f5702f50021488`
+- Comparison: working tree
+- Command: `git diff -- .recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- Run-106 changed file: `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- Pre-existing excluded drift: two modified llama-swap binary artifacts
+
+## Targeted code references for feasibility checks
+
+- `/role-model-router/apps/runtime-host-bridge/src/index.ts`: effort pool resolution, ingress normalization, difficulty, dispatch, runtime startup and decision projection
+- `/role-model-router/packages/core/src/router.ts`: eligibility, metric evidence, weighted scoring and tie-break
+- `/role-model-router/packages/protocol-routing/src/index.ts`: candidate projection and route wrapper
+- `/packages/pi-role-model/`: Pi discovery/provider binding
+- `/role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`: precedence
+- `/role-model-router/packages/sqlite-memory/src/index.ts`: evidence and telemetry persistence
+
+## Operator decisions to verify losslessly
+
+- Client-neutral across Pi, DSH, Codex and other clients.
+- Joint model-effort arm selection; effort-specific evidence.
+- Omitted=router, legacy scalar=preferred, explicit strict supported.
+- Preferred exact primary; pool-wide unsupported hint ignored with receipt; strict unavailable fails.
+- No implicit high/xhigh/max mapping; none/default/omitted distinct.
+- Approved F4/F5/F6 repairs included.
+- Strict TDD and substantive delegation required.
+- Packaged SEA tested with a real Pi process explicitly bound to a free isolated port; 3456/3457/3458 forbidden and untouched.
+
+## Audit questions
+
+1. Are R1-R15 stable, unambiguous, observable, internally consistent, and complete?
+2. Does preferred fallback distinguish pool-wide unsupported from exact arms made unavailable after hard eligibility?
+3. Can arms be executed, deduplicated, persisted, benchmarked, and scored without identity/evidence leakage?
+4. Are discovery and provenance sufficient for every client and operator surface?
+5. Are F4 difficulty, F5 cost/latency/Pareto, and F6 priors bounded enough for a safe Phase 2 plan?
+6. Does R15 prove that Pi itself reached the rebuilt runtime on a non-reserved isolated port, with identity-safe cleanup?
+7. Does strict TDD cover production behavior and preserve prior-run regressions?
+8. Are delegation, audit, action-record, and controller-verification obligations compliant with recursive-mode?
+9. Are out-of-scope, constraints, assumptions, tasks, and traceability sufficient?
+10. Identify contradictions, missing acceptance criteria, hidden implementation choices, scope explosions, and requirements that cannot be mechanically verified.
+
+## Required output
+
+Return:
+- findings ordered by severity with exact artifact line citations;
+- missing or ambiguous requirement mappings;
+- concrete repair text;
+- explicit `Audit: PASS` or `Audit: FAIL`;
+- enough detail for a durable subagent action record (inputs reread, files reviewed, findings, verification handoff).
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md b/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md
new file mode 100644
index 000000000..7cf9e09e5
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/evidence/review-bundles/03.5-code-review.md
@@ -0,0 +1,43 @@
+# Run 106 Phase 3.5 code review bundle
+
+Artifact Path: `/.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md`
+Artifact Content Hash: `8e8cb05f3ccc44940b98ef661fe28c92f18bf7e94920f3196bef29725792e89e`
+
+## Diff Basis
+- Baseline type: remote ref
+- Baseline reference: origin/dev
+- Comparison reference: working-tree
+- Normalized baseline: 701b8b8fc0b0eeebdfe818b757f5702f50021488
+- Normalized comparison: working-tree
+- Normalized diff command: git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488
+
+## Changed Files Reviewed
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+
+## Upstream Artifacts To Re-read
+- `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`
+
+## Relevant Addenda
+- none
+
+## Prior Recursive Evidence
+- `/.recursive/run/103-agent-strategy-and-scoring-strategy/00-requirements.md`
+
+## Targeted Code References
+- `role-model-router/apps/runtime-host-bridge/src/index.ts` (applyReasoningEffortToModelPool, normalizeReasoningEffortPolicy, resolveEffortPolicy, shouldShortcutToHard)
+- `role-model-router/packages/core/src/router.ts` (getQualityMetric, resolveBorrowedQualityPrior, shouldPreferNonInferiorChallenger, computeEffortUnionAndIntersection)
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts` (expandReasoningEffortArms)
+
+## Audit Questions
+- Is the preferred unsupported-effort fallback correct (router-managed, not refusal)?
+- Are the borrowed-prior source label and discount semantics correct?
+- Are the dead-code functions honestly disposed?
+- Is backward compatibility preserved when effortPolicy is absent?
+
+## Required Output
+- Severity-ordered findings with line citations; concrete repair text; Audit: PASS or FAIL.
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/00-requirements.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/00-requirements.receipt.json
new file mode 100644
index 000000000..1d3da8120
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/00-requirements.receipt.json
@@ -0,0 +1,9 @@
+{
+ "artifact": "00-requirements.md",
+ "artifact_hash": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "artifact_path": "D:\\DEV\\role-model\\.recursive\\run\\106-client-neutral-model-effort-routing\\00-requirements.md",
+ "locked_at": "2026-10-04T01:04:39Z",
+ "prerequisite_hashes": {},
+ "previous_receipt_hash": null,
+ "receipt_hash": "069fe0ac3486686937b9212ffaa88626e2fa1e030b6b0b8149efd45d2d66f5b2"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/00-worktree.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/00-worktree.receipt.json
new file mode 100644
index 000000000..3661afc3d
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/00-worktree.receipt.json
@@ -0,0 +1,11 @@
+{
+ "artifact": "00-worktree.md",
+ "artifact_hash": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\00-worktree.md",
+ "locked_at": "2026-10-04T01:15:16Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "410b4d209ebf9afd2fe57be2d854334cfa2e8c6c10a87a1713cf037f6b3b104d"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/01-as-is.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/01-as-is.receipt.json
new file mode 100644
index 000000000..f650fcbf0
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/01-as-is.receipt.json
@@ -0,0 +1,12 @@
+{
+ "artifact": "01-as-is.md",
+ "artifact_hash": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\01-as-is.md",
+ "locked_at": "2026-10-04T01:33:52Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "76d22260b5fff1c8e66e7cde09cc90b4f6d1e96fd9a51399dd8ad450035e6e76"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/01.5-root-cause.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/01.5-root-cause.receipt.json
new file mode 100644
index 000000000..c84f21075
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/01.5-root-cause.receipt.json
@@ -0,0 +1,13 @@
+{
+ "artifact": "01.5-root-cause.md",
+ "artifact_hash": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\01.5-root-cause.md",
+ "locked_at": "2026-10-04T01:35:35Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "8ef94872412b75dcb101e788bbeec2466c0417257acb33bf33dda9dc17a53530"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/02-to-be-plan.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/02-to-be-plan.receipt.json
new file mode 100644
index 000000000..076fb0073
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/02-to-be-plan.receipt.json
@@ -0,0 +1,14 @@
+{
+ "artifact": "02-to-be-plan.md",
+ "artifact_hash": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\02-to-be-plan.md",
+ "locked_at": "2026-10-04T01:44:35Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "ad172eb563ffd8559fbb48a9a54965a47551a23f367920557d3f9ed644af7de3"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/03-implementation-summary.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/03-implementation-summary.receipt.json
new file mode 100644
index 000000000..beb071e86
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/03-implementation-summary.receipt.json
@@ -0,0 +1,15 @@
+{
+ "artifact": "03-implementation-summary.md",
+ "artifact_hash": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\03-implementation-summary.md",
+ "locked_at": "2026-10-04T21:55:00Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "8d9aae225562607d06368637fd16b97e305061b013941ddef3455d67d33e2086"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/03.5-code-review.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/03.5-code-review.receipt.json
new file mode 100644
index 000000000..97355c310
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/03.5-code-review.receipt.json
@@ -0,0 +1,16 @@
+{
+ "artifact": "03.5-code-review.md",
+ "artifact_hash": "13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\03.5-code-review.md",
+ "locked_at": "2026-10-04T21:55:23Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "03-implementation-summary.md": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "6d9bc644730cc50657584ff8439db10ebde163508bf798f4e3afa9f8e6580be7"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/04-test-summary.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/04-test-summary.receipt.json
new file mode 100644
index 000000000..cda2c8e57
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/04-test-summary.receipt.json
@@ -0,0 +1,17 @@
+{
+ "artifact": "04-test-summary.md",
+ "artifact_hash": "389d370ed147c18878fd47dd8bd53deeeda17bfa090ded20c3587de88fcbd0e1",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\04-test-summary.md",
+ "locked_at": "2026-10-04T21:55:46Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "03-implementation-summary.md": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636",
+ "03.5-code-review.md": "13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "cc7700ff711136abba6395a08d5c875b64e04347aa251c7fe2cd5522095850f7"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/05-manual-qa.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/05-manual-qa.receipt.json
new file mode 100644
index 000000000..51ca09559
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/05-manual-qa.receipt.json
@@ -0,0 +1,18 @@
+{
+ "artifact": "05-manual-qa.md",
+ "artifact_hash": "0944426b518e6df96e3c70e09cd503bbda66791ac3a7b41a37d01b7ea1aa8482",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\05-manual-qa.md",
+ "locked_at": "2026-10-04T21:55:49Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "03-implementation-summary.md": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636",
+ "03.5-code-review.md": "13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f",
+ "04-test-summary.md": "389d370ed147c18878fd47dd8bd53deeeda17bfa090ded20c3587de88fcbd0e1"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "bedb2bea6a08a03343b6bceb05186fba5034b686b3489d1e312967cb5284397b"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/06-decisions-update.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/06-decisions-update.receipt.json
new file mode 100644
index 000000000..13a335906
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/06-decisions-update.receipt.json
@@ -0,0 +1,19 @@
+{
+ "artifact": "06-decisions-update.md",
+ "artifact_hash": "aff99b0e29e34210a0f28bca0b78241d7dc29f988a96d63d77919af491475197",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\06-decisions-update.md",
+ "locked_at": "2026-10-04T22:07:37Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "03-implementation-summary.md": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636",
+ "03.5-code-review.md": "13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f",
+ "04-test-summary.md": "389d370ed147c18878fd47dd8bd53deeeda17bfa090ded20c3587de88fcbd0e1",
+ "05-manual-qa.md": "0944426b518e6df96e3c70e09cd503bbda66791ac3a7b41a37d01b7ea1aa8482"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "7bb6aba366380533e56f5f46eca37b2183b0d965459fe328589620584c6184ac"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/07-state-update.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/07-state-update.receipt.json
new file mode 100644
index 000000000..688aabc7a
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/07-state-update.receipt.json
@@ -0,0 +1,20 @@
+{
+ "artifact": "07-state-update.md",
+ "artifact_hash": "843b62ca995091ac3750771e4af1010f05bb99e809406f726db3dcdfae333604",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\07-state-update.md",
+ "locked_at": "2026-10-04T22:07:39Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "03-implementation-summary.md": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636",
+ "03.5-code-review.md": "13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f",
+ "04-test-summary.md": "389d370ed147c18878fd47dd8bd53deeeda17bfa090ded20c3587de88fcbd0e1",
+ "05-manual-qa.md": "0944426b518e6df96e3c70e09cd503bbda66791ac3a7b41a37d01b7ea1aa8482",
+ "06-decisions-update.md": "aff99b0e29e34210a0f28bca0b78241d7dc29f988a96d63d77919af491475197"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "484df320e1d8ae031120f01151fd16847bc731c2f5cce2b53b7fd2ef0665c830"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/locks/08-memory-impact.receipt.json b/.recursive/run/106-client-neutral-model-effort-routing/locks/08-memory-impact.receipt.json
new file mode 100644
index 000000000..e7d36a5be
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/locks/08-memory-impact.receipt.json
@@ -0,0 +1,21 @@
+{
+ "artifact": "08-memory-impact.md",
+ "artifact_hash": "be069bbf7708d19783d5c2bd22e8ee32b894a2c7601eb22625c696093d4fb38e",
+ "artifact_path": "D:\\DEV\\role-model\\.worktrees\\106-client-neutral-model-effort-routing\\.recursive\\run\\106-client-neutral-model-effort-routing\\08-memory-impact.md",
+ "locked_at": "2026-10-04T22:07:42Z",
+ "prerequisite_hashes": {
+ "00-requirements.md": "9be64e945082f71fd7f93376c739ea49d90f002dfaf6e7d71e45dd16f764928f",
+ "00-worktree.md": "92c639d820bd6cf940ad9effa9b48ce184f361c902ba2e1db6734428f0bee763",
+ "01-as-is.md": "4eb5dd07463e24b05ac886cf5b894980faba13814ec76a55df2f516d26583120",
+ "01.5-root-cause.md": "2556019928b11363103a46decbb523eda6290bcff4934f90df908c5419a288c6",
+ "02-to-be-plan.md": "1d080de4ee4b8e630516ad9c89c15d87c95ba58176e2765af0b86935e7b90afc",
+ "03-implementation-summary.md": "1deae17f72a4810aaeeb49e4170690403b24ac81993157734a6f20915464e636",
+ "03.5-code-review.md": "13272ca4ec0347f6af302bc1f70218095510b7d68fef24f6a602fb621becf40f",
+ "04-test-summary.md": "389d370ed147c18878fd47dd8bd53deeeda17bfa090ded20c3587de88fcbd0e1",
+ "05-manual-qa.md": "0944426b518e6df96e3c70e09cd503bbda66791ac3a7b41a37d01b7ea1aa8482",
+ "06-decisions-update.md": "aff99b0e29e34210a0f28bca0b78241d7dc29f988a96d63d77919af491475197",
+ "07-state-update.md": "843b62ca995091ac3750771e4af1010f05bb99e809406f726db3dcdfae333604"
+ },
+ "previous_receipt_hash": null,
+ "receipt_hash": "b81170761c1da02a27538f7c7f02aedb6c34fe67831d475ea625c8614acbda48"
+}
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/subagents/analyst-323c261d.md b/.recursive/run/106-client-neutral-model-effort-routing/subagents/analyst-323c261d.md
new file mode 100644
index 000000000..444afca16
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/subagents/analyst-323c261d.md
@@ -0,0 +1,74 @@
+# Subagent Action Record
+
+## Metadata
+- Subagent ID: `323c261d-efa6-4f03-a794-67c9321427c0`
+- Run ID: `106-client-neutral-model-effort-routing`
+- Phase: 01 AS-IS
+- Purpose: `Read-only analyst pass over the reasoning-effort routing path`
+- Execution Mode: `in-session subagent (read-only)`
+- Timestamp: `2026-10-04T01:30:00Z`
+- Action Record Path: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/analyst-323c261d.md`
+
+## Inputs Provided
+- Current Artifact: `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- Artifact Content Hash: `af80c99a0ae0aa05cb7d2c62aceb12df393b4536891e4c75a785e3328cfc13a8`
+- Upstream Artifacts: `/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md`
+- Addenda: none
+- Diff Basis: `git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488`
+- Code Refs: `/role-model-router/apps/runtime-host-bridge/src/index.ts`, `/role-model-router/packages/core/src/router.ts`, `/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- Memory Refs: none
+- Audit / Task Questions: trace effort ingress, arm identity, evidence keys, resolution semantics, strategy/difficulty, latency selector, discovery/provenance.
+
+## Routing
+- Router Used: `none`
+- Routed Role: `none`
+- Routed CLI: `none`
+- Routed Model: `none`
+- Routing Config Path: `none`
+- Routing Discovery Path: `none`
+- Routing Resolution Basis: `none`
+- Routing Fallback Reason: `none`
+- CLI Probe Summary: `none`
+- Prompt Bundle Path: `none`
+- Invocation Exit Code: `none`
+- Output Capture Paths: none
+
+## Claimed Actions Taken
+
+Traced reasoning-effort routing from every ingress (Chat Completions, Responses, Pi, DSH, Codex, SDK, header, request-option) through readOpenAIReasoningRequest and applyReasoningEffortToModelPool; inventoried fixed/dynamic/provider-default identity and effort-scoped evidence keys; reproduced the Pro-high/Flash-high asymmetry; identified three inconsistent effort-source vocabularies.
+
+## Claimed File Impact
+### Created
+- none
+### Modified
+- none
+### Reviewed
+- `/role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `/role-model-router/packages/core/src/router.ts`
+- `/role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`
+- `/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `/role-model-router/packages/trace/src/lineage.ts`
+### Relevant but Untouched
+- none
+
+## Claimed Artifact Impact
+### Read
+- `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md`
+### Updated
+- none
+### Evidence Used
+- none
+
+## Claimed Findings
+- No effort_policy/effortPolicy anywhere; single optional reasoning.effort string.
+- Benchmark evidence is exact endpoint_id-keyed and never cross-effort (the 0.5-default seam).
+- resolveStrategy lets hard->quality override a saved latency strategy; unconditional toolCount>0 && codeOrSchemaBurden->hard remains.
+- Measured-latency selector is separate and gated.
+- Three inconsistent effort-source vocabularies.
+
+## Verification Handoff
+- Inspect first:
+- `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`
+- Notes:
+- Controller reconciled this report into 01-as-is.md and the Phase 1.5 root cause.
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md b/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md
new file mode 100644
index 000000000..67d676f21
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md
@@ -0,0 +1,73 @@
+# Subagent Action Record
+
+## Metadata
+- Subagent ID: `13f44730-5f67-46c9-b576-4f6cbbe227dc`
+- Run ID: `106-client-neutral-model-effort-routing`
+- Phase: 03.5 Code Review
+- Purpose: `Code review of SP1-SP7 + SP3b/SP4b`
+- Execution Mode: `in-session subagent (read-only)`
+- Timestamp: `2026-10-04T02:40:00Z`
+- Action Record Path: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-13f44730.md`
+
+## Inputs Provided
+- Current Artifact: `/.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md`
+- Artifact Content Hash: `8e8cb05f3ccc44940b98ef661fe28c92f18bf7e94920f3196bef29725792e89e`
+- Upstream Artifacts: `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`, `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`
+- Addenda: none
+- Diff Basis: `git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488`
+- Code Refs: `role-model-router/packages/core/src/router.ts`, `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- Memory Refs: none
+- Audit / Task Questions: verify correctness, edge cases, backward compatibility, and R3/R5 semantics.
+
+## Routing
+- Router Used: `none`
+- Routed Role: `none`
+- Routed CLI: `none`
+- Routed Model: `none`
+- Routing Config Path: `none`
+- Routing Discovery Path: `none`
+- Routing Resolution Basis: `none`
+- Routing Fallback Reason: `none`
+- CLI Probe Summary: `none`
+- Prompt Bundle Path: `none`
+- Invocation Exit Code: `none`
+- Output Capture Paths: none
+
+## Claimed Actions Taken
+
+Reviewed the product diff 701b8b8..HEAD (5 product files + 6 test files); returned 11 findings (2 HIGH, 4 MEDIUM, 5 LOW); re-reviewed the five code repairs and confirmed them correct; returned Audit: PASS (conditional on the disposition re-marking and R5 follow-up recording).
+
+## Claimed File Impact
+### Created
+- none
+### Modified
+- none
+### Reviewed
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/packages/core/src/types.ts`
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `role-model-router/packages/adapter-execution/src/index.ts`
+### Relevant but Untouched
+- none
+
+## Claimed Artifact Impact
+### Read
+- `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/03-implementation-summary.md`
+### Updated
+- none
+### Evidence Used
+- none
+
+## Claimed Findings
+- HIGH-1 preferred unsupported-fallback bug (fixed).
+- HIGH-2 dead-code functions (re-marked deferred).
+- MEDIUM-3b/4/5 fixed; MEDIUM-3a/3c follow-up; MEDIUM-6 re-marked.
+- LOW-7/8/9/10/11 (LOW-9 fixed, rest follow-up).
+
+## Verification Handoff
+- Inspect first:
+- `/.recursive/run/106-client-neutral-model-effort-routing/03.5-code-review.md`
+- Notes:
+- Controller applied the five code repairs (9547319a), re-marked dispositions (a478d006, 13ee8fe3), and recorded the R5 follow-ups.
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-5c071c27.md b/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-5c071c27.md
new file mode 100644
index 000000000..928e4c918
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-5c071c27.md
@@ -0,0 +1,78 @@
+# Subagent Action Record
+
+## Metadata
+- Subagent ID: `5c071c27-aa91-44c7-b597-2fa045562ac5`
+- Run ID: `106-client-neutral-model-effort-routing`
+- Phase: 02 TO-BE Plan
+- Purpose: `Traceability audit of 02-to-be-plan.md`
+- Execution Mode: `in-session subagent (read-only)`
+- Timestamp: `2026-10-04T02:00:00Z`
+- Action Record Path: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-5c071c27.md`
+
+## Inputs Provided
+- Current Artifact: `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`
+- Artifact Content Hash: `d02527dd73579ed29c95e2389395d212d7bd5e227f7ea88b4657f42ce15c759f`
+- Upstream Artifacts: `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`, `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`, `/.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md`, `/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md`
+- Addenda: none
+- Diff Basis: `git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488`
+- Code Refs: `role-model-router/apps/runtime-host-bridge/src/index.ts`, `role-model-router/packages/core/src/router.ts`, `role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`, `role-model-router/apps/runtime-host-bridge/src/routing-latency-selection.ts`, `role-model-router/packages/sqlite-memory/src/index.ts`
+- Memory Refs: none
+- Audit / Task Questions: verify R#->file->RED coverage and internal consistency.
+
+## Routing
+- Router Used: `none`
+- Routed Role: `none`
+- Routed CLI: `none`
+- Routed Model: `none`
+- Routing Config Path: `none`
+- Routing Discovery Path: `none`
+- Routing Resolution Basis: `none`
+- Routing Fallback Reason: `none`
+- CLI Probe Summary: `none`
+- Prompt Bundle Path: `none`
+- Invocation Exit Code: `none`
+- Output Capture Paths: none
+
+## Claimed Actions Taken
+
+Verified every R1-R15 maps to a real file and a RED test; confirmed all planned files exist and the targeted seams are real; returned 7 findings (2 HIGH, 2 MEDIUM, 3 LOW) covering R8/RC3 measured-latency unmapped, run-105 third conflict surface, R10 dual-map, R4 vocabulary under-map, trace/lineage path, R12 dual-map, and test-file anchoring.
+
+## Claimed File Impact
+### Created
+- none
+### Modified
+- none
+### Reviewed
+- `role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `role-model-router/packages/core/src/router.ts`
+- `role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`
+- `role-model-router/apps/runtime-host-bridge/src/routing-latency-selection.ts`
+- `role-model-router/packages/sqlite-memory/src/index.ts`
+### Relevant but Untouched
+- none
+
+## Claimed Artifact Impact
+### Read
+- `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/01.5-root-cause.md`
+### Updated
+- none
+### Evidence Used
+- none
+
+## Claimed Findings
+- F1 HIGH: R8 measured-latency + RC3 unmapped (no routing-latency-selection.ts bullet; SP6 RED covers Pareto only).
+- F2 HIGH: run-105 overlap incomplete (only 2 of 3 surfaces; deferred re-check).
+- F3 MED: R10 dual-mapped SP7 vs SP3.
+- F4 MED: R4 three-vocabulary convergence under-mapped.
+- F5 LOW: trace/lineage.ts path imprecise.
+- F6 LOW: R12 dual "all SPs + SP9" vs "SP9".
+- F7 LOW: RED tests behavior-named not file-anchored; Known Unknowns not carried.
+
+## Verification Handoff
+- Inspect first:
+- `/.recursive/run/106-client-neutral-model-effort-routing/02-to-be-plan.md`
+- Notes:
+- Controller applied all 7 repairs and recorded concrete run-105 region facts (80ad810e diff); re-audit expected PASS.
\ No newline at end of file
diff --git a/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-f4260377.md b/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-f4260377.md
new file mode 100644
index 000000000..d155efdd2
--- /dev/null
+++ b/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-f4260377.md
@@ -0,0 +1,74 @@
+# Subagent Action Record
+
+## Metadata
+- Subagent ID: `f4260377-b156-4e74-a253-b0e6275c52d1`
+- Run ID: `106-client-neutral-model-effort-routing`
+- Phase: 01 AS-IS
+- Purpose: `Independent phase-audit of 01-as-is.md`
+- Execution Mode: `in-session subagent (read-only)`
+- Timestamp: `2026-10-04T01:40:00Z`
+- Action Record Path: `/.recursive/run/106-client-neutral-model-effort-routing/subagents/auditor-f4260377.md`
+
+## Inputs Provided
+- Current Artifact: `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`
+- Artifact Content Hash: `b450373fb4c7591da08df9fe67c6e3984ea52531d0677bace26e1b0fb8178188`
+- Upstream Artifacts: `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`, `/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md`
+- Addenda: none
+- Diff Basis: `git diff --name-only 701b8b8fc0b0eeebdfe818b757f5702f50021488`
+- Code Refs: `/role-model-router/apps/runtime-host-bridge/src/index.ts`, `/role-model-router/packages/core/src/router.ts`, `/role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`
+- Memory Refs: none
+- Audit / Task Questions: verify every R1-R15 current-state and gap claim against the worktree source.
+
+## Routing
+- Router Used: `none`
+- Routed Role: `none`
+- Routed CLI: `none`
+- Routed Model: `none`
+- Routing Config Path: `none`
+- Routing Discovery Path: `none`
+- Routing Resolution Basis: `none`
+- Routing Fallback Reason: `none`
+- CLI Probe Summary: `none`
+- Prompt Bundle Path: `none`
+- Invocation Exit Code: `none`
+- Output Capture Paths: none
+
+## Claimed Actions Taken
+
+Verified every R1-R15 current-state and gap claim against the worktree source; confirmed worktree HEAD bfd01851 (Phase 0 on 701b8b8) with zero product-code drift; returned two citation repairs (F1, F2) and verified all other claims.
+
+## Claimed File Impact
+### Created
+- none
+### Modified
+- none
+### Reviewed
+- `/role-model-router/apps/runtime-host-bridge/src/index.ts`
+- `/role-model-router/packages/core/src/router.ts`
+- `/role-model-router/apps/runtime-host-bridge/src/scoring-strategy.ts`
+- `/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts`
+- `/role-model-router/packages/trace/src/lineage.ts`
+- `/role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts`
+### Relevant but Untouched
+- none
+
+## Claimed Artifact Impact
+### Read
+- `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/00-requirements.md`
+- `/.recursive/run/106-client-neutral-model-effort-routing/00-worktree.md`
+### Updated
+- none
+### Evidence Used
+- none
+
+## Claimed Findings
+- F1 [LOW-MODERATE]: R2 misattributed reasoning_effort_levels to effort-instance-identity.ts; actual declaration at packages/endpoint-registry/src/index.ts:63.
+- F2 [LOW]: R1/pointers/traceability cited index.ts:10569 (doc comment); actual call at :10573.
+- All other R1-R15 claims verified. Verdict: FAIL pending the two citation repairs, then re-audit PASS.
+
+## Verification Handoff
+- Inspect first:
+- `/.recursive/run/106-client-neutral-model-effort-routing/01-as-is.md`
+- Notes:
+- Controller applied F1 and F2; re-audit expected PASS.
\ No newline at end of file
diff --git a/packages/conformance/src/run106-effort-source-schema-compat.test.ts b/packages/conformance/src/run106-effort-source-schema-compat.test.ts
new file mode 100644
index 000000000..97199f002
--- /dev/null
+++ b/packages/conformance/src/run106-effort-source-schema-compat.test.ts
@@ -0,0 +1,29 @@
+import { readFile } from "node:fs/promises";
+import path from "node:path";
+import { fileURLToPath } from "node:url";
+
+import { describe, expect, test } from "vitest";
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const schemaDir = path.resolve(__dirname, "..", "..", "..", "protocol", "schemas");
+
+interface RouterDecisionSchema {
+ properties: {
+ effort_source: {
+ enum: string[];
+ };
+ };
+}
+
+describe("run 106 M-5: router-decision effort_source backward compatibility", () => {
+ test("keeps legacy client/variant/variant_coerced readable alongside canonical values", async () => {
+ const schema = JSON.parse(
+ await readFile(path.join(schemaDir, "router-decision.schema.json"), "utf8"),
+ ) as RouterDecisionSchema;
+ const values = schema.properties.effort_source.enum;
+ expect(values).toEqual(
+ expect.arrayContaining(["named", "disabled", "provider_default", "none"]),
+ );
+ expect(values).toEqual(expect.arrayContaining(["client", "variant", "variant_coerced"]));
+ });
+});
diff --git a/packages/conformance/src/run91-effort-schema.test.ts b/packages/conformance/src/run91-effort-schema.test.ts
index b3d42709d..30e4f319c 100644
--- a/packages/conformance/src/run91-effort-schema.test.ts
+++ b/packages/conformance/src/run91-effort-schema.test.ts
@@ -93,6 +93,7 @@ describe("Run 91 effort-instance protocol fields", () => {
catalogCapturedAt: null,
runtimeInventoryRevision: "run91",
},
+ effort: { union: ["medium"], portableIntersection: [] },
});
assertValid(routerDecision, {
routing_decision_id: "decision-1",
diff --git a/packages/protocol-types/src/generated.ts b/packages/protocol-types/src/generated.ts
index 9c410fca9..5e0af8f40 100644
--- a/packages/protocol-types/src/generated.ts
+++ b/packages/protocol-types/src/generated.ts
@@ -190,6 +190,10 @@ export interface DownstreamOpenAIDiscovery {
* @minItems 1
*/
models: [DownstreamOpenAIModelRecord, ...DownstreamOpenAIModelRecord[]];
+ effort: {
+ union: StringList;
+ portableIntersection: StringList;
+ };
setup: {
recommendedModel: string | null;
notes: string[];
@@ -352,7 +356,7 @@ export interface RoleDefinition {
export interface MetricEntry {
value: number;
- source: "measured" | "declared" | "default" | "catalog" | "benchmark";
+ source: "measured" | "declared" | "default" | "catalog" | "benchmark" | "borrowed";
raw?: {
[k: string]: unknown;
};
@@ -416,7 +420,38 @@ export interface RouterDecision {
}[];
chosen_endpoint_id: string;
reasoning_effort?: string | null;
- effort_source?: "none" | "client" | "variant" | "variant_coerced";
+ effort_source?:
+ | "named"
+ | "disabled"
+ | "provider_default"
+ | "none"
+ | "client"
+ | "variant"
+ | "variant_coerced";
+ effort_resolution?:
+ | "router_managed"
+ | "exact_primary"
+ | "exact_fallback_expanded"
+ | "unsupported_fallback"
+ | "strict_rejected"
+ | "equivalent_mapped";
+ effective_effort?: string | null;
+ requested_effort?: string | null;
+ requested_policy?: ("strict" | "preferred" | "router") | null;
+ effort_exact_arm_count_before_hard_eligibility?: number;
+ effort_exact_arm_count_after_hard_eligibility?: number;
+ effort_fallback_applied?: boolean;
+ /**
+ * Run 106 R8 (F5): records the non-inferiority promotion receipt - which arm outranked the weighted leader, the displaced leader, the rule thresholds, and whether it changed the weighted selection. Present only when the rule promoted a challenger.
+ */
+ non_inferiority_promotion?: {
+ promoted_endpoint_id: string;
+ displaced_endpoint_id: string;
+ quality_margin: number;
+ min_latency_advantage_ms: number;
+ min_cost_advantage_fraction: number;
+ changed_weighted_selection: boolean;
+ };
fallback_endpoint_ids: string[];
selection_reasons: (
| "BEST_TOTAL_SCORE"
@@ -440,6 +475,8 @@ export interface RouterDecision {
| "BENCHMARK_GROUP_SCORE"
| "BENCHMARK_FALLBACK_OVERALL_SCORE"
| "TELEMETRY_TASK_PERFORMANCE"
+ | "NON_INFERIOR_PROMOTION"
+ | "EFFORT_FALLBACK_APPLIED"
)[];
used_measured: boolean;
used_declared: boolean;
@@ -525,7 +562,14 @@ export interface TraceEvent {
request_id: string;
routing_decision_id: string;
reasoning_effort?: string | null;
- effort_source?: "none" | "client" | "variant" | "variant_coerced";
+ effort_source?:
+ | "named"
+ | "disabled"
+ | "provider_default"
+ | "none"
+ | "client"
+ | "variant"
+ | "variant_coerced";
timestamp_ms: number;
event_type:
| "router.decision.created"
@@ -546,7 +590,14 @@ export interface TraceSpan {
request_id: string;
routing_decision_id: string;
reasoning_effort?: string | null;
- effort_source?: "none" | "client" | "variant" | "variant_coerced";
+ effort_source?:
+ | "named"
+ | "disabled"
+ | "provider_default"
+ | "none"
+ | "client"
+ | "variant"
+ | "variant_coerced";
span_type:
| "router.eligibility"
| "router.scoring"
@@ -577,7 +628,14 @@ export interface UsageEvent {
endpoint_id: string;
model_id?: string;
reasoning_effort?: string | null;
- effort_source?: "none" | "client" | "variant" | "variant_coerced";
+ effort_source?:
+ | "named"
+ | "disabled"
+ | "provider_default"
+ | "none"
+ | "client"
+ | "variant"
+ | "variant_coerced";
package_id?: string;
provider_kind: string;
tokens_in: number;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 498d98284..8fb4fc71d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -563,6 +563,9 @@ importers:
'@role-model-router/adapter-execution':
specifier: workspace:*
version: link:../adapter-execution
+ '@role-model-router/core':
+ specifier: workspace:*
+ version: link:../core
'@role-model-router/profile-aggregator':
specifier: workspace:*
version: link:../profile-aggregator
@@ -592,6 +595,9 @@ importers:
'@role-model-router/catalog':
specifier: workspace:*
version: link:../catalog
+ '@role-model-router/core':
+ specifier: workspace:*
+ version: link:../core
'@role-model-router/profile-aggregator':
specifier: workspace:*
version: link:../profile-aggregator
@@ -612,6 +618,9 @@ importers:
role-model-router/packages/trace:
dependencies:
+ '@role-model-router/core':
+ specifier: workspace:*
+ version: link:../core
'@role-model/protocol-types':
specifier: workspace:*
version: link:../../../packages/protocol-types
diff --git a/protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json b/protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json
index 93a0cd979..c2b4bac15 100644
--- a/protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json
+++ b/protocol/fixtures/downstream-openai/downstream-openai-discovery-basic.json
@@ -189,5 +189,9 @@
"catalogVersion": "1",
"catalogCapturedAt": "2026-06-22T00:00:00.000Z",
"runtimeInventoryRevision": "fixture-revision"
+ },
+ "effort": {
+ "union": ["low", "high"],
+ "portableIntersection": []
}
}
diff --git a/protocol/schemas/downstream-openai-discovery.schema.json b/protocol/schemas/downstream-openai-discovery.schema.json
index f4ce5982d..73c03d57e 100644
--- a/protocol/schemas/downstream-openai-discovery.schema.json
+++ b/protocol/schemas/downstream-openai-discovery.schema.json
@@ -13,6 +13,7 @@
"endpoints",
"authentication",
"models",
+ "effort",
"setup",
"freshness"
],
@@ -53,6 +54,15 @@
"minItems": 1,
"items": { "$ref": "#/$defs/DownstreamOpenAIModelRecord" }
},
+ "effort": {
+ "type": "object",
+ "additionalProperties": false,
+ "required": ["union", "portableIntersection"],
+ "properties": {
+ "union": { "$ref": "#/$defs/StringList" },
+ "portableIntersection": { "$ref": "#/$defs/StringList" }
+ }
+ },
"setup": {
"type": "object",
"additionalProperties": false,
diff --git a/protocol/schemas/router-decision.schema.json b/protocol/schemas/router-decision.schema.json
index 3a6991b26..af999d7b8 100644
--- a/protocol/schemas/router-decision.schema.json
+++ b/protocol/schemas/router-decision.schema.json
@@ -117,7 +117,53 @@
"reasoning_effort": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
"effort_source": {
"type": "string",
- "enum": ["none", "client", "variant", "variant_coerced"]
+ "enum": [
+ "named",
+ "disabled",
+ "provider_default",
+ "none",
+ "client",
+ "variant",
+ "variant_coerced"
+ ]
+ },
+ "effort_resolution": {
+ "type": "string",
+ "enum": [
+ "router_managed",
+ "exact_primary",
+ "exact_fallback_expanded",
+ "unsupported_fallback",
+ "strict_rejected",
+ "equivalent_mapped"
+ ]
+ },
+ "effective_effort": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
+ "requested_effort": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
+ "requested_policy": { "type": ["string", "null"], "enum": ["strict", "preferred", "router"] },
+ "effort_exact_arm_count_before_hard_eligibility": { "type": "integer", "minimum": 0 },
+ "effort_exact_arm_count_after_hard_eligibility": { "type": "integer", "minimum": 0 },
+ "effort_fallback_applied": { "type": "boolean" },
+ "non_inferiority_promotion": {
+ "description": "Run 106 R8 (F5): records the non-inferiority promotion receipt - which arm outranked the weighted leader, the displaced leader, the rule thresholds, and whether it changed the weighted selection. Present only when the rule promoted a challenger.",
+ "type": "object",
+ "additionalProperties": false,
+ "required": [
+ "promoted_endpoint_id",
+ "displaced_endpoint_id",
+ "quality_margin",
+ "min_latency_advantage_ms",
+ "min_cost_advantage_fraction",
+ "changed_weighted_selection"
+ ],
+ "properties": {
+ "promoted_endpoint_id": { "type": "string" },
+ "displaced_endpoint_id": { "type": "string" },
+ "quality_margin": { "type": "number" },
+ "min_latency_advantage_ms": { "type": "number" },
+ "min_cost_advantage_fraction": { "type": "number" },
+ "changed_weighted_selection": { "type": "boolean" }
+ }
},
"fallback_endpoint_ids": { "type": "array", "items": { "type": "string" } },
"selection_reasons": {
@@ -145,7 +191,9 @@
"BENCHMARK_ROLE_SCORE",
"BENCHMARK_GROUP_SCORE",
"BENCHMARK_FALLBACK_OVERALL_SCORE",
- "TELEMETRY_TASK_PERFORMANCE"
+ "TELEMETRY_TASK_PERFORMANCE",
+ "NON_INFERIOR_PROMOTION",
+ "EFFORT_FALLBACK_APPLIED"
]
}
},
@@ -204,7 +252,7 @@
"value": { "type": "number", "minimum": 0, "maximum": 1 },
"source": {
"type": "string",
- "enum": ["measured", "declared", "default", "catalog", "benchmark"]
+ "enum": ["measured", "declared", "default", "catalog", "benchmark", "borrowed"]
},
"raw": {
"type": "object",
diff --git a/protocol/schemas/trace-event.schema.json b/protocol/schemas/trace-event.schema.json
index 7cecc78ad..7045f810b 100644
--- a/protocol/schemas/trace-event.schema.json
+++ b/protocol/schemas/trace-event.schema.json
@@ -22,7 +22,15 @@
"reasoning_effort": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
"effort_source": {
"type": "string",
- "enum": ["none", "client", "variant", "variant_coerced"]
+ "enum": [
+ "named",
+ "disabled",
+ "provider_default",
+ "none",
+ "client",
+ "variant",
+ "variant_coerced"
+ ]
},
"timestamp_ms": { "type": "integer", "minimum": 0 },
"event_type": {
diff --git a/protocol/schemas/trace-span.schema.json b/protocol/schemas/trace-span.schema.json
index db1a79947..b09fbe961 100644
--- a/protocol/schemas/trace-span.schema.json
+++ b/protocol/schemas/trace-span.schema.json
@@ -23,7 +23,15 @@
"reasoning_effort": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
"effort_source": {
"type": "string",
- "enum": ["none", "client", "variant", "variant_coerced"]
+ "enum": [
+ "named",
+ "disabled",
+ "provider_default",
+ "none",
+ "client",
+ "variant",
+ "variant_coerced"
+ ]
},
"span_type": {
"type": "string",
diff --git a/protocol/schemas/usage-event.schema.json b/protocol/schemas/usage-event.schema.json
index 75263932f..40cf1445d 100644
--- a/protocol/schemas/usage-event.schema.json
+++ b/protocol/schemas/usage-event.schema.json
@@ -28,7 +28,15 @@
"reasoning_effort": { "type": ["string", "null"], "minLength": 1, "maxLength": 128 },
"effort_source": {
"type": "string",
- "enum": ["none", "client", "variant", "variant_coerced"]
+ "enum": [
+ "named",
+ "disabled",
+ "provider_default",
+ "none",
+ "client",
+ "variant",
+ "variant_coerced"
+ ]
},
"package_id": { "type": "string" },
"provider_kind": { "type": "string" },
diff --git a/role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts b/role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts
index 46b2a4e1b..669b78ab9 100644
--- a/role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts
+++ b/role-model-router/apps/runtime-host-bridge/src/benchmark-summary.ts
@@ -166,6 +166,13 @@ export interface BenchmarkPreferences {
export interface BenchmarkCapability {
readonly evidenceSource: "run-artifact" | "profile-derived";
readonly overallScore: number | null;
+ /**
+ * Run 106 R5 (producer): borrowed cross-effort score from a sibling fixed-effort arm of the same
+ * model/provider. Present only on a provider-default arm that has no exact benchmark evidence of its
+ * own; `overallScore` stays null so the router never treats it as exact benchmark evidence. The
+ * router-side `resolveBorrowedQualityPrior` applies the symmetric regression toward neutral.
+ */
+ readonly relatedEffortOverallScore?: number | null;
readonly scoresByBucket: Partial<
Record<"easy" | "medium" | "hard", { readonly score: number; readonly cases?: number }>
>;
diff --git a/role-model-router/apps/runtime-host-bridge/src/cli.ts b/role-model-router/apps/runtime-host-bridge/src/cli.ts
index aaefc81a6..55b113199 100644
--- a/role-model-router/apps/runtime-host-bridge/src/cli.ts
+++ b/role-model-router/apps/runtime-host-bridge/src/cli.ts
@@ -8871,9 +8871,9 @@ export async function main(): Promise {
phase: "prepared",
attemptToken: replayAttemptToken,
});
- // A candidate without a reasoning effort is captured with `none`, not
- // `variant`: the durable capture contract couples a null effort to the
- // `none` source, and a mixed pair is rejected at the capture boundary.
+ // A candidate without a reasoning effort is captured with `none`, not `variant`:
+ // the durable capture contract couples a null effort to the `none` source, and a
+ // mixed pair is rejected at the capture boundary.
const preparedEffort =
typeof candidate.reasoningEffort === "string" && candidate.reasoningEffort
? { reasoningEffort: candidate.reasoningEffort, effortSource: "variant" as const }
diff --git a/role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts b/role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts
index 6d7c32dff..e30fc4fb6 100644
--- a/role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts
+++ b/role-model-router/apps/runtime-host-bridge/src/downstream-openai-discovery.ts
@@ -1,6 +1,7 @@
import { createHash } from "node:crypto";
import type { NormalizedCatalog } from "@role-model-router/catalog";
+import { computeEffortUnionAndIntersection } from "@role-model-router/core";
import type { EndpointRegistryResult } from "@role-model-router/endpoint-registry";
import {
@@ -118,6 +119,15 @@ export interface DownstreamOpenAIDiscoveryResponse {
readonly recommendedModel: string | null;
readonly notes: readonly string[];
};
+ /**
+ * Run 106 R9: the pool-wide effort union (every named effort advertised by an executable arm)
+ * and the portable intersection (named efforts every model can execute). An empty intersection is
+ * valid and does not hide usable union levels.
+ */
+ readonly effort: {
+ readonly union: readonly string[];
+ readonly portableIntersection: readonly string[];
+ };
readonly freshness: {
readonly generatedAt: string;
readonly catalogVersion: string;
@@ -225,6 +235,36 @@ function buildEndpointIdsByModelId(registry: EndpointRegistryResult): Map();
+ for (const endpoint of registry.endpoints) {
+ const modelId = endpoint.identity.model_id;
+ const list = byModelId.get(modelId) ?? [];
+ const effort = endpoint.identity.reasoning_effort;
+ const fixedEffort = typeof effort === "string" && effort.length > 0 ? effort : null;
+ list.push(fixedEffort);
+ if (fixedEffort === null) {
+ for (const level of endpoint.declared.reasoning_effort_levels ?? []) {
+ const trimmed = level.trim();
+ if (trimmed) {
+ list.push(trimmed);
+ }
+ }
+ }
+ byModelId.set(modelId, list);
+ }
+ return [...byModelId.values()].map((list) => [...new Set(list)]);
+}
+
/**
* A routing alias is only allowed to advertise an effort that it can select as
* a concrete configured endpoint instance. Catalog support describes what a
@@ -610,6 +650,9 @@ export function createDownstreamOpenAIDiscovery(
}
const models = modelRecords.sort((left, right) => compareText(left.id, right.id));
+ const effortProjection = computeEffortUnionAndIntersection({
+ modelEfforts: buildModelEffortLists(input.registry),
+ });
const recommendedModel =
(input.recommendedModelId && models.some((model) => model.id === input.recommendedModelId)
? input.recommendedModelId
@@ -638,6 +681,10 @@ export function createDownstreamOpenAIDiscovery(
note: "Inbound bearer validation is not enforced yet. If a downstream client requires a token field, use this placeholder value.",
},
models,
+ effort: {
+ union: effortProjection.union,
+ portableIntersection: effortProjection.portableIntersection,
+ },
setup: {
recommendedModel,
notes: [
diff --git a/role-model-router/apps/runtime-host-bridge/src/index.ts b/role-model-router/apps/runtime-host-bridge/src/index.ts
index 4fe13f7d5..532dbdefc 100644
--- a/role-model-router/apps/runtime-host-bridge/src/index.ts
+++ b/role-model-router/apps/runtime-host-bridge/src/index.ts
@@ -24,7 +24,7 @@ import {
type NormalizedCatalog,
type NormalizedCatalogModel,
type PricingHints,
- resolveReasoningEffortLevels,
+ resolveAdapterGatedReasoningEfforts,
} from "@role-model-router/catalog";
import { assembleContextEnvelope } from "@role-model-router/context-envelope";
import {
@@ -32,6 +32,7 @@ import {
supportsCapabilityRequirement,
taxonomyManifest,
} from "@role-model-router/core";
+import type { EffortResolution } from "@role-model-router/core";
import type { EndpointRegistryResult } from "@role-model-router/endpoint-registry";
import {
type RegistrySources,
@@ -43,6 +44,7 @@ import { ProcessSupervisor } from "@role-model-router/process-supervisor";
import {
type ObservedPerformanceSample,
aggregateOperationalPerformanceSamples,
+ resolveRelatedEffortOverallScore,
resolveRoutingBenchmarkQuality,
} from "@role-model-router/profile-aggregator";
import {
@@ -66,7 +68,8 @@ import { createOpenAIProviderAdapter } from "@role-model-router/provider-openai"
import { createRetrievalReceipt } from "@role-model-router/retrieval-receipt";
import {
type RuntimeCapturePolicy,
- type RuntimeEffortSource,
+ type RuntimeEffortReceipt,
+ type RuntimeEffortSourceValue,
type RuntimeExecutionCooldownReceipt,
type RuntimeExecutionFailedAttemptReceipt,
type RuntimeObservationBundle,
@@ -245,6 +248,7 @@ import {
evaluateBenchmarkTargetEligibility,
} from "./benchmark-start-guards.js";
import {
+ type BenchmarkCapability,
buildBenchmarkCapabilityForEndpoint,
listBenchmarkRuns,
readBenchmarkPreferences,
@@ -366,41 +370,11 @@ import {
rewriteUnifiedRuntimeConfigController,
} from "./unified-runtime-config.js";
-const REASONING_EFFORT_SERIALIZER_VERSION_BY_ADAPTER = new Map([
- ["ai-sdk-openai-compatible", "run91.openai-compatible.reasoning-effort.v1"],
- ["litellm-proxy", "run91.openai-compatible.reasoning-effort.v1"],
- ["codex-subscription-responses", "run91.codex-responses.reasoning-effort.v1"],
- ["ai-sdk-anthropic", "run93.anthropic.thinking-budget-tokens.v1"],
-]);
-
-export function resolveAdapterGatedReasoningEfforts(input: {
- readonly providerId: string;
- readonly modelId: string;
- readonly capabilities: readonly string[];
- readonly catalogLevels: readonly string[];
- readonly adapterFamily: string | null;
-}): readonly string[] {
- const adapterFamily = input.adapterFamily;
- const version =
- adapterFamily === null
- ? undefined
- : REASONING_EFFORT_SERIALIZER_VERSION_BY_ADAPTER.get(adapterFamily);
- return resolveReasoningEffortLevels({
- providerId: input.providerId,
- modelId: input.modelId,
- capabilities: input.capabilities,
- reasoningEffortLevels: input.catalogLevels,
- reasoningOptionKinds: ["effort"],
- adapter:
- version && adapterFamily
- ? {
- family: adapterFamily,
- version,
- serializers: input.catalogLevels,
- }
- : null,
- });
-}
+// Run 106 H-1: the adapter-gated reasoning-effort resolver now lives in
+// @role-model-router/catalog (next to resolveReasoningEffortLevels) so both the
+// runtime-host-bridge activation path and the endpoint-registry arm expansion can
+// resolve the executable effort set from one source of truth.
+export { resolveAdapterGatedReasoningEfforts } from "@role-model-router/catalog";
function markPhase(label: string): void {
if (process.env.ROLE_MODEL_PHASE_TIMING === "1") {
@@ -438,14 +412,27 @@ export function resolveEndpointExecutionEffort(input: {
readonly executionRequest: RuntimeExecutionRequest;
}): {
readonly executionRequest: RuntimeExecutionRequest;
- readonly receipt: {
- readonly reasoningEffort: string | null;
- readonly effortSource: RuntimeEffortSource;
- };
+ readonly receipt: RuntimeEffortReceipt;
} {
const fixedEffort = input.fixedEffort?.trim() || null;
const clientEffort = input.executionRequest.reasoning?.effort?.trim() || null;
if (fixedEffort === null) {
+ const clientEffortSource = input.executionRequest.reasoning?.effortSource;
+ if (
+ clientEffortSource === "disabled" ||
+ (clientEffort !== null && isDisabledReasoningEffort(clientEffort))
+ ) {
+ const { reasoning: _clientReasoning, ...executionRequestWithoutReasoning } =
+ input.executionRequest;
+ return {
+ executionRequest: executionRequestWithoutReasoning,
+ receipt: {
+ reasoningEffort: null,
+ effortSource: "none",
+ coerced: false,
+ },
+ };
+ }
const declaredEffortLevels = new Set(
(input.declaredEffortLevels ?? [])
.map((level) => level.trim())
@@ -457,6 +444,7 @@ export function resolveEndpointExecutionEffort(input: {
receipt: {
reasoningEffort: clientEffort,
effortSource: "client",
+ coerced: false,
},
};
}
@@ -472,9 +460,11 @@ export function resolveEndpointExecutionEffort(input: {
receipt: {
reasoningEffort: null,
effortSource: "none",
+ coerced: false,
},
};
}
+ const coerced = clientEffort !== null && clientEffort !== fixedEffort;
return {
executionRequest: {
...input.executionRequest,
@@ -485,8 +475,8 @@ export function resolveEndpointExecutionEffort(input: {
},
receipt: {
reasoningEffort: fixedEffort,
- effortSource:
- clientEffort !== null && clientEffort !== fixedEffort ? "variant_coerced" : "variant",
+ effortSource: coerced ? "variant_coerced" : "variant",
+ coerced,
},
};
}
@@ -967,19 +957,102 @@ function isOpenAIChatCompletionsMessage(
);
}
+export type NormalizedEffortPolicy = "strict" | "preferred" | "router";
+export type ClientEffortSource = "named" | "disabled" | "none";
+
+function isDisabledReasoningEffort(effort: string | undefined): boolean {
+ const trimmed = effort?.trim().toLowerCase();
+ return trimmed === "none" || trimmed === "off";
+}
+
+export function normalizeReasoningEffortPolicy(
+ effort: string | undefined,
+ explicitPolicy: string | undefined,
+): { effort: string | undefined; policy: NormalizedEffortPolicy; source: ClientEffortSource } {
+ const disabled = isDisabledReasoningEffort(effort);
+ const effectiveEffort = disabled ? undefined : effort;
+ const policy =
+ normalizeEffortPolicyValue(explicitPolicy) ?? (effectiveEffort ? "preferred" : "router");
+ const source: ClientEffortSource = disabled ? "disabled" : effectiveEffort ? "named" : "none";
+ return { effort: effectiveEffort, policy, source };
+}
+
+export type EffortPolicyResolutionKind =
+ | "router_managed"
+ | "exact_primary"
+ | "exact_fallback_expanded"
+ | "unsupported_fallback"
+ | "strict_rejected"
+ | "equivalent_mapped";
+
+export function resolveEffortPolicy(input: {
+ readonly requestedEffort: string | undefined;
+ readonly policy: "strict" | "preferred" | "router";
+ readonly availableEfforts: readonly (string | null)[];
+}): { resolution: EffortPolicyResolutionKind; effectiveEffort: string | null } {
+ if (input.policy === "router") {
+ return { resolution: "router_managed", effectiveEffort: null };
+ }
+ if (input.requestedEffort === undefined) {
+ // strict with no requested effort is a contradiction: refuse rather than silently router-managing.
+ return input.policy === "strict"
+ ? { resolution: "strict_rejected", effectiveEffort: null }
+ : { resolution: "router_managed", effectiveEffort: null };
+ }
+ const hasExact = input.availableEfforts.includes(input.requestedEffort);
+ if (hasExact) {
+ // strict names only the exact arms as the primary pool; preferred keeps the exact arms primary while the rest of
+ // the pool stays eligible as a receipted fallback (R3: exact_primary vs exact_fallback_expanded).
+ return input.policy === "strict"
+ ? { resolution: "exact_primary", effectiveEffort: input.requestedEffort }
+ : { resolution: "exact_fallback_expanded", effectiveEffort: input.requestedEffort };
+ }
+ if (input.policy === "strict") {
+ return { resolution: "strict_rejected", effectiveEffort: null };
+ }
+ return { resolution: "unsupported_fallback", effectiveEffort: null };
+}
+
+function normalizeEffortPolicyValue(value: string | undefined): NormalizedEffortPolicy | undefined {
+ if (value === undefined) {
+ return undefined;
+ }
+ const trimmed = value.trim();
+ if (trimmed === "strict" || trimmed === "preferred" || trimmed === "router") {
+ return trimmed;
+ }
+ throw new BridgeHttpError(400, {
+ error: {
+ type: "routing_eligibility_error",
+ code: "invalid_effort_policy",
+ message: `Invalid effort_policy: ${value}`,
+ received: value,
+ },
+ });
+}
+
function readOpenAIReasoningRequest(
body: Pick,
): RuntimeExecutionRequest["reasoning"] | undefined {
if (typeof body.reasoning_effort === "string") {
+ const normalized = normalizeReasoningEffortPolicy(body.reasoning_effort, undefined);
return {
- effort: body.reasoning_effort,
+ ...(normalized.effort !== undefined ? { effort: normalized.effort } : {}),
+ effortPolicy: normalized.policy,
+ effortSource: normalized.source,
};
}
const reasoning = asPlainRecord(body.reasoning);
if (reasoning) {
+ const effort = typeof reasoning.effort === "string" ? reasoning.effort : undefined;
+ const explicitPolicy =
+ typeof reasoning.effort_policy === "string" ? reasoning.effort_policy : undefined;
+ const normalized = normalizeReasoningEffortPolicy(effort, explicitPolicy);
return {
- ...(typeof reasoning.effort === "string" ? { effort: reasoning.effort } : {}),
+ ...(normalized.effort !== undefined ? { effort: normalized.effort } : {}),
+ effortPolicy: normalized.policy,
+ effortSource: normalized.source,
raw: reasoning,
};
}
@@ -1199,6 +1272,8 @@ export interface BridgeExecutionPlan {
readonly routingRequest: Parameters[0]["request"];
readonly executionRequest: RuntimeExecutionRequest;
readonly routingModel?: RoutingModelSelection;
+ /** Run 106 R10: the effort policy resolution the host computed before narrowing the pool. */
+ readonly effortResolution?: EffortResolution;
readonly routingDiagnostics?: Pick<
RuntimeRoutingDiagnostics,
| "aliasResolution"
@@ -1240,6 +1315,9 @@ interface BridgeDifficultyRoutingContext {
readonly cacheInvalidated?: boolean;
readonly cacheInvalidationReasons?: readonly string[];
readonly fallbackReason?: string;
+ readonly classifierVersion?: string;
+ readonly decisiveFeatures?: readonly string[];
+ readonly features?: DifficultyFeatureSet;
readonly rubricSignals: DifficultyRoutingSignals;
};
}
@@ -1344,26 +1422,29 @@ function summarizeDifficultySignals(input: {
declaredToolCount: input.toolCount,
});
const userMessages = input.messages.filter((message) => message.role === "user");
- const combined = combineDifficultyMessageText(input.messages);
- const askModeBurdenSource = askMode
- ? combineLastUserDifficultyMessageText(input.messages)
- : combined;
+ /**
+ * Run 106 R7 (F4): current-turn signals are derived from the newest user turn only, so a trivial
+ * follow-up in a long coding session does not inherit the code/schema or constraint burden of the
+ * whole transcript. Conversation burden (history turn count + context tokens) still reflects the
+ * full session and is handled by the bounded/diminishing feature model in the classifier.
+ */
+ const currentTurnText = combineLastUserDifficultyMessageText(input.messages);
const instructionConstraintCount = countMatches(
- askModeBurdenSource.toLowerCase(),
+ currentTurnText.toLowerCase(),
/\b(must|should|need to|required|preserve|verify|strict|do not|don't|never|without|constraint|compatible|ensure|maintain|avoid|breaking|regression)\b/g,
);
const decompositionKeywordCount = countMatches(
- combined.toLowerCase(),
+ currentTurnText.toLowerCase(),
/\b(analyze|compare|iterate|plan|step|decompose|refactor|workflow|multi-step|across|identify|explain|investigate|debug|patch|regression)\b/g,
);
const codePathSignal =
/(?:^|[\s"'`])(?:[\w.-]+[\\/])+[\w.-]+\.(?:ts|tsx|js|jsx|py|rs|go|java|c|cc|cpp|cs|json|yaml|yml|md)\b/i.test(
- askModeBurdenSource,
+ currentTurnText,
);
const workspaceFileActionSignal =
/\b(file|folder|directory|workspace|repo|repository|symbol|exported)\b/i.test(
- askModeBurdenSource,
- ) && /\b(read|write|create|patch|edit|inspect|open|grep|search)\b/i.test(askModeBurdenSource);
+ currentTurnText,
+ ) && /\b(read|write|create|patch|edit|inspect|open|grep|search)\b/i.test(currentTurnText);
const effectiveToolCount = askMode ? 0 : input.toolCount;
const effectiveHistoryTurnCount = askMode ? userMessages.length : input.messages.length;
const effectiveContextTokens = askMode
@@ -1376,12 +1457,78 @@ function summarizeDifficultySignals(input: {
instructionConstraintCount,
decompositionKeywordCount,
codeOrSchemaBurden:
- /\b(code|diff|patch|refactor|schema|contract|validation|test)\b/i.test(askModeBurdenSource) ||
+ /\b(code|diff|patch|refactor|schema|contract|validation|test)\b/i.test(currentTurnText) ||
codePathSignal ||
workspaceFileActionSignal,
};
}
+/**
+ * Run 106 R7 (F4): the heuristic difficulty classifier's version. Receipts and the difficulty
+ * classification cache carry this value so a classification produced by an older classifier is
+ * refused rather than silently reused (see shouldInvalidateDifficultyClassifierVersion).
+ */
+export const DIFFICULTY_CLASSIFIER_VERSION = "run106-turn-aware-v1";
+
+export type DifficultyFeatureName =
+ | "currentTurnBurden"
+ | "conversationBurden"
+ | "operationRisk"
+ | "requiredQuality"
+ | "latencySensitivity";
+
+export interface DifficultyFeatureSet {
+ readonly currentTurnBurden: number;
+ readonly conversationBurden: number;
+ readonly operationRisk: number;
+ readonly requiredQuality: number;
+ readonly latencySensitivity: number;
+}
+
+/**
+ * Run 106 R7 (F4): turn-aware feature separation. Conversation burden (history + context) is
+ * bounded and diminishing - it contributes at most two points and never escalates further, so a
+ * long session cannot force "hard" on its own. Current-turn burden, operation risk and required
+ * quality are the upward forces; latency sensitivity (a short, single-turn interactive ask) pulls
+ * toward the cheap/fast end.
+ */
+export function computeDifficultyFeatures(signals: DifficultyRoutingSignals): DifficultyFeatureSet {
+ const currentTurnBurden =
+ (signals.instructionConstraintCount >= 5
+ ? 2
+ : signals.instructionConstraintCount >= 2
+ ? 1
+ : 0) +
+ (signals.decompositionKeywordCount >= 3 ? 2 : signals.decompositionKeywordCount >= 1 ? 1 : 0);
+ const conversationBurden =
+ (signals.historyTurnCount >= 2 ? 1 : 0) + (signals.contextTokens >= 10_000 ? 1 : 0);
+ const operationRisk =
+ (signals.toolCount >= 5 ? 3 : signals.toolCount >= 2 ? 2 : signals.toolCount === 1 ? 1 : 0) +
+ (signals.codeOrSchemaBurden ? 2 : 0);
+ const requiredQuality =
+ signals.instructionConstraintCount >= 5 ? 2 : signals.instructionConstraintCount >= 2 ? 1 : 0;
+ const latencySensitivity = signals.historyTurnCount <= 1 && signals.contextTokens < 2_000 ? 1 : 0;
+ return {
+ currentTurnBurden,
+ conversationBurden,
+ operationRisk,
+ requiredQuality,
+ latencySensitivity,
+ };
+}
+
+/**
+ * Run 106 R7 (F4): cache invalidation follows the revised features. A cached classification whose
+ * classifier version differs from the current one (including a pre-versioning cache entry, which is
+ * undefined) is materially stale and must be reclassified.
+ */
+export function shouldInvalidateDifficultyClassifierVersion(
+ cachedClassifierVersion: string | undefined,
+ currentClassifierVersion: string,
+): boolean {
+ return cachedClassifierVersion !== currentClassifierVersion;
+}
+
export function classifyDifficultyFromSignals(input: {
readonly signals: DifficultyRoutingSignals;
readonly classifier?: UnifiedRuntimeDifficultyClassifierConfig;
@@ -1389,87 +1536,71 @@ export function classifyDifficultyFromSignals(input: {
readonly difficulty: UnifiedRuntimeDifficultyBucket;
readonly fallbackApplied: boolean;
readonly fallbackReason?: string;
+ readonly features: DifficultyFeatureSet;
+ readonly decisiveFeatures: readonly DifficultyFeatureName[];
} {
+ const features = computeDifficultyFeatures(input.signals);
if (input.signals.historyTurnCount === 0) {
return {
difficulty: input.classifier?.fallbackDifficulty ?? "hard",
fallbackApplied: true,
fallbackReason: "missing-request-content",
+ features,
+ decisiveFeatures: [],
};
}
+ /**
+ * Run 106 R7 (F4) documented risk rule: a current-turn tool-using code/schema operation is
+ * materially risky and stays hard. This replaces the pre-SP5 unconditional toolCount > 0 &&
+ * codeOrSchemaBurden => hard saturation: codeOrSchemaBurden is now computed from the current
+ * turn only (see summarizeDifficultySignals), so a trivial follow-up in a long coding session has
+ * codeOrSchemaBurden === false and does not reach this branch, while genuinely risky
+ * tool/code/schema work still does.
+ */
if (input.signals.toolCount > 0 && input.signals.codeOrSchemaBurden) {
return {
difficulty: "hard",
fallbackApplied: false,
+ features,
+ decisiveFeatures: ["operationRisk"],
};
}
- let score = 0;
- // Run 98 addendum 32 S3 (external audit §6): the rubric saturated because `contextTokens >= 2000`,
- // `toolCount >= 2` and `historyTurnCount >= 4` - worth 8 points together, already "hard" - are true
- // for essentially every agent session, so a 562K-token tool-heavy session shared a bucket with a
- // 2K-token one and the gate stopped selecting. The context contribution is graded across the observed
- // range (live `contextTokens` p50 = 130, p95 = 450,732) and the tool/history steps keep climbing
- // instead of stopping at the first rung.
- if (input.signals.contextTokens >= 200_000) {
- score += 5;
- } else if (input.signals.contextTokens >= 50_000) {
- score += 4;
- } else if (input.signals.contextTokens >= 10_000) {
- score += 3;
- } else if (input.signals.contextTokens >= 2_000) {
- score += 2;
- } else if (input.signals.contextTokens >= 600) {
- score += 1;
- }
- if (input.signals.toolCount >= 5) {
- score += 3;
- } else if (input.signals.toolCount >= 2) {
- score += 2;
- } else if (input.signals.toolCount === 1) {
- score += 1;
- }
- if (input.signals.historyTurnCount >= 16) {
- score += 3;
- } else if (input.signals.historyTurnCount >= 6) {
- score += 2;
- } else if (input.signals.historyTurnCount >= 2) {
- score += 1;
- }
- if (input.signals.instructionConstraintCount >= 5) {
- score += 2;
- } else if (input.signals.instructionConstraintCount >= 2) {
- score += 1;
- }
- if (input.signals.decompositionKeywordCount >= 3) {
- score += 2;
- } else if (input.signals.decompositionKeywordCount >= 1) {
- score += 1;
- }
- if (input.signals.codeOrSchemaBurden) {
- score += 2;
- }
- if (input.signals.codeOrSchemaBurden && input.signals.instructionConstraintCount >= 3) {
- score += 1;
+ // Turn-aware rubric: conversation burden is bounded/diminishing (max +2 via the feature model), so
+ // it cannot saturate hard on its own; current-turn burden, operation risk and required quality are
+ // the decisive upward forces and latency sensitivity (a short interactive ask) pulls toward easy.
+ const score =
+ features.currentTurnBurden +
+ features.conversationBurden +
+ features.operationRisk +
+ features.requiredQuality -
+ features.latencySensitivity;
+
+ const decisiveFeatures: DifficultyFeatureName[] = [];
+ if (features.currentTurnBurden >= 2) {
+ decisiveFeatures.push("currentTurnBurden");
+ }
+ if (features.conversationBurden >= 2) {
+ decisiveFeatures.push("conversationBurden");
+ }
+ if (features.operationRisk >= 2) {
+ decisiveFeatures.push("operationRisk");
+ }
+ if (features.requiredQuality >= 2) {
+ decisiveFeatures.push("requiredQuality");
+ }
+ if (features.latencySensitivity >= 1) {
+ decisiveFeatures.push("latencySensitivity");
}
if (score >= 7) {
- return {
- difficulty: "hard",
- fallbackApplied: false,
- };
+ return { difficulty: "hard", fallbackApplied: false, features, decisiveFeatures };
}
if (score >= 3) {
- return {
- difficulty: "medium",
- fallbackApplied: false,
- };
+ return { difficulty: "medium", fallbackApplied: false, features, decisiveFeatures };
}
- return {
- difficulty: "easy",
- fallbackApplied: false,
- };
+ return { difficulty: "easy", fallbackApplied: false, features, decisiveFeatures };
}
function createDifficultyFallbackResult(input: {
@@ -1481,7 +1612,10 @@ function createDifficultyFallbackResult(input: {
difficulty: input.classifier?.fallbackDifficulty ?? "hard",
fallbackApplied: true,
fallbackReason: input.reason,
+ classifierVersion: DIFFICULTY_CLASSIFIER_VERSION,
rubricSignals: input.signals,
+ features: computeDifficultyFeatures(input.signals),
+ decisiveFeatures: [],
};
}
@@ -2231,6 +2365,11 @@ function maybeApplyDifficultyRouting(input: {
difficulty: classified.difficulty,
strategy,
fallbackApplied: classified.fallbackApplied,
+ classifierVersion: DIFFICULTY_CLASSIFIER_VERSION,
+ ...(classified.decisiveFeatures?.length
+ ? { decisiveFeatures: classified.decisiveFeatures }
+ : {}),
+ ...(classified.features ? { features: classified.features } : {}),
...(classified.cacheHit ? { cacheHit: true } : {}),
...(classified.cacheInvalidated ? { cacheInvalidated: true } : {}),
...(classified.cacheInvalidationReasons?.length
@@ -2268,21 +2407,93 @@ function mergeCapabilityList(
return merged;
}
+function baseEndpointIdOfEndpoint(endpoint: {
+ readonly endpoint_id: string;
+ readonly reasoning_effort?: string | null;
+}): string {
+ const effort = endpoint.reasoning_effort?.trim() || null;
+ if (effort === null) {
+ return endpoint.endpoint_id;
+ }
+ const suffix = `-${encodeURIComponent(effort)}`;
+ return endpoint.endpoint_id.endsWith(suffix)
+ ? endpoint.endpoint_id.slice(0, -suffix.length)
+ : endpoint.endpoint_id;
+}
+
+/**
+ * Run 106 R2 (fallback dedup): a provider-default endpoint expands into effort arms that all
+ * resolve to the same downstream source. When one arm fails, falling back to a sibling arm would
+ * re-dispatch to that same source (and fail identically), so a provider-execution failure denies
+ * every endpoint in the arm's physical-source family, not just the failed arm id.
+ */
+function collectSharedSourceEndpointIds(
+ registry: EndpointRegistryResult,
+ endpointId: string,
+): readonly string[] {
+ const target = registry.endpoints.find(
+ (candidate) => candidate.identity.endpoint_id === endpointId,
+ );
+ const baseId = baseEndpointIdOfEndpoint(target?.identity ?? { endpoint_id: endpointId });
+ return registry.endpoints
+ .filter((candidate) => baseEndpointIdOfEndpoint(candidate.identity) === baseId)
+ .map((candidate) => candidate.identity.endpoint_id);
+}
+
+/**
+ * Run 106 R6: a controller/advisory preference for a base model/endpoint expands deterministically
+ * to every already-eligible effort arm of that base endpoint. The expansion is bounded by
+ * `allowEndpoints` (it can never invent an effort arm), and a preference that already names a
+ * specific arm stays exact.
+ */
+export function expandPreferredEndpointIdsToEffortArms(input: {
+ readonly registry: EndpointRegistryResult;
+ readonly allowEndpoints: readonly string[];
+ readonly preferredEndpointIds: readonly string[];
+}): readonly string[] {
+ const allowed = new Set(input.allowEndpoints);
+ const baseIdByEndpointId = new Map();
+ for (const endpoint of input.registry.endpoints) {
+ if (!allowed.has(endpoint.identity.endpoint_id)) {
+ continue;
+ }
+ baseIdByEndpointId.set(
+ endpoint.identity.endpoint_id,
+ baseEndpointIdOfEndpoint(endpoint.identity),
+ );
+ }
+ const baseIds = new Set(baseIdByEndpointId.values());
+ const matched = new Set();
+ for (const preferredId of input.preferredEndpointIds) {
+ if (baseIds.has(preferredId)) {
+ for (const [endpointId, baseId] of baseIdByEndpointId) {
+ if (baseId === preferredId) {
+ matched.add(endpointId);
+ }
+ }
+ } else if (allowed.has(preferredId)) {
+ matched.add(preferredId);
+ }
+ }
+ return input.allowEndpoints.filter((endpointId) => matched.has(endpointId));
+}
+
function collectPreferredEndpointIds(
+ registry: EndpointRegistryResult,
allowEndpoints: readonly string[] | undefined,
preferredEndpointIds: readonly string[] | undefined,
): readonly string[] {
- const allowSet = new Set(allowEndpoints ?? []);
- const filtered: string[] = [];
- for (const endpointId of preferredEndpointIds ?? []) {
- if (allowSet.has(endpointId) && !filtered.includes(endpointId)) {
- filtered.push(endpointId);
- }
- }
- if (allowSet.size > 0 && filtered.length === allowSet.size) {
+ const allow = allowEndpoints ?? [];
+ const expanded = expandPreferredEndpointIdsToEffortArms({
+ registry,
+ allowEndpoints: allow,
+ preferredEndpointIds: preferredEndpointIds ?? [],
+ });
+ // When the preference already covers the whole eligible pool, it carries no selection signal.
+ if (allow.length > 0 && expanded.length === allow.length) {
return [];
}
- return filtered;
+ return expanded;
}
function isOpenAICodexSubscriptionEndpointId(endpointId: string): boolean {
@@ -2343,6 +2554,7 @@ function maybeApplyControllerRouting(input: {
readonly effectiveRoutingMode: RuntimeRoutingMode;
readonly pinWeights?: boolean;
readonly requestedModel: string;
+ readonly registry: EndpointRegistryResult;
readonly modelAliases: readonly UnifiedRuntimeModelAliasConfig[];
readonly routingRequest: Parameters[0]["request"];
readonly routingDiagnostics?: Pick<
@@ -2423,6 +2635,7 @@ function maybeApplyControllerRouting(input: {
knownCapabilities,
);
const preferredEndpointIds = collectPreferredEndpointIds(
+ input.registry,
input.routingRequest.allowEndpoints ?? [],
guidance.preferredEndpointIds,
);
@@ -4411,17 +4624,22 @@ function normalizeCacheContinuityKeyValue(value: string | undefined): string | u
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
}
-function toCacheContinuityScopeDescriptor(executionRequest: RuntimeExecutionRequest): {
+export function toCacheContinuityScopeDescriptor(executionRequest: RuntimeExecutionRequest): {
readonly scopeSource: CacheContinuityScopeSource;
readonly scopeKey: string;
readonly scopeId: string;
} | null {
+ // Run 106 R6: cache continuity is effort-aware. A prompt-cache key or session id is only a
+ // continuity scope within one effort arm, so the requested reasoning effort is folded into the
+ // scope id. Requests without a requested effort keep the historical effort-free key.
+ const effort = normalizeCacheContinuityKeyValue(executionRequest.reasoning?.effort);
+ const effortSuffix = effort ? `:effort:${effort}` : "";
const promptCacheKey = normalizeCacheContinuityKeyValue(executionRequest.promptCache?.key);
if (promptCacheKey) {
return {
scopeSource: "prompt_cache_key",
scopeKey: promptCacheKey,
- scopeId: `prompt_cache_key:${promptCacheKey}`,
+ scopeId: `prompt_cache_key:${promptCacheKey}${effortSuffix}`,
};
}
const sessionId = normalizeCacheContinuityKeyValue(executionRequest.sessionAffinity?.sessionId);
@@ -4429,7 +4647,7 @@ function toCacheContinuityScopeDescriptor(executionRequest: RuntimeExecutionRequ
return {
scopeSource: "session_affinity",
scopeKey: sessionId,
- scopeId: `session_affinity:${sessionId}`,
+ scopeId: `session_affinity:${sessionId}${effortSuffix}`,
};
}
return null;
@@ -5364,7 +5582,7 @@ function buildPreExecutionFailureObservation(input: {
readonly modelId: string;
readonly sourceType: "local" | "remote";
readonly reasoningEffort: string | null;
- readonly effortSource: RuntimeEffortSource;
+ readonly effortSource: RuntimeEffortSourceValue;
readonly requestOperation?: "chat" | "responses";
readonly error: unknown;
readonly latencyMs: number;
@@ -9215,6 +9433,38 @@ function collectConfiguredReasoningEfforts(
return [...levels].sort(compareText);
}
+/**
+ * The efforts this pool can execute as an exact arm. A fixed-effort endpoint is always an exact arm for its own
+ * level; a provider-default endpoint (no fixed effort) executes its declared levels. A fixed-effort endpoint's own
+ * declared levels are catalog metadata, not executable arms, so they are deliberately excluded - matching
+ * `selectReasoningEffortInstanceIds` (run 116) rather than the broader error-reporting set in
+ * `collectConfiguredReasoningEfforts`.
+ */
+function collectExecutableReasoningEfforts(
+ registry: EndpointRegistryResult,
+ allowEndpoints: readonly string[],
+): readonly string[] {
+ const allowed = new Set(allowEndpoints);
+ const levels = new Set();
+ for (const endpoint of registry.endpoints) {
+ if (!allowed.has(endpoint.identity.endpoint_id)) {
+ continue;
+ }
+ const fixedEffort = endpoint.identity.reasoning_effort?.trim();
+ if (fixedEffort) {
+ levels.add(fixedEffort);
+ continue;
+ }
+ for (const level of endpoint.declared.reasoning_effort_levels ?? []) {
+ const trimmed = level.trim();
+ if (trimmed) {
+ levels.add(trimmed);
+ }
+ }
+ }
+ return [...levels].sort(compareText);
+}
+
function throwReasoningEffortUnavailable(input: {
readonly requestedModel: string;
readonly requestedEffort: string;
@@ -9617,6 +9867,8 @@ export function classifyBridgeRoutePass(input: {
export interface ReasoningEffortPoolApplication {
readonly allowEndpoints: readonly string[];
readonly preferredEndpointIds: readonly string[];
+ readonly resolution: EffortPolicyResolutionKind;
+ readonly effectiveEffort: string | null;
}
/**
@@ -9643,11 +9895,13 @@ export function applyReasoningEffortToModelPool(input: {
readonly registry: EndpointRegistryResult;
readonly requestedModel: string;
readonly requestedEffort?: string | null;
+ readonly requestedPolicy?: "strict" | "preferred" | "router";
readonly allowEndpoints: readonly string[];
readonly preferredEndpointIds: readonly string[];
readonly requestedEndpointId?: string | null;
}): ReasoningEffortPoolApplication {
const requestedEffort = input.requestedEffort?.trim() || null;
+ const policy = input.requestedPolicy ?? (requestedEffort ? "preferred" : "router");
/**
* The client named an instance only when it used an endpoint row - as the requested model value or as the
* explicit `endpointId` request option. Everything else (an alias, a model id) names a pool.
@@ -9660,43 +9914,89 @@ export function applyReasoningEffortToModelPool(input: {
toLegacyCredentializedEndpointId(endpoint.identity.endpoint_id) === input.requestedModel,
);
if (instanceSelected) {
- return {
- allowEndpoints: filterRequestedModelPoolByReasoningEffort({
- registry: input.registry,
- requestedModel: input.requestedModel,
- requestedEffort,
- allowEndpoints: input.allowEndpoints,
- }),
- preferredEndpointIds: input.preferredEndpointIds,
- };
- }
- if (requestedEffort === null) {
- return {
+ const narrowedAllowEndpoints = filterRequestedModelPoolByReasoningEffort({
+ registry: input.registry,
+ requestedModel: input.requestedModel,
+ requestedEffort,
allowEndpoints: input.allowEndpoints,
+ });
+ return {
+ allowEndpoints: narrowedAllowEndpoints,
preferredEndpointIds: input.preferredEndpointIds,
+ resolution: narrowedAllowEndpoints.length > 0 ? "exact_primary" : "strict_rejected",
+ effectiveEffort: narrowedAllowEndpoints.length > 0 ? requestedEffort : null,
};
}
- const effortInstanceIds = selectReasoningEffortInstanceIds({
- registry: input.registry,
- allowEndpoints: input.allowEndpoints,
- requestedEffort,
+ const availableEfforts = collectExecutableReasoningEfforts(input.registry, input.allowEndpoints);
+ const resolved = resolveEffortPolicy({
+ requestedEffort: requestedEffort ?? undefined,
+ policy,
+ availableEfforts,
});
- if (effortInstanceIds.length === 0) {
- // An effort that names no instance in this pool is not executable at all, and it keeps the bounded
- // `reasoning_effort_unavailable` refusal the callers already raise on an empty pool (run 98). The pool rule is
- // about the pool's *membership*: an effort that does name instances may order them, never trim them.
- return {
- allowEndpoints: [],
- preferredEndpointIds: [],
- };
+ const effortInstanceIds =
+ requestedEffort === null
+ ? []
+ : selectReasoningEffortInstanceIds({
+ registry: input.registry,
+ allowEndpoints: input.allowEndpoints,
+ requestedEffort,
+ });
+ switch (resolved.resolution) {
+ case "router_managed":
+ // Router-managed: the effort hint is ignored and the whole pool is scored jointly.
+ return {
+ allowEndpoints: input.allowEndpoints,
+ preferredEndpointIds: input.preferredEndpointIds,
+ resolution: resolved.resolution,
+ effectiveEffort: resolved.effectiveEffort,
+ };
+ case "exact_primary":
+ // Exact-effort arms only; non-exact arms are ineligible.
+ return {
+ allowEndpoints: effortInstanceIds,
+ preferredEndpointIds: [],
+ resolution: resolved.resolution,
+ effectiveEffort: resolved.effectiveEffort,
+ };
+ case "exact_fallback_expanded":
+ // Preferred keeps the exact arms primary while the rest of the pool stays eligible as a receipted fallback.
+ return {
+ allowEndpoints: input.allowEndpoints,
+ preferredEndpointIds: [
+ ...effortInstanceIds,
+ ...input.preferredEndpointIds.filter(
+ (endpointId) => !effortInstanceIds.includes(endpointId),
+ ),
+ ],
+ resolution: resolved.resolution,
+ effectiveEffort: resolved.effectiveEffort,
+ };
+ case "strict_rejected":
+ // strict requires an exact arm; empty pool lets the caller raise reasoning_effort_unavailable.
+ return {
+ allowEndpoints: [],
+ preferredEndpointIds: [],
+ resolution: resolved.resolution,
+ effectiveEffort: resolved.effectiveEffort,
+ };
+ case "unsupported_fallback":
+ // preferred with zero exact arms -> unsupported_fallback: ignore the hint and router-manage the pool (R3/D5).
+ return {
+ allowEndpoints: input.allowEndpoints,
+ preferredEndpointIds: input.preferredEndpointIds,
+ resolution: resolved.resolution,
+ effectiveEffort: resolved.effectiveEffort,
+ };
+ case "equivalent_mapped":
+ // `resolveEffortPolicy` does not produce this without explicit, versioned provider equivalence (R3/OOS1);
+ // treated defensively as router-managed until an equivalence table exists.
+ return {
+ allowEndpoints: input.allowEndpoints,
+ preferredEndpointIds: input.preferredEndpointIds,
+ resolution: resolved.resolution,
+ effectiveEffort: resolved.effectiveEffort,
+ };
}
- return {
- allowEndpoints: input.allowEndpoints,
- preferredEndpointIds: [
- ...effortInstanceIds,
- ...input.preferredEndpointIds.filter((endpointId) => !effortInstanceIds.includes(endpointId)),
- ],
- };
}
function applyRequestedEndpointOverride(input: {
@@ -10611,6 +10911,7 @@ export function mapChatCompletionsRequest(
registry,
requestedModel: body.model,
requestedEffort: reasoning?.effort,
+ requestedPolicy: reasoning?.effortPolicy,
allowEndpoints: applyRequestedEndpointOverride({
requestedModel: body.model,
allowEndpoints: modelAllowEndpoints,
@@ -10734,6 +11035,7 @@ export function mapChatCompletionsRequest(
effectiveRoutingMode,
pinWeights: routingPosture?.pinWeights === true,
requestedModel: body.model,
+ registry,
modelAliases,
routingRequest: {
requestId,
@@ -10817,6 +11119,13 @@ export function mapChatCompletionsRequest(
...(typeof body.temperature === "number" ? { temperature: body.temperature } : {}),
},
...(effectiveRoutingModel ? { routingModel: effectiveRoutingModel } : {}),
+ effortResolution: {
+ resolution: effortAppliedToModelPool.resolution,
+ effectiveEffort: effortAppliedToModelPool.effectiveEffort,
+ requestedEffort: reasoning?.effort ?? null,
+ requestedPolicy: reasoning?.effortPolicy,
+ source: reasoning?.effortSource ?? (reasoning?.effort ? "named" : "none"),
+ },
routingDiagnostics: withAliasPostureBinding(
withStrategyProvenance(
rolePolicyExecution.routingDiagnostics,
@@ -10915,6 +11224,7 @@ export function mapResponsesRequest(
registry,
requestedModel: body.model,
requestedEffort: reasoning?.effort,
+ requestedPolicy: reasoning?.effortPolicy,
allowEndpoints: applyRequestedEndpointOverride({
requestedModel: body.model,
allowEndpoints: modelAllowEndpoints,
@@ -11014,6 +11324,7 @@ export function mapResponsesRequest(
effectiveRoutingMode,
pinWeights: routingPosture?.pinWeights === true,
requestedModel: body.model,
+ registry,
modelAliases,
routingRequest: {
requestId,
@@ -11093,6 +11404,13 @@ export function mapResponsesRequest(
...(typeof body.temperature === "number" ? { temperature: body.temperature } : {}),
},
...(effectiveRoutingModel ? { routingModel: effectiveRoutingModel } : {}),
+ effortResolution: {
+ resolution: effortAppliedToModelPool.resolution,
+ effectiveEffort: effortAppliedToModelPool.effectiveEffort,
+ requestedEffort: reasoning?.effort ?? null,
+ requestedPolicy: reasoning?.effortPolicy,
+ source: reasoning?.effortSource ?? (reasoning?.effort ? "named" : "none"),
+ },
routingDiagnostics: withAliasPostureBinding(
withStrategyProvenance(
rolePolicyExecution.routingDiagnostics,
@@ -20228,7 +20546,7 @@ export async function createRuntimeBridgeBackend(
readonly endpointId: string;
readonly modelId: string;
readonly reasoningEffort: string | null;
- readonly effortSource: RuntimeEffortSource;
+ readonly effortSource: RuntimeEffortSourceValue;
readonly taskType: string;
readonly inputTokens: number;
readonly outputTokens: number;
@@ -20310,13 +20628,16 @@ export async function createRuntimeBridgeBackend(
);
const fixedEffort = fallbackEndpoint?.identity.reasoning_effort?.trim() || null;
const requestedEffort = input.requestedEffort?.trim() || null;
+ const failureCoerced =
+ fixedEffort !== null && requestedEffort !== null && requestedEffort !== fixedEffort;
const failureEffort = {
reasoningEffort: fixedEffort,
effortSource: (fixedEffort === null
? "none"
- : requestedEffort !== null && requestedEffort !== fixedEffort
+ : failureCoerced
? "variant_coerced"
- : "variant") as RuntimeEffortSource,
+ : "variant") as RuntimeEffortSourceValue,
+ coerced: failureCoerced,
};
const failureObservation = buildPreExecutionFailureObservation({
requestId: input.requestId,
@@ -20343,6 +20664,7 @@ export async function createRuntimeBridgeBackend(
endpointId: input.endpointId,
reasoningEffort: failureEffort.reasoningEffort,
effortSource: failureEffort.effortSource,
+ effortCoerced: failureEffort.coerced,
modelId: input.modelId,
requestedModelId: input.modelId,
requestOperation: input.requestOperation,
@@ -23945,8 +24267,16 @@ export async function createRuntimeBridgeBackend(
return record.modelId ? [record.modelId] : [];
case "reasoningEffort":
return record.reasoningEffort ? [record.reasoningEffort] : [];
- case "effortSource":
- return record.effortSource ? [record.effortSource] : [];
+ case "effortSource": {
+ const raw = record.effortSource;
+ if (!raw) return [];
+ // Query-time projection (run 106 R4 readback): the occurrence/telemetry layer
+ // stores the binary vocabulary (client|variant|variant_coerced|none), while the
+ // analytics effortSource dimension presents the canonical four-state "named"
+ // value. Map the named-like legacy sources to "named"; pass "none" and any
+ // already-canonical value through unchanged.
+ return [raw === "client" || raw === "variant" || raw === "variant_coerced" ? "named" : raw];
+ }
case "providerId":
return record.providerId ? [record.providerId] : [];
case "providerKind":
@@ -24015,8 +24345,13 @@ export async function createRuntimeBridgeBackend(
}
if (dimension === "effortSource") {
const labels: Readonly> = {
+ // Canonical four-state vocabulary (run 106 R4/R10).
+ named: "Named effort",
+ disabled: "Reasoning disabled",
+ provider_default: "Provider default",
+ none: "Router managed",
+ // Historical readable values (pre-migration rows).
client: "Client requested",
- none: "Provider default",
variant: "Variant fixed",
variant_coerced: "Variant coerced",
fixed: "Endpoint fixed",
@@ -25933,7 +26268,7 @@ export async function createRuntimeBridgeBackend(
const portfolioByEndpointId = new Map(
benchmarkPortfolio.entries.map((entry) => [entry.endpointId, entry] as const),
);
- return Object.fromEntries(
+ const capabilitiesByEndpointId: Record = Object.fromEntries(
currentRegistry.endpoints.map((endpoint) => {
const endpointId = endpoint.identity.endpoint_id;
const profile = profilesByEndpointId[endpointId];
@@ -25950,6 +26285,61 @@ export async function createRuntimeBridgeBackend(
] as const;
}),
);
+ /**
+ * Run 106 R5 (producer): a provider-default arm has no effort-encoded benchmark key, so it falls
+ * to the neutral default even though a fixed-effort sibling of the same model/provider holds the
+ * only benchmark evidence. Borrow that sibling's exact score as a labeled related-effort prior:
+ * this arm's own `overallScore` stays null (never exact benchmark evidence) and the router-side
+ * `resolveBorrowedQualityPrior` applies the symmetric regression toward neutral.
+ */
+ const benchmarkEvidenceSubjects = currentRegistry.endpoints.map((endpoint) => {
+ const endpointId = endpoint.identity.endpoint_id;
+ const modelId = endpoint.identity.model_id;
+ return {
+ endpointId,
+ modelId,
+ providerId: currentModelsById.get(modelId)?.providerId ?? null,
+ reasoningEffort: endpoint.identity.reasoning_effort ?? null,
+ overallScore: capabilitiesByEndpointId[endpointId]?.overallScore ?? null,
+ } as const;
+ });
+ for (const endpoint of currentRegistry.endpoints) {
+ const endpointId = endpoint.identity.endpoint_id;
+ const capability = capabilitiesByEndpointId[endpointId];
+ if (typeof capability?.overallScore === "number") {
+ continue;
+ }
+ const relatedEffortOverallScore = resolveRelatedEffortOverallScore({
+ endpointId,
+ modelId: endpoint.identity.model_id,
+ providerId: currentModelsById.get(endpoint.identity.model_id)?.providerId ?? null,
+ reasoningEffort: endpoint.identity.reasoning_effort ?? null,
+ subjects: benchmarkEvidenceSubjects,
+ });
+ if (relatedEffortOverallScore === null) {
+ continue;
+ }
+ capabilitiesByEndpointId[endpointId] = {
+ ...(capability ?? {
+ evidenceSource: "profile-derived",
+ overallScore: null,
+ scoresByBucket: {},
+ benchmarkSamples: 0,
+ sampleCount: 0,
+ measuredAtMs: null,
+ freshnessScore: null,
+ lastRunId: null,
+ lastRunCompletedAtMs: null,
+ lastRunMode: null,
+ lastRunSuiteId: null,
+ judgeEndpointId: null,
+ judgeModelId: null,
+ profileRevision: null,
+ }),
+ relatedEffortOverallScore,
+ };
+ }
+ return capabilitiesByEndpointId;
};
const buildEffectiveEligibilitySnapshot = () => {
// A configured runtime instance is eligible only after its own durable
@@ -26623,6 +27013,7 @@ export async function createRuntimeBridgeBackend(
taskDefinitions: executionSnapshot.taskDefinitions,
roleBindings,
routingModel: plan.routingModel ?? executionSnapshot.routingModel ?? undefined,
+ ...(plan.effortResolution ? { effortResolution: plan.effortResolution } : {}),
...(advisoryConsideration ? { advisoryConsideration } : {}),
...(cacheContinuityRouteHints
? {
@@ -28158,7 +28549,14 @@ export async function createRuntimeBridgeBackend(
await persistRoutedProviderFailure(error);
throw error;
}
- deniedEndpointIds.push(error.endpointId);
+ for (const sharedSourceEndpointId of collectSharedSourceEndpointIds(
+ executionSnapshot.registry,
+ error.endpointId,
+ )) {
+ if (!deniedEndpointIds.includes(sharedSourceEndpointId)) {
+ deniedEndpointIds.push(sharedSourceEndpointId);
+ }
+ }
let nextRoute: ReturnType;
try {
nextRoute = routeExecutionRequest(deniedEndpointIds);
@@ -28423,6 +28821,7 @@ export async function createRuntimeBridgeBackend(
trafficClass: observedTrafficClass,
reasoningEffort: effectiveEffort.reasoningEffort,
effortSource: effectiveEffort.effortSource,
+ effortCoerced: effectiveEffort.coerced,
// Run 98 addendum 40 (L1): record the provider breakdown beside the historical header time,
// so telemetry can report what the client waited for instead of the provider's first byte.
latencyBreakdown: {
@@ -28898,6 +29297,12 @@ export async function createRuntimeBridgeBackend(
currentSignals: signals,
invalidation: cachePolicy.invalidation,
}),
+ ...(shouldInvalidateDifficultyClassifierVersion(
+ cachedClassification.classifierVersion,
+ DIFFICULTY_CLASSIFIER_VERSION,
+ )
+ ? (["classifier-version-change"] as const)
+ : []),
]
: [];
if (cachedClassification && cacheInvalidationReasons.length === 0) {
@@ -28908,6 +29313,11 @@ export async function createRuntimeBridgeBackend(
? { fallbackReason: cachedClassification.fallbackReason }
: {}),
cacheHit: true,
+ classifierVersion: cachedClassification.classifierVersion ?? DIFFICULTY_CLASSIFIER_VERSION,
+ ...(cachedClassification.decisiveFeatures
+ ? { decisiveFeatures: cachedClassification.decisiveFeatures }
+ : {}),
+ ...(cachedClassification.features ? { features: cachedClassification.features } : {}),
rubricSignals: signals,
};
}
@@ -28923,6 +29333,11 @@ export async function createRuntimeBridgeBackend(
...(classification.fallbackReason
? { fallbackReason: classification.fallbackReason }
: {}),
+ classifierVersion: DIFFICULTY_CLASSIFIER_VERSION,
+ ...(classification.decisiveFeatures
+ ? { decisiveFeatures: classification.decisiveFeatures }
+ : {}),
+ ...(classification.features ? { features: classification.features } : {}),
cachedAtMs: nowMs,
expiresAtMs: nowMs + cachePolicy.cacheTtlMs,
rubricSignals: signals,
diff --git a/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts b/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts
index 7a2a23c4c..64628f5bf 100644
--- a/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts
+++ b/role-model-router/apps/runtime-host-bridge/src/track-b-runtime.ts
@@ -140,7 +140,7 @@ export function extensionHostTiming(env: Record = pr
};
}
-import type { RuntimeEffortSource } from "@role-model-router/runtime-observability";
+import type { RuntimeEffortSourceValue } from "@role-model-router/runtime-observability";
import {
type GraphArtifactReference,
type LegacyArtifactWriteInput,
@@ -4235,7 +4235,7 @@ export interface TrackBPostObservationWorkItem extends Readonly>;
readonly occurrenceId?: string;
@@ -5236,9 +5236,9 @@ function outboxSchema(database: DatabaseSync): void {
model_id IS NULL
OR trim(model_id) = ''
OR effort_source IS NULL
- OR effort_source NOT IN ('none', 'client', 'variant', 'variant_coerced')
- OR (reasoning_effort IS NULL AND effort_source <> 'none')
- OR (reasoning_effort IS NOT NULL AND effort_source = 'none')
+ OR effort_source NOT IN ('named', 'disabled', 'provider_default', 'none', 'client', 'variant', 'variant_coerced')
+ OR (reasoning_effort IS NULL AND effort_source IN ('named', 'client', 'variant', 'variant_coerced'))
+ OR (reasoning_effort IS NOT NULL AND effort_source IN ('disabled', 'provider_default', 'none'))
)
`);
}
@@ -5639,7 +5639,7 @@ export function createTrackBPostObservationOutbox({
endpoint_id: string;
model_id: string | null;
reasoning_effort: string | null;
- effort_source: RuntimeEffortSource | null;
+ effort_source: RuntimeEffortSourceValue | null;
run88_correlation_json: string | null;
observation_json: string | null;
legacy_identity_missing: number;
@@ -7024,7 +7024,7 @@ export interface TrackBVariantIdentity {
readonly endpointId: string;
readonly modelId: string;
readonly reasoningEffort: string | null;
- readonly effortSource: RuntimeEffortSource;
+ readonly effortSource: RuntimeEffortSourceValue;
}
export type TrackBRouteAdvisoryState = "fresh" | "stale" | "unavailable";
@@ -8236,7 +8236,9 @@ async function appendTrackBRouteAdvisoryObservationExclusive(input: {
return next;
}
-const TRACK_B_EFFORT_SOURCES = new Set([
+// The occurrence/telemetry effort-source vocabulary. A persisted observation carries
+// `none` for a null reasoning effort and `client`/`variant`/`variant_coerced` for a named effort.
+const TRACK_B_EFFORT_SOURCES = new Set([
"none",
"client",
"variant",
@@ -8280,13 +8282,15 @@ function normalizeTrackBVariantIdentity(
const effortSource = observation.effortSource;
if (
typeof effortSource !== "string" ||
- !TRACK_B_EFFORT_SOURCES.has(effortSource as RuntimeEffortSource)
+ !TRACK_B_EFFORT_SOURCES.has(effortSource as RuntimeEffortSourceValue)
) {
throw new Error("persisted observation effort identity effortSource is invalid");
}
+ const namedLikeSource =
+ effortSource === "client" || effortSource === "variant" || effortSource === "variant_coerced";
if (
- (reasoningEffort === null && effortSource !== "none") ||
- (reasoningEffort !== null && effortSource === "none")
+ (reasoningEffort === null && namedLikeSource) ||
+ (reasoningEffort !== null && !namedLikeSource)
) {
throw new Error("persisted observation effort identity effort/source pair is inconsistent");
}
@@ -8305,7 +8309,7 @@ function normalizeTrackBVariantIdentity(
endpointId,
modelId,
reasoningEffort: reasoningEffort as string | null,
- effortSource: effortSource as RuntimeEffortSource,
+ effortSource: effortSource as RuntimeEffortSourceValue,
};
}
diff --git a/role-model-router/apps/runtime-host-bridge/test/index.test.ts b/role-model-router/apps/runtime-host-bridge/test/index.test.ts
index 2a463e646..cf1d49935 100644
--- a/role-model-router/apps/runtime-host-bridge/test/index.test.ts
+++ b/role-model-router/apps/runtime-host-bridge/test/index.test.ts
@@ -5706,7 +5706,7 @@ describe("runtime-host-bridge", () => {
expect(result.routingRequest.allowEndpoints).toEqual([
"moonshot.personal.primary.global.kimi-k2.5",
]);
- expect(result.routingDiagnostics?.difficultyRouting).toEqual({
+ expect(result.routingDiagnostics?.difficultyRouting).toMatchObject({
difficulty: "hard",
strategy: "quality",
fallbackApplied: false,
@@ -5798,7 +5798,7 @@ describe("runtime-host-bridge", () => {
expect(result.routingRequest.allowEndpoints).toEqual([
"moonshot.personal.primary.global.kimi-k2.5",
]);
- expect(result.routingDiagnostics?.difficultyRouting).toEqual({
+ expect(result.routingDiagnostics?.difficultyRouting).toMatchObject({
difficulty: "hard",
strategy: "quality",
fallbackApplied: false,
@@ -5883,7 +5883,7 @@ describe("runtime-host-bridge", () => {
expect(result.routingRequest.allowEndpoints).toEqual([
"moonshot.personal.primary.global.kimi-k2.5",
]);
- expect(result.routingDiagnostics?.difficultyRouting).toEqual({
+ expect(result.routingDiagnostics?.difficultyRouting).toMatchObject({
difficulty: "hard",
strategy: "quality",
fallbackApplied: false,
@@ -6617,6 +6617,8 @@ describe("runtime-host-bridge", () => {
});
expect(result.executionRequest.reasoning).toEqual({
effort: "high",
+ effortPolicy: "preferred",
+ effortSource: "named",
});
expect(result.executionRequest.continuation).toEqual({
previousResponseId: "resp_prev_001",
@@ -7042,6 +7044,8 @@ describe("runtime-host-bridge", () => {
expect(result.routingRequest.requiredCapabilities).toContain("reasoning.effort_control");
expect(result.executionRequest.reasoning).toEqual({
effort: "high",
+ effortPolicy: "preferred",
+ effortSource: "named",
});
});
@@ -16454,7 +16458,11 @@ describe("runtime-host-bridge", () => {
statusCode: 402,
adapterFamily: "ai-sdk-openai-compatible",
executionFamily: "remote-service",
- eligibleEndpointIds: [endpoint.endpointId],
+ eligibleEndpointIds: [
+ endpoint.endpointId,
+ `${endpoint.endpointId}-high`,
+ `${endpoint.endpointId}-max`,
+ ],
}),
);
expect(failureRow?.endpointId).not.toBe("routing.failed.pre-execution");
@@ -22172,21 +22180,22 @@ describe("runtime-host-bridge", () => {
granularity: "hour",
metrics: ["requestCount"],
breakdown: "reasoningEffort",
- filters: { effortSources: ["variant"] },
+ filters: { effortSources: ["named"] },
ranking: { dimension: "effortSource", metric: "requestCount", limit: 8 },
}),
).resolves.toEqual(
expect.objectContaining({
- totals: expect.objectContaining({ requestCount: 1 }),
+ totals: expect.objectContaining({ requestCount: 2 }),
buckets: [
expect.objectContaining({
series: [
expect.objectContaining({ key: "high", label: "High", metrics: { requestCount: 1 } }),
+ expect.objectContaining({ key: "max", label: "Max", metrics: { requestCount: 1 } }),
],
}),
],
ranking: expect.objectContaining({
- rows: [expect.objectContaining({ key: "variant", label: "Variant fixed" })],
+ rows: [expect.objectContaining({ key: "named", label: "Named effort" })],
}),
identities: expect.objectContaining({
reasoningEffort: expect.objectContaining({
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts
new file mode 100644
index 000000000..1044f953c
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-arm-preference-expansion.test.ts
@@ -0,0 +1,76 @@
+import { describe, expect, it } from "vitest";
+
+import type { EndpointRegistryResult } from "@role-model-router/endpoint-registry";
+import { expandPreferredEndpointIdsToEffortArms } from "../src/index.js";
+
+function endpoint(id: string, reasoningEffort: string | null) {
+ return {
+ identity: {
+ endpoint_id: id,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: "acct.global.model",
+ runtime_version: "1",
+ region: "global",
+ ...(reasoningEffort === null
+ ? { reasoning_effort: null }
+ : { reasoning_effort: reasoningEffort }),
+ },
+ declared: {
+ endpoint_id: id,
+ capabilities: ["text.chat"],
+ modalities: ["text"],
+ max_context_tokens: 100_000,
+ tool_calling: { supported: false, style: "openai" },
+ supports_embeddings: false,
+ },
+ status: "active",
+ } as unknown as EndpointRegistryResult["endpoints"][number];
+}
+
+function registry(endpoints: ReturnType[]): EndpointRegistryResult {
+ return { endpoints } as unknown as EndpointRegistryResult;
+}
+
+describe("run106 arm-aware controller/advisory preference expansion (R6)", () => {
+ const base = "acct.global.model";
+ const high = `${base}-${encodeURIComponent("high")}`;
+ const max = `${base}-${encodeURIComponent("max")}`;
+
+ it("expands a base-endpoint preference to every eligible effort arm deterministically", () => {
+ const result = expandPreferredEndpointIdsToEffortArms({
+ registry: registry([endpoint(base, null), endpoint(high, "high"), endpoint(max, "max")]),
+ allowEndpoints: [base, high, max],
+ preferredEndpointIds: [base],
+ });
+ expect(result).toEqual([base, high, max]);
+ });
+
+ it("only expands into the already-eligible arms (never invents effort)", () => {
+ const result = expandPreferredEndpointIdsToEffortArms({
+ registry: registry([endpoint(base, null), endpoint(high, "high"), endpoint(max, "max")]),
+ allowEndpoints: [base, high],
+ preferredEndpointIds: [base],
+ });
+ expect(result).toEqual([base, high]);
+ });
+
+ it("keeps a specific fixed-arm preference exact", () => {
+ const result = expandPreferredEndpointIdsToEffortArms({
+ registry: registry([endpoint(base, null), endpoint(high, "high"), endpoint(max, "max")]),
+ allowEndpoints: [base, high, max],
+ preferredEndpointIds: [high],
+ });
+ expect(result).toEqual([high]);
+ });
+
+ it("drops a preference that names neither a base endpoint nor an eligible arm", () => {
+ const result = expandPreferredEndpointIdsToEffortArms({
+ registry: registry([endpoint(base, null), endpoint(high, "high")]),
+ allowEndpoints: [base, high],
+ preferredEndpointIds: ["other.base"],
+ });
+ expect(result).toEqual([]);
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts
new file mode 100644
index 000000000..e8a8e09d0
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-canonical-effort-emission.test.ts
@@ -0,0 +1,90 @@
+import { describe, expect, it } from "vitest";
+
+import { resolveEndpointExecutionEffort } from "../src/index.js";
+
+function executionRequest(effort?: string) {
+ return {
+ messages: [],
+ ...(effort ? { reasoning: { effort } } : {}),
+ };
+}
+
+describe("run106 canonical effort emission (R10)", () => {
+ it("fixed-effort arm without a client effort emits variant", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: "high",
+ declaredEffortLevels: [],
+ executionRequest: executionRequest(),
+ });
+ expect(result.receipt).toEqual({
+ reasoningEffort: "high",
+ effortSource: "variant",
+ coerced: false,
+ });
+ });
+
+ it("fixed-effort arm with a different client effort emits variant_coerced with coerced=true", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: "high",
+ declaredEffortLevels: [],
+ executionRequest: executionRequest("max"),
+ });
+ expect(result.receipt).toEqual({
+ reasoningEffort: "high",
+ effortSource: "variant_coerced",
+ coerced: true,
+ });
+ });
+
+ it("provider-default arm honoring a declared client effort emits client", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: null,
+ declaredEffortLevels: ["low", "high"],
+ executionRequest: executionRequest("high"),
+ });
+ expect(result.receipt).toEqual({
+ reasoningEffort: "high",
+ effortSource: "client",
+ coerced: false,
+ });
+ });
+
+ it("provider-default arm with no client effort emits none (not provider_default)", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: null,
+ declaredEffortLevels: ["low", "high"],
+ executionRequest: executionRequest(),
+ });
+ expect(result.receipt).toEqual({ reasoningEffort: null, effortSource: "none", coerced: false });
+ });
+
+ it("provider-default arm with an undeclared client effort strips reasoning and emits none", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: null,
+ declaredEffortLevels: ["low"],
+ executionRequest: executionRequest("max"),
+ });
+ expect(result.receipt).toEqual({ reasoningEffort: null, effortSource: "none", coerced: false });
+ expect(result.executionRequest.reasoning).toBeUndefined();
+ });
+
+ it("provider-default arm with disabled reasoning (none) emits none and strips reasoning", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: null,
+ declaredEffortLevels: ["low", "high"],
+ executionRequest: executionRequest("none"),
+ });
+ expect(result.receipt).toEqual({ reasoningEffort: null, effortSource: "none", coerced: false });
+ expect(result.executionRequest.reasoning).toBeUndefined();
+ });
+
+ it("provider-default arm with disabled reasoning (off) emits none", () => {
+ const result = resolveEndpointExecutionEffort({
+ fixedEffort: null,
+ declaredEffortLevels: ["low", "high"],
+ executionRequest: executionRequest("off"),
+ });
+ expect(result.receipt).toEqual({ reasoningEffort: null, effortSource: "none", coerced: false });
+ expect(result.executionRequest.reasoning).toBeUndefined();
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts
new file mode 100644
index 000000000..d9e46cc2b
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-discovery-effort-projection.test.ts
@@ -0,0 +1,135 @@
+import { describe, expect, test } from "vitest";
+
+import type { NormalizedCatalog, NormalizedCatalogModel } from "@role-model-router/catalog";
+import type { EndpointRegistryResult } from "@role-model-router/endpoint-registry";
+
+import { createDownstreamOpenAIDiscovery } from "../src/downstream-openai-discovery.js";
+
+const source = {
+ vendor: "models.dev",
+ commit: "test",
+ capturedAt: "2026-06-22T00:00:00.000Z",
+ schemaVersion: "models.dev.v1",
+};
+
+function model(
+ overrides: Partial & { modelId: string },
+): NormalizedCatalogModel {
+ return {
+ modelId: overrides.modelId,
+ providerId: overrides.providerId ?? overrides.modelId.split("/")[0] ?? "unknown",
+ providerKind: overrides.providerKind ?? "provider-openai",
+ authFamily: overrides.authFamily ?? "api-key",
+ displayName: overrides.displayName ?? overrides.modelId,
+ version: overrides.version ?? "test",
+ capabilities: overrides.capabilities ?? ["text.chat"],
+ modalities: overrides.modalities ?? ["text"],
+ contextWindow: overrides.contextWindow ?? 1000,
+ maxOutputTokens: overrides.maxOutputTokens ?? 1000,
+ pricing: null,
+ requestShapeHints: null,
+ experimentalModes: [],
+ extendsProvenance: { baseModelId: null, chain: [] },
+ localOverrideApplied: false,
+ localNotes: [],
+ upstreamProvenance: source,
+ };
+}
+
+const catalog: NormalizedCatalog = {
+ catalogVersion: "1",
+ source,
+ providers: [],
+ models: [
+ model({ modelId: "openai/gpt-5.4", providerId: "openai" }),
+ model({ modelId: "deepseek/deepseek-v4-pro", providerId: "deepseek" }),
+ model({ modelId: "deepseek/deepseek-v4-flash", providerId: "deepseek" }),
+ ],
+};
+
+function endpoint(
+ endpointId: string,
+ modelId: string,
+ reasoningEffort: string | null,
+ declaredLevels?: readonly string[],
+) {
+ return {
+ identity: {
+ endpoint_id: endpointId,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: modelId,
+ runtime_version: "1",
+ region: "global",
+ ...(reasoningEffort === null ? {} : { reasoning_effort: reasoningEffort }),
+ },
+ declared: {
+ endpoint_id: endpointId,
+ capabilities: ["text.chat"],
+ modalities: ["text"],
+ max_context_tokens: 1000,
+ tool_calling: { supported: false, style: "openai" },
+ supports_embeddings: false,
+ ...(declaredLevels && declaredLevels.length > 0
+ ? { reasoning_effort_levels: [...declaredLevels] }
+ : {}),
+ },
+ status: "active",
+ };
+}
+
+const registry = {
+ endpoints: [
+ endpoint("openai.gpt-5-4.low", "openai/gpt-5.4", "low"),
+ endpoint("openai.gpt-5-4.max", "openai/gpt-5.4", "max"),
+ endpoint("openai.gpt-5-4.default", "openai/gpt-5.4", null),
+ endpoint("deepseek.pro.low", "deepseek/deepseek-v4-pro", "low"),
+ endpoint("deepseek.pro.high", "deepseek/deepseek-v4-pro", "high"),
+ endpoint("deepseek.flash.low", "deepseek/deepseek-v4-flash", "low"),
+ ],
+ diagnostics: [],
+ lifecycleSummary: { active: 6, degraded: 0, offline: 0 },
+} as unknown as EndpointRegistryResult;
+
+describe("run106 discovery effort projection (R9 integration)", () => {
+ test("publishes the pool-wide effort union and portable intersection", () => {
+ const discovery = createDownstreamOpenAIDiscovery({
+ baseUrl: "http://127.0.0.1:3456",
+ catalog,
+ registry,
+ });
+
+ // union = every named effort across models; intersection = efforts shared by every model.
+ expect(discovery.effort).toEqual({
+ union: ["high", "low", "max"],
+ portableIntersection: ["low"],
+ });
+ });
+
+ test("includes provider-default declared levels in the union/intersection", () => {
+ const registryWithProviderDefaultLevels = {
+ endpoints: [
+ endpoint("openai.gpt-5-4.low", "openai/gpt-5.4", "low"),
+ endpoint("openai.gpt-5-4.max", "openai/gpt-5.4", "max"),
+ endpoint("openai.gpt-5-4.default", "openai/gpt-5.4", null, ["low", "medium"]),
+ endpoint("deepseek.pro.low", "deepseek/deepseek-v4-pro", "low"),
+ endpoint("deepseek.pro.high", "deepseek/deepseek-v4-pro", "high"),
+ endpoint("deepseek.flash.low", "deepseek/deepseek-v4-flash", "low"),
+ ],
+ diagnostics: [],
+ lifecycleSummary: { active: 6, degraded: 0, offline: 0 },
+ } as unknown as EndpointRegistryResult;
+
+ const discovery = createDownstreamOpenAIDiscovery({
+ baseUrl: "http://127.0.0.1:3456",
+ catalog,
+ registry: registryWithProviderDefaultLevels,
+ });
+
+ expect(discovery.effort).toEqual({
+ union: ["high", "low", "max", "medium"],
+ portableIntersection: ["low"],
+ });
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts
new file mode 100644
index 000000000..1bdf02183
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-effort-aware-cache-continuity.test.ts
@@ -0,0 +1,44 @@
+import { describe, expect, it } from "vitest";
+
+import { toCacheContinuityScopeDescriptor } from "../src/index.js";
+
+describe("run106 effort-aware cache continuity (R6)", () => {
+ it("keys a prompt-cache scope by the effort arm", () => {
+ const descriptor = toCacheContinuityScopeDescriptor({
+ messages: [],
+ promptCache: { key: "prompt-abc" },
+ reasoning: { effort: "high" },
+ });
+ expect(descriptor).toMatchObject({
+ scopeSource: "prompt_cache_key",
+ scopeId: "prompt_cache_key:prompt-abc:effort:high",
+ });
+ });
+
+ it("keys a session-affinity scope by the effort arm", () => {
+ const descriptor = toCacheContinuityScopeDescriptor({
+ messages: [],
+ sessionAffinity: { sessionId: "sess-1" },
+ reasoning: { effort: "low" },
+ });
+ expect(descriptor).toMatchObject({
+ scopeSource: "session_affinity",
+ scopeId: "session_affinity:sess-1:effort:low",
+ });
+ });
+
+ it("keeps the historical effort-free scope key when no effort is requested", () => {
+ const descriptor = toCacheContinuityScopeDescriptor({
+ messages: [],
+ promptCache: { key: "prompt-abc" },
+ });
+ expect(descriptor).toMatchObject({
+ scopeSource: "prompt_cache_key",
+ scopeId: "prompt_cache_key:prompt-abc",
+ });
+ });
+
+ it("returns null when neither a prompt-cache key nor a session id is present", () => {
+ expect(toCacheContinuityScopeDescriptor({ messages: [] })).toBeNull();
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts
new file mode 100644
index 000000000..4fb413ba9
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-normalization.test.ts
@@ -0,0 +1,57 @@
+import { describe, expect, it } from "vitest";
+import { normalizeReasoningEffortPolicy } from "../src/index.js";
+
+describe("run106 effort policy normalization", () => {
+ it("omitted effort normalizes to router-managed with source none", () => {
+ expect(normalizeReasoningEffortPolicy(undefined, undefined)).toEqual({
+ effort: undefined,
+ policy: "router",
+ source: "none",
+ });
+ });
+ it("legacy scalar effort normalizes to preferred with source named", () => {
+ expect(normalizeReasoningEffortPolicy("high", undefined)).toEqual({
+ effort: "high",
+ policy: "preferred",
+ source: "named",
+ });
+ });
+ it("explicit strict policy is authoritative", () => {
+ expect(normalizeReasoningEffortPolicy("high", "strict")).toEqual({
+ effort: "high",
+ policy: "strict",
+ source: "named",
+ });
+ });
+ it("explicit preferred policy is authoritative", () => {
+ expect(normalizeReasoningEffortPolicy("high", "preferred")).toEqual({
+ effort: "high",
+ policy: "preferred",
+ source: "named",
+ });
+ });
+ it("router policy preserves the requested effort for provenance", () => {
+ expect(normalizeReasoningEffortPolicy("high", "router")).toEqual({
+ effort: "high",
+ policy: "router",
+ source: "named",
+ });
+ });
+ it("maps OpenAI's disabled-reasoning convention (none) to source disabled", () => {
+ expect(normalizeReasoningEffortPolicy("none", undefined)).toEqual({
+ effort: undefined,
+ policy: "router",
+ source: "disabled",
+ });
+ });
+ it("maps OpenAI's disabled-reasoning convention (off) to source disabled", () => {
+ expect(normalizeReasoningEffortPolicy("off", undefined)).toEqual({
+ effort: undefined,
+ policy: "router",
+ source: "disabled",
+ });
+ });
+ it("rejects an invalid policy", () => {
+ expect(() => normalizeReasoningEffortPolicy("high", "bogus" as never)).toThrow();
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts
new file mode 100644
index 000000000..6364b6758
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-pool-application.test.ts
@@ -0,0 +1,182 @@
+import { describe, expect, test } from "vitest";
+
+import type { EndpointRegistryResult } from "@role-model-router/endpoint-registry";
+
+import { applyReasoningEffortToModelPool } from "../src/index.js";
+
+/**
+ * Run 106 R3/R10 (SP4b): the typed effort-policy resolution kind must be COMPUTED and RECORDED on the pool
+ * application, not left implicit in the inlined `if (policy === "strict")` branching.
+ *
+ * The R10 resolution vocabulary is
+ * router_managed | exact_primary | exact_fallback_expanded | unsupported_fallback | strict_rejected | equivalent_mapped.
+ * This test pins the pool-level kinds that resolveEffortPolicy can actually produce today: router_managed,
+ * exact_primary (strict + exact arm), exact_fallback_expanded (preferred + exact arm), strict_rejected
+ * (strict + no exact arm), and unsupported_fallback (preferred + zero exact arms).
+ */
+
+function endpoint(
+ endpointId: string,
+ modelId: string,
+ reasoningEffort: string | null,
+ options: { readonly declaredEffortLevels?: readonly string[] } = {},
+) {
+ return {
+ identity: {
+ endpoint_id: endpointId,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: modelId,
+ runtime_version: "run106-test",
+ region: "global",
+ ...(reasoningEffort === null ? {} : { reasoning_effort: reasoningEffort }),
+ },
+ declared: {
+ endpoint_id: endpointId,
+ capabilities: ["text.chat", "reasoning", "tools.function_calling"],
+ modalities: ["text"],
+ max_context_tokens: 128_000,
+ tool_calling: { supported: true, style: "openai" },
+ supports_embeddings: false,
+ ...(options.declaredEffortLevels
+ ? { reasoning_effort_levels: [...options.declaredEffortLevels] }
+ : {}),
+ },
+ status: "active",
+ };
+}
+
+const FLASH = "deepseek/deepseek-flash";
+const PRO = "deepseek/deepseek-v4-pro";
+
+const flashLow = "deepseek.global.deepseek-flash-low";
+const flashHigh = "deepseek.global.deepseek-flash-high";
+const flashMax = "deepseek.global.deepseek-flash-max";
+const proHigh = "deepseek.global.deepseek-v4-pro-high";
+const proMax = "deepseek.global.deepseek-v4-pro-max";
+const providerDefault = "deepseek.global.deepseek-v4-pro-default";
+
+const registry = {
+ endpoints: [
+ endpoint(flashLow, FLASH, "low"),
+ endpoint(flashHigh, FLASH, "high"),
+ endpoint(flashMax, FLASH, "max"),
+ endpoint(proHigh, PRO, "high"),
+ endpoint(proMax, PRO, "max"),
+ endpoint(providerDefault, PRO, null, { declaredEffortLevels: ["medium", "high"] }),
+ endpoint("moonshot.global.kimi-k3-code", "moonshot/kimi-k3-code", "high"),
+ ],
+} as never as EndpointRegistryResult;
+
+const aliasPool = [
+ flashLow,
+ flashHigh,
+ flashMax,
+ proHigh,
+ proMax,
+ providerDefault,
+ "moonshot.global.kimi-k3-code",
+];
+
+describe("run106 R3/R10: effort-policy resolution kind is recorded on the pool application", () => {
+ test("router policy records router_managed and keeps the pool and preference untouched", () => {
+ const applied = applyReasoningEffortToModelPool({
+ registry,
+ requestedModel: "baseline.remote-only",
+ requestedEffort: "high",
+ requestedPolicy: "router",
+ allowEndpoints: aliasPool,
+ preferredEndpointIds: [flashLow],
+ });
+
+ expect(applied.resolution).toBe("router_managed");
+ expect(applied.effectiveEffort).toBeNull();
+ expect(applied.allowEndpoints).toEqual(aliasPool);
+ expect(applied.preferredEndpointIds).toEqual([flashLow]);
+ });
+
+ test("strict with an exact arm records exact_primary and narrows to the exact arms", () => {
+ const applied = applyReasoningEffortToModelPool({
+ registry,
+ requestedModel: "baseline.remote-only",
+ requestedEffort: "high",
+ requestedPolicy: "strict",
+ allowEndpoints: aliasPool,
+ preferredEndpointIds: [],
+ });
+
+ expect(applied.resolution).toBe("exact_primary");
+ expect(applied.effectiveEffort).toBe("high");
+ expect(applied.allowEndpoints).toEqual([flashHigh, proHigh, "moonshot.global.kimi-k3-code"]);
+ expect(applied.preferredEndpointIds).toEqual([]);
+ });
+
+ test("strict with no exact arm records strict_rejected and empties the pool", () => {
+ const applied = applyReasoningEffortToModelPool({
+ registry,
+ requestedModel: "baseline.remote-only",
+ requestedEffort: "ultra",
+ requestedPolicy: "strict",
+ allowEndpoints: aliasPool,
+ preferredEndpointIds: [flashLow],
+ });
+
+ expect(applied.resolution).toBe("strict_rejected");
+ expect(applied.effectiveEffort).toBeNull();
+ expect(applied.allowEndpoints).toEqual([]);
+ expect(applied.preferredEndpointIds).toEqual([]);
+ });
+
+ test("preferred with an exact arm records exact_fallback_expanded and prefers the exact arms", () => {
+ const applied = applyReasoningEffortToModelPool({
+ registry,
+ requestedModel: "baseline.remote-only",
+ requestedEffort: "high",
+ requestedPolicy: "preferred",
+ allowEndpoints: aliasPool,
+ preferredEndpointIds: [],
+ });
+
+ expect(applied.resolution).toBe("exact_fallback_expanded");
+ expect(applied.effectiveEffort).toBe("high");
+ expect(applied.allowEndpoints).toEqual(aliasPool);
+ expect(applied.preferredEndpointIds).toEqual([
+ flashHigh,
+ proHigh,
+ "moonshot.global.kimi-k3-code",
+ ]);
+ });
+
+ test("preferred with zero exact arms records unsupported_fallback and keeps the pool router-managed", () => {
+ const applied = applyReasoningEffortToModelPool({
+ registry,
+ requestedModel: "baseline.remote-only",
+ requestedEffort: "ultra",
+ requestedPolicy: "preferred",
+ allowEndpoints: aliasPool,
+ preferredEndpointIds: [flashLow],
+ });
+
+ expect(applied.resolution).toBe("unsupported_fallback");
+ expect(applied.effectiveEffort).toBeNull();
+ expect(applied.allowEndpoints).toEqual(aliasPool);
+ expect(applied.preferredEndpointIds).toEqual([flashLow]);
+ });
+
+ test("no requested effort records router_managed regardless of policy", () => {
+ const applied = applyReasoningEffortToModelPool({
+ registry,
+ requestedModel: "baseline.remote-only",
+ requestedEffort: null,
+ requestedPolicy: "preferred",
+ allowEndpoints: aliasPool,
+ preferredEndpointIds: [flashLow],
+ });
+
+ expect(applied.resolution).toBe("router_managed");
+ expect(applied.effectiveEffort).toBeNull();
+ expect(applied.allowEndpoints).toEqual(aliasPool);
+ expect(applied.preferredEndpointIds).toEqual([flashLow]);
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts
new file mode 100644
index 000000000..247ae57cb
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-effort-policy-resolution.test.ts
@@ -0,0 +1,59 @@
+import { describe, expect, it } from "vitest";
+import { resolveEffortPolicy } from "../src/index.js";
+
+describe("run106 effort policy resolution", () => {
+ it("router policy selects jointly (router_managed)", () => {
+ expect(
+ resolveEffortPolicy({
+ requestedEffort: "high",
+ policy: "router",
+ availableEfforts: ["high", "max"],
+ }),
+ ).toEqual({ resolution: "router_managed", effectiveEffort: null });
+ });
+ it("strict with an exact arm resolves exact_primary", () => {
+ expect(
+ resolveEffortPolicy({
+ requestedEffort: "high",
+ policy: "strict",
+ availableEfforts: ["high", "max"],
+ }),
+ ).toEqual({ resolution: "exact_primary", effectiveEffort: "high" });
+ });
+ it("strict with no exact arm rejects", () => {
+ expect(
+ resolveEffortPolicy({
+ requestedEffort: "high",
+ policy: "strict",
+ availableEfforts: ["low", "max"],
+ }),
+ ).toEqual({ resolution: "strict_rejected", effectiveEffort: null });
+ });
+ it("preferred with zero exact arms falls back to router-managed", () => {
+ expect(
+ resolveEffortPolicy({
+ requestedEffort: "high",
+ policy: "preferred",
+ availableEfforts: ["low", "max"],
+ }),
+ ).toEqual({ resolution: "unsupported_fallback", effectiveEffort: null });
+ });
+ it("no requested effort is router-managed", () => {
+ expect(
+ resolveEffortPolicy({
+ requestedEffort: undefined,
+ policy: "preferred",
+ availableEfforts: ["low"],
+ }),
+ ).toEqual({ resolution: "router_managed", effectiveEffort: null });
+ });
+ it("strict with no requested effort is a typed refusal", () => {
+ expect(
+ resolveEffortPolicy({
+ requestedEffort: undefined,
+ policy: "strict",
+ availableEfforts: ["high"],
+ }),
+ ).toEqual({ resolution: "strict_rejected", effectiveEffort: null });
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts b/role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts
new file mode 100644
index 000000000..d9c0001a0
--- /dev/null
+++ b/role-model-router/apps/runtime-host-bridge/test/run106-turn-aware-difficulty.test.ts
@@ -0,0 +1,126 @@
+import { describe, expect, test } from "vitest";
+
+import {
+ DIFFICULTY_CLASSIFIER_VERSION,
+ classifyDifficultyFromSignals,
+ computeDifficultyFeatures,
+ shouldInvalidateDifficultyClassifierVersion,
+} from "../src/index.js";
+
+/**
+ * Run 106 R7 (F4): turn-aware difficulty repair. The pre-SP5 rubric saturated because conversation
+ * burden (context tokens + history turns) accumulated linearly, so a trivial follow-up in a long
+ * coding session shared the hard bucket with genuinely risky tool/code/schema work. Classification
+ * now separates current-turn burden, bounded/diminishing conversation burden, operation risk,
+ * required quality, and latency sensitivity; the unconditional toolCount>0 && codeOrSchemaBurden =>
+ * hard saturation is replaced by a documented risk rule keyed to the *current turn*; cache
+ * invalidation refuses materially stale classification; and receipts expose the decisive features
+ * plus the classifier version.
+ */
+
+const signals = (overrides: Partial> = {}) => ({
+ contextTokens: 130,
+ toolCount: 0,
+ historyTurnCount: 1,
+ instructionConstraintCount: 0,
+ decompositionKeywordCount: 0,
+ codeOrSchemaBurden: false,
+ ...overrides,
+});
+
+describe("run106 R7 turn-aware difficulty repair", () => {
+ test("a trivial follow-up in a long coding session classifies below hard", () => {
+ // 40-turn, 300K-token session whose newest turn is a trivial follow-up with no tools/code.
+ const result = classifyDifficultyFromSignals({
+ signals: signals({ contextTokens: 300_000, historyTurnCount: 40 }),
+ });
+ expect(result.difficulty).not.toBe("hard");
+ });
+
+ test("a trivial tool-bearing follow-up (no current-turn code/schema) stays below hard", () => {
+ const result = classifyDifficultyFromSignals({
+ signals: signals({ contextTokens: 80_000, historyTurnCount: 30, toolCount: 3 }),
+ });
+ expect(result.difficulty).not.toBe("hard");
+ });
+
+ test("a fresh genuinely risky tool/code/schema task stays hard", () => {
+ const result = classifyDifficultyFromSignals({
+ signals: signals({ contextTokens: 300, toolCount: 1, codeOrSchemaBurden: true }),
+ });
+ expect(result.difficulty).toBe("hard");
+ expect(result.decisiveFeatures).toContain("operationRisk");
+ });
+
+ test("a fresh hard task with strong current-turn complexity stays hard", () => {
+ const result = classifyDifficultyFromSignals({
+ signals: signals({
+ contextTokens: 500,
+ toolCount: 2,
+ historyTurnCount: 1,
+ instructionConstraintCount: 6,
+ decompositionKeywordCount: 4,
+ codeOrSchemaBurden: true,
+ }),
+ });
+ expect(result.difficulty).toBe("hard");
+ });
+
+ test("a tool-free ask with high required quality stays hard without tools", () => {
+ const result = classifyDifficultyFromSignals({
+ signals: signals({
+ contextTokens: 1_000,
+ toolCount: 0,
+ historyTurnCount: 1,
+ instructionConstraintCount: 6,
+ decompositionKeywordCount: 5,
+ codeOrSchemaBurden: true,
+ }),
+ });
+ expect(result.difficulty).toBe("hard");
+ });
+
+ test("a tool-free trivial ask stays easy", () => {
+ const result = classifyDifficultyFromSignals({ signals: signals() });
+ expect(result.difficulty).toBe("easy");
+ });
+
+ test("separates the five turn-aware feature dimensions", () => {
+ const features = computeDifficultyFeatures(
+ signals({
+ contextTokens: 50_000,
+ toolCount: 5,
+ historyTurnCount: 20,
+ instructionConstraintCount: 6,
+ decompositionKeywordCount: 4,
+ codeOrSchemaBurden: true,
+ }),
+ );
+ expect(features).toEqual({
+ currentTurnBurden: 4,
+ conversationBurden: 2,
+ operationRisk: 5,
+ requiredQuality: 2,
+ latencySensitivity: 0,
+ });
+ });
+
+ test("receipts expose the classifier version", () => {
+ expect(DIFFICULTY_CLASSIFIER_VERSION).toMatch(/run106/);
+ });
+
+ test("cache invalidation refuses a stale classifier version", () => {
+ expect(
+ shouldInvalidateDifficultyClassifierVersion("run98-a32", DIFFICULTY_CLASSIFIER_VERSION),
+ ).toBe(true);
+ expect(
+ shouldInvalidateDifficultyClassifierVersion(
+ DIFFICULTY_CLASSIFIER_VERSION,
+ DIFFICULTY_CLASSIFIER_VERSION,
+ ),
+ ).toBe(false);
+ expect(
+ shouldInvalidateDifficultyClassifierVersion(undefined, DIFFICULTY_CLASSIFIER_VERSION),
+ ).toBe(true);
+ });
+});
diff --git a/role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts b/role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts
index 2c2b369d4..95bd2d423 100644
--- a/role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts
+++ b/role-model-router/apps/runtime-host-bridge/test/run116-alias-effort-bias.test.ts
@@ -121,7 +121,7 @@ describe("run116 E3: an alias keeps its pool and treats the requested effort as
expect(applied.preferredEndpointIds).toEqual([flashLow]);
});
- test("an alias request whose effort names no instance in the pool still refuses instead of coercing silently", () => {
+ test("an alias request whose effort names no instance in the pool records unsupported_fallback and keeps the pool", () => {
const applied = applyReasoningEffortToModelPool({
registry,
requestedModel: "baseline.remote-only",
@@ -130,11 +130,11 @@ describe("run116 E3: an alias keeps its pool and treats the requested effort as
preferredEndpointIds: [flashLow],
});
- // An empty pool is what the callers turn into the bounded `reasoning_effort_unavailable` error (run 98), so an
- // effort nothing in the pool can run stays a refusal - the pool keeps its membership only when the effort can be
- // honoured by at least one of its instances.
- expect(applied.allowEndpoints).toEqual([]);
- expect(applied.preferredEndpointIds).toEqual([]);
+ // Run 106 R3/D5: preferred + zero exact executable arms records unsupported_fallback, ignores the hint, and
+ // keeps the pool router-managed instead of refusing; the effort is never silently coerced.
+ expect(applied.allowEndpoints).toEqual(aliasPool);
+ expect(applied.preferredEndpointIds).toEqual([flashLow]);
+ expect(applied.resolution).toBe("unsupported_fallback");
});
test("a model id is a pool: the requested effort orders it and the pool keeps its members", () => {
@@ -153,7 +153,7 @@ describe("run116 E3: an alias keeps its pool and treats the requested effort as
expect(applied.preferredEndpointIds).toEqual([flashHigh]);
});
- test("an explicit model id with an unsupported effort still refuses the pool", () => {
+ test("an explicit model id with an unsupported effort records unsupported_fallback and keeps the pool", () => {
const modelPool = [flashLow, flashHigh, flashMax];
const applied = applyReasoningEffortToModelPool({
registry,
@@ -163,7 +163,8 @@ describe("run116 E3: an alias keeps its pool and treats the requested effort as
preferredEndpointIds: [],
});
- expect(applied.allowEndpoints).toEqual([]);
+ expect(applied.allowEndpoints).toEqual(modelPool);
+ expect(applied.resolution).toBe("unsupported_fallback");
});
test("an endpoint row as the model value keeps exact instance selection", () => {
diff --git a/role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts b/role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts
index b7cc34778..19836bfb7 100644
--- a/role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts
+++ b/role-model-router/apps/runtime-host-bridge/test/run91-effort-instance-identity.test.ts
@@ -176,6 +176,7 @@ describe("Run 91 effort instance identity", () => {
expect(resolution.receipt).toEqual({
reasoningEffort: "high",
effortSource: "variant_coerced",
+ coerced: true,
});
});
@@ -191,6 +192,7 @@ describe("Run 91 effort instance identity", () => {
expect(resolution.receipt).toEqual({
reasoningEffort: "high",
effortSource: "variant",
+ coerced: false,
});
});
@@ -204,7 +206,11 @@ describe("Run 91 effort instance identity", () => {
});
expect(resolution.executionRequest.reasoning).toBeUndefined();
- expect(resolution.receipt).toEqual({ reasoningEffort: null, effortSource: "none" });
+ expect(resolution.receipt).toEqual({
+ reasoningEffort: null,
+ effortSource: "none",
+ coerced: false,
+ });
});
test("discovery retains the aggregate row and emits one selectable endpoint row per sibling", () => {
@@ -304,8 +310,9 @@ describe("Run 91 effort instance identity", () => {
* ineligibility (`eligible=2 codes=POLICY_DENY_ENDPOINT=5`, `eligible=1` for `low`). The effort now orders the pool
* through `routingModel.preferredEndpointIds` (the core router's `routingModelRank` adjustment) and no longer
* removes members. Exact instance selection still applies to an explicit model id or endpoint row - see the
- * "keeps an exact fixed endpoint authoritative" and "fails closed when an alias effort has neither a matching
- * variant nor provider-default" cases below.
+ * "keeps an exact fixed endpoint authoritative" case below. An alias or model id whose effort has no exact arm is
+ * unsupported_fallback (R3/D5): the hint is ignored and the pool stays router-managed - see the "keeps the pool and
+ * records unsupported_fallback" cases below.
*/
test("routes an alias with explicit reasoning effort across the pool while preferring matching fixed variants", () => {
const aliases = [
@@ -354,51 +361,83 @@ describe("Run 91 effort instance identity", () => {
]);
});
- test("fails closed rather than treating provider-default as an unconfigured effort variant", () => {
- expect(() =>
- mapChatCompletionsRequest(
- registry,
+ test("keeps the pool and records unsupported_fallback when an alias effort has no exact arm", () => {
+ const plan = mapChatCompletionsRequest(
+ registry,
+ {
+ model: "baseline.remote-only",
+ messages: [{ role: "user", content: "hello" }],
+ reasoning_effort: "high",
+ } as never,
+ "run91-alias-high-no-variant",
+ [
{
- model: "baseline.remote-only",
- messages: [{ role: "user", content: "hello" }],
- reasoning_effort: "high",
- } as never,
- "run91-alias-high-no-variant",
- [
- {
- aliasId: "baseline.remote-only",
- modelIds: ["deepseek/deepseek-v4-pro"],
- executionMode: "remote_only",
- },
- ] as never,
- ),
- ).toThrow(/no targets|no registry endpoints|no execution target/i);
+ aliasId: "baseline.remote-only",
+ modelIds: ["deepseek/deepseek-v4-pro"],
+ executionMode: "remote_only",
+ },
+ ] as never,
+ );
+
+ // R3/D5: preferred + zero exact arms -> unsupported_fallback: ignore the hint and router-manage the whole pool.
+ expect(plan.routingRequest.allowEndpoints).toEqual(
+ expect.arrayContaining([
+ "account.global.deepseek-v4-pro",
+ "account.global.deepseek-v4-pro-medium",
+ "account.global.deepseek-v4-pro-max",
+ ]),
+ );
+ expect(plan.routingRequest.allowEndpoints).toHaveLength(3);
+ expect(plan.routingModel).toBeUndefined();
+ expect(plan.effortResolution).toEqual({
+ resolution: "unsupported_fallback",
+ effectiveEffort: null,
+ requestedEffort: "high",
+ requestedPolicy: "preferred",
+ source: "named",
+ });
});
- test("fails closed when an alias effort has neither a matching variant nor provider-default", () => {
+ test("keeps the fixed-only pool and records unsupported_fallback when no exact arm exists", () => {
const fixedOnlyRegistry = {
...registry,
endpoints: [mediumEndpoint, maxEndpoint],
} as unknown as EndpointRegistryResult;
- expect(() =>
- mapChatCompletionsRequest(
- fixedOnlyRegistry,
+ const plan = mapChatCompletionsRequest(
+ fixedOnlyRegistry,
+ {
+ model: "baseline.remote-only",
+ messages: [{ role: "user", content: "hello" }],
+ reasoning_effort: "high",
+ } as never,
+ "run91-alias-high-no-fallback",
+ [
{
- model: "baseline.remote-only",
- messages: [{ role: "user", content: "hello" }],
- reasoning_effort: "high",
- } as never,
- "run91-alias-high-no-fallback",
- [
- {
- aliasId: "baseline.remote-only",
- modelIds: ["deepseek/deepseek-v4-pro"],
- executionMode: "remote_only",
- },
- ] as never,
- ),
- ).toThrow(/no targets|no registry endpoints|no execution target/i);
+ aliasId: "baseline.remote-only",
+ modelIds: ["deepseek/deepseek-v4-pro"],
+ executionMode: "remote_only",
+ },
+ ] as never,
+ );
+
+ // R3/D5: "high" has no exact arm and no provider-default declares it, so the hint is ignored and the pool stays
+ // router-managed (unsupported_fallback) instead of failing closed.
+ expect(plan.routingRequest.allowEndpoints).toEqual(
+ expect.arrayContaining([
+ "account.global.deepseek-v4-pro-medium",
+ "account.global.deepseek-v4-pro-max",
+ ]),
+ );
+ expect(plan.routingRequest.allowEndpoints).toHaveLength(2);
+ expect(plan.routingModel).toBeUndefined();
+ expect(plan.effortResolution).toEqual({
+ resolution: "unsupported_fallback",
+ effectiveEffort: null,
+ requestedEffort: "high",
+ requestedPolicy: "preferred",
+ source: "named",
+ });
});
test("keeps an exact fixed endpoint authoritative when client effort conflicts", () => {
@@ -504,10 +543,14 @@ describe("Run 91 effort instance identity", () => {
});
expect(resolution.executionRequest.reasoning).toEqual({ effort: "high" });
- expect(resolution.receipt).toEqual({ reasoningEffort: "high", effortSource: "client" });
+ expect(resolution.receipt).toEqual({
+ reasoningEffort: "high",
+ effortSource: "client",
+ coerced: false,
+ });
});
- test("reports a bounded reasoning-effort error instead of blaming capabilities", () => {
+ test("records unsupported_fallback instead of a reasoning-effort error for an undeclared effort", () => {
const undeclaredRegistry = {
endpoints: [
endpoint("moonshot.personal.kimi-code.global.kimi-k2.7-code", null, {
@@ -518,42 +561,45 @@ describe("Run 91 effort instance identity", () => {
diagnostics: [],
lifecycleSummary: { active: 1, degraded: 0, offline: 0 },
} as unknown as EndpointRegistryResult;
- let caught: { statusCode?: number; body?: { error?: Record } } | null = null;
- try {
- mapChatCompletionsRequest(
- undeclaredRegistry,
- {
- model: "baseline.remote-only",
- messages: [
- {
- role: "user",
- content: [
- { type: "text", text: "Describe this." },
- { type: "image_url", image_url: { url: "data:image/png;base64,abc" } },
- ],
- },
- ],
- reasoning_effort: "high",
- } as never,
- "run98-effort-undeclared-level",
- [
+
+ const plan = mapChatCompletionsRequest(
+ undeclaredRegistry,
+ {
+ model: "baseline.remote-only",
+ messages: [
{
- aliasId: "baseline.remote-only",
- modelIds: ["moonshot/kimi-k2.7-code"],
- executionMode: "remote_only",
+ role: "user",
+ content: [
+ { type: "text", text: "Describe this." },
+ { type: "image_url", image_url: { url: "data:image/png;base64,abc" } },
+ ],
},
- ] as never,
- );
- } catch (error) {
- caught = error as typeof caught;
- }
-
- expect(caught?.statusCode).toBe(400);
- expect(caught?.body?.error).toMatchObject({
- type: "routing_eligibility_error",
- code: "reasoning_effort_unavailable",
- requestedModel: "baseline.remote-only",
+ ],
+ reasoning_effort: "high",
+ } as never,
+ "run98-effort-undeclared-level",
+ [
+ {
+ aliasId: "baseline.remote-only",
+ modelIds: ["moonshot/kimi-k2.7-code"],
+ executionMode: "remote_only",
+ },
+ ] as never,
+ );
+
+ // R3/D5: an alias effort the single provider-default endpoint does not declare is unsupported_fallback, so the
+ // request stays router-managed on that endpoint instead of surfacing a bounded 400.
+ expect(plan.routingRequest.allowEndpoints).toEqual([
+ "moonshot.personal.kimi-code.global.kimi-k2.7-code",
+ ]);
+ expect(plan.routingRequest.requiredModalities).toEqual(["image", "text"]);
+ expect(plan.routingModel).toBeUndefined();
+ expect(plan.effortResolution).toEqual({
+ resolution: "unsupported_fallback",
+ effectiveEffort: null,
requestedEffort: "high",
+ requestedPolicy: "preferred",
+ source: "named",
});
});
});
diff --git a/role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts b/role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts
new file mode 100644
index 000000000..35a190304
--- /dev/null
+++ b/role-model-router/apps/runtime-ui/app/lib/effort-truth.test.ts
@@ -0,0 +1,166 @@
+import { describe, expect, test } from "vitest";
+
+import {
+ EFFORT_EVIDENCE_LABELS,
+ EFFORT_RESOLUTION_LABELS,
+ classifyEffortEvidence,
+ formatEffectiveEffortDisclosure,
+ formatEffortArmTruthDisclosure,
+ formatEffortEvidenceLabel,
+ formatEffortResolutionLabel,
+ isProminentEffortResolution,
+ readEffortResolutionKind,
+} from "./effort-truth";
+
+describe("run 106 R11 effort evidence exactness", () => {
+ test("classifies borrowed cross-effort evidence before exact or prior", () => {
+ expect(
+ classifyEffortEvidence({
+ evidenceSource: "profile-derived",
+ relatedEffortOverallScore: 0.82,
+ }),
+ ).toBe("borrowed");
+ expect(
+ classifyEffortEvidence({
+ evidenceSource: "run-artifact",
+ relatedEffortOverallScore: 0.61,
+ }),
+ ).toBe("borrowed");
+ });
+
+ test("classifies a real run artifact as exact benchmark evidence", () => {
+ expect(classifyEffortEvidence({ evidenceSource: "run-artifact" })).toBe("exact");
+ });
+
+ test("classifies a derived profile as prior evidence, never exact", () => {
+ expect(classifyEffortEvidence({ evidenceSource: "profile-derived" })).toBe("prior");
+ });
+
+ test("classifies absent or unknown evidence sources as none", () => {
+ expect(classifyEffortEvidence({})).toBe("none");
+ expect(classifyEffortEvidence({ evidenceSource: "unknown-label" })).toBe("none");
+ expect(classifyEffortEvidence({ evidenceSource: null })).toBe("none");
+ expect(classifyEffortEvidence({ evidenceSource: undefined })).toBe("none");
+ });
+
+ test("labels every evidence kind so borrowed evidence never reads as exact", () => {
+ expect(formatEffortEvidenceLabel("exact")).toBe("Exact (run artifact)");
+ expect(formatEffortEvidenceLabel("borrowed")).toBe("Borrowed (sibling effort)");
+ expect(formatEffortEvidenceLabel("prior")).toBe("Prior (profile-derived)");
+ expect(formatEffortEvidenceLabel("none")).toBe("No benchmark evidence");
+ expect(EFFORT_EVIDENCE_LABELS.borrowed).not.toContain("Exact");
+ });
+});
+
+describe("run 106 R11 effective reasoning-effort disclosure", () => {
+ test("discloses a fixed named effort without hiding the source", () => {
+ expect(
+ formatEffectiveEffortDisclosure({ reasoningEffort: "high", effortSource: "fixed" }),
+ ).toBe("High (fixed)");
+ expect(
+ formatEffectiveEffortDisclosure({ reasoningEffort: "xhigh", effortSource: "fixed" }),
+ ).toBe("XHigh (fixed)");
+ });
+
+ test("discloses a coerced effort explicitly", () => {
+ expect(
+ formatEffectiveEffortDisclosure({ reasoningEffort: "high", effortSource: "variant_coerced" }),
+ ).toBe("High (coerced)");
+ expect(
+ formatEffectiveEffortDisclosure({ reasoningEffort: "medium", effortSource: "variant" }),
+ ).toBe("Medium (coerced)");
+ });
+
+ test("distinguishes provider-default from no effort and disabled reasoning", () => {
+ expect(
+ formatEffectiveEffortDisclosure({ reasoningEffort: null, effortSource: "provider-default" }),
+ ).toBe("Provider default");
+ expect(formatEffectiveEffortDisclosure({ reasoningEffort: null, effortSource: null })).toBe(
+ "No reasoning effort",
+ );
+ expect(formatEffectiveEffortDisclosure({ reasoningEffort: "none", effortSource: null })).toBe(
+ "Disabled reasoning",
+ );
+ expect(formatEffectiveEffortDisclosure({ reasoningEffort: "off", effortSource: null })).toBe(
+ "Disabled reasoning",
+ );
+ });
+
+ test("keeps a named effort visible when its source is unknown", () => {
+ expect(formatEffectiveEffortDisclosure({ reasoningEffort: "turbo", effortSource: null })).toBe(
+ "Turbo",
+ );
+ });
+});
+
+describe("run 106 R11 effort policy/resolution surfacing", () => {
+ test("reads the resolution kind from the R3/R10 wire field spellings", () => {
+ expect(readEffortResolutionKind({ effortResolution: "unsupported_fallback" })).toBe(
+ "unsupported_fallback",
+ );
+ expect(readEffortResolutionKind({ effort_resolution: "exact_primary" })).toBe("exact_primary");
+ expect(readEffortResolutionKind({ resolution: "exact_fallback_expanded" })).toBe(
+ "exact_fallback_expanded",
+ );
+ });
+
+ test("rejects unknown or absent resolution values instead of inventing one", () => {
+ expect(readEffortResolutionKind({ resolution: "nearest_effort_map" })).toBe(null);
+ expect(readEffortResolutionKind({})).toBe(null);
+ expect(readEffortResolutionKind(null)).toBe(null);
+ expect(readEffortResolutionKind("unsupported_fallback")).toBe(null);
+ });
+
+ test("labels the full closed resolution vocabulary", () => {
+ expect(formatEffortResolutionLabel("router_managed")).toBe("Router-managed");
+ expect(formatEffortResolutionLabel("exact_primary")).toBe("Exact effort (primary pool)");
+ expect(formatEffortResolutionLabel("exact_fallback_expanded")).toBe(
+ "Exact effort primary · fallback expanded",
+ );
+ expect(formatEffortResolutionLabel("unsupported_fallback")).toBe(
+ "Unsupported effort · routed fallback",
+ );
+ expect(formatEffortResolutionLabel("strict_rejected")).toBe("Strict effort rejected");
+ expect(formatEffortResolutionLabel("equivalent_mapped")).toBe("Equivalent effort mapped");
+ expect(EFFORT_RESOLUTION_LABELS).toHaveProperty("unsupported_fallback");
+ });
+
+ test("marks unsupported fallback and fallback expansion as prominent", () => {
+ expect(isProminentEffortResolution("unsupported_fallback")).toBe(true);
+ expect(isProminentEffortResolution("exact_fallback_expanded")).toBe(true);
+ expect(isProminentEffortResolution("exact_primary")).toBe(false);
+ expect(isProminentEffortResolution("router_managed")).toBe(false);
+ expect(isProminentEffortResolution("strict_rejected")).toBe(false);
+ expect(isProminentEffortResolution("equivalent_mapped")).toBe(false);
+ });
+});
+
+describe("run 106 R11 combined arm truth disclosure", () => {
+ test("co-displays effective effort and evidence exactness in one operator line", () => {
+ expect(
+ formatEffortArmTruthDisclosure({
+ reasoningEffort: "high",
+ effortSource: "fixed",
+ evidence: { evidenceSource: "run-artifact" },
+ }),
+ ).toBe("High (fixed) · Exact (run artifact)");
+ expect(
+ formatEffortArmTruthDisclosure({
+ reasoningEffort: null,
+ effortSource: "provider-default",
+ evidence: { evidenceSource: "profile-derived", relatedEffortOverallScore: 0.78 },
+ }),
+ ).toBe("Provider default · Borrowed (sibling effort)");
+ });
+
+ test("never echoes a credential, prompt, or provider body", () => {
+ const disclosure = formatEffortArmTruthDisclosure({
+ reasoningEffort: "high",
+ effortSource: "fixed",
+ evidence: { evidenceSource: "run-artifact" },
+ });
+ expect(disclosure).not.toMatch(/sk-|Bearer|Authorization|api[_-]?key/i);
+ expect(disclosure).not.toContain("system prompt");
+ expect(disclosure).not.toContain("request body");
+ });
+});
diff --git a/role-model-router/apps/runtime-ui/app/lib/effort-truth.ts b/role-model-router/apps/runtime-ui/app/lib/effort-truth.ts
new file mode 100644
index 000000000..daa2a867e
--- /dev/null
+++ b/role-model-router/apps/runtime-ui/app/lib/effort-truth.ts
@@ -0,0 +1,149 @@
+/**
+ * Run 106 / R11 (SP8) — operator/UI truthfulness projections.
+ *
+ * The pure routing primitives (resolveEffortPolicy, resolveBorrowedQualityPrior) live in the host
+ * bridge and core packages. These UI projections turn the structured fields those wires already emit
+ * (`reasoningEffort`, `effortSource`, `evidenceSource`, `relatedEffortOverallScore`, `effortResolution`)
+ * into honest operator-facing disclosure. The rule is the same one R5 states for evidence: borrowed or
+ * prior evidence must never read as exact, and a provider-default or coerced arm must never present its
+ * effort as if the endpoint instance owned it.
+ */
+
+import { formatReasoningEffortLabel } from "./effort-identity";
+
+/**
+ * Whether a benchmark score is exact (measured on this endpoint+effort arm), borrowed (a sibling-effort
+ * arm of the same model/provider, discounted), prior (a profile-derived aggregate), or absent.
+ */
+export type EffortEvidenceKind = "exact" | "borrowed" | "prior" | "none";
+
+export interface EffortEvidenceInput {
+ readonly evidenceSource?: string | null;
+ /** Borrowed cross-effort score; the backend sets it only when the arm has no exact evidence of its own. */
+ readonly relatedEffortOverallScore?: number | null;
+}
+
+function isFiniteNumber(value: unknown): value is number {
+ return typeof value === "number" && Number.isFinite(value);
+}
+
+/**
+ * Borrowed wins over exact and prior: a cross-effort sibling score is the strongest non-exact marker and
+ * must never be styled as exact benchmark evidence (R5). `run-artifact` is the only exact source; a
+ * `profile-derived` capability is a labeled prior.
+ */
+export function classifyEffortEvidence(input: EffortEvidenceInput): EffortEvidenceKind {
+ if (isFiniteNumber(input.relatedEffortOverallScore)) {
+ return "borrowed";
+ }
+ if (input.evidenceSource === "run-artifact") {
+ return "exact";
+ }
+ if (input.evidenceSource === "profile-derived") {
+ return "prior";
+ }
+ return "none";
+}
+
+export const EFFORT_EVIDENCE_LABELS: Readonly> = {
+ exact: "Exact (run artifact)",
+ borrowed: "Borrowed (sibling effort)",
+ prior: "Prior (profile-derived)",
+ none: "No benchmark evidence",
+};
+
+export function formatEffortEvidenceLabel(kind: EffortEvidenceKind): string {
+ return EFFORT_EVIDENCE_LABELS[kind];
+}
+
+/** The closed resolution vocabulary from the R3/R10 wiring (EffortPolicyResolutionKind). */
+export type EffortResolutionKind =
+ | "router_managed"
+ | "exact_primary"
+ | "exact_fallback_expanded"
+ | "unsupported_fallback"
+ | "strict_rejected"
+ | "equivalent_mapped";
+
+export const EFFORT_RESOLUTION_LABELS: Readonly> = {
+ router_managed: "Router-managed",
+ exact_primary: "Exact effort (primary pool)",
+ exact_fallback_expanded: "Exact effort primary · fallback expanded",
+ unsupported_fallback: "Unsupported effort · routed fallback",
+ strict_rejected: "Strict effort rejected",
+ equivalent_mapped: "Equivalent effort mapped",
+};
+
+const EFFORT_RESOLUTION_KINDS: ReadonlySet = new Set(Object.keys(EFFORT_RESOLUTION_LABELS));
+
+/** Read a resolution kind from any of the R3/R10 wire field spellings, else null (never invent one). */
+export function readEffortResolutionKind(value: unknown): EffortResolutionKind | null {
+ if (!value || typeof value !== "object") {
+ return null;
+ }
+ const record = value as Record;
+ const candidate = record.effortResolution ?? record.effort_resolution ?? record.resolution;
+ return typeof candidate === "string" && EFFORT_RESOLUTION_KINDS.has(candidate)
+ ? (candidate as EffortResolutionKind)
+ : null;
+}
+
+export function formatEffortResolutionLabel(kind: EffortResolutionKind): string {
+ return EFFORT_RESOLUTION_LABELS[kind];
+}
+
+/**
+ * Unsupported fallback and exact-pool expansion change who actually serves the request, so they must be
+ * prominent rather than buried in the raw diagnostics bag (R11: color is not the sole distinction).
+ */
+export function isProminentEffortResolution(kind: EffortResolutionKind): boolean {
+ return kind === "unsupported_fallback" || kind === "exact_fallback_expanded";
+}
+
+export interface EffectiveEffortInput {
+ readonly reasoningEffort?: string | null;
+ readonly effortSource?: string | null;
+}
+
+function normalizeEffortSource(source: string | null | undefined): string {
+ return (source ?? "").trim().toLowerCase();
+}
+
+function isCoercedSource(source: string): boolean {
+ return source === "variant" || source === "variant_coerced";
+}
+
+/**
+ * The honest effective-effort disclosure for one arm row. A fixed arm owns its effort; a provider-default
+ * arm lets the adapter decide; a coerced arm is labeled as coerced; `none`/`off` are disabled reasoning,
+ * never "no effort". A named effort with an unknown source stays visible rather than being dropped.
+ */
+export function formatEffectiveEffortDisclosure(input: EffectiveEffortInput): string {
+ const normalizedEffort = (input.reasoningEffort ?? "").trim().toLowerCase();
+ const source = normalizeEffortSource(input.effortSource);
+ const coerced = isCoercedSource(source);
+
+ if (normalizedEffort === "none" || normalizedEffort === "off") {
+ return coerced ? "Disabled reasoning (coerced)" : "Disabled reasoning";
+ }
+ if (coerced) {
+ const label = formatReasoningEffortLabel(input.reasoningEffort);
+ return label ? `${label} (coerced)` : "Coerced effort";
+ }
+ const label = formatReasoningEffortLabel(input.reasoningEffort);
+ if (label) {
+ return source === "fixed" ? `${label} (fixed)` : label;
+ }
+ return source === "provider-default" ? "Provider default" : "No reasoning effort";
+}
+
+export interface EffortArmTruthInput extends EffectiveEffortInput {
+ readonly evidence?: EffortEvidenceInput | null;
+}
+
+/** One operator line that co-displays effective effort and evidence exactness (R11). */
+export function formatEffortArmTruthDisclosure(input: EffortArmTruthInput): string {
+ const effortDisclosure = formatEffectiveEffortDisclosure(input);
+ const evidenceKind = classifyEffortEvidence(input.evidence ?? {});
+ return `${effortDisclosure} · ${formatEffortEvidenceLabel(evidenceKind)}`;
+}
diff --git a/role-model-router/apps/runtime-ui/app/lib/runtime-api.ts b/role-model-router/apps/runtime-ui/app/lib/runtime-api.ts
index f8f8b0de7..f67290b45 100644
--- a/role-model-router/apps/runtime-ui/app/lib/runtime-api.ts
+++ b/role-model-router/apps/runtime-ui/app/lib/runtime-api.ts
@@ -1255,6 +1255,12 @@ export interface RouterConfig {
export interface BenchmarkCapability {
readonly evidenceSource?: "run-artifact" | "profile-derived";
readonly overallScore: number | null;
+ /**
+ * Run 106 R5 (borrowed): cross-effort score from a sibling fixed-effort arm of the same model/provider,
+ * present only when this arm has no exact benchmark evidence of its own. Borrowed evidence is always
+ * labeled and never styled as exact (R11).
+ */
+ readonly relatedEffortOverallScore?: number | null;
/**
* Run 98 addendum 42 B2: the benchmark run's own latency for this endpoint, derived from its case
* audits. The model pool's speed axis uses it until telemetry exists for the endpoint.
diff --git a/role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts b/role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts
index 88a1c0ad0..23784f878 100644
--- a/role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts
+++ b/role-model-router/apps/runtime-ui/app/lib/telemetry-chart-config.test.ts
@@ -114,7 +114,7 @@ describe("telemetry chart config", () => {
}
expect(requestsRoute).toContain('label: "Selected model"');
expect(requestsRoute).toContain('label: "Endpoint effort"');
- expect(requestsRoute).toContain('?? "Default"');
+ expect(requestsRoute).toContain("formatEffectiveEffortDisclosure");
expect(requestsRoute).not.toContain('label: "Request effort"');
});
});
diff --git a/role-model-router/apps/runtime-ui/app/lib/view-models.ts b/role-model-router/apps/runtime-ui/app/lib/view-models.ts
index 11305e94e..4dda56fa1 100644
--- a/role-model-router/apps/runtime-ui/app/lib/view-models.ts
+++ b/role-model-router/apps/runtime-ui/app/lib/view-models.ts
@@ -1565,6 +1565,7 @@ export function buildEndpointCatalogRows(endpoints: readonly RuntimeEndpoint[]):
benchmarkEligible?: boolean;
displayName?: string;
reasoningEffort?: string | null;
+ effortSource?: string | null;
upstreamModelId?: string | null;
}> {
return [...endpoints]
@@ -1597,6 +1598,7 @@ export function buildEndpointCatalogRows(endpoints: readonly RuntimeEndpoint[]):
...(typeof endpoint.benchmarkEligible === "boolean"
? { benchmarkEligible: endpoint.benchmarkEligible }
: {}),
+ ...(endpoint.effortSource ? { effortSource: endpoint.effortSource } : {}),
...(reasoningEffort || endpoint.displayName || upstreamModelId
? {
displayName: formatEndpointDisplayName({ base, reasoningEffort }),
diff --git a/role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts b/role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts
index c74143ccb..3bb5a52a8 100644
--- a/role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts
+++ b/role-model-router/apps/runtime-ui/app/routes/control-benchmark.test.ts
@@ -1,3 +1,5 @@
+import { readFileSync } from "node:fs";
+
import { expect, test, vi } from "vitest";
import * as benchmarkModule from "./control-benchmark";
@@ -42,3 +44,11 @@ test("publishes essential benchmark controls while advisory reads remain pending
expect(onAdvisory).not.toHaveBeenCalled();
dispose();
});
+
+const benchmarkSource = readFileSync(new URL("./control-benchmark.tsx", import.meta.url), "utf8");
+
+test("labels benchmark score evidence as exact/borrowed/prior (R11)", () => {
+ expect(benchmarkSource).toContain("classifyEffortEvidence");
+ expect(benchmarkSource).toContain("formatEffortEvidenceLabel");
+ expect(benchmarkSource).toContain("evidenceLabel");
+});
diff --git a/role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx b/role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx
index f810815ca..1346ab306 100644
--- a/role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/control-benchmark.tsx
@@ -27,6 +27,7 @@ import {
supportingTextClassName,
} from "../lib/design-system";
import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";
+import { classifyEffortEvidence, formatEffortEvidenceLabel } from "../lib/effort-truth";
import { formatScore, formatScoreWithCoverage } from "../lib/format-score";
import {
type BenchmarkCaseAuditEntry,
@@ -191,6 +192,7 @@ interface ModelScoreRow {
readonly latencyP95: number | null;
readonly lastRunId: string | null;
readonly lastRunMode: "quick" | "full" | null;
+ readonly evidenceLabel: string;
}
function buildModelScoreRows(
@@ -254,6 +256,17 @@ function buildModelScoreRows(
continue;
}
+ const evidenceLabel = grade
+ ? formatEffortEvidenceLabel("exact")
+ : capability
+ ? formatEffortEvidenceLabel(
+ classifyEffortEvidence({
+ evidenceSource: capability.evidenceSource,
+ relatedEffortOverallScore: capability.relatedEffortOverallScore,
+ }),
+ )
+ : formatEffortEvidenceLabel(profileQualityScore !== null ? "prior" : "none");
+
rows.push({
endpointId: candidate.endpointId,
modelId: candidate.modelId,
@@ -284,6 +297,7 @@ function buildModelScoreRows(
latencyP95,
lastRunId: grade?.runId ?? capability?.lastRunId ?? null,
lastRunMode: grade?.mode ?? capability?.lastRunMode ?? null,
+ evidenceLabel,
});
}
@@ -1050,6 +1064,9 @@ export default function ControlBenchmarkRoute() {
? `${row.lastRunId}${row.lastRunMode ? ` · ${row.lastRunMode}` : ""}`
: "profile-derived"}
+
+ {row.evidenceLabel}
+
{formatScore(row.overallScore)}
diff --git a/role-model-router/apps/runtime-ui/app/routes/control-models.test.ts b/role-model-router/apps/runtime-ui/app/routes/control-models.test.ts
index 9f425343a..2627d2e4d 100644
--- a/role-model-router/apps/runtime-ui/app/routes/control-models.test.ts
+++ b/role-model-router/apps/runtime-ui/app/routes/control-models.test.ts
@@ -1,3 +1,5 @@
+import { readFileSync } from "node:fs";
+
import { describe, expect, test, vi } from "vitest";
import type { RouterCandidate, RuntimeAccount } from "../lib/runtime-api";
@@ -772,3 +774,23 @@ describe("describeConfiguredModelRequestEvidence", () => {
).toBe("7 requests");
});
});
+
+const controlModelsSource = readFileSync(new URL("./control-models.tsx", import.meta.url), "utf8");
+
+test("labels model-pool benchmark evidence as exact/borrowed/prior (R11)", () => {
+ expect(
+ buildConfiguredModelInventoryPills({
+ toolCallingSupported: true,
+ endpointCount: 1,
+ capabilityScore: null,
+ evidenceLabel: "Borrowed (sibling effort)",
+ evidenceTone: "warning",
+ }),
+ ).toContainEqual({ label: "Borrowed (sibling effort)", tone: "warning" });
+});
+
+test("computes model-pool evidence from the candidate's benchmark capability (R11)", () => {
+ expect(controlModelsSource).toContain("classifyEffortEvidence");
+ expect(controlModelsSource).toContain("formatEffortEvidenceLabel");
+ expect(controlModelsSource).toContain("relatedEffortOverallScore");
+});
diff --git a/role-model-router/apps/runtime-ui/app/routes/control-models.tsx b/role-model-router/apps/runtime-ui/app/routes/control-models.tsx
index 326a0d14b..c6b0a1046 100644
--- a/role-model-router/apps/runtime-ui/app/routes/control-models.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/control-models.tsx
@@ -13,6 +13,7 @@ import {
secondaryButtonClassName,
supportingTextClassName,
} from "../lib/design-system";
+import { classifyEffortEvidence, formatEffortEvidenceLabel } from "../lib/effort-truth";
import { formatScore, formatScoreWithCoverage } from "../lib/format-score";
import { ModelRoleBindingTree } from "../lib/role-task-hierarchy";
import {
@@ -208,6 +209,8 @@ export function buildConfiguredModelInventoryPills(input: {
readonly toolCallingSupported: boolean;
readonly endpointCount: number;
readonly capabilityScore: number | null | undefined;
+ readonly evidenceLabel?: string | null;
+ readonly evidenceTone?: BadgeTone;
}): ConfiguredModelInventoryPill[] {
return [
{
@@ -226,6 +229,9 @@ export function buildConfiguredModelInventoryPills(input: {
},
]
: []),
+ ...(input.evidenceLabel && input.evidenceTone
+ ? [{ label: input.evidenceLabel, tone: input.evidenceTone }]
+ : []),
];
}
@@ -1090,13 +1096,31 @@ export default function ControlModelsRoute() {
{cards.map((card) => {
const cardKey = configuredModelCardKey(card);
const selected = selectedModelId === cardKey;
- const capabilityScore =
- resolveSelectedBenchmarkCandidate(candidates, card)?.benchmarkCapability
- ?.overallScore ?? null;
+ const benchmarkCapability = resolveSelectedBenchmarkCandidate(
+ candidates,
+ card,
+ )?.benchmarkCapability;
+ const capabilityScore = benchmarkCapability?.overallScore ?? null;
+ const evidenceKind = classifyEffortEvidence({
+ evidenceSource: benchmarkCapability?.evidenceSource,
+ relatedEffortOverallScore: benchmarkCapability?.relatedEffortOverallScore,
+ });
+ const evidenceTone: BadgeTone =
+ evidenceKind === "borrowed"
+ ? "warning"
+ : evidenceKind === "prior"
+ ? "advisory"
+ : "info";
const inventoryPills = buildConfiguredModelInventoryPills({
toolCallingSupported: card.toolCallingSupported,
endpointCount: card.endpointCount,
capabilityScore,
+ ...(evidenceKind === "none"
+ ? {}
+ : {
+ evidenceLabel: formatEffortEvidenceLabel(evidenceKind),
+ evidenceTone,
+ }),
});
return (
{
]);
expect(rows.some((row) => row.connectionLabel === "deepseek.litellm")).toBe(false);
});
+
+ test("labels each endpoint row's effective reasoning effort (R11)", () => {
+ const endpoints = [
+ {
+ endpointId: "deepseek.personal.deepseek-api-key.global.deepseek-v4-pro-high",
+ modelId: "deepseek/deepseek-v4-pro",
+ providerId: "deepseek",
+ providerAccountId: "deepseek.personal.deepseek-api-key",
+ sourceType: "remote" as const,
+ servingSource: "remote-service",
+ endpointKind: "remote_api",
+ status: "active",
+ healthStatus: "healthy",
+ routingEligible: true,
+ benchmarkEligible: true,
+ reasoningEffort: "high",
+ effortSource: "fixed",
+ },
+ {
+ endpointId: "deepseek.personal.deepseek-api-key.global.deepseek-v4-flash",
+ modelId: "deepseek/deepseek-v4-flash",
+ providerId: "deepseek",
+ providerAccountId: "deepseek.personal.deepseek-api-key",
+ sourceType: "remote" as const,
+ servingSource: "remote-service",
+ endpointKind: "remote_api",
+ status: "active",
+ healthStatus: "healthy",
+ routingEligible: true,
+ benchmarkEligible: true,
+ reasoningEffort: null,
+ effortSource: "provider-default",
+ },
+ ];
+ const rows = buildRuntimeConnectionRows({
+ providerRows: buildConfiguredProviderRows({ accounts: [], endpoints }),
+ endpointRows: buildEndpointCatalogRows(endpoints),
+ });
+ expect(rows).toContainEqual(expect.objectContaining({ effortLabel: "High (fixed)" }));
+ expect(rows).toContainEqual(expect.objectContaining({ effortLabel: "Provider default" }));
+ });
});
diff --git a/role-model-router/apps/runtime-ui/app/routes/endpoints.tsx b/role-model-router/apps/runtime-ui/app/routes/endpoints.tsx
index 8ae52f8b4..a1760c638 100644
--- a/role-model-router/apps/runtime-ui/app/routes/endpoints.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/endpoints.tsx
@@ -15,6 +15,7 @@ import {
supportingTextClassName,
} from "../lib/design-system";
import { formatEndpointDisplayPath } from "../lib/effort-identity";
+import { formatEffectiveEffortDisclosure } from "../lib/effort-truth";
import {
type RuntimeSnapshot,
fetchRuntimeAccounts,
@@ -96,6 +97,7 @@ export function buildRuntimeConnectionRows(input: {
connectionLabel: string;
modelLabel: string;
endpointLabel: string;
+ effortLabel: string;
sourceLabel: string;
healthLabel: string;
healthTone: "success" | "warning" | "neutral";
@@ -121,6 +123,10 @@ export function buildRuntimeConnectionRows(input: {
connectionLabel: endpoint.providerAccountId ?? "—",
modelLabel: endpoint.displayName ?? endpoint.modelId,
endpointLabel: formatEndpointDisplayPath(endpoint),
+ effortLabel: formatEffectiveEffortDisclosure({
+ reasoningEffort: endpoint.reasoningEffort,
+ effortSource: endpoint.effortSource,
+ }),
sourceLabel: `${formatServingSource(endpoint.servingSource, endpoint.sourceLabel)} / ${endpoint.endpointKind}`,
healthLabel: endpoint.healthStatus,
healthTone: healthTone(endpoint.healthStatus),
@@ -149,6 +155,7 @@ export function buildRuntimeConnectionRows(input: {
modelLabel:
provider.configuredModels.length > 0 ? provider.configuredModels.join(", ") : "No model",
endpointLabel: `${provider.activeEndpointCount}/${provider.endpointCount} active`,
+ effortLabel: "—",
sourceLabel: provider.authModes.join(", ") || "provider account",
healthLabel,
healthTone: healthTone(healthLabel),
@@ -247,6 +254,7 @@ export default function EndpointsRoute() {
Connection
Model
Endpoint
+ Effort
Source
Health
Readiness
@@ -259,6 +267,7 @@ export default function EndpointsRoute() {
{row.connectionLabel}
{row.modelLabel}
{row.endpointLabel}
+ {row.effortLabel}
{row.sourceLabel}
{row.healthLabel}
diff --git a/role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx b/role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx
index 7e919589d..1145849f2 100644
--- a/role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/request-detail.test.tsx
@@ -1,3 +1,5 @@
+import { readFileSync } from "node:fs";
+
import { describe, expect, test } from "vitest";
import { readPromptCacheRequestSource, readTokenTruth } from "./request-detail";
@@ -55,3 +57,10 @@ describe("request detail token truth", () => {
expect(readPromptCacheRequestSource({ promptCacheRequested: true })).toBeNull();
});
});
+
+const requestDetailSource = readFileSync(new URL("./request-detail.tsx", import.meta.url), "utf8");
+
+test("shows effective reasoning effort on the request detail (R11)", () => {
+ expect(requestDetailSource).toContain("formatEffectiveEffortDisclosure");
+ expect(requestDetailSource).toContain("effort_source");
+});
diff --git a/role-model-router/apps/runtime-ui/app/routes/request-detail.tsx b/role-model-router/apps/runtime-ui/app/routes/request-detail.tsx
index 6d3ce7131..baa2c9c39 100644
--- a/role-model-router/apps/runtime-ui/app/routes/request-detail.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/request-detail.tsx
@@ -21,6 +21,7 @@ import {
supportingTextClassName,
} from "../lib/design-system";
import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";
+import { formatEffectiveEffortDisclosure } from "../lib/effort-truth";
import { formatRoutingModeLabel } from "../lib/routing-mode";
import { fetchRequestDetail } from "../lib/runtime-api";
import { useShellHeaderOverride } from "../lib/shell-header-context";
@@ -326,6 +327,10 @@ export default function RequestDetailRoute() {
const reasoningEffort =
pickString(usageEvent, "reasoning_effort", "reasoningEffort") ??
pickString(endpointIdentity, "reasoning_effort", "reasoningEffort");
+ const effortSource =
+ pickString(usageEvent, "effort_source", "effortSource") ??
+ pickString(endpointIdentity, "effort_source", "effortSource") ??
+ null;
const modelDisplayName = formatModelIdentity({
modelId: modelId ?? endpointId,
endpointId,
@@ -819,6 +824,10 @@ export default function RequestDetailRoute() {
{[
["Provider", providerKind],
["Model", modelDisplayName],
+ [
+ "Effective effort",
+ formatEffectiveEffortDisclosure({ reasoningEffort, effortSource }),
+ ],
["Finish reason", finishReason],
["Input tokens", inputTokenTruth.text],
["Output tokens", outputTokenTruth.text],
diff --git a/role-model-router/apps/runtime-ui/app/routes/requests.test.tsx b/role-model-router/apps/runtime-ui/app/routes/requests.test.tsx
new file mode 100644
index 000000000..17dfa815c
--- /dev/null
+++ b/role-model-router/apps/runtime-ui/app/routes/requests.test.tsx
@@ -0,0 +1,12 @@
+import { readFileSync } from "node:fs";
+
+import { describe, expect, test } from "vitest";
+
+const source = readFileSync(new URL("./requests.tsx", import.meta.url), "utf8");
+
+describe("run 106 R11 request surface truthfulness", () => {
+ test("shows the endpoint's effective reasoning effort, not just its label", () => {
+ expect(source).toContain("formatEffectiveEffortDisclosure");
+ expect(source).not.toContain("formatReasoningEffortLabel(request.reasoningEffort)");
+ });
+});
diff --git a/role-model-router/apps/runtime-ui/app/routes/requests.tsx b/role-model-router/apps/runtime-ui/app/routes/requests.tsx
index 3eeea33e3..d65071fa4 100644
--- a/role-model-router/apps/runtime-ui/app/routes/requests.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/requests.tsx
@@ -19,7 +19,8 @@ import {
mutedPanelClassName,
supportingTextClassName,
} from "../lib/design-system";
-import { formatEndpointDisplayPath, formatReasoningEffortLabel } from "../lib/effort-identity";
+import { formatEndpointDisplayPath } from "../lib/effort-identity";
+import { formatEffectiveEffortDisclosure } from "../lib/effort-truth";
import { startDeferredLiveRefresh } from "../lib/live-refresh";
import { adaptObserveChartBlock } from "../lib/observe-chart-adapter";
import type {
@@ -635,7 +636,10 @@ export default function RequestsRoute() {
{
id: "effort",
label: "Endpoint effort",
- value: formatReasoningEffortLabel(request.reasoningEffort) ?? "Default",
+ value: formatEffectiveEffortDisclosure({
+ reasoningEffort: request.reasoningEffort,
+ effortSource: request.effortSource,
+ }),
},
{
id: "status",
diff --git a/role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx b/role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx
new file mode 100644
index 000000000..34c9ea27c
--- /dev/null
+++ b/role-model-router/apps/runtime-ui/app/routes/router-candidates.test.tsx
@@ -0,0 +1,31 @@
+import { readFileSync } from "node:fs";
+import { createElement } from "react";
+import { renderToStaticMarkup } from "react-dom/server";
+import { RouterProvider, createMemoryRouter } from "react-router";
+import { describe, expect, test } from "vitest";
+
+import RouterCandidatesRoute from "./router-candidates";
+
+const source = readFileSync(new URL("./router-candidates.tsx", import.meta.url), "utf8");
+
+describe("run 106 R11 candidate surface truthfulness", () => {
+ test("renders the candidate inventory loading shell", () => {
+ const router = createMemoryRouter(
+ [{ path: "/", element: createElement(RouterCandidatesRoute) }],
+ { initialEntries: ["/"] },
+ );
+ expect(renderToStaticMarkup(createElement(RouterProvider, { router }))).toContain(
+ "Loading routing candidates",
+ );
+ });
+
+ test("co-displays effective effort and labeled evidence on every arm row", () => {
+ expect(source).toContain("formatEffortArmTruthDisclosure");
+ expect(source).toContain('label: "Effort"');
+ expect(source).toContain("relatedEffortOverallScore");
+ });
+
+ test("never claims every candidate's benchmark evidence is exact", () => {
+ expect(source).not.toContain("CAP is exact endpoint benchmark capability");
+ });
+});
diff --git a/role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx b/role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx
index df66c4d96..91b5e57df 100644
--- a/role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/router-candidates.tsx
@@ -10,6 +10,7 @@ import {
} from "../components/page-primitives";
import { bodyStrongTextClassName, cardClassName } from "../lib/design-system";
import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";
+import { formatEffortArmTruthDisclosure } from "../lib/effort-truth";
import { formatScore } from "../lib/format-score";
import { type RouterCandidate, fetchRouterCandidates } from "../lib/runtime-api";
@@ -111,7 +112,7 @@ export default function RouterCandidatesRoute() {
{candidates.length === 0 ? (
@@ -160,6 +161,18 @@ export default function RouterCandidatesRoute() {
label: "Cap",
value: formatScore(capability?.overallScore),
},
+ {
+ id: "effort",
+ label: "Effort",
+ value: formatEffortArmTruthDisclosure({
+ reasoningEffort: candidate.reasoningEffort,
+ effortSource: candidate.effortSource,
+ evidence: {
+ evidenceSource: capability?.evidenceSource,
+ relatedEffortOverallScore: capability?.relatedEffortOverallScore,
+ },
+ }),
+ },
{
id: "p50",
label: "Live p50",
diff --git a/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx b/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx
index 32189e575..4e2fc5f29 100644
--- a/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.test.tsx
@@ -44,3 +44,24 @@ describe("run 103 decision surfaces", () => {
expect(listSource).not.toContain("formatRoutingModeLabel");
});
});
+
+describe("run 106 R11 decision surface truthfulness", () => {
+ test("surfaces effective effort, evidence exactness, and effort resolution", () => {
+ expect(detailSource).toContain("formatEffectiveEffortDisclosure");
+ expect(detailSource).toContain("classifyEffortEvidence");
+ expect(detailSource).toContain("formatEffortEvidenceLabel");
+ expect(detailSource).toContain("readEffortResolutionKind");
+ expect(detailSource).toContain("formatEffortResolutionLabel");
+ expect(detailSource).toContain("isProminentEffortResolution");
+ expect(detailSource).toContain("no effort resolution recorded");
+ });
+
+ test("labels benchmark provenance instead of echoing a raw source string", () => {
+ expect(detailSource).not.toContain("· ${benchmarkDecision.evidenceSource}");
+ });
+
+ test("the decision list rows co-display effective effort", () => {
+ expect(listSource).toContain("formatEffectiveEffortDisclosure");
+ expect(listSource).toContain('label: "Effort"');
+ });
+});
diff --git a/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx b/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx
index 89c4bfedf..186a21b85 100644
--- a/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/router-decision-detail.tsx
@@ -25,6 +25,14 @@ import {
supportingTextClassName,
} from "../lib/design-system";
import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";
+import {
+ classifyEffortEvidence,
+ formatEffectiveEffortDisclosure,
+ formatEffortEvidenceLabel,
+ formatEffortResolutionLabel,
+ isProminentEffortResolution,
+ readEffortResolutionKind,
+} from "../lib/effort-truth";
import { type RouterDecisionDetail, fetchRouterDecisionDetail } from "../lib/runtime-api";
export default function RouterDecisionDetailRoute() {
@@ -75,6 +83,7 @@ export default function RouterDecisionDetailRoute() {
const strategyReceipt = readStrategyReceipt(detail.routingDiagnostics);
const latencyReceipt = readLatencyReceipt(detail.routingDiagnostics);
const aliasPostureReceipt = readAliasPostureReceipt(detail.routingDiagnostics);
+ const effortResolutionKind = readEffortResolutionKind(detail.routingDiagnostics);
return (
@@ -121,10 +130,27 @@ export default function RouterDecisionDetailRoute() {
reasoningEffort: detail.reasoningEffort,
})}
+
+ {formatEffectiveEffortDisclosure({
+ reasoningEffort: detail.reasoningEffort,
+ effortSource: detail.effortSource,
+ })}
+
{strategyReceipt ? strategyReceipt.strategyLabel : "no strategy receipt"}
+
+ {effortResolutionKind
+ ? formatEffortResolutionLabel(effortResolutionKind)
+ : "no effort resolution recorded"}
+
{detail.fallbackEndpointIds.length} fallback
{detail.fallbackEndpointIds.length === 1 ? "" : "s"}
@@ -170,7 +196,11 @@ export default function RouterDecisionDetailRoute() {
{benchmarkDecision.runId ?? "profile-derived evidence"}
{benchmarkDecision.runMode ? ` · ${benchmarkDecision.runMode}` : ""}
- {` · ${benchmarkDecision.evidenceSource}`}
+ {` · ${formatEffortEvidenceLabel(
+ classifyEffortEvidence({
+ evidenceSource: benchmarkDecision.evidenceSource,
+ }),
+ )}`}
{benchmarkDecision.reason ? ` · ${benchmarkDecision.reason}` : ""}
diff --git a/role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx b/role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx
index d3f506433..222a8feea 100644
--- a/role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx
+++ b/role-model-router/apps/runtime-ui/app/routes/router-decisions.tsx
@@ -17,6 +17,7 @@ import {
supportingTextClassName,
} from "../lib/design-system";
import { formatEndpointDisplayPath, formatModelIdentity } from "../lib/effort-identity";
+import { formatEffectiveEffortDisclosure } from "../lib/effort-truth";
import { startDeferredLiveRefresh } from "../lib/live-refresh";
import {
type RouterDecisionListItem,
@@ -111,6 +112,14 @@ export default function RouterDecisionsRoute() {
reasoningEffort: decision.reasoningEffort,
}),
},
+ {
+ id: "effort",
+ label: "Effort",
+ value: formatEffectiveEffortDisclosure({
+ reasoningEffort: decision.reasoningEffort,
+ effortSource: decision.effortSource,
+ }),
+ },
{
id: "strategy",
label: "Strategy",
diff --git a/role-model-router/packages/adapter-execution/src/index.ts b/role-model-router/packages/adapter-execution/src/index.ts
index 614658152..273860f47 100644
--- a/role-model-router/packages/adapter-execution/src/index.ts
+++ b/role-model-router/packages/adapter-execution/src/index.ts
@@ -70,6 +70,13 @@ export interface PromptCacheRequest {
export interface RuntimeExecutionReasoningRequest {
readonly channel?: "reasoning" | "thinking";
readonly effort?: string;
+ readonly effortPolicy?: "strict" | "preferred" | "router";
+ /**
+ * Run 106 R4: the client's reasoning-effort source. "disabled" marks OpenAI's disabled-reasoning
+ * convention (reasoning.effort === "none" | "off"); "named" marks a concrete named effort level;
+ * "none" marks no client preference. Absent on legacy callers, which resolve from effort alone.
+ */
+ readonly effortSource?: "named" | "disabled" | "none";
readonly raw?: Record;
}
@@ -386,6 +393,29 @@ function findCloudSource(
return registrySources.cloud.find((source) => source.endpointId === endpointId);
}
+/**
+ * Run 106 H-1: a provider-default endpoint expands into one fixed arm per
+ * adapter-executable declared level (base endpoint id plus an encoded-effort
+ * suffix). Those arms share the provider-default source's execution mapping;
+ * resolve them back to that base source when the exact endpoint id is not
+ * itself a durable source.
+ */
+function resolveExpandedArmCloudSource(
+ registrySources: RegistrySources,
+ endpointId: string,
+ reasoningEffort: string | null | undefined,
+): RegistrySources["cloud"][number] | undefined {
+ if (typeof reasoningEffort !== "string" || reasoningEffort.length === 0) {
+ return undefined;
+ }
+ const suffix = `-${encodeURIComponent(reasoningEffort)}`;
+ if (!endpointId.endsWith(suffix)) {
+ return undefined;
+ }
+ const baseEndpointId = endpointId.slice(0, -suffix.length);
+ return registrySources.cloud.find((source) => source.endpointId === baseEndpointId);
+}
+
function findLocalSource(
registrySources: RegistrySources,
endpointId: string,
@@ -408,7 +438,13 @@ export function resolveExecutionTarget(
throw new Error(`Chosen endpoint ${endpointId} is not present in the registry result.`);
}
- const cloudSource = findCloudSource(input.registrySources, endpointId);
+ const cloudSource =
+ findCloudSource(input.registrySources, endpointId) ??
+ resolveExpandedArmCloudSource(
+ input.registrySources,
+ endpointId,
+ candidate.identity.reasoning_effort,
+ );
if (cloudSource) {
const account = input.accounts.find(
(entry) => entry.providerAccountId === cloudSource.providerAccountId,
diff --git a/role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts b/role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts
new file mode 100644
index 000000000..df5fc2b0c
--- /dev/null
+++ b/role-model-router/packages/adapter-execution/test/run106-arm-execution-mapping.test.ts
@@ -0,0 +1,146 @@
+import { describe, expect, test } from "vitest";
+
+import { resolveExecutionTarget } from "../src/index.js";
+
+const provenance = {
+ vendor: "models.dev",
+ commit: "test-catalog",
+ capturedAt: "2026-05-05T00:00:00Z",
+ schemaVersion: "1",
+};
+
+const baseEndpointId = "deepseek.personal.global.deepseek-v4-pro";
+const expandedEndpointId = `${baseEndpointId}-max`;
+const modelId = "deepseek/deepseek-v4-pro";
+const providerAccountId = "deepseek.personal";
+
+const catalog = {
+ catalogVersion: "1",
+ source: provenance,
+ providers: [
+ {
+ providerId: "deepseek",
+ displayName: "DeepSeek",
+ npmPackage: "@role-model-router/provider-deepseek",
+ providerKind: "provider-openai",
+ authFamily: "api-key",
+ adapterFamily: "ai-sdk-openai-compatible",
+ apiBase: "https://api.deepseek.com/v1",
+ docsUrl: null,
+ envVars: ["DEEPSEEK_API_KEY"],
+ supportedAuthModes: ["api-key-static"],
+ controlPlaneRequirements: [],
+ localOverrideApplied: false,
+ upstreamProvenance: provenance,
+ },
+ ],
+ models: [
+ {
+ modelId,
+ providerId: "deepseek",
+ providerKind: "provider-openai",
+ authFamily: "api-key",
+ displayName: "DeepSeek V4 Pro",
+ version: "1",
+ capabilities: ["text.chat", "reasoning"],
+ modalities: ["text"],
+ contextWindow: 262_144,
+ maxOutputTokens: 8192,
+ pricing: null,
+ requestShapeHints: null,
+ experimentalModes: [],
+ reasoningEffortLevels: ["medium", "max"],
+ reasoningOptionKinds: ["effort"],
+ extendsProvenance: { baseModelId: null, chain: [] },
+ localOverrideApplied: false,
+ localNotes: [],
+ upstreamProvenance: provenance,
+ },
+ ],
+};
+
+const account = {
+ providerAccountId,
+ providerId: "deepseek",
+ providerKind: "provider-openai",
+ orgScope: "personal",
+ accountScope: "default",
+ credentialRef: { backend: "env", ref: "DEEPSEEK_API_KEY" },
+ authMode: "api-key-static",
+ regionPolicy: { mode: "prefer", regions: ["global"] },
+ baseUrlOverride: null,
+ allowedModels: [modelId],
+ deniedModels: [],
+ entitlementTags: ["chat"],
+ budgetPolicyRef: "budget.default",
+ quotaPolicyRef: "quota.default",
+ status: "active",
+ healthStatus: "healthy",
+ rotationState: "stable",
+};
+
+const registry = {
+ endpoints: [
+ {
+ identity: {
+ endpoint_id: expandedEndpointId,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: modelId,
+ runtime_version: "1",
+ region: "global",
+ reasoning_effort: "max",
+ },
+ declared: {
+ endpoint_id: expandedEndpointId,
+ capabilities: ["text.chat"],
+ modalities: ["text"],
+ max_context_tokens: 262_144,
+ tool_calling: { supported: false, style: "openai" },
+ supports_embeddings: false,
+ },
+ status: "active",
+ },
+ ],
+ diagnostics: [],
+ lifecycleSummary: { active: 1, degraded: 0, offline: 0 },
+};
+
+const registrySources = {
+ cloud: [
+ {
+ endpointId: baseEndpointId,
+ providerAccountId,
+ modelId,
+ region: "global",
+ endpointKind: "remote-openai-compatible",
+ servingSource: "remote-service",
+ lifecycleState: "active",
+ healthStatus: "healthy",
+ reasoningEffort: null,
+ requestShapeHints: null,
+ },
+ ],
+ local: [],
+};
+
+describe("run106 arm execution mapping (H-1)", () => {
+ test("resolves an expanded per-level arm back to its provider-default base source", () => {
+ const target = resolveExecutionTarget({
+ routeResult: {
+ decision: { chosen_endpoint_id: expandedEndpointId },
+ } as never,
+ catalog: catalog as never,
+ accounts: [account] as never,
+ registry: registry as never,
+ registrySources: registrySources as never,
+ });
+
+ expect(target.endpointId).toBe(expandedEndpointId);
+ expect(target.modelId).toBe(modelId);
+ expect(target.providerAccountId).toBe(providerAccountId);
+ expect(target.adapterFamily).toBe("ai-sdk-openai-compatible");
+ expect(target.candidate.identity.reasoning_effort).toBe("max");
+ });
+});
diff --git a/role-model-router/packages/catalog/src/index.ts b/role-model-router/packages/catalog/src/index.ts
index 5337ce8ee..f0909e8c1 100644
--- a/role-model-router/packages/catalog/src/index.ts
+++ b/role-model-router/packages/catalog/src/index.ts
@@ -664,6 +664,8 @@ import { applyAliasedCatalogPricing } from "./token-economics.js";
export {
resolveReasoningEffortLevels,
+ resolveAdapterGatedReasoningEfforts,
+ REASONING_EFFORT_SERIALIZER_VERSION_BY_ADAPTER,
type ReasoningEffortAdapterCapability,
type ReasoningEffortFallback,
type ReasoningEffortResolutionInput,
diff --git a/role-model-router/packages/catalog/src/reasoning.ts b/role-model-router/packages/catalog/src/reasoning.ts
index 8f8bc887c..dda5cd58e 100644
--- a/role-model-router/packages/catalog/src/reasoning.ts
+++ b/role-model-router/packages/catalog/src/reasoning.ts
@@ -60,3 +60,49 @@ export function resolveReasoningEffortLevels(input: ReasoningEffortResolutionInp
const supported = new Set(input.adapter.serializers);
return candidates.filter((candidate) => supported.has(candidate));
}
+
+/**
+ * Tested reasoning-effort serializer contracts keyed by provider adapter family.
+ * Only these families can turn a catalog-declared effort level into an
+ * executable arm; any other family yields no executable effort set.
+ */
+export const REASONING_EFFORT_SERIALIZER_VERSION_BY_ADAPTER = new Map([
+ ["ai-sdk-openai-compatible", "run91.openai-compatible.reasoning-effort.v1"],
+ ["litellm-proxy", "run91.openai-compatible.reasoning-effort.v1"],
+ ["codex-subscription-responses", "run91.codex-responses.reasoning-effort.v1"],
+ ["ai-sdk-anthropic", "run93.anthropic.thinking-budget-tokens.v1"],
+]);
+
+/**
+ * The adapter-executable subset of a model's catalog-declared reasoning-effort
+ * levels. A catalog declaration alone is never routable: the level must also
+ * pass through a versioned, tested serializer for the resolved adapter family.
+ */
+export function resolveAdapterGatedReasoningEfforts(input: {
+ readonly providerId: string;
+ readonly modelId: string;
+ readonly capabilities: readonly string[];
+ readonly catalogLevels: readonly string[];
+ readonly adapterFamily: string | null;
+}): readonly string[] {
+ const adapterFamily = input.adapterFamily;
+ const version =
+ adapterFamily === null
+ ? undefined
+ : REASONING_EFFORT_SERIALIZER_VERSION_BY_ADAPTER.get(adapterFamily);
+ return resolveReasoningEffortLevels({
+ providerId: input.providerId,
+ modelId: input.modelId,
+ capabilities: input.capabilities,
+ reasoningEffortLevels: input.catalogLevels,
+ reasoningOptionKinds: ["effort"],
+ adapter:
+ version && adapterFamily
+ ? {
+ family: adapterFamily,
+ version,
+ serializers: input.catalogLevels,
+ }
+ : null,
+ });
+}
diff --git a/role-model-router/packages/core/src/reason-codes.ts b/role-model-router/packages/core/src/reason-codes.ts
index 82a82c349..e308073b0 100644
--- a/role-model-router/packages/core/src/reason-codes.ts
+++ b/role-model-router/packages/core/src/reason-codes.ts
@@ -47,4 +47,6 @@ export const SELECTION_REASON_CODES = [
"BENCHMARK_GROUP_SCORE",
"BENCHMARK_FALLBACK_OVERALL_SCORE",
"TELEMETRY_TASK_PERFORMANCE",
+ "NON_INFERIOR_PROMOTION",
+ "EFFORT_FALLBACK_APPLIED",
] as const;
diff --git a/role-model-router/packages/core/src/router.ts b/role-model-router/packages/core/src/router.ts
index ad229a308..3c96e65e0 100644
--- a/role-model-router/packages/core/src/router.ts
+++ b/role-model-router/packages/core/src/router.ts
@@ -343,7 +343,7 @@ type ScoringMetricName =
| "reliability"
| "preference";
-type MetricSource = "measured" | "declared" | "default" | "catalog" | "benchmark";
+type MetricSource = "measured" | "declared" | "default" | "catalog" | "benchmark" | "borrowed";
type MetricEntry = {
value: number;
source: MetricSource;
@@ -838,6 +838,140 @@ function applyTelemetryAdvisory(
};
}
+export function computeEffortUnionAndIntersection(input: {
+ readonly modelEfforts: readonly (readonly (string | null)[])[];
+}): { union: readonly string[]; portableIntersection: readonly string[] } {
+ const union = new Set();
+ const models = input.modelEfforts.map(
+ (efforts) => new Set(efforts.filter((effort): effort is string => effort !== null)),
+ );
+ for (const efforts of models) {
+ for (const effort of efforts) {
+ union.add(effort);
+ }
+ }
+ let intersection: Set | null = null;
+ if (models.length > 0) {
+ intersection = new Set(models[0]);
+ for (let index = 1; index < models.length; index += 1) {
+ intersection = new Set([...intersection].filter((effort) => models[index].has(effort)));
+ }
+ }
+ return {
+ union: [...union].sort(),
+ portableIntersection: [...(intersection ?? [])].sort(),
+ };
+}
+
+export function shouldPreferNonInferiorChallenger(input: {
+ readonly incumbentQuality: number;
+ readonly challengerQuality: number;
+ readonly qualityMargin: number;
+ readonly incumbentLatencyMs: number;
+ readonly challengerLatencyMs: number;
+ readonly incumbentCostUsd: number;
+ readonly challengerCostUsd: number;
+}): boolean {
+ const nonInferior = input.challengerQuality >= input.incumbentQuality - input.qualityMargin;
+ const faster = input.challengerLatencyMs < input.incumbentLatencyMs;
+ const cheaper = input.challengerCostUsd < input.incumbentCostUsd;
+ return nonInferior && faster && cheaper;
+}
+
+/**
+ * Run 106 R8 (F5): non-inferiority preference thresholds. After weighted scoring, a challenger
+ * arm may outrank the weighted leader when it is (1) statistically non-inferior on quality — its
+ * quality is within NON_INFERIORITY_QUALITY_MARGIN of the leader — and (2) materially faster AND
+ * materially cheaper. "Material" is a documented floor so noise-level latency/cost differences
+ * cannot flip a stable ranking. Missing quality never establishes non-inferiority: the rule only
+ * fires when both arms carry a non-default quality metric.
+ */
+const NON_INFERIORITY_QUALITY_MARGIN = 0.05;
+/** A challenger must beat the leader by at least this many milliseconds to count as "faster". */
+const NON_INFERIORITY_MIN_LATENCY_ADVANTAGE_MS = 200;
+/** A challenger must be at least this fraction cheaper than the leader to count as "cheaper". */
+const NON_INFERIORITY_MIN_COST_ADVANTAGE_FRACTION = 0.1;
+
+function getScoredCostUsd(scored: CandidateScoreResult): number {
+ const estimated = scored.metric_breakdown.cost.raw?.estimated_request_usd;
+ if (typeof estimated === "number") {
+ return estimated;
+ }
+ const per1k = scored.metric_breakdown.cost.raw?.cost_per_1k_tokens_est;
+ return typeof per1k === "number" ? per1k : DEFAULT_COST_TARGET;
+}
+
+/**
+ * Run 106 R8 (M-1): only exact benchmark quality can establish non-inferiority. A borrowed
+ * related-effort prior (source "borrowed"), a default, or any non-benchmark signal counts as
+ * missing quality for this gate, so a discounted cross-effort prior can never outrank an arm on
+ * the strength of quality it did not itself measure.
+ */
+function isExactBenchmarkQuality(entry: MetricEntry): boolean {
+ return entry.source === "benchmark" && entry.raw?.benchmark_reason !== "related_effort_prior";
+}
+
+/**
+ * Run 106 R8: return the index of the highest-ranked challenger that is statistically non-inferior
+ * on quality and materially faster and cheaper than the weighted leader, or -1 when none qualifies.
+ */
+function findNonInferiorChallengerIndex(scored: readonly CandidateScoreResult[]): number {
+ const leader = scored[0];
+ if (!leader || !isExactBenchmarkQuality(leader.metric_breakdown.quality)) {
+ return -1;
+ }
+ const incumbentQuality = leader.metric_breakdown.quality.value;
+ const incumbentLatencyMs = leader.tie_break.latency_ms;
+ const incumbentCostUsd = getScoredCostUsd(leader);
+
+ for (let index = 1; index < scored.length; index += 1) {
+ const challenger = scored[index];
+ if (!isExactBenchmarkQuality(challenger.metric_breakdown.quality)) {
+ continue;
+ }
+ const challengerLatencyMs = challenger.tie_break.latency_ms;
+ const challengerCostUsd = getScoredCostUsd(challenger);
+
+ const latencyAdvantageMs = incumbentLatencyMs - challengerLatencyMs;
+ const costAdvantageFraction =
+ incumbentCostUsd > 0 ? (incumbentCostUsd - challengerCostUsd) / incumbentCostUsd : 0;
+ if (latencyAdvantageMs < NON_INFERIORITY_MIN_LATENCY_ADVANTAGE_MS) {
+ continue;
+ }
+ if (costAdvantageFraction < NON_INFERIORITY_MIN_COST_ADVANTAGE_FRACTION) {
+ continue;
+ }
+ if (
+ shouldPreferNonInferiorChallenger({
+ incumbentQuality,
+ challengerQuality: challenger.metric_breakdown.quality.value,
+ qualityMargin: NON_INFERIORITY_QUALITY_MARGIN,
+ incumbentLatencyMs,
+ challengerLatencyMs,
+ incumbentCostUsd,
+ challengerCostUsd,
+ })
+ ) {
+ return index;
+ }
+ }
+ return -1;
+}
+
+export function resolveBorrowedQualityPrior(input: {
+ readonly relatedEffortScore?: number;
+ readonly discountFactor?: number;
+}): { value: number; source: "borrowed" } | null {
+ const score = input.relatedEffortScore;
+ if (typeof score !== "number" || !Number.isFinite(score)) {
+ return null;
+ }
+ const discount = typeof input.discountFactor === "number" ? input.discountFactor : 0.7;
+ // Symmetric shrink toward neutral (0.5): a borrowed sibling-effort score regresses toward the
+ // unknown default rather than collapsing to zero. Documented in R5.
+ return { value: clamp(0.5 + (score - 0.5) * discount), source: "borrowed" };
+}
+
export function getQualityMetric(
candidate: EndpointCandidate,
input: RouteRequestInput,
@@ -996,6 +1130,23 @@ export function getQualityMetric(
});
}
+ const relatedPrior = resolveBorrowedQualityPrior({
+ relatedEffortScore: candidate.benchmarkCapability?.relatedEffortOverallScore ?? undefined,
+ });
+ if (relatedPrior !== null) {
+ // Run 106 R5 (M-1): a cross-effort prior is a borrowed signal, never exact benchmark evidence.
+ // Keep the returned source ("borrowed") so the R8 non-inferiority gate can refuse it as missing.
+ return applyTelemetryAdvisory(input, candidate, {
+ value: relatedPrior.value,
+ source: relatedPrior.source,
+ raw: {
+ related_effort_prior: true,
+ related_effort_score: candidate.benchmarkCapability?.relatedEffortOverallScore,
+ benchmark_reason: "related_effort_prior",
+ },
+ });
+ }
+
return applyTelemetryAdvisory(input, candidate, {
value: 0.5,
source: "default",
@@ -1878,6 +2029,29 @@ export function routeRequest(input: RouteRequestInput): RouterDecisionRecord {
);
});
+ // Run 106 R8 (F5): a statistically non-inferior + materially faster/cheaper arm may outrank a
+ // dominated weighted leader. This runs after weighted scoring and before the advisory, so the
+ // advisory re-ranks on top of the non-inferiority-adjusted order.
+ let nonInferiorityPromotion: RouterDecisionRecord["non_inferiority_promotion"] | undefined;
+ const nonInferiorityIndex = findNonInferiorChallengerIndex(scored);
+ if (nonInferiorityIndex > 0) {
+ const displacedEndpointId = scored[0].endpoint_id;
+ const [promoted] = scored.splice(nonInferiorityIndex, 1);
+ if (promoted) {
+ scored.unshift(promoted);
+ // Run 106 R8 (M-2): receipt the rule's thresholds, the promoted/displaced arms, and the fact
+ // that it changed the weighted selection.
+ nonInferiorityPromotion = {
+ promoted_endpoint_id: promoted.endpoint_id,
+ displaced_endpoint_id: displacedEndpointId,
+ quality_margin: NON_INFERIORITY_QUALITY_MARGIN,
+ min_latency_advantage_ms: NON_INFERIORITY_MIN_LATENCY_ADVANTAGE_MS,
+ min_cost_advantage_fraction: NON_INFERIORITY_MIN_COST_ADVANTAGE_FRACTION,
+ changed_weighted_selection: true,
+ };
+ }
+ }
+
// Run 98 R5: the advisory is consulted only here, after hard eligibility and scoring,
// and only within the policy's score band.
const advisoryOutcome = evaluateRouteAdvisoryConsideration({
@@ -1912,10 +2086,37 @@ export function routeRequest(input: RouteRequestInput): RouterDecisionRecord {
? true
: Math.abs((chosen?.total_score ?? 0) - (runnerUp?.total_score ?? 0)) <=
ROUTER_SCORE_TIE_EPSILON);
+ const chosenCandidate = chosen
+ ? eligible.find((candidate) => candidate.identity.endpoint_id === chosen.endpoint_id)
+ : undefined;
+ const chosenReasoningEffort = chosenCandidate?.identity.reasoning_effort ?? null;
+ const effortResolution = normalizedInput.effortResolution;
+ const requestedEffort = effortResolution?.requestedEffort ?? null;
+ const effectiveEffort = effortResolution?.effectiveEffort ?? null;
+ const exactEffort = requestedEffort ?? effectiveEffort;
+ const effortExactArmCountBeforeHardEligibility =
+ effortResolution === undefined || exactEffort === null
+ ? undefined
+ : normalizedInput.candidates.filter(
+ (candidate) => candidate.identity.reasoning_effort === exactEffort,
+ ).length;
+ const effortExactArmCountAfterHardEligibility =
+ effortResolution === undefined || exactEffort === null
+ ? undefined
+ : eligible.filter((candidate) => candidate.identity.reasoning_effort === exactEffort).length;
+ // Run 106 R3 (L-4): under exact_fallback_expanded the effective effort is the client's request,
+ // while the chosen arm may be a non-exact fallback. Mark that disagreement explicitly so a
+ // consumer never mistakes a fallback arm's reasoning_effort for the requested effort.
+ const effortFallbackApplied =
+ Boolean(chosen) &&
+ effortResolution?.resolution === "exact_fallback_expanded" &&
+ chosenReasoningEffort !== effectiveEffort;
const selectionReasons: SelectionReasonCode[] = chosen
? unique([
"BEST_TOTAL_SCORE",
...(tieBreakApplied ? (["TIE_BREAK_APPLIED"] as const) : []),
+ ...(nonInferiorityPromotion ? (["NON_INFERIOR_PROMOTION"] as const) : []),
+ ...(effortFallbackApplied ? (["EFFORT_FALLBACK_APPLIED"] as const) : []),
...chosen.selectionReasons,
...(scored.length > 1 ? (["FALLBACK_CHAIN_COMPUTED"] as const) : []),
])
@@ -1928,10 +2129,6 @@ export function routeRequest(input: RouteRequestInput): RouterDecisionRecord {
...candidate
}) => candidate,
);
- const chosenCandidate = chosen
- ? eligible.find((candidate) => candidate.identity.endpoint_id === chosen.endpoint_id)
- : undefined;
- const chosenReasoningEffort = chosenCandidate?.identity.reasoning_effort ?? null;
return {
routing_decision_id: `decision-${normalizedInput.request.requestId}`,
@@ -1945,9 +2142,33 @@ export function routeRequest(input: RouteRequestInput): RouterDecisionRecord {
...(chosen
? {
reasoning_effort: chosenReasoningEffort,
- effort_source: chosenReasoningEffort === null ? ("none" as const) : ("variant" as const),
+ effort_source:
+ effortResolution?.source ??
+ (chosenReasoningEffort === null ? ("provider_default" as const) : ("named" as const)),
+ }
+ : {}),
+ ...(effortResolution
+ ? {
+ effort_resolution: effortResolution.resolution,
+ effective_effort: effortResolution.effectiveEffort,
+ requested_effort: requestedEffort,
+ requested_policy: effortResolution.requestedPolicy ?? null,
+ ...(effortExactArmCountBeforeHardEligibility === undefined
+ ? {}
+ : {
+ effort_exact_arm_count_before_hard_eligibility:
+ effortExactArmCountBeforeHardEligibility,
+ }),
+ ...(effortExactArmCountAfterHardEligibility === undefined
+ ? {}
+ : {
+ effort_exact_arm_count_after_hard_eligibility:
+ effortExactArmCountAfterHardEligibility,
+ }),
+ ...(effortFallbackApplied ? { effort_fallback_applied: true } : {}),
}
: {}),
+ ...(nonInferiorityPromotion ? { non_inferiority_promotion: nonInferiorityPromotion } : {}),
fallback_endpoint_ids: orderedFallbacks.slice(1).map((candidate) => candidate.endpoint_id),
selection_reasons: selectionReasons,
used_measured: chosen?.usedMeasured ?? false,
diff --git a/role-model-router/packages/core/src/types.ts b/role-model-router/packages/core/src/types.ts
index c9c6602c3..738dd5854 100644
--- a/role-model-router/packages/core/src/types.ts
+++ b/role-model-router/packages/core/src/types.ts
@@ -112,6 +112,7 @@ export interface EndpointCandidate {
readonly benchmarkCapability?: {
readonly evidenceSource?: "run-artifact" | "profile-derived";
readonly overallScore?: number | null;
+ readonly relatedEffortOverallScore?: number | null;
readonly lastRunId?: string | null;
readonly lastRunCompletedAtMs?: number | null;
readonly lastRunMode?: "quick" | "full" | null;
@@ -209,6 +210,37 @@ export interface RoutingIntent {
}[];
}
+export type EffortResolutionKind =
+ | "router_managed"
+ | "exact_primary"
+ | "exact_fallback_expanded"
+ | "unsupported_fallback"
+ | "strict_rejected"
+ | "equivalent_mapped";
+
+export interface EffortResolution {
+ readonly resolution: EffortResolutionKind;
+ readonly effectiveEffort: string | null;
+ /**
+ * Run 106 R10: the client's requested reasoning effort, when one was supplied. Carries the
+ * client request across the router so the decision record can explain what was requested even
+ * when it degrades to unsupported_fallback (effectiveEffort null).
+ */
+ readonly requestedEffort?: string | null;
+ /**
+ * Run 106 R10: the client's requested effort policy (strict | preferred | router). Absent when
+ * the client omitted effort and the host resolved router-managed.
+ */
+ readonly requestedPolicy?: "strict" | "preferred" | "router";
+ /**
+ * Run 106 R4: the client's effort source (named | disabled | none), carried so the decision can
+ * emit the lossless four-state effort_source instead of collapsing no-client-preference onto
+ * provider_default. Absent on legacy paths, where the router falls back to the chosen arm's
+ * identity (provider_default | named).
+ */
+ readonly source?: EffortSource;
+}
+
export interface RouteRequestInput {
request: RoutingRequest;
candidates: readonly EndpointCandidate[];
@@ -226,6 +258,12 @@ export interface RouteRequestInput {
* exact same decision it produced before.
*/
advisoryConsideration?: RouteAdvisoryConsiderationInput;
+ /**
+ * Run 106 R10: the effort policy resolution the host computed before narrowing the pool.
+ * Recorded verbatim on the decision so provenance (resolution kind + effective effort)
+ * survives the router's own scoring/selection pass.
+ */
+ effortResolution?: EffortResolution;
}
/**
@@ -349,3 +387,66 @@ export interface RouteAdvisoryConsiderationOutcome {
/** Run 105 C11: present only when the request declared a role (byte-compat when null). */
readonly requestRoleId?: string | null;
}
+
+/**
+ * Run 106 / R4: lossless effort-source states.
+ *
+ * Four mutually-exclusive states keep the effort dimension distinct through every layer:
+ * - `named`: a concrete named reasoning-effort level was requested/applied (reasoningEffort is the level).
+ * - `disabled`: reasoning was explicitly disabled (reasoningEffort is null).
+ * - `provider_default`: the provider-default instance applies (reasoningEffort is null).
+ * - `none`: no client preference; the router manages effort (reasoningEffort is null).
+ */
+export type EffortSource = "named" | "disabled" | "provider_default" | "none";
+
+/**
+ * Historical effort-source values that remain readable and migrate deterministically onto the
+ * canonical `EffortSource` vocabulary. `variant_coerced` keeps its coercion attribution through
+ * the `coerced` flag rather than being silently flattened into a plain named effort.
+ */
+export type LegacyEffortSource = "client" | "variant" | "variant_coerced";
+
+/** Any value that may appear in serialized or persisted rows, including legacy values. */
+export type EffortSourceValue = EffortSource | LegacyEffortSource;
+
+export interface NormalizedEffortSource {
+ readonly source: EffortSource;
+ /** True when the named effort was coerced from a variant (historical `variant_coerced`). */
+ readonly coerced: boolean;
+}
+
+/**
+ * Normalize a persisted or wire effort-source value onto the canonical four-state vocabulary.
+ *
+ * - Canonical values pass through unchanged.
+ * - Legacy named sources (`client`, `variant`) collapse onto `named`; their only distinction was
+ * who named the effort, which the lossless vocabulary does not carry.
+ * - `variant_coerced` stays readable as a coerced `named` effort.
+ * - `null`, `undefined`, and the empty string migrate deterministically to `provider_default`,
+ * matching the historical "null effort means the provider-default instance" semantics.
+ * - Unrecognized values are rejected rather than silently dropped.
+ */
+export function normalizeEffortSource(
+ value: EffortSourceValue | string | null | undefined,
+): NormalizedEffortSource {
+ if (value === null || value === undefined || value === "") {
+ return { source: "provider_default", coerced: false };
+ }
+ switch (value) {
+ case "named":
+ return { source: "named", coerced: false };
+ case "disabled":
+ return { source: "disabled", coerced: false };
+ case "provider_default":
+ return { source: "provider_default", coerced: false };
+ case "none":
+ return { source: "none", coerced: false };
+ case "client":
+ case "variant":
+ return { source: "named", coerced: false };
+ case "variant_coerced":
+ return { source: "named", coerced: true };
+ default:
+ throw new Error(`Unrecognized effort_source value: ${JSON.stringify(value)}.`);
+ }
+}
diff --git a/role-model-router/packages/core/test/routing-intent.test.ts b/role-model-router/packages/core/test/routing-intent.test.ts
index 30c8401d3..a366b6c22 100644
--- a/role-model-router/packages/core/test/routing-intent.test.ts
+++ b/role-model-router/packages/core/test/routing-intent.test.ts
@@ -374,7 +374,7 @@ describe("routing intent metadata", () => {
expect(decision).toMatchObject({
chosen_endpoint_id: "deepseek.flash-high",
reasoning_effort: "high",
- effort_source: "variant",
+ effort_source: "named",
});
expect(decision.scored_candidates[0]).toMatchObject({
endpoint_id: "deepseek.flash-high",
diff --git a/role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts b/role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts
new file mode 100644
index 000000000..9885ed8ed
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-borrowed-quality-prior.test.ts
@@ -0,0 +1,22 @@
+import { describe, expect, it } from "vitest";
+import { resolveBorrowedQualityPrior } from "../src/router.js";
+
+describe("run106 borrowed quality prior", () => {
+ it("borrows a discounted related-effort score", () => {
+ const prior = resolveBorrowedQualityPrior({ relatedEffortScore: 0.958, discountFactor: 0.7 });
+ expect(prior).not.toBeNull();
+ expect(prior?.source).toBe("borrowed");
+ expect(prior?.value).toBeCloseTo(0.8206, 4);
+ });
+ it("clamps the discounted prior to the unit interval", () => {
+ expect(
+ resolveBorrowedQualityPrior({ relatedEffortScore: 1.5, discountFactor: 0.9 })?.value,
+ ).toBe(1);
+ });
+ it("returns null when no related-effort score is available", () => {
+ expect(resolveBorrowedQualityPrior({})).toBeNull();
+ });
+ it("defaults the discount factor to 0.7", () => {
+ expect(resolveBorrowedQualityPrior({ relatedEffortScore: 0.5 })?.value).toBeCloseTo(0.5, 4);
+ });
+});
diff --git a/role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts b/role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts
new file mode 100644
index 000000000..69ddb915b
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-canonical-decision-provenance.test.ts
@@ -0,0 +1,130 @@
+import { describe, expect, test } from "vitest";
+
+import { routeRequest } from "../src/router.js";
+import type { EndpointCandidate, RouteRequestInput, RoutingRequest } from "../src/types.js";
+
+function candidate(
+ endpointId: string,
+ reasoningEffort: string | null,
+ overrides: Partial = {},
+): EndpointCandidate {
+ return {
+ identity: {
+ endpoint_id: endpointId,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: endpointId,
+ runtime_version: "1",
+ region: "global",
+ ...(reasoningEffort === null
+ ? { reasoning_effort: null }
+ : { reasoning_effort: reasoningEffort }),
+ },
+ declared: {
+ endpoint_id: endpointId,
+ capabilities: ["text.chat"],
+ modalities: ["text"],
+ max_context_tokens: 100_000,
+ tool_calling: { supported: false, style: "openai" },
+ supports_embeddings: false,
+ },
+ status: "active",
+ ...overrides,
+ };
+}
+
+const baseRequest: RoutingRequest = {
+ requestId: "run106-canonical-decision-provenance",
+ taskType: "text.chat",
+ requiredCapabilities: [],
+ preferredCapabilities: [],
+ requiredModalities: ["text"],
+ contextTokens: 1000,
+ needsTools: false,
+ strategy: "balanced",
+ preferLocal: false,
+};
+
+function buildInput(overrides: Partial = {}): RouteRequestInput {
+ return {
+ request: baseRequest,
+ candidates: [candidate("provider-default", null)],
+ ...overrides,
+ };
+}
+
+describe("run106 canonical decision provenance (R10)", () => {
+ test("a provider-default chosen arm records effort_source provider_default", () => {
+ const decision = routeRequest(buildInput());
+ expect(decision.effort_source).toBe("provider_default");
+ });
+
+ test("a fixed-effort chosen arm records effort_source named", () => {
+ const decision = routeRequest(buildInput({ candidates: [candidate("fixed-high", "high")] }));
+ expect(decision.reasoning_effort).toBe("high");
+ expect(decision.effort_source).toBe("named");
+ });
+
+ test("the decision records resolution kind and effective effort", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("fixed-high", "high")],
+ effortResolution: {
+ resolution: "exact_primary",
+ effectiveEffort: "high",
+ },
+ }),
+ );
+ expect(decision.effort_resolution).toBe("exact_primary");
+ expect(decision.effective_effort).toBe("high");
+ });
+
+ test("router-managed resolution records a null effective effort", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("fixed-high", "high")],
+ effortResolution: {
+ resolution: "router_managed",
+ effectiveEffort: null,
+ },
+ }),
+ );
+ expect(decision.effort_resolution).toBe("router_managed");
+ expect(decision.effective_effort).toBeNull();
+ });
+
+ test("effortResolution source none records the no-client-preference effort_source", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("provider-default", null)],
+ effortResolution: { resolution: "router_managed", effectiveEffort: null, source: "none" },
+ }),
+ );
+ expect(decision.effort_source).toBe("none");
+ });
+
+ test("effortResolution source disabled records the disabled-reasoning effort_source", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("provider-default", null)],
+ effortResolution: {
+ resolution: "router_managed",
+ effectiveEffort: null,
+ source: "disabled",
+ },
+ }),
+ );
+ expect(decision.effort_source).toBe("disabled");
+ });
+
+ test("effortResolution source named records the named effort_source", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("fixed-high", "high")],
+ effortResolution: { resolution: "exact_primary", effectiveEffort: "high", source: "named" },
+ }),
+ );
+ expect(decision.effort_source).toBe("named");
+ });
+});
diff --git a/role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts b/role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts
new file mode 100644
index 000000000..6fb8fa550
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-effort-source-vocabulary.test.ts
@@ -0,0 +1,37 @@
+import { describe, expect, test } from "vitest";
+
+import { normalizeEffortSource } from "../src/types.js";
+
+describe("Run 106 effort-source vocabulary", () => {
+ test("round-trips all four canonical states losslessly", () => {
+ expect(normalizeEffortSource("named")).toEqual({ source: "named", coerced: false });
+ expect(normalizeEffortSource("disabled")).toEqual({ source: "disabled", coerced: false });
+ expect(normalizeEffortSource("provider_default")).toEqual({
+ source: "provider_default",
+ coerced: false,
+ });
+ expect(normalizeEffortSource("none")).toEqual({ source: "none", coerced: false });
+ });
+
+ test("maps historical named sources onto the named state", () => {
+ expect(normalizeEffortSource("client")).toEqual({ source: "named", coerced: false });
+ expect(normalizeEffortSource("variant")).toEqual({ source: "named", coerced: false });
+ });
+
+ test("keeps historical variant_coerced readable as a coerced named effort", () => {
+ expect(normalizeEffortSource("variant_coerced")).toEqual({ source: "named", coerced: true });
+ });
+
+ test("migrates null, undefined, and empty deterministically to provider_default", () => {
+ expect(normalizeEffortSource(null)).toEqual({ source: "provider_default", coerced: false });
+ expect(normalizeEffortSource(undefined)).toEqual({
+ source: "provider_default",
+ coerced: false,
+ });
+ expect(normalizeEffortSource("")).toEqual({ source: "provider_default", coerced: false });
+ });
+
+ test("rejects unrecognized states instead of silently dropping them", () => {
+ expect(() => normalizeEffortSource("bogus")).toThrow(/effort_source/i);
+ });
+});
diff --git a/role-model-router/packages/core/test/run106-effort-union-intersection.test.ts b/role-model-router/packages/core/test/run106-effort-union-intersection.test.ts
new file mode 100644
index 000000000..5d138d74a
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-effort-union-intersection.test.ts
@@ -0,0 +1,30 @@
+import { describe, expect, it } from "vitest";
+import { computeEffortUnionAndIntersection } from "../src/router.js";
+
+describe("run106 effort union and portable intersection", () => {
+ it("computes union and portable intersection across models", () => {
+ const r = computeEffortUnionAndIntersection({
+ modelEfforts: [
+ ["low", "high", "max"],
+ ["high", "max"],
+ ["low", "high"],
+ ],
+ });
+ expect([...r.union].sort()).toEqual(["high", "low", "max"]);
+ expect([...r.portableIntersection].sort()).toEqual(["high"]);
+ });
+ it("returns an empty intersection when no effort is shared", () => {
+ const r = computeEffortUnionAndIntersection({ modelEfforts: [["low"], ["max"]] });
+ expect(r.portableIntersection).toEqual([]);
+ });
+ it("ignores null provider-default slots in the union", () => {
+ const r = computeEffortUnionAndIntersection({ modelEfforts: [["low", null], ["low"]] });
+ expect(r.union).toEqual(["low"]);
+ expect(r.portableIntersection).toEqual(["low"]);
+ });
+ it("an empty pool has an empty union and intersection", () => {
+ const r = computeEffortUnionAndIntersection({ modelEfforts: [] });
+ expect(r.union).toEqual([]);
+ expect(r.portableIntersection).toEqual([]);
+ });
+});
diff --git a/role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts b/role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts
new file mode 100644
index 000000000..d3b707832
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-non-inferiority-ranking.test.ts
@@ -0,0 +1,105 @@
+import { describe, expect, test } from "vitest";
+
+import { routeRequest } from "../src/router.js";
+import type { EndpointCandidate, RouteRequestInput, RoutingRequest } from "../src/types.js";
+
+function candidate(
+ endpointId: string,
+ overrides: Partial = {},
+): EndpointCandidate {
+ return {
+ identity: {
+ endpoint_id: endpointId,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: endpointId,
+ runtime_version: "1",
+ region: "global",
+ },
+ declared: {
+ endpoint_id: endpointId,
+ capabilities: ["text.chat"],
+ modalities: ["text"],
+ max_context_tokens: 100_000,
+ tool_calling: { supported: false, style: "openai" },
+ supports_embeddings: false,
+ },
+ status: "active",
+ ...overrides,
+ };
+}
+
+const baseRequest: RoutingRequest = {
+ requestId: "run106-non-inferiority-ranking",
+ taskType: "text.chat",
+ requiredCapabilities: [],
+ preferredCapabilities: [],
+ requiredModalities: ["text"],
+ contextTokens: 1000,
+ needsTools: false,
+ strategy: "balanced",
+ preferLocal: false,
+};
+
+function buildInput(): RouteRequestInput {
+ return {
+ request: baseRequest,
+ candidates: [
+ candidate("incumbent-dominated", {
+ observed: {
+ latency_ms_p50: 11_000,
+ latency_ms_p95: 11_000,
+ tokens_per_sec: 50,
+ failure_rate: 0,
+ cost_per_1k_tokens_est: 0.4,
+ measured_at_ms: Date.now(),
+ },
+ benchmarkCapability: { overallScore: 0.95 },
+ routingSignals: {
+ catalogCostEstimate: {
+ canonicalModelId: "incumbent-dominated",
+ tokenEconomicsSource: "catalog",
+ inputPer1M: null,
+ outputPer1M: null,
+ estimatedRequestUsd: 0.4,
+ cost_per_1k_tokens_est: 0.4,
+ },
+ },
+ }),
+ candidate("challenger-non-inferior", {
+ observed: {
+ latency_ms_p50: 7_000,
+ latency_ms_p95: 7_000,
+ tokens_per_sec: 50,
+ failure_rate: 0,
+ cost_per_1k_tokens_est: 0.25,
+ measured_at_ms: Date.now(),
+ },
+ benchmarkCapability: { overallScore: 0.91 },
+ routingSignals: {
+ catalogCostEstimate: {
+ canonicalModelId: "challenger-non-inferior",
+ tokenEconomicsSource: "catalog",
+ inputPer1M: null,
+ outputPer1M: null,
+ estimatedRequestUsd: 0.25,
+ cost_per_1k_tokens_est: 0.25,
+ },
+ },
+ }),
+ ],
+ };
+}
+
+describe("run106 non-inferiority ranking (R8 integration)", () => {
+ test("a non-inferior, materially faster and cheaper arm outranks a dominated weighted leader", () => {
+ const decision = routeRequest(buildInput());
+
+ // The challenger is non-inferior on quality (0.91 >= 0.95 - 0.05), and is materially
+ // faster (7000ms vs 11000ms) and cheaper ($0.25 vs $0.40). It must outrank the leader.
+ expect(decision.chosen_endpoint_id).toBe("challenger-non-inferior");
+ expect(decision.scored_candidates[0]?.endpoint_id).toBe("challenger-non-inferior");
+ expect(decision.fallback_endpoint_ids).toContain("incumbent-dominated");
+ });
+});
diff --git a/role-model-router/packages/core/test/run106-non-inferiority.test.ts b/role-model-router/packages/core/test/run106-non-inferiority.test.ts
new file mode 100644
index 000000000..357b0faa5
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-non-inferiority.test.ts
@@ -0,0 +1,51 @@
+import { describe, expect, it } from "vitest";
+import { shouldPreferNonInferiorChallenger } from "../src/router.js";
+
+describe("run106 non-inferiority preference", () => {
+ const base = {
+ incumbentQuality: 0.9,
+ qualityMargin: 0.05,
+ incumbentLatencyMs: 11000,
+ incumbentCostUsd: 0.4,
+ };
+ it("prefers a faster+cheaper non-inferior challenger", () => {
+ expect(
+ shouldPreferNonInferiorChallenger({
+ ...base,
+ challengerQuality: 0.88,
+ challengerLatencyMs: 7000,
+ challengerCostUsd: 0.25,
+ }),
+ ).toBe(true);
+ });
+ it("rejects a quality-inferior challenger", () => {
+ expect(
+ shouldPreferNonInferiorChallenger({
+ ...base,
+ challengerQuality: 0.7,
+ challengerLatencyMs: 7000,
+ challengerCostUsd: 0.25,
+ }),
+ ).toBe(false);
+ });
+ it("rejects a challenger that is not faster", () => {
+ expect(
+ shouldPreferNonInferiorChallenger({
+ ...base,
+ challengerQuality: 0.88,
+ challengerLatencyMs: 12000,
+ challengerCostUsd: 0.25,
+ }),
+ ).toBe(false);
+ });
+ it("rejects a challenger that is not cheaper", () => {
+ expect(
+ shouldPreferNonInferiorChallenger({
+ ...base,
+ challengerQuality: 0.88,
+ challengerLatencyMs: 7000,
+ challengerCostUsd: 0.5,
+ }),
+ ).toBe(false);
+ });
+});
diff --git a/role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts b/role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts
new file mode 100644
index 000000000..d65d52f0b
--- /dev/null
+++ b/role-model-router/packages/core/test/run106-phase35-review-fixes.test.ts
@@ -0,0 +1,168 @@
+import { describe, expect, test } from "vitest";
+
+import { getQualityMetric, routeRequest } from "../src/router.js";
+import type { EndpointCandidate, RouteRequestInput, RoutingRequest } from "../src/types.js";
+
+function candidate(
+ endpointId: string,
+ reasoningEffort: string | null,
+ overrides: Partial = {},
+): EndpointCandidate {
+ return {
+ identity: {
+ endpoint_id: endpointId,
+ endpoint_kind: "remote_api",
+ provider_kind: "remote_openai_compat",
+ serving_source: "remote-service",
+ model_id: endpointId,
+ runtime_version: "1",
+ region: "global",
+ ...(reasoningEffort === null
+ ? { reasoning_effort: null }
+ : { reasoning_effort: reasoningEffort }),
+ },
+ declared: {
+ endpoint_id: endpointId,
+ capabilities: ["text.chat"],
+ modalities: ["text"],
+ max_context_tokens: 100_000,
+ tool_calling: { supported: false, style: "openai" },
+ supports_embeddings: false,
+ },
+ status: "active",
+ ...overrides,
+ };
+}
+
+const baseRequest: RoutingRequest = {
+ requestId: "run106-phase35-review-fixes",
+ taskType: "text.chat",
+ requiredCapabilities: [],
+ preferredCapabilities: [],
+ requiredModalities: ["text"],
+ contextTokens: 1000,
+ needsTools: false,
+ strategy: "balanced",
+ preferLocal: false,
+};
+
+function buildInput(overrides: Partial = {}): RouteRequestInput {
+ return {
+ request: baseRequest,
+ candidates: [candidate("provider-default", null)],
+ ...overrides,
+ };
+}
+
+/** A measured profile with just the fields the non-inferiority gate reads. */
+function measured(latencyMsP50: number, latencyMsP95: number, costPer1k: number) {
+ return {
+ latency_ms_p50: latencyMsP50,
+ latency_ms_p95: latencyMsP95,
+ cost_per_1k_tokens_est: costPer1k,
+ measured_at_ms: 1,
+ };
+}
+
+describe("run106 Phase 3.5 review fixes (H-2, M-1, M-2, L-4)", () => {
+ test("M-1: getQualityMetric labels a borrowed related-effort prior as borrowed", () => {
+ const c = candidate("borrowed", null, {
+ benchmarkCapability: { relatedEffortOverallScore: 0.9 },
+ });
+ const metric = getQualityMetric(c, buildInput());
+ expect(metric.source).toBe("borrowed");
+ });
+
+ test("M-1: borrowed quality never establishes non-inferiority", () => {
+ const leader = candidate("borrowed-leader", "high", {
+ benchmarkCapability: { relatedEffortOverallScore: 1.0 },
+ observed: measured(11000, 12000, 0.4),
+ });
+ const challenger = candidate("benchmark-challenger", "high", {
+ benchmarkCapability: { overallScore: 0.8 },
+ observed: measured(6000, 6500, 0.25),
+ });
+ const decision = routeRequest(buildInput({ candidates: [leader, challenger] }));
+ expect(decision.chosen_endpoint_id).toBe("borrowed-leader");
+ });
+
+ test("M-2: non-inferiority promotion records its receipt and a selection reason", () => {
+ const leader = candidate("weighted-leader", "high", {
+ benchmarkCapability: { overallScore: 0.9 },
+ observed: measured(11000, 12000, 0.4),
+ });
+ const challenger = candidate("non-inferior-challenger", "high", {
+ benchmarkCapability: { overallScore: 0.88 },
+ observed: measured(6000, 6500, 0.25),
+ });
+ const decision = routeRequest(buildInput({ candidates: [leader, challenger] }));
+ expect(decision.chosen_endpoint_id).toBe("non-inferior-challenger");
+ expect(decision.non_inferiority_promotion).toMatchObject({
+ promoted_endpoint_id: "non-inferior-challenger",
+ displaced_endpoint_id: "weighted-leader",
+ quality_margin: 0.05,
+ min_latency_advantage_ms: 200,
+ min_cost_advantage_fraction: 0.1,
+ changed_weighted_selection: true,
+ });
+ expect(decision.selection_reasons).toContain("NON_INFERIOR_PROMOTION");
+ });
+
+ test("H-2: decision records requested effort, policy, and exact-arm counts", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [
+ candidate("exact-high", "high"),
+ candidate("exact-high-denied", "high"),
+ candidate("provider-default", null),
+ ],
+ request: { ...baseRequest, denyEndpoints: ["exact-high-denied"] },
+ effortResolution: {
+ resolution: "exact_fallback_expanded",
+ effectiveEffort: "high",
+ requestedEffort: "high",
+ requestedPolicy: "preferred",
+ },
+ }),
+ );
+ expect(decision.requested_effort).toBe("high");
+ expect(decision.requested_policy).toBe("preferred");
+ expect(decision.effort_exact_arm_count_before_hard_eligibility).toBe(2);
+ expect(decision.effort_exact_arm_count_after_hard_eligibility).toBe(1);
+ });
+
+ test("L-4: marks fallback when a non-exact arm wins under exact_fallback_expanded", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("exact-high", "high"), candidate("provider-default", null)],
+ request: { ...baseRequest, denyEndpoints: ["exact-high"] },
+ effortResolution: {
+ resolution: "exact_fallback_expanded",
+ effectiveEffort: "high",
+ requestedEffort: "high",
+ requestedPolicy: "preferred",
+ },
+ }),
+ );
+ expect(decision.chosen_endpoint_id).toBe("provider-default");
+ expect(decision.effort_fallback_applied).toBe(true);
+ expect(decision.selection_reasons).toContain("EFFORT_FALLBACK_APPLIED");
+ });
+
+ test("L-4: does not mark fallback when the exact arm wins under exact_fallback_expanded", () => {
+ const decision = routeRequest(
+ buildInput({
+ candidates: [candidate("exact-high", "high")],
+ effortResolution: {
+ resolution: "exact_fallback_expanded",
+ effectiveEffort: "high",
+ requestedEffort: "high",
+ requestedPolicy: "preferred",
+ },
+ }),
+ );
+ expect(decision.chosen_endpoint_id).toBe("exact-high");
+ expect(decision.effort_fallback_applied).not.toBe(true);
+ expect(decision.selection_reasons).not.toContain("EFFORT_FALLBACK_APPLIED");
+ });
+});
diff --git a/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts b/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts
index f22dc8fce..99290279b 100644
--- a/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts
+++ b/role-model-router/packages/endpoint-registry/src/effort-instance-identity.ts
@@ -117,4 +117,81 @@ export function readLegacyEndpointReasoningEffort(endpointId: string): string |
}
}
+export interface ReasoningEffortArm {
+ readonly endpointId: string;
+ readonly providerAccountId: string;
+ readonly region: string;
+ readonly modelId: string;
+ readonly effectiveEffort: string | null;
+ readonly source: "fixed" | "provider-default";
+}
+
+export function expandReasoningEffortArms(input: {
+ readonly providerAccountId: string;
+ readonly region: string;
+ readonly modelId: string;
+ readonly fixedEffort: string | null;
+ readonly declaredLevels?: readonly string[];
+ /** Optional explicit base id; preserves the caller's exact endpoint id (e.g. source.endpointId). */
+ readonly baseEndpointId?: string;
+}): ReasoningEffortArm[] {
+ const fixedEffort = normalizeReasoningEffort(input.fixedEffort);
+ if (fixedEffort !== null) {
+ // A fixed-effort source endpointId already carries its effort suffix; preserve it verbatim.
+ const endpointId =
+ input.baseEndpointId ??
+ `${createLegacyEndpointId(input.providerAccountId, input.region, input.modelId)}-${encodeURIComponent(fixedEffort)}`;
+ return [
+ {
+ endpointId,
+ providerAccountId: input.providerAccountId,
+ region: input.region,
+ modelId: input.modelId,
+ effectiveEffort: fixedEffort,
+ source: "fixed",
+ },
+ ];
+ }
+
+ const baseEndpointId =
+ input.baseEndpointId ??
+ createLegacyEndpointId(input.providerAccountId, input.region, input.modelId);
+ const arms: ReasoningEffortArm[] = [
+ {
+ endpointId: baseEndpointId,
+ providerAccountId: input.providerAccountId,
+ region: input.region,
+ modelId: input.modelId,
+ effectiveEffort: null,
+ source: "provider-default",
+ },
+ ];
+ const seen = new Set([baseEndpointId]);
+ for (const level of new Set(input.declaredLevels ?? [])) {
+ let normalized: string | null;
+ try {
+ normalized = normalizeReasoningEffort(level);
+ } catch {
+ continue;
+ }
+ if (normalized === null) {
+ continue;
+ }
+ const endpointId = `${baseEndpointId}-${encodeURIComponent(normalized)}`;
+ if (seen.has(endpointId)) {
+ continue;
+ }
+ seen.add(endpointId);
+ arms.push({
+ endpointId,
+ providerAccountId: input.providerAccountId,
+ region: input.region,
+ modelId: input.modelId,
+ effectiveEffort: normalized,
+ source: "fixed",
+ });
+ }
+ return arms;
+}
+
export { EFFORT_PREFIX, MAX_REASONING_EFFORT_BYTES };
diff --git a/role-model-router/packages/endpoint-registry/src/index.ts b/role-model-router/packages/endpoint-registry/src/index.ts
index 4093cc41d..aeceea867 100644
--- a/role-model-router/packages/endpoint-registry/src/index.ts
+++ b/role-model-router/packages/endpoint-registry/src/index.ts
@@ -3,8 +3,11 @@ import type {
NormalizedCatalogModel,
RequestShapeHints,
} from "@role-model-router/catalog";
+import { resolveAdapterGatedReasoningEfforts } from "@role-model-router/catalog";
import type { ProviderAccountRecord } from "@role-model-router/provider-account";
+import { type ReasoningEffortArm, expandReasoningEffortArms } from "./effort-instance-identity.js";
+
export * from "./effort-instance-identity.js";
export type RegistryEndpointKind =
@@ -229,10 +232,14 @@ function createCloudEndpoint(
model: NormalizedCatalogModel,
account: ProviderAccountRecord,
source: CloudRegistrySource,
+ arm?: ReasoningEffortArm,
): EndpointCandidate {
+ const endpointId = arm?.endpointId ?? source.endpointId;
+ const reasoningEffort = arm ? arm.effectiveEffort : (source.reasoningEffort ?? null);
+ const isProviderDefault = arm ? arm.source === "provider-default" : true;
return {
identity: {
- endpoint_id: source.endpointId,
+ endpoint_id: endpointId,
endpoint_kind: normalizeEndpointKind(source.endpointKind),
provider_kind: normalizeProviderKind(account.providerKind),
serving_source: source.servingSource,
@@ -246,10 +253,10 @@ function createCloudEndpoint(
device_class: "server",
region: source.region,
org_scope: account.orgScope,
- ...(source.reasoningEffort !== undefined ? { reasoning_effort: source.reasoningEffort } : {}),
+ ...(reasoningEffort !== null ? { reasoning_effort: reasoningEffort } : {}),
},
declared: {
- endpoint_id: source.endpointId,
+ endpoint_id: endpointId,
capabilities: toNonEmptyList(
model.capabilities,
`Catalog model ${model.modelId} capabilities`,
@@ -262,7 +269,9 @@ function createCloudEndpoint(
},
supports_embeddings: model.capabilities.includes("embeddings.text"),
platform_constraints: [],
- ...(Array.isArray(model.reasoningEffortLevels) && model.reasoningEffortLevels.length > 0
+ ...(isProviderDefault &&
+ Array.isArray(model.reasoningEffortLevels) &&
+ model.reasoningEffortLevels.length > 0
? { reasoning_effort_levels: [...model.reasoningEffortLevels] }
: {}),
},
@@ -308,6 +317,19 @@ function createLocalEndpoint(source: LocalRegistrySource): EndpointCandidate {
};
}
+function resolveAdapterFamilyForSource(
+ catalog: NormalizedCatalog,
+ account: ProviderAccountRecord,
+): string | null {
+ if (account.providerAccountId.endsWith(".litellm")) {
+ return "litellm-proxy";
+ }
+ return (
+ catalog.providers.find((provider) => provider.providerId === account.providerId)
+ ?.adapterFamily ?? null
+ );
+}
+
export function buildEndpointRegistry(input: BuildEndpointRegistryInput): EndpointRegistryResult {
const modelsById = new Map(input.catalog.models.map((model) => [model.modelId, model]));
const accountsById = new Map(
@@ -358,7 +380,29 @@ export function buildEndpointRegistry(input: BuildEndpointRegistryInput): Endpoi
continue;
}
- endpoints.push(createCloudEndpoint(model, account, source));
+ // Run 106 R2: expansion is gated on actual adapter executability, not the
+ // catalog declaration alone. Only declared levels with a valid adapter
+ // execution mapping (a tested reasoning-effort serializer) become fixed
+ // routing arms; the provider-default arm still advertises the full declared
+ // set on declared.reasoning_effort_levels for discovery (R9).
+ const executableLevels = resolveAdapterGatedReasoningEfforts({
+ providerId: account.providerId,
+ modelId: model.modelId,
+ capabilities: model.capabilities,
+ catalogLevels: model.reasoningEffortLevels ?? [],
+ adapterFamily: resolveAdapterFamilyForSource(input.catalog, account),
+ });
+ const arms = expandReasoningEffortArms({
+ providerAccountId: source.providerAccountId,
+ region: source.region,
+ modelId: source.modelId,
+ fixedEffort: source.reasoningEffort ?? null,
+ declaredLevels: executableLevels,
+ baseEndpointId: source.endpointId,
+ });
+ for (const arm of arms) {
+ endpoints.push(createCloudEndpoint(model, account, source, arm));
+ }
}
for (const source of input.sources.local) {
diff --git a/role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts b/role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts
new file mode 100644
index 000000000..c86bd5da7
--- /dev/null
+++ b/role-model-router/packages/endpoint-registry/test/run106-arm-expansion.test.ts
@@ -0,0 +1,74 @@
+import { describe, expect, it } from "vitest";
+import { expandReasoningEffortArms } from "../src/effort-instance-identity.js";
+
+describe("run106 reasoning-effort arm expansion", () => {
+ const base = {
+ providerAccountId: "deepseek.personal",
+ region: "global",
+ modelId: "deepseek/flash",
+ };
+
+ it("fixed endpoint yields exactly one fixed arm", () => {
+ const arms = expandReasoningEffortArms({ ...base, fixedEffort: "max" });
+ expect(arms).toHaveLength(1);
+ expect(arms[0].source).toBe("fixed");
+ expect(arms[0].effectiveEffort).toBe("max");
+ expect(arms[0].endpointId).toContain("-max");
+ });
+
+ it("provider-default endpoint expands declared levels plus a default arm", () => {
+ const arms = expandReasoningEffortArms({
+ ...base,
+ fixedEffort: null,
+ declaredLevels: ["low", "high", "max"],
+ });
+ expect(arms.map((a) => a.source)).toContain("provider-default");
+ expect(arms.filter((a) => a.source === "fixed")).toHaveLength(3);
+ expect(arms.filter((a) => a.effectiveEffort === null)).toHaveLength(1);
+ });
+
+ it("dedupes duplicate declared levels", () => {
+ const arms = expandReasoningEffortArms({
+ ...base,
+ fixedEffort: null,
+ declaredLevels: ["high", "high", "max"],
+ });
+ const fixedIds = arms.filter((a) => a.source === "fixed").map((a) => a.endpointId);
+ expect(new Set(fixedIds).size).toBe(2);
+ });
+
+ it("provider-default with no declared levels yields only the default arm", () => {
+ const arms = expandReasoningEffortArms({ ...base, fixedEffort: null });
+ expect(arms).toHaveLength(1);
+ expect(arms[0].effectiveEffort).toBeNull();
+ });
+
+ it("preserves a caller-supplied baseEndpointId and appends declared-level suffixes", () => {
+ const arms = expandReasoningEffortArms({
+ ...base,
+ fixedEffort: null,
+ declaredLevels: ["low", "high"],
+ baseEndpointId: "deepseek.capture.account.global.chat-capture-v1",
+ });
+ expect(arms.map((arm) => arm.endpointId)).toEqual([
+ "deepseek.capture.account.global.chat-capture-v1",
+ "deepseek.capture.account.global.chat-capture-v1-low",
+ "deepseek.capture.account.global.chat-capture-v1-high",
+ ]);
+ expect(arms[0].source).toBe("provider-default");
+ expect(arms[1].source).toBe("fixed");
+ expect(arms[2].source).toBe("fixed");
+ });
+
+ it("fixed endpoint with a caller-supplied baseEndpointId preserves it verbatim (no double suffix)", () => {
+ const arms = expandReasoningEffortArms({
+ ...base,
+ fixedEffort: "max",
+ baseEndpointId: "deepseek.personal.global.deepseek-flash-max",
+ });
+ expect(arms).toHaveLength(1);
+ expect(arms[0].endpointId).toBe("deepseek.personal.global.deepseek-flash-max");
+ expect(arms[0].source).toBe("fixed");
+ expect(arms[0].effectiveEffort).toBe("max");
+ });
+});
diff --git a/role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts b/role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts
new file mode 100644
index 000000000..9cf56281c
--- /dev/null
+++ b/role-model-router/packages/endpoint-registry/test/run106-registry-arm-expansion.test.ts
@@ -0,0 +1,179 @@
+import { describe, expect, it } from "vitest";
+
+import { buildEndpointRegistry } from "../src/index.js";
+
+const providerAccountId = "openai.effort";
+const region = "us-east-1";
+const modelId = "openai/gpt-4.1-mini-fast-effort";
+const baseEndpointId = "openai.effort.us-east-1";
+
+const provenance = {
+ vendor: "models.dev",
+ commit: "test-catalog",
+ capturedAt: "2026-05-05T00:00:00Z",
+ schemaVersion: "1",
+};
+
+const executableOpenAIProvider = {
+ providerId: "openai",
+ displayName: "OpenAI",
+ npmPackage: "@role-model-router/provider-openai",
+ providerKind: "provider-openai",
+ authFamily: "api-key",
+ adapterFamily: "ai-sdk-openai-compatible",
+ apiBase: "https://api.openai.test",
+ docsUrl: null,
+ envVars: ["OPENAI_API_KEY"],
+ supportedAuthModes: ["api-key-static"],
+ controlPlaneRequirements: [],
+ localOverrideApplied: false,
+ upstreamProvenance: provenance,
+};
+
+function buildModel(capabilities: string[]) {
+ return {
+ modelId,
+ providerId: "openai",
+ providerKind: "provider-openai",
+ authFamily: "api-key",
+ displayName: "GPT-4.1 Mini Fast Effort",
+ version: "1",
+ capabilities,
+ modalities: ["text"],
+ contextWindow: 32768,
+ maxOutputTokens: 4096,
+ pricing: null,
+ requestShapeHints: {
+ providerShape: "openai",
+ bodyKeys: ["messages"],
+ headerKeys: ["authorization"],
+ },
+ experimentalModes: [],
+ reasoningEffortLevels: ["low", "high"],
+ reasoningOptionKinds: ["effort"],
+ extendsProvenance: { baseModelId: null, chain: [] },
+ localOverrideApplied: false,
+ localNotes: [],
+ upstreamProvenance: provenance,
+ };
+}
+
+function buildCatalog({
+ capabilities = ["code.edit", "tools.function_calling"],
+ providers = [] as unknown[],
+} = {}) {
+ return {
+ catalogVersion: "1",
+ source: provenance,
+ providers,
+ models: [buildModel(capabilities)],
+ };
+}
+
+const account = {
+ providerAccountId,
+ providerId: "openai",
+ providerKind: "provider-openai",
+ orgScope: "personal",
+ accountScope: "default",
+ credentialRef: { backend: "env", ref: "OPENAI_API_KEY" },
+ authMode: "api-key-static",
+ regionPolicy: { mode: "prefer", regions: ["us-east-1"] },
+ baseUrlOverride: null,
+ allowedModels: [],
+ deniedModels: [],
+ entitlementTags: ["chat"],
+ budgetPolicyRef: "budget.default",
+ quotaPolicyRef: "quota.default",
+ status: "active",
+ healthStatus: "healthy",
+ rotationState: "stable",
+};
+
+function buildSources(overrides: Record = {}) {
+ return {
+ cloud: [
+ {
+ endpointId: baseEndpointId,
+ providerAccountId,
+ modelId,
+ region,
+ endpointKind: "remote-openai-compatible",
+ servingSource: "remote-service",
+ lifecycleState: "active",
+ healthStatus: "healthy",
+ ...overrides,
+ },
+ ],
+ local: [],
+ };
+}
+
+describe("run106 registry arm assembly", () => {
+ it("fixed-effort source yields a single fixed arm carrying its level in identity", () => {
+ const result = buildEndpointRegistry({
+ catalog: buildCatalog(),
+ accounts: [account],
+ sources: buildSources({ endpointId: `${baseEndpointId}-high`, reasoningEffort: "high" }),
+ });
+
+ expect(result.endpoints).toHaveLength(1);
+ expect(result.endpoints[0].identity.endpoint_id).toBe(`${baseEndpointId}-high`);
+ expect(result.endpoints[0].identity.reasoning_effort).toBe("high");
+ expect(result.endpoints[0].declared.reasoning_effort_levels).toBeUndefined();
+ });
+
+ it("provider-default source without reasoning capability keeps a single provider-default arm", () => {
+ const result = buildEndpointRegistry({
+ catalog: buildCatalog(),
+ accounts: [account],
+ sources: buildSources(),
+ });
+
+ // No "reasoning" capability => no adapter-executable levels => no expansion.
+ expect(result.endpoints).toHaveLength(1);
+ expect(result.endpoints[0].identity.endpoint_id).toBe(baseEndpointId);
+ expect(result.endpoints[0].identity.reasoning_effort).toBeUndefined();
+ expect(result.endpoints[0].declared.reasoning_effort_levels).toEqual(["low", "high"]);
+ });
+
+ it("provider-default source with an executable adapter expands declared levels into fixed arms plus a provider-default arm", () => {
+ const result = buildEndpointRegistry({
+ catalog: buildCatalog({
+ capabilities: ["code.edit", "tools.function_calling", "reasoning"],
+ providers: [executableOpenAIProvider],
+ }),
+ accounts: [account],
+ sources: buildSources(),
+ });
+
+ expect(result.endpoints.map((endpoint) => endpoint.identity.endpoint_id)).toEqual([
+ baseEndpointId,
+ `${baseEndpointId}-low`,
+ `${baseEndpointId}-high`,
+ ]);
+ expect(result.endpoints[0].identity.reasoning_effort).toBeUndefined();
+ expect(result.endpoints[0].declared.reasoning_effort_levels).toEqual(["low", "high"]);
+ expect(result.endpoints[1].identity.reasoning_effort).toBe("low");
+ expect(result.endpoints[1].declared.reasoning_effort_levels).toBeUndefined();
+ expect(result.endpoints[2].identity.reasoning_effort).toBe("high");
+ expect(result.endpoints[2].declared.reasoning_effort_levels).toBeUndefined();
+ });
+
+ it("provider-default source with declared levels but no executable adapter keeps a single provider-default arm", () => {
+ // Catalog declares levels, the model can reason, but there is no adapter
+ // execution mapping (empty providers) => expansion is gated off.
+ const result = buildEndpointRegistry({
+ catalog: buildCatalog({
+ capabilities: ["code.edit", "tools.function_calling", "reasoning"],
+ }),
+ accounts: [account],
+ sources: buildSources(),
+ });
+
+ expect(result.endpoints).toHaveLength(1);
+ expect(result.endpoints[0].identity.endpoint_id).toBe(baseEndpointId);
+ expect(result.endpoints[0].identity.reasoning_effort).toBeUndefined();
+ expect(result.endpoints[0].declared.reasoning_effort_levels).toEqual(["low", "high"]);
+ });
+});
diff --git a/role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts b/role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts
index 6365c41de..5ad5f23e6 100644
--- a/role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts
+++ b/role-model-router/packages/profile-aggregator/src/benchmark-routing-quality.ts
@@ -325,3 +325,83 @@ export function applyRoutingBenchmarkQualityToProfiles(input: {
difficultyProfiles,
};
}
+
+export interface EffortBenchmarkEvidenceSubject {
+ readonly endpointId: string;
+ readonly modelId?: string | null;
+ readonly providerId?: string | null;
+ readonly reasoningEffort?: string | null;
+ readonly overallScore?: number | null;
+}
+
+function isNamedEffort(value: string | null | undefined): value is string {
+ return typeof value === "string" && value.length > 0;
+}
+
+/**
+ * Run 106 R5 (producer): resolve a borrowed, related-effort benchmark score for a provider-default arm.
+ *
+ * A provider-default arm (`reasoningEffort` null/undefined) serves a dynamic effort and therefore has no
+ * effort-encoded benchmark key of its own. When it also has no exact benchmark evidence, the only defensible
+ * signal is a SIBLING fixed-effort arm of the same model (and provider, when both are known). The borrowed
+ * score is returned raw here; the router-side consumer (`resolveBorrowedQualityPrior`) applies the
+ * documented symmetric regression toward neutral and labels it `borrowed`, so it never appears as exact
+ * benchmark evidence.
+ *
+ * Selection is deterministic: the sibling with the highest exact `overallScore` wins, ties broken by
+ * endpoint id ascending, so the prior is stable across repeated snapshots.
+ */
+export function resolveRelatedEffortOverallScore(input: {
+ readonly endpointId: string;
+ readonly modelId?: string | null;
+ readonly providerId?: string | null;
+ readonly reasoningEffort?: string | null;
+ readonly subjects: readonly EffortBenchmarkEvidenceSubject[];
+}): number | null {
+ // Only a provider-default arm borrows. A fixed-effort arm names its own effort and must never be
+ // credited with another effort's evidence.
+ if (isNamedEffort(input.reasoningEffort)) {
+ return null;
+ }
+ // A sibling lookup needs a model key; without one there is no defensible "same model" match.
+ if (!isNamedEffort(input.modelId)) {
+ return null;
+ }
+ // If this arm already has exact benchmark evidence, borrowing would be a downgrade, not a prior.
+ const own = input.subjects.find((subject) => subject.endpointId === input.endpointId);
+ if (typeof own?.overallScore === "number" && Number.isFinite(own.overallScore)) {
+ return null;
+ }
+
+ const sameProvider = (subject: EffortBenchmarkEvidenceSubject): boolean => {
+ if (isNamedEffort(input.providerId) && isNamedEffort(subject.providerId)) {
+ return input.providerId === subject.providerId;
+ }
+ return true;
+ };
+
+ const siblings = input.subjects
+ .filter((subject) => subject.endpointId !== input.endpointId)
+ .filter((subject) => subject.modelId === input.modelId)
+ .filter((subject) => isNamedEffort(subject.reasoningEffort))
+ .filter(
+ (subject) =>
+ typeof subject.overallScore === "number" && Number.isFinite(subject.overallScore),
+ )
+ .filter(sameProvider);
+
+ if (siblings.length === 0) {
+ return null;
+ }
+
+ const best = siblings.reduce((best, candidate) => {
+ const bestScore = best.overallScore as number;
+ const candidateScore = candidate.overallScore as number;
+ if (candidateScore !== bestScore) {
+ return candidateScore > bestScore ? candidate : best;
+ }
+ return candidate.endpointId.localeCompare(best.endpointId) < 0 ? candidate : best;
+ });
+
+ return best.overallScore as number;
+}
diff --git a/role-model-router/packages/profile-aggregator/src/index.ts b/role-model-router/packages/profile-aggregator/src/index.ts
index c5b31ec97..3be57ef78 100644
--- a/role-model-router/packages/profile-aggregator/src/index.ts
+++ b/role-model-router/packages/profile-aggregator/src/index.ts
@@ -299,6 +299,7 @@ export {
applyRoutingBenchmarkQualityToProfile,
applyRoutingBenchmarkQualityToProfiles,
normalizeBenchmarkSampleVersions,
+ resolveRelatedEffortOverallScore,
resolveRoutingBenchmarkQuality,
} from "./benchmark-routing-quality.js";
export type {
@@ -306,6 +307,7 @@ export type {
BenchmarkDifficultyBucket,
BenchmarkHardBlend,
BenchmarkRoutingMode,
+ EffortBenchmarkEvidenceSubject,
RoutingBenchmarkQuality,
} from "./benchmark-routing-quality.js";
diff --git a/role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts b/role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts
new file mode 100644
index 000000000..d4dcd04b8
--- /dev/null
+++ b/role-model-router/packages/profile-aggregator/test/run106-related-effort-borrow.test.ts
@@ -0,0 +1,146 @@
+import { describe, expect, test } from "vitest";
+
+import {
+ type EffortBenchmarkEvidenceSubject,
+ resolveRelatedEffortOverallScore,
+} from "../src/index.js";
+
+function subject(input: {
+ readonly endpointId: string;
+ readonly modelId?: string | null;
+ readonly providerId?: string | null;
+ readonly reasoningEffort?: string | null;
+ readonly overallScore?: number | null;
+}): EffortBenchmarkEvidenceSubject {
+ return {
+ endpointId: input.endpointId,
+ modelId: input.modelId ?? null,
+ providerId: input.providerId ?? null,
+ reasoningEffort: input.reasoningEffort ?? null,
+ overallScore: input.overallScore ?? null,
+ };
+}
+
+describe("resolveRelatedEffortOverallScore", () => {
+ test("borrows a sibling fixed-effort benchmark score for a provider-default endpoint", () => {
+ const subjects = [
+ subject({ endpointId: "flash.default", modelId: "flash", reasoningEffort: null }),
+ subject({
+ endpointId: "flash.max",
+ modelId: "flash",
+ reasoningEffort: "max",
+ overallScore: 0.9,
+ }),
+ ];
+
+ expect(
+ resolveRelatedEffortOverallScore({
+ endpointId: "flash.default",
+ modelId: "flash",
+ reasoningEffort: null,
+ subjects,
+ }),
+ ).toBe(0.9);
+ });
+
+ test("returns null when the provider-default endpoint already has exact benchmark evidence", () => {
+ const subjects = [
+ subject({
+ endpointId: "flash.default",
+ modelId: "flash",
+ reasoningEffort: null,
+ overallScore: 0.7,
+ }),
+ subject({
+ endpointId: "flash.max",
+ modelId: "flash",
+ reasoningEffort: "max",
+ overallScore: 0.9,
+ }),
+ ];
+
+ expect(
+ resolveRelatedEffortOverallScore({
+ endpointId: "flash.default",
+ modelId: "flash",
+ reasoningEffort: null,
+ subjects,
+ }),
+ ).toBeNull();
+ });
+
+ test("returns null when no same-model sibling fixed-effort benchmark exists", () => {
+ const subjects = [
+ subject({ endpointId: "flash.default", modelId: "flash", reasoningEffort: null }),
+ subject({
+ endpointId: "other.max",
+ modelId: "other-model",
+ reasoningEffort: "max",
+ overallScore: 0.9,
+ }),
+ ];
+
+ expect(
+ resolveRelatedEffortOverallScore({
+ endpointId: "flash.default",
+ modelId: "flash",
+ reasoningEffort: null,
+ subjects,
+ }),
+ ).toBeNull();
+ });
+
+ test("never borrows for a fixed-effort endpoint", () => {
+ const subjects = [
+ subject({ endpointId: "flash.max", modelId: "flash", reasoningEffort: "max" }),
+ subject({
+ endpointId: "flash.high",
+ modelId: "flash",
+ reasoningEffort: "high",
+ overallScore: 0.8,
+ }),
+ ];
+
+ expect(
+ resolveRelatedEffortOverallScore({
+ endpointId: "flash.max",
+ modelId: "flash",
+ reasoningEffort: "max",
+ subjects,
+ }),
+ ).toBeNull();
+ });
+
+ test("picks the highest-scoring sibling deterministically when several fixed-effort siblings exist", () => {
+ const subjects = [
+ subject({ endpointId: "flash.default", modelId: "flash", reasoningEffort: null }),
+ subject({
+ endpointId: "flash.low",
+ modelId: "flash",
+ reasoningEffort: "low",
+ overallScore: 0.6,
+ }),
+ subject({
+ endpointId: "flash.high",
+ modelId: "flash",
+ reasoningEffort: "high",
+ overallScore: 0.8,
+ }),
+ subject({
+ endpointId: "flash.max",
+ modelId: "flash",
+ reasoningEffort: "max",
+ overallScore: 0.9,
+ }),
+ ];
+
+ expect(
+ resolveRelatedEffortOverallScore({
+ endpointId: "flash.default",
+ modelId: "flash",
+ reasoningEffort: null,
+ subjects,
+ }),
+ ).toBe(0.9);
+ });
+});
diff --git a/role-model-router/packages/protocol-routing/src/index.ts b/role-model-router/packages/protocol-routing/src/index.ts
index 8e45300ca..5c6459c34 100644
--- a/role-model-router/packages/protocol-routing/src/index.ts
+++ b/role-model-router/packages/protocol-routing/src/index.ts
@@ -60,6 +60,8 @@ export interface ProjectRuntimeRouteInputInput {
* effective learning stage is S2 or above; hard eligibility and scoring still run first.
*/
advisoryConsideration?: RouteRequestInput["advisoryConsideration"];
+ /** Run 106 R10: the effort policy resolution computed by the host before narrowing the pool. */
+ effortResolution?: RouteRequestInput["effortResolution"];
/**
* Run 100 addendum 10, E1: who is being routed. The verdict line is the only place a live eligibility collapse
* leaves a trace that does not require a store query, and without this the line named neither the request nor the
@@ -320,6 +322,7 @@ export function projectRuntimeRouteInput(
...(input.advisoryConsideration
? { advisoryConsideration: input.advisoryConsideration }
: {}),
+ ...(input.effortResolution ? { effortResolution: input.effortResolution } : {}),
},
routingDiagnostics: {
retrievalReceiptId: input.retrievalReceipt.receiptId,
diff --git a/role-model-router/packages/runtime-observability/package.json b/role-model-router/packages/runtime-observability/package.json
index af5d2565c..1c5c60a13 100644
--- a/role-model-router/packages/runtime-observability/package.json
+++ b/role-model-router/packages/runtime-observability/package.json
@@ -19,6 +19,7 @@
"dependencies": {
"@role-model/protocol-types": "workspace:*",
"@role-model-router/adapter-execution": "workspace:*",
+ "@role-model-router/core": "workspace:*",
"@role-model-router/profile-aggregator": "workspace:*",
"@role-model-router/tool-registry": "workspace:*",
"@role-model-router/trace": "workspace:*",
diff --git a/role-model-router/packages/runtime-observability/src/index.ts b/role-model-router/packages/runtime-observability/src/index.ts
index 4994fb51b..ddb708c58 100644
--- a/role-model-router/packages/runtime-observability/src/index.ts
+++ b/role-model-router/packages/runtime-observability/src/index.ts
@@ -85,6 +85,15 @@ export interface RuntimeRoutingDiagnostics {
readonly cacheInvalidated?: boolean;
readonly cacheInvalidationReasons?: readonly string[];
readonly fallbackReason?: string;
+ readonly classifierVersion?: string;
+ readonly decisiveFeatures?: readonly string[];
+ readonly features?: {
+ readonly currentTurnBurden: number;
+ readonly conversationBurden: number;
+ readonly operationRisk: number;
+ readonly requiredQuality: number;
+ readonly latencySensitivity: number;
+ };
readonly excludedEndpointIds?: readonly string[];
readonly overrideAppliedEndpointIds?: readonly string[];
readonly overrideRecommendedMaxDifficultyByEndpointId?: Record<
@@ -377,25 +386,36 @@ export interface RuntimeReasoningStreamReceipt {
}
export type RuntimeEffortSource = "none" | "client" | "variant" | "variant_coerced";
+export type RuntimeEffortSourceValue = RuntimeEffortSource;
export interface RuntimeEffortReceipt {
readonly reasoningEffort: string | null;
readonly effortSource: RuntimeEffortSource;
+ /** True when the named effort was coerced from a variant (historical `variant_coerced`). */
+ readonly coerced: boolean;
}
export interface RuntimeEffortReceiptInput {
readonly reasoningEffort?: string | null;
- readonly effortSource?: RuntimeEffortSource;
+ readonly effortSource?: RuntimeEffortSourceValue;
readonly reasoning_effort?: string | null;
- readonly effort_source?: RuntimeEffortSource;
+ readonly effort_source?: RuntimeEffortSourceValue;
+ /** Explicit coercion attribution; when absent it is derived from a legacy `variant_coerced` source. */
+ readonly coerced?: boolean;
}
-/** Normalize new and historical receipt shapes without inferring effort from endpoint identity. */
+/**
+ * Normalize runtime receipt shapes onto the occurrence/telemetry effort-source vocabulary
+ * (`none` for a null reasoning effort, otherwise `client`/`variant`/`variant_coerced`) without
+ * inferring effort from endpoint identity. This is deliberately distinct from the decision's
+ * four-state vocabulary (`named`/`disabled`/`provider_default`/`none`).
+ */
export function normalizeRuntimeEffortReceipt(
input: RuntimeEffortReceiptInput = {},
): RuntimeEffortReceipt {
const reasoningEffort = input.reasoningEffort ?? input.reasoning_effort ?? null;
- const effortSource = input.effortSource ?? input.effort_source ?? "none";
+ const effortSource =
+ input.effortSource ?? input.effort_source ?? (reasoningEffort === null ? "none" : "client");
if (reasoningEffort !== null && !reasoningEffort) {
throw new Error("reasoningEffort must be null or a non-empty value.");
}
@@ -405,7 +425,11 @@ export function normalizeRuntimeEffortReceipt(
if (reasoningEffort !== null && effortSource === "none") {
throw new Error("effortSource is required for an efforted request.");
}
- return { reasoningEffort, effortSource };
+ return {
+ reasoningEffort,
+ effortSource,
+ coerced: input.coerced ?? effortSource === "variant_coerced",
+ };
}
export interface RuntimeDiagnostic {
@@ -458,7 +482,9 @@ export interface RuntimeObservationBundleInput {
readonly trafficClass?: ObservedTrafficClass;
/** Explicit request effort; null means the provider-default instance. */
readonly reasoningEffort?: string | null;
- readonly effortSource?: RuntimeEffortSource;
+ readonly effortSource?: RuntimeEffortSourceValue;
+ /** True when the named effort was coerced from a variant (historical `variant_coerced`). */
+ readonly effortCoerced?: boolean;
readonly normalizedIntent?: Readonly>;
readonly routingDiagnostics?: RuntimeRoutingDiagnostics;
readonly retrievalReceipt: RuntimeRetrievalReceipt;
@@ -534,6 +560,8 @@ export interface RuntimeObservationBundle {
readonly clientRequestId?: string;
readonly reasoningEffort: string | null;
readonly effortSource: RuntimeEffortSource;
+ /** True when the named effort was coerced from a variant; absent otherwise. */
+ readonly effortCoerced?: boolean;
readonly routingDecisionId: string;
readonly endpointId: string;
readonly conversationId: string;
@@ -543,7 +571,13 @@ export interface RuntimeObservationBundle {
readonly retrievalReceipt: RuntimeRetrievalReceipt;
readonly contextEnvelope: RuntimeContextEnvelopeSummary;
readonly trace: RoutedExecutionResult["trace"];
- readonly usageEvent: RoutedExecutionResult["usageEvent"];
+ readonly usageEvent: Omit<
+ RoutedExecutionResult["usageEvent"],
+ "reasoning_effort" | "effort_source"
+ > & {
+ readonly reasoning_effort: string | null;
+ readonly effort_source: RuntimeEffortSource;
+ };
/** Run 98 addendum 40 (L1): provider header/completion/first-token breakdown for this request. */
readonly latencyBreakdown?: RuntimeObservationBundleInput["latencyBreakdown"];
readonly observedPerformance: {
@@ -1160,7 +1194,10 @@ export const extractTaxonomyFields = extractTaxonomyDimensions;
export function createRuntimeObservationBundle(
input: RuntimeObservationBundleInput,
): RuntimeObservationBundle {
- const effort = normalizeRuntimeEffortReceipt(input);
+ const effort = normalizeRuntimeEffortReceipt({
+ ...input,
+ ...(input.effortCoerced !== undefined ? { coerced: input.effortCoerced } : {}),
+ });
const endpointVersion = deriveEndpointVersion(input.execution);
const currentSample = buildObservedPerformanceSample(input, endpointVersion, effort);
const priorSamples = (input.priorSamples ?? []).filter(
@@ -1201,6 +1238,7 @@ export function createRuntimeObservationBundle(
...(input.clientRequestId ? { clientRequestId: input.clientRequestId } : {}),
reasoningEffort: effort.reasoningEffort,
effortSource: effort.effortSource,
+ ...(effort.coerced ? { effortCoerced: true } : {}),
routingDecisionId: input.decision.routing_decision_id,
endpointId: input.decision.chosen_endpoint_id,
conversationId: input.contextEnvelope.conversationId,
diff --git a/role-model-router/packages/runtime-observability/src/otel.ts b/role-model-router/packages/runtime-observability/src/otel.ts
index fb29779e9..2f3d2c9db 100644
--- a/role-model-router/packages/runtime-observability/src/otel.ts
+++ b/role-model-router/packages/runtime-observability/src/otel.ts
@@ -28,6 +28,9 @@ export function createOpenTelemetryGenAiExport(
if (bundle.reasoningEffort !== null) {
attributes["role_model.reasoning_effort"] = bundle.reasoningEffort;
}
+ if (bundle.effortCoerced === true) {
+ attributes["role_model.effort_coerced"] = true;
+ }
return {
traceId: rootSpan.trace_id,
diff --git a/role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts b/role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts
new file mode 100644
index 000000000..9a7ff70eb
--- /dev/null
+++ b/role-model-router/packages/runtime-observability/test/run106-effort-source-roundtrip.test.ts
@@ -0,0 +1,50 @@
+import { describe, expect, test } from "vitest";
+
+import { normalizeRuntimeEffortReceipt } from "../src/index.js";
+
+describe("Run 106 runtime effort-source round-trip", () => {
+ test("round-trips the occurrence/telemetry effort-source vocabulary", () => {
+ expect(
+ normalizeRuntimeEffortReceipt({ reasoningEffort: "high", effortSource: "client" }),
+ ).toEqual({ reasoningEffort: "high", effortSource: "client", coerced: false });
+ expect(
+ normalizeRuntimeEffortReceipt({ reasoningEffort: "high", effortSource: "variant" }),
+ ).toEqual({ reasoningEffort: "high", effortSource: "variant", coerced: false });
+ expect(
+ normalizeRuntimeEffortReceipt({ reasoningEffort: "high", effortSource: "variant_coerced" }),
+ ).toEqual({ reasoningEffort: "high", effortSource: "variant_coerced", coerced: true });
+ expect(normalizeRuntimeEffortReceipt({ reasoningEffort: null, effortSource: "none" })).toEqual({
+ reasoningEffort: null,
+ effortSource: "none",
+ coerced: false,
+ });
+ });
+
+ test("defaults a missing source to none for a null-effort request", () => {
+ expect(normalizeRuntimeEffortReceipt({ reasoningEffort: null })).toEqual({
+ reasoningEffort: null,
+ effortSource: "none",
+ coerced: false,
+ });
+ });
+
+ test("defaults a missing source to client for an efforted request", () => {
+ expect(normalizeRuntimeEffortReceipt({ reasoningEffort: "high" })).toEqual({
+ reasoningEffort: "high",
+ effortSource: "client",
+ coerced: false,
+ });
+ });
+
+ test("rejects a non-none source without a reasoning effort", () => {
+ expect(() =>
+ normalizeRuntimeEffortReceipt({ reasoningEffort: null, effortSource: "variant" }),
+ ).toThrow(/none|reasoningEffort|effort/i);
+ });
+
+ test("rejects a none source carrying a reasoning effort", () => {
+ expect(() =>
+ normalizeRuntimeEffortReceipt({ reasoningEffort: "high", effortSource: "none" }),
+ ).toThrow(/none|reasoningEffort|effort/i);
+ });
+});
diff --git a/role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts b/role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts
index f4a4d6003..31af9f48e 100644
--- a/role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts
+++ b/role-model-router/packages/runtime-observability/test/run91-effort-otel.test.ts
@@ -80,13 +80,14 @@ describe("Run 91 runtime effort receipts", () => {
}
});
- test("normalizes missing historical effort receipt to provider-default null", async () => {
+ test("normalizes missing historical effort receipt to none null", async () => {
const runtimeModuleImport = await import(
pathToFileURL(path.join(__dirname, "..", "src", "index.js")).href
);
expect(runtimeModuleImport.normalizeRuntimeEffortReceipt({})).toEqual({
reasoningEffort: null,
effortSource: "none",
+ coerced: false,
});
});
});
diff --git a/role-model-router/packages/sqlite-memory/package.json b/role-model-router/packages/sqlite-memory/package.json
index 6396b267d..7a96f913c 100644
--- a/role-model-router/packages/sqlite-memory/package.json
+++ b/role-model-router/packages/sqlite-memory/package.json
@@ -14,6 +14,7 @@
"dependencies": {
"@role-model/protocol-types": "workspace:*",
"@role-model-router/catalog": "workspace:*",
+ "@role-model-router/core": "workspace:*",
"@role-model-router/profile-aggregator": "workspace:*",
"@role-model-router/provider-account": "workspace:*"
},
diff --git a/role-model-router/packages/sqlite-memory/src/index.ts b/role-model-router/packages/sqlite-memory/src/index.ts
index 6b40736ad..336085d8f 100644
--- a/role-model-router/packages/sqlite-memory/src/index.ts
+++ b/role-model-router/packages/sqlite-memory/src/index.ts
@@ -819,6 +819,15 @@ export interface DifficultyClassificationCacheRecord {
readonly difficulty: "easy" | "medium" | "hard";
readonly fallbackApplied: boolean;
readonly fallbackReason?: string;
+ readonly classifierVersion?: string;
+ readonly decisiveFeatures?: readonly string[];
+ readonly features?: {
+ readonly currentTurnBurden: number;
+ readonly conversationBurden: number;
+ readonly operationRisk: number;
+ readonly requiredQuality: number;
+ readonly latencySensitivity: number;
+ };
readonly cachedAtMs: number;
readonly expiresAtMs: number;
readonly rubricSignals: {
@@ -996,12 +1005,17 @@ export interface ListRecentRuntimeRequestIdsInput {
readonly limit?: number;
}
+/** Occurrence/telemetry effort-source vocabulary; distinct from the decision's four-state vocabulary. */
+type SqliteEffortSource = "none" | "client" | "variant" | "variant_coerced";
+
export interface RuntimeTelemetryRecord {
readonly requestId: string;
readonly routingDecisionId: string;
readonly endpointId: string;
readonly reasoningEffort: string | null;
- readonly effortSource: "none" | "client" | "variant" | "variant_coerced";
+ readonly effortSource: SqliteEffortSource;
+ /** True when the named effort was coerced from a variant (historical variant_coerced). */
+ readonly effortCoerced?: boolean;
readonly conversationId: string;
readonly createdAtMs: number;
readonly clientRequestId: string | null;
@@ -1306,7 +1320,8 @@ export interface PersistedRuntimeObservationBundle {
readonly routingDecisionId: string;
readonly endpointId: string;
readonly reasoningEffort?: string | null;
- readonly effortSource?: "none" | "client" | "variant" | "variant_coerced";
+ readonly effortSource?: SqliteEffortSource;
+ readonly effortCoerced?: boolean;
readonly conversationId: string;
readonly usageEvent: {
readonly timestamp_ms: number;
@@ -1414,7 +1429,7 @@ export interface PersistedRuntimeObservationBundle {
};
readonly telemetrySnapshot?: {
readonly reasoningEffort?: string | null;
- readonly effortSource?: "none" | "client" | "variant" | "variant_coerced";
+ readonly effortSource?: SqliteEffortSource;
readonly providerId: string | null;
readonly providerAccountId: string | null;
readonly sourceType: "local" | "remote";
@@ -2948,17 +2963,19 @@ function mapRuntimeTelemetryRecord(row: {
dimensions?.promptCacheRequestSource === "synthesized"
? dimensions.promptCacheRequestSource
: null;
+ const effortSource =
+ row.effort_source === "client" ||
+ row.effort_source === "variant" ||
+ row.effort_source === "variant_coerced"
+ ? row.effort_source
+ : "none";
return {
requestId: row.request_id,
routingDecisionId: row.routing_decision_id,
endpointId: row.endpoint_id,
reasoningEffort: row.reasoning_effort ?? null,
- effortSource:
- row.effort_source === "client" ||
- row.effort_source === "variant" ||
- row.effort_source === "variant_coerced"
- ? row.effort_source
- : "none",
+ effortSource,
+ ...(effortSource === "variant_coerced" ? { effortCoerced: true } : {}),
conversationId: row.conversation_id,
createdAtMs: row.created_at_ms,
clientRequestId: row.client_request_id,
@@ -3154,6 +3171,7 @@ function toRuntimeTelemetryRecord(
observation.effortSource ??
telemetrySnapshot?.effortSource ??
(reasoningEffort === null ? "none" : "client");
+ const effortCoerced = observation.effortCoerced ?? effortSource === "variant_coerced";
const difficultyBucketCandidate =
routingDiagnostics?.difficultyRouting?.difficulty ??
observation.observedPerformance.sample.difficulty_bucket ??
@@ -3225,6 +3243,7 @@ function toRuntimeTelemetryRecord(
endpointId: observation.endpointId,
reasoningEffort,
effortSource,
+ ...(effortCoerced ? { effortCoerced: true } : {}),
conversationId: observation.conversationId,
createdAtMs: observation.usageEvent.timestamp_ms,
clientRequestId: observation.clientRequestId ?? null,
@@ -3383,7 +3402,7 @@ function runtimeTelemetryInsertValues(
record.routingDecisionId,
record.endpointId,
record.reasoningEffort,
- record.effortSource,
+ record.effortCoerced ? "variant_coerced" : record.effortSource,
record.conversationId,
record.createdAtMs,
record.clientRequestId,
@@ -3501,12 +3520,14 @@ function toFailureRuntimeTelemetryRecord(
input.observation.capturePolicy !== null
? (input.observation.capturePolicy as Record)
: null;
+ const effortSource = input.effortSource ?? (input.reasoningEffort ? "client" : "none");
return {
requestId: input.requestId,
routingDecisionId,
endpointId,
reasoningEffort: input.reasoningEffort ?? null,
- effortSource: input.effortSource ?? (input.reasoningEffort ? "client" : "none"),
+ effortSource,
+ ...((input.effortCoerced ?? effortSource === "variant_coerced") ? { effortCoerced: true } : {}),
conversationId: "conversation-main",
createdAtMs,
clientRequestId: input.clientRequestId ?? null,
@@ -5014,7 +5035,9 @@ export interface PersistRuntimeTelemetryFailureInput {
readonly routingDecisionId?: string;
readonly endpointId?: string;
readonly reasoningEffort?: string | null;
- readonly effortSource?: "none" | "client" | "variant" | "variant_coerced";
+ readonly effortSource?: SqliteEffortSource;
+ /** True when the named effort was coerced from a variant (historical `variant_coerced`). */
+ readonly effortCoerced?: boolean;
readonly modelId?: string;
readonly requestedModelId?: string | null;
readonly selectedModelId?: string | null;
diff --git a/role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts b/role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts
new file mode 100644
index 000000000..7ee3763c3
--- /dev/null
+++ b/role-model-router/packages/sqlite-memory/test/run106-effort-source-migration.test.ts
@@ -0,0 +1,71 @@
+import { mkdir, mkdtemp, rm } from "node:fs/promises";
+import os from "node:os";
+import path from "node:path";
+import { DatabaseSync } from "node:sqlite";
+import { describe, expect, test } from "vitest";
+
+import {
+ initializeSqliteMemory,
+ readRuntimeTelemetryRecord,
+ resolveSqliteMemoryLocation,
+} from "../src/index.ts";
+
+describe("Run 106 effort-source occurrence vocabulary", () => {
+ test("preserves the binary occurrence vocabulary and reads null effort_source as none", async () => {
+ const runtimeStateRoot = await mkdtemp(path.join(os.tmpdir(), "sqlite-effort-vocab-"));
+ const scopeId = "run106-effort-vocab";
+ const databasePath = resolveSqliteMemoryLocation({ runtimeStateRoot, scopeId });
+ try {
+ await mkdir(path.dirname(databasePath), { recursive: true });
+ const database = new DatabaseSync(databasePath);
+ database.exec(
+ "CREATE TABLE runtime_telemetry_records (" +
+ "request_id TEXT PRIMARY KEY, routing_decision_id TEXT NOT NULL, endpoint_id TEXT NOT NULL, " +
+ "reasoning_effort TEXT, effort_source TEXT, conversation_id TEXT NOT NULL, created_at_ms INTEGER NOT NULL" +
+ "); " +
+ "INSERT INTO runtime_telemetry_records (request_id, routing_decision_id, endpoint_id, reasoning_effort, effort_source, conversation_id, created_at_ms) VALUES " +
+ "('req-client', 'd1', 'e1', 'high', 'client', 'c', 1), " +
+ "('req-variant', 'd2', 'e2', 'high', 'variant', 'c', 2), " +
+ "('req-coerced', 'd3', 'e3', 'max', 'variant_coerced', 'c', 3), " +
+ "('req-none', 'd4', 'e4', NULL, 'none', 'c', 4), " +
+ "('req-null-default', 'd6', 'e6', NULL, NULL, 'c', 6);",
+ );
+ database.close();
+
+ initializeSqliteMemory({ runtimeStateRoot, scopeId, channel: "development" });
+
+ const reopened = new DatabaseSync(databasePath);
+ const stored = reopened
+ .prepare(
+ "SELECT request_id, reasoning_effort, effort_source FROM runtime_telemetry_records ORDER BY created_at_ms",
+ )
+ .all();
+ reopened.close();
+
+ // The binary occurrence vocabulary is preserved as-is; no four-state rewrite.
+ expect(stored).toEqual([
+ { request_id: "req-client", reasoning_effort: "high", effort_source: "client" },
+ { request_id: "req-variant", reasoning_effort: "high", effort_source: "variant" },
+ { request_id: "req-coerced", reasoning_effort: "max", effort_source: "variant_coerced" },
+ { request_id: "req-none", reasoning_effort: null, effort_source: "none" },
+ { request_id: "req-null-default", reasoning_effort: null, effort_source: null },
+ ]);
+
+ // The read path keeps coercion readable and normalizes a null source to none.
+ expect(readRuntimeTelemetryRecord({ databasePath, requestId: "req-coerced" })).toMatchObject({
+ effortSource: "variant_coerced",
+ effortCoerced: true,
+ });
+ expect(readRuntimeTelemetryRecord({ databasePath, requestId: "req-none" })).toMatchObject({
+ effortSource: "none",
+ });
+ expect(
+ readRuntimeTelemetryRecord({ databasePath, requestId: "req-null-default" }),
+ ).toMatchObject({
+ effortSource: "none",
+ });
+ } finally {
+ await rm(runtimeStateRoot, { recursive: true, force: true });
+ }
+ });
+});
diff --git a/role-model-router/packages/trace/package.json b/role-model-router/packages/trace/package.json
index 3c8589685..370bc3344 100644
--- a/role-model-router/packages/trace/package.json
+++ b/role-model-router/packages/trace/package.json
@@ -12,7 +12,8 @@
},
"files": ["src", "dist"],
"dependencies": {
- "@role-model/protocol-types": "workspace:*"
+ "@role-model/protocol-types": "workspace:*",
+ "@role-model-router/core": "workspace:*"
},
"scripts": {
"build": "tsc -p tsconfig.json",
diff --git a/role-model-router/packages/trace/src/index.ts b/role-model-router/packages/trace/src/index.ts
index 27f901b6e..1cec439ec 100644
--- a/role-model-router/packages/trace/src/index.ts
+++ b/role-model-router/packages/trace/src/index.ts
@@ -7,14 +7,17 @@ export * from "./projections/index.js";
export * from "./lineage.js";
export type TraceEffortSource = "none" | "client" | "variant" | "variant_coerced";
+export type TraceEffortSourceValue = TraceEffortSource;
export interface TraceEffortFields {
readonly reasoning_effort?: string | null;
readonly effort_source?: TraceEffortSource;
}
-export type TraceSpanRecord = TraceSpan & TraceEffortFields;
-export type TraceEventRecord = TraceEvent & TraceEffortFields;
+export type TraceSpanRecord = Omit &
+ TraceEffortFields;
+export type TraceEventRecord = Omit &
+ TraceEffortFields;
export async function writeTraceArtifacts(
outputDir: string,
diff --git a/role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts b/role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts
new file mode 100644
index 000000000..3e130c5dd
--- /dev/null
+++ b/role-model-router/packages/trace/test/run106-lineage-effort-source.test.ts
@@ -0,0 +1,82 @@
+import { describe, expect, test } from "vitest";
+
+import { type TraceLineageManifestInput, createTraceLineageManifest } from "../src/index.js";
+
+const stageNames = [
+ "router_ingress",
+ "routing_attempt",
+ "upstream_execution",
+ "runtime_observation",
+ "message_graph",
+ "contribution",
+ "crowdsourcing",
+ "recommendation",
+] as const;
+
+function makeInput(effort: {
+ reasoning_effort: string | null;
+ effort_source: string;
+}): TraceLineageManifestInput {
+ const common = {
+ request_id: "req-run106-effort",
+ routing_decision_id: "decision-run106-effort",
+ endpoint_id: "endpoint-run106-effort",
+ model_id: "model/run106",
+ reasoning_effort: effort.reasoning_effort,
+ effort_source: effort.effort_source,
+ };
+ return {
+ ...common,
+ source_set: ["request:req-run106-effort"],
+ stages: stageNames.map((stage, index) => ({
+ ...common,
+ stage_id: `stage-${stage}`,
+ stage,
+ receipt_id: `receipt-${stage}`,
+ disposition: "recorded" as const,
+ predecessor_stage_id: index ? `stage-${stageNames[index - 1]}` : undefined,
+ ...(stage === "message_graph"
+ ? {
+ artifact_hash: "sha256:graph",
+ occurrence_id: "occurrence-message",
+ content_id: "content-message",
+ predecessor_occurrence_id: "occurrence-root",
+ }
+ : {}),
+ })),
+ };
+}
+
+describe("Run 106 trace lineage effort-source", () => {
+ test("round-trips the occurrence/telemetry effort-source vocabulary", () => {
+ expect(
+ createTraceLineageManifest(makeInput({ reasoning_effort: "high", effort_source: "client" })),
+ ).toMatchObject({ reasoning_effort: "high", effort_source: "client" });
+
+ expect(
+ createTraceLineageManifest(makeInput({ reasoning_effort: "high", effort_source: "variant" })),
+ ).toMatchObject({ reasoning_effort: "high", effort_source: "variant" });
+
+ expect(
+ createTraceLineageManifest(
+ makeInput({ reasoning_effort: "high", effort_source: "variant_coerced" }),
+ ),
+ ).toMatchObject({ reasoning_effort: "high", effort_source: "variant_coerced" });
+
+ expect(
+ createTraceLineageManifest(makeInput({ reasoning_effort: null, effort_source: "none" })),
+ ).toMatchObject({ reasoning_effort: null, effort_source: "none" });
+ });
+
+ test("rejects a non-none source without an effort level", () => {
+ expect(() =>
+ createTraceLineageManifest(makeInput({ reasoning_effort: null, effort_source: "variant" })),
+ ).toThrow(/effort|none/i);
+ });
+
+ test("rejects a none source carrying an effort level", () => {
+ expect(() =>
+ createTraceLineageManifest(makeInput({ reasoning_effort: "high", effort_source: "none" })),
+ ).toThrow(/effort|none/i);
+ });
+});
diff --git a/role-model-router/packages/usage/src/index.ts b/role-model-router/packages/usage/src/index.ts
index dcb75cc16..74736903b 100644
--- a/role-model-router/packages/usage/src/index.ts
+++ b/role-model-router/packages/usage/src/index.ts
@@ -16,7 +16,6 @@ export interface UsageLinkageDecision {
readonly request_id: string;
readonly routing_decision_id: string;
readonly reasoning_effort?: string | null;
- readonly effort_source?: UsageEffortSource;
}
function normalizeEffortFields(event: UsageEventRecord): Required {
@@ -117,10 +116,5 @@ export function validateUsageLinkage(
`Usage event ${event.event_id} reasoning_effort ${eventEffort.reasoning_effort ?? "default"} does not match ${decisionEffort ?? "default"}.`,
);
}
- if (decision.effort_source && eventEffort.effort_source !== decision.effort_source) {
- throw new Error(
- `Usage event ${event.event_id} effort_source ${eventEffort.effort_source} does not match ${decision.effort_source}.`,
- );
- }
}
}
diff --git a/role-model-router/packages/usage/test/run91-effort-lineage.test.ts b/role-model-router/packages/usage/test/run91-effort-lineage.test.ts
index 1f4642e89..b03bd4c87 100644
--- a/role-model-router/packages/usage/test/run91-effort-lineage.test.ts
+++ b/role-model-router/packages/usage/test/run91-effort-lineage.test.ts
@@ -105,7 +105,6 @@ describe("Run 91 usage effort lineage", () => {
request_id: "req-001",
routing_decision_id: "dec-001",
reasoning_effort: "low",
- effort_source: "variant",
}),
).toThrow(/reasoning_effort medium does not match low/);
});