Skip to content

[adr] script and logging async/event API on driver.script - #17776

Open
titusfortner wants to merge 5 commits into
SeleniumHQ:trunkfrom
titusfortner:c/bold-archimedes-8235d8
Open

[adr] script and logging async/event API on driver.script#17776
titusfortner wants to merge 5 commits into
SeleniumHQ:trunkfrom
titusfortner:c/bold-archimedes-8235d8

Conversation

@titusfortner

@titusfortner titusfortner commented Jul 13, 2026

Copy link
Copy Markdown
Member

📄 The decision, its rationale, considered options, and consequences are in the record file this
PR adds (docs/decisions/17776-bidi-script.md); read it there. The sections below are proposal
notes and review logistics.

🔗 Related

📝 Proposal notes

  • Satisfies a charter requirement. This is the ADR the Selenium 5 charter ([docs] Selenium 5 release charter #17717) names for
    the script and logging async/event API; on acceptance the charter links back to it.
  • Already agreed — this record consolidates. From the summit ([🚀 Feature]: Implement high level BiDi script commands #13992): the driver.script
    accessor; placing the log-domain console and error events under script; pin / unpin /
    execute; and separate add/remove handlers for console messages, JavaScript errors, and DOM
    mutations.
  • New or revised here — needs fresh sign-off. Beyond the agreed surface, this record departs
    in two ways; the rest of its calls fill in details [🚀 Feature]: Implement high level BiDi script commands #13992 left unspecified and are reasoned in the
    record:
    • splits preload out of pin — the summit had a single pin; this separates run-by-handle
      (pin) from run-on-every-navigation (preload). Naming both lets the record classify each
      binding's current pin as one or the other;
    • returns a registration object from add_*, not an integer id.
  • Left open on purpose. script.execute(source) overlaps the existing execute_script (and
    executeAsyncScript); whether script.execute supersedes and deprecates them is a larger
    migration decision this record does not make.
  • Implementation is unspecified. The record fixes the surface and behavior; how each binding
    stores pinned scripts, routes log.entryAdded, and keys handler removal is left to the adopting
    PRs.

🗣 Discussion

Discussed at the TLC meetings below; see the minutes for the full discussion and attribution.

  • 2026-08-06pin and preload are one
    concept, not two; console and JavaScript error handlers stay separate. Related:
    mapping events back to contexts, where
    event payloads not identifying the firing context was raised as a spec gap.
  • 2026-08-13 — event scoping expressed as a
    window handle rather than a context, since events attach to a top-level navigable.

📌 Tracking

Tracking issue: (linked on acceptance)

@qodo-code-review

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Add ADR defining the driver.script async script & event API surface

📝 Documentation 🕐 10-20 Minutes

Grey Divider

AI Description

• Add a proposed ADR standardizing the protocol-neutral driver.script surface across bindings.
• Define execute, pin, preload, and handler registration/removal for console/error/DOM
 mutations.
• Document key design choices: split pin vs preload, return registration objects, shaped
 payloads.
High-Level Assessment

The following are alternative approaches to this PR:

1. Expose console/error events under a separate `driver.log` accessor
  • ➕ Mirrors BiDi protocol domains closely
  • ➕ May feel more natural to spec-focused users
  • ➖ Splits a single workflow across script and log (scripts + DOM mutation + console/error)
  • ➖ Conflicts with existing Selenium meaning of “logs” (e.g., manage().logs())
2. Keep a single `pin` API for both run-on-demand and run-on-navigation behaviors
  • ➕ Fewer commands to learn
  • ➕ Matches some current binding implementations
  • ➖ Encourages silent divergence across bindings (same name, different semantics)
  • ➖ Makes migration and documentation less explicit
3. Return primitive integer/long ids from `add_*` handlers
  • ➕ Simplest surface area
  • ➕ Aligns with current behavior in multiple bindings
  • ➖ Limits extensibility (harder to add metadata/behavior without new APIs)
  • ➖ Pushes more handler bookkeeping details onto users

Recommendation: Proceed with the ADR’s approach: a single protocol-neutral driver.script accessor that owns script execution and related event subscriptions, with an explicit split between run-on-demand (pin) and run-on-navigation (preload) and registration objects for removals. This best reduces cross-binding semantic drift while keeping the API extensible and user-focused; the main alternatives (separate log, single pin, primitive ids) trade short-term simplicity for long-term inconsistency and migration friction.

Files changed (1) +145 / -0

Documentation (1) +145 / -0
bidi-script.mdProposed ADR for 'driver.script' script execution and event subscriptions +145/-0

Proposed ADR for 'driver.script' script execution and event subscriptions

• Adds a proposed architecture decision record defining a protocol-neutral 'driver.script' API for script execution ('execute', 'pin', 'preload') and subscriptions to console messages, JavaScript errors, and DOM mutations. Captures behavioral requirements (shaped payloads, handler exception logging) and documents considered alternatives and consequences for binding convergence.

docs/decisions/bidi-script.md

@titusfortner
titusfortner force-pushed the c/bold-archimedes-8235d8 branch from 0cca0fc to c0cfe40 Compare July 13, 2026 21:52
@qodo-code-review

qodo-code-review Bot commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Old/new values undefined 🐞 Bug ≡ Correctness ⭐ New
Description
Decision 6 requires DOM-mutation payloads to include “old and new” values for attributes and
character data, but does not define field presence/nullability when a value does not exist (e.g.,
attribute added/removed) or when an “old” value was not captured. This allows incompatible payload
shapes across bindings (null vs omitted vs sentinel).
Code

docs/decisions/17776-bidi-script.md[R104-105]

+   kind, and the fields for that kind — an attribute name with its old and new value, the old and new
+   character data, or the added and removed nodes).
Evidence
Lines 104–105 mandate old/new values for attribute and character-data mutations, but the ADR does
not define the nullability/presence rules needed to represent additions/removals or non-captured old
values consistently.

docs/decisions/17776-bidi-script.md[101-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR states mutation payloads include old/new values for attributes and character data, but it does not specify how to represent cases where one of those values is absent (e.g., attribute removal => new value does not exist) or unknown/not captured. Without a precise contract, bindings will diverge in nullability and field presence.

### Issue Context
Mutation payloads are a core part of the convergence goal; consumers need consistent semantics to interpret additions/removals/changes.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[101-105]

### Suggested resolution
Define, for each mutation kind:
- whether `old_value` / `new_value` are always present vs nullable/optional
- how to represent “does not exist” (added/removed) vs “not captured/unknown”
- whether bindings must always capture old values, or if old values are best-effort (and how that is signaled)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Mutation types contract unclear ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR says DOM-mutation handlers can observe attributes/child-list/character-data “or any
combination” but does not state whether mutation types are required or what the default is when not
provided. This can cause bindings to implement different defaults or validation behavior, breaking
portability.
Code

docs/decisions/17776-bidi-script.md[R74-75]

+   **DOM-mutation handlers select which changes to observe** — attribute, child-list,
+   character-data, or any combination.
Evidence
The ADR introduces selectable mutation kinds but provides no contract for whether selection is
required vs optional/defaulted.

docs/decisions/17776-bidi-script.md[73-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR doesn’t define the requiredness/default behavior for selecting DOM mutation types on handler registration.

## Issue Context
The text says handlers select mutation kinds “or any combination,” but it does not specify whether callers must supply at least one kind, what happens if they omit the selection, nor how empty/invalid selections are handled.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[73-75]

## Suggested change
Clarify one of the following (explicitly):
1) `types` is mandatory (must include at least one kind), and specify the error/validation behavior for empty selections; or
2) `types` is optional, and specify the common default (e.g., observe all supported kinds vs attributes-only) and how to handle an empty list/set if provided.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Mutation payload incomplete ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR supports character-data DOM mutations but the payload description only specifies
attribute/child-list oriented fields (attribute name/old+new values, added/removed nodes), leaving
the character-data payload shape undefined. This ambiguity can lead bindings to expose incompatible
fields/nullability for character-data mutations.
Code

docs/decisions/17776-bidi-script.md[R102-104]

+   source location and stack trace: console message (level, text, type, arguments, source, stack
+   trace), JavaScript error (message, source, stack trace), DOM mutation (target element, mutation
+   kind, attribute name with old and new value, added and removed nodes).
Evidence
The ADR explicitly allows observing character-data mutations, but the later payload definition
omits any character-data-specific fields and only lists attribute/child-list relevant ones.

docs/decisions/17776-bidi-script.md[74-75]
docs/decisions/17776-bidi-script.md[102-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR defines DOM-mutation handler types including `character-data`, but the payload section only describes fields that map to attributes and child-list mutations. Without specifying the payload contract for character-data (and the presence/nullability of fields that don't apply), bindings are likely to diverge.

## Issue Context
This ADR’s stated goal is cross-binding convergence on surface and behavior, including shaped event payloads.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[74-75]
- docs/decisions/17776-bidi-script.md[102-104]

## Suggested change
Update the DOM-mutation payload description to be explicit per `mutation kind` (e.g., attributes vs child-list vs character-data), including what fields exist for each kind (or which are null/omitted) and add the missing character-data details (e.g., old/new text/value fields).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Console stacktrace ambiguity ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR says console and JavaScript-error handlers are split so console subscribers “do not also
receive stack traces,” but later requires console-message payloads to include a stack trace; this
conflict can lead bindings to implement different payload shapes. Clarify whether the intent is “no
JavaScript-error stack traces in console events” vs “console messages never include any stack
trace.”
Code

docs/decisions/17776-bidi-script.md[R72-74]

+4. **Console messages and JavaScript errors are separate handlers**, even though one `log` event
+   feeds both, so a console subscriber does not also receive stack traces. **DOM-mutation handlers
+   select which changes to observe** — attribute, child-list, character-data, or any combination.
Evidence
Decision 4 states console subscribers should not receive stack traces, but Decision 6 and the
examples explicitly include/access a stack trace for console messages, creating an
implementer-facing contradiction.

docs/decisions/17776-bidi-script.md[72-74]
docs/decisions/17776-bidi-script.md[100-111]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR text conflicts on whether console-message handlers receive stack traces: Decision 4 implies console subscribers should not receive stack traces, while Decision 6 explicitly lists a stack trace in the console-message payload.

### Issue Context
This ADR is intended to drive cross-binding convergence; contradictory normative language will likely produce divergent implementations and payload types.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[72-74]
- docs/decisions/17776-bidi-script.md[100-111]

### Suggested change
Adjust Decision 4 wording to explicitly distinguish *JavaScript-error stack traces* from *console-message stack traces* (or remove `stack` from Decision 6 if console messages are not meant to carry it), and make the examples consistent with the chosen rule.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
5. Preload timing underspecified ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR states preload(source) runs “before page scripts, on the current page and every
navigation,” but does not define behavior when preload() is called after the current document’s
scripts have already run. This ambiguity can cause bindings to diverge on whether the preload runs
immediately, only on the next navigation, or requires a reload to satisfy “before page scripts.”
Code

docs/decisions/17776-bidi-script.md[R57-59]

+3. **`preload(source)` registers a script to run automatically** — before page scripts, on the
+   current page and every navigation. It returns a handle that `remove_preload` discards; a preload
+   script runs only on its own, never by handle.
Evidence
The ADR asserts both 'before page scripts' and 'on the current page' but provides no definition for
how that should work when the current page has already executed scripts, leaving a key timing case
unspecified.

docs/decisions/17776-bidi-script.md[57-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR defines `preload(source)` as running "before page scripts" on the current page, but does not specify what happens if the user registers it after the page is already loaded (when "before page scripts" is no longer possible without a reload).

### Issue Context
Because this record is meant to standardize cross-binding semantics, leaving this lifecycle edge-case undefined will likely result in inconsistent user-visible behavior.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[57-60]

### Suggested change
Add a normative statement describing the expected behavior for late registration (e.g., applies only to subsequently created documents; or executes immediately in the current document but without the "before page scripts" guarantee; or triggers a reload explicitly if that guarantee is required).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can describe a rule in plain language on the Rules page and Qodo drafts it for you

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous review results

Review updated until commit 67d8d4e

Results up to commit c0cfe40


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Console stacktrace ambiguity ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR says console and JavaScript-error handlers are split so console subscribers “do not also
receive stack traces,” but later requires console-message payloads to include a stack trace; this
conflict can lead bindings to implement different payload shapes. Clarify whether the intent is “no
JavaScript-error stack traces in console events” vs “console messages never include any stack
trace.”
Code

docs/decisions/17776-bidi-script.md[R72-74]

+4. **Console messages and JavaScript errors are separate handlers**, even though one `log` event
+   feeds both, so a console subscriber does not also receive stack traces. **DOM-mutation handlers
+   select which changes to observe** — attribute, child-list, character-data, or any combination.
Evidence
Decision 4 states console subscribers should not receive stack traces, but Decision 6 and the
examples explicitly include/access a stack trace for console messages, creating an
implementer-facing contradiction.

docs/decisions/17776-bidi-script.md[72-74]
docs/decisions/17776-bidi-script.md[100-111]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR text conflicts on whether console-message handlers receive stack traces: Decision 4 implies console subscribers should not receive stack traces, while Decision 6 explicitly lists a stack trace in the console-message payload.

### Issue Context
This ADR is intended to drive cross-binding convergence; contradictory normative language will likely produce divergent implementations and payload types.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[72-74]
- docs/decisions/17776-bidi-script.md[100-111]

### Suggested change
Adjust Decision 4 wording to explicitly distinguish *JavaScript-error stack traces* from *console-message stack traces* (or remove `stack` from Decision 6 if console messages are not meant to carry it), and make the examples consistent with the chosen rule.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Preload timing underspecified ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR states preload(source) runs “before page scripts, on the current page and every
navigation,” but does not define behavior when preload() is called after the current document’s
scripts have already run. This ambiguity can cause bindings to diverge on whether the preload runs
immediately, only on the next navigation, or requires a reload to satisfy “before page scripts.”
Code

docs/decisions/17776-bidi-script.md[R57-59]

+3. **`preload(source)` registers a script to run automatically** — before page scripts, on the
+   current page and every navigation. It returns a handle that `remove_preload` discards; a preload
+   script runs only on its own, never by handle.
Evidence
The ADR asserts both 'before page scripts' and 'on the current page' but provides no definition for
how that should work when the current page has already executed scripts, leaving a key timing case
unspecified.

docs/decisions/17776-bidi-script.md[57-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR defines `preload(source)` as running "before page scripts" on the current page, but does not specify what happens if the user registers it after the page is already loaded (when "before page scripts" is no longer possible without a reload).

### Issue Context
Because this record is meant to standardize cross-binding semantics, leaving this lifecycle edge-case undefined will likely result in inconsistent user-visible behavior.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[57-60]

### Suggested change
Add a normative statement describing the expected behavior for late registration (e.g., applies only to subsequently created documents; or executes immediately in the current document but without the "before page scripts" guarantee; or triggers a reload explicitly if that guarantee is required).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 5905691


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Mutation payload incomplete ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR supports character-data DOM mutations but the payload description only specifies
attribute/child-list oriented fields (attribute name/old+new values, added/removed nodes), leaving
the character-data payload shape undefined. This ambiguity can lead bindings to expose incompatible
fields/nullability for character-data mutations.
Code

docs/decisions/17776-bidi-script.md[R102-104]

+   source location and stack trace: console message (level, text, type, arguments, source, stack
+   trace), JavaScript error (message, source, stack trace), DOM mutation (target element, mutation
+   kind, attribute name with old and new value, added and removed nodes).
Evidence
The ADR explicitly allows observing character-data mutations, but the later payload definition
omits any character-data-specific fields and only lists attribute/child-list relevant ones.

docs/decisions/17776-bidi-script.md[74-75]
docs/decisions/17776-bidi-script.md[102-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR defines DOM-mutation handler types including `character-data`, but the payload section only describes fields that map to attributes and child-list mutations. Without specifying the payload contract for character-data (and the presence/nullability of fields that don't apply), bindings are likely to diverge.

## Issue Context
This ADR’s stated goal is cross-binding convergence on surface and behavior, including shaped event payloads.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[74-75]
- docs/decisions/17776-bidi-script.md[102-104]

## Suggested change
Update the DOM-mutation payload description to be explicit per `mutation kind` (e.g., attributes vs child-list vs character-data), including what fields exist for each kind (or which are null/omitted) and add the missing character-data details (e.g., old/new text/value fields).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Mutation types contract unclear ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR says DOM-mutation handlers can observe attributes/child-list/character-data “or any
combination” but does not state whether mutation types are required or what the default is when not
provided. This can cause bindings to implement different defaults or validation behavior, breaking
portability.
Code

docs/decisions/17776-bidi-script.md[R74-75]

+   **DOM-mutation handlers select which changes to observe** — attribute, child-list,
+   character-data, or any combination.
Evidence
The ADR introduces selectable mutation kinds but provides no contract for whether selection is
required vs optional/defaulted.

docs/decisions/17776-bidi-script.md[73-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR doesn’t define the requiredness/default behavior for selecting DOM mutation types on handler registration.

## Issue Context
The text says handlers select mutation kinds “or any combination,” but it does not specify whether callers must supply at least one kind, what happens if they omit the selection, nor how empty/invalid selections are handled.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[73-75]

## Suggested change
Clarify one of the following (explicitly):
1) `types` is mandatory (must include at least one kind), and specify the error/validation behavior for empty selections; or
2) `types` is optional, and specify the common default (e.g., observe all supported kinds vs attributes-only) and how to handle an empty list/set if provided.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread docs/decisions/17776-bidi-script.md Outdated
Comment thread docs/decisions/17776-bidi-script.md Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Architecture/Design Record (ADR) that standardizes the cross-binding, protocol-neutral driver.script surface for script execution/pinning and for console/JS-error/DOM-mutation event subscriptions, intended to guide Selenium 5 convergence work.

Changes:

  • Defines the driver.script API responsibilities and normative behavior for execute, pin/unpin, and preload/removal.
  • Specifies handler registration/removal semantics (including returning registration objects) and the expected shaped payloads for console/error/mutation events.
  • Documents current per-binding divergence and the intended convergence outcomes.

Comment thread docs/decisions/17776-bidi-script.md Outdated
Comment thread docs/decisions/17776-bidi-script.md Outdated
Comment thread docs/decisions/17776-bidi-script.md Outdated
Comment thread docs/decisions/17776-bidi-script.md Outdated
Comment thread docs/decisions/17776-bidi-script.md Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 5905691

Comment thread docs/decisions/17776-bidi-script.md Outdated
@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 309ef00

@qodo-code-review

qodo-code-review Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Realm/args ambiguity 🐞 Bug ≡ Correctness ⭐ New
Description
Decision 1 defines execute(script, *args), but Decision 8 adds an optional realm and the Java
example execute("…", worker) is indistinguishable from passing worker as the first script
argument. This underspecifies the API shape and will likely produce incompatible binding signatures
and/or incorrect execution context selection.
Code

docs/decisions/17776-bidi-script.md[R161-162]

+driver.script().addConsoleMessageHandler(tab, m -> log(m.getText()));      // tab: a window handle
+driver.script().execute("return self.location.href", worker);              // worker: a frame/worker/tab realm
Evidence
The ADR currently specifies execute(script, *args) and later adds an optional realm; the Java
example demonstrates a positional second argument for realm without defining how this is
distinguished from script arguments, making the contract ambiguous for Java-like bindings.

docs/decisions/17776-bidi-script.md[33-37]
docs/decisions/17776-bidi-script.md[150-153]
docs/decisions/17776-bidi-script.md[161-162]
docs/decisions/17776-bidi-script.md[194-196]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR introduces an optional realm for `execute`, but doesn’t specify how that realm is passed without colliding with `*args` in bindings that use positional arguments (notably Java). The Java example currently implies the realm is the second positional argument, which conflicts with the earlier `execute(script, *args)` contract.

### Issue Context
This is an ADR intended to drive convergent API design across bindings; ambiguity here will cause divergent method signatures and user confusion.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[150-154]
- docs/decisions/17776-bidi-script.md[161-162]
- docs/decisions/17776-bidi-script.md[194-196]

### What to change (one of these, explicitly stated in the ADR)
- Define a required options/config object for non-keyword-arg languages (e.g., `ExecuteOptions{ realm, args }`) and update the Java example accordingly; **or**
- Define a Java-specific overload ordering that removes ambiguity (e.g., `execute(String script, Realm realm, Object... args)`), and update examples to show realm-first (and how to pass script args simultaneously); **or**
- Reserve a distinct type/wrapper for realm so it can’t be confused with normal args, and show the invocation pattern.

Update the Java snippet so it cannot be read as passing `worker` into the script’s arguments.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Scope contradicts pin semantics ✓ Resolved 🐞 Bug ≡ Correctness
Description
Decision 2 states pin applies in “every new browsing context for the rest of the session”, but
Decision 8 says pinning is scoped to the current browsing context unless an explicit scope is
provided, so bindings may implement pin as global vs per-context with incompatible behavior.
Code

docs/decisions/17776-bidi-script.md[R46-48]

+2. **`pin(source)` registers a script the browser keeps on every future page** — run before the
+   page's own scripts on each navigation and in every new browsing context for the rest of the
+   session. It does not apply to the already-loaded page; `execute` runs things now. It returns a
Evidence
Decision 2 describes pin as applying to “every new browsing context for the rest of the session,”
while Decision 8 says pinning is scoped to a context and defaults to the current browsing context;
these cannot both be true without an additional rule specifying when a user-context/global scope is
used.

docs/decisions/17776-bidi-script.md[46-48]
docs/decisions/17776-bidi-script.md[150-155]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR conflicts on whether `pin(source)` affects only the current browsing context by default or all future browsing contexts/session-wide.

### Issue Context
- Decision 2 claims pinning runs in “every new browsing context for the rest of the session”.
- Decision 8 claims every operation (including pinning) defaults to the current browsing context and can optionally target another browsing context or a user context.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[46-48]
- docs/decisions/17776-bidi-script.md[150-155]

### Suggested direction
Explicitly define:
- What `pin` defaults to (current browsing context only).
- What scope makes it apply to *all* browsing contexts (e.g., user-context scope) and whether it applies to contexts created after registration.
- Adjust wording in Decision 2 to remove “every new browsing context” unless user-context scope is intended and explicitly stated.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Handler persistence unclear 🐞 Bug ≡ Correctness
Description
Decision 4 says add_event_handler “runs the script now” and also persists on “every future load”
unless “limited to the current context,” but the ADR never defines how a caller requests
document-only vs navigation-persistent behavior (Decision 8 only defines browsing/user context
scoping).
Code

docs/decisions/17776-bidi-script.md[R87-89]

+   specialization of, exposed for events no binding pre-defines. The handler runs the script now and,
+   unless limited to the current context, keeps it on every future load so it survives navigation;
+   `remove_event_handler` detaches the subscription and stops future loads.
Evidence
Decision 4 mentions a persistence toggle (“unless limited… keeps it on every future load”) but
provides no API mechanism to select that behavior; Decision 8 only covers browsing/user context
scoping, and the consequences section only partially clarifies removal behavior rather than
registration modes.

docs/decisions/17776-bidi-script.md[87-89]
docs/decisions/17776-bidi-script.md[150-155]
docs/decisions/17776-bidi-script.md[200-203]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR introduces two lifetimes for event handlers (immediate + persistent across future loads vs limited) but does not define the API surface or semantics for choosing the lifetime.

### Issue Context
- Decision 4 uses “unless limited to the current context” but provides no parameter/flag describing that limitation.
- Decision 8 defines *which* browsing/user context is targeted, not whether the handler persists across navigations within that context.
- Consequences later clarify removal prevents future loads but doesn’t undo already-injected observers; that still leaves registration mode undefined.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[87-89]
- docs/decisions/17776-bidi-script.md[150-155]
- docs/decisions/17776-bidi-script.md[200-203]

### Suggested direction
Add explicit contract text (and/or a named parameter) that defines:
- Default lifetime (e.g., persists across navigations in the scoped browsing context).
- How to request "current document only" behavior.
- Interaction between lifetime and browsing-context vs user-context scoping.
- Confirm whether removal is required to teardown the current document or only prevent re-installation on future loads (and align Decision 4 wording accordingly).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (1)
4. Old/new values undefined 🐞 Bug ≡ Correctness
Description
Decision 6 requires DOM-mutation payloads to include “old and new” values for attributes and
character data, but does not define field presence/nullability when a value does not exist (e.g.,
attribute added/removed) or when an “old” value was not captured. This allows incompatible payload
shapes across bindings (null vs omitted vs sentinel).
Code

docs/decisions/17776-bidi-script.md[R104-105]

+   kind, and the fields for that kind — an attribute name with its old and new value, the old and new
+   character data, or the added and removed nodes).
Evidence
Lines 104–105 mandate old/new values for attribute and character-data mutations, but the ADR does
not define the nullability/presence rules needed to represent additions/removals or non-captured old
values consistently.

docs/decisions/17776-bidi-script.md[101-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR states mutation payloads include old/new values for attributes and character data, but it does not specify how to represent cases where one of those values is absent (e.g., attribute removal => new value does not exist) or unknown/not captured. Without a precise contract, bindings will diverge in nullability and field presence.

### Issue Context
Mutation payloads are a core part of the convergence goal; consumers need consistent semantics to interpret additions/removals/changes.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[101-105]

### Suggested resolution
Define, for each mutation kind:
- whether `old_value` / `new_value` are always present vs nullable/optional
- how to represent “does not exist” (added/removed) vs “not captured/unknown”
- whether bindings must always capture old values, or if old values are best-effort (and how that is signaled)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Mutation types contract unclear ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR says DOM-mutation handlers can observe attributes/child-list/character-data “or any
combination” but does not state whether mutation types are required or what the default is when not
provided. This can cause bindings to implement different defaults or validation behavior, breaking
portability.
Code

docs/decisions/17776-bidi-script.md[R74-75]

+   **DOM-mutation handlers select which changes to observe** — attribute, child-list,
+   character-data, or any combination.
Evidence
The ADR introduces selectable mutation kinds but provides no contract for whether selection is
required vs optional/defaulted.

docs/decisions/17776-bidi-script.md[73-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR doesn’t define the requiredness/default behavior for selecting DOM mutation types on handler registration.

## Issue Context
The text says handlers select mutation kinds “or any combination,” but it does not specify whether callers must supply at least one kind, what happens if they omit the selection, nor how empty/invalid selections are handled.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[73-75]

## Suggested change
Clarify one of the following (explicitly):
1) `types` is mandatory (must include at least one kind), and specify the error/validation behavior for empty selections; or
2) `types` is optional, and specify the common default (e.g., observe all supported kinds vs attributes-only) and how to handle an empty list/set if provided.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Mutation payload incomplete ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR supports character-data DOM mutations but the payload description only specifies
attribute/child-list oriented fields (attribute name/old+new values, added/removed nodes), leaving
the character-data payload shape undefined. This ambiguity can lead bindings to expose incompatible
fields/nullability for character-data mutations.
Code

docs/decisions/17776-bidi-script.md[R102-104]

+   source location and stack trace: console message (level, text, type, arguments, source, stack
+   trace), JavaScript error (message, source, stack trace), DOM mutation (target element, mutation
+   kind, attribute name with old and new value, added and removed nodes).
Evidence
The ADR explicitly allows observing character-data mutations, but the later payload definition
omits any character-data-specific fields and only lists attribute/child-list relevant ones.

docs/decisions/17776-bidi-script.md[74-75]
docs/decisions/17776-bidi-script.md[102-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR defines DOM-mutation handler types including `character-data`, but the payload section only describes fields that map to attributes and child-list mutations. Without specifying the payload contract for character-data (and the presence/nullability of fields that don't apply), bindings are likely to diverge.

## Issue Context
This ADR’s stated goal is cross-binding convergence on surface and behavior, including shaped event payloads.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[74-75]
- docs/decisions/17776-bidi-script.md[102-104]

## Suggested change
Update the DOM-mutation payload description to be explicit per `mutation kind` (e.g., attributes vs child-list vs character-data), including what fields exist for each kind (or which are null/omitted) and add the missing character-data details (e.g., old/new text/value fields).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Console stacktrace ambiguity ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR says console and JavaScript-error handlers are split so console subscribers “do not also
receive stack traces,” but later requires console-message payloads to include a stack trace; this
conflict can lead bindings to implement different payload shapes. Clarify whether the intent is “no
JavaScript-error stack traces in console events” vs “console messages never include any stack
trace.”
Code

docs/decisions/17776-bidi-script.md[R72-74]

+4. **Console messages and JavaScript errors are separate handlers**, even though one `log` event
+   feeds both, so a console subscriber does not also receive stack traces. **DOM-mutation handlers
+   select which changes to observe** — attribute, child-list, character-data, or any combination.
Evidence
Decision 4 states console subscribers should not receive stack traces, but Decision 6 and the
examples explicitly include/access a stack trace for console messages, creating an
implementer-facing contradiction.

docs/decisions/17776-bidi-script.md[72-74]
docs/decisions/17776-bidi-script.md[100-111]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR text conflicts on whether console-message handlers receive stack traces: Decision 4 implies console subscribers should not receive stack traces, while Decision 6 explicitly lists a stack trace in the console-message payload.

### Issue Context
This ADR is intended to drive cross-binding convergence; contradictory normative language will likely produce divergent implementations and payload types.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[72-74]
- docs/decisions/17776-bidi-script.md[100-111]

### Suggested change
Adjust Decision 4 wording to explicitly distinguish *JavaScript-error stack traces* from *console-message stack traces* (or remove `stack` from Decision 6 if console messages are not meant to carry it), and make the examples consistent with the chosen rule.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
8. Preload timing underspecified ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR states preload(source) runs “before page scripts, on the current page and every
navigation,” but does not define behavior when preload() is called after the current document’s
scripts have already run. This ambiguity can cause bindings to diverge on whether the preload runs
immediately, only on the next navigation, or requires a reload to satisfy “before page scripts.”
Code

docs/decisions/17776-bidi-script.md[R57-59]

+3. **`preload(source)` registers a script to run automatically** — before page scripts, on the
+   current page and every navigation. It returns a handle that `remove_preload` discards; a preload
+   script runs only on its own, never by handle.
Evidence
The ADR asserts both 'before page scripts' and 'on the current page' but provides no definition for
how that should work when the current page has already executed scripts, leaving a key timing case
unspecified.

docs/decisions/17776-bidi-script.md[57-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR defines `preload(source)` as running "before page scripts" on the current page, but does not specify what happens if the user registers it after the page is already loaded (when "before page scripts" is no longer possible without a reload).

### Issue Context
Because this record is meant to standardize cross-binding semantics, leaving this lifecycle edge-case undefined will likely result in inconsistent user-visible behavior.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[57-60]

### Suggested change
Add a normative statement describing the expected behavior for late registration (e.g., applies only to subsequently created documents; or executes immediately in the current document but without the "before page scripts" guarantee; or triggers a reload explicitly if that guarantee is required).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can describe a rule in plain language on the Rules page and Qodo drafts it for you

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous review results

Review updated until commit 67d8d4e ⚖️ Balanced

Results up to commit c0cfe40


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Console stacktrace ambiguity ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR says console and JavaScript-error handlers are split so console subscribers “do not also
receive stack traces,” but later requires console-message payloads to include a stack trace; this
conflict can lead bindings to implement different payload shapes. Clarify whether the intent is “no
JavaScript-error stack traces in console events” vs “console messages never include any stack
trace.”
Code

docs/decisions/17776-bidi-script.md[R72-74]

+4. **Console messages and JavaScript errors are separate handlers**, even though one `log` event
+   feeds both, so a console subscriber does not also receive stack traces. **DOM-mutation handlers
+   select which changes to observe** — attribute, child-list, character-data, or any combination.
Evidence
Decision 4 states console subscribers should not receive stack traces, but Decision 6 and the
examples explicitly include/access a stack trace for console messages, creating an
implementer-facing contradiction.

docs/decisions/17776-bidi-script.md[72-74]
docs/decisions/17776-bidi-script.md[100-111]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR text conflicts on whether console-message handlers receive stack traces: Decision 4 implies console subscribers should not receive stack traces, while Decision 6 explicitly lists a stack trace in the console-message payload.

### Issue Context
This ADR is intended to drive cross-binding convergence; contradictory normative language will likely produce divergent implementations and payload types.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[72-74]
- docs/decisions/17776-bidi-script.md[100-111]

### Suggested change
Adjust Decision 4 wording to explicitly distinguish *JavaScript-error stack traces* from *console-message stack traces* (or remove `stack` from Decision 6 if console messages are not meant to carry it), and make the examples consistent with the chosen rule.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Preload timing underspecified ✓ Resolved 🐞 Bug ⚙ Maintainability
Description
The ADR states preload(source) runs “before page scripts, on the current page and every
navigation,” but does not define behavior when preload() is called after the current document’s
scripts have already run. This ambiguity can cause bindings to diverge on whether the preload runs
immediately, only on the next navigation, or requires a reload to satisfy “before page scripts.”
Code

docs/decisions/17776-bidi-script.md[R57-59]

+3. **`preload(source)` registers a script to run automatically** — before page scripts, on the
+   current page and every navigation. It returns a handle that `remove_preload` discards; a preload
+   script runs only on its own, never by handle.
Evidence
The ADR asserts both 'before page scripts' and 'on the current page' but provides no definition for
how that should work when the current page has already executed scripts, leaving a key timing case
unspecified.

docs/decisions/17776-bidi-script.md[57-60]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR defines `preload(source)` as running "before page scripts" on the current page, but does not specify what happens if the user registers it after the page is already loaded (when "before page scripts" is no longer possible without a reload).

### Issue Context
Because this record is meant to standardize cross-binding semantics, leaving this lifecycle edge-case undefined will likely result in inconsistent user-visible behavior.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[57-60]

### Suggested change
Add a normative statement describing the expected behavior for late registration (e.g., applies only to subsequently created documents; or executes immediately in the current document but without the "before page scripts" guarantee; or triggers a reload explicitly if that guarantee is required).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 5905691


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Remediation recommended
1. Mutation types contract unclear ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR says DOM-mutation handlers can observe attributes/child-list/character-data “or any
combination” but does not state whether mutation types are required or what the default is when not
provided. This can cause bindings to implement different defaults or validation behavior, breaking
portability.
Code

docs/decisions/17776-bidi-script.md[R74-75]

+   **DOM-mutation handlers select which changes to observe** — attribute, child-list,
+   character-data, or any combination.
Evidence
The ADR introduces selectable mutation kinds but provides no contract for whether selection is
required vs optional/defaulted.

docs/decisions/17776-bidi-script.md[73-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR doesn’t define the requiredness/default behavior for selecting DOM mutation types on handler registration.

## Issue Context
The text says handlers select mutation kinds “or any combination,” but it does not specify whether callers must supply at least one kind, what happens if they omit the selection, nor how empty/invalid selections are handled.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[73-75]

## Suggested change
Clarify one of the following (explicitly):
1) `types` is mandatory (must include at least one kind), and specify the error/validation behavior for empty selections; or
2) `types` is optional, and specify the common default (e.g., observe all supported kinds vs attributes-only) and how to handle an empty list/set if provided.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Mutation payload incomplete ✓ Resolved 🐞 Bug ≡ Correctness
Description
The ADR supports character-data DOM mutations but the payload description only specifies
attribute/child-list oriented fields (attribute name/old+new values, added/removed nodes), leaving
the character-data payload shape undefined. This ambiguity can lead bindings to expose incompatible
fields/nullability for character-data mutations.
Code

docs/decisions/17776-bidi-script.md[R102-104]

+   source location and stack trace: console message (level, text, type, arguments, source, stack
+   trace), JavaScript error (message, source, stack trace), DOM mutation (target element, mutation
+   kind, attribute name with old and new value, added and removed nodes).
Evidence
The ADR explicitly allows observing character-data mutations, but the later payload definition
omits any character-data-specific fields and only lists attribute/child-list relevant ones.

docs/decisions/17776-bidi-script.md[74-75]
docs/decisions/17776-bidi-script.md[102-104]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The ADR defines DOM-mutation handler types including `character-data`, but the payload section only describes fields that map to attributes and child-list mutations. Without specifying the payload contract for character-data (and the presence/nullability of fields that don't apply), bindings are likely to diverge.

## Issue Context
This ADR’s stated goal is cross-binding convergence on surface and behavior, including shaped event payloads.

## Fix Focus Areas
- docs/decisions/17776-bidi-script.md[74-75]
- docs/decisions/17776-bidi-script.md[102-104]

## Suggested change
Update the DOM-mutation payload description to be explicit per `mutation kind` (e.g., attributes vs child-list vs character-data), including what fields exist for each kind (or which are null/omitted) and add the missing character-data details (e.g., old/new text/value fields).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 309ef00


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Old/new values undefined 🐞 Bug ≡ Correctness
Description
Decision 6 requires DOM-mutation payloads to include “old and new” values for attributes and
character data, but does not define field presence/nullability when a value does not exist (e.g.,
attribute added/removed) or when an “old” value was not captured. This allows incompatible payload
shapes across bindings (null vs omitted vs sentinel).
Code

docs/decisions/17776-bidi-script.md[R104-105]

+   kind, and the fields for that kind — an attribute name with its old and new value, the old and new
+   character data, or the added and removed nodes).
Evidence
Lines 104–105 mandate old/new values for attribute and character-data mutations, but the ADR does
not define the nullability/presence rules needed to represent additions/removals or non-captured old
values consistently.

docs/decisions/17776-bidi-script.md[101-105]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR states mutation payloads include old/new values for attributes and character data, but it does not specify how to represent cases where one of those values is absent (e.g., attribute removal => new value does not exist) or unknown/not captured. Without a precise contract, bindings will diverge in nullability and field presence.

### Issue Context
Mutation payloads are a core part of the convergence goal; consumers need consistent semantics to interpret additions/removals/changes.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[101-105]

### Suggested resolution
Define, for each mutation kind:
- whether `old_value` / `new_value` are always present vs nullable/optional
- how to represent “does not exist” (added/removed) vs “not captured/unknown”
- whether bindings must always capture old values, or if old values are best-effort (and how that is signaled)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Results up to commit 7437fd9 ⚖️ Balanced


🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Handler persistence unclear 🐞 Bug ≡ Correctness
Description
Decision 4 says add_event_handler “runs the script now” and also persists on “every future load”
unless “limited to the current context,” but the ADR never defines how a caller requests
document-only vs navigation-persistent behavior (Decision 8 only defines browsing/user context
scoping).
Code

docs/decisions/17776-bidi-script.md[R87-89]

+   specialization of, exposed for events no binding pre-defines. The handler runs the script now and,
+   unless limited to the current context, keeps it on every future load so it survives navigation;
+   `remove_event_handler` detaches the subscription and stops future loads.
Evidence
Decision 4 mentions a persistence toggle (“unless limited… keeps it on every future load”) but
provides no API mechanism to select that behavior; Decision 8 only covers browsing/user context
scoping, and the consequences section only partially clarifies removal behavior rather than
registration modes.

docs/decisions/17776-bidi-script.md[87-89]
docs/decisions/17776-bidi-script.md[150-155]
docs/decisions/17776-bidi-script.md[200-203]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR introduces two lifetimes for event handlers (immediate + persistent across future loads vs limited) but does not define the API surface or semantics for choosing the lifetime.

### Issue Context
- Decision 4 uses “unless limited to the current context” but provides no parameter/flag describing that limitation.
- Decision 8 defines *which* browsing/user context is targeted, not whether the handler persists across navigations within that context.
- Consequences later clarify removal prevents future loads but doesn’t undo already-injected observers; that still leaves registration mode undefined.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[87-89]
- docs/decisions/17776-bidi-script.md[150-155]
- docs/decisions/17776-bidi-script.md[200-203]

### Suggested direction
Add explicit contract text (and/or a named parameter) that defines:
- Default lifetime (e.g., persists across navigations in the scoped browsing context).
- How to request "current document only" behavior.
- Interaction between lifetime and browsing-context vs user-context scoping.
- Confirm whether removal is required to teardown the current document or only prevent re-installation on future loads (and align Decision 4 wording accordingly).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Scope contradicts pin semantics ✓ Resolved 🐞 Bug ≡ Correctness
Description
Decision 2 states pin applies in “every new browsing context for the rest of the session”, but
Decision 8 says pinning is scoped to the current browsing context unless an explicit scope is
provided, so bindings may implement pin as global vs per-context with incompatible behavior.
Code

docs/decisions/17776-bidi-script.md[R46-48]

+2. **`pin(source)` registers a script the browser keeps on every future page** — run before the
+   page's own scripts on each navigation and in every new browsing context for the rest of the
+   session. It does not apply to the already-loaded page; `execute` runs things now. It returns a
Evidence
Decision 2 describes pin as applying to “every new browsing context for the rest of the session,”
while Decision 8 says pinning is scoped to a context and defaults to the current browsing context;
these cannot both be true without an additional rule specifying when a user-context/global scope is
used.

docs/decisions/17776-bidi-script.md[46-48]
docs/decisions/17776-bidi-script.md[150-155]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The ADR conflicts on whether `pin(source)` affects only the current browsing context by default or all future browsing contexts/session-wide.

### Issue Context
- Decision 2 claims pinning runs in “every new browsing context for the rest of the session”.
- Decision 8 claims every operation (including pinning) defaults to the current browsing context and can optionally target another browsing context or a user context.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[46-48]
- docs/decisions/17776-bidi-script.md[150-155]

### Suggested direction
Explicitly define:
- What `pin` defaults to (current browsing context only).
- What scope makes it apply to *all* browsing contexts (e.g., user-context scope) and whether it applies to contexts created after registration.
- Adjust wording in Decision 2 to remove “every new browsing context” unless user-context scope is intended and explicitly stated.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

Comment thread docs/decisions/17776-bidi-script.md
Comment on lines +87 to +89
specialization of, exposed for events no binding pre-defines. The handler runs the script now and,
unless limited to the current context, keeps it on every future load so it survives navigation;
`remove_event_handler` detaches the subscription and stops future loads.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Handler persistence unclear 🐞 Bug ≡ Correctness

Decision 4 says add_event_handler “runs the script now” and also persists on “every future load”
unless “limited to the current context,” but the ADR never defines how a caller requests
document-only vs navigation-persistent behavior (Decision 8 only defines browsing/user context
scoping).
Agent Prompt
### Issue description
The ADR introduces two lifetimes for event handlers (immediate + persistent across future loads vs limited) but does not define the API surface or semantics for choosing the lifetime.

### Issue Context
- Decision 4 uses “unless limited to the current context” but provides no parameter/flag describing that limitation.
- Decision 8 defines *which* browsing/user context is targeted, not whether the handler persists across navigations within that context.
- Consequences later clarify removal prevents future loads but doesn’t undo already-injected observers; that still leaves registration mode undefined.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[87-89]
- docs/decisions/17776-bidi-script.md[150-155]
- docs/decisions/17776-bidi-script.md[200-203]

### Suggested direction
Add explicit contract text (and/or a named parameter) that defines:
- Default lifetime (e.g., persists across navigations in the scoped browsing context).
- How to request "current document only" behavior.
- Interaction between lifetime and browsing-context vs user-context scoping.
- Confirm whether removal is required to teardown the current document or only prevent re-installation on future loads (and align Decision 4 wording accordingly).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +161 to +162
driver.script().addConsoleMessageHandler(tab, m -> log(m.getText())); // tab: a window handle
driver.script().execute("return self.location.href", worker); // worker: a frame/worker/tab realm

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Realm/args ambiguity 🐞 Bug ≡ Correctness

Decision 1 defines execute(script, *args), but Decision 8 adds an optional realm and the Java
example execute("…", worker) is indistinguishable from passing worker as the first script
argument. This underspecifies the API shape and will likely produce incompatible binding signatures
and/or incorrect execution context selection.
Agent Prompt
### Issue description
The ADR introduces an optional realm for `execute`, but doesn’t specify how that realm is passed without colliding with `*args` in bindings that use positional arguments (notably Java). The Java example currently implies the realm is the second positional argument, which conflicts with the earlier `execute(script, *args)` contract.

### Issue Context
This is an ADR intended to drive convergent API design across bindings; ambiguity here will cause divergent method signatures and user confusion.

### Fix Focus Areas
- docs/decisions/17776-bidi-script.md[150-154]
- docs/decisions/17776-bidi-script.md[161-162]
- docs/decisions/17776-bidi-script.md[194-196]

### What to change (one of these, explicitly stated in the ADR)
- Define a required options/config object for non-keyword-arg languages (e.g., `ExecuteOptions{ realm, args }`) and update the Java example accordingly; **or**
- Define a Java-specific overload ordering that removes ambiguity (e.g., `execute(String script, Realm realm, Object... args)`), and update examples to show realm-first (and how to pass script args simultaneously); **or**
- Reserve a distinct type/wrapper for realm so it can’t be confused with normal args, and show the invocation pattern.

Update the Java snippet so it cannot be read as passing `worker` into the script’s arguments.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be clarified as well.

@qodo-code-review

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit 67d8d4e

driver.script().execute("return document.title");
```

2. **`pin(source)` registers a script the browser keeps on every future page** — run before the

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if a user wants to pin a script only for the current browser context? Is that a scenario we should consider?

Comment on lines +161 to +162
driver.script().addConsoleMessageHandler(tab, m -> log(m.getText())); // tab: a window handle
driver.script().execute("return self.location.href", worker); // worker: a frame/worker/tab realm

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be clarified as well.


**Scoping**

8. **Events attach to a window handle; `execute` runs in a realm.** A handler defaults to the current

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we add pin to this scoping? Would this allow a user to better scope the scripts they pin in case they need that?

Comment on lines +192 to +193
- `execute` overlaps the existing `execute_script`; whether it supersedes that method is a separate
migration decision, not settled here.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't this just be applying the deprecation policy to execute_script?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants