Audit Md11 (part 2 of 2). Adds an explicit Clear() so BattleSession can
release the archive at battle-end instead of waiting for the participant to
be GC'd. _next is intentionally NOT reset — a post-Clear emit is a bug per
the design, but the seq stream must stay monotonic if it does happen.
Tests cover empty archive after Clear, _next preservation across Clear,
and Clear-on-empty no-op. The BattleSession integration that calls Clear
lands in the next commit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Audit Md11 (part 1 of 2). Replace unbounded HashSet<long> _seen with a
WindowSize=256 ring (HashSet + Queue, LRU eviction). The stale-below-window
guard (pubSeq <= HighWaterMark - WindowSize) prevents window eviction from
re-admitting old seqs as novel — the load-bearing invariant.
pubSeq is client-monotonic and SIO retransmit horizons are seconds-scale, so
256 covers realistic retries by a wide margin. HighWaterMark semantics
preserved (Gungnir still reports it).
Tests: 5 new InboundTrackerTests covering below-window guard, evicted-seq
rejection, within-window dedup after eviction, memory bound, and watermark
monotonicity.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>