You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Problem — The Files Changed tab shows files that the current session's agent never edited. The root cause is the step-end event capturing all worktree changes between step-start and step-finish snapshots — including modifications by other concurrent sessions or external processes — and recording them as the session's changed files. The session.diff() endpoint trusts these records as the agent-touched-file filter, so the contamination propagates to the UI. Additionally, when the user reverts or further modifies an agent-edited file outside the agent's tools, the tab does not update — it only refreshes on agent tool completions and session status transitions, missing all external changes.
Approach — Three changes. (1) Fix the contamination by deriving the agent-touched-file filter in the server's session.diff() handler exclusively from tool filediff metadata, ignoring the workspace-wide file lists in patch/step-end parts. (2) Add external-change reactivity by removing the OPENCODE_EXPERIMENTAL_FILEWATCHER enable-gate (preserving the disable-gate as opt-out), adding a new file.watcher.updated handler in the client event-reducer that cross-references incoming events against the session's agent-touched file set, and debouncing a diff_version bump (1s trailing-edge). (3) Add a manual refresh button in the panel toolbar as a fallback.
Scope — in: contamination fix in the server's session.diff() handler, watcher flag cleanup, new client-side file.watcher.updated event handler, refresh button in the panel toolbar, new refresh icon SVG in the icon sprite. out: fixing patch/step-end part data at the processor source (existing records stay as-is), server-side per-session file tracking beyond the existing touchedFiles endpoint, showing user-only edits to files the agent never touched, detecting file deletions via bash rm (see Known Limitations).
Assumptions — @parcel/watcher (FSEvents on macOS, inotify on Linux) is performant enough to run by default on typical repos; the existing watcher.ignore config mitigates large-repo inotify pressure. The agent-touched file set per session is small enough that per-event cross-referencing is negligible. Watcher event paths and touched-file paths can be normalized to the same absolute form for matching.
Acceptance Criteria
A session with no edit/write/patch/apply_patch tool calls shows zero files in the Files Changed tab
A session with edit tool calls shows exactly the files those tools modified (deduplicated by path), with M/A/D status derived from the server's git-state comparison
Concurrent sessions editing different files do not leak files into each other's Files Changed tabs
When a user reverts an agent-edited file externally (Ctrl+Z, git checkout, terminal edit), the Files Changed tab updates automatically (target: within 2s; manual verification, not CI-asserted)
When a user further edits an agent-edited file, the diff content updates automatically (same target)
A refresh button (circular-arrow icon, tooltip "Refresh") appears in the panel toolbar after the Unified/Split toggle and triggers a full diff refetch on click
The @parcel/watcher worktree watch runs by default (OPENCODE_EXPERIMENTAL_FILEWATCHER enable-gate removed); OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHER preserved as opt-out
If @parcel/watcher fails to initialize, the tab continues to work via tool-completion and session-status triggers; the refresh button remains functional; no error is surfaced to the user
Testing Decisions
Extend the existing snapshot/session test suites:
Zero-edits test: construct a session with only read/grep/glob tool parts (no edit tools) and assert the diff response is empty
Contamination test: construct a session with patch parts containing extra files alongside tool parts with filediff metadata; assert session.diff() returns only the filediff files
Watcher reactivity: manual verification (file-system timing makes it flaky in CI)
Key Decisions
Filter at the query handler, not the event emitter. The patch/step-end data in the processor is left unchanged — filtering happens in the server's session.diff() handler. Simpler, no processor changes, no backward compatibility concerns with existing DB records.
New client-side file.watcher.updated handler. The SSE event type exists but the client event-reducer does not currently handle it. A new case is added that cross-references the file path (normalized to absolute) against the session's agent-touched file set and schedules a debounced diff_version bump on match. Watcher events for files not in the touched set are silently discarded — including the agent's own writes (which are already covered by the tool-completion trigger).
1s trailing-edge debounce, per-session. Coalesces rapid external changes into a single refetch. Noted as a tunable, not a permanent decision — a single event (e.g., git checkout) incurs 1s latency with no coalescing benefit; adaptive dispatch could improve this later.
Refresh button in the panel toolbar. Placed after the Unified/Split toggle (right end of toolbarEnd), where its panel-wide scope matches its visual context. Visible even when zero files are shown.
New refresh icon SVG. No circular-arrow icon exists in the current sprite; one must be added.
Known Limitations
Files deleted via bash rm are not captured by the filediff-based filter. The bash tool does not emit filediff metadata, so agent-mediated deletions outside the edit/write/patch/apply_patch tools will not appear in the Files Changed tab. Tracked separately.
Constraints & Invariants
The patch/step-end part schema is unchanged — existing sessions continue to work.
Snapshot hashes on step-start and step-finish parts remain the source of truth for the diff range.
The diff query contract (GET /session/:id/diff) returns only agent-touched files, never workspace-wide changes.
The existing touchedFiles server endpoint (which derives from tool metadata) is the read path; no new server-side per-session tracking state is added.
Tool-completion and session-status triggers remain the baseline reactivity path; watcher-based reactivity is additive.
On session re-open (tab switch, extension reload), the diff is refetched from the server and watcher subscriptions are re-established.
Important
Problem — The Files Changed tab shows files that the current session's agent never edited. The root cause is the step-end event capturing all worktree changes between step-start and step-finish snapshots — including modifications by other concurrent sessions or external processes — and recording them as the session's changed files. The
session.diff()endpoint trusts these records as the agent-touched-file filter, so the contamination propagates to the UI. Additionally, when the user reverts or further modifies an agent-edited file outside the agent's tools, the tab does not update — it only refreshes on agent tool completions and session status transitions, missing all external changes.Approach — Three changes. (1) Fix the contamination by deriving the agent-touched-file filter in the server's
session.diff()handler exclusively from toolfilediffmetadata, ignoring the workspace-wide file lists in patch/step-end parts. (2) Add external-change reactivity by removing theOPENCODE_EXPERIMENTAL_FILEWATCHERenable-gate (preserving the disable-gate as opt-out), adding a newfile.watcher.updatedhandler in the client event-reducer that cross-references incoming events against the session's agent-touched file set, and debouncing adiff_versionbump (1s trailing-edge). (3) Add a manual refresh button in the panel toolbar as a fallback.Scope — in: contamination fix in the server's
session.diff()handler, watcher flag cleanup, new client-sidefile.watcher.updatedevent handler, refresh button in the panel toolbar, new refresh icon SVG in the icon sprite. out: fixing patch/step-end part data at the processor source (existing records stay as-is), server-side per-session file tracking beyond the existingtouchedFilesendpoint, showing user-only edits to files the agent never touched, detecting file deletions viabash rm(see Known Limitations).Assumptions —
@parcel/watcher(FSEvents on macOS, inotify on Linux) is performant enough to run by default on typical repos; the existingwatcher.ignoreconfig mitigates large-repo inotify pressure. The agent-touched file set per session is small enough that per-event cross-referencing is negligible. Watcher event paths and touched-file paths can be normalized to the same absolute form for matching.Acceptance Criteria
git checkout, terminal edit), the Files Changed tab updates automatically (target: within 2s; manual verification, not CI-asserted)@parcel/watcherworktree watch runs by default (OPENCODE_EXPERIMENTAL_FILEWATCHERenable-gate removed);OPENCODE_EXPERIMENTAL_DISABLE_FILEWATCHERpreserved as opt-out@parcel/watcherfails to initialize, the tab continues to work via tool-completion and session-status triggers; the refresh button remains functional; no error is surfaced to the userTesting Decisions
Extend the existing snapshot/session test suites:
patchparts containing extra files alongside tool parts withfilediffmetadata; assertsession.diff()returns only thefiledifffilesKey Decisions
session.diff()handler. Simpler, no processor changes, no backward compatibility concerns with existing DB records.file.watcher.updatedhandler. The SSE event type exists but the client event-reducer does not currently handle it. A new case is added that cross-references the file path (normalized to absolute) against the session's agent-touched file set and schedules a debounceddiff_versionbump on match. Watcher events for files not in the touched set are silently discarded — including the agent's own writes (which are already covered by the tool-completion trigger).git checkout) incurs 1s latency with no coalescing benefit; adaptive dispatch could improve this later.toolbarEnd), where its panel-wide scope matches its visual context. Visible even when zero files are shown.refreshicon SVG. No circular-arrow icon exists in the current sprite; one must be added.Known Limitations
bash rmare not captured by thefilediff-based filter. Thebashtool does not emitfilediffmetadata, so agent-mediated deletions outside the edit/write/patch/apply_patch tools will not appear in the Files Changed tab. Tracked separately.Constraints & Invariants
GET /session/:id/diff) returns only agent-touched files, never workspace-wide changes.touchedFilesserver endpoint (which derives from tool metadata) is the read path; no new server-side per-session tracking state is added.Prior Art
diff_version+ mid-turn refetch mechanism (the existing reactivity infrastructure)Source
Follow-up to #733 (same root cause, different surface)