feat(seats): accounts without a 5-hour limit

Anthropic is removing the 5-hour limit in stages (from 2026-10-31), and
an account without it reports the weekly window alone. Until now the pool
took such an account for an unprobed seat: always eligible, ranked after
every other, never held to the weekly cutoff, with no cap on its passes.

- The burst window is the 5-hour one, else the weekly one
  (Seats::BurstWindow). An account whose burst window is the weekly one is
  ranked by it and admitted under the 95 % cutoff with the passes in
  flight projected on it, at the measured share per pass (0.04 at xhigh,
  0.125 otherwise; REVIEW_GATES_LENS_COST_7D_PCT), and waits for the weekly
  reset when over it.
- Every OAuth account and the local login takes at most 128 passes at once,
  every driver's counted (REVIEW_GATES_OAUTH_CONCURRENCY): every run
  measured with 149 or more in flight on one account drew usage-limit
  rejections, none of the 119 with 139 or fewer.
- A 'concurrents' rejection pauses the seat for 20 s or its retry-after,
  not until a window's reset (a seat sat two hours at 10 % on one).
- Board entries, the folded foreign record and the board's view carry
  cost7d, so the drivers see each other's weekly load.
- `seats` and the log table say `no limit` in such an account's 5-hour
  column; the board's others-line names its weekly projection.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Jorijn van der Graaf 2026-10-31 17:07:17 +01:00
commit c28307601b
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
11 changed files with 209 additions and 26 deletions

View file

@ -97,6 +97,51 @@ int main() {
requeued = SeatPool::Settle(api2, credits, now, cfg, acfg, &ledger, log);
Check("credit error: out, recorded in the ledger, requeued", requeued && api2.at("state") == "out" && Dyn::Truthy(ledger.Entry("api2").at("outSince")));
// 2026-10-31: a 'concurrents' rejection (too many requests at once on the
// account) is a short back-off, not the window's reset.
Json sc = With(SeatPool::NewSeat("c", "oauth", "t"), {{"state", "ok"}, {"util", 10}, {"running", 1}, {"pauseUntil", 0}, {"windows", {{"five_hour", {{"utilization", 10}, {"resetsAt", now + 7000}}}}}});
Json concurrents = {{"status", "limit"}, {"reason", "You've hit your usage limit"}, {"rateType", "concurrents"}, {"rateLimit", {{"five_hour", {{"utilization", 10}, {"resetsAt", now + 7000}}}}}};
requeued = SeatPool::Settle(sc, concurrents, now, cfg, acfg, &ledger, log);
Check("a 'concurrents' rejection on an oauth seat: requeued, paused for seconds, not until the 5h reset",
requeued && sc.at("state") == "limited" && sc.at("pauseUntil").get<double>() == now + SeatPool::ConcurrentBackoffS && !SeatPool::Eligible(sc, now, cfg, acfg));
Json backOk = {{"status", "ok"}, {"rateLimit", {{"five_hour", {{"utilization", 11}, {"resetsAt", now + 7000}}}}}};
requeued = SeatPool::Settle(sc, backOk, now + SeatPool::ConcurrentBackoffS + 1, cfg, acfg, &ledger, log);
Check("...and the seat is back after the back-off", !requeued && sc.at("state") == "ok" && SeatPool::Eligible(sc, now + SeatPool::ConcurrentBackoffS + 1, cfg, acfg));
// 2026-10-31: an account whose 5-hour limit is removed reports the weekly
// window alone; until then the pool took it for an unprobed seat - ranked
// after every other, never held to the weekly cutoff. The cutoff is 95 %.
const Json px = SeatPool::PoolConfig({}, "xhigh");
Json nf = With(SeatPool::NewSeat("n", "oauth", "tn"), {{"state", "ok"}, {"running", 0}, {"pauseUntil", 0}, {"windows", {{"seven_day", {{"utilization", 3}, {"resetsAt", now + 6 * 86400}}}}}});
Json f15 = With(SeatPool::NewSeat("f", "oauth", "tf"), {{"state", "ok"}, {"running", 0}, {"pauseUntil", 0},
{"windows", {{"five_hour", {{"utilization", 15}, {"resetsAt", now + 3600}}}, {"seven_day", {{"utilization", 11}, {"resetsAt", now + 86400}}}}}});
std::vector<Json> pair = {f15, nf};
std::vector<std::string> order;
for (const Json* s : SeatPool::Ranked(pair, now, px, acfg)) order.push_back(s->at("id").get<std::string>());
Check("an account without a 5-hour window is placed by its weekly one: ranked by it, ahead of a seat at 5h 15 %, its running passes projected at the weekly figure",
order == std::vector<std::string>{"n", "f"} && std::abs(SeatPool::OauthProjected(With(nf, {{"running", 100}}), px) - 7.0) < 1e-9, Dyn::Join(order, ","));
Json n93 = With(nf, {{"windows", {{"seven_day", {{"utilization", 93}, {"resetsAt", now + 86400}}}}}});
Json n93r40 = With(n93, {{"running", 40}});
Json n93r60 = With(n93, {{"running", 60}});
Check("...under the weekly cutoff alone, no 5-hour ceiling: at 93 % it takes a pass with 40 running, not with 60 (93 + 61 x 0.04 >= 95)",
SeatPool::Eligible(n93r40, now, px, acfg) && !SeatPool::Eligible(n93r60, now, px, acfg));
Json n95 = With(nf, {{"windows", {{"seven_day", {{"utilization", 95}, {"resetsAt", now + 86400}}}}}});
Check("...and over the cutoff it waits for its weekly reset + 30 s", !SeatPool::Eligible(n95, now, px, acfg) && SeatPool::EarliestResume({n95}, now) == now + 86430);
Json n127 = With(nf, {{"running", 127}});
Json n128 = With(nf, {{"running", 128}});
Json nShared = With(nf, {{"running", 100}, {"foreign", {{"count", 28}, {"cost5h", 0.0}, {"cost7d", 0.0}, {"costUsd", 0.0}}}});
Json f127 = With(f15, {{"running", 127}});
Json f128 = With(f15, {{"running", 128}});
Check("128 passes per OAuth account, every driver counted, whatever its windows; REVIEW_GATES_OAUTH_CONCURRENCY overrides",
SeatPool::Eligible(n127, now, px, acfg) && !SeatPool::Eligible(n128, now, px, acfg) && !SeatPool::Eligible(nShared, now, px, acfg) && SeatPool::Eligible(f127, now, px, acfg)
&& !SeatPool::Eligible(f128, now, px, acfg) && px.at("oauthConcurrency") == 128 && SeatPool::PoolConfig({{"REVIEW_GATES_OAUTH_CONCURRENCY", "64"}}, "xhigh").at("oauthConcurrency") == 64);
Json weekly = {{"status", "ok"}, {"rateLimit", {{"seven_day", {{"utilization", 4}, {"resetsAt", now + 6 * 86400}}}}}};
requeued = SeatPool::Settle(nf, weekly, now, px, acfg, &ledger, log);
Check("...a finished pass's reading keeps it a weekly seat, unpaused; the log table says `no limit` in its 5h column",
!requeued && Seats::BurstWindow(nf.at("windows")) == "seven_day" && nf.at("pauseUntil") == 0 && SeatPool::Table({nf}).contains("| no limit |"), SeatPool::Table({nf}));
Check("the weekly share of a pass follows the run's effort (0.04 at xhigh, 0.125 otherwise); the env overrides it",
Dyn::Equal(px.at("lensCost7dPct"), 0.04) && Dyn::Equal(SeatPool::PoolConfig({}).at("lensCost7dPct"), 0.125) && Dyn::Equal(SeatPool::PoolConfig({}, "max").at("lensCost7dPct"), 0.125)
&& Dyn::Equal(SeatPool::PoolConfig({{"REVIEW_GATES_LENS_COST_7D_PCT", "0.5"}}, "xhigh").at("lensCost7dPct"), 0.5));
const fs::path scratch = td / "scratch";
fs::create_directories(scratch);
const std::map<std::string, std::string> baseEnv = {{"PATH", "/bin"}, {"ANTHROPIC_API_KEY", "leak"}, {"CLAUDE_CODE_OAUTH_TOKEN", "leak2"}, {"HOME", td.string()}};