LearnNewsExamplesServices
Frontmatter
id15136
titleDemo C dock projection: preserve tab-chrome identity across document refresh
stateOpen
labels
enhancementdesignaiarchitecture
assignees[]
createdAt9:14 PM
updatedAt9:14 PM
githubUrlhttps://github.com/neomjs/neo/issues/15136
authorneo-gpt-emmy
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
milestonev13.2

Demo C dock projection: preserve tab-chrome identity across document refresh

Open Backlog/active-chunk-5 enhancementdesignaiarchitecture
neo-gpt-emmy
neo-gpt-emmy commented on 9:14 PM

Context

The visual-repair pass on #15099 proved that Demo C already preserves the hard part of docking permanence: DemoCWorkspace.refreshDockWorkspace() stages the destination shell, moves cached live pane instances through Neo's native container ownership path, and reconciles once at the closest common parent. The pane components and DOM nodes survive.

The tab chrome does not. Every dock-document refresh creates a new EdgeZone shell, new tab.Container instances, new header toolbars, new strips, and new overflow plugins. Their construction animations replay as flicker. The draft PR contains a local .agentos-dockdemo-chrome-settling containment class which disables those replacement-shell transitions. It prevents the false animation, but it also proves the deeper identity gap and cannot restore normal active-tab motion.

A live latest-20-open sweep plus all-state GitHub search was checked at 2026-07-13T19:13Z; no equivalent ticket exists. Closed #14968 owns operation-correlated tab-insert animation, not surviving tab-container identity. Open #14780 owns the motion vocabulary. The current A2A all-state window contains no overlapping claim or intent.

The Problem

A surviving logical tabs node is currently rendered as a new component tree after every dock operation. Consequences:

  • tab-header and strip identities reset even when the dock node still exists;
  • construction/entry effects can replay as whole-strip flicker;
  • the overflow plugin and its floating control are torn down and recreated;
  • a blunt animation-disable class is needed to keep coarse projection visually honest;
  • normal active-tab indicator motion cannot be distinguished cleanly from replacement-shell construction.

The panes have object permanence while their containing chrome does not. For a flagship docking demo, that split is visible.

Architectural Reality

  • apps/agentos/childapps/dockdemo/view/DemoCWorkspace.mjs#refreshDockWorkspace already demonstrates the native permanence transaction: both source and destination parents exist, pane removals/inserts are silent, and one host.update() with updateDepth = -1 emits DOM moves.
  • src/tab/Container.mjs#createItems creates one header toolbar, strip, and body container per tab-container instance. Replacing the tab container necessarily replaces all three.
  • src/dashboard/DockLayoutAdapter.mjs projects JSON-first dock nodes into configs; it is not currently an identity reconciler.
  • Closed #14968 intentionally prevents broad tab-enter animation on coarse re-projection. This follow-up must preserve that operation-correlation contract rather than reintroducing a selector-wide animation.
  • Open #14780 explicitly allows an intentional instant path for coarse projection, but a hard cut caused only by component replacement is not a substitute for surviving component identity.

The Fix

Extend Demo C's identity-preserving projection transaction to surviving tab chrome.

  1. Key each projected tabs surface by the dock node id and retain its tab.Container when that logical node survives.
  2. Reconcile item moves/additions/removals through native container operations:
    • apply the source and destination ownership changes silently;
    • update once at their closest common parent with the narrowest correct updateDepth;
    • let Neo emit DOM move operations for surviving header/button/body identities.
  3. Create or destroy a tab container only when the logical dock node itself enters or leaves the topology.
  4. Preserve the surviving strip, header toolbar, and overflow-plugin/control identities; reproject their data, not their selves.
  5. Remove the Demo-C agentos-dockdemo-chrome-settling animation suppression once identity makes it unnecessary.
  6. Keep operation-specific motion under the existing DockMotionSignal/token contracts. Ordinary active-tab changes should use the normal tab-strip animation; coarse refresh must not replay construction effects.

Start at the Demo-C consumer. Lift a reusable reconciler into src/ only if the implementation proves a second real consumer and a stable contract; do not make DockLayoutAdapter stateful merely to avoid local code.

Contract Ledger

Target surface Source of authority Proposed behavior Fallback / failure Docs Evidence
surviving tabs node dock node id + projected tab.Container.dockNodeId same component instance survives projection node removed from document = destroy exactly once reconciliation JSDoc component-id before/after matrix
item ownership Neo container remove/insert/update contract silent source/destination mutation, one common-parent reconciliation invalid parent/index fails named; never duplicate an item app method JSDoc unit ownership + DOM identity assertions
tab strip/header Neo.tab.Container child lifecycle surviving toolbar/strip/buttons keep identity genuinely new/removed item may create/destroy its button no new timing literals NL identity journey
overflow control Neo.tab.plugin.Overflow one surviving plugin/control per surviving heavy tabs node node removal retires the control; no transient duplicate owner comment exact-one-control + stable-id assertion
motion #14780 + closed #14968 normal active-tab motion survives; coarse projection does not replay entry motion reduced motion and intentional instant paths remain token-owned remove local suppression rationale animation/transition browser oracle

Decision Record impact

none if implemented as a Demo-C reconciliation consumer using existing container and docking contracts. A shared src/ reconciler would require an architecture step-back and an explicit ADR-impact statement before implementation.

Acceptance Criteria

  • A dock operation that preserves a logical tabs node preserves that node's tab.Container, header-toolbar, strip, overflow plugin/control, and surviving tab-button component identities.
  • Live pane component and DOM identity remains stable across the same operation.
  • Item transfer uses silent source/destination mutations followed by one closest-common-parent update at a justified updateDepth.
  • A logical tabs node entering or leaving the document creates or destroys its chrome exactly once.
  • No coarse refresh replays construction/tab-enter effects across every header.
  • A normal active-tab change still produces the standard smooth tab-strip/indicator transition.
  • Demo C removes agentos-dockdemo-chrome-settling and its transition-duration suppression.
  • Overflow remains truthful with exactly one floating control; its identity survives while the heavy tabs node survives.
  • Focused unit coverage pins the ownership/identity matrix and one whitebox E2E journey pins component ids, DOM ids, exact-one overflow, and animation behavior.
  • The PR records whether the solution stayed Demo-C-local or proved a reusable second consumer; no speculative shared abstraction.

Out of Scope

Changing DockZoneModel document identity · reintroducing broad tab-enter CSS · rewriting FLIP geometry motion · cross-window transfer choreography · general keyed-VDOM diffing · changing tab.Container public APIs without a separate architecture decision.

Avoided Traps

  • Do not equate cached pane identity with complete workspace permanence.
  • Do not hide replacement with a permanent zero-duration override.
  • Do not retain components whose logical dock node was actually removed.
  • Do not make DockLayoutAdapter stateful by default.
  • Do not create a second timing or motion-observability source.

Related

Related: #15099 · #13158 · #14780 · #14968 · #14653

Origin Session ID: f95e01ff-ba36-409a-98af-573263fab247

Retrieval Hint: Demo C dock tab chrome identity coarse projection common parent updateDepth overflow flicker permanence