LearnNewsExamplesServices
Frontmatter
id17980
titleA tab-bar child write beside an open reconcile duplicates retained chrome
stateClosed
labels[]
assigneesneo-gpt
createdAtAug 31, 2026, 11:02 PM
updatedAtSep 1, 2026, 8:48 AM
githubUrlhttps://github.com/neomjs/neo/issues/17980
authorneo-opus-vega
commentsCount10
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[x] 18000 A duplicated-chrome failure reports itself as a state assertion
closedAtSep 1, 2026, 8:48 AM

A tab-bar child write beside an open reconcile duplicates retained chrome

neo-opus-vega
neo-opus-vega commented on Aug 31, 2026, 11:02 PM

The Problem

A change-guarded, legitimate config write on a header-action button (one set(), one update) issued while the dock projection/reconcile train is still applying can duplicate retained tab-bar chrome: the bar renders a doubled tab button and a doubled action set with IDENTICAL element ids (one subtree applied twice). Reproduced only on slow rigs (GitHub CI), never locally — timing-gated.

Evidence

PR #17974's CI history: three consecutive red runs with the strict-mode signature resolved to 2 elements (identical ids) and a page snapshot showing Alpha, Beta, Beta in one strip. Every intermediate mitigation (write batching, deferral, fixture isolation) only moved which arm failed; the PR went green once bar writes were serialized onto the refresh's settled tail (4dd6b0edf5).

That serialization is insufficient, measured 2026-08-31 22:10Z. It merged and is on dev (refreshPromise chaining at src/dashboard/dock/Workspace.mjs:1018, :1038, :1532), and dev is RED at fa20136f29 with the identical signature — run 33440382357, DockReload.spec.mjs:181. A second capture on PR #17987 (33444096674) hit :250 instead. Both arms are activation-followed-by-write, so the reachable set is that shape rather than one test, and every branch cut from dev inherits the red at a rotating arm number.

One residual unserialized write path is already identified: Workspace.mjs:1387's mount-time sweep is time-based (timeout(100)) with a !refreshPromise guard sampled 100ms before the write lands, so a refresh starting inside that window is invisible to it. Not yet shown to be the path either capture took — both fail well after mount — but it is an unserialized bar write that survived the serialization above.

The Fix (to investigate)

The update-collision handling between a child component's vdom round trip and a parent-level reconcile application should either queue or merge — never double-apply. Consumers can serialize (the settled-tail idiom now in Workspace), but the engine hazard remains for any toolbar/tab consumer writing during projection.

Acceptance Criteria

  • A deterministic repro (throttled or instrumented) demonstrating the double-apply without dock involvement, or root-cause analysis showing where the stale-vnode diff enters.
  • The collision path queues/merges; the repro goes green without consumer-side serialization.

Related

Parent: #13158 (surfaced by the dock family). Consumer-side mitigation shipped in PR #17974.

Origin Session ID: 914dffcd-0057-46a5-a0c6-9ca807fd5c91

Retrieval Hint: "tab bar duplicate chrome vdom update collision reconcile double apply"

— Vega (Fable 5, Claude Code) 🌿