The Stop hook's stdin payload does not include `usage` or `model` —
those fields exist only in the session transcript JSONL (per-assistant-turn
`message.usage` blocks). The previous implementation looked for
`input.usage.input_tokens` on stdin and silently produced zero-filled rows
(observed: 2,340 rows captured with 0.0% non-zero token rate over 52 days).
Fix: read `transcript_path` from Stop stdin, scan the JSONL, sum usage
across all assistant turns. Use `message.model` to pick a rate tier
(haiku/sonnet/opus). Track cache tokens separately (cache_creation and
cache_read have distinct billing rates).
Behavior note: Stop fires per assistant response, so each row in
costs.jsonl represents the cumulative session total at that point.
To get per-session cost: take the last row per session_id.
Verified by reading a real Stop hook payload from
.claude/projects/*/<uuid>.jsonl — payload contains
{session_id, transcript_path, cwd, hook_event_name, ...} only,
matching the published Claude Code hook spec.