This repository was archived by the owner on May 26, 2026. It is now read-only.
KR-P2-K ST3: downshift selector pure-function library - #68
Merged
Conversation
rafe-walker
changed the base branch from
feat/kora-KR-P2-K-st2-estimator-wire-in
to
main
May 22, 2026 00:11
`agent/cost_downshift.py`: rung-aware ticket-criticality-aware
selector that decides effective model tier (or defer) per R4.1 §9.6.
Per PM ruling A1 the substrate's 2-value criticality CHECK enum
(`downshift_eligible` / `frontier_only`, migration 0098) is the source
of truth; NULL is treated as `frontier_only` for fail-CLOSED safety.
Per-rung behavior:
- NORMAL: all tickets run at configured_tier.
- WARN_75: downshift_eligible steps one tier (Opus→Sonnet,
Sonnet→Haiku, Haiku floor); frontier_only / NULL defer.
- DOWNSHIFT_90: downshift_eligible drops to Haiku;
frontier_only / NULL defer.
- HARD_STOP_100: all defer (defensive; ST4 wires the actual
PAUSED{COST} transition so the poller never reaches selector
at this rung).
Why frontier-only defers at WARN_75 (stricter than the bucket
sketch's "only DOWNSHIFT_90 defers"): PM ruling text is explicit
that any cost-pressure rung defers non-eligible tickets. Conservative
choice is correct — at WARN_75 we're already projected to overrun
the pool, so continuing non-downshiftable work compounds the
projection.
Pure-function library; no state mutation. Returns a frozen
`DownshiftDecision(defer, effective_tier, reason)`. Poller wire-in
deferred until KR-P2-E (Sea_Ticket consumer) lands.
Also ships `classify_model_tier(model_name)` helper for callers
that need to map full identifiers (`anthropic/claude-opus-4.6`,
`claude-haiku-4-5`, etc.) onto the 3-value tier enum.
Tests: 69 pytest parameterized across 4 rungs x 3 criticality
values x 3 configured tiers; pyright/ruff clean. Combined
KR-P2-K suite (ST1+ST2+ST3) = 121 passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rafe-walker
force-pushed
the
feat/kora-KR-P2-K-st3-downshift-selector
branch
from
May 22, 2026 00:12
a320ec3 to
9b4fb18
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ST3 of KR-P2-K (cost ladder runtime, R4.1 §9.6). Ships
`agent/cost_downshift.py` — a pure-function library that the
future Sea_Ticket poller (KR-P2-E) and any other dispatch site
can consult to decide what model tier to run a ticket at, or
whether to defer it entirely.
Per-rung behavior (PM ruling A1)
Substrate `tickets.criticality` is a 2-value CHECK enum from
migration 0098: `downshift_eligible` / `frontier_only`. NULL is
treated as `frontier_only` (fail-CLOSED).
Why frontier-only defers at WARN_75 (stricter than the bucket
sketch): PM ruling text is explicit — any cost-pressure rung
defers non-eligible tickets. At WARN_75 we are already projected
to overrun the pool, so continuing non-downshiftable work
compounds the projection. Documented in module docstring.
Module surface
```python
class ModelTier(str, Enum): # OPUS / SONNET / HAIKU
@DataClass(frozen=True, slots=True)
class DownshiftDecision:
defer: bool
effective_tier: Optional[ModelTier]
reason: str # operator-readable
def select_effective_model_tier(
ticket_criticality: Optional[str],
active_rung: CostRung,
configured_tier: ModelTier,
) -> DownshiftDecision: ...
def classify_model_tier(model_name: Optional[str]) -> Optional[ModelTier]: ...
```
Pure functions; no state mutation. Caller acts on the
DownshiftDecision.
Scope note — poller wire-in deferred
The bucket spec ST3 title says "selector + poller per-rung
filtering." The poller (KR-P2-E Sea_Ticket consumer) is parked
pending substrate fix-up. This PR ships the selector library
only; the caller wire-in (skip non-eligible tickets at
WARN_75+, transition deferred tickets to `deferred_cost_limit`
status) lands when KR-P2-E unblocks. The selector's public
surface is stable and unit-tested independently of any consumer.
Test plan
across 4 rungs x 3 criticality values x 3 configured tiers
Cascade
Stacked on #67 (ST2). Base-switch to main when #67 merges, then
this merges into main.
🤖 Generated with Claude Code