LearnNewsExamplesServices
Frontmatter
id19684
titleUndo of a popup''s native close: main''s superseded return projection takes the pane back from the reopened popup
stateClosed
labels
bugaitestingdashboard
assigneesneo-opus-grace
createdAtOct 13, 2026, 12:05 AM
updatedAtOct 13, 2026, 3:42 AM
githubUrlhttps://github.com/neomjs/neo/issues/19684
authorneo-opus-grace
commentsCount0
parentIssue19655
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 13, 2026, 3:42 AM

Undo of a popup's native close: main's superseded return projection takes the pane back from the reopened popup

Closed Backlog/active-chunk-8 bugaitestingdashboard
neo-opus-grace
neo-opus-grace commented on Oct 13, 2026, 12:05 AM

Context

WorkstationNL.spec.mjs:2604 ("pop-out uses the Group cursor to return and replay the same live pane") is in #19657's intermittent set. It fails at the assertion "undo reopens the pane", at both screen sizes. Dev runs: 38306161797 at 1920 and 38309244286 at 2560.

The test pops out commits, returns it with a native popup close, then undoes that return. The undo restores the popup-owned document and reopens the popup, so the live pane must move into it.

Observed, on hosted probes from an unmerged branch that log every participant projection, pane resolution and window adoption after the undo:

  • Run 38324514355: 6 of 18 runs ended with the pane visible in neither window; the test caught 4 of them. Of the other two, one passed because the assertion saw the pane in the popup just before it was taken back. The other ended unmounted in the popup's own tab container, a variant not yet explained.
  • Run 38325733035, with a sequence id on every scheduled projection: 7 of 18 runs lost the pane. Every main refresh came from the main participant's own chain, so nothing outside it re-projected.

A lost run (all times in ms after the undo):

  • At โˆ’36, the native-close return commits. Main schedules projection #4 (commits in main), and the popup schedules its own.
  • At +4, the undo commits. Main schedules #5 (commits gone), and the popup schedules #5 (commits in the popup).
  • At +235, main only now starts #3, from before the return. Across the lost runs that logged main, #3 starts at +107 to +241 and #4 at +854 to +1005.
  • At +676, the popup projects #5 and adopts the parked pane.
  • At +1005, main reaches #4, the return's document. At +1039 its resolveProjectedPane('commits') takes the live pane out of the popup's card, where it was mounted.
  • Main's #5 runs about 0.8 s later and removes commits again. The pane ends unmounted, visible in neither window.

The Problem

A superseded commit's projection still runs on a participant whose refresh chain is behind, and it can claim a shared live pane that a newer commit already moved elsewhere. Each participant's chain is ordered, but the two chains are not ordered against each other. Panes are single live instances resolved by identity, so whichever participant reconciles last takes the pane. That last reconcile can belong to an older snapshot.

The Architectural Reality

  • src/manager/transaction/Commit.mjs complete() dispatches each participant's projection in a microtask and refuses a superseded one: group.snapshot !== result.snapshot returns early. That check runs only at dispatch. At that moment the return commit is still current, so its projection is queued. It executes on the participant's chain about a second later, after the undo.
  • src/dashboard/dock/Workspace.mjs projectDockZoneDocument() records scheduledProjection = {document} and chains the refresh on refreshPromise.
  • onDockProjectionFailed() already holds the rule this case needs: a repair stands down when scheduledProjection has moved on, "since that newer commit's projection is the repair and the failed snapshot must not re-project over it".
  • resolveProjectedPane() resolves a live pane by identity, wherever it is mounted.

Design authority: Commit.complete()'s supersession guard (a superseded snapshot does not project) and the repair path's stand-down (a superseded document must not re-project over a newer one).

The Fix

Apply the existing supersession rule where the projection runs, not only where it is dispatched. Proposed: the chained refresh in projectDockZoneDocument() stands down when this participant's scheduledProjection.document is no longer the document it was scheduled for, as the repair path already does. A newer projection for the same participant is chained behind it and renders the current document from the live shell. A participant that a newer commit did not touch has no newer projection scheduled, so it still projects.

Alternatives, for the dock owners to weigh:

  • An ownership guard in resolveProjectedPane(): refuse a live pane that the current Group snapshot assigns to another participant.
  • Group-level ordering: project commit N+1 only after every participant has settled commit N.

Acceptance Criteria

  • The ordering that leaves the pane outside the popup is named, with the receipt that shows it: the two runs above. Main's stale #4 resolves commits out of the popup after the popup has adopted it.
  • A test forces that order (a participant whose chain is behind receives a superseded projection after a sibling has adopted the pane) and goes red before the fix, green after.
  • WorkstationNL.spec.mjs:2604 passes 20/20 alone on a hosted runner, with the probe's lost-pane count at 0 (post-merge receipt).

Out of Scope

  • The other popup intermittents in #19657, such as LegacyPopupReturnNL:12, which was a separate App-worker stall.
  • Why main's chain runs a second behind. Slow refreshes are legitimate; letting a stale one claim a pane is the defect.
  • The FilmTour quarantine, unless the same ordering turns out to explain it.

Related

  • #19657 and epic #19655: the intermittent set and the burn-in.
  • #19273: the native-close return. #18314: Group cursor and popup ownership. #18642: the repair stand-down.

Live latest-open sweep: the latest 20 open issues at 2026-10-12T22:04Z, own assignments, and gh search issues for "undo reopen popup pane". No equivalent found, and no competing lane claim in A2A.

Origin Session ID: 02040656-932a-48c8-8894-6f43d0368663

tobiu referenced in commit de92007 - "fix(dock): a Group projection stands down once a newer commit adopted its participant's next document (#19684) (#19703) on Oct 13, 2026, 3:42 AM
tobiu closed this issue on Oct 13, 2026, 3:42 AM