# Proof audit, pass 1

**Findings first.** [#33721](https://git.cafe/pingdotgg/t3code/pull/33721) has no linked screenshots or recordings. Its numeric runtime table cannot prove the visible branches below. This is a proof gap, not a newly found implementation defect. No app or browser was launched during this pass.

Reviewed the complete two-file diff in the supplied checkout, local merged head [0957a043af](https://github.com/pingdotgg/t3code/commit/0957a043af9ef9cd6507964a9533a2b3c7a66e0c), against current-main [934c7f8d8e](https://github.com/pingdotgg/t3code/commit/934c7f8d8e7a012aa55be9c0b17498979040fe02). The local merge is not published; its commit link may not resolve. The published PR head is [83fcfc691f](https://github.com/pingdotgg/t3code/commit/83fcfc691f5c87e3695f8a71d7d2777672f35a41). Captures must use the supplied current-main baseline, not the PR body's older [6c9adfb273](https://github.com/pingdotgg/t3code/commit/6c9adfb2739205244b84e607736f6fd8b4611e69) baseline.

The full-table claim was independently reproduced: **4,893 source entries; 5,215 → 5,231 parsed rates; zero existing rates changed; zero removed; 16 aliases added.** Snapshot fetched 2026-11-10T06:40:28Z, SHA-256 `42677c2cfeaa9c5012806ae1f73c35779eeefa37ae8b8d29396b0f1412710325`. Main prices the sample Mythos record as unknown; the supplied head prices it at $1.60. The seven-row base/regional/GovCloud test was also reproduced outside the repository, in both entry orders, together with precedence and pricing guards. This does not claim a fresh repository test-suite run.

**Trace and render inventory.** Only `parseRateTable` and its unit test changed; there is no changed React component. The production parser callers are fresh HTTP loading and disk-cache loading in [UsageService.ts](https://github.com/pingdotgg/t3code/blob/83fcfc691f5c87e3695f8a71d7d2777672f35a41/apps/server/src/usage/UsageService.ts#L225). Both feed `UsageAggregator`, which calls `priceUsage` and `cacheSavingsUsd`, producing cost, split categories, fast/ultrafast cost, premium, and unpriced counts. `UsageSummary` crosses the existing RPC contract; web and native `useUsage` use the shared [usageMerge.ts](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/packages/shared/src/usageMerge.ts#L334) to form model/provider shares, cost sorting, daily/hourly points, category costs, and quality figures. Token/session counts do not change. Overrides still win; a provider-reported total remains authoritative, but newly available rates can now split it into categories.

- Web: [UsagePage](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/web/src/components/usage/UsagePage.tsx#L177) is the `/usage` route; command-palette navigation and `usage.open` keyboard navigation reach this same instance. Its `UsageOverview` consumes `merged`, `metric`, day/hour window, provider/environment selection, loading/kept data, and diagnostics availability. A cost transition changes headline and provider costs, cost shares/ranking, daily/hourly chart values and scale, model ordering and bars, Cost cell `Unpriced` → dollars, blank cost Share → percentage, unpriced-info popover content/presence, category bars/legends, and cache savings. Tokens mode still changes row cost cells and provider dollar subtitles, and may change cost tie-break ordering, while its headline/chart/token shares stay constant. Time breakdown changes provider and total cost cells. The chart is a provider area/line chart, not a per-model stacked chart; model-specific trends are in the dialog.
- Web detail: the model-name button opens the sole [UsageModelDialog](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/web/src/components/usage/UsageModelDialog.tsx#L36) through `UsageModelDialogHost`. Props are `model`, `environments`, `metric`, `chartWindow`, and close/set-price handlers. Fully unknown → priced changes Cost, adds cost-share text and Per 1M statistic, changes cost-mode chart from token fallback to cost, adds Cost by type, and removes the unpriced-token/Set price footer. Cache-hit statistics depend only on input tokens. Partially unknown models already show dollars and cost charts; pricing their remaining records updates cost, effective price, shares, categories, and footer count/presence instead. Set price opens `UsagePriceOverrides`; its fields reflect configured overrides, not inferred LiteLLM prices, so the editor itself has no new visual branch.
- Shared web leaves: [UsageProviderChart](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/web/src/components/usage/UsageProviderChart.tsx#L404) is called by the overview and dialog. Relevant props: providers, days/daily or hours/hourly, cost/tokens, reference time/time zone/hour format, loading-provider set. Pointer movement shows a period/provider/total tooltip; pointer leave hides it. Zero cost → positive changes axes and geometry. [UsageShareBar](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/web/src/components/usage/UsageShareBar.tsx#L12) is called by overview and dialog for token/category/speed segments: nonpositive segments disappear, zero total hides the entire bar, positive speed cost adds its separate bar, and pointer hover reveals value/share tooltips. Category `Other` is suppressed below $0.005. Known cache and fast records in fixture B exercise the newly positive branches without inventing unsupported tiers.
- Native: [UsageRouteScreen](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/mobile/src/features/usage/UsageRouteScreen.tsx#L71) is reached through the Usage stack/settings route and the workspace extra tab; both render the same `UsageScreen`. Cost headline, provider totals/subtitles, chart values, cache savings/detail ratio, permanent Unpriced percentage, Cost section, and By model rows change. Unlike web it has no model detail dialog or time-breakdown table. Cost section is entirely absent at zero cost. Tokens mode still shows changed model/provider cost subtitles and cost sections. Width <600 uses phone layout; >=600 puts summary/providers next to a larger chart, >=900 uses six total columns, and wide models use two columns. [iOS chart](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/mobile/src/features/usage/UsageDailyChart.ios.tsx) is animated SwiftUI; [Android chart](https://github.com/pingdotgg/t3code/blob/934c7f8d8e7a012aa55be9c0b17498979040fe02/apps/mobile/src/features/usage/UsageDailyChart.tsx) uses native View bars. They are not pixel-identical, so each has a small native proof row. Desktop loads the same web route and RPC data, with no pricing-specific Electron branch; a separate desktop capture adds no renderer coverage.

**Fixture data.** Use only one selected isolated environment, Claude visible, all models included, compatible contract, connected session with diagnostics permission, no custom prices/aliases, no failures, and settled scans. Use identical transcript bytes and a single LiteLLM snapshot on both sides. Pin timestamps well inside the selected window; do not place them at midnight or a rolling-window edge.

- **A — mixed controls:** PR body's four models, one assistant usage record each: `claude-mythos-5-2`, `claude-fable-5-2`, `claude-mythos-5-1`, `claude-fable-5-1`. Each has 100,000 uncached input, 20,000 output, zero cache, standard speed, no reported cost. Give unique message/request IDs, same nonempty synthetic session, timestamps 3 hours before capture with minute offsets. Expected cost rows: Mythos 5.2 Unpriced → $1.60; Fable 5.2 $1.60 unchanged; other two $2.00 unchanged. Total $5.60 → $7.20; token total 480K unchanged; unpriced-record share 25% → 0%; Mythos cost share absent → 22.2% (formatting follows app); the other models' cost shares also change despite stable dollar values. Cost category totals Input $2.80 → $3.60, Output $2.80 → $3.60. All sessions/tokens remain stable.
- **B — only alias, cached and fast:** two Mythos 5.2 records, unique IDs, one standard and one with `message.usage.speed: "fast"`, timestamps respectively 3h and 2h before capture. Each has input 100K, output 20K, cache-read 50K, cache-write 10K; no reported cost. Both records unpriced before. After each is $1.71, total $3.42, processed tokens 360K, cache savings $0.78, effective price $9.50/M, cache hit 31.25%; category costs Input $1.60, Read $0.02, Write $0.20, Output $1.60. Speed costs Standard $1.71 and Fast $1.71, premium $0.00: snapshot has no Mythos fast tier, so fallback to standard rates is correct. Before: no positive cost/type/speed bars; after: all four category segments and speed section appear. Unpriced records 100% → 0%. Native cache savings detail changes from “vs full input rates” to roughly “0.2x the raw cost”.
- **C — partially unpriced with reported cost:** two Mythos 5.2 records, each 100K input + 20K output, standard, no cache; one has top-level `costUSD: 1.6`, the other omits it. Before: model already shows $1.60, total $1.60, 50% unpriced, 120K unknown tokens, Cost by type is Other $1.60. After: $3.20, 0% unpriced, no unknown-token footer, Input $1.60 + Output $1.60, no Other. The reported record remains $1.60; newly available rates split it instead of overriding it. This covers the mixed-known/unknown model branch without a second environment.

**Matrix.** “Missing” means no capture exists as of this pass. All required visual rows are affected by the diff. A recording is required when the row asserts an interaction, a window transition, hover behavior, or native chart animation; screenshots of settled endpoints can be extracted from that same recording. Setup navigation alone does not make a static row temporal.

| Row | Named fixture / visible combination | Diff effect and assertion | Minimum surface / capture | Status |
|---|---|---|---|---|
| W1 | A, Cost, Model breakdown, 30d, settled | Four row prices; headline/provider totals; controls unchanged; shares/ranks/bars; 25% notice disappears; category totals | Web 1440×1000, light, before/after overview + Breakdown captures | MISSING |
| W2 | A, same content, compact width | Same pricing; model names wrap; Share column hidden; compact metric/period selects; no clipping of price/tokens | Web 390×844, dark, before/after; scroll to Breakdown | MISSING |
| W3 | A, selected Mythos detail | Open row; cost/chart fallback/stat-count/category/footer branches; close; before optionally open Set price then cancel without saving | **recording**, web 1440×1000 light and 390×844 dark; same sessions as W1/W2 | MISSING |
| W4 | A, alternate controls and tooltips | Hover unpriced info before; chart period tooltip; cost-segment tooltip; switch Tokens then Cost; switch Model → Day; 24h → Hour; restore. Token values stable, cost cells/subtitles/time rows updated | **recording**, web 1440×1000 light; same session as W1/W3. Exercise compact selectors in W2 session, no duplicate full timeline needed | MISSING |
| W5 | B, zero known cost → positive, Cost overview and detail | Entire positive category/speed sections appear; all cache categories; savings; standard fallback for Fast; detail stats/footer | **recording**, web 1440×1000 dark, before/after, open/close detail | MISSING |
| W6 | C, partially unpriced model / reported-cost split | Dollar cell remains a dollar cell; total rises; Other → Input/Output; partial-price footer disappears; reported amount respected | **recording**, web 1440×1000 light, before/after overview and open/close detail | MISSING |
| M1 | B, native compact Cost then Tokens | Native zero-cost section gate, model price/subtitle, quality, savings, charts; switch 24h/30d; let chart animation settle | **recording**, one iOS phone near 390pt wide, dark, same isolated server fixtures | MISSING |
| M2 | B, native compact Cost then Tokens | Same values through independent View-bar chart renderer, not SwiftUI | **recording**, one Android phone near 390dp wide, dark; no need to duplicate tablet/theme combinations | MISSING |
| N1 | Exact full LiteLLM snapshot, old/new parsers | Existing map entries unchanged, none removed, all additions listed; sample old unknown/new $1.60 | Nonvisual scratch script + document hash | PASS: 0 changed, 0 removed, 16 added |
| N2 | Seven Bedrock IDs, both orders, priority guards | Base rate wins; exact bare/first-party beat cloud; conflicting equal-priority candidate stays unknown | Nonvisual scratch assertions; equivalent new PR test reproduced without repo test runner | PASS |
| N3 | Cache/fast/reported/override/no-rate guards | B per-record $1.71, savings $0.39; reported total unchanged and split; override still wins; empty rate table still unknown | Nonvisual scratch assertions | PASS |
| X1 | No environments/selection; no permission; empty window; hidden Claude; source error; loading/kept/partial state; Limits | Parser cannot change connectivity, permissions, transcript count, selected filters, or limit data. Skeleton/error/no-activity branches remain the same; generic loading dimming is unchanged | No new capture. If encountered while seeding, wait for settled fixture rather than claim it proves price behavior | EXCLUDED by scope |
| X2 | Other lengths/counts/themes; native tablet/workspace; separate desktop/local/relay/tunnel runs | No changed CSS, wire shape, platform or transport code. Data is identical at equal viewport/theme/filter; desktop embeds the web renderer. Native tablet layout is existing arrangement of the same figures | No full cross-product. Web 1440 light +390 dark cover distinct responsive states and both theme palettes; B adds wide dark positive sections. Native phone rows cover separate native leaves | CODE-TRACED; extra captures not required |
| X3 | Explicit refresh/reconnect/TTL/error recovery | Refresh rates and rescan logic unchanged; a new server parses the same disk document with the new parser immediately. Cached/fresh/unavailable status itself is not rendered as pricing UI in these Usage views | No dedicated time-dependent capture for this fix. If included, label **recording**, retain source/hash, and respect 60s floor below | EXCLUDED; N1–N3 cover parser inputs |

**Minimum capture set:** six paired sessions (before + after): A at web 1440/light for W1+W3+W4; A at web 390/dark for W2+W3 plus compact controls; B at web 1440/dark for W5; C at web 1440/light for W6; B on one compact iOS device for M1; B on one compact Android device for M2. This uses only three transcript fixtures; no 1440/390 × light/dark × every fixture multiplication. Take settled labeled before/after stills from recordings for the PR. A full-page screenshot can document layout but cannot replace the interaction rows. iOS/Android are intentionally not called identical; their charts use different renderers. No native app work is performed in this pass.

**How to seed captures.** The future capture runner should use the supplied baseline and integrated-head checkouts, never modify this checkout during this read-only pass. Create each run in a fresh timestamped subdirectory of the lead's scratch root, with separate `claude` and `home` directories. No copied live database and no migrated seed: **every dev start must include `T3CODE_DEV_SEED=0`**. Write only synthetic JSONL under `CLAUDE_CONFIG_DIR/projects/-tmp-demo/synthetic-session.jsonl`. Omit `costUSD` except in C; it is top-level, while `speed` belongs inside `message.usage`. `sessionId`, timestamp and model must be nonempty, IDs unique. A compact generator for all fixtures follows (the JSONL records are intentionally synthetic, not real account data):

```python
import datetime, json, pathlib, sys
run = pathlib.Path(sys.argv[1])  # fresh timestamped scratch run directory
fixture = sys.argv[2]           # A, B, or C
now = datetime.datetime.now(datetime.timezone.utc).replace(microsecond=0)
models = ["claude-mythos-5-2", "claude-fable-5-2", "claude-mythos-5-1", "claude-fable-5-1"]
if fixture != "A": models = [models[0], models[0]]
lines = []
for i, model in enumerate(models):
    usage = dict(input_tokens=100000, output_tokens=20000,
                 cache_read_input_tokens=50000 if fixture == "B" else 0,
                 cache_creation_input_tokens=10000 if fixture == "B" else 0)
    if fixture == "B" and i == 1: usage["speed"] = "fast"
    ts = now - datetime.timedelta(hours=3) + datetime.timedelta(minutes=i)
    if fixture == "B" and i == 1: ts = now - datetime.timedelta(hours=2)
    row = dict(type="assistant", timestamp=ts.isoformat().replace("+00:00", "Z"),
               sessionId="synthetic-session", requestId=f"req_{fixture}_{i}",
               message=dict(id=f"msg_{fixture}_{i}", role="assistant", model=model, usage=usage))
    if fixture == "C" and i == 0: row["costUSD"] = 1.6
    lines.append(row)
out = run / "claude/projects/-tmp-demo/synthetic-session.jsonl"
out.parent.mkdir(parents=True, exist_ok=True)
out.write_text("\n".join(map(json.dumps, lines)) + "\n")
```

Generate once and copy the synthetic transcript into the two isolated capture runs so both sides use the same bytes/timestamps. Choose 30d for settled daily captures, then 24h for hour interactions; use the same local time zone and hour-format settings. There is no provider turn and no provider login needed to scan these synthetic records. The Claude reader resolves configured `homePath` before inherited `CLAUDE_CONFIG_DIR`, so a fresh database/default provider config matters. If a provider was configured manually, clear its homePath in that isolated app or point it to the same synthetic directory. Do not add real account credentials. Ensure diagnostics scope is granted to the paired test client.

Start from each capture checkout with the equivalent of:

```sh
T3CODE_DEV_SEED=0 CLAUDE_CONFIG_DIR=<absolute-run>/claude vp run dev --home-dir <absolute-run>/home
```

Read the actual server/web ports from `[dev-runner]`. The explicit home makes state `<absolute-run>/home/userdata`, independent of ambient T3 home. Let the lead use `test-t3-app` / `test-t3-mobile` for pairing, browser/device verification, and cleanup. Mobile must connect to this isolated server, not live developer state; a missing dev client is an install step. Do not consume a sharing URL intended for the user. Stop only tracked processes and release any leased devices.

**Rate-table pinning and refresh.** [UsageService.loadRates](https://github.com/pingdotgg/t3code/blob/83fcfc691f5c87e3695f8a71d7d2777672f35a41/apps/server/src/usage/UsageService.ts#L237) fetches the [LiteLLM raw table](https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json), falling back to the GitHub contents endpoint. Each HTTP attempt times out after 10s. It retains an immutable parsed table in memory and writes the original document, not the expanded aliases, to `config.stateDir/usage-model-rates.json` as `{ "fetchedAtMs": <milliseconds>, "document": <raw table object> }`. Ordinary reads use a 24h TTL; explicit Refresh usage uses a **60s minimum age**, and failed fetches have a 60s retry floor. Failed fetches preserve any available cached table.

To pin: before starting each fresh isolated server, put the exact downloaded snapshot in `<run>/home/userdata/usage-model-rates.json`, wrapped with a current `fetchedAtMs`. Disk loading re-runs that checkout's parser, so the same document is a faithful before/after input and no database mutation is needed. The snapshot must still have no bare Mythos 5.2 entry; N1 verifies that property. Ordinary period/metric changes retain this snapshot for 24h. There is no rate URL override in this service. Do not press Refresh usage after 60s in a pinned comparison: it can refetch mutable upstream data. An early refresh within the first minute is a no-op for rate fetching, not proof of refetch behavior. For a separate refresh demonstration, record actual returned/cached document and hash or use controlled network responses; do not represent a mutable fetch as pinned. Fresh/cached pricing metadata and known-model counts are not shown in these Usage components, so disk pinning does not hide a visible state required by this fix.

**Reproducing nonvisual proof.** [Download the reproduction archive](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/ec0455d5c42d8db7/reproduction.zip). It contains the exact public LiteLLM snapshot, the two parser sources extracted using `git show`, `regression.mjs`, `regression.json`, `policy.mjs`, and its transcript. Extract only into a new scratch run directory and run `node regression.mjs` and `node policy.mjs` (Node with native TypeScript stripping; this pass used Node 26). These scripts only import parser files and write the report next to themselves. They never start a server or touch a database.

For a new full-table comparison, extract `apps/server/src/usage/usagePricing.ts` from the exact requested main and head with `git show <sha>:apps/server/src/usage/usagePricing.ts` into `before.ts` and `after.ts`; download the LiteLLM JSON once into `litellm.json`; run `regression.mjs`. It records SHA-256 and source row count, compares every existing parsed key's full rate object (including cache and speed fields), lists added/removed keys, asserts unchanged existing entries, asserts old Mythos lookup is null, asserts new $8/M input/$40/M output and $1.60 sample cost, and checks forward/reverse full-document order. A future upstream change can legitimately alter the count or add a bare row; preserve that snapshot and distinguish it from this fixed-input regression rather than editing expected results to make it pass. N2 additionally tests the seven actual ID shapes with different base/regional/GovCloud rates in both orders, exact/first-party precedence and equal-priority disagreement. N3 tests positive cache/fast fallback, provider-reported split, explicit free override and unavailable-table behavior. No screenshots are claimed by these checks.

Read-only scope was preserved: no edits in the supplied worktree, no pushes, no comments, no servers or devices started. Temporary files are uploaded before removal; the lead owns the supplied checkout and parent scratch directory. Public attribution: AI-assisted; verified with the tests and tools listed above.

FRICTION: none
VERDICT: INSUFFICIENT W1, W2, W3, W4, W5, W6, M1, M2 captures missing
