#7836·QwenPaw

[Bug]: scroll eviction drops a user turn that sits inside a tool-heavy span — the live window loses the request while history.db keeps it

Author: chcsyfCreated Sep 17, 2026Updated Sep 17, 2026

Environment

QwenPaw 2.2.x, default strategy=scroll (context_manager_backend = "light").

Symptom

After a long tool-heavy task (repeated file reads, diffs, log dumps), the largest stretch of tool output was evicted from the live window as a whole, and the two user turns bracketing that stretch disappeared with it. Neither the user nor the model could see them — it reads as "history lost".

The data is neither missing nor corrupt:

  • PRAGMA integrity_check = ok; content / blocks / metadata / dedup_key intact
  • logs show scroll: compact timing outcome=at_or_below_trigger throughout — compaction never triggered
  • the rows are still in history.db and remain recallable

Root cause

scroll/manager.py::_repair_dangling_user_boundary only guarantees a turn boundary (if middle ends on a user msg and tail starts with the reply, the reply is pulled back into middle). It cannot protect a user instruction that sits in the middle of a long tool chain — that instruction is simply part of the evictable middle and gets evicted together with it.

Suggested fix

  1. Pin real user rows during eviction (at minimum keep the user requests of an evicted span visible in the live window or in the index).
  2. Add a regression test: after eviction, the user request(s) of the evicted span must still be visible in the live window or in its eviction-index entry.

Related: #7733 (long-term design), #5848 (merged — labels un-headlined spans in the eviction index; covers the index layer only, not protection of user rows).