LearnNewsExamplesServices
Frontmatter
id16506
titleCorrect the theme-deferral gate's causal story and give it one worker read
stateClosed
labels
bugdocumentationai
assigneesneo-fable
createdAtAug 4, 2026, 5:07 PM
updatedAtAug 7, 2026, 2:06 PM
githubUrlhttps://github.com/neomjs/neo/issues/16506
authorneo-fable
commentsCount1
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]
closedAtAug 7, 2026, 2:06 PM

Correct the theme-deferral gate's causal story and give it one worker read

Closed Backlog/active-chunk-12 bugdocumentationai
neo-fable
neo-fable commented on Aug 4, 2026, 5:07 PM

Context

The Approve+Follow-Up obligation from PR #16504's review (Emmy, 2026-08-04 — her Depth Floor falsified the shipped causal story while approving the seam; the operator's SharedWorker concern was the falsifier she chased). Filed at merge per the A+FU contract. Live latest-open sweep at filing: latest 20 checked, no equivalent.

The Problem

PR #16504 shipped the RIGHT repair (resolve Neo.currentWorker at call time in both theme-deferral gates) wearing the WRONG law. The source comments, ticket #16503, and PR body claim: "test runners reuse worker processes across spec files and reassign the world between them" / "a later spec file's setup() builds a fresh app world and reassigns Neo.currentWorker." Both claims are falsified by the exact tree:

  • test/playwright/setup.mjs assigns via Neo.currentWorker ??= — it never replaces an existing worker.
  • The true mechanism is module evaluation before harness setup: BodyContainer.spec.mjs statically imports the component/VdomLifecycle graph before its top-level setup() executes, so the module-load binding captured undefined; the old gate then threw TypeError: Cannot read properties of undefined (reading 'countLoadingThemeFiles'), and Overflow.syncControl()'s catch swallowed the rejected mount — presenting as "0 listeners" and hiding the import-time undefined.
  • The production framing is also wrong in the comments: a surviving SharedWorker realm keeps the SAME App-worker object on reconnect (WHATWG matching/lifetime); realm death refreshes modules AND singleton together. There is no production world-reassignment the comment's "law" warns about — the issue is captured-identity-possibly-undefined at import time, never "stale mutable state of a previous world" (a captured object reference always exposes live mutable fields).

The Architectural Reality

  • src/mixin/VdomLifecycle.mjs: the binding-site guard comment and both gate comments carry the false story; the gates each read Neo.currentWorker twice (count consult + listener registration).
  • Reviewer's non-blocking shape suggestion, adopted here: per gate, one method-local const worker = Neo.currentWorker, then worker.countLoadingThemeFiles / worker.on(...) — one coherent owner, one global read.
  • #16503's close-out comment carries the corrected mechanism; this ticket corrects the SOURCE surfaces.

The Fix

  • Rewrite the three comment blocks in VdomLifecycle.mjs to state the true mechanism (import-time capture may precede harness setup ⟹ possibly undefined; call-time resolution is the contract) and drop the false worker-reassignment/previous-world-state claims.
  • Apply the single-read shape at both gates (const worker = Neo.currentWorker).
  • Optional hardening witness if cheap: a unit probe pinning the cold-import-order case (module graph evaluated before setup()), so the swallowed-TypeError presentation can never hide this class again.

Acceptance Criteria

  • No comment in VdomLifecycle.mjs claims worker-world reassignment or previous-world mutable state; the stated mechanism matches the review's falsified-and-corrected account.
  • Both gates read Neo.currentWorker exactly once per invocation via a method-local.
  • Full tab suite + isolation stay green (31 passed / 26 passed); behavior byte-identical.
  • If the cold-order witness is added, it fails against the pre-#16504 gate shape.

Out of Scope

  • Any behavioral change to the theme-deferral contract (proven by the #16434 five-beats E2E).
  • Harness import-order policy.

Decision Record impact

none.

Related

#16503 / PR #16504 (the shipped seam + the review carrying the falsification), #16434 (the contract's origin), PR #16489 (first CI casualty).

Origin Session ID: 1913de09-6dc0-4d1e-a9a3-b51c33b46cdc

Retrieval Hint: query_raw_memories("theme deferral causal story correction import-time undefined module evaluation before setup single worker read")

tobiu referenced in commit 3c3efa4 - "chore(mixin): theme-deferral gates carry the true import-order story, one worker read (#16506) (#16625)" on Aug 7, 2026, 2:06 PM
tobiu closed this issue on Aug 7, 2026, 2:06 PM