Skip to content

[finding] app-shell's two confirm runtimes reset confirmState differently when the dialog closes #6034

Description

@yinlianghui

Observation recorded while executing #5835 (type RecordDetailView's confirm handler as the published ConfirmationHandler + pin that both runtimes feed ActionConfirmDialog the same fields). Filed unassigned, observation-class — nothing user-reachable is known to be broken. Out of #5835's fence, which is the OPEN path; this is the CLOSE path.

Verified on origin/main @ 53dc89db8.

The two runtimes agree on open and disagree on close

Both mount ActionConfirmDialog and both hand it the same field set when it opens — { open, message, options, resolve }. That parity is now pinned by packages/app-shell/src/views/RecordDetailView.confirmRuntimeParity-5835.test.tsx.

Their onOpenChange handlers differ:

  • packages/app-shell/src/hooks/useConsoleActionRuntime.tsx — replaces the whole state: setConfirmState({ open: false, message: '' }). message is blanked, and options / resolve are dropped.
  • packages/app-shell/src/views/RecordDetailView.tsx — spreads and flips one flag: setConfirmState(s => ({ ...s, open: false })). message, options and resolve are all retained.

Why it may matter, and why it is filed rather than fixed

Two observable consequences, neither confirmed against a running app:

  1. A blank frame during the close animation.ActionConfirmDialog renders state.message into AlertDialogDescription and keeps rendering during Radix's exit transition. The console runtime clears message synchronously on close, so the description can go empty while the dialog is still fading; RecordDetailView's copy fades out with its text intact.
  2. A retained resolve.RecordDetailView keeps the previous promise's resolve in state after close. It is not a correctness bug today — ActionConfirmDialog calls state.resolve?.(false) itself before onOpenChange(false), so the promise is already settled and a second call would be a no-op — but it leaves a stale closure reachable in state, and the two runtimes disagree about whether that is intended.

Neither runtime is obviously the correct one; picking a winner is a call, not a cleanup, which is why this is filed instead of fixed. Same drift family as #5610 and #3320RecordDetailView re-implementing a shared runtime and then diverging from it with nothing red in between.

Not a request to merge the two runtimes; #5835's triage ruled that a larger refactor and out of scope.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions