Skip to content

feat(agent): keep a file's reads out of compaction (roadmap B5, S4) - #314

Merged
yusiwen merged 2 commits into
masterfrom
feat/kept-paths
Oct 31, 2026
Merged

yusiwen merged 2 commits into
masterfrom
feat/kept-paths

Conversation

@yusiwen

@yusiwen yusiwen commented Oct 31, 2026

Copy link
Copy Markdown
Owner

What changed

  • agent: KeptPaths + KeepPath/UnkeepPath/keepsPath; compactRunMessages keeps any round whose
    tool_calls arguments name a kept path verbatim (after the marker, before the tail), summarizes the
    rest, and does nothing at all when every round is kept.
  • session: Session.KeptPaths, written by persistSession and restored by adoptSession, so a resume
    keeps the rule.
  • TUI: /keep <path>, /keep (list), /unkeep <path>, all refused while a run is active; palette
    entries and /help lines; goldens regenerated.
  • Docs: CODEBASE.md (the three functions), roadmap B5 → Delivered — [agent] Give context management turn-level control: pin, unpin, drop #306 (17 delivered, 1 in
    progress, 21 not started, total 40), test count 1285 → 1291.

Why

S4's acceptance was rewritten when S2 landed, because its original sentence — "/drop <path> removes the
tool results that read that path" — assumed a command channel that does not exist: a run's messages are
local to Run, and the TUI refuses commands (which would mutate the slice the run appends to) while it
runs. The rule therefore moves to where it can be made safely: before the run, persisted with the
session.

Kept rounds are re-inserted after the compaction marker rather than in place. That is the same
approximation the pinned-group rule makes for history compression: a summary is already a lossy stand-in,
and keeping the text at all matters more than its exact position in the stand-in.

Verification

  • go test ./... -count=1 and -race: 16 packages ok; go vet and gofmt -l clean.
  • Mutation checks, both load-bearing paths:
    • the kept-round check disabled → TestCompactRunMessagesKeepsPathsTheUserKept fails with the kept read was summarized away;
    • the persist line dropped → TestKeepPathSurvivesTheSessionFile fails with the session kept [].
  • New tests: 3 in agent (list cleaning/dedupe, a kept read surviving while an unkept one is summarized,
    an all-kept run costing no call) and 3 in tui (the three command forms, persist + resume, the run
    guard).
  • git log --format='%h %G? %s' → G.

Honest scope

  • Matching is a substring of the tool-call arguments: a kept path of a.go also matches data/a.go. For
    a path a person types at the prompt that is a convenience, not a correctness guarantee; a directory
    prefix would be the alternative and was not chosen.
  • The list is per session, not per project: the same file kept in one session is not kept in the next
    unless it is still the same session.
  • A kept round is kept verbatim: if the read itself is huge, the run keeps paying for it. That is what
    "keep" means, and the tool layer's own truncation is what bounds a single result.

Follow-ups

Refs #306, #168

The last increment of B5, and the one its acceptance had to be rewritten for:
`/drop <path>` cannot remove a run's tool results, because those live inside
Run and the TUI refuses commands while a run is active. The decision therefore
moves to where it can be made — before the run.

`Agent.KeptPaths` names files whose tool reads must survive compaction.
`compactRunMessages` walks the rounds it would summarize and keeps any round
whose `tool_calls` arguments mention a kept path, verbatim, after the compaction
marker and before the recent tail. A run whose every round is kept is left alone
and costs no summary call. The list travels with the session
(`session.Session.KeptPaths`), so `--resume` keeps the rule.

Commands: `/keep <path>`, `/keep` (list), `/unkeep <path>`, all refused while a
run is active — the run's compaction reads that list.

Verified: go test ./... -count=1 and -race, 16 packages ok; go vet and gofmt
clean; both load-bearing paths mutation-checked — disabling the kept-round check
fails "the kept read was summarized away", and dropping the persist line fails
"the session kept []".

Refs #306, #168
@yusiwen yusiwen added the feature A new capability rather than an improvement to existing behaviour label Oct 31, 2026
The palette grew by two entries with S4's commands, and at 80x24 the "Commands:"
heading now scrolls off the list before the list scrolls. The scenario's first
wait was on that heading, so it timed out with the palette correctly open.

It waits on "Show help" — the first entry — instead: that is what "the palette is
open" means, and it does not depend on the list fitting one screen. Run locally
through tuiprobe: 13 steps, exit 0.

Refs #314
@yusiwen
yusiwen merged commit 08a078f into master Oct 31, 2026
9 checks passed
@yusiwen
yusiwen deleted the feat/kept-paths branch October 31, 2026 14:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature A new capability rather than an improvement to existing behaviour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant