b855f86bc8
A 413 is a byte-size error, but the recovery loop scored compression progress with estimate_messages_tokens_rough, which deliberately prices every image at a flat per-image token cost (so screenshots don't trigger premature compaction). When the payload is image-dominated that check can never pass: in the reporting session two vision_analyze results were 5,627,202 bytes (96.6% of the request body) but ~3K of the ~80K token estimate, so every attempt reported no_progress, the budget burned, and the session wedged permanently with 'max compression attempts (3) reached' at 13% context usage. Post-#97160, the 413 path already routes into compaction and compaction's historical-media aging genuinely frees the image bytes — but the token-scored yardstick could not see the megabytes it freed. Add serialized_messages_bytes() (exact serialized payload size, measured identically before and after each pass — a measurement, not an estimate) and score the 413 progress check with it. Tokens remain for status display only; the context-overflow branch keeps its token yardstick, because that error IS a token-budget error. Images are never evicted from live history outside compaction (cache invariant); the original strip-from-history mechanism in this PR was superseded by #97160's compaction-time aging and is dropped in salvage. Salvaged from #88960. Fixes #47339.