| # REVIEW — what changed this session, for your eyes |
|
|
| > Quick review file. Delete after you've read it. |
|
|
| --- |
|
|
| ## What the numbers look like now |
|
|
| ``` |
| === CLAUDE (./sigrank) === |
| source: ccusage claude |
| ledger R 2.65B · C 136.21M · I 2.90M · O 12.32M |
| SNR 0.810 |
| 10x DEV 2.96 |
| velocity 4.25× |
| leverage 914× |
| $/1M $0.715 |
| Υ yield 3,886 |
| class Closed-Loop Kinetic · holds both axes |
| rank #2 of 8 |
| |
| === CODEX (./sigrank --codex) === |
| source: ccusage codex |
| ⚠ estimated via turn-delta (cache_create from daily context growth) |
| ledger R 707.30M · C 26.17M · I 58.92M · O 4.01M |
| SNR 0.064 |
| 10x DEV 1.08 |
| velocity 0.07× |
| leverage 12× |
| $/1M $0.561 |
| Υ yield 1 |
| class Archival Sponge · high reuse, low generation |
| rank #5 of 8 |
| ``` |
|
|
| --- |
|
|
| ## Problem being solved |
|
|
| `ccusage --json` combines Claude + Codex + every other agent into one total. |
| When combined, Codex's large `inputTokens` (58.9M) tanked Υ quadratically. |
| Fix: run them separately — `ccusage claude --json` and `ccusage codex --json`. |
|
|
| --- |
|
|
| ## What was wrong with Codex before (and the fix) |
|
|
| **Bug 1 — detection miss (already fixed earlier):** |
| `is_codex_shape()` checked for `cached_input_tokens` (snake_case) but |
| `ccusage codex --json` emits `cachedInputTokens` (camelCase). Codex JSON |
| fell through to `parse_ccusage` — no split, no cache, raw 58.9M input. |
| Fix: check both cases. |
|
|
| **Bug 2 — anchor now uses turn-delta (CODEX.md item 1):** |
| Old: `est_fresh = 2 * output` (fixed 2:1). |
| New: with daily granularity present (we have 29 days of data), estimates |
| `cache_create` from per-day context growth deltas instead. |
| Fallback: if no daily data, uses Claude's measured I/O ratio (0.236:1) |
| instead of fixed 2:1 — grounded in your real data, not a constant. |
|
|
| --- |
|
|
| ## What the Codex numbers mean |
|
|
| | field | value | source | |
| |---|---|---| |
| | input (I) | 58.92M | `inputTokens` — fresh input directly from Codex JSON | |
| | output (O) | 4.01M | `outputTokens` + `reasoningOutputTokens` | |
| | cache_create (C) | 26.17M | **estimated** via turn-delta | |
| | cache_read (R) | 707.30M | `cachedInputTokens` — measured directly | |
| | cost | real ($0.561/1M) | from `costUSD` in the JSON | |
|
|
| The 707.3M cache reads are real and measured. Codex is reading a LOT of |
| cached context. It just generates very little output relative to input |
| (velocity 0.07×), so Υ is low. That's Codex's architecture, not a bug. |
|
|
| --- |
|
|
| ## Board marker (CODEX.md item 4) |
|
|
| Estimated rows (Codex-anchored) now show a `~` next to the operator name |
| in the leaderboard. Measured rows (real ccusage) show clean. |
|
|
| --- |
|
|
| ## What is NOT right (open questions for you) |
|
|
| 1. **Codex `inputTokens` interpretation** — the turn-delta treats `inputTokens` |
| as already-fresh (not combined with reads). If OpenAI actually reports |
| combined fresh+cached in that field, the I value (58.92M) is too high |
| and Υ will be artificially low. Do you know which it is? |
|
|
| 2. **Υ=1 for Codex** — with 58.9M fresh input and only 4M output, Υ is |
| nearly 0. That may be correct (Codex is a heavy reader, light generator) |
| or it may mean `inputTokens` is the combined figure and needs splitting. |
|
|
| 3. **CODEX.md items 2 + 3 still open:** |
| - Item 2: `test_metrics.py` (pytest for canonical numbers) |
| - Item 3: self-cost via OpenAI per-1M pricing table in `parse_codex` |
| (cost already comes through from `costUSD`, so this may be done?) |
| |
| --- |
|
|
| ## Files changed this session |
|
|
| | file | what changed | |
| |---|---| |
| | `ingest.py` | `is_codex_shape` → camelCase fix; `parse_codex` → turn-delta + io_ratio param; `ingest_meta` → io_ratio passthrough | |
| | `sigrank.py` | default changed to `ccusage claude --json`; `--codex` path fetches Claude ratio first | |
| | `app.py` | `html.escape(name)` XSS fix; `~` marker on estimated board rows | |
| |