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's session.diff() handler builds its agent-touched-file filter from two sources: tool filediff metadata (clean — records exactly what the agent's edit/write/patch/apply_patch tools modified) and patch part file lists (contaminated — captures all worktree changes between step-start and step-finish snapshots, including modifications by other sessions or external processes). The contaminated source causes the tab to show files the current session never edited.
Approach — Remove the patch part file lists from the agentFilesAbsolute set in session.diff(). Derive the filter exclusively from tool filediff metadata. The patch parts retain their snapshot hashes (used for the from/to diff range) but their files arrays no longer feed the filter.
Scope — in: the session.diff() handler's file-filter loop, two new tests. out: the processor's patch-part emission (unchanged), the patch-part schema (unchanged), client-side code.
Acceptance Criteria
A session with no edit/write/patch/apply_patch tool calls shows zero files in the Files Changed tab — the session.diff() endpoint returns an empty array
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 — not from patch-part file lists
Concurrent sessions editing different files do not leak files into each other's Files Changed tabs
Existing sessions with contaminated patch parts in the DB retroactively show correct (filtered) results
Testing Decisions
Zero-edits test (new): construct a session with only read/grep/glob tool parts and patch parts containing file lists — assert session.diff() returns an empty array
Contamination test (new): construct a session with patch parts listing files A, B, C alongside tool parts with filediff metadata for file A only — assert session.diff() returns only file A
Key Decisions
Filter at the query handler, not the event emitter. The patch/step-end data in the processor is left unchanged — no backward compatibility concerns with existing DB records. The fix is a single loop change in session.diff().
Snapshot hashes on patch parts still used. The from/to diff range computation reads step-start and step-finish snapshot hashes from their respective parts — these are independent of the patch.files array and remain the source of truth.
Constraints & Invariants
The patch/step-end part schema is unchanged — no migration needed
The diff query contract (GET /session/:id/diff) returns only agent-touched files, never workspace-wide changes
The fallback chain (summary diffs, tool-part accumulation) continues to work for sessions lacking filediff metadata
Prior Art
The session.diff() handler in the opencode server's session/session.ts (lines 838-998)
Important
Problem — The Files Changed tab's
session.diff()handler builds its agent-touched-file filter from two sources: toolfilediffmetadata (clean — records exactly what the agent's edit/write/patch/apply_patch tools modified) andpatchpart file lists (contaminated — captures all worktree changes between step-start and step-finish snapshots, including modifications by other sessions or external processes). The contaminated source causes the tab to show files the current session never edited.Approach — Remove the
patchpart file lists from theagentFilesAbsoluteset insession.diff(). Derive the filter exclusively from toolfilediffmetadata. Thepatchparts retain their snapshot hashes (used for the from/to diff range) but theirfilesarrays no longer feed the filter.Scope — in: the
session.diff()handler's file-filter loop, two new tests. out: the processor's patch-part emission (unchanged), the patch-part schema (unchanged), client-side code.Acceptance Criteria
session.diff()endpoint returns an empty arraypatchparts in the DB retroactively show correct (filtered) resultsTesting Decisions
patchparts containing file lists — assertsession.diff()returns an empty arraypatchparts listing files A, B, C alongside tool parts withfilediffmetadata for file A only — assertsession.diff()returns only file AKey Decisions
session.diff().from/todiff range computation readsstep-startandstep-finishsnapshot hashes from their respective parts — these are independent of thepatch.filesarray and remain the source of truth.Constraints & Invariants
GET /session/:id/diff) returns only agent-touched files, never workspace-wide changesfilediffmetadataPrior Art
session.diff()handler in the opencode server'ssession/session.ts(lines 838-998)Source
Part of #741 · Follow-up to #733