Skip to content

Replace 'Files Changed' with session-scoped agent changes #174

Description

@jeonghun-jj-lee

Important

Problem: The Files Changed panel currently shows git working-tree diffs — all uncommitted changes regardless of source. This is noise when the user cares about what this session's agent actually wrote.

Approach: Replace the git/branch/turn mode system entirely with a single session-scoped view. Compute a net diff (session-start snapshot vs current state) filtered to only files the agent touched (via PatchParts). Reuse the existing snapshot infrastructure and file tree UI.

Scope: Backend: revive Session.diff with snapshot-based net-diff logic. Frontend: remove VCS mode machinery, wire the panel to the session diff endpoint. No new dependencies.

Assumptions: Snapshot tree hashes survive for the session's lifetime (GC is 7 days; sessions rarely outlive that). Bash-authored files are captured via PatchParts (snapshot-based, not tool-metadata-based).


Acceptance Criteria

  • The Files Changed panel shows only files written by the agent during the current session
  • The diff shown is the net diff (state at session start vs current state), not per-turn patches
  • A file tree is rendered on the left with A/D/M badges; selecting a file shows its diff on the right
  • No git/branch/turn mode selector exists in the UI
  • A session with no agent file changes shows an empty state ("No changes yet")
  • Files touched via Bash (e.g. sed, mv) are included (PatchPart captures them)
  • Files the agent edited then externally reverted show no diff (filtered out when additions + deletions === 0)
  • Sessions older than snapshot GC (7 days) gracefully show empty state

Key Decisions

Decision Choice Rationale
Mode system Remove entirely User only wants session context; git/branch are noise
File set source Union of PatchPart.files across session Captures all agent-authored files including Bash writes
Diff computation snapshot.diffFull(firstStepStart, current) Gives true net diff; reuses existing infra
Filtering Intersect diffFull result with PatchPart file set Excludes external changes that happened to land in the snapshot window
Empty/stale session Return [], render empty state Graceful degradation, no error

Implementation Sketch

Backend (packages/opencode/src/session/)

  1. Session.diff — replace the stub with:

    • Query all messages + parts for the session
    • Extract first step-start hash (session-start ref)
    • Union all PatchPart.files (agent-touched set)
    • snapshot.track() for current state
    • snapshot.diffFull(from, to) filtered to agent-touched files
    • Filter out zero-change entries
  2. HTTP handlerGET /session/:sessionID/diff already wired; just returns the revived Session.diff result

Frontend (packages/app/src/pages/session.tsx + side panel)

  1. Remove reviewMode signal and ChangeMode type
  2. Remove vcsQuery (the sdk().api.vcs.diff(...) call)
  3. Replace reviewDiffs() with a single query to sdk().api.session.diff(sessionID)
  4. Re-fetch on file.watcher.updated events (same trigger as before)
  5. File tree + diff viewer stay as-is, fed by the new data source
  6. Empty state when diffs.length === 0

TUI (packages/tui/)

  • Remove mode selector from diff-viewer
  • Point at session diff endpoint

Constraints & Invariants

  • Snapshot tree objects must exist for the session's first turn (GC = 7 days)
  • PatchPart is the canonical source of "which files the agent touched" — no alternative tracking needed
  • The file tree component (file-tree-v2.tsx) and diff viewer are untouched — only their data source changes

Metadata

Metadata

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions