Skip to content

fix(changes): bound the Changes panel by files, not by mutations - #1049

Open
L4XB wants to merge 1 commit into
Gentleman-Programming:mainfrom
L4XB:fix/1043-session-changes-coalesce-by-path
Open

L4XB wants to merge 1 commit into
Gentleman-Programming:mainfrom
L4XB:fix/1043-session-changes-coalesce-by-path

Conversation

@L4XB

@L4XB L4XB commented Sep 15, 2026

Copy link
Copy Markdown

Fixes #1043

The problem

The Changes panel shows files. The cap counted mutation evidence records:

if (this.seen.size >= MAX_RECORDS || this.bytes + bytes > MAX_SESSION_BYTES) {

seen holds one toolCallId per admitted write/edit, so every repeat edit of a file already on screen spent one of the 256 slots. A long SDD session that touches a handful of files over and over reaches the warning while the panel lists maybe five entries, which is what the report describes.

The second half is what made it look frozen rather than merely capped. Once the bound fired, a later edit to a file the panel was already showing was dropped too, so that entry sat at its last admitted state. Refusing it bounded nothing: the FileState it would have updated is already held in files.

The fix

MAX_RECORDS becomes MAX_FILES, checked against the number of distinct paths held, and only for a path that is not held yet:

let files = this.files.get(evidence.root);
const previous = files?.get(evidence.path);
if (!previous && this.trackedFiles >= MAX_FILES) {
  this.notice = FILE_LIMIT_NOTICE;
  return false;
}

An edit to a tracked file is now always admitted. What a long session can accumulate is still bounded, by the 4 MiB snapshot budget, which is unchanged.

The two bounds also stop sharing one sentence. The report asks for this and it is right: they have different remedies, and "additional changes are not displayed" told an operator neither which one filled up nor that the session itself was fine.

files:  Session change capture limit reached; 256 files are shown and later files
        are not tracked. Earlier files keep updating.
bytes:  Session change capture limit reached; the snapshot budget is full and
        later changes are not captured.

Tests

tests/session-changes.test.ts, five cells added, and the existing 257-unique-path cell is untouched and still passes, since the bound is the same number for that shape.

cell what it stops
many edits to few files never reach the cap the reported defect: 600 edits across 3 files, no notice, and a fourth file still admitted afterwards
a tracked file keeps updating after the cap fires the staleness half, which a cap alone would leave in place
the notice names which bound fired both bounds collapsing back into one sentence
a no-op edit to an unseen path does not spend a slot before === after being charged for a file it never tracked

Mutation results, 6 of 6 caught:

mutation result
the cap counts records again (the reported defect) caught
a known file is refused once the cap is reached caught
the file counter never advances caught
the counter advances on every record, not only a new file caught
both bounds share one notice again caught
the byte budget is not enforced caught

The fourth is worth naming. Advancing the counter per record rather than per new file passes every other assertion in the file, and only surfaces as a new file being refused after 256 repeat edits, which is the original defect moved one line over. The first version of my own test did not catch it; the extra assertion in the many-edits cell is there because the mutation run said so.

pnpm run typecheck: 200 recorded diagnostics, no regressions. tests/session-changes.test.ts and tests/session-changes-shell.test.ts: 17 pass.

What this does not change

The cap is still 256 and still hard. A session that genuinely touches more than 256 distinct files gets the same refusal, now with a notice that says so and does not imply the run failed. Coalescing without any bound was the other option in the report; I did not take it, because the panel's memory would then follow the session's file count with nothing holding it.

Summary by CodeRabbit

  • Bug Fixes

    • Session changes are now limited by the number of distinct files rather than the number of individual edits.
    • Repeated edits to already tracked files continue to be captured, even after the file limit is reached.
    • Capacity notices now clearly identify whether the file-count or snapshot-size limit was reached.
  • Tests

    • Added coverage for file-based limits, continued updates, available capacity, and no-op edits.

The panel shows files; the cap counted mutation evidence records, so every
repeat `write`/`edit` of a file already on screen spent one of the 256 slots. A
long session hit `Session change capture limit reached` while tracking a
handful of files, and from then on nothing updated: a later edit to a file the
panel was already showing was dropped too, so its entry sat at the last
admitted state (Gentleman-Programming#1043).

`MAX_RECORDS` becomes `MAX_FILES` and is checked against the number of distinct
paths held, and only for a path that is not held yet. An edit to a file already
on screen is always admitted, because refusing it bounded nothing: the entry it
would have updated is already in memory. What a long session can accumulate is
bounded by the 4 MiB snapshot budget, which is unchanged and now reports
separately.

The two bounds also stop sharing one sentence. They have different remedies,
and "additional changes are not displayed" told an operator neither which one
filled up nor that the session itself was fine.

Five cells: many edits to few files never reach the cap and still leave room for
a new file, a tracked file keeps updating after the cap fires, the notice names
which bound fired, and a no-op edit to an unseen path does not spend a slot.
The existing 257-unique-path cell is unchanged and still passes, since the
bound is the same number for that shape.

Six mutations, all killed. One is worth naming: advancing the counter per
record rather than per new file passes every other assertion and only shows up
as a new file being refused after 256 repeat edits, which is the original
defect moved one line over.
@coderabbitai

coderabbitai Bot commented Sep 15, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 54dde1b3-3b31-4cc7-a959-ef63c8af6dc7

📥 Commits

Reviewing files that changed from the base of the PR and between 0da9bcc and 6ddf459.

📒 Files selected for processing (2)
  • lib/session-changes.ts
  • tests/session-changes.test.ts

Included review availability: Your plan provides up to 4 included reviews per hour; 2 remain after this review.


📝 Walkthrough

Walkthrough

Session change capture now limits distinct tracked files instead of mutation records. Repeated updates to tracked files remain admissible. File-count and byte-budget limits emit separate notices, with regression tests covering both limits and no-op edits.

Changes

Session capture limits

Layer / File(s) Summary
Distinct-file admission logic
lib/session-changes.ts
The capture limit now counts admitted file paths. Updates to tracked files bypass the file-count limit. File-count and byte-budget notices use separate messages.
Limit behavior regression coverage
tests/session-changes.test.ts
Tests cover repeated edits, capacity for new files, updates after the cap, distinct notices, and unseen no-op edits.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: alan-thegentleman

Merge Risk: ⚪ Minimal · up to 6ddf4

The updated file-limit behavior is covered without a remaining actionable defect.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: the Changes panel is limited by distinct files instead of mutation records.
Linked Issues check ✅ Passed The changes satisfy the coding requirements in issue #1043. SessionChanges.record() tracks capacity with trackedFiles, so repeated edits to an existing root/path do not consume the 256-file limit.…
Out of Scope Changes check ✅ Passed The reviewed changes are limited to lib/session-changes.ts and tests/session-changes.test.ts. The implementation and tests directly support issue #1043 by changing file-capacity behavior and valid…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

bug(changes): session change capture stops after 256 write/edit records

1 participant