fix(core): a resumed session's /context prices the memory index it carries - #264
Merged
Merged
Conversation
…rries PromptBreakdown::from_persisted repopulated tools and skills from the frozen registry but left memory empty, while the persisted prompt it prices carries the memory section on every request: after a resume with no refreeze, /context showed no memory rows for bytes the prefix pays. A manifest-restored registry holds no memory section and a fresh disk scan would price today's selection, so the rows are parsed from the persisted prompt's own bytes (the shared section header, then the index line shape), reproducing the live scan's accounting exactly.
…bytes The parser took the FIRST heading occurrence, and AGENTS.md is injected before the generated section, so a user-authored lookalike heading plus a row-shaped line was priced as the memory index while the real rows were dropped. The parser takes the LAST occurrence (nothing after the real section can hold the heading's embedded newlines), and rows are cross-checked against the manifest's memory identities when the registry carries them, so an unknown stem is never priced as a memory.
…tion A heading-shaped filename rendered verbatim by the layout section (Linux filenames may hold newlines) sat after the real section and made the last-occurrence pick parse the layout and return nothing. Every heading occurrence now yields a row run, and the LAST run that still holds identity-passing rows wins: the layout spoof has no row-shaped lines, an AGENTS.md lookalike filters to zero known stems, and the real section, frozen with the same identities, always survives.
from_manifest clears memory_files on purpose (the resume-delta baseline), so a restored registry filtered nothing and a resumed prompt carrying an AGENTS.md lookalike with no genuine section was priced as saved memory. The freeze's identities now ride a separate frozen channel: set beside memory_files on a fresh freeze, restored from the manifest (which always carried them), written back by to_manifest from the frozen channel so a restored registry re-suspending cannot erase them. The delta baseline stays reset exactly as before.
…parse Reconstructing /context's memory rows from persisted prompt bytes was an arms race: filenames and AGENTS.md render into the same prompt, and a newline-bearing filename can spell the section header AND a row reusing a genuine stem, defeating any content filter. The freeze now records its own row accounting (stem, line bytes) in the manifest (MANIFEST_VERSION 4; older manifests read as absent and refreeze, so the channel is Some on every live path), from_persisted reads only that channel, and the prompt parser is deleted. The resume-delta baseline stays reset as before.
# Conflicts: # crates/core/src/registry.rs
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.
Why
Round-5 ticket T4 (.scratch/selfext-round5/findings.md).
PromptBreakdown::from_persistedfills tools and skills from the frozen registry but leftmemoryempty, while the persisted prompt it prices carries the memory section. After a resume that does not refreeze, /context showed zero memory rows for bytes paid on every request.Summary
from_persistedtakes the persisted prompt text (it previously took only its length) and parses the memory rows from the prompt's own bytes: the section header (now a shared const, so assembly and parser cannot drift) followed by consecutive- name: description — pathlines. Each row is priced as the line length including its newline, the exact accounting the live scan records.Test Plan
a_persisted_breakdown_prices_the_memory_index_it_carries: two memories; the resumed breakdown's rows must equal the live scan's rows exactly (names and byte costs), and a prompt with no section prices none. Red against the previous no-fill behavior (verified).skillshalf of the accounting test updated to the new signature and still asserts resumed == fresh.Greptile Summary
Resumed
/contextaccounting now uses the memory-index rows captured when the session prompt was frozen. The manifest preserves those rows across restoration, preventing prompt content from changing the displayed memory costs.Confidence Score: 5/5
No blocking failure remains.
Focused manifest round-trip and forged-prompt tests passed, confirming that restored accounting retains freeze-time rows and does not interpret prompt bytes.
What T-Rex did
Reviews (6): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile