fix(parser): keep both halves of a midnight-straddling turn, and stop --provider leaking claude - #929
Open
ozymandiashh wants to merge 1 commit into
Open
Conversation
ozymandiashh
marked this pull request as draft
August 5, 2026 10:03
Collaborator
Author
|
Converted to draft: this was opened with only a self-review by the model that wrote it, which is not the review bar this batch is held to. Independent review by two other reviewers is running now; I will mark it ready once both have passed and any findings are applied. Apologies for the noise. |
ozymandiashh
force-pushed
the
fix/port-parser
branch
from
August 5, 2026 13:20
17dcd82 to
8cfa91f
Compare
ozymandiashh
marked this pull request as ready for review
August 5, 2026 13:39
ozymandiashh
marked this pull request as draft
August 5, 2026 14:13
… --provider leaking claude Ports upstream fixes for two defects this branch never received. **A turn that spans local midnight was filtered as a unit.** The range and day filter keyed on the turn's FIRST call, so every later call that landed in the requested day was discarded along with it. A long autonomous Codex run, or Claude work that crossed midnight, made `codeburn today` under-report until the turn ended, and multi-day totals attributed the whole turn to its start day. Range and day filters now slice inside the turn: only the calls inside the requested window survive, and the turn's timestamp re-anchors to its first surviving call so turn-anchored rollups — category, editTurns, oneShotTurns, the daily cache — land on the day the retained calls actually happened. Cost, calls, savings and tokens bucket under each call's own local day, so day N plus day N+1 conserves the whole-range total. A sliced turn is still classified from its FULL call list, because category, hasEdits and retries describe the whole exchange rather than the surviving slice — matching the Claude path. **The inverse leak hit provider-filtered runs.** `--provider <other>` still entered the claude scan, whose orphan pass read the entire cached claude section, treated every cached PR-bearing transcript as no-longer-discovered and re-injected it. By Project and By Model listed Anthropic spend under `--provider cursor` while the headline showed cursor alone. The scan is now guarded by an explicit in-scope check — deliberately not a directory-count check, so when claude IS in scope but every transcript has been pruned, PR-attributed orphans still survive. **The daily cache is bumped to 17**, because leaving it at 15 would double-count the post-midnight half of a straddling turn for an upgrading user. A v15 rollup finalized by the pre-fix binary holds the WHOLE turn on its start day, and the new slicing then also puts the post-midnight call on the next day — the same cost twice, in a cache whose ten-year retention never ages it out. The bump mints a fresh filename; adoption marks the merged result incomplete, so the next hydration re-derives every day whose sources survive under per-call bucketing and carries forward only what it cannot re-derive. 16 is deliberately skipped: main already spent it on the codex structural-discovery fix (eece4cf), so claiming 16 here would load a main-built v16 cache — which holds only the codex fix — as current and complete and the invalidation would never fire. Blast radius: daily-history rows, the JSON daily fallback and range-query session totals change shape for straddling days, as call-derived values move to the call's own day — the intended correction, asserted by this commit's tests. The session-cache FORMAT is unchanged. One caveat worth stating rather than leaving to be found. The multi-day all-provider By Activity rollup still derives today's slice from the unsliced range parse, so a straddling turn's category cost stays anchored on its start day and categories can sum below the headline on that surface; upstream has a follow-up for it.
ozymandiashh
force-pushed
the
fix/port-parser
branch
from
August 5, 2026 14:20
8cfa91f to
556b59d
Compare
ozymandiashh
marked this pull request as ready for review
August 5, 2026 14:40
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.
Ports upstream fixes for two defects this branch never received. Both are conservation bugs: work that happened is not where the report says it is.
A turn spanning local midnight was filtered as a unit
The range and day filter keyed on the turn's first call, so every later call that landed in the requested day was discarded along with it. A long autonomous Codex run, or Claude work that crossed midnight, made
codeburn todayunder-report until the turn ended — and multi-day totals attributed the whole turn to its start day.Filters now slice inside the turn. Only the calls inside the requested window survive, and the turn's timestamp re-anchors to its first surviving call, so turn-anchored rollups (category, editTurns, oneShotTurns, the daily cache) land on the day the retained calls actually happened. Cost, calls, savings and tokens bucket under each call's own local day, so day N + day N+1 conserves the whole-range total.
A sliced turn is still classified from its full call list — category, hasEdits and retries describe the whole exchange, not the surviving slice. That matches the Claude path and is deliberate.
The inverse leak, on provider-filtered runs
--provider <other>still entered the claude scan, whose orphan pass read the entire cached claude section, treated every cached PR-bearing transcript as no-longer-discovered, and re-injected it. By Project and By Model listed Anthropic spend under--provider cursorwhile the headline showed cursor alone.Now guarded by an explicit in-scope check — deliberately not a directory-count check, so when claude is in scope but every transcript has been pruned, PR-attributed orphans still survive.
Blast radius
Daily-history rows and the JSON daily fallback change shape for straddling days: call-derived values move to the call's own day. Session totals and the session-cache format are unchanged.
Two caveats, stated rather than left to be found