Skip to content

fix(usage): transcript-derived cost is a lower bound even under API key (background model calls omitted) #156

@manzil-infinity180

Description

@manzil-infinity180

Summary

aflock derives tokens/cost from the Claude Code session JSONL (internal/usage/jsonl.go) and, under auth_mode=api_key, sets CostMeasured=true and treats the figure as authoritative for maxSpendUSD enforcement (internal/policy/evaluator.goIsAdvisoryLimit). But the conversation transcript omits Claude Code's background model calls — haiku title generation, compaction/summary calls, quota probes — which still hit the bill. These are missing in both subscription and API-key modes, so transcript cost is a systematic lower bound, not an exact figure, even under API key.

Evidence

  • internal/auth/claudeauth/detect.go already notes title-gen / compaction "hit the bill but never the transcript" — but frames it as subscription-only. The omission is auth-mode-independent.
  • Concrete: a captured session's first model call is a claude-haiku-4-5 title-generation request. Datadog lapdog captures it (reads the wire); an out-of-band transcript reader does not — the transcript holds only the conversation turns.

Why it matters

CostMeasured=true under API key implies "this equals the bill." It doesn't — it's " this." Enforcement that under-counts can let a session quietly exceed its real maxSpendUSD cap.

Options

  1. Cheap / honest (now): relabel transcript cost as a documented lower bound — surface "≥ $X" / "approx", not authoritative. Keep enforcing (a lower-bound breach is still a real breach), but stop claiming exactness.
  2. Reconcile (API key only): periodically reconcile against Anthropic's usage/cost API. Not real-time, API-key only.
  3. Full fix: read the wire — captures every call exactly in any auth mode (tracked in feat(usage): optional wire-interception proxy for complete, real-time, subscription-accurate accounting + enforcement #157).

Verify

For one session, compare Σ(transcript usage) vs Claude Code /usage vs Anthropic billing; quantify the gap.

Related: #111, #96.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions