Skip to content

feat(core): compute real session-level modified-files diff - #71

Closed
quickbeard wants to merge 4 commits into
mainfrom
session-diff
Closed

quickbeard wants to merge 4 commits into
mainfrom
session-diff

Conversation

@quickbeard

@quickbeard quickbeard commented Jul 14, 2026 •

Copy link
Copy Markdown
Owner

What

SessionSummary.summarize now computes the whole-session snapshot diff — computeDiff over all session messages (first step-start snapshot → last step-finish snapshot), reusing the already-computed turn diff for single-turn sessions — and publishes it via Session.Event.Diff together with real session.summary additions/deletions/files aggregates. GET /session/{id}/diff without a messageID (the hydrate path used by both the TUI and the web app) returns the computed session-wide diff instead of [].

This lights up three dormant surfaces at once, with zero client changes:

Upstream publishes a permanently empty session-level diff (summary.ts hardcodes diff: []; only session revert carries data). That was a deliberate perf fix — anomalyco/opencode#30127 removed automatic full-session diffs after a snapshot-heavy historical session recomputed a multi-megabyte diff every turn — so this is a fork-only divergence, documented in DIVERGENCES.md. We accept the recompute cost: the single-turn reuse covers the common case, and counts-only publishing (patch is optional in the schema) is the follow-up lever if large sessions bite.

Details:

  • Single publish per summarize (no upfront empty publish → no sidebar flicker mid-computation); clearing paths (snapshots disabled, no messages, missing target) still publish zeros/empty.
  • All returned/published paths go through a shared unquoteDiffs (git C-quoting), matching the existing per-message endpoint behavior.
  • Legacy session_diff storage rows are still never read back, preserving the #26574 regression guard; that test's stale header comment updated.
  • New no-mock test test/session/summary.test.ts (real git snapshots, modeled on revert-compact.test.ts): multi-turn session-wide diff + counters, single-turn reuse path, and the clearing path.

Known limitations (accepted)

  • Session.Event.Diff now ships full patches per step-finish; share-next forwards it verbatim — larger SSE/share payloads on big sessions (upstream revert already ships full patches on this event).
  • Multi-turn sessions pay a second diffFull per step-finish (serialized behind the snapshot lock); debounce is a follow-up if it ever shows in traces.
  • Share full-sync still uses the Session.diff [] stub, so a freshly shared idle session shows an empty diff until its next activity.
  • While a session sits reverted, a fresh hydrate recomputes over still-present messages rather than the revert-range diff from the last event; self-heals on the next prompt (upstream showed [] there).

Verification

bun typecheck + test/session/summary.test.ts, test/server/session-diff-missing-patch.test.ts, test/session/revert-compact.test.ts, test/snapshot/snapshot.test.ts, test/share/share-next.test.ts all green from packages/opencode.

Live TUI run (tmux, scratch git project, real model turns): agent edits 2 files → footer hint shows ctrl+b 2 modified files, sidebar lists both files with +1 -1; a later turn restoring one file to its original content drops it from the list (net diff, matches git status); TUI restart + -c reopen shows 1 modified file from the hydrate path, which previously always returned empty.

🤖 Generated with Claude Code

quickbeard and others added 4 commits July 14, 2026 11:19
SessionSummary.summarize now computes the whole-session snapshot diff
(computeDiff over all messages, reusing the turn diff for single-turn
sessions) and publishes it via Session.Event.Diff along with real
session.summary aggregates, instead of upstream's unconditional
zeros/empty diff. The GET /session/:id/diff endpoint without a
messageID returns the computed session-wide diff instead of [].

This lights up the TUI sidebar "Modified Files" section, the
prompt-footer files hint (#69), and the web app's session diff, all of
which upstream leaves permanently empty (only revert published data).
Clearing paths (snapshots disabled, no messages, missing target) still
publish empty; legacy session_diff storage rows are still never read
back (#26574 guard preserved).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@quickbeard quickbeard closed this Jul 28, 2026
@quickbeard
quickbeard deleted the session-diff branch July 28, 2026 07:08
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.

1 participant