Found while investigating billion-context-pi #336 (closed PR #225).
Bug: isCovered(id, covered) in src/prune.ts only tests exact id membership. If a compression block's recorded effective message ids use sub-id forms (base#callId, base#r0, …) while the current projection emits plain base (or vice versa after a projection change), coverage checks fail and already-compressed messages re-enter the visible view resurrected (measured: a 762K-token leak in replay after introducing thinking sub-id projections).
Fix: normalize to the base id before membership — covered.has(id) || covered.has(base) || any covered entry shares the same base prefix. Currently latent (no shipped adapter projects sub-ids), but it bites anyone who extends the projection.
Found while investigating billion-context-pi #336 (closed PR #225).
Bug:
isCovered(id, covered)in src/prune.ts only tests exact id membership. If a compression block's recorded effective message ids use sub-id forms (base#callId,base#r0, …) while the current projection emits plainbase(or vice versa after a projection change), coverage checks fail and already-compressed messages re-enter the visible view resurrected (measured: a 762K-token leak in replay after introducing thinking sub-id projections).Fix: normalize to the base id before membership —
covered.has(id) || covered.has(base) || any covered entry shares the same base prefix. Currently latent (no shipped adapter projects sub-ids), but it bites anyone who extends the projection.