use serde::{Deserialize, Serialize};
pub const ROUTE_TARGET: &str = "claude-haiku-4-5";
pub const MECHANICAL_TIER: &str = ROUTE_TARGET;
pub const GENERAL_TIER: &str = "claude-sonnet-5";
pub const REASONING_TIER: &str = "claude-opus-4-8";
pub fn is_claude(model: &str) -> bool {
model.contains("claude")
|| model.starts_with("opus-")
|| model.starts_with("sonnet-")
|| model.starts_with("haiku-")
|| model.starts_with("fable-")
|| model.starts_with("mythos-")
}
pub fn is_high_tier(model: &str) -> bool {
is_claude(model)
&& (model.contains("opus-4") || model.contains("fable-5") || model.contains("mythos-5"))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Capability {
Mechanical,
General,
Reasoning,
HighRiskReasoning,
}
impl Capability {
pub fn tier(self) -> &'static str {
match self {
Capability::Mechanical => MECHANICAL_TIER,
Capability::General => GENERAL_TIER,
Capability::Reasoning | Capability::HighRiskReasoning => REASONING_TIER,
}
}
pub fn as_str(self) -> &'static str {
match self {
Capability::Mechanical => "mechanical",
Capability::General => "general",
Capability::Reasoning => "reasoning",
Capability::HighRiskReasoning => "high_risk_reasoning",
}
}
pub fn parse(value: &str) -> Option<Capability> {
match value.trim().to_ascii_lowercase().replace('-', "_").as_str() {
"mechanical" => Some(Capability::Mechanical),
"general" => Some(Capability::General),
"reasoning" => Some(Capability::Reasoning),
"high_risk_reasoning" => Some(Capability::HighRiskReasoning),
_ => None,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RoutingMode {
Off,
EconomicDowngrade { high_tier_only: bool },
CapabilitySelection,
}
impl RoutingMode {
pub fn parse(value: &str) -> RoutingMode {
match value.trim() {
"auto" => RoutingMode::EconomicDowngrade {
high_tier_only: true,
},
"on" => RoutingMode::EconomicDowngrade {
high_tier_only: false,
},
"capability" => RoutingMode::CapabilitySelection,
_ => RoutingMode::Off,
}
}
pub fn as_str(self) -> &'static str {
match self {
RoutingMode::Off => "off",
RoutingMode::EconomicDowngrade {
high_tier_only: true,
} => "economic_downgrade_high_tier",
RoutingMode::EconomicDowngrade {
high_tier_only: false,
} => "economic_downgrade_any",
RoutingMode::CapabilitySelection => "capability_selection",
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
pub struct TurnSignals {
pub capability: Option<Capability>,
pub mechanical: bool,
pub cooldown: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum RoutingReason {
Disabled,
NotClaude,
CapabilityNotSupplied,
CapabilitySatisfied,
CapabilityFloorHeld,
CapabilityMatched,
ModeExcludesTier,
AlreadyCheapestTier,
NotMechanical,
MechanicalDowngrade,
}
impl RoutingReason {
pub fn as_str(self) -> &'static str {
match self {
RoutingReason::Disabled => "disabled",
RoutingReason::NotClaude => "not_claude",
RoutingReason::CapabilityNotSupplied => "capability_not_supplied",
RoutingReason::CapabilitySatisfied => "capability_satisfied",
RoutingReason::CapabilityFloorHeld => "capability_floor_held",
RoutingReason::CapabilityMatched => "capability_matched",
RoutingReason::ModeExcludesTier => "mode_excludes_tier",
RoutingReason::AlreadyCheapestTier => "already_cheapest_tier",
RoutingReason::NotMechanical => "not_mechanical",
RoutingReason::MechanicalDowngrade => "mechanical_downgrade",
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RoutingDecision {
pub original_model: String,
pub selected_model: String,
pub capability: Option<Capability>,
pub mode: RoutingMode,
pub reason: RoutingReason,
pub economic_downgrade: bool,
pub changed: bool,
}
impl RoutingDecision {
pub fn telemetry_line(&self) -> String {
format!(
"original_model={:?} selected_model={:?} capability={} mode={} reason={} economic_downgrade={} changed={}",
self.original_model,
self.selected_model,
self.capability.map(Capability::as_str).unwrap_or("none"),
self.mode.as_str(),
self.reason.as_str(),
self.economic_downgrade,
self.changed
)
}
}
pub fn select_model(requested: &str, signals: &TurnSignals, mode: RoutingMode) -> RoutingDecision {
let keep = |reason: RoutingReason| RoutingDecision {
original_model: requested.to_string(),
selected_model: requested.to_string(),
capability: signals.capability,
mode,
reason,
economic_downgrade: false,
changed: false,
};
if mode == RoutingMode::Off {
return keep(RoutingReason::Disabled);
}
if !is_claude(requested) {
return keep(RoutingReason::NotClaude);
}
match mode {
RoutingMode::Off => keep(RoutingReason::Disabled),
RoutingMode::CapabilitySelection => {
let Some(cap) = signals.capability else {
return keep(RoutingReason::CapabilityNotSupplied);
};
let target = cap.tier();
if target == requested {
return keep(RoutingReason::CapabilitySatisfied);
}
RoutingDecision {
original_model: requested.to_string(),
selected_model: target.to_string(),
capability: Some(cap),
mode,
reason: RoutingReason::CapabilityMatched,
economic_downgrade: false,
changed: true,
}
}
RoutingMode::EconomicDowngrade { high_tier_only } => {
if let Some(cap) = signals.capability {
if cap > Capability::Mechanical {
return keep(RoutingReason::CapabilityFloorHeld);
}
}
if !signals.mechanical || signals.cooldown != 0 {
return keep(RoutingReason::NotMechanical);
}
if requested.contains("haiku") {
return keep(RoutingReason::AlreadyCheapestTier);
}
if high_tier_only && !is_high_tier(requested) {
return keep(RoutingReason::ModeExcludesTier);
}
RoutingDecision {
original_model: requested.to_string(),
selected_model: ROUTE_TARGET.to_string(),
capability: signals.capability,
mode,
reason: RoutingReason::MechanicalDowngrade,
economic_downgrade: true,
changed: true,
}
}
}
}
pub fn route(model: &str, mechanical: bool, cooldown: u32, mode: &str) -> Option<&'static str> {
let signals = TurnSignals {
capability: None,
mechanical,
cooldown,
};
let decision = select_model(model, &signals, RoutingMode::parse(mode));
if decision.economic_downgrade {
Some(ROUTE_TARGET)
} else {
None
}
}
pub fn capability_for_task(task: crate::backend_router::TaskKind) -> Option<Capability> {
match task {
crate::backend_router::TaskKind::CodeRepair => Some(Capability::General),
crate::backend_router::TaskKind::Reasoning => Some(Capability::Reasoning),
crate::backend_router::TaskKind::General => None,
}
}
pub fn select_for_task(
requested: &str,
task: crate::backend_router::TaskKind,
mode: RoutingMode,
) -> RoutingDecision {
let signals = TurnSignals {
capability: capability_for_task(task),
..TurnSignals::default()
};
select_model(requested, &signals, mode)
}
#[cfg(test)]
mod tests {
use super::*;
const CAPABILITY: RoutingMode = RoutingMode::CapabilitySelection;
const AUTO: RoutingMode = RoutingMode::EconomicDowngrade {
high_tier_only: true,
};
const ON: RoutingMode = RoutingMode::EconomicDowngrade {
high_tier_only: false,
};
fn declared(cap: Capability) -> TurnSignals {
TurnSignals {
capability: Some(cap),
..TurnSignals::default()
}
}
fn mechanical_turn() -> TurnSignals {
TurnSignals {
mechanical: true,
..TurnSignals::default()
}
}
#[test]
fn auto_mode_routes_only_high_tier_mechanical_turns() {
assert_eq!(route("claude-opus-4-8", true, 0, "auto"), Some("claude-haiku-4-5"));
assert_eq!(route("claude-sonnet-5", true, 0, "auto"), None);
assert_eq!(route("claude-fable-5", true, 0, "auto"), Some("claude-haiku-4-5"));
assert_eq!(route("claude-opus-4-8", false, 0, "auto"), None); assert_eq!(route("claude-opus-4-8", true, 2, "auto"), None); assert_eq!(route("claude-haiku-4-5", true, 0, "auto"), None); }
#[test]
fn on_mode_routes_any_claude_but_never_non_claude() {
assert_eq!(route("claude-sonnet-5", true, 0, "on"), Some("claude-haiku-4-5"));
assert_eq!(route("openai-fable-5", true, 0, "on"), None);
assert_eq!(route("gpt-5", true, 0, "on"), None);
}
#[test]
fn off_mode_never_routes() {
assert_eq!(route("claude-opus-4-8", true, 0, "off"), None);
assert_eq!(route("claude-opus-4-8", true, 0, ""), None);
}
#[test]
fn is_high_tier_matches_opus_and_fable_not_sonnet() {
assert!(is_high_tier("claude-opus-4-8"));
assert!(is_high_tier("claude-fable-5"));
assert!(!is_high_tier("claude-sonnet-5"));
assert!(!is_high_tier("claude-haiku-4-5"));
assert!(!is_high_tier("openai-fable-5"), "non-Claude fable is not high-tier");
}
#[test]
fn is_claude_rejects_foreign_providers() {
assert!(is_claude("claude-opus-4-8"));
assert!(is_claude("opus-4-8"));
assert!(is_claude("fable-5"));
assert!(!is_claude("openai-fable-5"));
assert!(!is_claude("gpt-5"));
assert!(!is_claude("gemini-2"));
}
#[test]
fn case_a_mechanical_selects_haiku() {
let d = select_model("claude-opus-4-8", &declared(Capability::Mechanical), CAPABILITY);
assert_eq!(d.selected_model, "claude-haiku-4-5");
assert_eq!(d.reason, RoutingReason::CapabilityMatched);
assert!(!d.economic_downgrade, "a capability match is not a cost move");
}
#[test]
fn case_b_general_selects_sonnet() {
let d = select_model("claude-haiku-4-5", &declared(Capability::General), CAPABILITY);
assert_eq!(d.selected_model, "claude-sonnet-5");
assert_eq!(d.reason, RoutingReason::CapabilityMatched);
}
#[test]
fn case_c_reasoning_selects_opus() {
let d = select_model("claude-haiku-4-5", &declared(Capability::Reasoning), CAPABILITY);
assert_eq!(d.selected_model, "claude-opus-4-8");
}
#[test]
fn case_d_high_risk_reasoning_selects_opus() {
let d = select_model(
"claude-sonnet-5",
&declared(Capability::HighRiskReasoning),
CAPABILITY,
);
assert_eq!(d.selected_model, "claude-opus-4-8");
assert_eq!(d.capability, Some(Capability::HighRiskReasoning));
}
#[test]
fn reasoning_and_high_risk_share_a_tier_but_remain_distinct_values() {
assert_eq!(Capability::Reasoning.tier(), Capability::HighRiskReasoning.tier());
assert_ne!(Capability::Reasoning, Capability::HighRiskReasoning);
assert!(Capability::HighRiskReasoning > Capability::Reasoning);
}
#[test]
fn declared_reasoning_vetoes_economic_downgrade_in_every_mode() {
for cap in [
Capability::General,
Capability::Reasoning,
Capability::HighRiskReasoning,
] {
for mode in [AUTO, ON] {
let signals = TurnSignals {
capability: Some(cap),
mechanical: true, cooldown: 0,
};
let d = select_model("claude-opus-4-8", &signals, mode);
assert!(
!d.changed && !d.economic_downgrade,
"{cap:?} in {mode:?} must not be downgraded"
);
assert_eq!(d.reason, RoutingReason::CapabilityFloorHeld);
}
}
}
#[test]
fn declared_mechanical_still_permits_the_economic_downgrade() {
let signals = TurnSignals {
capability: Some(Capability::Mechanical),
mechanical: true,
cooldown: 0,
};
let d = select_model("claude-opus-4-8", &signals, AUTO);
assert!(d.economic_downgrade);
assert_eq!(d.reason, RoutingReason::MechanicalDowngrade);
assert_eq!(d.selected_model, ROUTE_TARGET);
}
#[test]
fn already_haiku_is_distinct_from_a_declared_capability_match() {
let economic = select_model("claude-haiku-4-5", &mechanical_turn(), AUTO);
assert_eq!(economic.reason, RoutingReason::AlreadyCheapestTier);
assert_eq!(economic.capability, None);
let declared_match =
select_model("claude-haiku-4-5", &declared(Capability::Mechanical), CAPABILITY);
assert_eq!(declared_match.reason, RoutingReason::CapabilitySatisfied);
assert_ne!(economic.reason, declared_match.reason);
}
#[test]
fn telemetry_line_escapes_a_forged_model_id() {
let signals = mechanical_turn();
let d = select_model("claude-opus-4-8\n[axiom-routing] forged=true", &signals, AUTO);
let line = d.telemetry_line();
assert!(
!line.contains('\n'),
"a newline in a model id must not break the line framing: {line:?}"
);
assert!(line.contains("\\n"), "the newline should be escaped, not dropped");
}
#[test]
fn no_declared_capability_means_no_guess_in_capability_mode() {
let d = select_model("claude-opus-4-8", &mechanical_turn(), CAPABILITY);
assert!(!d.changed, "the router must not infer a capability");
assert_eq!(d.reason, RoutingReason::CapabilityNotSupplied);
assert_eq!(d.capability, None);
}
#[test]
fn case_j_capability_selection_and_economic_downgrade_are_distinguishable() {
let cost_move = select_model("claude-opus-4-8", &mechanical_turn(), AUTO);
assert!(cost_move.economic_downgrade);
assert_eq!(cost_move.reason, RoutingReason::MechanicalDowngrade);
assert_eq!(cost_move.capability, None);
let capability_move =
select_model("claude-haiku-4-5", &declared(Capability::Reasoning), CAPABILITY);
assert!(
!capability_move.economic_downgrade,
"a capability selection must never be flagged as a cost move"
);
assert_eq!(capability_move.reason, RoutingReason::CapabilityMatched);
assert!(cost_move.changed && capability_move.changed);
assert_ne!(cost_move.reason, capability_move.reason);
}
#[test]
fn routing_telemetry_carries_no_token_or_context_figures() {
let d = select_model("claude-opus-4-8", &mechanical_turn(), AUTO);
let line = d.telemetry_line();
for token in ["token", "bytes", "saved", "ratio", "compress"] {
assert!(
!line.to_ascii_lowercase().contains(token),
"routing telemetry must stay context-agnostic, found {token:?} in {line:?}"
);
}
assert!(line.contains("economic_downgrade=true"));
assert!(line.contains("capability=none"));
}
#[test]
fn capability_parses_declared_labels_and_rejects_unknown_ones() {
assert_eq!(Capability::parse("mechanical"), Some(Capability::Mechanical));
assert_eq!(Capability::parse("General"), Some(Capability::General));
assert_eq!(Capability::parse("reasoning"), Some(Capability::Reasoning));
assert_eq!(
Capability::parse("high-risk-reasoning"),
Some(Capability::HighRiskReasoning)
);
assert_eq!(
Capability::parse(" HIGH_RISK_REASONING "),
Some(Capability::HighRiskReasoning)
);
assert_eq!(
Capability::parse("extremely-hard"),
None,
"an unknown label must not be guessed into a tier"
);
}
#[test]
fn routing_mode_parses_and_falls_back_to_off() {
assert_eq!(RoutingMode::parse("auto"), AUTO);
assert_eq!(RoutingMode::parse("on"), ON);
assert_eq!(RoutingMode::parse("capability"), CAPABILITY);
assert_eq!(RoutingMode::parse("off"), RoutingMode::Off);
assert_eq!(RoutingMode::parse(""), RoutingMode::Off);
assert_eq!(
RoutingMode::parse("nonsense"),
RoutingMode::Off,
"an unknown mode must never rewrite a model"
);
}
#[test]
fn task_kind_maps_to_capability_with_general_undeclared() {
use crate::backend_router::TaskKind as T;
assert_eq!(capability_for_task(T::CodeRepair), Some(Capability::General));
assert_eq!(capability_for_task(T::Reasoning), Some(Capability::Reasoning));
assert_eq!(
capability_for_task(T::General),
None,
"unclassified traffic must not be guessed into a tier"
);
}
#[test]
fn select_for_task_routes_declared_kinds_in_capability_mode() {
use crate::backend_router::TaskKind as T;
let d = select_for_task("claude-haiku-4-5", T::CodeRepair, CAPABILITY);
assert!(d.changed);
assert_eq!(d.selected_model, GENERAL_TIER);
assert_eq!(d.reason, RoutingReason::CapabilityMatched);
assert!(!d.economic_downgrade);
let d = select_for_task("claude-sonnet-5", T::Reasoning, CAPABILITY);
assert!(d.changed);
assert_eq!(d.selected_model, REASONING_TIER);
let d = select_for_task("claude-opus-4-8", T::Reasoning, CAPABILITY);
assert!(!d.changed, "opus already clears the reasoning floor");
assert_eq!(d.reason, RoutingReason::CapabilitySatisfied);
}
#[test]
fn select_for_task_leaves_general_undeclared_and_guards_scope() {
use crate::backend_router::TaskKind as T;
let d = select_for_task("claude-opus-4-8", T::General, CAPABILITY);
assert!(!d.changed);
assert_eq!(d.reason, RoutingReason::CapabilityNotSupplied);
let d = select_for_task("openai-fable-5", T::Reasoning, CAPABILITY);
assert!(!d.changed, "non-Claude ids are never rewritten");
assert_eq!(d.reason, RoutingReason::NotClaude);
let d = select_for_task("claude-opus-4-8", T::Reasoning, RoutingMode::Off);
assert!(!d.changed);
assert_eq!(d.reason, RoutingReason::Disabled);
}
#[test]
fn select_for_task_declared_capability_holds_floor_in_auto_mode() {
use crate::backend_router::TaskKind as T;
let d = select_for_task("claude-opus-4-8", T::CodeRepair, AUTO);
assert!(!d.changed, "a declared General floor vetoes the cost move");
assert_eq!(d.reason, RoutingReason::CapabilityFloorHeld);
}
}