Skip to content

fix(app): remove per-message Changed files section from chat output #733

Description

@jeonghun-jj-lee

Important

Problem — Two issues with the "Changed files" surfaces:

  1. Noise. Every completed assistant turn appends a collapsible "N Changed files +X −Y" section at the bottom of the chat. This is redundant with the side-panel Files Changed tab (file tree, inline diffs, search) and noisy — a long session pushes dozens or hundreds of file rows into the conversation, displacing actual content.

  2. Cross-session leak. File changes bleed across sessions. The snapshot system uses one shadow git repo per project (~/.local/share/opencode/snapshot/<project-id>/<worktree-hash>/), shared by all sessions. snapshot.track() captures the full working tree, so when sessions run concurrently, diffFull(step-start, step-finish) includes files changed by other sessions (or manual VS Code edits) between those two points.

Approach — Two changes:

  • Overlay (amicode): Suppress the per-message DiffSummary timeline row in the row builder. Leave the rendering code, CSS, and i18n keys in place (dead but harmless). Guard the equivalent v1 session-turn-diffs section.
  • Fork (harmoniqs/opencode, follow-up): Add agent-file filtering to summary.ts:computeDiff — mirror the agentFiles filter that Session.diff already applies in its primary path. This fixes the stored message.summary.diffs data (consumed by the side-panel's Fallback 1) and prevents the leak at the source.

Scope — in: suppress DiffSummary row in v2 timeline builder (rows.ts), guard v1 session-turn-diffs (session-turn.tsx). out: side-panel Files Changed tab, inline Edited-files tool groups, server-side summary.diffs computation, CSS/i18n cleanup (follow-up).

Assumptions — The v2 timeline layout is the active layout (dev channel, newLayoutDesigns default ON). The v1 path is guarded for completeness but is not the primary surface.

Acceptance Criteria

  • Completed assistant turns no longer show the "N Changed files" collapsible section at the bottom of the chat message
  • The side-panel Files Changed tab continues to show per-session file diffs correctly
  • Inline "Edited files" tool groups (mid-message, per-tool-call) still render normally
  • Existing tests pass (pnpm --filter amicode test)

Testing Decisions

Extend no new test suite — the overlay change is a deletion. Verify visually that the section is absent after an edit-heavy session and that the side panel still works. Existing overlay and parity tests cover the surrounding components.

Key Decisions

  • Suppress, don't delete the renderer. The TimelineDiffSummaryRow component and its DiffSummary case in the timeline switch stay as dead code. This keeps the diff small and makes reversal trivial. A follow-up can clean up the dead code, CSS (session-turn-diffs selectors in session-turn.css), and orphaned i18n keys (ui.sessionTurn.diffs.*).
  • Fork mirroring required. The overlay files are overwritten on each opencode:pin re-extraction. The same change must land in harmoniqs/opencode before the next pin bump, or the section will reappear.

Cross-session leak analysis

The snapshot diff pipeline has three layers with different isolation properties:

Surface Data source Leaks? Why
Per-message "Changed files" summary.ts:computeDiff (unfiltered snapshot diff) Yes No agent-file filter
Side panel (primary path) Session.diff with agentFiles filter Partial Same-file concurrent edits share the cumulative diff
Side panel (Fallback 1) Aggregated message.summary.diffs Yes Inherits per-message leak
Side panel (Fallback 2) Tool part filediff metadata No Session-scoped
Touched-files endpoint Tool part scan No Session-scoped
Client-side fallback accumulateDiffs from loaded tool parts No Session-scoped

Root cause: summary.ts:computeDiff returns raw snapshot.diffFull(from, to) with no filtering by agent-touched files. The fork fix is to collect agentFiles from the turn's tool part filediff metadata (the same scan Session.diff does) and filter the result. This also fixes Fallback 1 by inheritance.

Constraints & Invariants

  • Server-side summary.diffs computation must remain intact — the side panel and future consumers depend on it.
  • The EditToolGroup component (inline "Edited files" groups during a live turn) is a separate code path and must not be affected.

Prior Art

  • Timeline row builder: packages/app-bundle/overlay/packages/app/src/pages/session/timeline/rows.ts
  • v1 session turn: packages/app-bundle/overlay/packages/session-ui/src/components/session-turn.tsx
  • Side-panel review: packages/app-bundle/overlay/packages/app/src/pages/session/v2/review-panel-v2.tsx
  • Server diff (with filter): packages/opencode/src/session/session.ts Session.diff
  • Server diff (no filter): packages/opencode/src/session/summary.ts computeDiff

Notes

The per-message diffs section is an upstream opencode feature (introduced Feb 2026). The side-panel Files Changed tab is the preferred surface for reviewing file changes. The cross-session leak affects any project with concurrent sessions (spawned tabs, parallel agents) or external file edits during a turn.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions