Skip to content

feat(cost): a SPEND card that prices seats, beside a TOKEN COST card - #44

Merged
kleyt0n merged 2 commits into
mainfrom
feat/spend-vs-token-cost
Aug 3, 2026
Merged

feat(cost): a SPEND card that prices seats, beside a TOKEN COST card#44
kleyt0n merged 2 commits into
mainfrom
feat/spend-vs-token-cost

Conversation

@as-koshiyama

Copy link
Copy Markdown
Contributor

What

The Overview led with SPEND over a figure that is not spend — it is the window's tokens priced at API list rates. Two cards now ask two different questions about the same tokens:

  • TOKEN COST — the old figure under the name it deserved: tokens × API list rates, with the rate, delta, and unpriced qualifiers unchanged.
  • SPEND — what the seats behind that usage actually cost per month.

Where SPEND's figures come from

  1. [cost.subscriptions] — configured seat prices, shown plainly. Always wins.
  2. Failing that, the plan the tool's own transcripts name: Codex writes rate_limits.plan_type beside its token counts, so this reads no account state. A detected plan is priced at its published list rate via the fallback table CostConfig::monthly already carried (previously unreachable — the plan argument was always None) and marked an estimate.
  3. A tool with usage but no figure makes the total a floor; knowing nothing, the card shows and names the config key. Never a guess.

The Cost view's subscription table picks up detected plans through the same line, still suffixed est.

Ledger v5

Detected plans persist in the ledger (plans: tool → plan), version 4 → 5 — the same argument that put session metadata in v4: steady-state scans read no bytes, so anything gathered during a read must survive between scans. First scan after upgrading re-reads transcripts once.

Verification

  • End-to-end on a real corpus: a fresh scan writes "plans":{"codex":"team"} and the card shows ≥≈$30.00/mo · 1 plan(s) detected · ▲ 1 tool(s) unpriced (Claude Code here has usage but no plan/config — correctly floored).
  • Six new tests: plan parsed beside the counts, plan absent without rate_limits, plan ingested into the ledger, plan survives save/reload (last one wins), and the card's three states (dash/never-guess, detected estimate, floor with configured seat).
  • --demo seeds two plans so the card demos populated. Docs updated everywhere the "does not guess your plan" claim lived (README, dashboard.md, costs.md, configuration.md, surface.example.toml) plus CHANGELOG.
  • cargo fmt, clippy -D warnings, all 249 tests pass.

Interactions

Independent of the other open PRs (#41, #42, #43); it will conflict trivially with #43 on the qualifier line under what is now the TOKEN COST card — whichever lands second rebases one line.

🤖 Generated with Claude Code

The Overview led with SPEND over a figure that is not spend - it is
the window's tokens priced at API list rates. That figure keeps its
card under the name it deserved, TOKEN COST, with the rate, delta and
unpriced qualifiers unchanged.

The SPEND card now answers the question its name asks: what the seats
behind the usage actually cost per month. Figures come from
[cost.subscriptions], or failing that from the plan the tool's own
transcripts name - Codex writes rate_limits.plan_type on the same
records the token counts come from, so this reads no account state.
A detected plan prices at its published list rate via the fallback
table CostConfig::monthly already carried, and is marked as an
estimate; a tool with usage but no figure floors the total; knowing
nothing, the card shows a dash and the config key rather than a guess.

The Cost view's subscription table picks up detected plans through the
same one line, still suffixed est. Detected plans persist in the
ledger - version 5, because a steady-state scan reads no bytes and
anything gathered during a read has to survive between scans, the same
argument that put session metadata in version 4. The first scan after
upgrading re-reads transcripts once.

Verified against a real corpus: a fresh scan writes
plans:{codex:team} and the card prices it at $30/mo, flagged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kleyt0n
kleyt0n previously approved these changes Aug 1, 2026

@kleyt0n kleyt0n left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

# Conflicts:
#	CHANGELOG.md
#	docs/guide/dashboard.md
#	src/ui/mod.rs
@kleyt0n
kleyt0n merged commit 34cb658 into main Aug 3, 2026
7 checks passed
kleyt0n added a commit that referenced this pull request Aug 11, 2026
Two conflicts, both from main having merged #44 (spend-vs-token-cost) after
this branch already carried it.

src/ui/mod.rs — main's copy of `the_token_cost_card_qualifies_its_dollars`
landed as a duplicate of the one already here (commit cf88d91 gave this
branch's copy the same cache rates), and git split the duplicate across the
metering tests. Dropped the duplicate, kept main's fuller doc comment on the
surviving copy, and kept `metering: Default::default()` on the fixture main
does not know the field for.

CHANGELOG.md — this branch had flattened main's entries to ASCII (`—` → `-`,
`≥` → `>=`), truncated their prose and added a UTF-8 BOM. Main's text is
canonical for the shared entries, so the section is rebuilt from it plus the
three entries only this branch adds: the card row, the metering view and
`[usage.repo_aliases]`. BOM removed.

cargo fmt / clippy -D warnings clean; 287 tests pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants