Files

5.4 KiB

Row 126 (#1620): design notes before the brief

Dewey, 2026-10-18. These notes were written read-only against row 125's round 2 candidate (manifest 71c55638…, base 19fe85c3e) while row 126 is queued and unclaimed. Nothing here is a claim, and there is no code or run behind it. Line numbers are in the 125 r2 tree. Brief: docs/plans/2026-10-14_prd-1.2-build.md § "Daily quota for the credential the stack uses today", blob 6ff35c81d3.

The constraint

The brief says the quota "ships as a second limit check, packages/plugins/limit-check/daily-quota/, with no change to the launcher or bus". Its acceptance says: "Outside daily-quota/, the diff touches only item 1's account naming and the organization-file schema."

Row 125's core doesn't let a second check bring its own kind of limit:

  • Checks get { business, limits: launch.limits, subject, records, now } (limits.mjs:126, :171). Nothing else in the organization file reaches them, so a quota defined outside launch.limits is invisible to the check.
  • A mayLaunch/mustStop hit must name a leaf that limitLeaves returns, with that leaf's limit (limits.mjs:108-110). A report entry must name such a leaf with its limit and since, and a counted entry has exactly path, limit, since, count, kinds, unknownTurns (:148-153). limitLeaves walks only tokens.instances|providers|keys|models (the DEPTH table, :32).
  • The business writer launch-settings.mjs stamps and resets since on the same four depths, and launch.mjs:43-55 takes only those four keys under tokens, each a {limit, since} leaf.
  • token-limit counts every tokens.keys.<account> leaf cumulatively since since (token-limit/index.mjs:33-34). If the daily quota sat on that leaf, token-limit would count the same leaf cumulatively and refuse for good after the first full day. Core's report takes the first counted entry (limits.mjs:177-182), so Settings would show only one of the two counts.
  • A counted report entry has no room for the brief's item 4 line ("counts only the stack's own use"). The CLI formatter (cli limits.mjs:14-26) and the Settings page print only the fields above.

So item 2, as briefed, needs at least one of these:

Option Where the quota lives Changes outside daily-quota/ and the item 1 naming/schema
A (recommended) a new depth-1 kind, tokens.daily.<account> = {limit, since, reset: "HH:MM", timeZone: "<IANA>"} one DEPTH entry in bus limits.mjs and in business launch-settings.mjs, plus the launch.mjs schema (the organization-file schema, allowed). token-limit never sees daily, so the two checks never share a leaf.
B extra fields on tokens.keys.<account> token-limit must skip daily leaves (a plugins change outside daily-quota/), and the two checks still share one path in core's report.
C an accounts section beside item 1's naming core must pass more than launch.limits to checks: a bus change larger than A's.

Item 4's line under any option needs either a fixed CLI and Settings line for the daily kind, or a new optional report field such as note, which is a core validation change. A fixed line keyed on the daily path is the smaller change.

Item 1 itself already touches the bus and launcher, which the acceptance allows. usage.mjs:93-94 inserts account as NULL, so naming the account means passing it from the launch into usage.begin/usage.end. It also needs the launch log line (launcher.mjs, beside the SESSION_CREDENTIALS check at :214).

The rest of the design (once the question above is settled)

  • Item 1. The organization file gets the account name and a credential reference, never the secret. That means which SESSION_CREDENTIALS set (session.mjs:98) the bus uses, by variable name. The launcher logs the name on each launch, and usage records carry it as account, so tokens.keys.<account> limits become enforced, ending lead decision 150 Q1's "not enforced".
  • Day window. The window starts at the latest reset wall-clock time in timeZone at or before now, found with Intl.DateTimeFormat in the check. The quota's count is from the later of that start and since. Tests cover a non-UTC zone (America/Chicago) across the reset, both DST changes, and a reset time that a DST change skips or repeats.
  • Refusal and stop. These are core's existing mayLaunch and mustStop paths, logged as limit-reached with the check's name. Tests cover a refusal at the quota, a stop at the end of the turn that crosses it, and a new launch allowed after the reset.
  • Mutants. There is one per behavior above, each with its killing test, as the brief asks.

Rulings on brief blob 6b473b9304 (sage-0910, 2026-10-18T21:22Z)

The rewritten brief is option A. These are Sage's answers to my two points:

  1. A credential set's name is its variable names joined with "+", e.g. CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_AUTH_TOKEN+ANTHROPIC_BASE_URL. If the organization file names a set the environment doesn't have, the launch refuses with a code (fail closed): logging a name that isn't the credential in use would record something false. The code goes in the refusal table that the brief's test list covers.
  2. "Settings" in item 5 is the webui Settings read and its test, wherever limits render. Row 126 builds on the base row 156 lands on, since both touch launcher.mjs and the usage path.