fix(session): preserve live comments across daemon-driven reloads#278
fix(session): preserve live comments across daemon-driven reloads#278mvanhorn wants to merge 1 commit intomodem-dev:mainfrom
Conversation
Greptile SummaryThis PR fixes a bug where
Confidence Score: 5/5Safe to merge — the change is a one-line targeted fix to an established, tested code path with no side effects on unrelated behaviour. The daemon reload path now matches the behavior of the interactive No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant Daemon as Daemon / Agent
participant Bridge as bridge.ts (createHunkSessionBridge)
participant AppHost as AppHost.tsx (reloadSession)
participant App as App component
Daemon->>Bridge: "dispatchCommand(reload_session, { sourcePath })"
Note over Bridge: OLD: forwarded only sourcePath<br/>NEW: also passes resetApp: false
Bridge->>AppHost: "reloadSession(nextInput, { resetApp: false, sourcePath })"
AppHost->>AppHost: setActiveBootstrap(nextBootstrap)
alt "resetApp !== false (OLD behaviour)"
AppHost->>App: setAppVersion(v+1) full remount, state lost
else "resetApp === false (NEW behaviour)"
AppHost-->>App: no remount, liveCommentsByFileId preserved
end
AppHost-->>Daemon: ReloadedSessionResult
Reviews (1): Last reviewed commit: "fix(session): preserve live comments acr..." | Re-trigger Greptile |
Summary
hunk session reload(the daemon-driven reload path) was wiping the in-memory live-comment state. After this PR, daemon reloads preserve live comments the same way therkeystroke and watch-mode auto-reload already do.Why this matters
Per #212, after an agent annotates the diff with hunk-level comments, calling
hunk session reload(from a second terminal or from another agent message on the same session) reloaded the diff and dropped every annotation the user was actively reviewing. The maintainer confirmed the behavior in the issue comment: "Thanks for sharing. This is definitely a problem."The root cause is in
src/hunk-session/bridge.ts:70: thereload_sessionhandler forwardedsourcePathbut notresetApp.AppHost.tsx:63treats undefinedresetAppas truthy (options?.resetApp !== falseistrue), which incrementsappVersion, remounts<App />, and discards the React state inuseReviewController-- includingliveCommentsByFileId. The interactiverreload and watch-mode reload both passresetApp: false(seeApp.tsx:354), so they preserve state; only the daemon path didn't.Changes
src/hunk-session/bridge.ts: thereload_sessionhandler now passesresetApp: falsealongsidesourcePath, matching the contractApp.tsx:354already uses. The handler type now also acceptsresetAppso future opt-in-to-hard-reset is a one-line addition.src/hunk-session/bridge.test.ts: extended the existing dispatch test with an exact-match assertion viatoHaveBeenCalledWith({ resetApp: false, sourcePath: "/repo" })-- exact match so accidental regression to the oldundefined-passing behavior is caught.src/ui/AppHost.interactions.test.tsx: new higher-level test that writes a live comment, dispatches areload_sessionafter rewriting the right-hand file, and asserts both the new content and the original review note appear in the rendered frame.Testing
bun run typecheck-- cleanbun run format:check-- cleanbun run lint-- clean (0 warnings)bun test ./src/hunk-session/bridge.test.ts ./src/ui/AppHost.interactions.test.tsx-- 45 pass, 0 failhunk diffin one terminal, write a live comment via the session bridge, runhunk session reloadfrom a second terminal -- the comment persists across the reload.Residual risk: an agent that explicitly wanted a hard reset on
reload_sessionloses that capability. The handler type now acceptsresetApp, so an explicit opt-in wire flag is a follow-up if anyone needs it.Fixes #212
AI was used for assistance.