Role-split scarcity blend: weekly (strategic) vs 5h/time (tactical) windows with 5× weighting and advisory short-window floor #71

Closed
opened 2026-09-13 02:54:53 +00:00 by kilo · 0 comments
Member

Problem

The D-026 scarcity aggregation takes the most restrictive remaining percentage across all applicable windows (effective_remaining = min(remaining)). This was frozen so a healthy short window can never hide a critical weekly one — but the flip side treats a drained short window as equally fatal as a drained weekly one, which contradicts the owner's real workflow:

  • 5h=80% / weekly=20% and 5h=20% / weekly=80% produce an identical penalty (6400) — an artificial tie resolved by unrelated tie-breakers.
  • Zeroing the weekly quota blocks the provider for days; zeroing the five-hour window self-heals in hours. They are not the same loss.
  • A model with 5h=5% / weekly=95% currently loses to 5h=95% / weekly=5% on blended scarcity, yet the first is the strategically healthier one and per owner guidance should be preferred (its low short window is a finish-risk to surface, not a strategic deficit).

Additionally, the reset timestamps of windows are deliberately excluded from ranking (D-026), so window duration — the only honest proxy for how long an exhaustion blocks — is currently invisible to selection.

Proposal (owner guidance, 2026-09-13)

Split applicable windows into two roles (frozen mapping in code, no new required config):

  • Strategic — kind: weekly windows (and conservatively, unknown-kind token windows): represent long-horizon subscription health.
  • Tactical — kind: five_hour and resource: time (Z.ai TIME_LIMIT) windows: represent whether work can happen right now.

Blend the two role minima using the owner's planning assumption weekly quota = 5 × five-hour quota (6 total units):

units    = tactical + 5 * strategic          # each role defaults to the other when absent
effective_remaining = units // 6             # integer, 0..100
penalty_units = (100 - effective)^2          # scale 10000 — unchanged contract

Owner case table (all exact integer divisions):

tactical / strategic effective penalty
80 / 20 30 4900
20 / 80 70 900
5 / 95 80 400 — preferred ✓
95 / 5 20 6400

Plus an advisory-only short-window floor (one optional selector-policy key short_window_floor_percent, default 10, 0 disables): a known tactical window below the floor flags the selected/alternative candidate with a finish-risk warning (short_window_below_floor, serialized only when true). Advisory only — it never demotes, excludes or rewrites ranking, and 0% exhaustion still excludes in every role.

Acceptance criteria

  • Decision record D-037 in docs/decisions.md (amends D-026 aggregation; records rejected alternatives: weighted config knobs, reset-proximity penalty, lexicographic weekly-first, floor-as-ranking-class — the last rejected by the owner's 5h=5/w=95 preference).
  • assess_scarcity implements role pools (most-restrictive within each role), the integer blend, strategic-preferred governing evidence and additive strategic_window/tactical_window evidence fields.
  • Owner case table pinned by scenario tests; single-role fallbacks; unknown-kind conservative routing; exhaustion/unknown semantics unchanged.
  • Selector ranking order unchanged (knowledge class → happy-hour → blended penalty → margin → effort → preference → identity); SelectorPolicy.short_window_floor_percent additive optional member.
  • Advisory flag + human warning rendering; serialized contracts stay additive (D-032 discipline).
  • Full validation gate passes; docs updated (selection-policy.md, capacity-model.md).

Boundary

scarcity_router/scarcity.py, selector.py, selection_app.py rendering, tests, docs. No provider adapters, no catalog ratings, no REST/MCP schema-version change, no execution behavior.

## Problem The D-026 scarcity aggregation takes the most restrictive remaining percentage across **all** applicable windows (`effective_remaining = min(remaining)`). This was frozen so a healthy short window can never hide a critical weekly one — but the flip side treats a drained short window as equally fatal as a drained weekly one, which contradicts the owner's real workflow: - **5h=80% / weekly=20%** and **5h=20% / weekly=80%** produce an identical penalty (6400) — an artificial tie resolved by unrelated tie-breakers. - Zeroing the weekly quota blocks the provider for days; zeroing the five-hour window self-heals in hours. They are not the same loss. - A model with 5h=5% / weekly=95% currently loses to 5h=95% / weekly=5% on blended scarcity, yet the first is the strategically healthier one and per owner guidance should be **preferred** (its low short window is a finish-risk to surface, not a strategic deficit). Additionally, the reset timestamps of windows are deliberately excluded from ranking (D-026), so window *duration* — the only honest proxy for how long an exhaustion blocks — is currently invisible to selection. ## Proposal (owner guidance, 2026-09-13) Split applicable windows into two roles (frozen mapping in code, no new required config): - **Strategic** — `kind: weekly` windows (and conservatively, unknown-kind token windows): represent long-horizon subscription health. - **Tactical** — `kind: five_hour` and `resource: time` (Z.ai `TIME_LIMIT`) windows: represent whether work can happen right now. Blend the two role minima using the owner's planning assumption **weekly quota = 5 × five-hour quota** (6 total units): ```text units = tactical + 5 * strategic # each role defaults to the other when absent effective_remaining = units // 6 # integer, 0..100 penalty_units = (100 - effective)^2 # scale 10000 — unchanged contract ``` Owner case table (all exact integer divisions): | tactical / strategic | effective | penalty | |---|---|---| | 80 / 20 | 30 | 4900 | | 20 / 80 | 70 | 900 | | 5 / 95 | 80 | 400 — preferred ✓ | | 95 / 5 | 20 | 6400 | Plus an **advisory-only** short-window floor (one optional selector-policy key `short_window_floor_percent`, default 10, `0` disables): a known tactical window below the floor flags the selected/alternative candidate with a finish-risk warning (`short_window_below_floor`, serialized only when true). Advisory only — it never demotes, excludes or rewrites ranking, and 0% exhaustion still excludes in every role. ## Acceptance criteria - [ ] Decision record D-037 in `docs/decisions.md` (amends D-026 aggregation; records rejected alternatives: weighted config knobs, reset-proximity penalty, lexicographic weekly-first, floor-as-ranking-class — the last rejected by the owner's 5h=5/w=95 preference). - [ ] `assess_scarcity` implements role pools (most-restrictive **within** each role), the integer blend, strategic-preferred governing evidence and additive `strategic_window`/`tactical_window` evidence fields. - [ ] Owner case table pinned by scenario tests; single-role fallbacks; unknown-kind conservative routing; exhaustion/unknown semantics unchanged. - [ ] Selector ranking order unchanged (knowledge class → happy-hour → blended penalty → margin → effort → preference → identity); `SelectorPolicy.short_window_floor_percent` additive optional member. - [ ] Advisory flag + human warning rendering; serialized contracts stay additive (D-032 discipline). - [ ] Full validation gate passes; docs updated (`selection-policy.md`, `capacity-model.md`). ## Boundary `scarcity_router/scarcity.py`, `selector.py`, `selection_app.py` rendering, tests, docs. No provider adapters, no catalog ratings, no REST/MCP schema-version change, no execution behavior.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Creatidy/scarcity-router#71
No description provided.