Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ The organization currently documents a **solo-maintainer** governance condition.
- Keep Blink, V8, Skia, Viz, Dawn, Chromium sandboxing, Site Isolation, and Manifest V3 compatibility upstream-aligned.
- Map browser presentation capabilities only when the protocol proves the complete canonical surface: width and height do not prove screen color depth, and one locale does not prove ordered languages.
- Keep browser command planning distinct from execution evidence: a typed command intent bound to a validated context has not been sent, acknowledged, or observed by a page.
- A reusable presentation planner must accept only the explicitly restorable fields, never a complete `PresentationProfile` whose omitted surfaces could be mistaken for applied.
- Marking a draft Ready can enqueue a new exact-head run; do not merge from an earlier green result until that new run is terminal and re-fetched.
- Do not assume browser/session teardown removed presentation overrides; model explicit cleanup for every override a presentation plan emits and require post-cleanup observation before reusing a browser boundary.
- Pin protocol provenance to the immutable dated W3C TR URI; a mutable latest page or lagging index must not silently redefine the capability contract.
- New product logic belongs in Rust control-plane modules behind narrow adapters.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +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.
- 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
Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ Additional constraints:
- Do not merge logical origin, destination authorization, direct TCP peer proof, TLS service identity, proxy routing, or HTTP resource policy into one ambient authority.
- Do not add hostname reconnect, proxy-environment inheritance, dangerous certificate-verifier hooks, Common Name fallback, TLS 0-RTT, key logging, or secret extraction to a production TLS path.
- Keep changes bounded to one product gap and preserve modular crate boundaries.
- For partial browser-emulation plans, require only the named restorable fields; do not accept a complete profile unless every requested surface has an explicit application witness.
- A Ready transition can replace an earlier green with a queued exact-head run; wait for its terminal result before merge.
- Never claim a test, benchmark, browser integration, TLS identity, GPU execution, release, or merge succeeded without current exact-head evidence.
52 changes: 30 additions & 22 deletions crates/originweave-bidi/src/presentation_capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::{error::Error, fmt};

use originweave_fingerprint::{
PresentationError, PresentationProfile, PresentationSurface, require_presentation_surfaces,
DevicePixelRatio, PresentationError, PresentationSurface, PresentationTimeZone, ViewportBounds,
require_presentation_surfaces,
};

const MAX_BROWSING_CONTEXT_BYTES: usize = 256;
Expand Down Expand Up @@ -48,25 +49,25 @@ 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.
#[derive(Debug, Clone, PartialEq)]
/// 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.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum WebDriverBidiPresentationCommand {
/// Set viewport dimensions and device-pixel ratio together.
SetViewport {
/// Exact target browsing context.
context: WebDriverBidiBrowsingContext,
/// CSS-pixel viewport width.
width: u32,
/// CSS-pixel viewport height.
height: u32,
/// Positive device-pixel ratio.
device_pixel_ratio: f64,
/// Validated viewport bounds from the presentation-identity kernel.
viewport: ViewportBounds,
/// Validated quantized device-pixel ratio from the presentation-identity kernel.
device_pixel_ratio: DevicePixelRatio,
},
/// Set the named time zone.
SetTimezone {
/// Exact target browsing context.
context: WebDriverBidiBrowsingContext,
/// IANA time-zone identifier.
timezone: String,
/// Validated presentation time-zone identity.
timezone: PresentationTimeZone,
},
/// Set the reduced-motion media feature.
///
Expand Down Expand Up @@ -96,23 +97,26 @@ pub enum WebDriverBidiPresentationCommand {
/// pinned Working Draft. Reduced motion remains an expressible protocol capability, but the default
/// reusable plan does not install it because `features: null` clears the complete media-feature
/// configuration rather than restoring only OriginWeave's prior `prefers-reduced-motion` value.
/// A Browser Session owner must first bind media mutation to a genuinely disposable lifecycle or a
/// complete snapshot/restore path before constructing and sending `SetReducedMotion`.
/// The explicit arguments make this a partial-plan API: it cannot be mistaken for application of
/// a complete [`originweave_fingerprint::PresentationProfile`]. A Browser Session owner must first
/// bind media mutation to a genuinely disposable lifecycle or a complete snapshot/restore path
/// before constructing and sending `SetReducedMotion`.
#[must_use]
pub fn plan_standard_presentation_commands(
context: &WebDriverBidiBrowsingContext,
profile: &PresentationProfile,
viewport: &ViewportBounds,
device_pixel_ratio: DevicePixelRatio,
timezone: PresentationTimeZone,
) -> [WebDriverBidiPresentationCommand; 2] {
[
WebDriverBidiPresentationCommand::SetViewport {
context: context.clone(),
width: profile.viewport().width(),
height: profile.viewport().height(),
device_pixel_ratio: profile.device_pixel_ratio().value(),
viewport: *viewport,
device_pixel_ratio,
},
WebDriverBidiPresentationCommand::SetTimezone {
context: context.clone(),
timezone: profile.timezone().iana_name().to_owned(),
timezone,
},
]
}
Expand Down Expand Up @@ -246,17 +250,21 @@ mod tests {
assert_eq!(context.as_str(), "context-17");

assert_eq!(
plan_standard_presentation_commands(&context, &profile),
plan_standard_presentation_commands(
&context,
profile.viewport(),
profile.device_pixel_ratio(),
profile.timezone(),
),
[
WebDriverBidiPresentationCommand::SetViewport {
context: context.clone(),
width: 1440,
height: 900,
device_pixel_ratio: 2.0,
viewport: *profile.viewport(),
device_pixel_ratio: profile.device_pixel_ratio(),
},
WebDriverBidiPresentationCommand::SetTimezone {
context: context.clone(),
timezone: "UTC".to_owned(),
timezone: profile.timezone(),
},
]
);
Expand Down
6 changes: 6 additions & 0 deletions docs/product-technical-gap-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

This is a dated delivery baseline, not a substitute for the PRD, TRD, roadmap, architecture decisions, or live GitHub state. It keeps buyer-visible gaps, current issues, active pull-request evidence, and commercial completion tracks in one discoverable place. Protected `main` is the implementation boundary: code in an open pull request is not shipped behavior.

## Live continuity note: 2026-09-09

- Protected `main` was re-fetched at `87c4daa1830bac5a5228b6036752ad5633232085`. Issue #292 remains open; its buyer-visible acceptance is still pinned Chromium application followed by page-observed and post-cleanup evidence.
- Draft #293 (`476a8e09aa1aa7ab2e87cf7452a8ecfca47bf9c1`) is only the versioned standard-BiDi capability boundary. Its reusable command API previously accepted a complete profile despite planning only viewport/DPR and timezone. The active successor makes that partiality explicit at the type boundary; it is not Chromium runtime evidence or protected-main behavior.
- The next executable owner path remains the existing pinned-Chrome Agent Task lane, not a second browser runner: apply admitted overrides before navigation, read the controlled fixture's declared observations through bounded DOM endpoints, then prove explicit reset or owned-boundary destruction. Command acknowledgement and session teardown alone remain non-passing.

## Observed snapshot: 2026-08-26

### Protected-main truth
Expand Down
31 changes: 31 additions & 0 deletions tests/test_webdriver_bidi_presentation_adapter_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,37 @@ def test_reusable_apply_and_cleanup_do_not_mutate_unrestorable_media_state(self)
)[0]
self.assertNotIn("ResetMediaFeatures", standard_cleanup)

def test_reusable_plan_cannot_be_mistaken_for_complete_profile_application(self) -> None:
"""The reusable planner must require the explicitly admitted fields only."""

source = ROOT / "crates/originweave-bidi/src/presentation_capabilities.rs"
text = source.read_text(encoding="utf-8")
standard_apply = text.split("pub fn plan_standard_presentation_commands", maxsplit=1)[1]
standard_apply = standard_apply.split(") ->", maxsplit=1)[0]

self.assertNotIn("profile: &PresentationProfile", standard_apply)
self.assertIn("viewport: &ViewportBounds", standard_apply)
self.assertIn("device_pixel_ratio: DevicePixelRatio", standard_apply)
self.assertIn("timezone: PresentationTimeZone", standard_apply)

def test_public_command_intents_carry_validated_presentation_value_objects(self) -> None:
"""Public command construction must not reopen validation already owned by the kernel."""

source = ROOT / "crates/originweave-bidi/src/presentation_capabilities.rs"
text = source.read_text(encoding="utf-8")
command_enum = text.split("pub enum WebDriverBidiPresentationCommand", maxsplit=1)[1]
command_enum = command_enum.split(
"pub fn plan_standard_presentation_commands", maxsplit=1
)[0]

self.assertIn("viewport: ViewportBounds", command_enum)
self.assertIn("device_pixel_ratio: DevicePixelRatio", command_enum)
self.assertIn("timezone: PresentationTimeZone", command_enum)
self.assertNotIn("width: u32", command_enum)
self.assertNotIn("height: u32", command_enum)
self.assertNotIn("device_pixel_ratio: f64", command_enum)
self.assertNotIn("timezone: String", command_enum)


if __name__ == "__main__":
unittest.main()