fix(compaction): reject stale pre-compaction anchor in context breakdown

getContextBreakdown used message position (anchorIndex >= pending.cutoffCount) as a proxy for usage freshness. After a mid-run compaction rebased the in-flight snapshot, an in-flight provider response whose request predated the compaction landed past the rebase cutoff carrying pre-compaction usage, so it out-ranked the rebased estimate and reported the pre-compaction token count (~2.6x the real one). That phantom overflow tripped the "freed too little context to make progress" guard and drove the frame-rescue path on a byte-identical tokensBefore.

Assistant context snapshots now carry a monotonic compaction epoch, bumped in rebaseAfterCompaction and stamped at message-record time. A post-cutoff anchor whose epoch predates the pending snapshot's epoch is no longer trusted over the rebased estimate.

Fixes #8887
This commit is contained in:
roboomp
2026-08-19 09:13:33 +00:00
parent d94bdfa1bb
commit e6c0cf90a4
5 changed files with 103 additions and 3 deletions
+7
View File
@@ -886,6 +886,13 @@ export interface ContextSnapshot {
nonMessageTokens: number; // estimated non-message total at send time
/** Estimated prompt tokens removed by local history rewrites after this provider snapshot was recorded. */
historyRewriteTokensRemoved?: number;
/**
* Compaction epoch current when this snapshot's provider request was recorded.
* A later compaction bumps the session epoch, so an anchor whose epoch is
* older than the current in-flight snapshot describes pre-compaction history
* and must not override the rebased estimate.
*/
compactionEpoch?: number;
lastMessageTimestamp?: number;
}