The #15252 native Take 17 review exposed a large unused black strip inside Chrome. The first reading was a Workstation viewport defect; source and runtime receipts falsify that premise.
This is a film-harness geometry mismatch: the app fills the Playwright page, but the Playwright page remains smaller than the native Chrome content area after film staging enlarges the OS window.
Measured Failure
At frozen capture source 1cd8a37cd0f01e04ff7462e7c14353b3799ea5cc:
Browser.setWindowBounds reported a native Chrome window of 1602x980;
the same ready receipt reported window.innerWidth=1280 and window.innerHeight=800;
the native frame showed the Workstation ending at that fixed page boundary, with unused black browser space to the right;
resources/scss/src/container/Viewport.scss already gives body > .neo-viewportwidth: 100% and height: 100%.
The cause is explicit in test/playwright/e2e/workstation/WorkstationFiveBeatNL.spec.mjs: every mode declares viewport: {height: 800, width: 1280}, while film mode later changes only the native window through Browser.setWindowBounds.
Playwright documents viewport: null as the supported opt-out from fixed viewport emulation, making the page viewport follow the host OS window. Existing Neo precedent already uses this shape in DemoBVesselConversionNL.spec.mjs. The film path binds and receipts its host window explicitly, so it does not need the ordinary test path's fixed 1280x800 emulation.
Architectural Reality
There are two geometry authorities with different jobs:
ordinary E2E mode needs a deterministic emulated viewport for repeatable geometry assertions;
native film mode needs page geometry to follow the explicitly pinned native window that the camera records.
A Workstation CSS change would only conceal the harness error. Hard-coding the native outer bounds as a page viewport would also be wrong because browser chrome makes outer and inner dimensions different.
One guard is not enough: under fixed emulation, both the root rect and window.innerWidth / window.innerHeight remain 1280x800, so a root-versus-inner comparison can pass while the native window is still larger. The repair needs separate host-adoption and app-fill witnesses.
Proposed Fix
Keep {width: 1280, height: 800} plus the current emulated screen for ordinary E2E mode.
In NEO_FILM_TAKE=1, disable fixed viewport emulation (viewport: null) and omit the inert/conflicting emulated screen declaration.
Replace film-path assumptions that page.viewportSize() is truthy. Use live inner geometry or screencast metadata for diagnostic screencast sizing/cropping.
After Browser.setWindowBounds settles, receipt browser outer bounds, browser inner geometry, managed inner/outer geometry, DPR, and .neo-viewport bounds as distinct surfaces.
Add two fail-closed guards:
host adoption: film mode has page.viewportSize() === null, and browser chrome insets (outer - inner) remain stable across the native resize;
app fill:.neo-viewport begins at (0,0) and covers the live browser inner viewport within the documented tolerance.
Acceptance Criteria
Film and ordinary context options are conditional: film mode uses viewport: null without an emulated screen; ordinary mode retains deterministic 1280x800 viewport emulation.
A controlled film-mode boot with native bounds larger than 1280x800 proves host adoption through page.viewportSize() === null plus stable browser-chrome insets across native resize.
The .neo-viewport rect starts at (0,0) and covers the live browser inner viewport on both axes; the ready/frame-zero native still contains no unused right or bottom browser strip.
The host-adoption guard goes red if film mode is deliberately returned to fixed 1280x800 while the native window remains larger, even though a root-versus-inner comparison still passes.
Existing film-path page.viewportSize() and screencast-cropping consumers work when the Playwright viewport is null.
The full five-beat film journey remains green, including popup birth, conversion, docking, and reintegration geometry.
Native popup geometry remains governed by Workstation windowFeatures, and popup-to-manager.Window parity remains green.
Ordinary non-film runs retain the deterministic 1280x800 viewport and existing assertions.
The semantic-ready receipt keeps browser outer/inner, managed outer/inner, DPR, root bounds, and fixed-emulation state distinct.
Avoided Traps
Do not patch Workstation CSS: the app already fills the page it receives.
Do not use root-versus-inner equality as the host-adoption witness; fixed emulation makes both surfaces agree.
Do not set the page viewport to the native outer-window dimensions: browser chrome means they are not the same surface.
Do not remove deterministic viewport emulation from ordinary E2E runs.
Do not treat Playwright's per-page video canvas as visual authority under viewport: null; popup aspect changes can pad or crop it. Native desktop capture remains the film witness.
Do not accept a green semantic journey as visual proof; the native ready frame is the film-surface witness.
Prior Art / Duplicate Sweep
DemoBVesselConversionNL.spec.mjs already uses viewport: null and verifies popup-to-manager.Window geometry.
#15924 introduced deterministic native stage placement and is the direct closed precedent; it did not bind the page viewport to the resized native window.
#16090 is the separate missing drag-embodiment product defect.
Live title/body, latest-open, Memory Core, Knowledge Base, and A2A sweeps found no exact open duplicate.
Context
The #15252 native Take 17 review exposed a large unused black strip inside Chrome. The first reading was a Workstation viewport defect; source and runtime receipts falsify that premise.
This is a film-harness geometry mismatch: the app fills the Playwright page, but the Playwright page remains smaller than the native Chrome content area after film staging enlarges the OS window.
Measured Failure
At frozen capture source
1cd8a37cd0f01e04ff7462e7c14353b3799ea5cc:Browser.setWindowBoundsreported a native Chrome window of1602x980;window.innerWidth=1280andwindow.innerHeight=800;resources/scss/src/container/Viewport.scssalready givesbody > .neo-viewportwidth: 100%andheight: 100%.The cause is explicit in
test/playwright/e2e/workstation/WorkstationFiveBeatNL.spec.mjs: every mode declaresviewport: {height: 800, width: 1280}, while film mode later changes only the native window throughBrowser.setWindowBounds.Playwright documents
viewport: nullas the supported opt-out from fixed viewport emulation, making the page viewport follow the host OS window. Existing Neo precedent already uses this shape inDemoBVesselConversionNL.spec.mjs. The film path binds and receipts its host window explicitly, so it does not need the ordinary test path's fixed1280x800emulation.Architectural Reality
There are two geometry authorities with different jobs:
A Workstation CSS change would only conceal the harness error. Hard-coding the native outer bounds as a page viewport would also be wrong because browser chrome makes outer and inner dimensions different.
One guard is not enough: under fixed emulation, both the root rect and
window.innerWidth/window.innerHeightremain1280x800, so a root-versus-inner comparison can pass while the native window is still larger. The repair needs separate host-adoption and app-fill witnesses.Proposed Fix
{width: 1280, height: 800}plus the current emulatedscreenfor ordinary E2E mode.NEO_FILM_TAKE=1, disable fixed viewport emulation (viewport: null) and omit the inert/conflicting emulatedscreendeclaration.page.viewportSize()is truthy. Use live inner geometry or screencast metadata for diagnostic screencast sizing/cropping.Browser.setWindowBoundssettles, receipt browser outer bounds, browser inner geometry, managed inner/outer geometry, DPR, and.neo-viewportbounds as distinct surfaces.page.viewportSize() === null, and browser chrome insets (outer - inner) remain stable across the native resize;.neo-viewportbegins at(0,0)and covers the live browser inner viewport within the documented tolerance.Acceptance Criteria
viewport: nullwithout an emulatedscreen; ordinary mode retains deterministic1280x800viewport emulation.1280x800proves host adoption throughpage.viewportSize() === nullplus stable browser-chrome insets across native resize..neo-viewportrect starts at(0,0)and covers the live browser inner viewport on both axes; the ready/frame-zero native still contains no unused right or bottom browser strip.1280x800while the native window remains larger, even though a root-versus-inner comparison still passes.page.viewportSize()and screencast-cropping consumers work when the Playwright viewport isnull.windowFeatures, and popup-to-manager.Windowparity remains green.1280x800viewport and existing assertions.Avoided Traps
viewport: null; popup aspect changes can pad or crop it. Native desktop capture remains the film witness.Prior Art / Duplicate Sweep
DemoBVesselConversionNL.spec.mjsalready usesviewport: nulland verifies popup-to-manager.Windowgeometry.Related: #15252, #15924.
Origin Session ID:
019f9e1e-2ef1-72c3-a04d-6bc67a531a8bRetrieval hint:
query_raw_memories("film stage setWindowBounds fixed viewport 1280 800 black strip viewport null")