Skip to content

feat(auto-routing): add model-switch telemetry to decision logging#4623

Merged
iscekic merged 3 commits into
mainfrom
feat/auto-routing-decision-telemetry
Jul 20, 2026
Merged

feat(auto-routing): add model-switch telemetry to decision logging#4623
iscekic merged 3 commits into
mainfrom
feat/auto-routing-decision-telemetry

Conversation

@iscekic

@iscekic iscekic commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Stacked on #4611; retarget to main once it merges.

Problem

We cannot measure real model switching in kilo-auto/efficient today: the auto_routing_decision log event has no incumbent field (sticky: false fires even when the model did not change), and successful decisions are sampled at ~1%, which decimates within-session switch sequences. This telemetry gates planned policy improvements (threshold hardening, near-miss hysteresis, route-flip debounce).

Changes

  • incumbentModel — the sticky model considered for this decision (null when none).
  • switched — the incumbent existed and the decided model differs from it.
  • switchReason — returned by computeDecision on the decision (additive optional contract field): threshold (incumbent denied, off the route, or below the accuracy bar), cost (the mode's switch condition triggered), capability (ejected by feat(auto-routing): modality and context-size aware efficient routing #4611's modality/context filters), null when there was no incumbent or it was kept.
  • routeChanged — this decision's route key vs the incumbent's; the sticky cache entry now stores the route key alongside the model. Null when unknowable (no incumbent, or a pre-routeKey cache entry — old entries still parse).
  • Sampling bypass — decisions with switched: true always log; sampled: false marks bypassed lines (also retries/failures) so downstream rate math only scales sampled rows.
  • contextTokensconstraints.promptTokensEstimate when the gateway sent it (available since feat(auto-routing): modality and context-size aware efficient routing #4611), null otherwise; no new plumbing.

Notes / assumptions

  • In best_accuracy mode the accuracy-gap switch condition is reported as cost — it is the same "eligible incumbent, but the switch pays off" branch as the cost factor.
  • All fields are additive; no schema/contract breaks, no new datastores.

Verification

  • services/auto-routing: vitest 138 passed (new coverage: switchReason threshold/cost/capability, routeChanged incl. legacy sticky entries, sampling bypass on switch, drop of routine unsampled decisions), typecheck, lint clean.
  • packages/auto-routing-contracts: vitest 83 passed, typecheck, lint clean.

@iscekic iscekic self-assigned this Jul 18, 2026
@kilo-code-bot

kilo-code-bot Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the additive model-switch telemetry (commit 1, previously covered), the shared constraint-predicate refactor and file-modality fix (commit 2), and the mobile touch-target tweak (commit 3); both prior review findings are resolved in the current code and no new issues were found.

Files Reviewed (10 files)
  • packages/auto-routing-contracts/src/index.ts
  • packages/auto-routing-contracts/src/normalize.ts - previous finding resolved (bare file-key fallback dropped)
  • packages/auto-routing-contracts/src/normalize.test.ts
  • services/auto-routing/src/decide.ts
  • services/auto-routing/src/decision-cache.ts
  • services/auto-routing/src/decision-cache.test.ts
  • services/auto-routing/src/decision-engine.ts - previous finding resolved (shared modelSatisfiesConstraints predicate extracted)
  • services/auto-routing/src/decision-engine.test.ts
  • services/auto-routing/src/index.test.ts
  • apps/mobile/src/components/agents/session-message-list.tsx
Previous Review Summary (commit 2d94747)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 2d94747)

Status: No Issues Found | Recommendation: Merge

Executive Summary

Reviewed the additive model-switch telemetry fields (incumbentModel, switched, switchReason, routeChanged, contextTokens, sampled) and the sticky-cache routeKey migration across all 7 changed files with high confidence and found no security, correctness, or breaking-API issues in the changed code.

Files Reviewed (7 files)
  • packages/auto-routing-contracts/src/index.ts
  • services/auto-routing/src/decide.ts
  • services/auto-routing/src/decision-cache.ts
  • services/auto-routing/src/decision-cache.test.ts
  • services/auto-routing/src/decision-engine.ts
  • services/auto-routing/src/decision-engine.test.ts
  • services/auto-routing/src/index.test.ts

Reviewed by claude-sonnet-5 · Input: 50 · Output: 10.2K · Cached: 1.4M

Review guidance: REVIEW.md from base branch main

Base automatically changed from feat/auto-routing-capability-aware to main July 20, 2026 23:00
Comment thread packages/auto-routing-contracts/src/normalize.ts Outdated
Comment thread services/auto-routing/src/decision-engine.ts
iscekic added 3 commits July 21, 2026 01:42
The auto_routing_decision event could not measure real model switching:
sticky:false fires even when nothing changed, and ~1% success sampling
decimates within-session switch sequences.

- incumbentModel, switched, switchReason (threshold/cost/capability,
  derived inside computeDecision), and routeChanged (previous route key
  now stored alongside the sticky model) on every decision log line
- switches bypass the success sample rate; sampled:false marks bypassed
  lines so downstream rate math only scales sampled rows
- contextTokens from constraints.promptTokensEstimate when present
…ty detection

Extract modelSatisfiesConstraints/satisfiesRequiredModalities/contextProvablyTooSmall
into decision-engine so the coding-plan short-circuit and benchmark routing no longer
duplicate the policy. Drop the bare `file`-key modality fallback that misclassified
structured tool output as a document request; typed input_file/document cases still cover
the real provider shapes.
Add hitSlop={2} so the 40pt affordance meets the 44pt guideline, matching the
mic/composer control convention.
@iscekic
iscekic force-pushed the feat/auto-routing-decision-telemetry branch from 2d94747 to 46e1560 Compare July 20, 2026 23:47
@iscekic
iscekic merged commit 9574224 into main Jul 20, 2026
63 checks passed
@iscekic
iscekic deleted the feat/auto-routing-decision-telemetry branch July 20, 2026 23:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants