Skip to content

cost-tracker.sh: cache writes always priced at 5m TTL, never 1h TTL #162

Closed

Description

@wasikarn

Problem

hooks/stop/cost-tracker.sh's rate function prices every cache-write token at the
5-minute-TTL cache-write rate, for every model, always. It has no way to charge the
1-hour-TTL rate, which every model prices roughly 1.6x-2x higher than the 5-minute rate
(confirmed live against platform.claude.com/docs/en/about-claude/pricing, 2026-09-25,
e.g. Opus 5.5: $5/MTok at 5m vs $8/MTok at 1h).

The root cause: raw_records() (hooks/stop/cost-tracker.sh:163) reads only the flat
cache_creation_input_tokens field from each transcript usage object. That field does not
distinguish 5-minute from 1-hour cache writes. The current Messages API usage object exposes
a breakdown (cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens) that
this script never reads.

This is not hypothetical: this harness's own Claude Code sessions run at a 1-hour cache TTL
(stated directly in the ScheduleWakeup tool's own description this session: "This session's
requests use a 1-hour Anthropic prompt-cache TTL"). So most, possibly all, cache-write tokens
recorded in ~/.local/share/kbg/metrics/costs.jsonl have likely been undercounted since this
pricing table existed, across every model bucket, not just Opus 5.5.

Found by

mh:deep-audit, 2026-09-25, reviewing commit fe388ba5 (the Opus 5.5 pricing-branch fix).
Also independently surfaced by a Codex (gpt-6-sol) fresh-context checker dispatched as part
of that audit.

Suggested fix shape (not scoped or verified yet)

  1. raw_records() reads .message.usage.cache_creation.ephemeral_5m_input_tokens and
    .ephemeral_1h_input_tokens instead of (or alongside, for older transcripts that only have
    the flat field) cache_creation_input_tokens.
  2. rate()'s per-model table gets a second cache-write rate (cw1h alongside cw) for every
    branch, each independently confirmed against the live pricing page before shipping v:true.
  3. group_and_price()'s cost formula splits cache-write cost by the two buckets instead of one
    flat cw * cw_tokens term.
  4. Decide whether to backfill/relabel the ~121+ already-mispriced historical rows in
    costs.jsonl, or just note the correction point going forward.

Scope note

Not fixed in the 1.1.117 pass because it needs its own investigation into exactly how large
the historical undercount is and whether older transcripts even carry the breakdown field —
a same-pass patch risked shipping a second unverified pricing claim on top of the first.

Activity

  1. wasikarn commented on Sep 25, 2026

    @wasikarn
    OwnerAuthor

    Follow-up from mh:blind-spot-hunter's whole-picture pass on the 1.1.117 fix round (2026-09-25).

    Measured, not just theoretical

    Checked live: transcripts do carry the usage.cache_creation.ephemeral_1h_input_tokens /
    ephemeral_5m_input_tokens breakdown for 100% of 23,484 deduped messages across 400 files
    since 2026-09-14. The 1-hour share of cache-write tokens is 0.97-1.00 for every model family
    in that window. Over the last 2 weeks, cache writes are 22% of total cost, so recorded totals
    run roughly 11.8% under the true 1h-priced total (
    $3,169 vs the recorded ~$2,796). For Opus
    5.5 specifically, cache writes are 56% of its cost, so it runs about 25% under.

    Caveat for a fix: 258 of those 23,484 messages (0.55%, ~603K tokens) have
    flat != 1h_tokens + 5m_tokens — a real remainder. A correct fix should price
    flat - (1h_tokens + 5m_tokens) at some fallback rate rather than dropping it, not just switch
    to reading the two split fields alone.

    A second, distinct bug in the same area (not this issue's scope, filing here for visibility)

    Before the 1.1.116 fix, claude-opus-5-5 matched the old bare opus branch and got
    rate_verified:true at the wrong (Opus 5) rate. 122 rows across 8 sessions (2026-09-23 to
    09-25) in ~/.local/share/kbg/metrics/costs.jsonl carry this stale price with no way for
    cost-report to tell they're wrong — rate_verified:true reads as confirmed-correct, and
    nothing marks the mh-version boundary. Reported total for that window is ~$17.22; the correct
    figure is ~$10.03 at the 5m cache-write rate (or ~$13.39 if this issue's 1h fix also lands).

    This needs its own fix in skills/meta/cost-report/: an Eras row plus a
    note: keyed on model~opus-5-5 && mh_version < 1.1.116, or an explicit accepted-inaccuracy
    note — separate from the 5m/1h TTL fix above, since it's about wrong-branch mispricing before
    the fix, not TTL-blindness after it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions