Skip to content

Session bank: postcommit restores do not refresh entry recency - #554

Open
jvmenen wants to merge 1 commit into
youssofal:mainfrom
jvmenen:pr/bank-maintenance-reads
Open

jvmenen wants to merge 1 commit into
youssofal:mainfrom
jvmenen:pr/bank-maintenance-reads

Conversation

@jvmenen

@jvmenen jvmenen commented Sep 28, 2026

Copy link
Copy Markdown

Summary

The async retokenized postcommit restores a turn's own prompt-prefix entry from the session bank to re-render its history. That restore counted as use and refreshed the entry's last_access_s. Under the per-session retention cap this could rank the superseded prompt prefix above a sibling lineage (for example the entry of a tool-fed retry that diverged early in the transcript) and evict the entry the next request needed, which then prefilled from much further back. With this change the postcommit's restore no longer counts as use; client restores still do. No switch.

Motivation

SessionBank keeps at most per_session_max_entries entries per session and evicts the least recently used. On an agent turn that is retried (a first pass plus a tool-fed retry diverging early), the bank holds two lineages for the session. The postcommit then restores the first pass's prompt prefix, which refreshes that entry's recency, and banks the re-rendered history as a new entry. The refreshed old prefix now outranks the retry lineage, so the next insert evicts the retry entry, although the old prefix is superseded by the entry the postcommit just stored. A following retry then misses and prefills from an early boundary.

The restore is bank maintenance, not a client using the entry, so it should not move the entry in the LRU order.

Change

  • mtplx/session_bank.py: new SessionBank.maintenance_reads() context manager (thread-local depth counter). A RAM restore inside the block leaves entry.last_access_s unchanged; hit counters and everything else are as before.
  • mtplx/server/openai.py: _store_retokenized_history_snapshot runs its restore_or_prefill_prompt_state call inside maintenance_reads() (via _bank_maintenance_reads, which falls back to nullcontext() for banks without the method).
  • Client restores, eviction policy and retention caps are unchanged.

Tests

  • tests/test_session_bank.py::test_postcommit_restore_keeps_the_retry_lineage_under_retention: a bank simulation of agent turns with a first pass, an early-diverging retry and a postcommit, with and without the postcommit landing; the next first pass restores from the expected entry and the retry lineage survives retention. Fails without the change.
  • tests/test_postcommit_prefix_reuse.py::test_postcommit_restore_runs_as_bank_maintenance: the postcommit's restore runs inside maintenance_reads() and the block is left afterwards.
  • tests/test_session_bank.py and tests/test_postcommit_prefix_reuse.py pass.
  • Full suite with MTPLX_CONFIG=/nonexistent: 9,384 passed, 67 skipped, 1 failed. The failure is test_laguna_model.py::test_laguna_s_2_1_ar_route_skips_qwen_performance_hooks, which fails the same way on main on a Mac with less than 85.3 GiB (addressed in Tests no longer read the user's ~/.mtplx/config.toml or depend on the Mac's memory size #535). Ruff: no new findings.

Code change and unit tests only, no model run.

🤖 Generated with Claude Code

The async retokenized postcommit restores the turn's own prompt-prefix
entry to re-render history. Counting that read as use ranked the
superseded prompt prefix above a sibling lineage under the per-session
retention cap, so a following tool-fed retry could lose the entry it
needed and prefill from much further back.

SessionBank.maintenance_reads() keeps last_access_s unchanged for
restores inside the block (per thread); the postcommit restore runs
inside it. Client restores still refresh recency.

Tests: tests/test_session_bank.py (the retry lineage survives retention
when the postcommit restore lands), tests/test_postcommit_prefix_reuse.py
(the postcommit restore runs inside maintenance_reads).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@jvmenen
jvmenen requested a review from youssofal as a code owner September 28, 2026 09:40

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant