[adr] Behavioral contract for the low-level WebDriver BiDi layer#17786
[adr] Behavioral contract for the low-level WebDriver BiDi layer#17786titusfortner wants to merge 7 commits into
Conversation
PR Summary by QodoAdd ADR defining behavioral contract for low-level WebDriver BiDi layer
AI Description
Diagram
High-Level Assessment
Files changed (1)
|
Code Review by Qodo
1.
|
|
Code review by qodo was updated up to the latest commit 98e1858 |
There was a problem hiding this comment.
Pull request overview
Adds a new ADR to the cross-binding decision log that defines a behavioral contract for Selenium’s internal, low-level WebDriver BiDi protocol layer (validation, extensibility, parsing strictness, and surface shape), intended to keep binding implementations aligned on wire-observable behavior.
Changes:
- Introduces a decision record enumerating required outbound/inbound behaviors for the BiDi low-level layer.
- Defines a two-tier taxonomy (Compliance vs Decision) to separate spec-forced requirements from Selenium-standardized choices.
- Records rationale, alternatives, and consequences to support consistent adoption across bindings.
|
Code review by qodo was updated up to the latest commit dfe1c07 |
|
Code review by qodo was updated up to the latest commit 5b77f31 |
|
Code review by qodo was updated up to the latest commit e965829 |
|
Code review by qodo was updated up to the latest commit 1b0e91a |
…uire only that malformed input raises
Code Review by Qodo
1. Undefined error-code surfacing
|
| misrepresenting the response, and it is cheaper to loosen a strict contract than to tighten a lenient | ||
| one. When a real remote end is seen sending off-spec data, the specific field or command is relaxed | ||
| through a documented, reversible change (citing the offending implementation and the spec issue), | ||
| applied to every binding at once — never one alone, and never by starting lenient. One exception is |
There was a problem hiding this comment.
1. Undefined error-code surfacing 🐞 Bug ⚙ Maintainability
Item 9 requires unknown ErrorResponse enum tokens to be “surfaced, not thrown” but does not define the minimum observable semantics (e.g., raw-token preservation and how callers access it), which can lead to divergent binding behavior despite the ADR’s stated goal of uniform wire-observable behavior.
Agent Prompt
### Issue description
Item 9 says an unknown `ErrorResponse` error-code token must be “surfaced, not thrown”, but that leaves implementers room to diverge on what is required (whether the raw token is preserved verbatim, and what shape it takes when exposed to callers).
### Issue Context
This ADR is explicitly intended to prevent cross-binding drift on wire-observable behavior; underspecified requirements defeat that goal.
### Fix Focus Areas
- docs/decisions/17786-bidi-low-level-behavioral-contract.md[122-130]
### Suggested change (one possible wording)
Amend item 9 to define the binding-neutral minimum:
- parsing must not throw on unknown `ErrorResponse` code tokens
- the exact raw wire token must be preserved verbatim
- callers must be able to retrieve that raw token (via an idiomatic “unknown/other” representation)
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
|
||
| - The contract holds for any implementation regardless of language or production method; conformance is | ||
| checkable independently of how the layer was built. | ||
| - The per-type signals items 5/6/8 need are all derivable from the spec; a binding that discards one, or |
There was a problem hiding this comment.
2. Broken consequences sentence 🐞 Bug ⚙ Maintainability
The final Consequences bullet ends with an ungrammatical fragment (“the items that signal feeds”), which reduces clarity for future readers quoting or implementing the summary.
Agent Prompt
### Issue description
The last sentence in Consequences is grammatically incorrect (“the items that signal feeds”), making the summary unclear.
### Issue Context
This is the concluding summary statement and is likely to be quoted in reviews.
### Fix Focus Areas
- docs/decisions/17786-bidi-low-level-behavioral-contract.md[189-190]
### Suggested change
Rewrite to something like:
- “...falls out of conformance on exactly the items those signals feed.”
or
- “...falls out of conformance on exactly items 5, 6, or 8.”
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
📄 The decision, its rationale, considered options, and consequences are in the record file
this PR adds; read it there. The sections below are proposal notes and review logistics.
🔗 Related
binding-neutral schema ([js] Add binding-neutral BiDi schema with cddl2ts-gated fidelity #17700).
📝 Proposal notes
and drifts on wire-observable behavior without a shared contract. This record fixes that behavior
once, so every binding is held to the same bar and a review can cite one place instead of re-deciding.
(generation is one way to satisfy the contract, not a requirement), the checked-in-vs-build-time
generation choice, and per-binding adoption. The record fixes behavior only.
Decisions this record owns — a strict, typed, validated design the spec permits but does not compel, so
review should focus there. Exactly one Decision turns on the internal-implementation premise: scoping
preserved extras tightly (item 8), affordable because an internal layer can widen later at no cost. The
rest — local outbound validation (3), strict-by-default inbound with reactive cross-binding relaxation
(6, 9), extensibility off the spec's per-type signal (4), typed and read-only objects (11, 12),
spec-mirroring names (10) — stand on their own merits, not on the premise.
📊 Conformance snapshot (point-in-time)
Measured against seven existing implementations of this layer. Columns — independent:
net,wdio.Selenium on trunk:
rb(generated, merged in #17731),py trunk,.NET(hand-written). In-flight PRs:py 17761(#17761),java 17777(#17777). A snapshot only — it changesas bindings converge, and moves to the tracking issue on acceptance.
Legend: ✅ meets it · ❌ does not (includes partial) · ①–② diverges by a deliberate design choice
(numbered below), not a defect.
net = webdriverbidi-net · wdio = WebdriverIO
① Lenient inbound parsing (wdio). WebdriverIO tolerates off-spec responses rather than raising —
reasonable for a public library facing a churning spec. This record raises instead, on merit rather than
because it is internal: a clear error beats silently misrepresenting the response. Note that net, also
public, is strict here (✅ on 5, 6, 9) — so strictness is a design choice, not a public-vs-internal one.
② Broad extras handling (net, wdio). Both public implementations keep unknown fields broadly, so they
never silently drop a vendor field a user relies on — the right call for a surface that can't narrow
later. This record scopes tightly because the layer is internal and can widen later at no cost. This is
the one decision that actually turns on internal-vs-public. (net stores extras broadly; wdio doesn't
build a store at all — same root, different degree.)
How to read it
🗣 Discussion
Notes from Slack and TLC minutes are recorded here as the proposal is discussed.
📌 Tracking
Tracking issue: (linked on acceptance)