LearnNewsExamplesServices
Frontmatter
id19462
titleClosing a dashboard popup duplicates its returned widget
stateClosed
labels
bugaidashboard
assigneesneo-gpt-sophie
createdAtOct 8, 2026, 2:47 AM
updatedAtOct 8, 2026, 11:12 AM
githubUrlhttps://github.com/neomjs/neo/issues/19462
authorneo-gpt-sophie
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtOct 8, 2026, 11:12 AM

Closing a dashboard popup duplicates its returned widget

neo-gpt-sophie
neo-gpt-sophie commented on Oct 8, 2026, 2:47 AM

Context

The operator reported a distinct Fleet Manager Accounts failure on 2026-10-08: tear the pane into a popup, close that popup, observe an empty source view, navigate to another left-rail view and back, then see two Accounts panels stacked.

This is independent of the overly broad body drag handle tracked in neomjs/neo-agent-institution#601. A legitimate header tear-out must return correctly too.

Installed witness: Institution fd958fba1e7d492a5ae2b9b283df1f65e5cc1a6e, Engine 82bc6158444306e0c342e8cda480e77158c9fedb. Read-only Neural Link verification after the reported sequence finds one Accounts instance, present twice each in its source dashboard's items, VDOM and DOM; detachedItems.size === 0. The window log records the child disconnect/re-integration, followed by navigation away/back and a wedged viewport update. The installed observation is distinct from the isolated browser attribution below.

The Problem

Closing the popup neither immediately restores a usable source pane nor preserves unique membership through navigation. The duplicated rendering must not be hidden with a restart or a second instance.

Design authority: src/dashboard/Container.mjs class JSDoc promises that a manually closed detached window has its widget “correctly reclaimed and restored to the dashboard”.

The Architectural Reality

This is the legacy Neo.dashboard.Container lifecycle used by Accounts, not the cockpit's newer DockLayout. At reproduction baseline Engine 994fa3e6d87a132ac8c46e3f6b08b969e55aab55:

  • onWindowConnect() adds the widget to the popup with removeFromPreviousParent = !#isWindowDragging.
  • onWindowDisconnect() returns through me.insert(index, widget).
  • src/container/Base.mjs#insert only early-returns for the same parent at the same index; otherwise it inserts the instance and its VDOM.

A 2026-10-08 isolated Node probe now confirms the retained-membership mechanism using real Dashboard, container and component instances plus the unit runtime, with only window admission/URL seams stubbed. Held tear-out → connect → terminal drop/end → disconnect leaves two source items and two VDOM references to the original widget, drains the popup and clears the detached map. The ordinary (non-drag) popup control removes the source slot on connect and returns exactly one item/reference at its original index. A repeated disconnect adds nothing further. The browser repair receipt additionally isolates the initially blank return: ordinary removal queues an update for the closed popup, and coalesced source remove/reinsert leaves the source vnode believing its missing DOM node exists.

The Fix

Repair manual-close return in the owning dashboard lifecycle so the original component reattaches exactly once, with coherent parent/window/render state. Reuse existing container ownership primitives; avoid a second Accounts instance or consumer-side duplicate filtering. Add regression coverage to the existing dashboard tests and a browser journey through popup close and source hide/show.

Target surface Source of authority Proposed behavior Fallback Docs Evidence
Legacy dashboard popup-close return Dashboard class restoration contract Original widget restored once immediately; navigation preserves it Existing refusal/cleanup paths retain recoverable ownership Existing lifecycle JSDoc Component identity and item/VDOM/DOM counts, plus browser close-and-return journey

Decision Record impact: none; restoration of the existing lifecycle contract. Owning files already exist in Engine; no new service or public API is required.

Acceptance Criteria

  • A normal header tear-out followed by manual popup close restores the original view without navigation or app restart.
  • Source dashboard items, VDOM and DOM each contain the widget exactly once, with source parent/window ownership and no stale detached entry.
  • Navigate away and back, then repeat tear-out/close: still one usable pane with its selection/state retained.
  • Coverage exposes the retained-membership duplicate on the unfixed path and passes with the repair, including close/update ordering relevant to the initially empty view.
  • Existing dashboard drag-back reintegration remains functional.
  • Post-merge installed acceptance on the next authorized FM candidate records the header drag, close, immediate return and navigation checks separately from source/CI results.

Out of Scope

Body drag admission (Institution #601), global DockLayout refactoring, migration/restart of peer harnesses, and an app install without its own boundary.

Related and discovery

Related: neomjs/neo-agent-institution#12 and neomjs/neo-agent-institution#601.

Live latest-open sweep: latest 20 created-descending Engine issues at 2026-10-08T00:47Z, no equivalent. Latest 30 all-state A2A messages: no competing legacy Accounts return claim. Org historical searches for Accounts popup and dashboard popup disconnect duplicate found no equivalent. MC problem sweep returned three earlier popup/dock reports; none establishes this close/navigation cause. Own-assignment sweep: only #19446, a separate grid-scroll defect.

Sophie owns implementation and the installed acceptance handoff. The local source/browser receipt is linked above; the installed FM candidate remains a separate post-merge validation.

Origin Session ID: e6ce4d70-a7ff-454e-996d-e7c25efdf4cf

Retrieval Hint: "Accounts popup close empty navigation duplicate retained widget dashboard"

tobiu referenced in commit 156fd8a - "fix(dashboard): return closed popup widgets once (#19462) (#19464) on Oct 8, 2026, 11:12 AM
tobiu closed this issue on Oct 8, 2026, 11:12 AM