Skip to content

Exploration notes: cheaper window-expiry processing from retained contributions #130

Closed as not planned

Description

@rsyuzyov

Following the #121 review suggestion to explore cheaper expiry processing from retained contributions — some measurements and a structural finding from a workstation with a 976-file, 1.58 GB history.

Measured cost today (four days of live logs)

So exact per-drift boundary re-reads cost roughly 3–4 minutes per four days here — real, but an order of magnitude below what the mutation rebuilds cost.

Structural finding

Exact expiry subtraction needs to remove, from a file's retained AnalysisAcc, precisely the events that crossed the cutoff:

  • structuralEvents carry no timestamps, so expired tool events cannot be selected from them;
  • seenUuids expiry interacts with first-owner dedup: an expired UUID may have an in-window twin whose ownership must be restored (the 'ownership' plan machinery would need the expired UUIDs enumerated);
  • prompts do carry observedAtEpochMs, so the bounded tail is fine.

Closing the gap means retaining per-event (or per-bucket-per-timestamp) data for the whole 30-day window — a memory cost paid on every refresh to save a small one-off read per boundary file. An exact middle ground I sketched is an offset-slice re-read: keep the byte offset of the oldest retained line per file, and on drift re-read only the newly expired prefix slice (transcripts are append-only and near-monotonic in time, with a full-read fallback when the guard trips). That keeps retention flat but still touches parse, subtraction for every sub-structure, and the ownership handoff.

My conclusion: not worth the contract churn now — #127 and #128 remove the storms, and the drift re-reads are already bounded to the few files the cutoff is crossing. Filing this so the exploration is on record; happy to build the offset-slice variant if you want it anyway.

🤖 Generated with Claude Code

Activity

  1. github-actions commented on Oct 9, 2026

    @github-actions

    🤖 Automated first-pass reply

    TL;DR
    The measurements are clear and the cost is small: ~3–4 minutes of read-parse per four days from drift re-reads, an order of magnitude below the ~9 deletion rebuilds (#127) and ~31 rewrite rebuilds (#128). The structural finding is the real conclusion: exact expiry subtraction would require retaining per-event or per-bucket-per-timestamp data for the full 30-day window, paid on every refresh. Not worth the contract churn now.

    Analysis

    • Where this sits in the architecture: the drift/append path is claudeIncrementalIndex.ts — "Runtime refreshes must not fall back to a full-corpus body read", with append/truncate/replace/move/delete work "limited to affected files and affected aggregate groups while preserving the established response-identity and content-analysis semantics." The exact per-drift boundary re-read is exactly this "affected files" set.
    • The stated blockers match the retained structures described for that module: structuralEvents carry no timestamps (so expired tool events cannot be selected), seenUuids expiry couples to first-owner dedup via the 'ownership' plan machinery (so expired UUIDs would need enumeration to restore an in-window twin's ownership), while prompts do carry observedAtEpochMs and the bounded tail is already fine.
    • The offset-slice sketch (oldest-retained-line byte offset + re-read only the newly expired prefix, with a full-read guard fallback) keeps retention flat but "still touches parse, subtraction for every sub-structure, and the ownership handoff." That is the contract-churn argument, and it is consistent with the module's mandate to preserve exact dedup and content-analysis semantics.
    • The cold-start full reads are called out separately as the remaining big rock, "presumably covered by the checkpoint work that just landed for Codex caches." That is a Codex-side invariant (persistent per-file aggregate index / checkpoint hydration), not a Claude drift concern; keeping the two distinct avoids attributing the Codex checkpoint gain to the Claude path.

    Suggested next step(s)

    • Record this as exploration-only. The issue can be closed as "on record, no action" while perf: deleting a transcript no longer re-reads the whole history (#99) #127 and perf: rewriting a transcript no longer re-reads the whole history (#99) #128 carry the actual cost reduction.
    • If the offset-slice variant is ever wanted, it should be a separate proposal with its own acceptance criteria for exact dedup ownership restoration and content-analysis equivalence — not a drive-by change to claudeIncrementalIndex.ts. A cheap prerequisite measurement would be how often the near-monotonic-time guard trips on real transcripts, since that bounds the fallback cost.
    • One clarification that would sharpen the record: is the cold-start full-read item intended as a separate tracking issue, or is it already covered by the landed Codex checkpoint work (given the Codex/Claude distinction above)?

    🤖 Generated by DeepSeek as an automated first pass — not a maintainer decision.

  2. Carl723000 commented on Oct 15, 2026

    @Carl723000
    Collaborator

    Thanks @rsyuzyov for the measurements and for spelling out the expiry/ownership trade-off. This is useful exploration to keep on record. The current exact rolling-window contract is retained; an offset-slice implementation would need a separate proposal and regressions for out-of-order timestamps, UUID first-owner restoration and full-loader content-analysis equivalence.

    One important scope distinction: Codex's persistent checkpoints do not eliminate Claude's cold-start in-memory build. Also, #127 and #128 are still open, so their mutation-rebuild optimizations should not be read as already shipped in 2.5.0.

    Closing this exploration as not planned for the current scope, rather than as an implemented optimization. The original contribution and measurements remain here; #99 and the original performance PRs continue to track the remaining work. A future offset-slice proposal can link back to these findings.


    🤖 Generated by OpenAI Codex as an automated first pass — not a maintainer decision.

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions