Files
jason.woltjeandClaude Opus 5.5 70504d23a4 bus, cli, webui: token accounting per run, schema 3h usage_records (row 124, #1618)
Rocko's round 2 candidate e09313aba4d155a1c5af7bfb227ec397e96c0d57444782cd0b48593102bcc684
(38 paths, base 23533625d), approved by Dewey in #1618 comment 28923 (queue rev 1757).
Packet: agents/rocko/work/queue-124/r2/.

- Schema 3g to 3h: packages/bus/src/migrations/3g-3h.sql adds an append-only
  usage_records table; nothing earlier changes. usage_records is in timedTables.
- The transcript usage-source module reads token counts from Pi and Claude
  Code session transcripts and follows no symlink.
- `mosaic usage` in the CLI and a read-only usage section in the Console's
  Settings (one GET route; 400 on a query string).

Decision 123 go: Mos, mos-0737. Activation (3g to 3h) is a migrating run
with Jason present, in Mos's combined re-pin; landing changes nothing live.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-18 11:08:17 -05:00

39 lines
2.3 KiB
Markdown

# Transcript usage source
REQ-LIMIT-4, interface version 1. Enable with
`"plugins": { "usage-source": ["transcript"] }` in the organization file,
keeping its other plug-in kinds. Human changes use `mosaic plugins set` and
the current revision. No agent edits the live organization file.
`readTurn({ harness, root })` returns `{status:'known', entries}` or
`{status:'unknown', code}`. Entries map assistant message identities to
`{input, output, cacheWrite, cacheRead}`. This is a snapshot; the bus stores a
baseline and computes the turn's new entries. No known new entry means unknown,
not zero. The bus attributes records to the bound run/instance/provider/model;
the account is null. No token limit or enforcement ships here.
For Pi, root is the run's session directory, or a resumed thread's persistent
session directory. JSONL `message` entries with `message.role === 'assistant'`
have `id` and `message.usage` input/output/cacheWrite/cacheRead counters.
For Claude Code, root is `home/.claude/projects`, or the thread's persistent
`claude-projects` directory: one project-directory level, then session JSONL
files. Assistant entries have message.id and message.usage input_tokens,
output_tokens, cache_creation_input_tokens and cache_read_input_tokens. Claude's
absent optional cache fields mean no reported cache usage; missing required
input/output is unknown. Duplicate identical identities count once; conflicting
counters refuse the snapshot.
The source follows no user symlink: root components and project directories
are opened with directory descriptors and O_NOFOLLOW; final opens add
O_NONBLOCK. Files must be regular and single-link. Both fstat size and bytes
actually read are bounded, and edits during a read refuse the snapshot. Limits:
8 MiB total bytes, 1 MiB per line, 512 directory entries and 20,000 JSON records
per snapshot. These are parser resource bounds, not policy token ceilings.
Invalid UTF-8, malformed/cut JSONL or invalid counters return unknown, never
zero. Reads/logs return no transcript text or parser exception text.
A session can edit its own transcript. Counts are the stack's best reading,
not proof. Resumed history present before a run's next turn is excluded by its
baseline. Rewriting that baseline makes the turn unknown. Missing data or a
source disabled/failed at a restart leaves its pending turn visibly unknown.