Defines Tier: a harness-agnostic complexity bucket (Auto, Low, Med, High)
used to classify task complexity and gate model selection.
Tier derives PartialOrd such that Auto < Low < Med < High. Gating is a simple
> comparison: a task whose effective tier exceeds the running model’s tier should
prompt the user to switch.
Defines ModelConfig (under [model] in the global TOML config) and TierMap (per-harness
tier→model name resolution under [model.tiers.<harness>]).
detect_harness() reads environment variables (CLAUDE_CODE_SESSION, CODEX_SESSION)
to identify the active agent harness, falling back to "default".
resolve_tier_to_model(tier, harness, config) maps a Tier to the concrete model name
configured for the given harness, falling back to built-in defaults for the
claude-code, codex, and default harnesses.
tier_from_model_name(name, harness, config) is the reverse lookup: given a concrete
model name (e.g., "opus"), find the tier it belongs to in the harness mapping.
Tier::FromStr accepts case-insensitive auto | low | med | high.
Total ordering: Tier implements PartialOrd deterministically; gating logic
is a single comparison and can be safely executed by any model tier.
Auto is the lowest: Tier::Auto represents “no preference” and compares less than
Low. The effective_tier composition treats Auto as “fall through to next source.”
Built-in defaults: when no [model.tiers.<harness>] section is present, the
resolver falls back to compiled-in maps for known harnesses. This means a fresh
install needs zero config for the common case.
Reverse lookup is partial: tier_from_model_name returns None if the model
name doesn’t appear in any tier slot for the harness. Callers should treat None
as “unknown — leave tier as Auto.”