Files
stack/packages/plugins/usage-source/transcript
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
..

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.