Confirm text-stage regeneration against unsaved edits with an inline diff - #3424
Merged
Conversation
… diff (#3398) The dirty gate on text-stage Generate blocked the button outright once the output editor diverged, so there was no way to see what the new version would have been without first saving or discarding. Generate now stays live while dirty: it opens an inline confirm row, and the result is held in an InlineDiff against the live editor text instead of being written into the textarea. Apply replaces the editor text; keeping the edits leaves them exactly as typed (still dirty against the newly persisted output, so Save pushes them back over it). The generated stage is lifted to the parent either way -- the server already persisted it, so run history stays truthful -- and the parent-driven reset effect is suppressed for the record under review only, so switching issue or stage drops the pending comparison and reloads normally.
…t a kickoff snapshot Three review findings on the #3398 flow: - The decision to open the diff was snapshotted when the request was sent, so text typed while a multi-minute generate was in flight was silently replaced. The check now runs at resolve time against the persisted text the run started from, using a ref for the current draft. - A result landing after the panel moved to another issue/stage could open a review over the record now on screen. The pending review carries the record it belongs to and is both set and rendered under that key. - "Generate & compare" skipped the gates its Generate counterpart has -- the confirm row can sit open while a save or settings write starts -- so it now disables on generating/saving/actionsGated, and the row hides once the edits it was warning about are gone.
…nerate on an in-flight save Review round 2: - A generation that resolved after the panel switched issue/stage still called onStageUpdate, so issue A's result patched whichever record was on screen. It now returns before the lift (the run is persisted server-side, so the toast still fires) instead of only skipping the diff review. - Generate stayed clickable while a save PATCH was in flight -- reachable with a seed-only edit, since the dirty routing keys on output drift -- letting the save and the generation write race the same stage record. It now disables on `saving` like its confirm-row counterpart.
atomantic
force-pushed
the
claim/issue-3398
branch
from
August 3, 2026 20:17
506d0f6 to
376a29d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Text-stage Generate was hard-disabled once the output editor went dirty ("Save or discard your edits first"), which turned "you might lose your edits" into "you can't generate at all" — with no way to see what the new version would have been.
StageHistoryModalonly diffs persistedrunHistory, so an unsaved draft had nothing to compare against.Generate is live again while the editor is dirty, behind a two-step flow in
TextStagePanel.jsx:alert/confirm, per the repo's confirmation-UX convention.InlineDiffagainst the live editor text (not a kickoff snapshot, so typing while the review is open keeps the comparison honest) rather than being written into the textarea. Use new version applies it; Keep my edits leaves the text exactly as typed — still dirty against the newly persisted output, so Save pushes the user's version back over it.Details worth calling out:
onStageUpdateeither way — the server already persisted the run, sorunHistory/lastRunIdstay truthful while the user decides.issue.id:stageId); switching issue or stage drops the pending comparison and reloads normally.serverGeneratingstill syncs unconditionally so a held review can't strand the spinner.outputDirtysignal and the existingInlineDiffcomponent; no new diff rendering and no parallel dirty tracking.Closes #3398
Test plan
cd client && npm test— 530 files / 6095 tests pass.TextStagePanel.test.jsxgains aregenerate-over-unsaved-edits review (#3398)block covering: the diff appears and the editor keeps the unsaved text; applying replaces the editor text and dismisses the diff; canceling preserves the unsaved edits and re-enables Save; identical text skips the review; the stage is still lifted to the parent while the review is open.npx eslintclean on the touched files.Review follow-ups (codex, 2 rounds → clean)
onStageUpdate(which would patch whichever record is on screen now).generating/actionsGated/saving; the confirm row hides once the edits it warned about are gone. The save gate is reachable with a seed-only edit, since the dirty routing keys on output drift.