# Row 124 / #1618 — token accounting per run Base 9098c33f7, detached /mnt/storage/src/mosaic-stack-rocko-124. Claim rev 1718 after sage-0705 re-pinned the unchanged section at rev 1716. Brief: docs/plans/2026-10-14_prd-1.2-build.md, Token accounting per run. Requirements: REQ-LIMIT-2/3 counting foundation, REQ-LIMIT-4, REQ-PLUG-1 and REQ-WEB-1. Reviewer Dewey (decision 130). Source is not committed; Sage lands. ## Implementation and acceptance mapping - transcript plug-in is interface 1's first usage source. It is reached only through the packages/plugins loader, never a named core import. Runtime injects the accountant into Broker, preserving its exact sandbox client import closure. Enabled/disabled source tests and real-runtime socket integration pin this; a copied fixture plug-in tree tests multiple sources, thrown failures and malformed readings. - The runner brackets actual harness invocations with private usage.begin/end protocol calls. The broker requires its held role and delivered message, binds the business/run/instance/harness/provider/model and rejects extra keys, paths and token counts. Launcher passes selected provider/model in its trusted bind record so a later settings change cannot relabel old runs. No harness tool or grant expands. Real runner ordering and socket tests cover this boundary; a read is scoped to the bound business. - Per-source begin snapshots and end outcomes are durable and append-only. The baseline excludes existing history on resumed threads. Retries consume no new reading; known records sum; pending turns, missing begins, rewritten history, failed/disabled sources, malformed readings and no new usage stay unknown. Multiple sources can contribute known counts while a failed source leaves that turn visibly unknown. Each unknown end logs its fixed safe code; no parser/source exception text or transcript content is logged. - Each kind is separate: input/output/cacheWrite/cacheRead. Per-turn values are safe nonnegative integers; an unrepresentable per-turn sum is unknown. Aggregates use BigInt internally and return exact decimal strings above JavaScript's safe integer range. These are representation/parser bounds, not a token-policy ceiling. Account is null until account tracking ships. - usage returns total and byRun/byInstance/byModel/byProvider/byAccount groups, each with unknownTurns counted distinctly by run+turn. CLI text shows it beside every total; --json retains the view. scripts/mosaic dispatches usage; the shared read adapter and strict read-only HTTP route are tested. - Settings adds only its own Token usage section. It shows all four kinds and unknown turns for every grouping, escapes labels, has no write controls and reports unavailable reads without inventing zeros. The actual browser test runs in the gate; its four mutants pin fields, unknowns, section and escaping. No row 155 Settings editor code is replaced. - The 3g→3h migration and current-schema copy test are described in MIGRATION.md. Every old evidence column/row/sequence is checked, including existing names. Ordered future migration chaining remains tested, now through fixture 3i. The source follows no session symlink. Each root/project component is anchored with directory descriptors, O_DIRECTORY and O_NOFOLLOW; final opens add O_NOFOLLOW/O_NONBLOCK and require a regular single-link file. fstat size, actual stream bytes, line bytes, entry/record counts, stable file identity, UTF-8, complete JSONL, usage/id shape and safe nonnegative counters are checked. Each has a fixture and a named mutant. A session can edit its own transcript: counts are the stack's best reading, not proof. The resource bounds and exact source API are in packages/plugins/usage-source/transcript/README.md and DESIGN.md. ## Gate, corrections and scope sage-0714 granted five package suites (plugins, bus, harness, cli, webui), the Settings browser test, test-land-work.sh, test-config.sh and mutants. Busy check exited 0/CLEAR at 2026-10-18T15:12:55Z. Every step is gated on its exit code with pipefail. TMPDIR=/mnt/storage/scratch/rocko-124/tmp throughout the gate/mutants; DOCKER_HOST=unix:///nonexistent.sock. No Docker, live store/file/unit action, push or activation. No task/queue shell suite; Sage owns those and the full landing gate. Public landing waits for Mos's go (decision 123). Shell-reader search over changed packages and scripts/mosaic identified scripts/test-land-work.sh, test-config.sh, test-task.sh and test-queue.sh. land-work directly imports the Store schema exports; config exercises command configuration. Task reads the unchanged mosaic-task CLI; queue exercises the unchanged queue branch and shell dispatcher syntax. Sage approved the first two here and retains the others for landing, sage-0714. The first bus suite found stale schema expectations, not a runtime defect: chief-of-staff.test builds a pinned 3c engine by replacing the current version literal, and schema.test pins table/trigger counts. Updated 3g→3h references and counts 15→16 tables, 67→70 triggers, preserving all authority assertions. One remaining current-version assertion in chief was fixed on its focused rerun. Original bus failure logs are retained. These are not known flakes. Other historical migration tests change only their current target, copy the additional step when needed, and keep their pinned source DDL unchanged. After the gate passed, added nonblocking-open/name and multiple-source/precision fixtures, then reran the two owning packages; the final counts below include them. No product change was needed after these additional tests. Mutants are exact-once edits, isolated process groups, source restored in finally and group/descendant kill on timeout. No runner timeout or import/syntax fault counts as a kill. Case 44 originally caused JSON.parse in the JSON-output test to fail as intended, but the classifier falsely labelled any SyntaxError as invalid. Corrected classification uses node --check / bash -n for mutated source syntax, retained the first classifier log and resumed at case 44 on the same unchanged source. A second classifier-only correction selects node --check for public .js too, rather than bash -n; its browser test already failed on the intended 0-versus-7 assertion. Final results combine 01–43, resumed 44–46 and resumed 47–64. Final verification, counts, kill table and packet digests follow below. The first focused target for case 63 survived because the runtime fixture's provider is literally other-provider, the mutant's constant. The exact same fault is killed by usage.test.mjs, which asserts the other fixture provider (fixture). Retargeted case 63 to that existing owning-file check; retained the original runtime survivor log. No source or assertion change was needed. ## Final verification Observed completion: 2026-10-18T15:26:07Z. | Suite | Passed | Failed | Skipped | | --- | ---: | ---: | ---: | | plugins | 52 | 0 | 0 | | bus | 362 | 0 | 0 | | harness | 110 | 0 | 0 | | cli | 244 | 0 | 0 | | webui | 146 | 0 | 0 | Total 914 package tests passed; no cancelled/skipped cases. land-work: 86 passed, 0 failed. config: 24 passed, 0 failed. No #258/#261/#262/#263 recurrence. Final gate script passed at 15:19:26Z; final owning-package reruns include the added guard tests. | Mutant | Owning test | Result | | --- | --- | --- | | 01-dir-no-follow | packages/plugins/tests/transcript.test.mjs | KILLED | | 02-file-no-follow | packages/plugins/tests/transcript.test.mjs | KILLED | | 03-regular-single-link | packages/plugins/tests/transcript.test.mjs | KILLED | | 04-stat-size-before-read | packages/plugins/tests/transcript.test.mjs | KILLED | | 05-stream-size-bound | packages/plugins/tests/transcript.test.mjs | KILLED | | 06-snapshot-stability | packages/plugins/tests/transcript.test.mjs | KILLED | | 07-fatal-utf8 | packages/plugins/tests/transcript.test.mjs | KILLED | | 08-cut-line | packages/plugins/tests/transcript.test.mjs | KILLED | | 09-line-byte-bound | packages/plugins/tests/transcript.test.mjs | KILLED | | 10-record-bound | packages/plugins/tests/transcript.test.mjs | KILLED | | 11-directory-entry-bound | packages/plugins/tests/transcript.test.mjs | KILLED | | 12-root-confinement | packages/plugins/tests/transcript.test.mjs | KILLED | | 13-harness-validation | packages/plugins/tests/transcript.test.mjs | KILLED | | 14-json-object | packages/plugins/tests/transcript.test.mjs | KILLED | | 15-assistant-id | packages/plugins/tests/transcript.test.mjs | KILLED | | 16-usage-object | packages/plugins/tests/transcript.test.mjs | KILLED | | 17-nonnegative-safe-integers | packages/plugins/tests/transcript.test.mjs | KILLED | | 18-conflicting-duplicates | packages/plugins/tests/transcript.test.mjs | KILLED | | 19-claude-kinds | packages/plugins/tests/transcript.test.mjs | KILLED | | 20-pi-kinds | packages/plugins/tests/transcript.test.mjs | KILLED | | 21-dedup-identical | packages/plugins/tests/transcript.test.mjs | KILLED | | 22-baseline-required | packages/bus/tests/usage.test.mjs | KILLED | | 23-rewritten-history | packages/bus/tests/usage.test.mjs | KILLED | | 24-no-new-usage-unknown | packages/bus/tests/usage.test.mjs | KILLED | | 25-turn-idempotence | packages/bus/tests/usage.test.mjs | KILLED | | 26-unknowns-beside-totals | packages/bus/tests/usage.test.mjs | KILLED | | 27-log-unknown | packages/bus/tests/usage.test.mjs | KILLED | | 28-safe-parse-code | packages/bus/tests/usage.test.mjs | KILLED | | 29-business-scoped-view | packages/bus/tests/usage.test.mjs | KILLED | | 30-loader-only-source | packages/bus/tests/usage.test.mjs | KILLED | | 31-run-grouping | packages/bus/tests/usage.test.mjs | KILLED | | 32-thread-transcript-root | packages/bus/tests/usage.test.mjs | KILLED | | 33-exact-large-totals | packages/bus/tests/usage.test.mjs | KILLED | | 34-runner-role-check | packages/bus/tests/usage-broker.test.mjs | KILLED | | 35-bound-delivered-turn | packages/bus/tests/usage-broker.test.mjs | KILLED | | 36-no-path-in-request | packages/bus/tests/usage-broker.test.mjs | KILLED | | 37-reader-usage-allowed | packages/bus/tests/usage-broker.test.mjs | KILLED | | 38-view-bound-business | packages/bus/tests/usage-broker.test.mjs | KILLED | | 39-runtime-injection | packages/bus/tests/usage-runtime.test.mjs | KILLED | | 40-await-usage | packages/bus/tests/usage-runtime.test.mjs | KILLED | | 41-runner-begin | packages/harness/tests/runner.test.mjs | KILLED | | 42-runner-end | packages/harness/tests/runner.test.mjs | KILLED | | 43-cli-unknown | packages/cli/tests/usage.test.mjs | KILLED | | 44-cli-json | packages/cli/tests/usage.test.mjs | KILLED | | 45-dispatch | packages/cli/tests/usage.test.mjs | KILLED | | 46-read-adapter | packages/cli/tests/usage.test.mjs | KILLED | | 47-settings-unknown | packages/webui/tests/usage-browser.test.mjs | KILLED | | 48-settings-four-kinds | packages/webui/tests/usage-browser.test.mjs | KILLED | | 49-settings-section | packages/webui/tests/usage-browser.test.mjs | KILLED | | 50-settings-safe-labels | packages/webui/tests/usage-browser.test.mjs | KILLED | | 51-http-arguments | packages/webui/tests/usage.test.mjs | KILLED | | 52-http-shape | packages/webui/tests/usage.test.mjs | KILLED | | 53-migration-step | packages/bus/tests/usage-migration.test.mjs | KILLED | | 54-migration-chain | packages/bus/tests/comment-migration.test.mjs | KILLED | | 55-nonblocking-open | packages/plugins/tests/transcript.test.mjs | KILLED | | 56-entry-name-validation | packages/plugins/tests/transcript.test.mjs | KILLED | | 57-source-output-validation | packages/bus/tests/usage.test.mjs | KILLED | | 58-turn-sum-precision | packages/bus/tests/usage.test.mjs | KILLED | | 59-source-failure-is-unknown | packages/bus/tests/usage.test.mjs | KILLED | | 60-all-enabled-sources | packages/bus/tests/usage.test.mjs | KILLED | | 61-instance-group | packages/bus/tests/usage.test.mjs | KILLED | | 62-model-group | packages/bus/tests/usage.test.mjs | KILLED | | 63-provider-group | packages/bus/tests/usage.test.mjs | KILLED | | 64-account-unassigned | packages/bus/tests/usage.test.mjs | KILLED | 64/64 final kills, no runner timeout or invalid syntax/module failure. All 37 candidate file hashes and staged blobs restored. Node/chromium/Git/ bwrap/Python cwd-and-argv sweep under the worktree and scratch found none; every runner exited. No Docker network was created. No live files/units touched. Candidate manifest SHA-256: b7139ea3909c49449436daee2eb45f542bca0ffce2515870e1f49ba27e918016.