Conversation
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>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
SessionBankkeeps at mostper_session_max_entriesentries 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: newSessionBank.maintenance_reads()context manager (thread-local depth counter). A RAM restore inside the block leavesentry.last_access_sunchanged; hit counters and everything else are as before.mtplx/server/openai.py:_store_retokenized_history_snapshotruns itsrestore_or_prefill_prompt_statecall insidemaintenance_reads()(via_bank_maintenance_reads, which falls back tonullcontext()for banks without the method).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 insidemaintenance_reads()and the block is left afterwards.tests/test_session_bank.pyandtests/test_postcommit_prefix_reuse.pypass.MTPLX_CONFIG=/nonexistent: 9,384 passed, 67 skipped, 1 failed. The failure istest_laguna_model.py::test_laguna_s_2_1_ar_route_skips_qwen_performance_hooks, which fails the same way onmainon 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