Repository navigation
🤖 fix: an open edit loses its typed changes on a workspace switch (#5801), plus two older edit races #5808
Description
Activity
- changed the title
[-]🤖 fix: edit-mode follow-ups after #5801 (workspace switch drops edit text, notes leak, Stop restore race)[/-][+]🤖 fix: an open edit loses its typed changes on a workspace switch (#5801), plus two older edit races[/+]on Oct 6, 2026 Found by the normal review of #5801's repair head
72a15a919c(the fix for item 1 is on that branch). #5801 is parked. These must be fixed before it can merge:- Transcript-only switch during an edit loses the edit's typed changes (introduced by 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801). ChatPane swaps ChatInput for the transcript-only notice and clears the edit target, so the memory-only buffer is orphaned. Fix idea: release the buffer into the normal draft (after the unsent draft, as
releaseEndedEditdoes) before the composer is replaced. Thread: 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801 (comment) - A second Edit during an open edit overwrites the first edit's buffer (introduced by 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801).
beginEditingMessagechecks only a pending edit send, andbeginEditDraftwith a new id replaces the buffer. Fix idea: release the open edit first, or keep Edit disabled while an edit is open. Note: this overlaps item 2 above (the note leak on a second edit). A fix here can cover both. Thread: 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801 (comment) hasOlderHistoryguard (tradeoff). An edit whose row another renderer really deleted stays open until its send is refused (history-changed). The refresh then releases the text, so nothing is lost. Fix idea: tell an unloaded row from a deleted one, using the target's history sequence against the loaded window or a backend check. Thread: 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801 (comment)
Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$49.02- Transcript-only switch during an edit loses the edit's typed changes (introduced by 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801). ChatPane swaps ChatInput for the transcript-only notice and clears the edit target, so the memory-only buffer is orphaned. Fix idea: release the buffer into the normal draft (after the unsent draft, as
#5801 is parked again at
e8acc69cd8, after its last allowed repair push.That push added one rule: an edit that loses its target without a settle keeps its text and files in the draft, after the unsent draft. It covers transcript-only, a second Edit, a deleted row and target-not-found, and it addresses item 1 and the overlap with item 2. #5801 is not merged, so nothing here is resolved on main.
The normal review then found three new defects in the same design. The edit outlives a composer remount (a workspace switch), but some composer-local state does not survive with it:
- Duplicate edit send: a remounted composer can send the same edit again while the first send is in flight.
sendingCountis local state, andcanSendignores the restored session'ssendInFlight. 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801 (comment) - Review notes: a send accepted after a switch away and back restores the notes only in the unmounted composer, so the edit's notes stay as the override. 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801 (comment)
- Refresh retry: a failed history refresh loses its retry state on a switch away and back, so Send stays disabled with no retry button. 🤖 fix: an edit keeps its text in memory, so the unsent draft survives a reload and stays out of other windows #5801 (comment)
Re-plan before more code: keep all of the edit's per-edit state with one owner that survives the remount (the send in flight, the review restoration, the refresh retry), or end the edit on a switch and keep its contents in the draft with the same preservation rule. The second option is simpler: it gives up "the edit resumes after a switch" but keeps every typed change.
Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$54.92- Duplicate edit send: a remounted composer can send the same edit again while the first send is in flight.
- addedinvestigationTriage: proposal / research / trackingTriage: proposal / research / tracking
on Oct 9, 2026
Follow-ups from the final readiness check of PR #5801 (edit text lives only in the composer's memory, #5672 / #5571).
1. A workspace switch drops an open edit's typed changes (introduced by #5801, blocks it)
What happens: you open an edit, type changes (text, attachments), switch to another workspace, and come back. The edit reopens with the original message text, and the typed changes are gone.
Cause: ChatInput is keyed by workspace (
ChatPane.tsx~2011), so a switch remounts it. ChatPane keepseditingStateper workspace (~381-386), so the edit itself survives the switch. The memory-only edit buffer lives in the remounted ChatInput (useComposerDraft), so the buffer does not survive. When you come back, the composer refills the edit from the original message (ChatInput/index.tsx~1448).On main the edit text survived a switch but replaced the unsent draft. #5801 keeps the unsent draft but loses the edit changes. The accepted tradeoff of #5801 covers reload only.
Fix idea: give the edit buffer a stable per-workspace, memory-only owner that survives the ChatInput remount (next to ChatPane's
editingState, or an equivalent). It must survive workspace switches, stay out of other windows, and still disappear on reload. Failing-first test: switch away and back with edit text and an attachment, and check that the edit keeps both and the unsent draft stays intact.2. Starting a second edit while one is open leaks the first edit's notes (pre-existing on main, not part of the #5801 repair)
beginEditingMessagedoes not check for an open edit (ChatPane.tsx~416-427). The new session snapshotspreEditReviews: draftReviews(index.tsx~1444), and those are the first edit's notes. Cancelling the second edit then puts the first edit's notes on the unsent draft. Main had the same snapshot.3. A Stop restore can race with opening an edit (pre-existing on main, narrow, not part of the #5801 repair)
A restore event that arrives before the edit opens, with its async
acceptedSendIdslookup resolving after (index.tsx~1632), skips the edit check (~1656).setInput(mergedText)(~1665) then replaces the edit buffer, and a later cancel loses the restored text. Main lost it in the same race.Generated with
xum• Model:anthropic:claude-opus-5-5• Thinking:high• Cost:$35.15