Repository navigation
fix(desktop): remove Regenerate in favor of edit and resend - #5468
Conversation
a47aea8 to
d561312
Compare
d561312 to
b2a501e
Compare
Astro-Han
left a comment
There was a problem hiding this comment.
Verified the removal end to end — this is a clean excision, and the semantics hold.
Removal is complete. turn.regenerate is gone from TURN_OPERATION_SPECS, TurnRegenerateInput, the remote-owner grant list, the interactive-turn coordinator handler map, prepareRegenerateTurn, RuntimeRegenerateTurnError, normalizeRegenerateTurnInput, the session-execution IPC handler, the client method, and the renderer regenerateTurn port — zero dangling references outside intentional lineage surfaces. The epoch-167 bump correctly rejects old peers that could still submit the operation.
Legacy terminalization is the right shape. The intent decode survives (SessionTurnRegenerateRequestIntent in session-collaboration.ts) — necessary, since durable access requests persisted before the upgrade must still load — while the coordinator now does !('content' in request.intent) → 'failed': approved-but-unexecuted regenerate intents reach a terminal state without executing and without hanging. Admission recovery additionally Excludes kind:'regenerate', so a persisted descriptor can't resurrect on restart. The new test pins exactly this (started === false, admission 'failed').
Replacement path is real, not just deletion. Side Chat's onEditUserMessage finds the user message for the turn and refills the composer via setText + focus — edit-and-resend is genuinely wired. No renderer constructs regenerate intents anymore; the owner approval/history UI is retained only to render legacy pendings, which is correct.
Lineage read-side preserved. regeneratedFromTurnId/regeneratedToTurnId still decode through core session/runtime-event and project through materialize.ts to badges — historical regeneration chains keep rendering.
P3s (none blocking):
packages/ui/src/conversation-copy.ts(~line 934): the truncated-output text still says "Regenerate it or inspect the persisted task log" — user-facing instruction pointing at a removed affordance. Reword to edit-and-resend or drop the clause.packages/ui/src/chat-view.tsx(~line 409): comment still says "a clickable regenerate/branch" — regenerate no longer exists; minor staleness.- Coordination note: #5503 also bumps the epoch to 167 — whichever lands second needs to renumber to 168.
…iew P3s The Regenerate footer fields and their three locale entries were a rebase artifact over apache#5468's removal - the earlier verification grepped the wrong file (packages/ui conversation-copy) and wrongly cleared them; the review's correction is confirmed and this removes the dead copy from the desktop contract (zh-TW typo included). Also closes the review's P3s: the conflict gate decides pending directories before the unchanged check (verbatim text plus a new folder is a real change), the mixed-context refusal copy no longer mentions restored quotes (quote additions pass now), the lifecycle docstrings describe what the code does, the app-shell drops the dead restoreAttachments field and destructure, and the side-chat edit says why it refuses quote- or attachment-bearing messages instead of silently doing nothing. Generated-by: GLM-5.3-Flash (ZCode)
apache#5468 removed the Regenerate feature (87ff279), deleting the footer's `regenerate` label and the `regenerateRunning` / `regenerateAgain` / `regenerate` / `requestRegenerate` keys from the conversation copy. This branch's stale base still carried the block, so the merge-base diff re-adds those keys across the contract type and all three locales (including the zh-TW 本輪迴答 wording) while nothing on current main references them — merging would resurrect dead strings. Drop the block from the type and the zh-CN / zh-TW / en entries, matching the upstream shape exactly; the `lineage.regenerated*` keys are a different, live feature and stay. Generated-by: GLM-5.3-Flash (ZCode)
Review follow-ups (#5274 review): - prepareRevisionSend re-keyed the edit-start snapshot, so quotes the user removed or re-annotated during the edit reappeared on the branch and could be sent. The re-key now lands the plate's current quotes, and the send reads them live (the before-send snapshot retires — the re-key covers its case). - Drops the stale-base footer copy block and a dead regenerate key: no production code on current main references the old footer shape that survived in this branch's base. The no-op gate keeps counting the model-facing comment. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main into fix/desktop-revision-structured-context fix(desktop,ui): preserve the quote plate across the in-flight revision send The revision send awaited prepareRevisionSend before reading the plate, and the lifecycle re-keys it mid-send: the plate's current quotes are copied onto the branch child and the source bucket is emptied in place. The still-running sendWithAttachments invocation holds quotesForSend from the render that started the send, so it read the emptied source bucket, got undefined, and submitted the edited replacement without its quotes or their edited annotations (#5274 review). Read the plate through the re-keyed owner explicitly: quotesForSend now resolves the bucket by owner key (defaulting to the live draft key for the non-revision send paths), and the revision send passes the prepared draft's session id. The resumed send therefore reads the child bucket the lifecycle just wrote — removals and re-annotations included. The regression test drives beginEditUserMessage → an in-render quotesForSend capture → prepareRevisionSend and asserts the re-keyed plate with its edited annotation still reaches the send; it fails on the previous head with `actual: undefined`. Generated-by: GLM-5.3-Flash (ZCode) fix(desktop,ui): keep quotes added during a cancelled edit Cancelling a revision draft cleared both draft keys wholesale, so quotes the user staged during the edit were lost together with the edit's own restaged set (#5274 review: "Cancelling an edit deletes quotes added during it" — on main they stayed in the composer, and adding quotes during an edit is supported). clearQuotes now returns the entries it removed, and clearRevisionStagedContext re-stages whatever lies beyond the edit's beginEdit snapshot (matched per QuoteRef field set, counted as a multiset) onto the source Session the cancel returns to — whether the user added them before or after the branch child was prepared. The edit's own items are still dropped wherever the commit left them. The regression tests drive a cancelled edit with a user-added quote on each side of the prepare step and assert the addition survives on the source key while the composer text rolls back; both fail on the previous head, the first with the edit's restaged quote returned instead of the user's own, the second with no plate restore at all. Generated-by: GLM-5.3-Flash (ZCode) fix(ui): treat negative owned counts as fully user-owned clearRevisionStagedContext drops the edit's own quotes by per-key count: the first N entries matching the beginEdit snapshot are the edit's, and everything past that count is the user's own staging. The kept check compared the remaining count with `=== 0`, so once the counter ran negative the surplus stopped matching: when the user added a second copy of a quote the edit had also staged, the third identical plate entry was dropped despite being the user's. Treat any non-positive count as fully user-owned (`<= 0`), so every entry past the edit's own count survives the cancel. Fixes a P3 raised inline on #5274. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main (8648258) Brings in the composer-submit extraction (#5815) and the allow-unchanged edit-and-resend decision, merged into the revision staged-context feature: - app-shell.tsx keeps the upstream extraction; the staged-context wiring and the #5274 re-keyed quotesForSend/clearQuotes semantics move into features/conversation/controller/composer-submit.ts (owner-keyed ports). - app-shell-revision-actions.ts keeps the @maka/ui delegation; TurnRevisionDraftBase drops originalText and the unchanged gate (revisionStagedContextUnchanged) so unchanged resends pass through per upstream #5815, while the mixed-context conflict gate stays. - conversation-copy.ts keeps both new locale keys (revisionDraftQuoteConflict, revisionMixedContextUnsupported) on top of upstream's revisionUnchanged removal and #5815 copy updates. - renderer-architecture.json regenerated via check-renderer-architecture --write; app-shell.tsx budget drops 12091 -> 11154. Tests: upstream app-shell-revision-resend gains a stagedContext fake; the ui revision suite expectations updated to the allow-unchanged behavior. Generated-by: GLM-5.3-Flash (ZCode) fix(desktop): assemble the revision staged context outside the frozen shell Root cause: upstream #5546 extracted app-shell helpers and drove the frozen shell's nonTriviaTokens baseline down to 11129 with zero headroom, so the merge that re-attached this PR's stagedContext wiring (a 7-line factory in the createAppShellRevisionActions ports object, +25 tokens) broke the renderer architecture ratchet: 11129 -> 11154. Fix: assemble the RevisionStagedContext closure inside the desktop useComposerAttachments controller (a feature file outside the debt ledger), right beside the hooks that own the quote/attachment buckets. The frozen shell now forwards one member (stagedContext,) instead of building the factory inline. The restoreAttachments entry the shell only carried for that factory is dropped from its destructure: its sole consumer was the deleted block (RevisionStagedContext declares no such member and nothing in @maka/ui reads it from the staged context). Verification: - check:renderer-architecture --base 6e21e61 --strict-base: red (11129 -> 11154) before, green (11129 == base) after; ledger diff is the single app-shell.tsx nonTriviaTokens line, no other entry moved. - desktop focused suites (app-shell-revision-actions, use-composer-quotes-revision-send, app-shell-revision-resend, new-task-staged-content): 18/18 pass. - packages/ui full suite: 710/710 pass. - typecheck green: ui tsconfig + desktop preload/main/renderer/storybook. - biome lint clean on both touched source files; check:asf-headers green. Generated-by: GLM-5.3-Flash (ZCode) Merge upstream/main (28cc4e6) Resolve the renderer-architecture.json conflict by re-pricing the ledger from the merged tree via check-renderer-architecture.mjs --write (all entries at real merged-tree values, within baseline); drop the trailing blank line at EOF in conversation-copy.ts flagged by diff-check. Merge upstream/main (0aa2707) Resolve renderer-architecture.json by re-pricing from the merged tree via check-renderer-architecture.mjs --write. Merge upstream/main (d6876d7) Resolve the renderer-architecture.json conflict by taking main's ledger (new #5851 file entries) as the base and re-pricing every entry from the merged tree via check-renderer-architecture.mjs --write; the check passes against the ratchet baseline. Merge upstream/main (d7dffca) Merge upstream/main (c838e1f) Fourth structural catch-up for #5274: carries #5868 (Composer staging moved into a persistent ComposerStagingProvider owner) and #5884 (task archive timestamps). Conflict resolution ports the revision staged-context semantics onto the new owner structure: ComposerStagingSubmission gains optional owner-key reads/clears (snapshot for captured submissions, live plate for the revision re-key) and ComposerStagingCommands gains stagedContext(); the frozen shell forwards the one composerStaging handle and the revision assembler derives the gate probe and plate reads from it. Merge upstream/main (1e80e3b) into fix/desktop-revision-structured-context # Conflicts: # apps/desktop/renderer-architecture.json Merge upstream/main (c7fa6bb) into fix/desktop-revision-structured-context # Conflicts: # apps/desktop/renderer-architecture.json Merge upstream/main (255ae23) into fix/desktop-revision-structured-context Merge upstream/main (229e1b4) into fix/desktop-revision-structured-context Merge upstream/main (f7633c3) into fix/desktop-revision-structured-context Merge upstream/main (7c90bac) into fix/desktop-revision-structured-context Merge remote-tracking branch 'upstream/main' into fix/desktop-revision-structured-context # Conflicts: # apps/desktop/renderer-architecture.json fix(desktop): drop the stale regenerate footer copy #5468 removed the Regenerate feature (87ff279), deleting the footer's `regenerate` label and the `regenerateRunning` / `regenerateAgain` / `regenerate` / `requestRegenerate` keys from the conversation copy. This branch's stale base still carried the block, so the merge-base diff re-adds those keys across the contract type and all three locales (including the zh-TW 本輪迴答 wording) while nothing on current main references them — merging would resurrect dead strings. Drop the block from the type and the zh-CN / zh-TW / en entries, matching the upstream shape exactly; the `lineage.regenerated*` keys are a different, live feature and stay. Generated-by: GLM-5.3-Flash (ZCode)
Closes #5132.
Summary
Note
Edit & resend still cannot preserve attachments, quotes, or directory references. This temporary gap is tracked by #5109 and #5118.
Validation
npm run lintnpm run format:checknpm exec -- tsx --test apps/desktop/src/main/__tests__/app-shell-turn-actions.test.ts apps/desktop/src/main/__tests__/permission-response-ipc-boundary.test.ts apps/desktop/src/main/__tests__/workbar-services-adapter.test.ts packages/runtime-host/src/__tests__/session-collaboration-authority.test.tsnpm --workspace @maka/runtime run typechecknpm --workspace @maka/runtime-host run typechecknpm --workspace @maka/desktop run check:architectureDesktop typecheck is blocked only by three existing
packages/uiprop mismatches (autoScroll,settledText, andtrailingAction).AI disclosure: Prepared with OpenAI Codex at the contributor's request.