plans: row 126 brief rewritten on Dewey's tokens.daily design after row 125 landed (#1620)
Row 125's core lets a check see only launch.limits and accept hits on the four DEPTH kinds, so the quota gets its own depth-1 kind, tokens.daily.<account>, in the two DEPTH tables and the organization-file schema. Display is a fixed line keyed on the daily path; no report field. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -485,26 +485,66 @@ Build step 9a, small to medium. Gitea #1620.
|
||||
- Reviewer: filbert (organization file and launcher, no sandbox change).
|
||||
- Requirements: REQ-LIMIT-2, REQ-LIMIT-4.
|
||||
|
||||
Sage rewrote this section on 2026-10-18, after row 125 landed (aa625565f),
|
||||
with Dewey's option A from
|
||||
`agents/dewey/work/queue-126/DESIGN-NOTES.md`. The first version said the
|
||||
quota needed no change outside its own check. Row 125's core doesn't allow
|
||||
that: a check sees only `launch.limits`, a hit must name a leaf that
|
||||
`limitLeaves` returns, and `limitLeaves` walks only the four token kinds in
|
||||
`DEPTH` (`packages/bus/src/limits.mjs:32`). A quota on `tokens.keys.<account>`
|
||||
would also be counted forever by `token-limit`, which counts every key leaf
|
||||
since its `since`.
|
||||
|
||||
**What ships.**
|
||||
|
||||
1. The organization file names the one account the bus uses today
|
||||
(`SESSION_CREDENTIALS`, `packages/seat/src/session.mjs:76`, decision
|
||||
119) by a name and a credential reference, never the secret
|
||||
(invariant 3). Launches log the account name, and step 7's records
|
||||
carry it.
|
||||
2. A daily quota on that account, in tokens (a draft position, PRD
|
||||
REQ-LIMIT-2), with a reset time and time zone. It ships as a second
|
||||
limit check, `packages/plugins/limit-check/daily-quota/`, with no
|
||||
change to the launcher or bus.
|
||||
3. At the quota, new launches on the account are refused and running
|
||||
sessions stop at the end of their current turn. Both are logged.
|
||||
4. Settings and `mosaic limits` show the quota with the line that it
|
||||
counts only the stack's own use (lead decision 142, ruling 9).
|
||||
1. **The account name.** The organization file names the one account the
|
||||
bus uses today (`SESSION_CREDENTIALS`,
|
||||
`packages/seat/src/session.mjs:98`, decision 119) by a name and a
|
||||
credential reference: the name of the `SESSION_CREDENTIALS` set the bus
|
||||
uses, never the secret (invariant 3). The launcher
|
||||
(`packages/cli/src/launcher.mjs`) logs the account name on each launch.
|
||||
Usage records carry it as `account` instead of `NULL`
|
||||
(`packages/bus/src/usage.mjs:93`), so `tokens.keys.<account>` limits,
|
||||
which match nothing today, start to count.
|
||||
2. **A new token kind, `tokens.daily.<account>`.** Its leaf is
|
||||
`{limit, since, reset, timeZone}`: `limit` in tokens (a draft position,
|
||||
PRD REQ-LIMIT-2), `reset` a wall-clock `HH:MM` and `timeZone` an IANA
|
||||
name. It is a depth-1 kind beside `instances`, `providers`, `keys` and
|
||||
`models`. Three places learn it, and nothing else in core changes: the
|
||||
`DEPTH` table in `packages/bus/src/limits.mjs`, the `DEPTH` table in
|
||||
`packages/business/src/launch-settings.mjs` (which stamps and resets
|
||||
`since`), and `checkTokenLimits` in `packages/business/src/launch.mjs`
|
||||
(the organization-file schema). `token-limit` doesn't read `daily`, so
|
||||
the two checks never share a leaf.
|
||||
3. **The check**, `packages/plugins/limit-check/daily-quota/`, a second
|
||||
limit check. The day window starts at the latest `reset` time in
|
||||
`timeZone` at or before `now`, found with `Intl.DateTimeFormat`. The
|
||||
count runs from the later of that start and `since`, over records whose
|
||||
`account` is the leaf's account.
|
||||
4. **Refusal and stop** use core's existing `mayLaunch` and `mustStop`
|
||||
paths. At the quota, new launches on the account are refused and
|
||||
running sessions stop at the end of their current turn. Both are logged
|
||||
as `limit-reached` with the check's name.
|
||||
5. **Display.** Settings and `mosaic limits`
|
||||
(`packages/cli/src/limits.mjs`) show the daily quota with a fixed line,
|
||||
keyed on the `daily` path, saying it counts only the stack's own use
|
||||
(lead decision 142, ruling 9). No new report field: core's report
|
||||
validation stays as row 125 left it.
|
||||
|
||||
**Acceptance.** Tests for the count, the day boundary in a non-UTC time
|
||||
zone, the refusal and the stop. Outside
|
||||
`packages/plugins/limit-check/daily-quota/`, the diff touches only item
|
||||
1's account naming and the organization-file schema. Mutants for each.
|
||||
**Acceptance.**
|
||||
|
||||
- Tests for the count; the day boundary in America/Chicago across the
|
||||
reset; both DST changes; a `reset` time that a DST change skips or
|
||||
repeats; a refusal at the quota; a stop at the end of the turn that
|
||||
crosses it; and a new launch allowed after the reset.
|
||||
- Tests that `token-limit` ignores `tokens.daily`, that a `daily` leaf
|
||||
with a bad `reset` or `timeZone` fails the organization-file read, and
|
||||
that a launch logs the account name and its usage records carry it.
|
||||
- Outside `packages/plugins/limit-check/daily-quota/`, the diff touches
|
||||
only item 1's account naming, the two `DEPTH` tables, the
|
||||
`checkTokenLimits` schema and item 5's fixed line, with their tests and
|
||||
docs. No sandbox change.
|
||||
- One mutant per behavior above, each with the test that kills it.
|
||||
|
||||
## Quota for more than one account or per proxy key (parked on #237)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user