Repository navigation
perf(telemetry): the ledger is kept by day, so an ingest costs what it adds - #1031
Merged
Merged
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
…ndow Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
…indow One ingested call now loads, folds and writes only its calls' days and the day on each side, plus any monthly partition those days fall in, which it splits into days. Damage and duplicates in the window are rewritten with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
The report rewrites, folded, every partition that is damaged, monthly, or holds a call another one holds, so the bytes on disk are those of one ingest of the same calls whatever order the ingests ran in. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Pins that forget removes daily and monthly partitions as the ledger, never as an earlier day file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Kills the two mutants the telemetry run left in the ledger adapter: an unanchored monthly name, and a duplicate inside one day going unseen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
dayOf now gives no day for a time without an explicit zone (Z or +-hh:mm), or whose UTC day falls outside four-digit years. Such a call is counted undated at ingest, and such a ledger line is counted and dropped as not a record, instead of landing in a file DAILY never reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
The report settles the ledger, so a line that is not a record is gone after it, as after an ingest. Both now say so in the same words. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
…nged nothing A day's key never equals a month's, so filtering names to monthly files before matching them against the touched months was redundant: the equivalent mutant the review saw survive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Once on disk and order-independent bytes hold after a report settles the ledger; an ingest reads its window plus a month it splits; save removes a named day it holds no records for rather than writing it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Adds torn lines in a monthly file and in a stray day, calls already held in a monthly file read again, 200 runs, an assertion that the bytes are the canonical partitionByDay(foldUsage(calls)) with each call once, and that a second settle finds nothing to do and changes nothing. Red when settle ignores damaged partitions or save keeps an emptied day. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
The four-digit check on the computed day was a ten-character regex on a ten-character slice, so its anchors were equivalent mutants; it is now a sign check. Reading a stored time goes through dayOf alone. Tests pin the leading anchor and a zoned time naming no real day. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
7ff1dee read a stored time through dayOf(String(at)), so a time held in a one-element array coerced to a zoned string and was accepted with a non-text at. The text check is restored, superseding that commit's "goes through dayOf alone"; the new refusal case also kills its mutant, so the check is no longer equivalent. The zone pattern's closing anchor is kept and says why no test can observe it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VWNxk63AGKkqE8HRqHLjGp
blafourcade
marked this pull request as ready for review
October 15, 2026 14:43
This was referenced Oct 15, 2026
Merged
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🎯 What & why
One ingested call used to cost the whole ledger: every partition read and refolded, and its month rewritten (#1001). The ledger is now kept by UTC day, and an ingest reads, folds and rewrites only the days around its calls. One call into a 265k-call ledger: ~1.65 s → 58-64 ms, flat as history grows.
🛠️ How it works
ledger/<YYYY-MM-DD>.jsonlreplace<YYYY-MM>.jsonl. The mechanism is unchanged: canonical order, a changed partition rewritten whole by rename, one call per line (usage-ledger-adapter.ts).atwithout a zone or outside four-digit years is now unusable, so a day never depends on the machine's TZ. Incoming calls like that count asundated; stored lines like that are dropped as damage. Claude always writesZ: 1.83M local timestamps checked, none without it.🧪 How to verify
cd cli && pnpm test: 6495 passed.pnpm test:mutation:telemetry: 96.14 (floor 96).node scripts/check-claude-tokens-end-to-end.cjs(and--attended):2 calls, 393 tokens, all on task demo, ticket T-1.reportstill reads the whole ledger (~2.8 s on a 265k-call month). That is out of scope here.IngestResult.skippedLedgerLinesnow counts damage inside the ingest's window. The report's figure covers everything.AIDD_TELEMETRY_DIRpoints atledger/itself,forgetwould list day files as files from the earlier version. This is a pre-existing oddity.🔗 Linked issue
Closes #1001
✅ I certify
🤖 Generated with Claude Code