fix(context): reset context length after a /compact boundary#524
Merged
sirmalloc merged 2 commits intoJul 25, 2026
Merged
Conversation
…dary - Stop context length sticking at the stale pre-compaction size after a compaction: usage entries before the most recent compact_boundary no longer drive contextLength - Prefer the first main-chain turn after the boundary, fall back to the boundary's compactMetadata.postTokens, otherwise 0 - Export isCompactBoundary and add getCompactBoundaryPostTokens helper in compaction.ts - Add tests covering boundary with postTokens, boundary followed by a new turn, and older-format boundary without postTokens
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.
Problem
Context-length / context-percentage widgets stay stuck at the pre-compaction token count after a
/compact, until the next assistant turn — the bug reported in #92.Right after
/compact, Claude Code setscontext_window.current_usagetonull, so the context widgets fall back to transcript parsing.getTokenMetrics()then derives context length from the most recent usage entry — the now-defunct pre-compaction turn — so the displayed size never drops.When #92 was closed, the reason given was that
/compact"doesn't send anything back that gets logged to the jsonl." That's no longer true: Claude Code writes a{ type: 'system', subtype: 'compact_boundary', compactMetadata: { preTokens, postTokens } }record on every compaction — the same marker the Compaction Counter widget already parses.Fix
getTokenMetrics()is now compaction-aware. Usage entries before the most recentcompact_boundarydescribe a context that no longer exists, so they no longer drive context length. Resolution order forcontextLength:compactMetadata.postTokens, else0(older transcripts withoutpostTokens) — never the stale pre-compaction number.Session token totals (
inputTokens,outputTokens,cachedTokens,totalTokens) stay cumulative — onlycontextLengthresets. Behavior with no compaction is unchanged.Boundary detection is reused from
compaction.ts(isCompactBoundaryis now exported, plus a smallgetCompactBoundaryPostTokenshelper), so there's no duplicated parsing and no second pass over the transcript.Tests
Added 3 cases to
jsonl-metrics.test.ts:postTokensbefore the next turn,postTokensestimate,postTokens+ no following turn →0(no stale leak).bun test(full suite) andbun run lint(tsc + eslint,--max-warnings=0) pass.Before / after
Post-
/compact, boundarypostTokens = 18000, pre-compaction context ~235k:... 235.0k (23.5%)... 18.0k (1.8%)