`. A hit is
`{path, limit, count, unknownTurns}`.
- `report` gives one counted entry per daily leaf, with `since` being the
leaf's `since` (core's validEntry requires that), not the window start.
## Item 4: refusal and stop
Both use core's existing `mayLaunch`/`mustStop`, logged as `limit-reached`
with `check: "daily-quota"`. Nothing in core changes beyond the DEPTH entry
and the account passing.
## Item 5: the fixed line
Both lines are keyed on `path[1] === "daily"` and print once when any daily
row is present. The text is a draft for review:
> Daily quotas count only this stack's own use of the account, not its use
> anywhere else.
- **CLI** (packages/cli/src/limits.mjs `formatTokens`): the line goes after
the list.
- **webui** (packages/webui/src/public/bus.js `tokenLimits`, :593-603): a
`` under the table. Its test
is packages/webui/tests/limits-browser.test.mjs.
- **This is a public/ change, so it needs Mos's decision 123 go before
landing.** The diff goes in this packet as public.diff.
- serve.mjs doesn't change; it passes `tokens` through (:78-79).
## Files
**New:**
- packages/plugins/limit-check/daily-quota/index.mjs
- packages/plugins/limit-check/daily-quota/README.md
- packages/plugins/tests/daily-quota.test.mjs
**Changed source:**
- packages/business/src/launch.mjs
- packages/business/src/business.mjs
- packages/business/src/launch-settings.mjs
- packages/bus/src/limits.mjs
- packages/bus/src/usage.mjs
- packages/bus/src/broker.mjs
- packages/bus/src/runtime.mjs
- packages/cli/src/launcher.mjs
- packages/cli/src/limits.mjs
- packages/webui/src/public/bus.js
**Tests and docs:** the tests below; packages/plugins/README.md,
packages/business/README.md, packages/cli/README.md.
**The org-file change for Jason** (the packet gives it; I don't edit the
file): add `"account": {"name": "", "credential": ""}` to
`launch`. `` is whichever of `CLAUDE_CODE_OAUTH_TOKEN`,
`ANTHROPIC_API_KEY` or `ANTHROPIC_AUTH_TOKEN+ANTHROPIC_BASE_URL` the bus
unit's EnvironmentFile sets. I won't read that file. If Q1 is accepted, the
file must set only that set.
**No sandbox change.** session.mjs, sandbox.mjs and `ENV_ALLOW` stay
untouched.
## Paths shared with other rows
- **Row 165** (Darkwing, on the slot; paths from
agents/darkwing/work/queue-165/BUILD.md):
- packages/bus/src/broker.mjs
- packages/bus/src/runtime.mjs
- packages/webui/src/public/bus.js
- packages/cli/README.md
- possibly packages/bus/README.md, if 126 touches it (not planned)
- **Row 156** (mine, in review, candidate afea1df3):
- packages/bus/src/broker.mjs
- packages/bus/src/runtime.mjs
- packages/cli/src/launcher.mjs
- packages/cli/tests/launcher.test.mjs
- packages/cli/README.md
- Whichever lands first, 126 rebases onto it and reruns the whole gate on
the new base (candidate-base-drift rule).
## Tests (each run singly)
**New, packages/plugins/tests/daily-quota.test.mjs (REQ-LIMIT-2, REQ-LIMIT-4):**
- the count: every kind; only this account; from `max(start, since)`;
unknown turns kept apart
- the America/Chicago boundary at 05:00: a record at 04:59 CDT is outside
today's window, and one at 05:00 is inside
- the spring DST change with a 00:00 reset: the window is 23 h
- the fall DST change with a 00:00 reset: the window is 25 h
- a reset DST skips (02:30 on 03-08), starting at 08:00Z
- a reset DST repeats (01:30 on 11-01): one window, from 06:30Z
- a refusal at the quota (`count === limit`)
- `mustStop` once the turn's records reach it
- an allow after the next reset
- bad leaves throw a code (fail closed)
**Changed:**
- token-limit.test.mjs: token-limit ignores `tokens.daily`.
- packages/business/tests (the launch schema test file, picked at build
time):
- a bad `reset` refuses the read
- a bad `timeZone` refuses the read (a non-IANA name, an offset, an
unknown zone)
- a bad `account` refuses the read
- a daily key that isn't the account refuses the read
- launch-settings tests: a daily leaf gets its `since` stamped and reset.
- bus:
- limits.test.mjs: `limitLeaves` walks `daily`.
- limit-checks.test.mjs or limits-runtime.test.mjs: daily-quota loaded
through the loader refuses at the quota and allows after the reset.
- limit-stop.test.mjs: a stop at the end of the turn that crosses it, with
`account` on the subject.
- usage-broker.test.mjs: records carry the bound account.
- launcher.test.mjs:
- the launch log names the account
- `account-credential-missing`
- `account-credential-ambiguous`
- a pi launch logs `account: null`
- `mayLaunch` gets the account
- cli limits test: the fixed line.
- webui limits-browser.test.mjs: the fixed line.
- Hash pins and path-reading tests: I grep tests for every manifest path and
for 64-hex pins on the changed files before in-review.
## Mutants (one each, with the test that kills it)
| # | Mutant | Killed by |
|---|---|---|
| D01 | never steps back to yesterday | the boundary test |
| D02 | window computed in UTC | the Chicago boundary test |
| D03 | offset taken once from `now` | the two DST-change tests |
| D04 | skipped reset uses Temporal-style +gap (03:30) | the skip test |
| D05 | repeated reset takes the later 01:30 | the repeat test |
| D06 | ignores `since` | the count test |
| D07 | ignores account | the count test |
| D08 | `>=` becomes `>` | the refusal-at-quota test |
| D09 | token-limit walks `daily` | the ignores-daily test |
| D10 | schema drops the `reset` check | the bad reset test |
| D11 | schema drops the `timeZone` check | the bad zone test |
| D12 | no cross-check of the daily key against the account | the cross-check test |
| D13 | launcher skips the missing-set refusal | the missing-set refusal test |
| D14 | launcher skips the ambiguity refusal | the ambiguity refusal test |
| D15 | launch log omits the account | the log test |
| D16 | usage inserts `NULL` | the usage-broker test |
| D17 | broker `mustStop` omits the account | the limit-stop test |
| D18 | runtime drops the account from `mayLaunch` | the bus refusal test |
| D19 | bus DEPTH lacks `daily` | the limitLeaves and bus refusal tests |
| D20 | settings DEPTH lacks `daily` | the stamp test |
| D21 | CLI line removed | the CLI test |
| D22 | webui line removed | the browser test |