From 788b55cf980c7cc744c433fa4e73f56f284ea02f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:06:03 +0900 Subject: [PATCH 01/35] test(bidi): require reversible screen settings planning --- ...webdriver_bidi_screen_settings_contract.py | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 tests/test_webdriver_bidi_screen_settings_contract.py diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py new file mode 100644 index 000000000..5b9641b34 --- /dev/null +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -0,0 +1,46 @@ +"""Repository contract for reversible standard-BiDi screen settings planning.""" + +from __future__ import annotations + +import pathlib +import unittest + +ROOT = pathlib.Path(__file__).resolve().parents[1] +SOURCE = ROOT / "crates/originweave-bidi/src/presentation_capabilities.rs" + + +class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): + """Keep the screen presentation surface typed, scoped, and reversible.""" + + def test_standard_planner_uses_screen_settings_override(self) -> None: + """The qualified BiDi adapter must plan the standard screen-area command.""" + text = SOURCE.read_text(encoding="utf-8") + + self.assertIn("ScreenMetrics", text) + self.assertIn("SetScreenSettings", text) + self.assertIn("screen: ScreenMetrics", text) + self.assertIn("profile.screen()", text) + + def test_standard_cleanup_removes_only_its_screen_override(self) -> None: + """Reusable cleanup must use the command's nullable context-scoped reset.""" + text = SOURCE.read_text(encoding="utf-8") + cleanup = text.split("pub fn plan_standard_presentation_cleanup", maxsplit=1)[1] + cleanup = cleanup.split( + "pub const WEBDRIVER_BIDI_PRESENTATION_REVISION", maxsplit=1 + )[0] + + self.assertIn("ResetScreenSettings", cleanup) + self.assertNotIn("ResetMediaFeatures", cleanup) + + def test_screen_surface_is_admitted_by_the_standard_capability_map(self) -> None: + """A standard command that OriginWeave can reversibly own must be advertised.""" + text = SOURCE.read_text(encoding="utf-8") + surfaces = text.split( + "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 + )[1].split("];", maxsplit=1)[0] + + self.assertIn("PresentationSurface::Screen", surfaces) + + +if __name__ == "__main__": + unittest.main() From c75c37fce951ac69772e51cc38216583b0d9cd57 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:07:53 +0900 Subject: [PATCH 02/35] test(bidi): separate screen geometry from full screen surface --- ...webdriver_bidi_screen_settings_contract.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 5b9641b34..c74301830 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -1,4 +1,4 @@ -"""Repository contract for reversible standard-BiDi screen settings planning.""" +"""Repository contract for reversible standard-BiDi screen-area planning.""" from __future__ import annotations @@ -10,18 +10,18 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): - """Keep the screen presentation surface typed, scoped, and reversible.""" + """Keep screen geometry typed and reversible without overstating color-depth control.""" def test_standard_planner_uses_screen_settings_override(self) -> None: """The qualified BiDi adapter must plan the standard screen-area command.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) - self.assertIn("SetScreenSettings", text) + self.assertIn("SetScreenArea", text) self.assertIn("screen: ScreenMetrics", text) self.assertIn("profile.screen()", text) - def test_standard_cleanup_removes_only_its_screen_override(self) -> None: + def test_standard_cleanup_removes_only_its_screen_area_override(self) -> None: """Reusable cleanup must use the command's nullable context-scoped reset.""" text = SOURCE.read_text(encoding="utf-8") cleanup = text.split("pub fn plan_standard_presentation_cleanup", maxsplit=1)[1] @@ -29,17 +29,21 @@ def test_standard_cleanup_removes_only_its_screen_override(self) -> None: "pub const WEBDRIVER_BIDI_PRESENTATION_REVISION", maxsplit=1 )[0] - self.assertIn("ResetScreenSettings", cleanup) + self.assertIn("ResetScreenArea", cleanup) self.assertNotIn("ResetMediaFeatures", cleanup) - def test_screen_surface_is_admitted_by_the_standard_capability_map(self) -> None: - """A standard command that OriginWeave can reversibly own must be advertised.""" + def test_screen_surface_remains_fail_closed_until_color_depth_is_controlled(self) -> None: + """Screen area alone cannot satisfy ScreenMetrics because color depth remains observable.""" text = SOURCE.read_text(encoding="utf-8") surfaces = text.split( "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 )[1].split("];", maxsplit=1)[0] - self.assertIn("PresentationSurface::Screen", surfaces) + self.assertNotIn("PresentationSurface::Screen", surfaces) + self.assertIn( + "PresentationError::MissingSurface(PresentationSurface::Screen)", + "".join(text.split()), + ) if __name__ == "__main__": From 68da86f6c0e2ac81b2f1579411ebd9acfdea0288 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:08:35 +0900 Subject: [PATCH 03/35] feat(bidi): plan reversible screen area overrides --- .../src/presentation_capabilities.rs | 86 +++++++++++++------ 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index 70fdbcd0b..92a8acee3 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -1,8 +1,8 @@ use std::{error::Error, fmt}; use originweave_fingerprint::{ - DevicePixelRatio, PresentationError, PresentationSurface, PresentationTimeZone, ViewportBounds, - require_presentation_surfaces, + DevicePixelRatio, PresentationError, PresentationSurface, PresentationTimeZone, ScreenMetrics, + ViewportBounds, require_presentation_surfaces, }; const MAX_BROWSING_CONTEXT_BYTES: usize = 256; @@ -50,11 +50,20 @@ impl WebDriverBidiBrowsingContext { /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain the validated fingerprint value objects so a transport adapter cannot -/// bypass their bounds by constructing raw viewport, DPR, or time-zone values. This reusable-boundary -/// enum deliberately exposes no media-feature mutation command because this crate has no ownership or -/// snapshot witness that would make such mutation reversibly safe. +/// bypass their bounds by constructing raw screen, viewport, DPR, or time-zone values. Screen-area +/// commands project only width and height from [`ScreenMetrics`]; they do not control its color-depth +/// field and therefore do not satisfy the complete `PresentationSurface::Screen` contract. This +/// reusable-boundary enum deliberately exposes no media-feature mutation command because this crate +/// has no ownership or snapshot witness that would make such mutation reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { + /// Set web-exposed screen width and height without claiming color-depth control. + SetScreenArea { + /// Exact target browsing context. + context: WebDriverBidiBrowsingContext, + /// Validated screen metrics whose width and height form the protocol screen area. + screen: ScreenMetrics, + }, /// Set viewport dimensions and device-pixel ratio together. SetViewport { /// Exact target browsing context. @@ -71,6 +80,11 @@ pub enum WebDriverBidiPresentationCommand { /// Validated presentation time-zone identity. timezone: PresentationTimeZone, }, + /// Remove the web-exposed screen-area override for the exact browsing context. + ResetScreenArea { + /// Exact target browsing context. + context: WebDriverBidiBrowsingContext, + }, /// Restore the implementation-defined viewport and remove the device-pixel-ratio override. ResetViewport { /// Exact target browsing context. @@ -85,10 +99,12 @@ pub enum WebDriverBidiPresentationCommand { /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// -/// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the -/// pinned Working Draft. Reduced motion remains an expressible protocol capability, but this reusable -/// planning boundary neither installs nor exposes a media-mutation command because `features: null` -/// clears the complete media-feature configuration rather than restoring only OriginWeave's prior +/// Screen-area, viewport/device-pixel-ratio, and time-zone state each have a non-destructive nullable +/// reset in the pinned Working Draft. Screen-area application covers only width and height, so it does +/// not promote the complete `Screen` presentation surface while page-observable color depth remains +/// uncontrolled. Reduced motion remains an expressible protocol capability, but this reusable planning +/// boundary neither installs nor exposes a media-mutation command because `features: null` clears the +/// complete media-feature configuration rather than restoring only OriginWeave's prior /// `prefers-reduced-motion` value. The explicit arguments make this a partial-plan API: it cannot be /// mistaken for application of a complete [`originweave_fingerprint::PresentationProfile`]. A later /// Browser Session-owned adapter may introduce reduced-motion application only after it can prove a @@ -96,11 +112,16 @@ pub enum WebDriverBidiPresentationCommand { #[must_use] pub fn plan_standard_presentation_commands( context: &WebDriverBidiBrowsingContext, + screen: &ScreenMetrics, viewport: &ViewportBounds, device_pixel_ratio: DevicePixelRatio, timezone: PresentationTimeZone, -) -> [WebDriverBidiPresentationCommand; 2] { +) -> [WebDriverBidiPresentationCommand; 3] { [ + WebDriverBidiPresentationCommand::SetScreenArea { + context: context.clone(), + screen: *screen, + }, WebDriverBidiPresentationCommand::SetViewport { context: context.clone(), viewport: *viewport, @@ -113,17 +134,20 @@ pub fn plan_standard_presentation_commands( ] } -/// Plan cleanup that is non-destructive to unrelated media-feature overrides. +/// Plan cleanup that is non-destructive to unrelated presentation or media overrides. /// -/// The pinned Working Draft provides independently nullable reset paths for viewport/DPR and -/// time-zone state, so these two resets are safe to plan for a reusable browsing context. Media -/// cleanup is deliberately absent because `features: null` clears the complete media-feature -/// override configuration rather than selectively undoing `prefers-reduced-motion`. +/// The pinned Working Draft provides independently nullable context-scoped reset paths for screen +/// area, viewport/DPR, and time-zone state, so these three resets are safe to plan for a reusable +/// browsing context. Media cleanup is deliberately absent because `features: null` clears the complete +/// media-feature override configuration rather than selectively undoing `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( context: &WebDriverBidiBrowsingContext, -) -> [WebDriverBidiPresentationCommand; 2] { +) -> [WebDriverBidiPresentationCommand; 3] { [ + WebDriverBidiPresentationCommand::ResetScreenArea { + context: context.clone(), + }, WebDriverBidiPresentationCommand::ResetViewport { context: context.clone(), }, @@ -153,13 +177,14 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ PresentationSurface::ReducedMotion, ]; -/// Return presentation surfaces expressible through the pinned standard BiDi contract. +/// Return complete presentation surfaces expressible through the pinned standard BiDi contract. /// -/// Complete screen and ordered-language surfaces, hardware concurrency, and the -/// Chromium platform/User-Agent Client Hints surface are intentionally absent. -/// Reduced motion is listed as protocol capability even though reusable application leaves media -/// state untouched until a Browser Session owner supplies a restorable lifecycle and corresponding -/// command authority. +/// The protocol can now plan screen width/height through `emulation.setScreenSettingsOverride`, but +/// OriginWeave's `Screen` surface also includes color depth, so it remains intentionally absent until +/// that observable is controlled. Ordered-language surfaces, hardware concurrency, and the Chromium +/// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol +/// capability even though reusable application leaves media state untouched until a Browser Session +/// owner supplies a restorable lifecycle and corresponding command authority. #[must_use] pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSurface] { &WEBDRIVER_BIDI_PRESENTATION_SURFACES @@ -167,9 +192,10 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// -/// The current result is fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)`. -/// Callers must not translate that result into ambient-host fallback. +/// The current result remains fail-closed with +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because screen-area geometry does +/// not control the `ScreenMetrics` color-depth field. Callers must not translate that result into +/// ambient-host fallback. pub fn require_complete_presentation_profile() -> Result<(), PresentationError> { require_presentation_surfaces(webdriver_bidi_presentation_surfaces()) } @@ -245,11 +271,16 @@ mod tests { assert_eq!( plan_standard_presentation_commands( &context, + profile.screen(), profile.viewport(), profile.device_pixel_ratio(), profile.timezone(), ), [ + WebDriverBidiPresentationCommand::SetScreenArea { + context: context.clone(), + screen: *profile.screen(), + }, WebDriverBidiPresentationCommand::SetViewport { context: context.clone(), viewport: *profile.viewport(), @@ -271,6 +302,9 @@ mod tests { assert_eq!( plan_standard_presentation_cleanup(&context), [ + WebDriverBidiPresentationCommand::ResetScreenArea { + context: context.clone(), + }, WebDriverBidiPresentationCommand::ResetViewport { context: context.clone(), }, @@ -278,4 +312,4 @@ mod tests { ] ); } -} +} \ No newline at end of file From c28634f7f997d7586134e170b9d35a827bcd95c8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:12:41 +0900 Subject: [PATCH 04/35] refactor(bidi): keep screen-area intent exact --- .../src/presentation_capabilities.rs | 61 +++++++++++++++---- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index 92a8acee3..25bbbe22b 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -45,24 +45,58 @@ impl WebDriverBidiBrowsingContext { } } +/// Screen-area fields representable by `emulation.setScreenSettingsOverride`. +/// +/// Construction accepts only an already validated [`ScreenMetrics`] value and deliberately projects +/// width and height without carrying color depth. The type therefore cannot be mistaken for the +/// complete OriginWeave `PresentationSurface::Screen` contract. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct WebDriverBidiScreenArea { + width_px: u32, + height_px: u32, +} + +impl WebDriverBidiScreenArea { + /// Project the protocol-owned width and height from validated presentation screen metrics. + #[must_use] + pub const fn from_screen(screen: &ScreenMetrics) -> Self { + Self { + width_px: screen.width(), + height_px: screen.height(), + } + } + + /// Return the web-exposed screen width in CSS pixels. + #[must_use] + pub const fn width(&self) -> u32 { + self.width_px + } + + /// Return the web-exposed screen height in CSS pixels. + #[must_use] + pub const fn height(&self) -> u32 { + self.height_px + } +} + /// Typed standard-BiDi presentation command intent for one explicit browsing context. /// /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. -/// Presentation payloads retain the validated fingerprint value objects so a transport adapter cannot -/// bypass their bounds by constructing raw screen, viewport, DPR, or time-zone values. Screen-area -/// commands project only width and height from [`ScreenMetrics`]; they do not control its color-depth -/// field and therefore do not satisfy the complete `PresentationSurface::Screen` contract. This -/// reusable-boundary enum deliberately exposes no media-feature mutation command because this crate -/// has no ownership or snapshot witness that would make such mutation reversibly safe. +/// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw +/// screen, viewport, DPR, or time-zone validation. Screen-area commands carry only width and height; +/// they do not control color depth and therefore do not satisfy the complete +/// `PresentationSurface::Screen` contract. This reusable-boundary enum deliberately exposes no +/// media-feature mutation command because this crate has no ownership or snapshot witness that would +/// make such mutation reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { /// Set web-exposed screen width and height without claiming color-depth control. SetScreenArea { /// Exact target browsing context. context: WebDriverBidiBrowsingContext, - /// Validated screen metrics whose width and height form the protocol screen area. - screen: ScreenMetrics, + /// Exact standard-BiDi screen-area payload derived from validated screen metrics. + screen_area: WebDriverBidiScreenArea, }, /// Set viewport dimensions and device-pixel ratio together. SetViewport { @@ -120,7 +154,7 @@ pub fn plan_standard_presentation_commands( [ WebDriverBidiPresentationCommand::SetScreenArea { context: context.clone(), - screen: *screen, + screen_area: WebDriverBidiScreenArea::from_screen(screen), }, WebDriverBidiPresentationCommand::SetViewport { context: context.clone(), @@ -179,7 +213,7 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ /// Return complete presentation surfaces expressible through the pinned standard BiDi contract. /// -/// The protocol can now plan screen width/height through `emulation.setScreenSettingsOverride`, but +/// The protocol can plan screen width/height through `emulation.setScreenSettingsOverride`, but /// OriginWeave's `Screen` surface also includes color depth, so it remains intentionally absent until /// that observable is controlled. Ordered-language surfaces, hardware concurrency, and the Chromium /// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol @@ -268,6 +302,9 @@ mod tests { WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); assert_eq!(context.as_str(), "context-17"); + let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); + assert_eq!(screen_area.width(), 1920); + assert_eq!(screen_area.height(), 1080); assert_eq!( plan_standard_presentation_commands( &context, @@ -279,7 +316,7 @@ mod tests { [ WebDriverBidiPresentationCommand::SetScreenArea { context: context.clone(), - screen: *profile.screen(), + screen_area, }, WebDriverBidiPresentationCommand::SetViewport { context: context.clone(), @@ -312,4 +349,4 @@ mod tests { ] ); } -} \ No newline at end of file +} From a6d88d6d8488349f731f84498afd2b034b403c26 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:12:56 +0900 Subject: [PATCH 05/35] test(bidi): require exact screen-area value object --- ...test_webdriver_bidi_screen_settings_contract.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index c74301830..8ab457985 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -17,8 +17,10 @@ def test_standard_planner_uses_screen_settings_override(self) -> None: text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) + self.assertIn("WebDriverBidiScreenArea", text) self.assertIn("SetScreenArea", text) - self.assertIn("screen: ScreenMetrics", text) + self.assertIn("screen_area: WebDriverBidiScreenArea", text) + self.assertIn("screen: &ScreenMetrics", text) self.assertIn("profile.screen()", text) def test_standard_cleanup_removes_only_its_screen_area_override(self) -> None: @@ -45,6 +47,16 @@ def test_screen_surface_remains_fail_closed_until_color_depth_is_controlled(self "".join(text.split()), ) + def test_screen_area_payload_does_not_carry_color_depth(self) -> None: + """The command intent must not imply authority over an unapplied screen observable.""" + text = SOURCE.read_text(encoding="utf-8") + screen_area = text.split("pub struct WebDriverBidiScreenArea", maxsplit=1)[1] + screen_area = screen_area.split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] + + self.assertIn("width_px: u32", screen_area) + self.assertIn("height_px: u32", screen_area) + self.assertNotIn("color_depth", screen_area) + if __name__ == "__main__": unittest.main() From a384fd4842509c8b161b5dea1bb4c4c64bf94ca6 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:13:17 +0900 Subject: [PATCH 06/35] docs(bidi): trace screen-area planning boundary --- .../webdriver-bidi-screen-area-planning.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 docs/traceability/webdriver-bidi-screen-area-planning.md diff --git a/docs/traceability/webdriver-bidi-screen-area-planning.md b/docs/traceability/webdriver-bidi-screen-area-planning.md new file mode 100644 index 000000000..7cd150eab --- /dev/null +++ b/docs/traceability/webdriver-bidi-screen-area-planning.md @@ -0,0 +1,46 @@ +# WebDriver BiDi screen-area planning traceability + +## Problem + +The runtime-qualified WebDriver BiDi adapter already plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. OriginWeave did not expose that standard screen-area operation in its typed planning boundary. + +This is a narrower gap than the complete `PresentationSurface::Screen` requirement. `ScreenMetrics` includes width, height, and color depth, but the WebDriver BiDi `screenArea` payload controls only width and height. Advertising the complete Screen surface after adding this command would therefore create a false-green admission path. + +## Constraints + +- Keep browser-domain truth in OriginWeave; WebDriver BiDi remains an adapter, not policy authority. +- Preserve the runtime-qualified 3 September 2026 Working Draft pin. Publication freshness is owned separately by `webdriver-bidi-publication-current.md`. +- Reuse validated presentation value objects rather than reopen raw width/height validation in the adapter. +- A reusable browsing context may plan only overrides with a context-scoped, non-destructive reset. +- Do not add media-feature cleanup, ambient-host fallback, live protocol I/O, command-ACK success semantics, or Chromium-specific authority here. + +## Alternatives + +1. **Keep screen area unplanned.** Rejected because the qualified standard already provides an independently resettable screen-area operation and omitting it leaves a useful standard capability unused. +2. **Mark `PresentationSurface::Screen` supported after planning width/height.** Rejected because color depth remains page-observable and uncontrolled. +3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would then contain a field the protocol operation does not apply, making evidence and later serialization authority ambiguous. +4. **Project a dedicated `WebDriverBidiScreenArea` from validated `ScreenMetrics`.** Selected. The adapter carries exactly the standard-owned width/height payload while retaining the complete Screen fail-closed invariant. + +## Decision + +`originweave-bidi` plans `SetScreenArea` before viewport/DPR and time-zone operations and plans the matching `ResetScreenArea` during reusable-context cleanup. `WebDriverBidiScreenArea` can only be derived from validated `ScreenMetrics`; it contains width and height only. The complete capability map intentionally continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until another reviewed owner controls color depth as well. + +The planner produces typed intent only. Transport execution, page-observed post-conditions, browser/session cleanup evidence, crash recovery, and the remaining Chromium-only presentation surfaces stay with the existing #292/#299 acceptance path and its canonical runtime owners. + +## Evidence and acceptance + +The test-first lineage begins at PR #310 test-only commits and requires: + +- a typed screen-area intent derived from validated screen metrics; +- a context-scoped screen-area reset; +- no media-feature reset; +- no color-depth field in the screen-area command value object; and +- continued fail-closed complete Screen admission. + +Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence and must not be transferred from predecessor heads. + +## References + +World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ + +World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* [Working Draft; latest publication tracked separately]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ From 2cc97adc324e7e6baa79b4b6a84c96ba16f7643d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:13:57 +0900 Subject: [PATCH 07/35] docs(adr): record reversible BiDi screen-area planning --- docs/adr/0107-browser-protocol-adapter-strategy.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/adr/0107-browser-protocol-adapter-strategy.md b/docs/adr/0107-browser-protocol-adapter-strategy.md index 066c22942..b4b9ba570 100644 --- a/docs/adr/0107-browser-protocol-adapter-strategy.md +++ b/docs/adr/0107-browser-protocol-adapter-strategy.md @@ -46,7 +46,7 @@ The version boundary is explicit: the protected-main routing foundation and acti PR #293 was merged into PR #229 on 2026-09-09, so its `originweave-bidi` capability boundary is inherited by this parent rather than remaining a separate active stacked slice. The adapter remains runtime-qualified 3 September 2026 against the immutable WebDriver BiDi Working Draft URI `https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`. W3C has since published the latest published 9 September 2026 Working Draft; publication freshness is recorded separately in `docs/traceability/webdriver-bidi-publication-current.md` and does not silently repin runtime compatibility. A newer runtime pin requires a dedicated compatibility/conformance change and pinned-browser evidence. -The inherited capability map delegates complete-profile admission to `originweave-fingerprint` and intentionally excludes `Screen`, `Languages`, `HardwareConcurrency`, and `Platform`: the standard screen command omits color depth, while the locale command cannot prove ordered language preferences. Standard BiDi alone must therefore return the kernel's first `MissingSurface(Screen)` result rather than accept ambient host values. The adapter can derive typed viewport/DPR and timezone command intents plus matching cleanup intents for one bounded reusable browsing-context identifier. Reduced motion remains an expressible protocol capability but is excluded from the reusable plan because the standard cannot selectively restore prior media state; no caller-mintable exclusive-reset type substitutes for Browser Session lifecycle evidence. Planning does not send a command, create an acknowledgement, apply or prove cleanup of a profile, or produce page-observed evidence. Those remain #292 follow-up work and require exact-head verification plus a version-pinned Chromium/CDP adapter for the remainder. +The inherited capability map delegates complete-profile admission to `originweave-fingerprint` and intentionally excludes `Screen`, `Languages`, `HardwareConcurrency`, and `Platform`: the standard screen command omits color depth, while the locale command cannot prove ordered language preferences. Standard BiDi alone must therefore return the kernel's first `MissingSurface(Screen)` result rather than accept ambient host values. PR #310 extends the typed reusable-context plan with the standard `emulation.setScreenSettingsOverride` screen-area operation and its nullable reset, alongside viewport/DPR and timezone. Its `WebDriverBidiScreenArea` projects only width and height from validated `ScreenMetrics`; it deliberately does not carry color depth and therefore does not promote the complete `Screen` capability. Reduced motion remains an expressible protocol capability but is excluded from the reusable plan because the standard cannot selectively restore prior media state; no caller-mintable exclusive-reset type substitutes for Browser Session lifecycle evidence. Planning does not send a command, create an acknowledgement, apply or prove cleanup of a profile, or produce page-observed evidence. Those remain #292 follow-up work and require exact-head verification plus a version-pinned Chromium/CDP adapter for the remainder. The detailed decision and acceptance boundary are recorded in `docs/traceability/webdriver-bidi-screen-area-planning.md`. ## Consequences @@ -68,7 +68,7 @@ Require version-negotiation tests, schema/property tests, malformed-message test For the protected-main `tools/call` foundation, acceptance includes deterministic method and tool-name bounds/syntax, exact header/body method and tool-name correlation only after both sides are bounded, explicit invalid-method/invalid-tool-name/unknown-tool rejection, one unambiguous tool-to-action registry, independent capability/risk expectations, route/action mismatch denial before ordinary policy evaluation, exact 100% owned-production coverage, and integrated review evidence from PR #168. For active PR #170, exact-current acceptance additionally requires bounded protocol metadata before cross-field comparison, required client-capabilities presence, bounded `tools/list` method correlation, rejection of unissued cursors, deterministic result/cache semantics, exact 100% owned-production coverage, and unchanged-head CI/security/review evidence. These checks do not substitute for complete transport or adapter conformance. -For the inherited PR #293 capability-boundary delta now carried by PR #229, acceptance requires the original regression proving the absence of an `originweave-bidi` bounded context on its predecessor, cleanup regressions that refuse to leave adapter-owned overrides behind, and exact-head Rust/Python/rustdoc/Clippy/coverage verification that the minimal adapter compiles and the runtime-qualified standard set fails with the canonical fingerprint-kernel missing-surface error. This is not acceptance of #292 as a whole. Real pinned-Chromium application, page-observed post-condition evidence, navigation/renderer/crash/cleanup behavior, and the Chromium-only CDP remainder still require realistic browser E2E. Publication of a newer Working Draft is not compatibility evidence and cannot by itself change this acceptance basis. +For the inherited PR #293 capability-boundary delta now carried by PR #229, acceptance requires the original regression proving the absence of an `originweave-bidi` bounded context on its predecessor, cleanup regressions that refuse to leave adapter-owned overrides behind, and exact-head Rust/Python/rustdoc/Clippy/coverage verification that the minimal adapter compiles and the runtime-qualified standard set fails with the canonical fingerprint-kernel missing-surface error. PR #310 additionally requires exact screen-area projection from validated `ScreenMetrics`, matching context-scoped reset intent, absence of color depth from the standard payload object, and continued `MissingSurface(Screen)` admission until color depth is independently controlled. This is not acceptance of #292 as a whole. Real pinned-Chromium application, page-observed post-condition evidence, navigation/renderer/crash/cleanup behavior, and the Chromium-only CDP remainder still require realistic browser E2E. Publication of a newer Working Draft is not compatibility evidence and cannot by itself change this acceptance basis. ## Migration and rollback @@ -100,4 +100,4 @@ World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; ## Related documents -See `docs/API_CONTRACT.md`, `docs/TRD.md`, `docs/doctoring.md`, `docs/doctoring/product-documentation-baseline.md`, `docs/traceability/README.md`, `docs/traceability/webdriver-bidi-publication-current.md`, and `docs/DATA_GOVERNANCE.md`. \ No newline at end of file +See `docs/API_CONTRACT.md`, `docs/TRD.md`, `docs/doctoring.md`, `docs/doctoring/product-documentation-baseline.md`, `docs/traceability/README.md`, `docs/traceability/webdriver-bidi-publication-current.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/DATA_GOVERNANCE.md`. From f507439b482e6a4b0f7a2ed2df3d833abf27c676 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:15:13 +0900 Subject: [PATCH 08/35] docs(doctoring): pin BiDi screen-area semantics --- docs/doctoring/webdriver-bidi-screen-area.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/doctoring/webdriver-bidi-screen-area.md diff --git a/docs/doctoring/webdriver-bidi-screen-area.md b/docs/doctoring/webdriver-bidi-screen-area.md new file mode 100644 index 000000000..00ee6499d --- /dev/null +++ b/docs/doctoring/webdriver-bidi-screen-area.md @@ -0,0 +1,15 @@ +# WebDriver BiDi screen-area doctoring + +The runtime-qualified protocol identity remains the W3C WebDriver BiDi Working Draft published 3 September 2026. The current 9 September 2026 publication retains the same relevant `emulation.setScreenSettingsOverride` shape, but publication freshness does not itself change OriginWeave's runtime pin. + +For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. A non-null screen area changes the web-exposed screen dimensions for the target context; `screenArea: null` removes that override. This gives OriginWeave a symmetric apply/reset path suitable for reusable-context planning. + +The standard operation does **not** control color depth. OriginWeave's `ScreenMetrics` and `PresentationSurface::Screen` contract include color depth as well as dimensions. The adapter therefore projects a dedicated `WebDriverBidiScreenArea` containing only validated width and height and continues to reject complete-profile admission with `MissingSurface(Screen)`. Treating the screen-area command as proof of the complete Screen surface would overstate protocol authority. + +This evidence changes only typed command planning. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence. + +## References + +World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ + +World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* [Working Draft; latest publication tracked separately]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ From a9c0faec63907a01198d41d274b03c32381f58a2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:16:26 +0900 Subject: [PATCH 09/35] docs(changelog): record reversible BiDi screen-area planning --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10e5986f6..a0c1b69b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to OriginWeave are documented in this file. The format follo ## [Unreleased] -- Made the reusable WebDriver BiDi presentation planner accept only viewport, DPR, and timezone inputs. It no longer accepts a complete presentation profile while leaving unsupported or lifecycle-unrestorable surfaces unapplied. +- Extended the reusable WebDriver BiDi presentation planner with a context-scoped `emulation.setScreenSettingsOverride` screen-area intent and matching reset, alongside viewport/DPR and timezone. The adapter projects only validated width and height into a dedicated `WebDriverBidiScreenArea`; color depth remains uncontrolled, so complete `PresentationSurface::Screen` admission still fails closed instead of treating screen geometry as the whole screen fingerprint surface. - Refreshed the product-gap queue to 126 open pull requests (54 ready, 72 draft) after #190, #188, #185, #192, #182, #184, #115, #181, #116, #117, #118, #183, #114, #127, #112, #109, #186, #110, #108, #111, #174, and #113 were merged into their immediate stacked prerequisites. PRs #147, #146, #145, #144, #143, #142, #141, #139, #136, #132, #129, and #128 moved to ready after exact-head checks and thread review; these are queue-consolidation results, not protected-main shipment. ### Fixed @@ -12,7 +12,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Restored canonical Rust formatting for the WebDriver BiDi presentation cleanup assertion so exact-head contracts can execute the test, Clippy, and rustdoc gates. ### Added -- Added a version-pinned `originweave-bidi` presentation-capability boundary for the W3C WebDriver BiDi Working Draft published on 3 September 2026 (`https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`). It depends inward on `originweave-fingerprint`, plans only the symmetrically restorable viewport/DPR and timezone commands for one bounded reusable browsing context, and fails first on the complete screen surface because standard BiDi cannot prove color depth or ordered languages. Reduced motion remains an expressible protocol capability but is not installed by the reusable plan because standard cleanup cannot selectively restore prior media state. No caller-mintable exclusive-reset type is exposed; a Browser Session owner must prove a disposable lifecycle or complete prior-state restoration. Planning performs no transport I/O or acknowledgement, cleanup, ownership, or page-observed evidence. Hardware concurrency and the complete Chromium platform/User-Agent Client Hints surface still require a separate versioned Chromium adapter. +- Added a version-pinned `originweave-bidi` presentation-capability boundary for the W3C WebDriver BiDi Working Draft published on 3 September 2026 (`https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`). It depends inward on `originweave-fingerprint`, plans the symmetrically restorable screen-area, viewport/DPR, and timezone commands for one bounded reusable browsing context, and still fails first on the complete screen surface because standard BiDi screen-area emulation cannot prove color depth or ordered languages. Reduced motion remains an expressible protocol capability but is not installed by the reusable plan because standard cleanup cannot selectively restore prior media state. No caller-mintable exclusive-reset type is exposed; a Browser Session owner must prove a disposable lifecycle or complete prior-state restoration. Planning performs no transport I/O or acknowledgement, cleanup, ownership, or page-observed evidence. Hardware concurrency and the complete Chromium platform/User-Agent Client Hints surface still require a separate versioned Chromium adapter. - Added a bounded Rust presentation-identity kernel for explicit browser-visible profiles and credential-free replay digests, including control-safe mobile UA-CH model values; applying those profiles to Chromium and proving page-observed effects remain separate adapter and browser-E2E work. - Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate. From e3b2b412d8ad880c87354fb3ffd5f5b4ff6cde0d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:20:12 +0900 Subject: [PATCH 10/35] docs(doctoring): align BiDi screen-area evidence --- docs/doctoring.md | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/docs/doctoring.md b/docs/doctoring.md index 44fb51d13..7e80d13f2 100644 --- a/docs/doctoring.md +++ b/docs/doctoring.md @@ -53,30 +53,37 @@ screen, user-agent, viewport, and time-zone emulation commands under the immutab publication `https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`. The screen shape contains width and height but not color depth, and locale accepts one value rather than an ordered language list, so neither proves the corresponding complete -OriginWeave surface. The draft also does not define a hardware-concurrency -override. Chromium's tip-of-tree DevTools Protocol exposes -`Emulation.setHardwareConcurrencyOverride` as Experimental and warns that -tip-of-tree commands can change without notice. OriginWeave therefore records -required presentation surfaces in a protocol-neutral Rust admission contract; -the adapter records those four complete standard surfaces as protocol -capabilities, while the reusable-context plan emits only two typed command -intents—viewport/DPR and timezone—bound to one bounded opaque browsing context. - -Cleanup authority is asymmetric. Nullable viewport and timezone operations can -restore those adapter-owned overrides on a reusable context, so generic cleanup -plans reset viewport/DPR and timezone. By contrast, +OriginWeave surface. The 9 September 2026 Working Draft retains the relevant +`emulation.setScreenSettingsOverride` screen-area shape; that publication update is +tracked separately and does not silently repin runtime compatibility. The draft also +does not define a hardware-concurrency override. Chromium's tip-of-tree DevTools +Protocol exposes `Emulation.setHardwareConcurrencyOverride` as Experimental and +warns that tip-of-tree commands can change without notice. OriginWeave therefore +records required presentation surfaces in a protocol-neutral Rust admission +contract. The capability map records the same four complete standard surfaces as +before, while the reusable-context plan now emits three typed command intents—screen +area, viewport/DPR, and timezone—bound to one bounded opaque browsing context. The +dedicated screen-area value projects only width and height from validated +`ScreenMetrics`; it carries no color depth, so complete `PresentationSurface::Screen` +admission remains fail-closed. + +Cleanup authority is asymmetric. Nullable screen-area, viewport, and timezone +operations can remove those adapter-owned overrides on a reusable context, so generic +cleanup plans reset screen area, viewport/DPR, and timezone. By contrast, `emulation.setMediaFeaturesOverride` with `features: null` unsets the target's complete media-feature override configuration rather than selectively reversing only `prefers-reduced-motion`. The reusable-context plan therefore neither installs reduced motion nor emits a media reset. No caller-mintable exclusive reset is exposed as ownership evidence; a Browser Session owner must prove a -disposable context lifecycle or restore the complete prior media configuration. Constructing application or cleanup -intents performs no transport I/O and cannot be treated as acknowledgement, -successful cleanup, ownership evidence, or page-observed presentation evidence. -A later pinned Chromium adapter must capability-negotiate every surface, observe -post-conditions after apply and cleanup, and either prove exclusive disposable -context ownership or restore the complete pre-existing media configuration -before reusing the browser boundary. +disposable context lifecycle or restore the complete prior media configuration. +Constructing application or cleanup intents performs no transport I/O and cannot be +treated as acknowledgement, successful cleanup, ownership evidence, or page-observed +presentation evidence. A later pinned Chromium adapter must capability-negotiate every +surface, observe post-conditions after apply and cleanup, and either prove exclusive +disposable context ownership or restore the complete pre-existing media configuration +before reusing the browser boundary. The focused evidence and alternatives for the +screen-area slice are recorded in `docs/doctoring/webdriver-bidi-screen-area.md` and +`docs/traceability/webdriver-bidi-screen-area-planning.md`. ### Extension-to-Agent grant origin binding @@ -266,6 +273,8 @@ World Wide Web Consortium. (2013). *PROV-O: The PROV ontology*. https://www.w3.o World Wide Web Consortium. (2025, September 25). *Mitigating browser fingerprinting in Web specifications*. https://www.w3.org/TR/fingerprinting-guidance/ +World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* (W3C Working Draft). https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ + World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* (W3C Working Draft). https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ World Wide Web Consortium. (2026). *WebDriver BiDi* (Editor's Draft). https://w3c.github.io/webdriver-bidi/ From 8f74471e1a5414e8781531f968b46807e2d7e3d8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:32:09 +0900 Subject: [PATCH 11/35] test(bidi): fail on unmodeled available screen mutation --- ...webdriver_bidi_screen_settings_contract.py | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 8ab457985..f2f104a75 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -7,32 +7,50 @@ ROOT = pathlib.Path(__file__).resolve().parents[1] SOURCE = ROOT / "crates/originweave-bidi/src/presentation_capabilities.rs" +FINGERPRINT_SOURCE = ROOT / "crates/originweave-fingerprint/src/lib.rs" class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): - """Keep screen geometry typed and reversible without overstating color-depth control.""" + """Keep screen geometry typed and reversible without overstating observable control.""" def test_standard_planner_uses_screen_settings_override(self) -> None: - """The qualified BiDi adapter must plan the standard screen-area command.""" + """The qualified BiDi adapter must expose the standard screen-area command.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) self.assertIn("WebDriverBidiScreenArea", text) self.assertIn("SetScreenArea", text) - self.assertIn("screen_area: WebDriverBidiScreenArea", text) - self.assertIn("screen: &ScreenMetrics", text) - self.assertIn("profile.screen()", text) + + def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: + """A profile-derived reusable plan must not change an unmodelled page observable.""" + source = SOURCE.read_text(encoding="utf-8") + fingerprint = FINGERPRINT_SOURCE.read_text(encoding="utf-8") + screen_metrics = fingerprint.split("pub struct ScreenMetrics", maxsplit=1)[1] + screen_metrics = screen_metrics.split("impl ScreenMetrics", maxsplit=1)[0] + planner = source.split("pub fn plan_standard_presentation_commands", maxsplit=1)[1] + planner = planner.split("pub fn plan_standard_presentation_cleanup", maxsplit=1)[0] + + models_available_screen_area = ( + "available_width" in screen_metrics + and "available_height" in screen_metrics + ) + profile_plans_screen_override = ( + "screen: &ScreenMetrics" in planner and "SetScreenArea" in planner + ) + + self.assertTrue( + models_available_screen_area or not profile_plans_screen_override, + "WebDriver BiDi screen settings override also changes screen.availWidth/availHeight; " + "the reusable profile-derived plan must model those observables or keep the override " + "behind a separately explicit partial intent", + ) def test_standard_cleanup_removes_only_its_screen_area_override(self) -> None: - """Reusable cleanup must use the command's nullable context-scoped reset.""" + """An explicit screen-area cleanup must use the command's nullable context-scoped reset.""" text = SOURCE.read_text(encoding="utf-8") - cleanup = text.split("pub fn plan_standard_presentation_cleanup", maxsplit=1)[1] - cleanup = cleanup.split( - "pub const WEBDRIVER_BIDI_PRESENTATION_REVISION", maxsplit=1 - )[0] - self.assertIn("ResetScreenArea", cleanup) - self.assertNotIn("ResetMediaFeatures", cleanup) + self.assertIn("ResetScreenArea", text) + self.assertNotIn("ResetMediaFeatures", text) def test_screen_surface_remains_fail_closed_until_color_depth_is_controlled(self) -> None: """Screen area alone cannot satisfy ScreenMetrics because color depth remains observable.""" From 11bc8097187629589ad06b318777ab6db8622f57 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:33:28 +0900 Subject: [PATCH 12/35] fix(bidi): isolate coupled screen-area override --- .../src/presentation_capabilities.rs | 157 ++++++++++++------ 1 file changed, 103 insertions(+), 54 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index 25bbbe22b..6ac5719e1 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -45,11 +45,13 @@ impl WebDriverBidiBrowsingContext { } } -/// Screen-area fields representable by `emulation.setScreenSettingsOverride`. +/// Coupled total-and-available screen-area fields representable by +/// `emulation.setScreenSettingsOverride`. /// -/// Construction accepts only an already validated [`ScreenMetrics`] value and deliberately projects -/// width and height without carrying color depth. The type therefore cannot be mistaken for the -/// complete OriginWeave `PresentationSurface::Screen` contract. +/// WebDriver BiDi applies one rectangle to both the web-exposed total screen area and available +/// screen area. Construction therefore remains an explicit partial capability: it projects width and +/// height from validated [`ScreenMetrics`] but does not claim that the presentation profile models the +/// resulting `screen.availWidth` / `screen.availHeight` observables or screen color depth. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct WebDriverBidiScreenArea { width_px: u32, @@ -57,7 +59,11 @@ pub struct WebDriverBidiScreenArea { } impl WebDriverBidiScreenArea { - /// Project the protocol-owned width and height from validated presentation screen metrics. + /// Project the protocol-owned rectangle from validated presentation screen metrics. + /// + /// The returned value intentionally means that total and available screen areas will be coupled to + /// the same rectangle. It must not be inserted into a profile-derived reusable plan unless the + /// presentation schema has first modelled and authorized those available-area observables. #[must_use] pub const fn from_screen(screen: &ScreenMetrics) -> Self { Self { @@ -66,13 +72,13 @@ impl WebDriverBidiScreenArea { } } - /// Return the web-exposed screen width in CSS pixels. + /// Return the width applied to both total and available web-exposed screen areas. #[must_use] pub const fn width(&self) -> u32 { self.width_px } - /// Return the web-exposed screen height in CSS pixels. + /// Return the height applied to both total and available web-exposed screen areas. #[must_use] pub const fn height(&self) -> u32 { self.height_px @@ -84,18 +90,18 @@ impl WebDriverBidiScreenArea { /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// screen, viewport, DPR, or time-zone validation. Screen-area commands carry only width and height; -/// they do not control color depth and therefore do not satisfy the complete +/// screen, viewport, DPR, or time-zone validation. Screen-area commands couple total and available +/// screen geometry, do not control color depth, and therefore do not satisfy the complete /// `PresentationSurface::Screen` contract. This reusable-boundary enum deliberately exposes no /// media-feature mutation command because this crate has no ownership or snapshot witness that would /// make such mutation reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { - /// Set web-exposed screen width and height without claiming color-depth control. + /// Set total and available web-exposed screen width and height together. SetScreenArea { /// Exact target browsing context. context: WebDriverBidiBrowsingContext, - /// Exact standard-BiDi screen-area payload derived from validated screen metrics. + /// Exact coupled standard-BiDi screen-area payload derived from validated screen metrics. screen_area: WebDriverBidiScreenArea, }, /// Set viewport dimensions and device-pixel ratio together. @@ -114,7 +120,7 @@ pub enum WebDriverBidiPresentationCommand { /// Validated presentation time-zone identity. timezone: PresentationTimeZone, }, - /// Remove the web-exposed screen-area override for the exact browsing context. + /// Remove the coupled total-and-available screen-area override for the exact browsing context. ResetScreenArea { /// Exact target browsing context. context: WebDriverBidiBrowsingContext, @@ -131,31 +137,54 @@ pub enum WebDriverBidiPresentationCommand { }, } +/// Plan one explicit partial screen-area override for a bounded browsing context. +/// +/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is +/// deliberately separate from [`plan_standard_presentation_commands`] because the current +/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`; callers must not +/// mistake this explicit coupled operation for application of the complete profile. +#[must_use] +pub fn plan_explicit_screen_area_override( + context: &WebDriverBidiBrowsingContext, + screen: &ScreenMetrics, +) -> WebDriverBidiPresentationCommand { + WebDriverBidiPresentationCommand::SetScreenArea { + context: context.clone(), + screen_area: WebDriverBidiScreenArea::from_screen(screen), + } +} + +/// Plan cleanup for one explicitly applied coupled screen-area override. +/// +/// The pinned Working Draft defines `screenArea: null` as removal of that exact context-scoped +/// override. Planning the reset does not prove transport execution or post-cleanup page observation. +#[must_use] +pub fn plan_explicit_screen_area_cleanup( + context: &WebDriverBidiBrowsingContext, +) -> WebDriverBidiPresentationCommand { + WebDriverBidiPresentationCommand::ResetScreenArea { + context: context.clone(), + } +} + /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// -/// Screen-area, viewport/device-pixel-ratio, and time-zone state each have a non-destructive nullable -/// reset in the pinned Working Draft. Screen-area application covers only width and height, so it does -/// not promote the complete `Screen` presentation surface while page-observable color depth remains -/// uncontrolled. Reduced motion remains an expressible protocol capability, but this reusable planning -/// boundary neither installs nor exposes a media-mutation command because `features: null` clears the -/// complete media-feature configuration rather than restoring only OriginWeave's prior -/// `prefers-reduced-motion` value. The explicit arguments make this a partial-plan API: it cannot be -/// mistaken for application of a complete [`originweave_fingerprint::PresentationProfile`]. A later -/// Browser Session-owned adapter may introduce reduced-motion application only after it can prove a -/// genuinely disposable lifecycle or a complete snapshot/restore path. +/// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the +/// pinned Working Draft. The screen-settings override is excluded from this profile-derived plan even +/// though it is reversible because it also changes the unmodelled page-observable available screen +/// area. Reduced motion remains an expressible protocol capability, but this reusable planning boundary +/// neither installs nor exposes a media-mutation command because `features: null` clears the complete +/// media-feature configuration rather than restoring only OriginWeave's prior `prefers-reduced-motion` +/// value. The explicit arguments make this a partial-plan API: it cannot be mistaken for application of +/// a complete [`originweave_fingerprint::PresentationProfile`]. #[must_use] pub fn plan_standard_presentation_commands( context: &WebDriverBidiBrowsingContext, - screen: &ScreenMetrics, viewport: &ViewportBounds, device_pixel_ratio: DevicePixelRatio, timezone: PresentationTimeZone, -) -> [WebDriverBidiPresentationCommand; 3] { +) -> [WebDriverBidiPresentationCommand; 2] { [ - WebDriverBidiPresentationCommand::SetScreenArea { - context: context.clone(), - screen_area: WebDriverBidiScreenArea::from_screen(screen), - }, WebDriverBidiPresentationCommand::SetViewport { context: context.clone(), viewport: *viewport, @@ -170,18 +199,16 @@ pub fn plan_standard_presentation_commands( /// Plan cleanup that is non-destructive to unrelated presentation or media overrides. /// -/// The pinned Working Draft provides independently nullable context-scoped reset paths for screen -/// area, viewport/DPR, and time-zone state, so these three resets are safe to plan for a reusable -/// browsing context. Media cleanup is deliberately absent because `features: null` clears the complete +/// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR +/// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area +/// cleanup is deliberately separate because this reusable plan does not install the coupled total-and- +/// available screen override. Media cleanup is absent because `features: null` clears the complete /// media-feature override configuration rather than selectively undoing `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( context: &WebDriverBidiBrowsingContext, -) -> [WebDriverBidiPresentationCommand; 3] { +) -> [WebDriverBidiPresentationCommand; 2] { [ - WebDriverBidiPresentationCommand::ResetScreenArea { - context: context.clone(), - }, WebDriverBidiPresentationCommand::ResetViewport { context: context.clone(), }, @@ -213,9 +240,10 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ /// Return complete presentation surfaces expressible through the pinned standard BiDi contract. /// -/// The protocol can plan screen width/height through `emulation.setScreenSettingsOverride`, but -/// OriginWeave's `Screen` surface also includes color depth, so it remains intentionally absent until -/// that observable is controlled. Ordered-language surfaces, hardware concurrency, and the Chromium +/// The protocol can explicitly couple total and available screen width/height through +/// `emulation.setScreenSettingsOverride`, but OriginWeave's `Screen` surface also includes color depth +/// and the current profile does not model the available screen rectangle. `Screen` therefore remains +/// intentionally absent. Ordered-language surfaces, hardware concurrency, and the Chromium /// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol /// capability even though reusable application leaves media state untouched until a Browser Session /// owner supplies a restorable lifecycle and corresponding command authority. @@ -227,9 +255,9 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because screen-area geometry does -/// not control the `ScreenMetrics` color-depth field. Callers must not translate that result into -/// ambient-host fallback. +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area +/// command does not control color depth and additionally couples an available-screen observable absent +/// from the current profile. Callers must not translate that result into ambient-host fallback. pub fn require_complete_presentation_profile() -> Result<(), PresentationError> { require_presentation_surfaces(webdriver_bidi_presentation_surfaces()) } @@ -273,7 +301,39 @@ mod tests { } #[test] - fn reusable_standard_commands_bind_only_symmetrically_restorable_state() { + fn explicit_screen_area_command_preserves_the_protocol_coupling_boundary() { + let profile = PresentationProfile::new( + ScreenMetrics::new(1920, 1080).expect("valid screen"), + ViewportBounds::new(1440, 900).expect("valid viewport"), + DevicePixelRatio::Quantized2, + 8, + PresentationTimeZone::Utc, + PresentationPlatform::MacOS, + vec!["en-US".to_owned()], + true, + ) + .expect("consistent profile"); + let context = + WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); + let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); + + assert_eq!(screen_area.width(), 1920); + assert_eq!(screen_area.height(), 1080); + assert_eq!( + plan_explicit_screen_area_override(&context, profile.screen()), + WebDriverBidiPresentationCommand::SetScreenArea { + context: context.clone(), + screen_area, + } + ); + assert_eq!( + plan_explicit_screen_area_cleanup(&context), + WebDriverBidiPresentationCommand::ResetScreenArea { context } + ); + } + + #[test] + fn reusable_standard_commands_bind_only_modelled_symmetrically_restorable_state() { let error = WebDriverBidiCommandError::InvalidBrowsingContext; assert_eq!(error.to_string(), "invalid WebDriver BiDi browsing context"); assert!(Error::source(&error).is_none()); @@ -302,22 +362,14 @@ mod tests { WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); assert_eq!(context.as_str(), "context-17"); - let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); - assert_eq!(screen_area.width(), 1920); - assert_eq!(screen_area.height(), 1080); assert_eq!( plan_standard_presentation_commands( &context, - profile.screen(), profile.viewport(), profile.device_pixel_ratio(), profile.timezone(), ), [ - WebDriverBidiPresentationCommand::SetScreenArea { - context: context.clone(), - screen_area, - }, WebDriverBidiPresentationCommand::SetViewport { context: context.clone(), viewport: *profile.viewport(), @@ -332,16 +384,13 @@ mod tests { } #[test] - fn reusable_cleanup_does_not_clear_unrelated_media_feature_state() { + fn reusable_cleanup_does_not_clear_unrelated_screen_or_media_state() { let context = WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); assert_eq!( plan_standard_presentation_cleanup(&context), [ - WebDriverBidiPresentationCommand::ResetScreenArea { - context: context.clone(), - }, WebDriverBidiPresentationCommand::ResetViewport { context: context.clone(), }, From 1904bea698477e0bd1074171e39694e0aafa0417 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:34:28 +0900 Subject: [PATCH 13/35] docs(bidi): record available-screen coupling --- docs/doctoring/webdriver-bidi-screen-area.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/doctoring/webdriver-bidi-screen-area.md b/docs/doctoring/webdriver-bidi-screen-area.md index 00ee6499d..5fcf5fa01 100644 --- a/docs/doctoring/webdriver-bidi-screen-area.md +++ b/docs/doctoring/webdriver-bidi-screen-area.md @@ -2,11 +2,13 @@ The runtime-qualified protocol identity remains the W3C WebDriver BiDi Working Draft published 3 September 2026. The current 9 September 2026 publication retains the same relevant `emulation.setScreenSettingsOverride` shape, but publication freshness does not itself change OriginWeave's runtime pin. -For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. A non-null screen area changes the web-exposed screen dimensions for the target context; `screenArea: null` removes that override. This gives OriginWeave a symmetric apply/reset path suitable for reusable-context planning. +For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. The W3C operation uses the same non-null rectangle for both the web-exposed total screen area and the web-exposed available screen area; `screenArea: null` removes that context-scoped override. The reset is symmetric, but the mutation is wider than `ScreenMetrics(width, height, color_depth)` because the current presentation identity does not model `screen.availWidth` or `screen.availHeight`. -The standard operation does **not** control color depth. OriginWeave's `ScreenMetrics` and `PresentationSurface::Screen` contract include color depth as well as dimensions. The adapter therefore projects a dedicated `WebDriverBidiScreenArea` containing only validated width and height and continues to reject complete-profile admission with `MissingSurface(Screen)`. Treating the screen-area command as proof of the complete Screen surface would overstate protocol authority. +OriginWeave therefore exposes this as an explicit partial `WebDriverBidiScreenArea` intent rather than inserting it into the reusable profile-derived presentation plan. The value object can only project width and height from validated `ScreenMetrics`, and its rustdoc makes the total/available-area coupling explicit. The ordinary reusable planner remains limited to viewport/DPR and time zone until the presentation schema deliberately models and digest-binds the available-screen observable. -This evidence changes only typed command planning. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence. +The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an explicit screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. + +This evidence changes only typed command planning. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence, including post-reset re-observation before a reusable context can be trusted again. ## References From 6cef413b98f198f728ef148b54e374ce3cbfb806 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:34:52 +0900 Subject: [PATCH 14/35] docs(bidi): bind screen-area side effects --- .../webdriver-bidi-screen-area-planning.md | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/traceability/webdriver-bidi-screen-area-planning.md b/docs/traceability/webdriver-bidi-screen-area-planning.md index 7cd150eab..f99e056a5 100644 --- a/docs/traceability/webdriver-bidi-screen-area-planning.md +++ b/docs/traceability/webdriver-bidi-screen-area-planning.md @@ -2,37 +2,44 @@ ## Problem -The runtime-qualified WebDriver BiDi adapter already plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. OriginWeave did not expose that standard screen-area operation in its typed planning boundary. +The runtime-qualified WebDriver BiDi adapter already plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. OriginWeave did not expose that standard operation in its typed planning boundary. -This is a narrower gap than the complete `PresentationSurface::Screen` requirement. `ScreenMetrics` includes width, height, and color depth, but the WebDriver BiDi `screenArea` payload controls only width and height. Advertising the complete Screen surface after adding this command would therefore create a false-green admission path. +The operation is not merely a narrower version of `PresentationSurface::Screen`. WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total screen area and the web-exposed available screen area. OriginWeave `ScreenMetrics` currently models width, height, and color depth, but not `screen.availWidth` or `screen.availHeight`. Automatically deriving the command from `ScreenMetrics` inside the reusable profile plan would therefore mutate a page-observable fingerprint surface that the profile neither selected nor digest-bound. Color depth remains independently uncontrolled as well. ## Constraints - Keep browser-domain truth in OriginWeave; WebDriver BiDi remains an adapter, not policy authority. - Preserve the runtime-qualified 3 September 2026 Working Draft pin. Publication freshness is owned separately by `webdriver-bidi-publication-current.md`. - Reuse validated presentation value objects rather than reopen raw width/height validation in the adapter. -- A reusable browsing context may plan only overrides with a context-scoped, non-destructive reset. +- A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with a context-scoped, non-destructive reset. - Do not add media-feature cleanup, ambient-host fallback, live protocol I/O, command-ACK success semantics, or Chromium-specific authority here. ## Alternatives -1. **Keep screen area unplanned.** Rejected because the qualified standard already provides an independently resettable screen-area operation and omitting it leaves a useful standard capability unused. -2. **Mark `PresentationSurface::Screen` supported after planning width/height.** Rejected because color depth remains page-observable and uncontrolled. -3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would then contain a field the protocol operation does not apply, making evidence and later serialization authority ambiguous. -4. **Project a dedicated `WebDriverBidiScreenArea` from validated `ScreenMetrics`.** Selected. The adapter carries exactly the standard-owned width/height payload while retaining the complete Screen fail-closed invariant. +1. **Insert screen settings into the reusable profile-derived plan.** Rejected. Although `screenArea: null` provides a symmetric reset, the apply operation also changes the currently unmodelled available-screen rectangle. Reversibility alone does not authorize an additional page observable. +2. **Mark `PresentationSurface::Screen` supported after planning width/height.** Rejected because color depth remains page-observable and uncontrolled, and available-screen geometry is absent from the profile. +3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would contain color depth, which the protocol operation does not apply, while still failing to name the available-screen side effect. +4. **Expose an explicit coupled screen-area partial intent and keep it out of the reusable profile-derived plan.** Selected. `WebDriverBidiScreenArea` projects validated width/height, documents that the same rectangle becomes both total and available screen area, and has a separate context-scoped reset. This preserves the protocol capability without silently broadening the presentation profile. +5. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence. It requires its own test-first bounded change rather than being hidden inside an adapter slice. ## Decision -`originweave-bidi` plans `SetScreenArea` before viewport/DPR and time-zone operations and plans the matching `ResetScreenArea` during reusable-context cleanup. `WebDriverBidiScreenArea` can only be derived from validated `ScreenMetrics`; it contains width and height only. The complete capability map intentionally continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until another reviewed owner controls color depth as well. +`originweave-bidi` exposes `plan_explicit_screen_area_override` and `plan_explicit_screen_area_cleanup` as a separately explicit partial capability. The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone because those are the currently modelled, reusable-plan observables with symmetric resets. + +`WebDriverBidiScreenArea` can only be derived from validated `ScreenMetrics`; its documentation records that WebDriver BiDi couples total and available screen areas to the same rectangle. The complete capability map intentionally continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models the available-screen observable and controls color depth as well. The planner produces typed intent only. Transport execution, page-observed post-conditions, browser/session cleanup evidence, crash recovery, and the remaining Chromium-only presentation surfaces stay with the existing #292/#299 acceptance path and its canonical runtime owners. ## Evidence and acceptance -The test-first lineage begins at PR #310 test-only commits and requires: +The review finding on PR #310 exact `e3b2b412d8ad880c87354fb3ffd5f5b4ff6cde0d` identified the unmodelled available-screen side effect. Test-first successor `8f74471e1a5414e8781531f968b46807e2d7e3d8` adds a contract that fails whenever the profile-derived reusable planner schedules `SetScreenArea` without available width/height being represented by `ScreenMetrics`. The minimal source repair separates the explicit screen-area operation from the reusable profile-derived plan. + +Acceptance requires: - a typed screen-area intent derived from validated screen metrics; -- a context-scoped screen-area reset; +- explicit documentation that one WebDriver BiDi rectangle controls both total and available screen areas; +- a separately explicit context-scoped screen-area reset; +- no screen-area mutation in the reusable profile-derived plan while available-screen geometry is unmodelled; - no media-feature reset; - no color-depth field in the screen-area command value object; and - continued fail-closed complete Screen admission. From c1effef9468864b4f731f21076b64838a101b2ac Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:35:09 +0900 Subject: [PATCH 15/35] test(bidi): require explicit screen-area intent --- ...webdriver_bidi_screen_settings_contract.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index f2f104a75..b2753b36b 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -1,4 +1,4 @@ -"""Repository contract for reversible standard-BiDi screen-area planning.""" +"""Repository contract for bounded standard-BiDi screen-area planning.""" from __future__ import annotations @@ -11,15 +11,17 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): - """Keep screen geometry typed and reversible without overstating observable control.""" + """Keep screen geometry typed without silently widening page-observable authority.""" - def test_standard_planner_uses_screen_settings_override(self) -> None: - """The qualified BiDi adapter must expose the standard screen-area command.""" + def test_adapter_exposes_explicit_screen_settings_override(self) -> None: + """The qualified BiDi adapter must expose the standard operation as explicit partial intent.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) self.assertIn("WebDriverBidiScreenArea", text) self.assertIn("SetScreenArea", text) + self.assertIn("plan_explicit_screen_area_override", text) + self.assertIn("plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -45,15 +47,16 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) "behind a separately explicit partial intent", ) - def test_standard_cleanup_removes_only_its_screen_area_override(self) -> None: - """An explicit screen-area cleanup must use the command's nullable context-scoped reset.""" + def test_explicit_cleanup_uses_context_scoped_screen_area_reset(self) -> None: + """The explicit screen-area cleanup must use the command's nullable context-scoped reset.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ResetScreenArea", text) + self.assertIn("plan_explicit_screen_area_cleanup", text) self.assertNotIn("ResetMediaFeatures", text) - def test_screen_surface_remains_fail_closed_until_color_depth_is_controlled(self) -> None: - """Screen area alone cannot satisfy ScreenMetrics because color depth remains observable.""" + def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: + """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" text = SOURCE.read_text(encoding="utf-8") surfaces = text.split( "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 From b7d82b274d5db314634f5f8958923f75621dade9 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:36:09 +0900 Subject: [PATCH 16/35] docs(adr): isolate screen-area side effects --- docs/adr/0107-browser-protocol-adapter-strategy.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/adr/0107-browser-protocol-adapter-strategy.md b/docs/adr/0107-browser-protocol-adapter-strategy.md index b4b9ba570..491359110 100644 --- a/docs/adr/0107-browser-protocol-adapter-strategy.md +++ b/docs/adr/0107-browser-protocol-adapter-strategy.md @@ -46,7 +46,9 @@ The version boundary is explicit: the protected-main routing foundation and acti PR #293 was merged into PR #229 on 2026-09-09, so its `originweave-bidi` capability boundary is inherited by this parent rather than remaining a separate active stacked slice. The adapter remains runtime-qualified 3 September 2026 against the immutable WebDriver BiDi Working Draft URI `https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`. W3C has since published the latest published 9 September 2026 Working Draft; publication freshness is recorded separately in `docs/traceability/webdriver-bidi-publication-current.md` and does not silently repin runtime compatibility. A newer runtime pin requires a dedicated compatibility/conformance change and pinned-browser evidence. -The inherited capability map delegates complete-profile admission to `originweave-fingerprint` and intentionally excludes `Screen`, `Languages`, `HardwareConcurrency`, and `Platform`: the standard screen command omits color depth, while the locale command cannot prove ordered language preferences. Standard BiDi alone must therefore return the kernel's first `MissingSurface(Screen)` result rather than accept ambient host values. PR #310 extends the typed reusable-context plan with the standard `emulation.setScreenSettingsOverride` screen-area operation and its nullable reset, alongside viewport/DPR and timezone. Its `WebDriverBidiScreenArea` projects only width and height from validated `ScreenMetrics`; it deliberately does not carry color depth and therefore does not promote the complete `Screen` capability. Reduced motion remains an expressible protocol capability but is excluded from the reusable plan because the standard cannot selectively restore prior media state; no caller-mintable exclusive-reset type substitutes for Browser Session lifecycle evidence. Planning does not send a command, create an acknowledgement, apply or prove cleanup of a profile, or produce page-observed evidence. Those remain #292 follow-up work and require exact-head verification plus a version-pinned Chromium/CDP adapter for the remainder. The detailed decision and acceptance boundary are recorded in `docs/traceability/webdriver-bidi-screen-area-planning.md`. +The inherited capability map delegates complete-profile admission to `originweave-fingerprint` and intentionally excludes `Screen`, `Languages`, `HardwareConcurrency`, and `Platform`. The standard screen-settings command omits color depth and, importantly, applies one rectangle to both the web-exposed total screen area and available screen area, while the current OriginWeave presentation profile does not model the available-screen rectangle. The locale command likewise cannot prove ordered language preferences. Standard BiDi alone must therefore return the kernel's first `MissingSurface(Screen)` result rather than accept ambient host values. + +PR #310 exposes the standard `emulation.setScreenSettingsOverride` operation as a separately explicit partial intent instead of inserting it into the reusable profile-derived plan. `WebDriverBidiScreenArea` projects validated width and height from `ScreenMetrics` and documents the protocol's total/available-area coupling; its matching reset is also explicit. The ordinary reusable-context plan remains viewport/DPR plus timezone while available-screen geometry is unmodelled. Reduced motion remains an expressible protocol capability but is excluded from the reusable plan because the standard cannot selectively restore prior media state; no caller-mintable exclusive-reset type substitutes for Browser Session lifecycle evidence. Planning does not send a command, create an acknowledgement, apply or prove cleanup of a profile, or produce page-observed evidence. Those remain #292 follow-up work and require exact-head verification plus a version-pinned Chromium/CDP adapter for the remainder. The detailed decision and acceptance boundary are recorded in `docs/traceability/webdriver-bidi-screen-area-planning.md`. ## Consequences @@ -60,7 +62,7 @@ Adapter negotiation failure disables only affected capabilities. Unsupported or Protocol validation occurs before messages influence policy. Tool/page-provided strings remain untrusted. Method and tool routing metadata is shape-bounded before correlation, preventing malformed or oversized untrusted routing strings from being reinterpreted through mismatch handling. Secret handles never become raw secret protocol payloads; only the separately authorized trusted broker-to-browser delivery path may materialize the value, and that value does not pass through MCP, WebMCP, BiDi observation, or model-visible CDP output. Adapter version/provenance is recorded for audit and incident reconstruction. -For presentation emulation, protocol availability is not presentation evidence. The adapter must bind its capability claim to an explicit protocol/browser revision, fail closed on missing required surfaces, clear every override that its presentation plan establishes before reuse is treated as clean, and later prove page-visible state after application and cleanup. Neither a protocol command acknowledgement nor an unobserved browser setting is sufficient evidence. +For presentation emulation, protocol availability is not presentation evidence. The adapter must bind its capability claim to an explicit protocol/browser revision, fail closed on missing required surfaces, and must not silently mutate a page-observable surface absent from the selected and digest-bound presentation identity. Every override actually applied must have owned cleanup before reuse is treated as clean, followed by page-visible post-cleanup observation. Neither a protocol command acknowledgement nor an unobserved browser setting is sufficient evidence. ## Tests and acceptance evidence @@ -68,7 +70,7 @@ Require version-negotiation tests, schema/property tests, malformed-message test For the protected-main `tools/call` foundation, acceptance includes deterministic method and tool-name bounds/syntax, exact header/body method and tool-name correlation only after both sides are bounded, explicit invalid-method/invalid-tool-name/unknown-tool rejection, one unambiguous tool-to-action registry, independent capability/risk expectations, route/action mismatch denial before ordinary policy evaluation, exact 100% owned-production coverage, and integrated review evidence from PR #168. For active PR #170, exact-current acceptance additionally requires bounded protocol metadata before cross-field comparison, required client-capabilities presence, bounded `tools/list` method correlation, rejection of unissued cursors, deterministic result/cache semantics, exact 100% owned-production coverage, and unchanged-head CI/security/review evidence. These checks do not substitute for complete transport or adapter conformance. -For the inherited PR #293 capability-boundary delta now carried by PR #229, acceptance requires the original regression proving the absence of an `originweave-bidi` bounded context on its predecessor, cleanup regressions that refuse to leave adapter-owned overrides behind, and exact-head Rust/Python/rustdoc/Clippy/coverage verification that the minimal adapter compiles and the runtime-qualified standard set fails with the canonical fingerprint-kernel missing-surface error. PR #310 additionally requires exact screen-area projection from validated `ScreenMetrics`, matching context-scoped reset intent, absence of color depth from the standard payload object, and continued `MissingSurface(Screen)` admission until color depth is independently controlled. This is not acceptance of #292 as a whole. Real pinned-Chromium application, page-observed post-condition evidence, navigation/renderer/crash/cleanup behavior, and the Chromium-only CDP remainder still require realistic browser E2E. Publication of a newer Working Draft is not compatibility evidence and cannot by itself change this acceptance basis. +For the inherited PR #293 capability-boundary delta now carried by PR #229, acceptance requires the original regression proving the absence of an `originweave-bidi` bounded context on its predecessor, cleanup regressions that refuse to leave adapter-owned overrides behind, and exact-head Rust/Python/rustdoc/Clippy/coverage verification that the minimal adapter compiles and the runtime-qualified standard set fails with the canonical fingerprint-kernel missing-surface error. PR #310 additionally requires an explicit screen-area intent derived from validated `ScreenMetrics`, explicit total/available-area coupling semantics, a matching context-scoped reset, absence of color depth from the standard payload object, no automatic screen-area mutation in the reusable profile-derived plan while available-screen geometry is unmodelled, and continued `MissingSurface(Screen)` admission. This is not acceptance of #292 as a whole. Real pinned-Chromium application, page-observed post-condition evidence, navigation/renderer/crash/cleanup behavior, and the Chromium-only CDP remainder still require realistic browser E2E. Publication of a newer Working Draft is not compatibility evidence and cannot by itself change this acceptance basis. ## Migration and rollback @@ -76,7 +78,7 @@ Adapters are independently versioned and can be canaried. Clients migrate throug ## Open follow-ups -Define internal protocol versioning rules, complete MCP Streamable HTTP/request-metadata validation, MCP transport serialization, authenticated deployment, and MCP/WebMCP schema isolation. For presentation identity, implement the exact pinned Chromium/BiDi command path, a narrow version-pinned `originweave-cdp` capability owner for required non-BiDi surfaces, post-application and post-cleanup page observation, navigation/renderer invalidation, crash/cleanup behavior, and release compatibility evidence. +Define internal protocol versioning rules, complete MCP Streamable HTTP/request-metadata validation, MCP transport serialization, authenticated deployment, and MCP/WebMCP schema isolation. For presentation identity, decide and test the canonical available-screen-area model before any profile-derived `setScreenSettingsOverride` application, implement the exact pinned Chromium/BiDi command path, add a narrow version-pinned `originweave-cdp` capability owner for required non-BiDi surfaces, require post-application and post-cleanup page observation, navigation/renderer invalidation, crash/cleanup behavior, and release compatibility evidence. ## Supersession / reversal conditions From b2da7e2989b3a2966cb7c0b60bc0fb22177d7859 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:38:07 +0900 Subject: [PATCH 17/35] docs: doctor screen-area observable coupling --- docs/doctoring.md | 59 +++++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/docs/doctoring.md b/docs/doctoring.md index 7e80d13f2..0fb13a2fc 100644 --- a/docs/doctoring.md +++ b/docs/doctoring.md @@ -51,38 +51,41 @@ that a non-mobile user agent reports an empty model (see ADR 0112). The pinned 3 September 2026 WebDriver BiDi Working Draft exposes locale, media, screen, user-agent, viewport, and time-zone emulation commands under the immutable publication `https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`. The screen -shape contains width and height but not color depth, and locale accepts one value -rather than an ordered language list, so neither proves the corresponding complete -OriginWeave surface. The 9 September 2026 Working Draft retains the relevant -`emulation.setScreenSettingsOverride` screen-area shape; that publication update is -tracked separately and does not silently repin runtime compatibility. The draft also -does not define a hardware-concurrency override. Chromium's tip-of-tree DevTools -Protocol exposes `Emulation.setHardwareConcurrencyOverride` as Experimental and -warns that tip-of-tree commands can change without notice. OriginWeave therefore -records required presentation surfaces in a protocol-neutral Rust admission -contract. The capability map records the same four complete standard surfaces as -before, while the reusable-context plan now emits three typed command intents—screen -area, viewport/DPR, and timezone—bound to one bounded opaque browsing context. The -dedicated screen-area value projects only width and height from validated -`ScreenMetrics`; it carries no color depth, so complete `PresentationSurface::Screen` -admission remains fail-closed. - -Cleanup authority is asymmetric. Nullable screen-area, viewport, and timezone -operations can remove those adapter-owned overrides on a reusable context, so generic -cleanup plans reset screen area, viewport/DPR, and timezone. By contrast, -`emulation.setMediaFeaturesOverride` with `features: null` unsets the target's -complete media-feature override configuration rather than selectively reversing -only `prefers-reduced-motion`. The reusable-context plan therefore neither -installs reduced motion nor emits a media reset. No caller-mintable exclusive -reset is exposed as ownership evidence; a Browser Session owner must prove a -disposable context lifecycle or restore the complete prior media configuration. +settings shape contains width and height but not color depth, and locale accepts one +value rather than an ordered language list, so neither proves the corresponding +complete OriginWeave surface. The 9 September 2026 Working Draft retains the relevant +`emulation.setScreenSettingsOverride` shape; that publication update is tracked +separately and does not silently repin runtime compatibility. + +The screen-settings operation has a second page-observable effect that the earlier +planner description omitted: the specification applies the same `screenArea` +rectangle to both the web-exposed total screen area and the web-exposed available +screen area. OriginWeave `ScreenMetrics` currently models width, height, and color +depth but not `screen.availWidth` or `screen.availHeight`. A reusable profile-derived +planner therefore cannot silently schedule this operation merely because it has a +nullable reset. PR #310 keeps the typed `WebDriverBidiScreenArea` capability and its +context-scoped reset, but exposes them as a separately explicit partial intent; the +ordinary reusable plan remains viewport/DPR plus timezone until available-screen +geometry is deliberately represented and digest-bound by the presentation identity. +Complete `PresentationSurface::Screen` admission remains fail-closed because color +depth is still uncontrolled as well. + +The draft does not define a hardware-concurrency override. Chromium's tip-of-tree +DevTools Protocol exposes `Emulation.setHardwareConcurrencyOverride` as Experimental +and warns that tip-of-tree commands can change without notice. OriginWeave therefore +records required presentation surfaces in a protocol-neutral Rust admission contract. +Reduced motion remains an expressible protocol capability, but the reusable-context +plan neither installs it nor emits a media reset because +`emulation.setMediaFeaturesOverride` with `features: null` clears the complete media +configuration rather than selectively reversing only `prefers-reduced-motion`. +No caller-mintable exclusive reset substitutes for Browser Session ownership evidence. Constructing application or cleanup intents performs no transport I/O and cannot be treated as acknowledgement, successful cleanup, ownership evidence, or page-observed presentation evidence. A later pinned Chromium adapter must capability-negotiate every surface, observe post-conditions after apply and cleanup, and either prove exclusive -disposable context ownership or restore the complete pre-existing media configuration -before reusing the browser boundary. The focused evidence and alternatives for the -screen-area slice are recorded in `docs/doctoring/webdriver-bidi-screen-area.md` and +disposable context ownership or restore the complete pre-existing configuration before +reusing the browser boundary. The focused screen-area evidence and alternatives are +recorded in `docs/doctoring/webdriver-bidi-screen-area.md` and `docs/traceability/webdriver-bidi-screen-area-planning.md`. ### Extension-to-Agent grant origin binding From 3445a4886d97cb33891a984947f438912906b7ba Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:39:03 +0900 Subject: [PATCH 18/35] docs(changelog): bound screen-area partial intent --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0c1b69b3..a317fc24e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,15 +4,16 @@ All notable changes to OriginWeave are documented in this file. The format follo ## [Unreleased] -- Extended the reusable WebDriver BiDi presentation planner with a context-scoped `emulation.setScreenSettingsOverride` screen-area intent and matching reset, alongside viewport/DPR and timezone. The adapter projects only validated width and height into a dedicated `WebDriverBidiScreenArea`; color depth remains uncontrolled, so complete `PresentationSurface::Screen` admission still fails closed instead of treating screen geometry as the whole screen fingerprint surface. +- Exposed WebDriver BiDi `emulation.setScreenSettingsOverride` as a separately explicit, context-scoped partial screen-area intent with matching reset. The protocol couples total and available screen areas to one rectangle, while the current presentation profile does not model `screen.availWidth` / `screen.availHeight`; the reusable profile-derived planner therefore remains viewport/DPR plus timezone rather than silently mutating an unmodelled page observable. - Refreshed the product-gap queue to 126 open pull requests (54 ready, 72 draft) after #190, #188, #185, #192, #182, #184, #115, #181, #116, #117, #118, #183, #114, #127, #112, #109, #186, #110, #108, #111, #174, and #113 were merged into their immediate stacked prerequisites. PRs #147, #146, #145, #144, #143, #142, #141, #139, #136, #132, #129, and #128 moved to ready after exact-head checks and thread review; these are queue-consolidation results, not protected-main shipment. ### Fixed +- Prevented the reusable profile-derived WebDriver BiDi planner from scheduling `setScreenSettingsOverride` from `ScreenMetrics` alone, because the standard operation also changes the page-observable available screen rectangle that the current presentation identity neither selects nor digest-binds. - Restored canonical Rust formatting for the WebDriver BiDi presentation cleanup assertion so exact-head contracts can execute the test, Clippy, and rustdoc gates. ### Added -- Added a version-pinned `originweave-bidi` presentation-capability boundary for the W3C WebDriver BiDi Working Draft published on 3 September 2026 (`https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`). It depends inward on `originweave-fingerprint`, plans the symmetrically restorable screen-area, viewport/DPR, and timezone commands for one bounded reusable browsing context, and still fails first on the complete screen surface because standard BiDi screen-area emulation cannot prove color depth or ordered languages. Reduced motion remains an expressible protocol capability but is not installed by the reusable plan because standard cleanup cannot selectively restore prior media state. No caller-mintable exclusive-reset type is exposed; a Browser Session owner must prove a disposable lifecycle or complete prior-state restoration. Planning performs no transport I/O or acknowledgement, cleanup, ownership, or page-observed evidence. Hardware concurrency and the complete Chromium platform/User-Agent Client Hints surface still require a separate versioned Chromium adapter. +- Added a version-pinned `originweave-bidi` presentation-capability boundary for the W3C WebDriver BiDi Working Draft published on 3 September 2026 (`https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`). It depends inward on `originweave-fingerprint`, keeps the reusable plan limited to symmetrically restorable and explicitly modelled viewport/DPR and timezone commands, and exposes screen settings as a separate typed partial intent whose one rectangle controls both total and available screen area. Complete `PresentationSurface::Screen` admission still fails closed because available-screen geometry is unmodelled and color depth remains uncontrolled. Reduced motion remains an expressible protocol capability but is not installed by the reusable plan because standard cleanup cannot selectively restore prior media state. No caller-mintable exclusive-reset type is exposed; a Browser Session owner must prove a disposable lifecycle or complete prior-state restoration. Planning performs no transport I/O or acknowledgement, cleanup, ownership, or page-observed evidence. Hardware concurrency and the complete Chromium platform/User-Agent Client Hints surface still require a separate versioned Chromium adapter. - Added a bounded Rust presentation-identity kernel for explicit browser-visible profiles and credential-free replay digests, including control-safe mobile UA-CH model values; applying those profiles to Chromium and proving page-observed effects remain separate adapter and browser-E2E work. - Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate. From eac7db0a21842baa447c24a0050acba1db42a5e8 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 07:42:42 +0900 Subject: [PATCH 19/35] test(bidi): close planner contract loophole --- ...webdriver_bidi_screen_settings_contract.py | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index b2753b36b..927c3e06e 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -31,21 +31,31 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) screen_metrics = screen_metrics.split("impl ScreenMetrics", maxsplit=1)[0] planner = source.split("pub fn plan_standard_presentation_commands", maxsplit=1)[1] planner = planner.split("pub fn plan_standard_presentation_cleanup", maxsplit=1)[0] + cleanup = source.split("pub fn plan_standard_presentation_cleanup", maxsplit=1)[1] + cleanup = cleanup.split( + "pub const WEBDRIVER_BIDI_PRESENTATION_REVISION", maxsplit=1 + )[0] models_available_screen_area = ( "available_width" in screen_metrics and "available_height" in screen_metrics ) - profile_plans_screen_override = ( - "screen: &ScreenMetrics" in planner and "SetScreenArea" in planner - ) + if models_available_screen_area: + return - self.assertTrue( - models_available_screen_area or not profile_plans_screen_override, + self.assertNotIn( + "SetScreenArea", + planner, "WebDriver BiDi screen settings override also changes screen.availWidth/availHeight; " "the reusable profile-derived plan must model those observables or keep the override " "behind a separately explicit partial intent", ) + self.assertNotIn( + "ResetScreenArea", + cleanup, + "generic reusable cleanup must not clear a screen override that the generic plan did " + "not own or install", + ) def test_explicit_cleanup_uses_context_scoped_screen_area_reset(self) -> None: """The explicit screen-area cleanup must use the command's nullable context-scoped reset.""" From be0c74573b713e3fb55229be8d5f0d95a070588f Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:01:51 +0900 Subject: [PATCH 20/35] test(bidi): require screen-area ownership before mutation --- ...webdriver_bidi_screen_settings_contract.py | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 927c3e06e..36100d1f0 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -13,15 +13,16 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): """Keep screen geometry typed without silently widening page-observable authority.""" - def test_adapter_exposes_explicit_screen_settings_override(self) -> None: - """The qualified BiDi adapter must expose the standard operation as explicit partial intent.""" + def test_adapter_exposes_screen_area_value_without_unowned_mutation_intent(self) -> None: + """Geometry may be typed before Browser Session proves authority to mutate it.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) self.assertIn("WebDriverBidiScreenArea", text) - self.assertIn("SetScreenArea", text) - self.assertIn("plan_explicit_screen_area_override", text) - self.assertIn("plan_explicit_screen_area_cleanup", text) + self.assertNotIn("SetScreenArea", text) + self.assertNotIn("ResetScreenArea", text) + self.assertNotIn("plan_explicit_screen_area_override", text) + self.assertNotIn("plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -48,7 +49,7 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) planner, "WebDriver BiDi screen settings override also changes screen.availWidth/availHeight; " "the reusable profile-derived plan must model those observables or keep the override " - "behind a separately explicit partial intent", + "behind Browser Session ownership", ) self.assertNotIn( "ResetScreenArea", @@ -57,16 +58,17 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) "not own or install", ) - def test_explicit_cleanup_uses_context_scoped_screen_area_reset(self) -> None: - """The explicit screen-area cleanup must use the command's nullable context-scoped reset.""" + def test_screen_area_mutation_requires_browser_session_ownership(self) -> None: + """A context identifier alone cannot authorize replacing or clearing another owner's override.""" text = SOURCE.read_text(encoding="utf-8") - self.assertIn("ResetScreenArea", text) - self.assertIn("plan_explicit_screen_area_cleanup", text) - self.assertNotIn("ResetMediaFeatures", text) + self.assertNotIn("SetScreenArea", text) + self.assertNotIn("ResetScreenArea", text) + self.assertNotIn("plan_explicit_screen_area_override", text) + self.assertNotIn("plan_explicit_screen_area_cleanup", text) def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: - """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" + """Screen-area representation cannot satisfy the complete page-observable Screen contract.""" text = SOURCE.read_text(encoding="utf-8") surfaces = text.split( "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 @@ -79,7 +81,7 @@ def test_screen_surface_remains_fail_closed_until_complete_observables_are_contr ) def test_screen_area_payload_does_not_carry_color_depth(self) -> None: - """The command intent must not imply authority over an unapplied screen observable.""" + """The protocol value must not imply authority over an unapplied screen observable.""" text = SOURCE.read_text(encoding="utf-8") screen_area = text.split("pub struct WebDriverBidiScreenArea", maxsplit=1)[1] screen_area = screen_area.split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] From f6ad7387cf9c3d96edc8eb15528807fe62c97b04 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:04:18 +0900 Subject: [PATCH 21/35] fix(bidi): withhold unowned screen-area mutation --- .../src/presentation_capabilities.rs | 120 +++++------------- 1 file changed, 35 insertions(+), 85 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index 6ac5719e1..b44d616e4 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -49,9 +49,10 @@ impl WebDriverBidiBrowsingContext { /// `emulation.setScreenSettingsOverride`. /// /// WebDriver BiDi applies one rectangle to both the web-exposed total screen area and available -/// screen area. Construction therefore remains an explicit partial capability: it projects width and -/// height from validated [`ScreenMetrics`] but does not claim that the presentation profile models the -/// resulting `screen.availWidth` / `screen.availHeight` observables or screen color depth. +/// screen area. This value deliberately represents geometry only: a browsing-context identifier does +/// not prove that OriginWeave owns the existing override and therefore cannot authorize replacing or +/// clearing it. A Browser Session owner must establish an exclusive/disposable context or equivalent +/// ownership witness before a transport adapter may materialize the mutation. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct WebDriverBidiScreenArea { width_px: u32, @@ -61,9 +62,10 @@ pub struct WebDriverBidiScreenArea { impl WebDriverBidiScreenArea { /// Project the protocol-owned rectangle from validated presentation screen metrics. /// - /// The returned value intentionally means that total and available screen areas will be coupled to - /// the same rectangle. It must not be inserted into a profile-derived reusable plan unless the - /// presentation schema has first modelled and authorized those available-area observables. + /// The returned value intentionally means that total and available screen areas would be coupled + /// to the same rectangle if an authorized Browser Session later applies it. Constructing this + /// value grants no mutation or cleanup authority and does not claim that the presentation profile + /// models `screen.availWidth`, `screen.availHeight`, or screen color depth. #[must_use] pub const fn from_screen(screen: &ScreenMetrics) -> Self { Self { @@ -72,13 +74,13 @@ impl WebDriverBidiScreenArea { } } - /// Return the width applied to both total and available web-exposed screen areas. + /// Return the width represented for both total and available web-exposed screen areas. #[must_use] pub const fn width(&self) -> u32 { self.width_px } - /// Return the height applied to both total and available web-exposed screen areas. + /// Return the height represented for both total and available web-exposed screen areas. #[must_use] pub const fn height(&self) -> u32 { self.height_px @@ -90,20 +92,12 @@ impl WebDriverBidiScreenArea { /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// screen, viewport, DPR, or time-zone validation. Screen-area commands couple total and available -/// screen geometry, do not control color depth, and therefore do not satisfy the complete -/// `PresentationSurface::Screen` contract. This reusable-boundary enum deliberately exposes no -/// media-feature mutation command because this crate has no ownership or snapshot witness that would -/// make such mutation reversibly safe. +/// viewport, DPR, or time-zone validation. Screen-area mutation is intentionally absent: the standard +/// operation replaces or removes context state, while this adapter has no ownership or snapshot +/// witness proving that such state belongs to OriginWeave. This reusable-boundary enum deliberately +/// exposes no media-feature mutation command for the same non-destructive-cleanup reason. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { - /// Set total and available web-exposed screen width and height together. - SetScreenArea { - /// Exact target browsing context. - context: WebDriverBidiBrowsingContext, - /// Exact coupled standard-BiDi screen-area payload derived from validated screen metrics. - screen_area: WebDriverBidiScreenArea, - }, /// Set viewport dimensions and device-pixel ratio together. SetViewport { /// Exact target browsing context. @@ -120,11 +114,6 @@ pub enum WebDriverBidiPresentationCommand { /// Validated presentation time-zone identity. timezone: PresentationTimeZone, }, - /// Remove the coupled total-and-available screen-area override for the exact browsing context. - ResetScreenArea { - /// Exact target browsing context. - context: WebDriverBidiBrowsingContext, - }, /// Restore the implementation-defined viewport and remove the device-pixel-ratio override. ResetViewport { /// Exact target browsing context. @@ -137,46 +126,17 @@ pub enum WebDriverBidiPresentationCommand { }, } -/// Plan one explicit partial screen-area override for a bounded browsing context. -/// -/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is -/// deliberately separate from [`plan_standard_presentation_commands`] because the current -/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`; callers must not -/// mistake this explicit coupled operation for application of the complete profile. -#[must_use] -pub fn plan_explicit_screen_area_override( - context: &WebDriverBidiBrowsingContext, - screen: &ScreenMetrics, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::SetScreenArea { - context: context.clone(), - screen_area: WebDriverBidiScreenArea::from_screen(screen), - } -} - -/// Plan cleanup for one explicitly applied coupled screen-area override. -/// -/// The pinned Working Draft defines `screenArea: null` as removal of that exact context-scoped -/// override. Planning the reset does not prove transport execution or post-cleanup page observation. -#[must_use] -pub fn plan_explicit_screen_area_cleanup( - context: &WebDriverBidiBrowsingContext, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::ResetScreenArea { - context: context.clone(), - } -} - /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// /// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the -/// pinned Working Draft. The screen-settings override is excluded from this profile-derived plan even -/// though it is reversible because it also changes the unmodelled page-observable available screen -/// area. Reduced motion remains an expressible protocol capability, but this reusable planning boundary -/// neither installs nor exposes a media-mutation command because `features: null` clears the complete -/// media-feature configuration rather than restoring only OriginWeave's prior `prefers-reduced-motion` -/// value. The explicit arguments make this a partial-plan API: it cannot be mistaken for application of -/// a complete [`originweave_fingerprint::PresentationProfile`]. +/// pinned Working Draft. Screen-area mutation is excluded even as an explicit context-only command: +/// setting a rectangle can replace another owner's override and `screenArea: null` removes the current +/// override rather than restoring a prior value. Reduced motion remains an expressible protocol +/// capability, but this reusable planning boundary neither installs nor exposes a media-mutation +/// command because `features: null` clears the complete media-feature configuration rather than +/// restoring only OriginWeave's prior `prefers-reduced-motion` value. The explicit arguments make this +/// a partial-plan API: it cannot be mistaken for application of a complete +/// [`originweave_fingerprint::PresentationProfile`]. #[must_use] pub fn plan_standard_presentation_commands( context: &WebDriverBidiBrowsingContext, @@ -201,8 +161,8 @@ pub fn plan_standard_presentation_commands( /// /// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR /// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area -/// cleanup is deliberately separate because this reusable plan does not install the coupled total-and- -/// available screen override. Media cleanup is absent because `features: null` clears the complete +/// cleanup is absent because this boundary cannot prove ownership of the current screen override or +/// restore a predecessor value. Media cleanup is absent because `features: null` clears the complete /// media-feature override configuration rather than selectively undoing `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( @@ -243,10 +203,12 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ /// The protocol can explicitly couple total and available screen width/height through /// `emulation.setScreenSettingsOverride`, but OriginWeave's `Screen` surface also includes color depth /// and the current profile does not model the available screen rectangle. `Screen` therefore remains -/// intentionally absent. Ordered-language surfaces, hardware concurrency, and the Chromium -/// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol -/// capability even though reusable application leaves media state untouched until a Browser Session -/// owner supplies a restorable lifecycle and corresponding command authority. +/// intentionally absent. This adapter additionally withholds screen-area mutation until Browser +/// Session proves ownership of the affected override lifecycle. Ordered-language surfaces, hardware +/// concurrency, and the Chromium platform/User-Agent Client Hints surface are also absent. Reduced +/// motion is listed as protocol capability even though reusable application leaves media state +/// untouched until a Browser Session owner supplies a restorable lifecycle and corresponding command +/// authority. #[must_use] pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSurface] { &WEBDRIVER_BIDI_PRESENTATION_SURFACES @@ -255,9 +217,10 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area -/// command does not control color depth and additionally couples an available-screen observable absent -/// from the current profile. Callers must not translate that result into ambient-host fallback. +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the standard screen-area +/// value does not control color depth, the profile does not model available-screen geometry, and this +/// adapter has no Browser Session ownership witness for mutating existing screen-settings state. +/// Callers must not translate that result into ambient-host fallback. pub fn require_complete_presentation_profile() -> Result<(), PresentationError> { require_presentation_surfaces(webdriver_bidi_presentation_surfaces()) } @@ -301,7 +264,7 @@ mod tests { } #[test] - fn explicit_screen_area_command_preserves_the_protocol_coupling_boundary() { + fn screen_area_value_preserves_protocol_coupling_without_mutation_authority() { let profile = PresentationProfile::new( ScreenMetrics::new(1920, 1080).expect("valid screen"), ViewportBounds::new(1440, 900).expect("valid viewport"), @@ -313,23 +276,10 @@ mod tests { true, ) .expect("consistent profile"); - let context = - WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); assert_eq!(screen_area.width(), 1920); assert_eq!(screen_area.height(), 1080); - assert_eq!( - plan_explicit_screen_area_override(&context, profile.screen()), - WebDriverBidiPresentationCommand::SetScreenArea { - context: context.clone(), - screen_area, - } - ); - assert_eq!( - plan_explicit_screen_area_cleanup(&context), - WebDriverBidiPresentationCommand::ResetScreenArea { context } - ); } #[test] From 597108d560ae44770eccab04676dcd10956238a5 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:06:59 +0900 Subject: [PATCH 22/35] test(bidi): bind screen-area intent to ownership witness --- ...webdriver_bidi_screen_settings_contract.py | 50 +++++++++++++------ 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 36100d1f0..67832d4ef 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -13,16 +13,17 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): """Keep screen geometry typed without silently widening page-observable authority.""" - def test_adapter_exposes_screen_area_value_without_unowned_mutation_intent(self) -> None: - """Geometry may be typed before Browser Session proves authority to mutate it.""" + def test_adapter_exposes_screen_area_only_through_owned_mutation_intent(self) -> None: + """The standard operation stays typed but requires Browser Session ownership.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) self.assertIn("WebDriverBidiScreenArea", text) - self.assertNotIn("SetScreenArea", text) - self.assertNotIn("ResetScreenArea", text) - self.assertNotIn("plan_explicit_screen_area_override", text) - self.assertNotIn("plan_explicit_screen_area_cleanup", text) + self.assertIn("WebDriverBidiScreenAreaOwnership", text) + self.assertIn("SetScreenArea", text) + self.assertIn("ResetScreenArea", text) + self.assertIn("plan_explicit_screen_area_override", text) + self.assertIn("plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -58,17 +59,36 @@ def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) "not own or install", ) - def test_screen_area_mutation_requires_browser_session_ownership(self) -> None: + def test_screen_area_mutation_requires_non_mintable_browser_session_ownership(self) -> None: """A context identifier alone cannot authorize replacing or clearing another owner's override.""" text = SOURCE.read_text(encoding="utf-8") - - self.assertNotIn("SetScreenArea", text) - self.assertNotIn("ResetScreenArea", text) - self.assertNotIn("plan_explicit_screen_area_override", text) - self.assertNotIn("plan_explicit_screen_area_cleanup", text) + ownership = text.split( + "pub struct WebDriverBidiScreenAreaOwnership", maxsplit=1 + )[1].split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] + set_variant = text.split("SetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] + reset_variant = text.split("ResetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] + override_planner = text.split( + "pub fn plan_explicit_screen_area_override", maxsplit=1 + )[1].split("pub fn plan_explicit_screen_area_cleanup", maxsplit=1)[0] + cleanup_planner = text.split( + "pub fn plan_explicit_screen_area_cleanup", maxsplit=1 + )[1].split("pub fn plan_standard_presentation_commands", maxsplit=1)[0] + + self.assertIn("context: WebDriverBidiBrowsingContext", ownership) + self.assertNotIn("pub context:", ownership) + self.assertNotIn("pub fn new(", ownership) + self.assertNotIn("pub fn from_", ownership) + self.assertIn("ownership: WebDriverBidiScreenAreaOwnership", set_variant) + self.assertNotIn("context: WebDriverBidiBrowsingContext", set_variant) + self.assertIn("ownership: WebDriverBidiScreenAreaOwnership", reset_variant) + self.assertNotIn("context: WebDriverBidiBrowsingContext", reset_variant) + self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", override_planner) + self.assertNotIn("context: &WebDriverBidiBrowsingContext", override_planner) + self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", cleanup_planner) + self.assertNotIn("context: &WebDriverBidiBrowsingContext", cleanup_planner) def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: - """Screen-area representation cannot satisfy the complete page-observable Screen contract.""" + """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" text = SOURCE.read_text(encoding="utf-8") surfaces = text.split( "const WEBDRIVER_BIDI_PRESENTATION_SURFACES", maxsplit=1 @@ -81,10 +101,10 @@ def test_screen_surface_remains_fail_closed_until_complete_observables_are_contr ) def test_screen_area_payload_does_not_carry_color_depth(self) -> None: - """The protocol value must not imply authority over an unapplied screen observable.""" + """The command intent must not imply authority over an unapplied screen observable.""" text = SOURCE.read_text(encoding="utf-8") screen_area = text.split("pub struct WebDriverBidiScreenArea", maxsplit=1)[1] - screen_area = screen_area.split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] + screen_area = screen_area.split("pub struct WebDriverBidiScreenAreaOwnership", maxsplit=1)[0] self.assertIn("width_px: u32", screen_area) self.assertIn("height_px: u32", screen_area) From fa17e07f9c6cfdc3c3ec69105bf447ed49977990 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:07:40 +0900 Subject: [PATCH 23/35] fix(bidi): gate screen-area commands on ownership witness --- .../src/presentation_capabilities.rs | 153 +++++++++++++----- 1 file changed, 117 insertions(+), 36 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index b44d616e4..d58ccf2b0 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -49,10 +49,9 @@ impl WebDriverBidiBrowsingContext { /// `emulation.setScreenSettingsOverride`. /// /// WebDriver BiDi applies one rectangle to both the web-exposed total screen area and available -/// screen area. This value deliberately represents geometry only: a browsing-context identifier does -/// not prove that OriginWeave owns the existing override and therefore cannot authorize replacing or -/// clearing it. A Browser Session owner must establish an exclusive/disposable context or equivalent -/// ownership witness before a transport adapter may materialize the mutation. +/// screen area. Construction therefore remains an explicit partial capability: it projects width and +/// height from validated [`ScreenMetrics`] but does not claim that the presentation profile models the +/// resulting `screen.availWidth` / `screen.availHeight` observables or screen color depth. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct WebDriverBidiScreenArea { width_px: u32, @@ -62,10 +61,9 @@ pub struct WebDriverBidiScreenArea { impl WebDriverBidiScreenArea { /// Project the protocol-owned rectangle from validated presentation screen metrics. /// - /// The returned value intentionally means that total and available screen areas would be coupled - /// to the same rectangle if an authorized Browser Session later applies it. Constructing this - /// value grants no mutation or cleanup authority and does not claim that the presentation profile - /// models `screen.availWidth`, `screen.availHeight`, or screen color depth. + /// The returned value intentionally means that total and available screen areas will be coupled to + /// the same rectangle. It must not be inserted into a profile-derived reusable plan unless the + /// presentation schema has first modelled and authorized those available-area observables. #[must_use] pub const fn from_screen(screen: &ScreenMetrics) -> Self { Self { @@ -74,30 +72,59 @@ impl WebDriverBidiScreenArea { } } - /// Return the width represented for both total and available web-exposed screen areas. + /// Return the width applied to both total and available web-exposed screen areas. #[must_use] pub const fn width(&self) -> u32 { self.width_px } - /// Return the height represented for both total and available web-exposed screen areas. + /// Return the height applied to both total and available web-exposed screen areas. #[must_use] pub const fn height(&self) -> u32 { self.height_px } } +/// Proof that Browser Session owns screen-settings mutation for one browsing context. +/// +/// This type intentionally has no public constructor. A remote-issued context identifier is identity, +/// not authority: WebDriver BiDi replaces the current screen-area override when setting a rectangle and +/// removes it when `screenArea` is null. A Browser Session integration may create this witness only +/// after it has established an exclusive/disposable context or an equivalent lifecycle that proves no +/// unrelated owner state can be overwritten or cleared. Until that integration exists, external +/// callers can inspect neither a mint path nor a context-only escape hatch for screen-area mutation. +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct WebDriverBidiScreenAreaOwnership { + context: WebDriverBidiBrowsingContext, +} + +impl WebDriverBidiScreenAreaOwnership { + /// Return the exact browsing context covered by this ownership witness. + #[must_use] + pub const fn context(&self) -> &WebDriverBidiBrowsingContext { + &self.context + } +} + /// Typed standard-BiDi presentation command intent for one explicit browsing context. /// /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// viewport, DPR, or time-zone validation. Screen-area mutation is intentionally absent: the standard -/// operation replaces or removes context state, while this adapter has no ownership or snapshot -/// witness proving that such state belongs to OriginWeave. This reusable-boundary enum deliberately -/// exposes no media-feature mutation command for the same non-destructive-cleanup reason. +/// screen, viewport, DPR, or time-zone validation. Screen-area commands require an opaque Browser +/// Session ownership witness because setting or clearing the context override is destructive to any +/// predecessor value. This reusable-boundary enum deliberately exposes no media-feature mutation +/// command because this crate has no ownership or snapshot witness that would make such mutation +/// reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { + /// Set total and available web-exposed screen width and height together. + SetScreenArea { + /// Browser Session proof that this context's screen-settings lifecycle is exclusively owned. + ownership: WebDriverBidiScreenAreaOwnership, + /// Exact coupled standard-BiDi screen-area payload derived from validated screen metrics. + screen_area: WebDriverBidiScreenArea, + }, /// Set viewport dimensions and device-pixel ratio together. SetViewport { /// Exact target browsing context. @@ -114,6 +141,11 @@ pub enum WebDriverBidiPresentationCommand { /// Validated presentation time-zone identity. timezone: PresentationTimeZone, }, + /// Remove the coupled total-and-available screen-area override for the owned browsing context. + ResetScreenArea { + /// Browser Session proof that clearing this context cannot remove another owner's override. + ownership: WebDriverBidiScreenAreaOwnership, + }, /// Restore the implementation-defined viewport and remove the device-pixel-ratio override. ResetViewport { /// Exact target browsing context. @@ -126,17 +158,50 @@ pub enum WebDriverBidiPresentationCommand { }, } +/// Plan one explicit partial screen-area override for a Browser Session-owned browsing context. +/// +/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is +/// deliberately separate from [`plan_standard_presentation_commands`] because the current +/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`. Possession of the +/// opaque ownership witness is additionally required because replacing the existing context override +/// is not a reversible context-only operation. +#[must_use] +pub fn plan_explicit_screen_area_override( + ownership: &WebDriverBidiScreenAreaOwnership, + screen: &ScreenMetrics, +) -> WebDriverBidiPresentationCommand { + WebDriverBidiPresentationCommand::SetScreenArea { + ownership: ownership.clone(), + screen_area: WebDriverBidiScreenArea::from_screen(screen), + } +} + +/// Plan cleanup for one explicitly applied, Browser Session-owned screen-area override. +/// +/// The pinned Working Draft defines `screenArea: null` as removal of the exact context-scoped override; +/// it does not restore a predecessor value. Requiring the same opaque ownership witness prevents a raw +/// browsing-context identifier from becoming cleanup authority. Planning still proves neither transport +/// execution nor post-cleanup page observation. +#[must_use] +pub fn plan_explicit_screen_area_cleanup( + ownership: &WebDriverBidiScreenAreaOwnership, +) -> WebDriverBidiPresentationCommand { + WebDriverBidiPresentationCommand::ResetScreenArea { + ownership: ownership.clone(), + } +} + /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// /// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the -/// pinned Working Draft. Screen-area mutation is excluded even as an explicit context-only command: -/// setting a rectangle can replace another owner's override and `screenArea: null` removes the current -/// override rather than restoring a prior value. Reduced motion remains an expressible protocol -/// capability, but this reusable planning boundary neither installs nor exposes a media-mutation -/// command because `features: null` clears the complete media-feature configuration rather than -/// restoring only OriginWeave's prior `prefers-reduced-motion` value. The explicit arguments make this -/// a partial-plan API: it cannot be mistaken for application of a complete -/// [`originweave_fingerprint::PresentationProfile`]. +/// pinned Working Draft. The screen-settings override is excluded from this profile-derived plan even +/// though the protocol exposes a nullable reset because it also changes the unmodelled page-observable +/// available screen area and requires Browser Session ownership of the predecessor state. Reduced +/// motion remains an expressible protocol capability, but this reusable planning boundary neither +/// installs nor exposes a media-mutation command because `features: null` clears the complete +/// media-feature configuration rather than restoring only OriginWeave's prior `prefers-reduced-motion` +/// value. The explicit arguments make this a partial-plan API: it cannot be mistaken for application of +/// a complete [`originweave_fingerprint::PresentationProfile`]. #[must_use] pub fn plan_standard_presentation_commands( context: &WebDriverBidiBrowsingContext, @@ -161,9 +226,10 @@ pub fn plan_standard_presentation_commands( /// /// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR /// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area -/// cleanup is absent because this boundary cannot prove ownership of the current screen override or -/// restore a predecessor value. Media cleanup is absent because `features: null` clears the complete -/// media-feature override configuration rather than selectively undoing `prefers-reduced-motion`. +/// cleanup is deliberately separate and ownership-gated because `screenArea: null` removes the current +/// override rather than restoring any predecessor. Media cleanup is absent because `features: null` +/// clears the complete media-feature override configuration rather than selectively undoing +/// `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( context: &WebDriverBidiBrowsingContext, @@ -203,12 +269,10 @@ const WEBDRIVER_BIDI_PRESENTATION_SURFACES: [PresentationSurface; 4] = [ /// The protocol can explicitly couple total and available screen width/height through /// `emulation.setScreenSettingsOverride`, but OriginWeave's `Screen` surface also includes color depth /// and the current profile does not model the available screen rectangle. `Screen` therefore remains -/// intentionally absent. This adapter additionally withholds screen-area mutation until Browser -/// Session proves ownership of the affected override lifecycle. Ordered-language surfaces, hardware -/// concurrency, and the Chromium platform/User-Agent Client Hints surface are also absent. Reduced -/// motion is listed as protocol capability even though reusable application leaves media state -/// untouched until a Browser Session owner supplies a restorable lifecycle and corresponding command -/// authority. +/// intentionally absent. Ordered-language surfaces, hardware concurrency, and the Chromium +/// platform/User-Agent Client Hints surface are also absent. Reduced motion is listed as protocol +/// capability even though reusable application leaves media state untouched until a Browser Session +/// owner supplies a restorable lifecycle and corresponding command authority. #[must_use] pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSurface] { &WEBDRIVER_BIDI_PRESENTATION_SURFACES @@ -217,10 +281,10 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the standard screen-area -/// value does not control color depth, the profile does not model available-screen geometry, and this -/// adapter has no Browser Session ownership witness for mutating existing screen-settings state. -/// Callers must not translate that result into ambient-host fallback. +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area +/// command does not control color depth, additionally couples an available-screen observable absent +/// from the current profile, and cannot be materialized until Browser Session supplies ownership of the +/// screen-settings lifecycle. Callers must not translate that result into ambient-host fallback. pub fn require_complete_presentation_profile() -> Result<(), PresentationError> { require_presentation_surfaces(webdriver_bidi_presentation_surfaces()) } @@ -264,7 +328,7 @@ mod tests { } #[test] - fn screen_area_value_preserves_protocol_coupling_without_mutation_authority() { + fn explicit_screen_area_commands_require_the_same_ownership_witness() { let profile = PresentationProfile::new( ScreenMetrics::new(1920, 1080).expect("valid screen"), ViewportBounds::new(1440, 900).expect("valid viewport"), @@ -276,10 +340,27 @@ mod tests { true, ) .expect("consistent profile"); + let context = + WebDriverBidiBrowsingContext::new("context-17").expect("bounded context identifier"); + let ownership = WebDriverBidiScreenAreaOwnership { + context: context.clone(), + }; let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); + assert_eq!(ownership.context(), &context); assert_eq!(screen_area.width(), 1920); assert_eq!(screen_area.height(), 1080); + assert_eq!( + plan_explicit_screen_area_override(&ownership, profile.screen()), + WebDriverBidiPresentationCommand::SetScreenArea { + ownership: ownership.clone(), + screen_area, + } + ); + assert_eq!( + plan_explicit_screen_area_cleanup(&ownership), + WebDriverBidiPresentationCommand::ResetScreenArea { ownership } + ); } #[test] From c85a4bf5effa415295c1024ea26161d17954d6ae Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:08:06 +0900 Subject: [PATCH 24/35] docs(bidi): single-source publication freshness --- docs/doctoring.md | 64 +++++++++++++++++++---------------------------- 1 file changed, 26 insertions(+), 38 deletions(-) diff --git a/docs/doctoring.md b/docs/doctoring.md index 0fb13a2fc..44fb51d13 100644 --- a/docs/doctoring.md +++ b/docs/doctoring.md @@ -51,42 +51,32 @@ that a non-mobile user agent reports an empty model (see ADR 0112). The pinned 3 September 2026 WebDriver BiDi Working Draft exposes locale, media, screen, user-agent, viewport, and time-zone emulation commands under the immutable publication `https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/`. The screen -settings shape contains width and height but not color depth, and locale accepts one -value rather than an ordered language list, so neither proves the corresponding -complete OriginWeave surface. The 9 September 2026 Working Draft retains the relevant -`emulation.setScreenSettingsOverride` shape; that publication update is tracked -separately and does not silently repin runtime compatibility. - -The screen-settings operation has a second page-observable effect that the earlier -planner description omitted: the specification applies the same `screenArea` -rectangle to both the web-exposed total screen area and the web-exposed available -screen area. OriginWeave `ScreenMetrics` currently models width, height, and color -depth but not `screen.availWidth` or `screen.availHeight`. A reusable profile-derived -planner therefore cannot silently schedule this operation merely because it has a -nullable reset. PR #310 keeps the typed `WebDriverBidiScreenArea` capability and its -context-scoped reset, but exposes them as a separately explicit partial intent; the -ordinary reusable plan remains viewport/DPR plus timezone until available-screen -geometry is deliberately represented and digest-bound by the presentation identity. -Complete `PresentationSurface::Screen` admission remains fail-closed because color -depth is still uncontrolled as well. - -The draft does not define a hardware-concurrency override. Chromium's tip-of-tree -DevTools Protocol exposes `Emulation.setHardwareConcurrencyOverride` as Experimental -and warns that tip-of-tree commands can change without notice. OriginWeave therefore -records required presentation surfaces in a protocol-neutral Rust admission contract. -Reduced motion remains an expressible protocol capability, but the reusable-context -plan neither installs it nor emits a media reset because -`emulation.setMediaFeaturesOverride` with `features: null` clears the complete media -configuration rather than selectively reversing only `prefers-reduced-motion`. -No caller-mintable exclusive reset substitutes for Browser Session ownership evidence. -Constructing application or cleanup intents performs no transport I/O and cannot be -treated as acknowledgement, successful cleanup, ownership evidence, or page-observed -presentation evidence. A later pinned Chromium adapter must capability-negotiate every -surface, observe post-conditions after apply and cleanup, and either prove exclusive -disposable context ownership or restore the complete pre-existing configuration before -reusing the browser boundary. The focused screen-area evidence and alternatives are -recorded in `docs/doctoring/webdriver-bidi-screen-area.md` and -`docs/traceability/webdriver-bidi-screen-area-planning.md`. +shape contains width and height but not color depth, and locale accepts one value +rather than an ordered language list, so neither proves the corresponding complete +OriginWeave surface. The draft also does not define a hardware-concurrency +override. Chromium's tip-of-tree DevTools Protocol exposes +`Emulation.setHardwareConcurrencyOverride` as Experimental and warns that +tip-of-tree commands can change without notice. OriginWeave therefore records +required presentation surfaces in a protocol-neutral Rust admission contract; +the adapter records those four complete standard surfaces as protocol +capabilities, while the reusable-context plan emits only two typed command +intents—viewport/DPR and timezone—bound to one bounded opaque browsing context. + +Cleanup authority is asymmetric. Nullable viewport and timezone operations can +restore those adapter-owned overrides on a reusable context, so generic cleanup +plans reset viewport/DPR and timezone. By contrast, +`emulation.setMediaFeaturesOverride` with `features: null` unsets the target's +complete media-feature override configuration rather than selectively reversing +only `prefers-reduced-motion`. The reusable-context plan therefore neither +installs reduced motion nor emits a media reset. No caller-mintable exclusive +reset is exposed as ownership evidence; a Browser Session owner must prove a +disposable context lifecycle or restore the complete prior media configuration. Constructing application or cleanup +intents performs no transport I/O and cannot be treated as acknowledgement, +successful cleanup, ownership evidence, or page-observed presentation evidence. +A later pinned Chromium adapter must capability-negotiate every surface, observe +post-conditions after apply and cleanup, and either prove exclusive disposable +context ownership or restore the complete pre-existing media configuration +before reusing the browser boundary. ### Extension-to-Agent grant origin binding @@ -276,8 +266,6 @@ World Wide Web Consortium. (2013). *PROV-O: The PROV ontology*. https://www.w3.o World Wide Web Consortium. (2025, September 25). *Mitigating browser fingerprinting in Web specifications*. https://www.w3.org/TR/fingerprinting-guidance/ -World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* (W3C Working Draft). https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ - World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* (W3C Working Draft). https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ World Wide Web Consortium. (2026). *WebDriver BiDi* (Editor's Draft). https://w3c.github.io/webdriver-bidi/ From 48373090dd982b1f853731957078d0ef4f744961 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:09:04 +0900 Subject: [PATCH 25/35] docs(bidi): bind screen-area reset to owned lifecycle --- docs/doctoring/webdriver-bidi-screen-area.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/doctoring/webdriver-bidi-screen-area.md b/docs/doctoring/webdriver-bidi-screen-area.md index 5fcf5fa01..a6dcdce63 100644 --- a/docs/doctoring/webdriver-bidi-screen-area.md +++ b/docs/doctoring/webdriver-bidi-screen-area.md @@ -1,17 +1,17 @@ # WebDriver BiDi screen-area doctoring -The runtime-qualified protocol identity remains the W3C WebDriver BiDi Working Draft published 3 September 2026. The current 9 September 2026 publication retains the same relevant `emulation.setScreenSettingsOverride` shape, but publication freshness does not itself change OriginWeave's runtime pin. +The runtime-qualified protocol identity remains the W3C WebDriver BiDi Working Draft published 3 September 2026. Publication freshness is tracked separately in `docs/traceability/webdriver-bidi-publication-current.md` and does not by itself change OriginWeave's runtime pin. -For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. The W3C operation uses the same non-null rectangle for both the web-exposed total screen area and the web-exposed available screen area; `screenArea: null` removes that context-scoped override. The reset is symmetric, but the mutation is wider than `ScreenMetrics(width, height, color_depth)` because the current presentation identity does not model `screen.availWidth` or `screen.availHeight`. +For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `screenArea` as width/height or `null`. The W3C operation uses the same non-null rectangle for both the web-exposed total screen area and the web-exposed available screen area. When `screenArea` is `null`, the remote end removes that context from the screen-settings override map; the command does not restore any predecessor override value. -OriginWeave therefore exposes this as an explicit partial `WebDriverBidiScreenArea` intent rather than inserting it into the reusable profile-derived presentation plan. The value object can only project width and height from validated `ScreenMetrics`, and its rustdoc makes the total/available-area coupling explicit. The ordinary reusable planner remains limited to viewport/DPR and time zone until the presentation schema deliberately models and digest-binds the available-screen observable. +That lifecycle matters independently of the profile schema. `ScreenMetrics(width, height, color_depth)` still does not model `screen.availWidth` or `screen.availHeight`, so the reusable profile-derived plan cannot silently apply the operation. A raw `WebDriverBidiBrowsingContext` also cannot authorize the separate explicit operation: replacing or removing the current override could mutate state installed by another owner. -The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an explicit screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. +OriginWeave therefore keeps `WebDriverBidiScreenArea` as the typed width/height representation but gates `SetScreenArea`, `ResetScreenArea`, and both explicit planners on an opaque `WebDriverBidiScreenAreaOwnership` witness. That witness has no public constructor in the adapter. A Browser Session integration may create it only after establishing an exclusive/disposable browsing context or an equivalent lifecycle proof that prevents replacement or removal of unrelated screen-settings state. Possession of a remote context identifier alone is not ownership evidence. -This evidence changes only typed command planning. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence, including post-reset re-observation before a reusable context can be trusted again. +The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an owned screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. + +This evidence changes typed command authority only. It is not live WebDriver BiDi transport, command acknowledgement, page-observed state, browser cleanup proof, or complete Chromium presentation acceptance. Those remain separate Browser Session/runtime evidence, including post-reset observation and actual disposable-context destruction or equivalent restoration proof before a reusable boundary can be trusted again. ## References World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ - -World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* [Working Draft; latest publication tracked separately]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ From aee332cc0cd631770d0747d0f0ed6faf6d8d2877 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:09:22 +0900 Subject: [PATCH 26/35] docs(bidi): trace screen-area ownership authority --- .../webdriver-bidi-screen-area-planning.md | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/traceability/webdriver-bidi-screen-area-planning.md b/docs/traceability/webdriver-bidi-screen-area-planning.md index f99e056a5..0a10842dd 100644 --- a/docs/traceability/webdriver-bidi-screen-area-planning.md +++ b/docs/traceability/webdriver-bidi-screen-area-planning.md @@ -2,52 +2,58 @@ ## Problem -The runtime-qualified WebDriver BiDi adapter already plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. OriginWeave did not expose that standard operation in its typed planning boundary. +The runtime-qualified WebDriver BiDi adapter plans reversible viewport/device-pixel-ratio and time-zone overrides, while the 3 September 2026 Working Draft also defines `emulation.setScreenSettingsOverride`. The screen operation is wider and more destructive than its width/height payload initially suggests. -The operation is not merely a narrower version of `PresentationSurface::Screen`. WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total screen area and the web-exposed available screen area. OriginWeave `ScreenMetrics` currently models width, height, and color depth, but not `screen.availWidth` or `screen.availHeight`. Automatically deriving the command from `ScreenMetrics` inside the reusable profile plan would therefore mutate a page-observable fingerprint surface that the profile neither selected nor digest-bound. Color depth remains independently uncontrolled as well. +WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total screen area and the web-exposed available screen area. OriginWeave `ScreenMetrics` currently models width, height, and color depth, but not `screen.availWidth` or `screen.availHeight`. Automatically deriving the command from `ScreenMetrics` inside the reusable profile plan would therefore mutate a page-observable fingerprint surface that the profile neither selected nor digest-bound. Color depth remains independently uncontrolled. + +A second authority defect remains even when the operation is separated from the profile-derived plan. The standard stores one override per target browsing context. Setting a rectangle replaces that target's current override; `screenArea: null` removes the target from the override map. The standard does not restore a predecessor value. A validated browsing-context identifier therefore identifies where a mutation would occur but does not prove that OriginWeave owns the state being replaced or cleared. ## Constraints - Keep browser-domain truth in OriginWeave; WebDriver BiDi remains an adapter, not policy authority. - Preserve the runtime-qualified 3 September 2026 Working Draft pin. Publication freshness is owned separately by `webdriver-bidi-publication-current.md`. - Reuse validated presentation value objects rather than reopen raw width/height validation in the adapter. -- A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with a context-scoped, non-destructive reset. +- Do not treat a browsing-context identifier as mutation authority. +- A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with non-destructive cleanup. +- Screen-area mutation requires an exclusive/disposable Browser Session context or equivalent ownership proof before the command can be materialized. - Do not add media-feature cleanup, ambient-host fallback, live protocol I/O, command-ACK success semantics, or Chromium-specific authority here. ## Alternatives -1. **Insert screen settings into the reusable profile-derived plan.** Rejected. Although `screenArea: null` provides a symmetric reset, the apply operation also changes the currently unmodelled available-screen rectangle. Reversibility alone does not authorize an additional page observable. +1. **Insert screen settings into the reusable profile-derived plan.** Rejected. The apply operation changes the currently unmodelled available-screen rectangle, and the nullable reset does not restore a predecessor override. 2. **Mark `PresentationSurface::Screen` supported after planning width/height.** Rejected because color depth remains page-observable and uncontrolled, and available-screen geometry is absent from the profile. 3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would contain color depth, which the protocol operation does not apply, while still failing to name the available-screen side effect. -4. **Expose an explicit coupled screen-area partial intent and keep it out of the reusable profile-derived plan.** Selected. `WebDriverBidiScreenArea` projects validated width/height, documents that the same rectangle becomes both total and available screen area, and has a separate context-scoped reset. This preserves the protocol capability without silently broadening the presentation profile. -5. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence. It requires its own test-first bounded change rather than being hidden inside an adapter slice. +4. **Expose context-only explicit Set/Reset commands.** Rejected after review. A context identifier does not establish ownership; setting can replace another owner's override and resetting can erase it without restoration. +5. **Remove the standard capability entirely.** Rejected. The protocol operation is useful and can be represented safely without making it ambient authority. +6. **Keep the typed screen-area value and gate explicit mutation on an opaque Browser Session ownership witness.** Selected. The adapter retains protocol semantics while making lifecycle authority non-caller-mintable until a Browser Session owner proves an exclusive/disposable context or equivalent safe ownership transition. +7. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence and needs its own test-first change. ## Decision -`originweave-bidi` exposes `plan_explicit_screen_area_override` and `plan_explicit_screen_area_cleanup` as a separately explicit partial capability. The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone because those are the currently modelled, reusable-plan observables with symmetric resets. +`originweave-bidi` retains `WebDriverBidiScreenArea` as the validated width/height projection and retains explicit `SetScreenArea` / `ResetScreenArea` command intent. Both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership` rather than a raw `WebDriverBidiBrowsingContext`. -`WebDriverBidiScreenArea` can only be derived from validated `ScreenMetrics`; its documentation records that WebDriver BiDi couples total and available screen areas to the same rectangle. The complete capability map intentionally continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models the available-screen observable and controls color depth as well. +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context but intentionally has no public constructor. The adapter therefore cannot mint its own proof from a context identifier. A future Browser Session integration may create the witness only after proving an exclusive/disposable lifecycle or an equivalent ownership transition. Possession of the witness is the authority to plan both the apply and matching cleanup for that owned lifecycle; it is not transport acknowledgement or page-observed evidence. -The planner produces typed intent only. Transport execution, page-observed post-conditions, browser/session cleanup evidence, crash recovery, and the remaining Chromium-only presentation surfaces stay with the existing #292/#299 acceptance path and its canonical runtime owners. +The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone. The complete capability map continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models available-screen geometry, controls color depth, and proves the runtime application/cleanup lifecycle. ## Evidence and acceptance -The review finding on PR #310 exact `e3b2b412d8ad880c87354fb3ffd5f5b4ff6cde0d` identified the unmodelled available-screen side effect. Test-first successor `8f74471e1a5414e8781531f968b46807e2d7e3d8` adds a contract that fails whenever the profile-derived reusable planner schedules `SetScreenArea` without available width/height being represented by `ScreenMetrics`. The minimal source repair separates the explicit screen-area operation from the reusable profile-derived plan. +PR #310 review identified two distinct findings. The first was the unmodelled available-screen side effect, repaired by keeping screen-area mutation out of the profile-derived reusable plan. The later exact-head review identified the ownership gap: a context-only `ResetScreenArea` could remove another owner's active override because `screenArea: null` deletes the target's override-map entry rather than restoring a prior value. -Acceptance requires: +The successor contract requires: -- a typed screen-area intent derived from validated screen metrics; -- explicit documentation that one WebDriver BiDi rectangle controls both total and available screen areas; -- a separately explicit context-scoped screen-area reset; +- `WebDriverBidiScreenArea` to remain the typed width/height representation derived from validated screen metrics; +- an opaque `WebDriverBidiScreenAreaOwnership` carrying the exact context with no public mint constructor in the adapter; +- `SetScreenArea`, `ResetScreenArea`, and both explicit planners to require that ownership witness rather than a raw context identifier; - no screen-area mutation in the reusable profile-derived plan while available-screen geometry is unmodelled; - no media-feature reset; -- no color-depth field in the screen-area command value object; and +- no color-depth field in the screen-area value object; and - continued fail-closed complete Screen admission. -Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence and must not be transferred from predecessor heads. +The initial successor RED briefly over-constrained the repair by requiring removal of all screen-area command intents. That was corrected before acceptance: deleting a useful standard capability is not necessary when its mutation authority can instead be represented explicitly and made non-caller-mintable. + +Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence. A command intent or acknowledgement is never substituted for apply → page-observed post-condition → interaction/outcome → owned cleanup/destruction → post-cleanup observation. ## References World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ - -World Wide Web Consortium. (2026, September 9). *WebDriver BiDi* [Working Draft; latest publication tracked separately]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260909/ From 47ab396fd8234e95f53c8a429be30d29b91f5041 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:10:12 +0900 Subject: [PATCH 27/35] docs(adr): govern BiDi screen-area ownership witness --- ...13-webdriver-bidi-screen-area-ownership.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/adr/0113-webdriver-bidi-screen-area-ownership.md diff --git a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md new file mode 100644 index 000000000..d8c797a1e --- /dev/null +++ b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md @@ -0,0 +1,65 @@ +# ADR 0113: WebDriver BiDi screen-area ownership witness + +- Status: Proposed +- Date: 2026-09-10 +- Supersedes: none +- Superseded by: none +- Refines: ADR 0107 + +## Problem + +ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned cleanup for presentation overrides. PR #310 then exposed `emulation.setScreenSettingsOverride` as an explicit partial intent while correctly excluding it from the reusable profile-derived plan because one rectangle changes both total and available screen geometry. + +The remaining authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. + +## Constraints + +- Keep browser-domain and Browser Session lifecycle authority in OriginWeave. +- Keep WebDriver BiDi as an adapter; protocol addressability is not product authorization. +- Preserve the runtime-qualified 3 September 2026 Working Draft pin until a separate compatibility change proves a newer revision. +- Preserve the typed `WebDriverBidiScreenArea` width/height representation and the protocol's total/available-area coupling. +- Do not invent a snapshot/restore facility that WebDriver BiDi does not provide. +- Do not let a command acknowledgement substitute for page-observed application or cleanup evidence. +- Keep the reusable profile-derived planner free of screen-area mutation while available-screen geometry remains unmodelled and color depth remains uncontrolled. + +## Alternatives + +1. **Keep context-only Set/Reset planners.** Rejected. Any caller able to supply a valid remote context identifier could replace or delete screen-settings state without proving ownership. +2. **Delete screen-area support.** Rejected. The standard capability is useful and can be represented without granting ambient mutation authority. +3. **Capture and restore an assumed predecessor value.** Rejected. This slice has no authoritative predecessor snapshot and the standard reset semantics remove the override rather than restore one. +4. **Treat a successful Set command as ownership proof.** Rejected. It can already have overwritten another owner's state; acknowledgement is too late to establish authorization. +5. **Require an opaque Browser Session ownership witness before planning Set or Reset.** Selected. The witness is not caller-mintable from a context identifier and can later be produced only by the lifecycle owner after exclusive/disposable-context establishment or equivalent ownership proof. + +## Decision + +`originweave-bidi` retains `WebDriverBidiScreenArea` and the explicit `SetScreenArea` / `ResetScreenArea` command intents, but both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership`. + +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context and intentionally exposes no public constructor in the adapter. Its public context accessor permits a transport integration that already possesses the witness to address the command without reopening validation. A future Browser Session integration may mint the witness only after establishing an exclusive/disposable browsing context or an equivalent lifecycle guarantee that no unrelated screen override can be replaced or removed. + +This is capability representation, not runtime proof. The current adapter has no external mint path, so screen-area mutation is unavailable until Browser Session supplies the missing ownership transition. The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. + +## Security and governance effects + +A remote-issued context identifier is treated as untrusted addressing metadata rather than mutation authority. The ownership witness prevents adapters, MCP callers, LLM output, page content, or other context-aware code from acquiring screen-settings mutation merely by naming a valid browsing context. + +The witness must never be synthesized from command acknowledgement, ambient browser state, mutable external metadata, or a raw context identifier. If the Browser Session owner cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, screen-area mutation remains unavailable and the complete presentation profile continues to fail closed. + +## Acceptance evidence + +The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the tests now require an opaque non-caller-mintable ownership type, require both Set and Reset variants to carry it, require both explicit planners to accept it rather than a raw context, and continue to forbid screen-area commands in the reusable profile-derived plan. + +Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. + +## Risks and follow-up + +The opaque witness deliberately makes screen-area application unusable until Browser Session integration exists. That is preferred to exposing destructive context-only cleanup. The next browser-runtime slice must define where the witness is minted, how exclusivity/disposability is proven, how it is invalidated on context destruction/navigation boundaries where applicable, and how runtime evidence binds the witness to the exact command and cleanup lifecycle. + +If a future WebDriver BiDi revision adds authoritative predecessor-state restoration, the ownership model may be revisited through a separate versioned compatibility decision; publication alone is not sufficient. + +## References + +World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ + +## Related documents + +See ADR 0107, `docs/doctoring/webdriver-bidi-screen-area.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/traceability/webdriver-bidi-publication-current.md`. From 7bb310507d6f47799489264a17d82280329e2343 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:15:55 +0900 Subject: [PATCH 28/35] docs(adr): index screen-area ownership decision --- docs/adr/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index a9fffa042..25aa31c0c 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -65,10 +65,11 @@ ADR 0013, ADR 0014, ADR 0110, ADR 0111, and ADR 0112 exist only on this document | ADR | Decision | Status | Governs | |---|---|---|---| | [0016](0016-bap-task-lifecycle-authority.md) | BAP task lifecycle and state authority | Proposed | BAP task states, transitions, recovery validation, transition sequencing, and authority separation | +| [0113](0113-webdriver-bidi-screen-area-ownership.md) | WebDriver BiDi screen-area ownership witness | Proposed | Browser Session-owned screen-settings mutation, destructive reset boundary, and fail-closed adapter authority | -ADR 0016 belongs to the active BAP lifecycle feature branch. Indexing it makes the branch documentation graph complete while preserving its Proposed lifecycle and active-PR, non-protected-main maturity. +ADR 0016 belongs to the active BAP lifecycle feature branch. ADR 0113 belongs to the active WebDriver BiDi screen-area ownership successor. Indexing them makes the branch documentation graph complete while preserving Proposed lifecycle and active-PR, non-protected-main maturity. -After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 from Proposed or assert implementation maturity. +After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 or ADR 0113 from Proposed or assert implementation maturity. Other active feature PRs may contain additional Proposed ADRs. Those files are not part of this canonical documentation line until integrated or deliberately reconciled here. Historical PR checks, stale branch state, or chat decisions never transfer ADR acceptance across a changed head. From 8eb3340fde264d34e1cc0f4152dd909a6f634cec Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:17:14 +0900 Subject: [PATCH 29/35] docs(adr): discover screen-area ownership decision --- docs/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/README.md b/docs/README.md index 622fc7e99..fd2c19ec9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -93,9 +93,10 @@ The second group exists only on this documentation branch until the branch integ ### Proposed decisions introduced by active feature work - [ADR 0016: BAP task lifecycle and state authority](adr/0016-bap-task-lifecycle-authority.md) +- [ADR 0113: WebDriver BiDi screen-area ownership witness](adr/0113-webdriver-bidi-screen-area-ownership.md) -ADR 0016 is owned by this active BAP lifecycle feature branch and remains Proposed. Its presence here makes the branch documentation graph complete without presenting the decision or implementation as protected-main truth before integration. +ADR 0016 is owned by the active BAP lifecycle feature branch. ADR 0113 is owned by the active WebDriver BiDi screen-area ownership successor. Their presence here makes the branch documentation graph complete without presenting either decision or implementation as protected-main truth before integration. -After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 from Proposed or assert implementation maturity. +After protected-main integration, retain this subsection only when it is intentionally serving as historical provenance; otherwise protected-main reconciliation must remove it. In either case, integration alone does not change ADR 0016 or ADR 0113 from Proposed or assert implementation maturity. See the [ADR index](adr/README.md) for status rules, required decision structure, supersession rules, and active feature ADRs. The index and each ADR's own status metadata must agree; a PR body, chat transcript, automation prompt, or stale issue reference cannot change ADR status. From f1380ab8e091964ccbdd576d933cf19d696c3791 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 08:20:11 +0900 Subject: [PATCH 30/35] docs(adr): align screen ownership decision structure --- ...13-webdriver-bidi-screen-area-ownership.md | 90 +++++++++++++------ 1 file changed, 62 insertions(+), 28 deletions(-) diff --git a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md index d8c797a1e..96c2a4397 100644 --- a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md +++ b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md @@ -1,33 +1,41 @@ # ADR 0113: WebDriver BiDi screen-area ownership witness -- Status: Proposed -- Date: 2026-09-10 -- Supersedes: none -- Superseded by: none -- Refines: ADR 0107 +- **Status:** Proposed +- **Date:** 2026-09-10 +- **Supersedes:** none +- **Superseded by:** none +- **Refines:** ADR 0107 -## Problem +## Context -ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned cleanup for presentation overrides. PR #310 then exposed `emulation.setScreenSettingsOverride` as an explicit partial intent while correctly excluding it from the reusable profile-derived plan because one rectangle changes both total and available screen geometry. +ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned cleanup for presentation overrides. PR #310 exposed `emulation.setScreenSettingsOverride` as an explicit partial intent while correctly excluding it from the reusable profile-derived plan because one rectangle changes both total and available screen geometry. -The remaining authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. +A second authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. -## Constraints +## Decision drivers -- Keep browser-domain and Browser Session lifecycle authority in OriginWeave. -- Keep WebDriver BiDi as an adapter; protocol addressability is not product authorization. -- Preserve the runtime-qualified 3 September 2026 Working Draft pin until a separate compatibility change proves a newer revision. -- Preserve the typed `WebDriverBidiScreenArea` width/height representation and the protocol's total/available-area coupling. -- Do not invent a snapshot/restore facility that WebDriver BiDi does not provide. -- Do not let a command acknowledgement substitute for page-observed application or cleanup evidence. -- Keep the reusable profile-derived planner free of screen-area mutation while available-screen geometry remains unmodelled and color depth remains uncontrolled. +- Preserve the useful typed WebDriver BiDi screen-area capability without granting ambient mutation authority. +- Prevent a raw browsing-context identifier from authorizing replacement or removal of another owner's override. +- Keep cleanup evidence causal: ownership must exist before the destructive mutation, not be inferred from a later command acknowledgement. +- Keep the reusable profile-derived planner limited to observables represented by the profile and paired with safe cleanup semantics. +- Keep complete Screen admission fail-closed while available-screen geometry and color depth remain uncontrolled. -## Alternatives +## Assumptions and authority boundaries + +- Browser-domain and Browser Session lifecycle authority remain in OriginWeave. +- WebDriver BiDi remains an adapter; protocol addressability is not product authorization. +- The runtime-qualified 3 September 2026 Working Draft pin remains unchanged until a separate compatibility change proves a newer revision. +- `WebDriverBidiScreenArea` remains the typed width/height representation of the protocol's coupled total/available-area rectangle. +- This slice has no authoritative predecessor-state snapshot and does not invent one. +- A command acknowledgement is not page-observed application, ownership evidence, cleanup evidence, or restoration evidence. +- Screen-area mutation may become executable only after Browser Session proves an exclusive/disposable browsing context or an equivalent restoration-safe lifecycle. + +## Options considered 1. **Keep context-only Set/Reset planners.** Rejected. Any caller able to supply a valid remote context identifier could replace or delete screen-settings state without proving ownership. 2. **Delete screen-area support.** Rejected. The standard capability is useful and can be represented without granting ambient mutation authority. 3. **Capture and restore an assumed predecessor value.** Rejected. This slice has no authoritative predecessor snapshot and the standard reset semantics remove the override rather than restore one. -4. **Treat a successful Set command as ownership proof.** Rejected. It can already have overwritten another owner's state; acknowledgement is too late to establish authorization. +4. **Treat a successful Set command as ownership proof.** Rejected. The Set can already have overwritten another owner's state; acknowledgement is too late to establish authorization. 5. **Require an opaque Browser Session ownership witness before planning Set or Reset.** Selected. The witness is not caller-mintable from a context identifier and can later be produced only by the lifecycle owner after exclusive/disposable-context establishment or equivalent ownership proof. ## Decision @@ -38,28 +46,54 @@ The remaining authority problem is independent of that schema gap. WebDriver BiD This is capability representation, not runtime proof. The current adapter has no external mint path, so screen-area mutation is unavailable until Browser Session supplies the missing ownership transition. The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. -## Security and governance effects +## Consequences + +The adapter preserves the standard screen-area value and explicit command vocabulary while making destructive mutation unavailable to ordinary context-aware callers. A later Browser Session integration has a narrow place to attach lifecycle proof instead of widening the browsing-context value object into authorization. + +The trade-off is deliberate: screen-area application cannot currently be materialized outside the module. Product code must remain fail-closed until the lifecycle owner supplies a reviewed witness producer. + +## Failure and degraded behavior + +If Browser Session cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, no ownership witness is available and screen-area Set/Reset cannot be planned by external callers. OriginWeave must not fall back to a raw context identifier, ambient browser state, an LLM decision, a command acknowledgement, or best-effort cleanup. + +The reusable profile planner continues to omit screen-area mutation. Complete presentation-profile admission continues to return `MissingSurface(Screen)` because available-screen geometry is unmodelled and color depth is uncontrolled. + +## Security / privacy / governance impact A remote-issued context identifier is treated as untrusted addressing metadata rather than mutation authority. The ownership witness prevents adapters, MCP callers, LLM output, page content, or other context-aware code from acquiring screen-settings mutation merely by naming a valid browsing context. -The witness must never be synthesized from command acknowledgement, ambient browser state, mutable external metadata, or a raw context identifier. If the Browser Session owner cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, screen-area mutation remains unavailable and the complete presentation profile continues to fail closed. +The witness must never be synthesized from command acknowledgement, ambient browser state, mutable external metadata, or a raw context identifier. If lifecycle ownership cannot be proven, screen-area mutation remains unavailable. -## Acceptance evidence +No identity, egress, secret, policy, approval, or Context Fabric authority moves into the WebDriver BiDi adapter. The decision remains Proposed until policy-compliant protected-main review changes its lifecycle. -The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the tests now require an opaque non-caller-mintable ownership type, require both Set and Reset variants to carry it, require both explicit planners to accept it rather than a raw context, and continue to forbid screen-area commands in the reusable profile-derived plan. +## Tests and acceptance evidence + +The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the repository contract now requires an opaque non-caller-mintable ownership type, requires both Set and Reset variants to carry it, requires both explicit planners to accept it rather than a raw context, and continues to forbid screen-area commands in the reusable profile-derived plan. Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. -## Risks and follow-up +## Migration and rollback + +This active branch changes only the typed planner contract. Existing callers that used context-only screen-area planners must not be mechanically migrated by manufacturing a witness; they must move behind the future Browser Session lifecycle owner or remain unable to invoke the operation. + +Rollback removes ADR 0113 and the ownership-witness change together with its contract tests. It must not restore the context-only public Set/Reset authority without a separate reviewed decision, because that would reintroduce the destructive-cleanup defect. + +## Open follow-ups -The opaque witness deliberately makes screen-area application unusable until Browser Session integration exists. That is preferred to exposing destructive context-only cleanup. The next browser-runtime slice must define where the witness is minted, how exclusivity/disposability is proven, how it is invalidated on context destruction/navigation boundaries where applicable, and how runtime evidence binds the witness to the exact command and cleanup lifecycle. +- Define the Browser Session aggregate transition that mints the witness only after exclusive/disposable-context establishment or equivalent ownership proof. +- Bind witness invalidation to context/session destruction and any lifecycle boundary that makes the proof stale. +- Bind runtime evidence to the exact ownership witness, Set command, page-observed post-condition, cleanup or context destruction, and post-cleanup observation. +- Decide in a separate schema change whether `PresentationProfile` should model available-screen geometry; do not infer it from total screen size. +- Continue #299/#292 real-Chromium acceptance independently of this repository-only authority contract. -If a future WebDriver BiDi revision adds authoritative predecessor-state restoration, the ownership model may be revisited through a separate versioned compatibility decision; publication alone is not sufficient. +## Supersession / reversal conditions + +This ADR may be superseded if a later reviewed Browser Session design provides an equivalent non-forgeable capability with stronger lifetime semantics, or if a future WebDriver BiDi revision adds authoritative predecessor-state restoration that is separately compatibility-qualified. Publication of a newer draft alone is not sufficient. + +It is reversed only if OriginWeave removes the screen-area capability entirely or adopts another reviewed browser protocol boundary that provides equivalent ownership and cleanup guarantees. ## References World Wide Web Consortium. (2026, September 3). *WebDriver BiDi* [Working Draft; runtime-qualified OriginWeave adapter pin]. https://www.w3.org/TR/2026/WD-webdriver-bidi-20260903/ -## Related documents - -See ADR 0107, `docs/doctoring/webdriver-bidi-screen-area.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/traceability/webdriver-bidi-publication-current.md`. +Related repository evidence: ADR 0107, `docs/doctoring/webdriver-bidi-screen-area.md`, `docs/traceability/webdriver-bidi-screen-area-planning.md`, and `docs/traceability/webdriver-bidi-publication-current.md`. From e5295a0b72c0f2bb5693305a3ffa145a7fa88b30 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:01:35 +0900 Subject: [PATCH 31/35] test(bidi): reject dead screen-area planners before ownership mint --- ...webdriver_bidi_screen_settings_contract.py | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/test_webdriver_bidi_screen_settings_contract.py b/tests/test_webdriver_bidi_screen_settings_contract.py index 67832d4ef..00300e2d9 100644 --- a/tests/test_webdriver_bidi_screen_settings_contract.py +++ b/tests/test_webdriver_bidi_screen_settings_contract.py @@ -13,8 +13,8 @@ class WebDriverBiDiScreenSettingsContractTests(unittest.TestCase): """Keep screen geometry typed without silently widening page-observable authority.""" - def test_adapter_exposes_screen_area_only_through_owned_mutation_intent(self) -> None: - """The standard operation stays typed but requires Browser Session ownership.""" + def test_adapter_keeps_screen_area_typed_without_a_dead_external_planner(self) -> None: + """Dormant screen mutation stays typed but has no callable path before ownership can be minted.""" text = SOURCE.read_text(encoding="utf-8") self.assertIn("ScreenMetrics", text) @@ -22,8 +22,8 @@ def test_adapter_exposes_screen_area_only_through_owned_mutation_intent(self) -> self.assertIn("WebDriverBidiScreenAreaOwnership", text) self.assertIn("SetScreenArea", text) self.assertIn("ResetScreenArea", text) - self.assertIn("plan_explicit_screen_area_override", text) - self.assertIn("plan_explicit_screen_area_cleanup", text) + self.assertNotIn("pub fn plan_explicit_screen_area_override", text) + self.assertNotIn("pub fn plan_explicit_screen_area_cleanup", text) def test_profile_derived_plan_cannot_silently_mutate_available_screen_area(self) -> None: """A profile-derived reusable plan must not change an unmodelled page observable.""" @@ -67,12 +67,6 @@ def test_screen_area_mutation_requires_non_mintable_browser_session_ownership(se )[1].split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[0] set_variant = text.split("SetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] reset_variant = text.split("ResetScreenArea {", maxsplit=1)[1].split("},", maxsplit=1)[0] - override_planner = text.split( - "pub fn plan_explicit_screen_area_override", maxsplit=1 - )[1].split("pub fn plan_explicit_screen_area_cleanup", maxsplit=1)[0] - cleanup_planner = text.split( - "pub fn plan_explicit_screen_area_cleanup", maxsplit=1 - )[1].split("pub fn plan_standard_presentation_commands", maxsplit=1)[0] self.assertIn("context: WebDriverBidiBrowsingContext", ownership) self.assertNotIn("pub context:", ownership) @@ -82,10 +76,8 @@ def test_screen_area_mutation_requires_non_mintable_browser_session_ownership(se self.assertNotIn("context: WebDriverBidiBrowsingContext", set_variant) self.assertIn("ownership: WebDriverBidiScreenAreaOwnership", reset_variant) self.assertNotIn("context: WebDriverBidiBrowsingContext", reset_variant) - self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", override_planner) - self.assertNotIn("context: &WebDriverBidiBrowsingContext", override_planner) - self.assertIn("ownership: &WebDriverBidiScreenAreaOwnership", cleanup_planner) - self.assertNotIn("context: &WebDriverBidiBrowsingContext", cleanup_planner) + self.assertNotIn("pub fn plan_explicit_screen_area_override", text) + self.assertNotIn("pub fn plan_explicit_screen_area_cleanup", text) def test_screen_surface_remains_fail_closed_until_complete_observables_are_controlled(self) -> None: """Screen-area intent cannot satisfy the complete page-observable Screen contract.""" From 2fc2f64a102a5bf6f87b9d20e709efcab2905c1d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:02:37 +0900 Subject: [PATCH 32/35] fix(bidi): remove unreachable screen-area planner API --- .../src/presentation_capabilities.rs | 67 ++++++------------- 1 file changed, 21 insertions(+), 46 deletions(-) diff --git a/crates/originweave-bidi/src/presentation_capabilities.rs b/crates/originweave-bidi/src/presentation_capabilities.rs index d58ccf2b0..b47939e8a 100644 --- a/crates/originweave-bidi/src/presentation_capabilities.rs +++ b/crates/originweave-bidi/src/presentation_capabilities.rs @@ -92,7 +92,7 @@ impl WebDriverBidiScreenArea { /// removes it when `screenArea` is null. A Browser Session integration may create this witness only /// after it has established an exclusive/disposable context or an equivalent lifecycle that proves no /// unrelated owner state can be overwritten or cleared. Until that integration exists, external -/// callers can inspect neither a mint path nor a context-only escape hatch for screen-area mutation. +/// callers have neither a mint path nor a callable screen-area planner. #[derive(Debug, Clone, PartialEq, Eq)] pub struct WebDriverBidiScreenAreaOwnership { context: WebDriverBidiBrowsingContext, @@ -111,11 +111,11 @@ impl WebDriverBidiScreenAreaOwnership { /// These values are inputs to a later transport owner. Constructing them does not send a command, /// prove an acknowledgement, establish Browser Session ownership, or establish page-observed state. /// Presentation payloads retain validated value objects so a transport adapter cannot reopen raw -/// screen, viewport, DPR, or time-zone validation. Screen-area commands require an opaque Browser -/// Session ownership witness because setting or clearing the context override is destructive to any -/// predecessor value. This reusable-boundary enum deliberately exposes no media-feature mutation -/// command because this crate has no ownership or snapshot witness that would make such mutation -/// reversibly safe. +/// screen, viewport, DPR, or time-zone validation. Screen-area command vocabulary retains the opaque +/// Browser Session ownership witness because setting or clearing the context override is destructive to +/// any predecessor value. No public screen-area planner is exposed until Browser Session can mint that +/// witness. This reusable-boundary enum deliberately exposes no media-feature mutation command because +/// this crate has no ownership or snapshot witness that would make such mutation reversibly safe. #[derive(Debug, Clone, PartialEq, Eq)] pub enum WebDriverBidiPresentationCommand { /// Set total and available web-exposed screen width and height together. @@ -158,39 +158,6 @@ pub enum WebDriverBidiPresentationCommand { }, } -/// Plan one explicit partial screen-area override for a Browser Session-owned browsing context. -/// -/// WebDriver BiDi uses the same rectangle for both total and available screen areas. This operation is -/// deliberately separate from [`plan_standard_presentation_commands`] because the current -/// `PresentationProfile` does not model `screen.availWidth` or `screen.availHeight`. Possession of the -/// opaque ownership witness is additionally required because replacing the existing context override -/// is not a reversible context-only operation. -#[must_use] -pub fn plan_explicit_screen_area_override( - ownership: &WebDriverBidiScreenAreaOwnership, - screen: &ScreenMetrics, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::SetScreenArea { - ownership: ownership.clone(), - screen_area: WebDriverBidiScreenArea::from_screen(screen), - } -} - -/// Plan cleanup for one explicitly applied, Browser Session-owned screen-area override. -/// -/// The pinned Working Draft defines `screenArea: null` as removal of the exact context-scoped override; -/// it does not restore a predecessor value. Requiring the same opaque ownership witness prevents a raw -/// browsing-context identifier from becoming cleanup authority. Planning still proves neither transport -/// execution nor post-cleanup page observation. -#[must_use] -pub fn plan_explicit_screen_area_cleanup( - ownership: &WebDriverBidiScreenAreaOwnership, -) -> WebDriverBidiPresentationCommand { - WebDriverBidiPresentationCommand::ResetScreenArea { - ownership: ownership.clone(), - } -} - /// Plan the reversible standard-BiDi presentation commands safe for a reusable browsing context. /// /// Viewport/device-pixel-ratio and time-zone state each have a non-destructive nullable reset in the @@ -226,9 +193,10 @@ pub fn plan_standard_presentation_commands( /// /// The pinned Working Draft provides independently nullable context-scoped reset paths for viewport/DPR /// and time-zone state, so these two resets are safe to plan for a reusable browsing context. Screen-area -/// cleanup is deliberately separate and ownership-gated because `screenArea: null` removes the current -/// override rather than restoring any predecessor. Media cleanup is absent because `features: null` -/// clears the complete media-feature override configuration rather than selectively undoing +/// command intent remains ownership-gated, but no callable screen-area cleanup planner exists until +/// Browser Session can mint the ownership witness; `screenArea: null` removes the current override +/// rather than restoring any predecessor. Media cleanup is absent because `features: null` clears the +/// complete media-feature override configuration rather than selectively undoing /// `prefers-reduced-motion`. #[must_use] pub fn plan_standard_presentation_cleanup( @@ -281,7 +249,7 @@ pub const fn webdriver_bidi_presentation_surfaces() -> &'static [PresentationSur /// Require the pinned standard BiDi capability set to satisfy the complete profile. /// /// The current result remains fail-closed with -/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the explicit screen-area +/// `PresentationError::MissingSurface(PresentationSurface::Screen)` because the dormant screen-area /// command does not control color depth, additionally couples an available-screen observable absent /// from the current profile, and cannot be materialized until Browser Session supplies ownership of the /// screen-settings lifecycle. Callers must not translate that result into ambient-host fallback. @@ -328,7 +296,7 @@ mod tests { } #[test] - fn explicit_screen_area_commands_require_the_same_ownership_witness() { + fn screen_area_command_shape_requires_the_same_ownership_witness() { let profile = PresentationProfile::new( ScreenMetrics::new(1920, 1080).expect("valid screen"), ViewportBounds::new(1440, 900).expect("valid viewport"), @@ -346,19 +314,26 @@ mod tests { context: context.clone(), }; let screen_area = WebDriverBidiScreenArea::from_screen(profile.screen()); + let set_command = WebDriverBidiPresentationCommand::SetScreenArea { + ownership: ownership.clone(), + screen_area, + }; + let reset_command = WebDriverBidiPresentationCommand::ResetScreenArea { + ownership: ownership.clone(), + }; assert_eq!(ownership.context(), &context); assert_eq!(screen_area.width(), 1920); assert_eq!(screen_area.height(), 1080); assert_eq!( - plan_explicit_screen_area_override(&ownership, profile.screen()), + set_command, WebDriverBidiPresentationCommand::SetScreenArea { ownership: ownership.clone(), screen_area, } ); assert_eq!( - plan_explicit_screen_area_cleanup(&ownership), + reset_command, WebDriverBidiPresentationCommand::ResetScreenArea { ownership } ); } From bc3865df57ffdd6300184bbe4a8571bf6deab10d Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:03:11 +0900 Subject: [PATCH 33/35] docs(adr): remove dead planner from ownership decision --- ...13-webdriver-bidi-screen-area-ownership.md | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md index 96c2a4397..be8eb089c 100644 --- a/docs/adr/0113-webdriver-bidi-screen-area-ownership.md +++ b/docs/adr/0113-webdriver-bidi-screen-area-ownership.md @@ -12,11 +12,14 @@ ADR 0107 keeps WebDriver BiDi behind a versioned adapter and requires owned clea A second authority problem is independent of that schema gap. WebDriver BiDi stores the screen-area override against a browsing context. Setting a non-null rectangle replaces the target entry; sending `screenArea: null` removes the target entry. The standard does not restore a predecessor override. A `WebDriverBidiBrowsingContext` therefore identifies a mutation target but cannot prove that OriginWeave owns the state being replaced or cleared. +The first ownership-witness implementation retained public explicit planner functions while intentionally exposing no Browser Session witness-mint path. Exact-head CI `34419810636` made that contradiction executable: Python repository contracts, formatting, and locked workspace tests passed, but strict Clippy rejected both planners as dead production code. Exact production coverage passed separately. A callable planner API with no legal production caller is not a deferred capability; it is unreachable surface area that obscures the lifecycle boundary. + ## Decision drivers -- Preserve the useful typed WebDriver BiDi screen-area capability without granting ambient mutation authority. +- Preserve the useful typed WebDriver BiDi screen-area vocabulary without granting ambient mutation authority. - Prevent a raw browsing-context identifier from authorizing replacement or removal of another owner's override. - Keep cleanup evidence causal: ownership must exist before the destructive mutation, not be inferred from a later command acknowledgement. +- Do not suppress `dead_code` or retain unreachable public helpers merely to advertise a future capability. - Keep the reusable profile-derived planner limited to observables represented by the profile and paired with safe cleanup semantics. - Keep complete Screen admission fail-closed while available-screen geometry and color depth remain uncontrolled. @@ -36,25 +39,28 @@ A second authority problem is independent of that schema gap. WebDriver BiDi sto 2. **Delete screen-area support.** Rejected. The standard capability is useful and can be represented without granting ambient mutation authority. 3. **Capture and restore an assumed predecessor value.** Rejected. This slice has no authoritative predecessor snapshot and the standard reset semantics remove the override rather than restore one. 4. **Treat a successful Set command as ownership proof.** Rejected. The Set can already have overwritten another owner's state; acknowledgement is too late to establish authorization. -5. **Require an opaque Browser Session ownership witness before planning Set or Reset.** Selected. The witness is not caller-mintable from a context identifier and can later be produced only by the lifecycle owner after exclusive/disposable-context establishment or equivalent ownership proof. +5. **Keep public explicit planners that accept an opaque witness even though no production mint path exists.** Rejected by executable evidence. Exact-head strict Clippy identified both helpers as dead code; suppressing the warning would preserve an API that no legal caller can reach. +6. **Retain the typed command/witness vocabulary but expose no screen-area planner until Browser Session can mint the witness.** Selected. The protocol semantics remain represented, while executable authority appears only when the lifecycle owner supplies a reviewed mint transition and can consume the witness without reopening raw-context authority. ## Decision -`originweave-bidi` retains `WebDriverBidiScreenArea` and the explicit `SetScreenArea` / `ResetScreenArea` command intents, but both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership`. +`originweave-bidi` retains `WebDriverBidiScreenArea`, `WebDriverBidiScreenAreaOwnership`, and the typed `SetScreenArea` / `ResetScreenArea` command variants. Both variants carry the ownership witness rather than a raw `WebDriverBidiBrowsingContext`. + +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context and intentionally exposes no public constructor in the adapter. Its context accessor preserves the target bound to the proof. A future Browser Session integration may mint the witness only after establishing an exclusive/disposable browsing context or an equivalent lifecycle guarantee that no unrelated screen override can be replaced or removed. -`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context and intentionally exposes no public constructor in the adapter. Its public context accessor permits a transport integration that already possesses the witness to address the command without reopening validation. A future Browser Session integration may mint the witness only after establishing an exclusive/disposable browsing context or an equivalent lifecycle guarantee that no unrelated screen override can be replaced or removed. +Until that mint path exists, the adapter exposes no public explicit screen-area planner. This is deliberate fail-closed capability representation, not an incomplete helper API. When Browser Session adds the ownership transition, the planner/transport path must be introduced in the same reviewed slice so strict Clippy, repository contracts, runtime evidence, and lifecycle invalidation prove that the capability is actually reachable through the canonical owner. -This is capability representation, not runtime proof. The current adapter has no external mint path, so screen-area mutation is unavailable until Browser Session supplies the missing ownership transition. The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. +The standard reusable plan remains viewport/DPR plus timezone. Complete `PresentationSurface::Screen` remains unsupported because available-screen geometry is not represented by `ScreenMetrics` and color depth is not controlled by the standard operation. ## Consequences -The adapter preserves the standard screen-area value and explicit command vocabulary while making destructive mutation unavailable to ordinary context-aware callers. A later Browser Session integration has a narrow place to attach lifecycle proof instead of widening the browsing-context value object into authorization. +The adapter preserves the protocol vocabulary needed for a future owned integration while ordinary context-aware callers cannot plan destructive screen-area mutation. The Browser Session owner now has a narrow future integration point instead of a context-only authorization escape hatch or dead public planner. -The trade-off is deliberate: screen-area application cannot currently be materialized outside the module. Product code must remain fail-closed until the lifecycle owner supplies a reviewed witness producer. +The trade-off is deliberate: screen-area application cannot currently be materialized outside the module. Product code remains fail-closed until the lifecycle owner supplies a reviewed witness producer and a live consumer path. ## Failure and degraded behavior -If Browser Session cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, no ownership witness is available and screen-area Set/Reset cannot be planned by external callers. OriginWeave must not fall back to a raw context identifier, ambient browser state, an LLM decision, a command acknowledgement, or best-effort cleanup. +If Browser Session cannot prove an exclusive/disposable lifecycle or equivalent restoration-safe ownership, no ownership witness is available and no screen-area Set/Reset plan is exposed to external callers. OriginWeave must not fall back to a raw context identifier, ambient browser state, an LLM decision, a command acknowledgement, best-effort cleanup, or a `dead_code` suppression. The reusable profile planner continues to omit screen-area mutation. Complete presentation-profile admission continues to return `MissingSurface(Screen)` because available-screen geometry is unmodelled and color depth is uncontrolled. @@ -68,19 +74,20 @@ No identity, egress, secret, policy, approval, or Context Fabric authority moves ## Tests and acceptance evidence -The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected before acceptance: the useful protocol capability remains, but the repository contract now requires an opaque non-caller-mintable ownership type, requires both Set and Reset variants to carry it, requires both explicit planners to accept it rather than a raw context, and continues to forbid screen-area commands in the reusable profile-derived plan. +The test-first successor to #310 initially over-constrained the repair by requiring deletion of all screen-area command intents. That was corrected: the useful protocol vocabulary remains, but the repository contract requires an opaque non-caller-mintable ownership type and requires both Set and Reset variants to carry it. After executable CI exposed the dead-helper contradiction, the contract was tightened to require that no public explicit screen-area planner exists before a Browser Session mint path does. -Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. +Repository acceptance requires exact-head Python contracts, Rust formatting, locked workspace tests, strict Clippy, rustdoc/API documentation, and exact 100% owned-production function/line/region/branch coverage. The failing `34419810636` run is RED evidence, not acceptance. Browser acceptance remains separate and requires the pinned Chromium lane to prove application, page-observed post-condition, native interaction/outcome, owned cleanup or context destruction, and post-cleanup observation. Neither this ADR nor repository GREEN is browser GREEN. ## Migration and rollback -This active branch changes only the typed planner contract. Existing callers that used context-only screen-area planners must not be mechanically migrated by manufacturing a witness; they must move behind the future Browser Session lifecycle owner or remain unable to invoke the operation. +This active branch changes only the typed authority boundary. Existing callers must not be mechanically migrated by manufacturing a witness. There is intentionally no explicit public planner to call until the future Browser Session lifecycle owner creates the witness and the consuming path together. -Rollback removes ADR 0113 and the ownership-witness change together with its contract tests. It must not restore the context-only public Set/Reset authority without a separate reviewed decision, because that would reintroduce the destructive-cleanup defect. +Rollback removes ADR 0113 and the ownership-witness change together with its contract tests. It must not restore context-only public Set/Reset authority or dead planner helpers without a separate reviewed decision, because either would reintroduce the authority or reachability defect. ## Open follow-ups - Define the Browser Session aggregate transition that mints the witness only after exclusive/disposable-context establishment or equivalent ownership proof. +- Add the screen-area planner/transport consumer only in the same slice that makes the ownership witness legitimately mintable and reachable. - Bind witness invalidation to context/session destruction and any lifecycle boundary that makes the proof stale. - Bind runtime evidence to the exact ownership witness, Set command, page-observed post-condition, cleanup or context destruction, and post-cleanup observation. - Decide in a separate schema change whether `PresentationProfile` should model available-screen geometry; do not infer it from total screen size. From 35b95d929c35182913749f8348f56bd2c8ae17f4 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:03:22 +0900 Subject: [PATCH 34/35] docs(bidi): record fail-closed planner reachability --- docs/doctoring/webdriver-bidi-screen-area.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/doctoring/webdriver-bidi-screen-area.md b/docs/doctoring/webdriver-bidi-screen-area.md index a6dcdce63..27b0d1ed1 100644 --- a/docs/doctoring/webdriver-bidi-screen-area.md +++ b/docs/doctoring/webdriver-bidi-screen-area.md @@ -6,7 +6,9 @@ For one exact browsing context, `emulation.setScreenSettingsOverride` accepts `s That lifecycle matters independently of the profile schema. `ScreenMetrics(width, height, color_depth)` still does not model `screen.availWidth` or `screen.availHeight`, so the reusable profile-derived plan cannot silently apply the operation. A raw `WebDriverBidiBrowsingContext` also cannot authorize the separate explicit operation: replacing or removing the current override could mutate state installed by another owner. -OriginWeave therefore keeps `WebDriverBidiScreenArea` as the typed width/height representation but gates `SetScreenArea`, `ResetScreenArea`, and both explicit planners on an opaque `WebDriverBidiScreenAreaOwnership` witness. That witness has no public constructor in the adapter. A Browser Session integration may create it only after establishing an exclusive/disposable browsing context or an equivalent lifecycle proof that prevents replacement or removal of unrelated screen-settings state. Possession of a remote context identifier alone is not ownership evidence. +OriginWeave therefore keeps `WebDriverBidiScreenArea` and the `SetScreenArea` / `ResetScreenArea` command vocabulary behind an opaque `WebDriverBidiScreenAreaOwnership` witness. That witness has no public constructor in the adapter. A Browser Session integration may create it only after establishing an exclusive/disposable browsing context or an equivalent lifecycle proof that prevents replacement or removal of unrelated screen-settings state. Possession of a remote context identifier alone is not ownership evidence. + +The first witness implementation also retained two public explicit screen-area planner helpers even though no legal production path could mint the witness. Exact-head CI `34419810636` rejected both helpers under strict Clippy as dead code while repository contracts, formatting, workspace tests, and exact production coverage otherwise passed. OriginWeave does not suppress that finding. Until Browser Session introduces the reviewed witness-mint transition and a real consuming path, the adapter exposes no public explicit screen-area planner; the typed command vocabulary remains dormant and fail-closed. The standard operation also does **not** control color depth. `PresentationSurface::Screen` continues to fail closed with `MissingSurface(Screen)`: neither an owned screen-area command nor its command acknowledgement proves the complete Screen fingerprint surface. From 43377c2de00865d0e92126c455ca6390297c9cf7 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Thu, 10 Sep 2026 10:03:44 +0900 Subject: [PATCH 35/35] docs(trace): bind screen planner repair to executable Clippy RED --- .../webdriver-bidi-screen-area-planning.md | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/docs/traceability/webdriver-bidi-screen-area-planning.md b/docs/traceability/webdriver-bidi-screen-area-planning.md index 0a10842dd..1ccbe8ea4 100644 --- a/docs/traceability/webdriver-bidi-screen-area-planning.md +++ b/docs/traceability/webdriver-bidi-screen-area-planning.md @@ -8,6 +8,8 @@ WebDriver BiDi applies one `screenArea` rectangle to both the web-exposed total A second authority defect remains even when the operation is separated from the profile-derived plan. The standard stores one override per target browsing context. Setting a rectangle replaces that target's current override; `screenArea: null` removes the target from the override map. The standard does not restore a predecessor value. A validated browsing-context identifier therefore identifies where a mutation would occur but does not prove that OriginWeave owns the state being replaced or cleared. +A third reachability defect became executable after the ownership witness was introduced. The adapter intentionally had no production mint path for `WebDriverBidiScreenAreaOwnership` but still retained public explicit screen-area planner helpers. Exact-head CI `34419810636` ran on a GitHub-hosted Ubuntu 24.04 runner: Python repository contracts, formatting, and locked workspace tests passed; exact production coverage passed; strict Clippy failed because both explicit planner functions were dead production code. Keeping those helpers with a lint waiver would advertise executable authority that the canonical Browser Session owner cannot yet provide. + ## Constraints - Keep browser-domain truth in OriginWeave; WebDriver BiDi remains an adapter, not policy authority. @@ -16,6 +18,7 @@ A second authority defect remains even when the operation is separated from the - Do not treat a browsing-context identifier as mutation authority. - A reusable browsing context may automatically plan only observables represented by the explicit presentation contract and paired with non-destructive cleanup. - Screen-area mutation requires an exclusive/disposable Browser Session context or equivalent ownership proof before the command can be materialized. +- Do not retain dead public planner helpers or suppress strict Clippy while the ownership mint path is absent. - Do not add media-feature cleanup, ambient-host fallback, live protocol I/O, command-ACK success semantics, or Chromium-specific authority here. ## Alternatives @@ -25,14 +28,17 @@ A second authority defect remains even when the operation is separated from the 3. **Carry full `ScreenMetrics` in the command payload.** Rejected because the command would contain color depth, which the protocol operation does not apply, while still failing to name the available-screen side effect. 4. **Expose context-only explicit Set/Reset commands.** Rejected after review. A context identifier does not establish ownership; setting can replace another owner's override and resetting can erase it without restoration. 5. **Remove the standard capability entirely.** Rejected. The protocol operation is useful and can be represented safely without making it ambient authority. -6. **Keep the typed screen-area value and gate explicit mutation on an opaque Browser Session ownership witness.** Selected. The adapter retains protocol semantics while making lifecycle authority non-caller-mintable until a Browser Session owner proves an exclusive/disposable context or equivalent safe ownership transition. -7. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence and needs its own test-first change. +6. **Keep public explicit planners that accept an opaque witness before any production witness-mint path exists.** Rejected by exact-head Clippy RED. No legal production caller can reach them, so they are dead API rather than useful capability. +7. **Retain the typed screen-area value, ownership witness, and Set/Reset command vocabulary, but expose no screen-area planner until Browser Session supplies the mint transition and consumer path.** Selected. Protocol semantics remain explicit while executable authority stays with the lifecycle owner. +8. **Expand `PresentationProfile` immediately with available-screen dimensions.** Deferred. That changes the canonical fingerprint schema, replay digest, consistency rules, fixtures, and buyer evidence and needs its own test-first change. ## Decision -`originweave-bidi` retains `WebDriverBidiScreenArea` as the validated width/height projection and retains explicit `SetScreenArea` / `ResetScreenArea` command intent. Both command variants and both explicit planner functions require `WebDriverBidiScreenAreaOwnership` rather than a raw `WebDriverBidiBrowsingContext`. +`originweave-bidi` retains `WebDriverBidiScreenArea` as the validated width/height projection, retains opaque `WebDriverBidiScreenAreaOwnership`, and retains explicit `SetScreenArea` / `ResetScreenArea` command intent. Both command variants carry the ownership witness rather than a raw `WebDriverBidiBrowsingContext`. + +`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context but intentionally has no public constructor. The adapter therefore cannot mint its own proof from a context identifier. A future Browser Session integration may create the witness only after proving an exclusive/disposable lifecycle or an equivalent ownership transition. -`WebDriverBidiScreenAreaOwnership` contains the exact validated browsing context but intentionally has no public constructor. The adapter therefore cannot mint its own proof from a context identifier. A future Browser Session integration may create the witness only after proving an exclusive/disposable lifecycle or an equivalent ownership transition. Possession of the witness is the authority to plan both the apply and matching cleanup for that owned lifecycle; it is not transport acknowledgement or page-observed evidence. +There is no public explicit screen-area planner while that mint path is absent. The planner/transport consumer must be introduced together with the reviewed Browser Session ownership transition so strict Clippy and runtime evidence prove a real canonical call path. No `allow(dead_code)`/`expect(dead_code)` exception is used. The ordinary `plan_standard_presentation_commands` and `plan_standard_presentation_cleanup` remain limited to viewport/DPR and time zone. The complete capability map continues to omit `PresentationSurface::Screen`, so `require_complete_presentation_profile()` still returns `MissingSurface(Screen)` until a reviewed owner models available-screen geometry, controls color depth, and proves the runtime application/cleanup lifecycle. @@ -40,17 +46,20 @@ The ordinary `plan_standard_presentation_commands` and `plan_standard_presentati PR #310 review identified two distinct findings. The first was the unmodelled available-screen side effect, repaired by keeping screen-area mutation out of the profile-derived reusable plan. The later exact-head review identified the ownership gap: a context-only `ResetScreenArea` could remove another owner's active override because `screenArea: null` deletes the target's override-map entry rather than restoring a prior value. -The successor contract requires: +The first #311 ownership-witness implementation then exposed a third, executable finding. Run `34419810636` on exact `f1380ab8e091964ccbdd576d933cf19d696c3791` assigned hosted runners and executed repository code. `Rust contracts` job `102692565837` passed Python contracts, formatting, and the complete locked workspace tests before strict Clippy rejected `plan_explicit_screen_area_override` and `plan_explicit_screen_area_cleanup` as dead code. `Production coverage` job `102692565938` passed measurement, diagnostics publication, and exact enforcement. This is a source RED, not a queue or coverage failure. + +The successor contract therefore requires: - `WebDriverBidiScreenArea` to remain the typed width/height representation derived from validated screen metrics; - an opaque `WebDriverBidiScreenAreaOwnership` carrying the exact context with no public mint constructor in the adapter; -- `SetScreenArea`, `ResetScreenArea`, and both explicit planners to require that ownership witness rather than a raw context identifier; +- `SetScreenArea` and `ResetScreenArea` to carry that ownership witness rather than a raw context identifier; +- no public explicit screen-area planner until the Browser Session ownership mint path and consuming integration exist; - no screen-area mutation in the reusable profile-derived plan while available-screen geometry is unmodelled; - no media-feature reset; - no color-depth field in the screen-area value object; and - continued fail-closed complete Screen admission. -The initial successor RED briefly over-constrained the repair by requiring removal of all screen-area command intents. That was corrected before acceptance: deleting a useful standard capability is not necessary when its mutation authority can instead be represented explicitly and made non-caller-mintable. +The initial successor RED briefly over-constrained the repair by requiring removal of all screen-area command intents. That remains unnecessary: the typed protocol vocabulary can stay dormant without exposing a callable dead planner or widening mutation authority. Hosted exact-head repository checks, 100% owned-production coverage, security checks, central required workflows, and realistic pinned-Chromium acceptance remain separate evidence. A command intent or acknowledgement is never substituted for apply → page-observed post-condition → interaction/outcome → owned cleanup/destruction → post-cleanup observation.