feat(seats): a pass's share of the windows by the run's effort, the weekly cutoff at 99 %
The 5-hour share of a running pass was a flat 0.25 points; it follows the run's effort now, as the weekly share already did: 0.5 at max and any other effort, 0.125 at xhigh - the pooled means of 5438 Opus 5.5 passes on 141 seat-runs (2026-10-12..15), rounded up. The weekly cutoff moves from 95 % to 99 %: the weekly window is the budget the lenses run out of, and with the running passes projected against the cutoff the last percent is spent a pass at a time, not in a burst. REVIEW_GATES_LENS_COST_PCT and REVIEW_GATES_LENS_COST_7D_PCT still override every effort.
This commit is contained in:
parent
51bdd6298a
commit
ea4d362a10
8 changed files with 44 additions and 31 deletions
|
|
@ -108,7 +108,8 @@ Conventions:
|
||||||
No file the drivers write holds these in practice, and a file that fails to parse is treated as a damaged one.
|
No file the drivers write holds these in practice, and a file that fails to parse is treated as a damaged one.
|
||||||
- **HTTP.** `ClientHTTP1::Fetch` ignores `*_proxy` variables. The OpenRouter requests send `User-Agent: crafter-review`; `app_ready` sends `review-gates`. Reason phrases are the standard ones, not the server's.
|
- **HTTP.** `ClientHTTP1::Fetch` ignores `*_proxy` variables. The OpenRouter requests send `User-Agent: crafter-review`; `app_ready` sends `review-gates`. Reason phrases are the standard ones, not the server's.
|
||||||
- **Seat placement** (SeatPool, Seats, Drivers):
|
- **Seat placement** (SeatPool, Seats, Drivers):
|
||||||
- An account whose 5-hour limit Anthropic has removed reports the weekly window alone. Its burst window (`Seats::BurstWindow`) is the weekly one: it is ranked and admitted by the weekly window with the passes in flight projected on it (0.04 points per pass at xhigh, 0.125 otherwise), under the 95 % cutoff.
|
- An account whose 5-hour limit Anthropic has removed reports the weekly window alone. Its burst window (`Seats::BurstWindow`) is the weekly one: it is ranked and admitted by the weekly window with the passes in flight projected on it (0.04 points per pass at xhigh, 0.125 otherwise), under the 99 % cutoff.
|
||||||
|
- A pass's projected share of the windows follows the run's effort: 0.5 / 0.125 points of the 5-hour window and 0.125 / 0.04 of the weekly one at max / xhigh (`SeatPool::LensCostPct`, `LensCost7dPct`), the pooled means of 5438 passes on 141 seat-runs (2026-10-12..15) rounded up. The weekly cutoff is 99 %: the running passes are projected against it, so the last percent is spent a pass at a time.
|
||||||
- Every OAuth account and the local login takes at most 128 passes at once, every driver's counted.
|
- Every OAuth account and the local login takes at most 128 passes at once, every driver's counted.
|
||||||
- There is no machine-wide width (2026-10-31, Jorijn: "there is no need to do a global cap anymore, the cap should be 128 per available account"). `--concurrency` caps only when given, and the dump's `args.concurrency` is then null. The board's driver settings read `128 per account`, which every driver's `seats` shows as that driver's width (Scheduler, Runs).
|
- There is no machine-wide width (2026-10-31, Jorijn: "there is no need to do a global cap anymore, the cap should be 128 per available account"). `--concurrency` caps only when given, and the dump's `args.concurrency` is then null. The board's driver settings read `128 per account`, which every driver's `seats` shows as that driver's width (Scheduler, Runs).
|
||||||
- A 'concurrents' rejection pauses the seat for 20 s or its retry-after, not until a window's reset.
|
- A 'concurrents' rejection pauses the seat for 20 s or its retry-after, not until a window's reset.
|
||||||
|
|
@ -179,7 +180,7 @@ What the binary reads at run time, and how. A variable the driver only sets or s
|
||||||
| `SEATS_ENV_FILE` | `:Run` Gate0 (run), `seats` | run: `<repo>/.env` if it exists; `seats`: `./.env` if it exists | `--env-file` wins (in run even `--env-file ""`, meaning no file); empty counts as unset. Only seat lines are taken (`[export ]NAME=value`, one pair of matching quotes stripped), overriding the process environment; no knob below is ever read from the file. A file that cannot be read, or is not UTF-8: run stops at preflight (exit 3), `seats` exits 1 with the read error. | The dotenv file the seat secrets come from |
|
| `SEATS_ENV_FILE` | `:Run` Gate0 (run), `seats` | run: `<repo>/.env` if it exists; `seats`: `./.env` if it exists | `--env-file` wins (in run even `--env-file ""`, meaning no file); empty counts as unset. Only seat lines are taken (`[export ]NAME=value`, one pair of matching quotes stripped), overriding the process environment; no knob below is ever read from the file. A file that cannot be read, or is not UTF-8: run stops at preflight (exit 3), `seats` exits 1 with the read error. | The dotenv file the seat secrets come from |
|
||||||
| `REVIEW_GATES_SEATS` | `:Driver` RunCommand → LoadSeats | `auto` | Only without `--seats`. Stripped, case-sensitive; unset or empty is `auto` (every api and oauth seat, else `local`); `local`, `api`, `oauth`, `openrouter` select that kind; anything else is a comma list of ids (`apiN`, `N`, `orN`, `local`; blank items skipped). An id not configured, or OpenRouter mixed with others, is a preflight error (exit 3). | The seats a run places lens processes on |
|
| `REVIEW_GATES_SEATS` | `:Driver` RunCommand → LoadSeats | `auto` | Only without `--seats`. Stripped, case-sensitive; unset or empty is `auto` (every api and oauth seat, else `local`); `local`, `api`, `oauth`, `openrouter` select that kind; anything else is a comma list of ids (`apiN`, `N`, `orN`, `local`; blank items skipped). An id not configured, or OpenRouter mixed with others, is a preflight error (exit 3). | The seats a run places lens processes on |
|
||||||
| `REVIEW_GATES_SEAT_MAX_UTIL` | `:Seats` ConfigFromEnv (`seats`; run through `:SeatPool` PoolConfig) | `85` | A finite number >= 0, in decimal or exponent notation; surrounding whitespace, `_` between digits and Unicode digits are taken. Empty, garbage, negative, `inf`, `nan` keep the default; a whole value is stored as an int. Process environment only. | Ceiling (%) of an OAuth seat's projected 5-hour utilisation |
|
| `REVIEW_GATES_SEAT_MAX_UTIL` | `:Seats` ConfigFromEnv (`seats`; run through `:SeatPool` PoolConfig) | `85` | A finite number >= 0, in decimal or exponent notation; surrounding whitespace, `_` between digits and Unicode digits are taken. Empty, garbage, negative, `inf`, `nan` keep the default; a whole value is stored as an int. Process environment only. | Ceiling (%) of an OAuth seat's projected 5-hour utilisation |
|
||||||
| `REVIEW_GATES_LENS_COST_PCT` | `:Seats` ConfigFromEnv; `:SeatPool` PoolConfig | run: `0.25`; `seats`: `10` | As MAX_UTIL. PoolConfig puts in 0.25 only when it is unset or blank, so a set but invalid value gives 10, in run too. | Percentage points of the 5-hour window a running process is projected to add (its cost on the board too) |
|
| `REVIEW_GATES_LENS_COST_PCT` | `:Seats` ConfigFromEnv; `:SeatPool` PoolConfig | run: `0.5` at max and any other effort, `0.125` at xhigh; `seats`: `10` | As MAX_UTIL. PoolConfig puts in the effort's figure only when it is unset or blank, so a set but invalid value gives 10, in run too. | Percentage points of the 5-hour window a running process is projected to add (its cost on the board too) |
|
||||||
| `REVIEW_GATES_SEAT_POLICY` | `:Seats` ConfigFromEnv | `spread` | Exactly `pack` (case-sensitive, untrimmed) is pack; anything else spread. | pack: the first eligible OAuth seat by id; spread: the lowest projected one |
|
| `REVIEW_GATES_SEAT_POLICY` | `:Seats` ConfigFromEnv | `spread` | Exactly `pack` (case-sensitive, untrimmed) is pack; anything else spread. | pack: the first eligible OAuth seat by id; spread: the lowest projected one |
|
||||||
| `REVIEW_GATES_SEAT_WAIT_MIN` | `:Seats` ConfigFromEnv | `15` | As MAX_UTIL | Shown by `seats --json` as `waitMaxMin`; nothing else reads it |
|
| `REVIEW_GATES_SEAT_WAIT_MIN` | `:Seats` ConfigFromEnv | `15` | As MAX_UTIL | Shown by `seats --json` as `waitMaxMin`; nothing else reads it |
|
||||||
| `REVIEW_GATES_SEAT_HANDOVER_PCT` | `:Seats` ConfigFromEnv | `90` | As MAX_UTIL | Shown in the `seats` report and `--json` only |
|
| `REVIEW_GATES_SEAT_HANDOVER_PCT` | `:Seats` ConfigFromEnv | `90` | As MAX_UTIL | Shown in the `seats` report and `--json` only |
|
||||||
|
|
|
||||||
|
|
@ -518,10 +518,10 @@ namespace Crafter::Review::SeatPool {
|
||||||
return n && !Dyn::Strip(text).empty() && std::isfinite(*n) && *n >= 0 ? *n : fallback;
|
return n && !Dyn::Strip(text).empty() && std::isfinite(*n) && *n >= 0 ? *n : fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A pass's share of the weekly window, as measured: 0.04 at xhigh,
|
// A pass's share of the weekly window: the config's, else the max
|
||||||
// 0.125 at max and for any other effort.
|
// figure.
|
||||||
double Cost7d(const Json& config) {
|
double Cost7d(const Json& config) {
|
||||||
return Dyn::Has(config, "lensCost7dPct") ? AsDouble(config.at("lensCost7dPct")) : 0.125;
|
return Dyn::Has(config, "lensCost7dPct") ? AsDouble(config.at("lensCost7dPct")) : LensCost7dPct({});
|
||||||
}
|
}
|
||||||
|
|
||||||
// The weekly window with the passes in flight and this one projected
|
// The weekly window with the passes in flight and this one projected
|
||||||
|
|
@ -540,8 +540,8 @@ namespace Crafter::Review::SeatPool {
|
||||||
|
|
||||||
Json PoolConfig(const std::map<std::string, std::string>& env, std::string_view effort) {
|
Json PoolConfig(const std::map<std::string, std::string>& env, std::string_view effort) {
|
||||||
Json config = Seats::ConfigFromEnv(env);
|
Json config = Seats::ConfigFromEnv(env);
|
||||||
if (Dyn::Strip(EnvOf(env, "REVIEW_GATES_LENS_COST_PCT")).empty()) config["lensCostPct"] = 0.25;
|
if (Dyn::Strip(EnvOf(env, "REVIEW_GATES_LENS_COST_PCT")).empty()) config["lensCostPct"] = LensCostPct(effort);
|
||||||
config["lensCost7dPct"] = EnvNumber(env, "REVIEW_GATES_LENS_COST_7D_PCT", effort == "xhigh" ? 0.04 : 0.125);
|
config["lensCost7dPct"] = EnvNumber(env, "REVIEW_GATES_LENS_COST_7D_PCT", LensCost7dPct(effort));
|
||||||
config["oauthConcurrency"] = static_cast<std::int64_t>(EnvNumber(env, "REVIEW_GATES_OAUTH_CONCURRENCY", static_cast<double>(OauthConcurrency)));
|
config["oauthConcurrency"] = static_cast<std::int64_t>(EnvNumber(env, "REVIEW_GATES_OAUTH_CONCURRENCY", static_cast<double>(OauthConcurrency)));
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,16 @@ export namespace Crafter::Review::SeatPool {
|
||||||
// rejections, none of the 119 with 139 or fewer.
|
// rejections, none of the 119 with 139 or fewer.
|
||||||
// REVIEW_GATES_OAUTH_CONCURRENCY overrides.
|
// REVIEW_GATES_OAUTH_CONCURRENCY overrides.
|
||||||
constexpr std::int64_t OauthConcurrency = 128;
|
constexpr std::int64_t OauthConcurrency = 128;
|
||||||
|
// What one running pass is projected to cost of an OAuth seat's windows,
|
||||||
|
// in percentage points, by the run's reasoning effort (every lens of a run
|
||||||
|
// shares --effort): the pooled means of 5438 Opus 5.5 passes on 141
|
||||||
|
// seat-runs (2026-10-12..15), rounded up - max 0.44 / 0.118, xhigh
|
||||||
|
// 0.12 / 0.033. The 85 % ceiling and the cutoff's last percent absorb the
|
||||||
|
// spread. An effort not in the table projects at the max figures;
|
||||||
|
// REVIEW_GATES_LENS_COST_PCT and REVIEW_GATES_LENS_COST_7D_PCT override
|
||||||
|
// every effort.
|
||||||
|
constexpr double LensCostPct(std::string_view effort) { return effort == "xhigh" ? 0.125 : 0.5; }
|
||||||
|
constexpr double LensCost7dPct(std::string_view effort) { return effort == "xhigh" ? 0.04 : 0.125; }
|
||||||
// The kinds whose processes cost money the ledger counts.
|
// The kinds whose processes cost money the ledger counts.
|
||||||
constexpr std::array<std::string_view, 2> Paid = {"api", "openrouter"};
|
constexpr std::array<std::string_view, 2> Paid = {"api", "openrouter"};
|
||||||
// The kinds whose out/invalid verdict crosses drivers on the board.
|
// The kinds whose out/invalid verdict crosses drivers on the board.
|
||||||
|
|
@ -101,12 +111,9 @@ export namespace Crafter::Review::SeatPool {
|
||||||
void ApplyProbe(Json& seat, const Json& result);
|
void ApplyProbe(Json& seat, const Json& result);
|
||||||
std::string Describe(const Json& seat);
|
std::string Describe(const Json& seat);
|
||||||
|
|
||||||
// The OAuth placement knobs, with the pool's own per-process projections:
|
// The OAuth placement knobs, with the pool's own per-pass projections at
|
||||||
// 0.25 of the 5-hour window (the 2026-10-15 load test moved a 20x seat's
|
// the run's effort (LensCostPct, LensCost7dPct; the env overrides them)
|
||||||
// window 0.08 points a pass) and, for an account without a 5-hour limit,
|
// and the per-account cap.
|
||||||
// the measured share of the weekly window at the run's effort (0.04 at
|
|
||||||
// xhigh, 0.125 otherwise; REVIEW_GATES_LENS_COST_7D_PCT); and the
|
|
||||||
// per-account cap.
|
|
||||||
Json PoolConfig(const std::map<std::string, std::string>& env, std::string_view effort = {});
|
Json PoolConfig(const std::map<std::string, std::string>& env, std::string_view effort = {});
|
||||||
double OauthProjected(const Json& seat, const Json& config);
|
double OauthProjected(const Json& seat, const Json& config);
|
||||||
// A window whose reset has passed counts as empty until the next reading.
|
// A window whose reset has passed counts as empty until the next reading.
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,12 @@ export namespace Crafter::Review::Seats {
|
||||||
// Fixed rules, not knobs: utilisation is rounded to RankQuantum before
|
// Fixed rules, not knobs: utilisation is rounded to RankQuantum before
|
||||||
// ranking, and a seat whose 7-day window is at or above LongWindowCutoff is
|
// ranking, and a seat whose 7-day window is at or above LongWindowCutoff is
|
||||||
// out regardless — its reset is days away. The Fable window is exempt here.
|
// out regardless — its reset is days away. The Fable window is exempt here.
|
||||||
|
// 99 since 2026-10-15 (95 before): the weekly window is the budget the
|
||||||
|
// lenses run out of, and the pool projects its running passes against the
|
||||||
|
// cutoff (SeatPool::LensCost7dPct), so the last percent is spent a pass at
|
||||||
|
// a time, not in a burst.
|
||||||
constexpr std::int32_t RankQuantum = 5;
|
constexpr std::int32_t RankQuantum = 5;
|
||||||
constexpr std::int32_t LongWindowCutoff = 95;
|
constexpr std::int32_t LongWindowCutoff = 99;
|
||||||
|
|
||||||
// JavaScript's Math.round: halves go up, never to even.
|
// JavaScript's Math.round: halves go up, never to even.
|
||||||
double JsRound(double x);
|
double JsRound(double x);
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ drivers running and what they hold. The seat pool still places
|
||||||
every process by its seat's projected 5-hour headroom
|
every process by its seat's projected 5-hour headroom
|
||||||
(`REVIEW_GATES_LENS_COST_PCT`, `REVIEW_GATES_SEAT_MAX_UTIL`) — or, on an
|
(`REVIEW_GATES_LENS_COST_PCT`, `REVIEW_GATES_SEAT_MAX_UTIL`) — or, on an
|
||||||
account whose 5-hour limit Anthropic has removed, by its weekly window
|
account whose 5-hour limit Anthropic has removed, by its weekly window
|
||||||
under the 95 % cutoff — at most 128 passes per account, every driver's
|
under the 99 % cutoff — at most 128 passes per account, every driver's
|
||||||
counted (`REVIEW_GATES_OAUTH_CONCURRENCY`), and a pass
|
counted (`REVIEW_GATES_OAUTH_CONCURRENCY`), and a pass
|
||||||
launches only when its environment's instrument is free and it fits in
|
launches only when its environment's instrument is free and it fits in
|
||||||
free memory (How the passes share the stacks): the driver logs per gate
|
free memory (How the passes share the stacks): the driver logs per gate
|
||||||
|
|
|
||||||
|
|
@ -169,14 +169,14 @@ namespace {
|
||||||
const Json f1 = At(sa, "1").at("foreign");
|
const Json f1 = At(sa, "1").at("foreign");
|
||||||
const Json fa = At(sa, "api1").at("foreign");
|
const Json fa = At(sa, "api1").at("foreign");
|
||||||
Check("three passes of B on seat 1 and two on api1 fold into A as foreign, at B's own per-pass figures",
|
Check("three passes of B on seat 1 and two on api1 fold into A as foreign, at B's own per-pass figures",
|
||||||
f1.at("count") == 3 && Dyn::Equal(f1.at("cost5h"), 0.75) && Dyn::Equal(f1.at("costUsd"), 0) && fa.at("count") == 2 && Dyn::Equal(fa.at("costUsd"), 2.0)
|
f1.at("count") == 3 && Dyn::Equal(f1.at("cost5h"), 1.5) && Dyn::Equal(f1.at("costUsd"), 0) && fa.at("count") == 2 && Dyn::Equal(fa.at("costUsd"), 2.0)
|
||||||
&& Dyn::Equal(f1.at("drivers"), {{B.Me(), 3}}),
|
&& Dyn::Equal(f1.at("drivers"), {{B.Me(), 3}}),
|
||||||
std::format("{} {}", DumpSpaced(f1), DumpSpaced(fa)));
|
std::format("{} {}", DumpSpaced(f1), DumpSpaced(fa)));
|
||||||
Json s84 = mk("x", "oauth", "tx", 84, 50);
|
Json s84 = mk("x", "oauth", "tx", 84, 50);
|
||||||
s84["foreign"] = {{"count", 3}, {"cost5h", 1.5}, {"costUsd", 0}};
|
s84["foreign"] = {{"count", 3}, {"cost5h", 1.5}, {"costUsd", 0}};
|
||||||
const bool over = !SeatPool::Eligible(s84, now, cfg, acfg);
|
const bool over = !SeatPool::Eligible(s84, now, cfg, acfg);
|
||||||
Json s84Bare = With(s84, {{"foreign", {{"count", 0}, {"cost5h", 0.0}, {"costUsd", 0.0}}}});
|
Json s84Bare = With(s84, {{"foreign", {{"count", 0}, {"cost5h", 0.0}, {"costUsd", 0.0}}}});
|
||||||
Check("the 5-hour projection counts the foreign passes: 84 + 1.5 + 0.25 is over 85, without them under", over && SeatPool::Eligible(s84Bare, now, cfg, acfg));
|
Check("the 5-hour projection counts the foreign passes: 84 + 1.5 + 0.5 is over 85, without them under", over && SeatPool::Eligible(s84Bare, now, cfg, acfg));
|
||||||
Json a8 = mk("api9", "api", "k9");
|
Json a8 = mk("api9", "api", "k9");
|
||||||
a8["foreign"] = {{"count", 6}, {"cost5h", 0}, {"costUsd", 6.0}};
|
a8["foreign"] = {{"count", 6}, {"cost5h", 0}, {"costUsd", 6.0}};
|
||||||
a8["running"] = 2;
|
a8["running"] = 2;
|
||||||
|
|
@ -338,7 +338,7 @@ namespace {
|
||||||
// The board's reading of the account (40, B's) folded in before the
|
// The board's reading of the account (40, B's) folded in before the
|
||||||
// projection.
|
// projection.
|
||||||
const Json base = sm["windows"]["five_hour"]["utilization"];
|
const Json base = sm["windows"]["five_hour"]["utilization"];
|
||||||
Check("a driver's passes fold at its own projection (2 % each) into another driver's (0.25 %)",
|
Check("a driver's passes fold at its own projection (2 % each) into another driver's (0.5 %)",
|
||||||
Dyn::Equal(sm["foreign"], {{"count", 2}, {"cost5h", 4.0}, {"cost7d", 0.25}, {"costUsd", 0}, {"drivers", {{D.Me(), 2}}}}) && base == 40
|
Dyn::Equal(sm["foreign"], {{"count", 2}, {"cost5h", 4.0}, {"cost7d", 0.25}, {"costUsd", 0}, {"drivers", {{D.Me(), 2}}}}) && base == 40
|
||||||
&& SeatPool::OauthProjected(sm, cfg) == base.get<double>() + 4.0,
|
&& SeatPool::OauthProjected(sm, cfg) == base.get<double>() + 4.0,
|
||||||
std::format("{} {}", DumpSpaced(sm["foreign"]), base.dump()));
|
std::format("{} {}", DumpSpaced(sm["foreign"]), base.dump()));
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,9 @@ int main() {
|
||||||
Ids(seats) == "api1,1,2" && Ids(SeatPool::LoadSeats({}, std::nullopt, "")) == "local", Ids(seats));
|
Ids(seats) == "api1,1,2" && Ids(SeatPool::LoadSeats({}, std::nullopt, "")) == "local", Ids(seats));
|
||||||
const std::string summary = DumpSpaced(SeatPool::Summary(seats));
|
const std::string summary = DumpSpaced(SeatPool::Summary(seats));
|
||||||
Check("no secret in the summary or the table", !(summary + SeatPool::Table(seats)).contains("tok-one") && !summary.contains("sk-ant"));
|
Check("no secret in the summary or the table", !(summary + SeatPool::Table(seats)).contains("tok-one") && !summary.contains("sk-ant"));
|
||||||
Check("the pool's default projection is 0.25% of the 5-hour window per process (measured 0.08, 2026-10-15); the env overrides",
|
Check("the 5-hour share of a pass follows the run's effort (0.125 at xhigh, 0.5 at max and any other); the env overrides every effort",
|
||||||
Dyn::Equal(SeatPool::PoolConfig({}).at("lensCostPct"), 0.25) && Dyn::Equal(SeatPool::PoolConfig({{"REVIEW_GATES_LENS_COST_PCT", "5"}}).at("lensCostPct"), 5));
|
Dyn::Equal(SeatPool::PoolConfig({}).at("lensCostPct"), 0.5) && Dyn::Equal(SeatPool::PoolConfig({}, "max").at("lensCostPct"), 0.5)
|
||||||
|
&& Dyn::Equal(SeatPool::PoolConfig({}, "xhigh").at("lensCostPct"), 0.125) && Dyn::Equal(SeatPool::PoolConfig({{"REVIEW_GATES_LENS_COST_PCT", "5"}}, "xhigh").at("lensCostPct"), 5));
|
||||||
|
|
||||||
const double now = std::floor(Platform::Now());
|
const double now = std::floor(Platform::Now());
|
||||||
Json& api1 = seats[0];
|
Json& api1 = seats[0];
|
||||||
|
|
@ -109,7 +110,7 @@ int main() {
|
||||||
Check("...and the seat is back after the back-off", !requeued && sc.at("state") == "ok" && SeatPool::Eligible(sc, now + SeatPool::ConcurrentBackoffS + 1, cfg, acfg));
|
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
|
// 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
|
// 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 %.
|
// after every other, never held to the weekly cutoff. The cutoff is 99 %.
|
||||||
const Json px = SeatPool::PoolConfig({}, "xhigh");
|
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 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},
|
Json f15 = With(SeatPool::NewSeat("f", "oauth", "tf"), {{"state", "ok"}, {"running", 0}, {"pauseUntil", 0},
|
||||||
|
|
@ -119,13 +120,13 @@ int main() {
|
||||||
for (const Json* s : SeatPool::Ranked(pair, now, px, acfg)) order.push_back(s->at("id").get<std::string>());
|
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",
|
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, ","));
|
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 n97 = With(nf, {{"windows", {{"seven_day", {{"utilization", 97}, {"resetsAt", now + 86400}}}}}});
|
||||||
Json n93r40 = With(n93, {{"running", 40}});
|
Json n97r40 = With(n97, {{"running", 40}});
|
||||||
Json n93r60 = With(n93, {{"running", 60}});
|
Json n97r60 = With(n97, {{"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)",
|
Check("...under the weekly cutoff alone, no 5-hour ceiling: at 97 % it takes a pass with 40 running, not with 60 (97 + 61 x 0.04 >= 99)",
|
||||||
SeatPool::Eligible(n93r40, now, px, acfg) && !SeatPool::Eligible(n93r60, now, px, acfg));
|
SeatPool::Eligible(n97r40, now, px, acfg) && !SeatPool::Eligible(n97r60, now, px, acfg));
|
||||||
Json n95 = With(nf, {{"windows", {{"seven_day", {{"utilization", 95}, {"resetsAt", now + 86400}}}}}});
|
Json n99 = With(nf, {{"windows", {{"seven_day", {{"utilization", 99}, {"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);
|
Check("...and over the cutoff it waits for its weekly reset + 30 s", !SeatPool::Eligible(n99, now, px, acfg) && SeatPool::EarliestResume({n99}, now) == now + 86430);
|
||||||
Json n127 = With(nf, {{"running", 127}});
|
Json n127 = With(nf, {{"running", 127}});
|
||||||
Json n128 = With(nf, {{"running", 128}});
|
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 nShared = With(nf, {{"running", 100}, {"foreign", {{"count", 28}, {"cost5h", 0.0}, {"cost7d", 0.0}, {"costUsd", 0.0}}}});
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ int main() {
|
||||||
Eq(lines.at(3), "| 2 | 61% | 10:10 (in 10 min) | 18% | Thu 10 Sept, 10:00 (in 3d 0h) | — |");
|
Eq(lines.at(3), "| 2 | 61% | 10:10 (in 10 min) | 18% | Thu 10 Sept, 10:00 (in 3d 0h) | — |");
|
||||||
Eq(lines.at(4), "| 3 | 62% | 10:15 (in 15 min) | 16% | Thu 10 Sept, 10:00 (in 3d 0h) | 22% |");
|
Eq(lines.at(4), "| 3 | 62% | 10:15 (in 15 min) | 16% | Thu 10 Sept, 10:00 (in 3d 0h) | 22% |");
|
||||||
Eq(lines.at(5), "");
|
Eq(lines.at(5), "");
|
||||||
Eq(lines.at(6), "policy spread · ceiling 85% · handover at 90% · a lens is placed at +10% · 7d cutoff 95%");
|
Eq(lines.at(6), "policy spread · ceiling 85% · handover at 90% · a lens is placed at +10% · 7d cutoff 99%");
|
||||||
Eq(lines.at(7), "eligible now: seat 2 (25% headroom), seat 3 (25% headroom) → next lens: seat 2");
|
Eq(lines.at(7), "eligible now: seat 2 (25% headroom), seat 3 (25% headroom) → next lens: seat 2");
|
||||||
Eq(lines.at(8), "fable lenses: seat 3 (63% fable headroom)");
|
Eq(lines.at(8), "fable lenses: seat 3 (63% fable headroom)");
|
||||||
Eq(lines.at(9), "limited: seat 1 until 10:05 (in 5 min)");
|
Eq(lines.at(9), "limited: seat 1 until 10:05 (in 5 min)");
|
||||||
|
|
@ -223,8 +223,8 @@ int main() {
|
||||||
auto pair = [](const std::pair<Json, std::string>& p) { return Json::array({p.first, p.second}); };
|
auto pair = [](const std::pair<Json, std::string>& p) { return Json::array({p.first, p.second}); };
|
||||||
EqJson(pair(SeatUtil({{"five_hour", {{"utilization", 61}, {"resetsAt", 1}}}, {"seven_day", {{"utilization", 18}, {"resetsAt", 2}}}})), Json::array({60, "five_hour"}));
|
EqJson(pair(SeatUtil({{"five_hour", {{"utilization", 61}, {"resetsAt", 1}}}, {"seven_day", {{"utilization", 18}, {"resetsAt", 2}}}})), Json::array({60, "five_hour"}));
|
||||||
EqJson(pair(SeatUtil({{"five_hour", {{"utilization", 12}, {"resetsAt", 1}}}, {"seven_day_fable", {{"utilization", 97}, {"resetsAt", 2}}}})), Json::array({95, "seven_day_fable"}));
|
EqJson(pair(SeatUtil({{"five_hour", {{"utilization", 12}, {"resetsAt", 1}}}, {"seven_day_fable", {{"utilization", 97}, {"resetsAt", 2}}}})), Json::array({95, "seven_day_fable"}));
|
||||||
Eq(IsEligible(seat(1, 10, 96), With(cfg, {{"maxUtil", 100}})), false);
|
Eq(IsEligible(seat(1, 10, 99), With(cfg, {{"maxUtil", 100}})), false);
|
||||||
Eq(IsEligible(seat(1, 10, 94), With(cfg, {{"maxUtil", 100}})), true);
|
Eq(IsEligible(seat(1, 10, 98), With(cfg, {{"maxUtil", 100}})), true);
|
||||||
Eq(IsEligible(seat(1, 10, 94), cfg), false);
|
Eq(IsEligible(seat(1, 10, 94), cfg), false);
|
||||||
// Redaction: the seat's own token, token shapes and addresses; auth
|
// Redaction: the seat's own token, token shapes and addresses; auth
|
||||||
// failures by status or by text.
|
// failures by status or by text.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue