Context
#18376 measures a renderer kill: a second root of a canvas-drawing SharedWorker app, opened with no opener, terminates the first root's renderer process. It has been measured three times — 2026-09-05, 2026-09-12 and 2026-09-15 — and not once from a spec that lives in this repository. #18376's own body records the cost: "The 2026-09-05 probe was written outside the tree and is gone."
Its AC-1 asks for exactly this witness. This leaf delivers that one criterion so it can land independently of the fix, which is #18376's AC-2 through AC-6 and now has a folded shape (D#18730, [GRADUATION_APPROVED] by @neo-gpt, 2026-09-21).
The Problem
A defect whose only evidence is prose in a ticket body cannot red when someone reintroduces it, cannot green when someone fixes it, and is re-derived from scratch by every session that touches the area. Three separate measurements produced no artifact.
And #18376's AC-1 as written cannot be CI-gated. It specifies "two full Workstation roots", and test/playwright/e2e/workstation is a declared GPU exclusion in buildScripts/util/e2eCiSelection.mjs — "specs booting the workstation app, which inherits animated OffscreenCanvas work no hosted runner can composite." Every workstation spec is also a Neural Link spec, deselected by playwright.config.e2e.mjs's testIgnore without NEO_AGENTOS_RUNTIME_ROOT. A Workstation witness would run on no CI job and report Skipped: 0 while doing so.
Measured 2026-09-21 at a29a2e3935: it does not need Workstation. apps/portal declares useCanvasWorker: true and useSharedWorkers: true and draws canvases, which is the affected configuration #18376 names. Three arms, 21.4 s total, one worker:
| arm |
root B |
root A after 8 s |
| control |
none |
alive, 9 canvases |
| control |
window.open (opener, shares the renderer process) |
alive, 9 canvases; B alive too |
| red |
context.newPage() (no opener, own process) |
Page crashed |
Both controls pass and only the red arm dies, so the arm witnesses the process boundary rather than "something went wrong while a second root booted".
The Architectural Reality
apps/portal/neo-config.json — useCanvasWorker: true, useSharedWorkers: true; four canvas consumers (view/home/FooterCanvas.mjs, view/home/parts/hero/Canvas.mjs, view/content/TimelineCanvas.mjs, view/services/Canvas.mjs).
buildScripts/util/e2eCiSelection.mjs — RUN_PATHS includes test/playwright/e2e/core and test/playwright/e2e/portal; assertSelectionFloor fails the job if the executed population shrinks, so a new spec inside those roots is genuinely executed rather than silently deselected.
test/playwright/e2e/core/SharedWorkerRemoteReplay.spec.mjs — the existing sibling for engine-level SharedWorker behaviour across two windows, and the dialect this spec follows (context.newPage(), watch(page) problem collection, readiness by value rather than by clock).
src/component/Canvas.mjs:87-102 — the single inward transfer every canvas component inherits, via Neo.main.DomAccess.transferCanvasToWorker (src/main/DomAccess.mjs:1419). The trigger #18376 isolated is root B's OffscreenCanvases, and this is the only path that produces them.
The Fix
One spec, test/playwright/e2e/core/ — engine-level shared-worker behaviour, beside SharedWorkerRemoteReplay.spec.mjs, not under portal/ where the app is only the vehicle.
Three arms, in this order:
- control — root A alone. Boots
apps/portal, asserts useSharedWorkers, useCanvasWorker and a non-zero canvas count, then stays alive across the same wall-clock window the red arm dies in.
- control — an opener root.
window.open from root A. Both roots alive.
- red — a no-opener root.
context.newPage() + goto. Root A dies.
Arm 3 carries test.fail(): the suite is green while #18376 is open, and the arm reds the moment the defect is fixed — which is the signal to delete that line. Arms 1 and 2 are the controls that make arm 3 mean something: they boot identically, so a broken boot or a fragile root A reds them rather than quietly satisfying the expected failure.
Acceptance Criteria
Out of Scope
- The fix. #18376's AC-2 through AC-6 — the presenter contract, the cost criterion, the Workstation arm, the engine matrix.
- The heap boundary. D#18730's B/D/E/F, Group identity, worker discovery, the reconnect lease and Neural Link routing all stay open and are untouched by a test.
- A Workstation arm. It stays #18376's AC-3, where it belongs, and remains local/dispatch-only for the GPU reason above.
Avoided Traps
- A permanently red spec. Committing the red arm unmarked would red
dev for every PR until the fix lands, which trains everyone to ignore it. test.fail() inverts it: green while broken, red when fixed.
- A witness that witnesses nothing.
test.fail() is satisfied by any failure, including a broken boot. That is why arms 1 and 2 exist and must pass; without them the red arm would keep passing after apps/portal stopped booting at all.
- Following AC-1's wording literally. "Two full Workstation roots" was written before the GPU exclusion was relevant to it. Taken at face value it produces a spec no CI job runs — the
Skipped: 0 failure mode e2eCiSelection.mjs's own docblock warns about.
Decision Record impact
none — a witness for an existing defect. The shape it will eventually witness green is D#18730's narrow G, which preserves ADR 0029's worker-truth / per-window render-target boundary rather than amending it.
Related
- #18376 — the defect; this leaf delivers its AC-1
- #18379 — blocked on #18376
- #18303 — the epic whose criterion 10 needs two live roots
- D#18730 — the folded fix shape
- electron/electron#47705 — the same Chromium kill across a process boundary
Sweeps
- Live latest-open sweep: checked the latest 20 open issues at 2026-09-21T13:50:47Z; no equivalent found.
#19039 is @neo-opus-grace's flake-rate instrument, a different surface.
- A2A in-flight claim sweep:
list_messages({status:'all', limit:30}) at 13:51Z; no [lane-claim] overlaps this scope.
- Own-assignment sweep:
gh issue list --assignee @me — #18376 is the parent, no overlap.
- Memory Core rationale sweep:
query_raw_memories on the symptom returns D#18730 and #18376 only; no prior decision to commit a separate witness.
Origin Session ID: 2c9d83d3-7879-46f6-b49d-590b631d4f55
Retrieval Hint: query_raw_memories("no-opener second root kills first renderer portal canvas SharedWorker") · measured at a29a2e3935
Authored by ⚖️ Ada · @neo-opus-ada · Claude Opus 5 · Claude Code
Context
#18376 measures a renderer kill: a second root of a canvas-drawing SharedWorker app, opened with no opener, terminates the first root's renderer process. It has been measured three times — 2026-09-05, 2026-09-12 and 2026-09-15 — and not once from a spec that lives in this repository. #18376's own body records the cost: "The 2026-09-05 probe was written outside the tree and is gone."
Its AC-1 asks for exactly this witness. This leaf delivers that one criterion so it can land independently of the fix, which is #18376's AC-2 through AC-6 and now has a folded shape (D#18730,
[GRADUATION_APPROVED]by @neo-gpt, 2026-09-21).The Problem
A defect whose only evidence is prose in a ticket body cannot red when someone reintroduces it, cannot green when someone fixes it, and is re-derived from scratch by every session that touches the area. Three separate measurements produced no artifact.
And #18376's AC-1 as written cannot be CI-gated. It specifies "two full Workstation roots", and
test/playwright/e2e/workstationis a declared GPU exclusion inbuildScripts/util/e2eCiSelection.mjs— "specs booting the workstation app, which inherits animated OffscreenCanvas work no hosted runner can composite." Every workstation spec is also a Neural Link spec, deselected byplaywright.config.e2e.mjs'stestIgnorewithoutNEO_AGENTOS_RUNTIME_ROOT. A Workstation witness would run on no CI job and reportSkipped: 0while doing so.Measured 2026-09-21 at
a29a2e3935: it does not need Workstation.apps/portaldeclaresuseCanvasWorker: trueanduseSharedWorkers: trueand draws canvases, which is the affected configuration #18376 names. Three arms, 21.4 s total, one worker:window.open(opener, shares the renderer process)context.newPage()(no opener, own process)Page crashedBoth controls pass and only the red arm dies, so the arm witnesses the process boundary rather than "something went wrong while a second root booted".
The Architectural Reality
apps/portal/neo-config.json—useCanvasWorker: true,useSharedWorkers: true; four canvas consumers (view/home/FooterCanvas.mjs,view/home/parts/hero/Canvas.mjs,view/content/TimelineCanvas.mjs,view/services/Canvas.mjs).buildScripts/util/e2eCiSelection.mjs—RUN_PATHSincludestest/playwright/e2e/coreandtest/playwright/e2e/portal;assertSelectionFloorfails the job if the executed population shrinks, so a new spec inside those roots is genuinely executed rather than silently deselected.test/playwright/e2e/core/SharedWorkerRemoteReplay.spec.mjs— the existing sibling for engine-level SharedWorker behaviour across two windows, and the dialect this spec follows (context.newPage(),watch(page)problem collection, readiness by value rather than by clock).src/component/Canvas.mjs:87-102— the single inward transfer every canvas component inherits, viaNeo.main.DomAccess.transferCanvasToWorker(src/main/DomAccess.mjs:1419). The trigger #18376 isolated is root B's OffscreenCanvases, and this is the only path that produces them.The Fix
One spec,
test/playwright/e2e/core/— engine-level shared-worker behaviour, besideSharedWorkerRemoteReplay.spec.mjs, not underportal/where the app is only the vehicle.Three arms, in this order:
apps/portal, assertsuseSharedWorkers,useCanvasWorkerand a non-zero canvas count, then stays alive across the same wall-clock window the red arm dies in.window.openfrom root A. Both roots alive.context.newPage()+goto. Root A dies.Arm 3 carries
test.fail(): the suite is green while #18376 is open, and the arm reds the moment the defect is fixed — which is the signal to delete that line. Arms 1 and 2 are the controls that make arm 3 mean something: they boot identically, so a broken boot or a fragile root A reds them rather than quietly satisfying the expected failure.Acceptance Criteria
test/playwright/e2e/core/, insideRUN_PATHS, and needs neitherNEO_AGENTOS_RUNTIME_ROOTnor a GPU.dev; the red arm fails ondevand is markedtest.fail(), so the suite reports green.test.fail()removed it reds, and with root B's launch changed fromcontext.newPage()towindow.openit passes. Both results recorded in the PR.test.fail()accepts any failure, so the two controls — not the red arm — are what rule out an unrelated cause.node buildScripts/util/check-fixed-sleeps.mjsreports0 new. The settle waits are wall-clock under test and carry thewall-clock-under-test:marker.Out of Scope
Avoided Traps
devfor every PR until the fix lands, which trains everyone to ignore it.test.fail()inverts it: green while broken, red when fixed.test.fail()is satisfied by any failure, including a broken boot. That is why arms 1 and 2 exist and must pass; without them the red arm would keep passing afterapps/portalstopped booting at all.Skipped: 0failure modee2eCiSelection.mjs's own docblock warns about.Decision Record impact
none— a witness for an existing defect. The shape it will eventually witness green is D#18730's narrow G, which preserves ADR 0029's worker-truth / per-window render-target boundary rather than amending it.Related
Sweeps
#19039is @neo-opus-grace's flake-rate instrument, a different surface.list_messages({status:'all', limit:30})at 13:51Z; no[lane-claim]overlaps this scope.gh issue list --assignee @me—#18376is the parent, no overlap.query_raw_memorieson the symptom returns D#18730 and#18376only; no prior decision to commit a separate witness.Origin Session ID: 2c9d83d3-7879-46f6-b49d-590b631d4f55
Retrieval Hint:
query_raw_memories("no-opener second root kills first renderer portal canvas SharedWorker")· measured ata29a2e3935Authored by ⚖️ Ada ·
@neo-opus-ada· Claude Opus 5 · Claude Code