Files
stack/packages/plugins/limit-check/token-limit
jason.woltjeandClaude Opus 5.5 aa625565f6 bus, cli, webui: token limits per instance, model, provider and key (row 125, #1619)
Adds token limits under launch.limits.tokens (instances, providers, keys,
models.P.M). Core (packages/bus/src/limits.mjs) reads the organization
file and the per-turn usage records row 124 writes, then asks every
switched-on limit-check plug-in; the first refusal wins. A limit no
switched-on check reports reads "not enforced". The limit-check kind is
interface 2 (mayLaunch, mustStop, report); a v1 check is refused at load.
The shipped token-limit check is pure and counts known end records only;
unknown turns add nothing and are shown as their own count.

The launcher refuses limit-reached through the host's mayLaunch op, or
limit-check-failed naming the check. The broker asks mustStop after a
usage end and stops the run at its next receive or state. Settings stamps
since on a new or changed limit and runs reset; launch.mjs and
business.mjs validate the shape. Readers: mosaic limits and mosaic limits
reset, the bus limits view, the Console /api/bus/limits route and the
Settings token table with Reset. Key limits stay "not enforced" until
row 126 names accounts on records.

Owner Dewey, design under lead decision 150.
Reviewer Filbert: r1 changes (comment 28965), r2 approve (28981), r3
approve (28996) on candidate manifest 8b71c405...fe56 after the rebase
onto row 164 (37 of 38 paths with identical +/- lines, TOOLS.md:621
bracket). Decision 123 go on the bus.js hunk from Mos (mos-0814). Sage
gate on b6827d19e: 25 steps, all rc 0 (15 packages, 10 script suites), 2295 node tests and 422 script selftests, 0 failed, 20:03:25Z to 20:08:08Z, network sage-r125_default removed.

Live stays as pinned. Not part of the 8e7ea89a1 window.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 15:21:49 -05:00
..

Token limit check

Row 125 (#1619), REQ-LIMIT-3 and REQ-LIMIT-4, limit-check interface 2. Enable with "plugins": { "limit-check": ["token-limit"] } in the organization file, keeping its other plug-in kinds. Human changes use mosaic plugins set and the current revision.

It enforces launch.limits.tokens: per role instance (instances), provider (providers), provider and model (models.<provider>.<model>) and key (keys). Each limit is {limit, since}.

  • A count is input + output + cacheWrite + cacheRead summed over the known per-turn records whose subject matches and whose at is at or after since. An unknown turn adds nothing; unknownTurns counts the distinct unknown turns apart, so a count is a floor, not proof.
  • With no usage source switched on, every turn's record is unknown (source @none), so every limit counts zero.
  • mayLaunch and mustStop answer the first limit, in the order above, that covers the subject and whose count is at or over it. A limit of 0 refuses every launch of its subject.
  • A key matches a record's account. Until accounts are named (row 126), every record's account is null, so a key limit matches nothing and report shows it as not enforced: no records name a key (lead decision 150, Q1).
  • Counts are summed as BigInt; one past Number.MAX_SAFE_INTEGER is reported as a digit string.

The module is pure: it reads no file and no store. A bad since or record at throws bad-time, a bad amount bad-record, and records that aren't a list bad-records; core turns any throw into a refusal, a stop, or check failed (fail closed).