docs(environment): document the browser start time, its fallback lag and older readers

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Edgar ArakelyanandClaude Opus 5.5 committed 2026-10-23 23:57:41 -07:00
1 parent 8c63c17b93
commit b92a11b6d8
4 files changed
+50 -36

No files matched your search

+3 -2
View File
@@ -125,8 +125,9 @@ the replayed body is the bytes the browser exposes for each response, with any
declared secret replaced by its redaction marker (a body that redaction had to
empty replays no body).
Each record takes its start time from when the scenario observed the request
and its duration from the browser's timing, so the state orders and overlaps
Each record takes its start and duration from the browser's timing (the time
the scenario observed the request where the browser reported no start), so the
state orders and overlaps
records as it does a HAR's and learns a write clock: an update the application
stamps with a modification time can be served. A scenario captured before
these times were recorded has none; its records keep request order and the
+16 -10
View File
@@ -356,13 +356,16 @@ All three options default to `false`. Any selected network content also enables
network metadata observation; listing `network` in `events` is then optional.
Each observed request object receives a capture-scoped `transaction_id`.
Each `request` event carries `observed_at`, the wall-clock time REA observed the
request start (a few milliseconds after the browser started it), and each
`request-finished` or `request-failed` event carries `elapsed_ms`, the browser's
own time from the request start to the end of its response, when the browser
reports one. The environment views time scenario records from these, as HAR
entries are timed; captures made before these fields existed lack them and are
read in record order. Scenario comparisons ignore both fields
(`ignore_network_request_timing`).
request start. Playwright reports the browser's own start only once a request
ends, so each `request-finished` or `request-failed` event carries `started_at`,
the browser's wall-clock start, and `elapsed_ms`, its time from that start to
the end of the response, when the browser reports them. The environment views
time scenario records from these, as HAR entries are timed: the browser's start
where it reported one, else `observed_at`, which trails it by up to tens of
milliseconds while REA reads other responses, and a duration of 0 where the
browser reported none. Captures made before these fields existed lack them and
are read in record order. REA versions before them refuse captures that carry
them. Scenario comparisons ignore all three (`ignore_network_request_timing`).
Requests sharing a URL remain distinct. Redirects link to the preceding
transaction only when it was observed; a null predecessor does not establish
that no earlier hop existed. Request events require both transaction fields;
@@ -460,8 +463,8 @@ and compared as an unordered collection after caller rules apply, because
concurrent responses arrive in any order and can land in a later step; a
redirect retains the complete predecessor ancestry, including each hop's own
request, response outcome, and selected network content. Each transaction's
capture-local IDs, sequence/index fields, and content source-sequence anchor
are removed. Caller rules normalize retained strings before hashing. The
capture-local IDs, sequence/index fields, content source-sequence anchor and
request times (`observed_at`, `started_at`, `elapsed_ms`) are removed. Caller rules normalize retained strings before hashing. The
`preserve_redirect_transaction_ancestry` built-in rule fingerprints each hop
as canonical SHA-256 of `{ events, redirected_from }`: `events` is the sorted
list of its normalized event SHA-256 digests, and `redirected_from` is its
@@ -482,7 +485,10 @@ scope/flags, value fingerprints, and duplicate entries even when redaction or
literal rules make names collide. Captured storage arrays retain their original
order. The `compare_storage_entries_as_unordered_collection` built-in rule
participates in the normalization commitment; new storage comparison digests
therefore differ from earlier order-sensitive comparisons.
therefore differ from earlier order-sensitive comparisons. The
`ignore_network_request_timing` built-in rule likewise joins the commitment, so
normalization digests differ from comparisons made before it, though captures
with and without request times compare alike.
Each aligned step reports changed, unchanged, or unknown. Changed and unknown
action, screenshot, DOM, accessibility, URL, history, storage, and event
@@ -1,19 +1,22 @@
# Plan
1. Schema: optional `observed_at` (ISO date-time) on `request` events and
`elapsed_ms` (non-negative number) on `request-finished` and
`request-failed` events.
2. Collector: stamp `observed_at` from an injectable wall clock when a request
is observed, admitting it with the other metadata strings, and copy the
browser's `timing().responseEnd` into `elapsed_ms` when it is known.
3. Records: index each transaction's finished or failed duration and give each
attributable record `startedDateTime` and `time`; add a limitation when any
record is timed.
1. Schema: optional `observed_at` (ISO date-time) on `request` events, and
`started_at` (ISO date-time) and `elapsed_ms` (non-negative number) on
`request-finished` and `request-failed` events.
2. Collector: stamp `observed_at` when a request is observed and copy the
browser's `timing().startTime` and `responseEnd` into `started_at` and
`elapsed_ms` when it reports them, admitting the strings with the other
metadata.
3. Records: index each transaction's single finished or failed start and
duration and give each attributable record `startedDateTime` and `time`;
add a limitation when any record is timed.
4. Comparison: drop both fields from network evidence before fingerprinting and
commit the rule in the built-in list and the comparison limitation.
5. Docs: the scenario contract's network evidence and the environment docs'
browser scenario section.
6. Tests: the collector stamps both fields, records take them, the state learns
the HAR's clock and verdicts from a timed scenario and none from an untimed
one, comparisons ignore them, and the real-Chrome network lane checks every
request and finished response is timed.
or partly untimed one, a request that never ended or ended twice falls back
to its observation, comparisons ignore the times (also against an untimed
capture), and the real-Chrome network lane checks every request is observed
and every finished request carries the browser's start and duration.
@@ -16,17 +16,20 @@ scenario capture learns the clock a HAR does.
## Requirements
- Each `request` event carries `observed_at`, the ISO wall-clock time the
provider observed the request start; Playwright reports no start time until
the response.
- Each `request-finished` and `request-failed` event carries `elapsed_ms`, the
browser's time from the request start to the end of its response, when the
browser reports one (`timing().responseEnd >= 0`).
- Both fields are optional in the schema, so Evidence captured before them
still parses and is read exactly as before.
- Scenario records take `startedDateTime` from `observed_at` and `time` from the
transaction's single finished or failed event (0 without one), and say so in
a limitation; a capture whose requests all carry `observed_at` gets the
recorded-start-time timeline and a write clock.
provider observed the request start; Playwright reports the browser's start
only once a request ends.
- Each `request-finished` and `request-failed` event carries `started_at`, the
browser's wall-clock start (`timing().startTime > 0`), and `elapsed_ms`, its
time from that start to the end of the response (`timing().responseEnd >= 0`),
when the browser reports them.
- The fields are optional in the schema, so Evidence captured before them still
parses and is read exactly as before. REA versions before them refuse
Evidence that carries them.
- Scenario records take `startedDateTime` from the transaction's single
finished or failed event's `started_at`, else from `observed_at`, and `time`
from its `elapsed_ms` (0 without one), and say so in a limitation; a capture
whose requests are all timed gets the recorded-start-time timeline and a
write clock.
- Scenario comparisons ignore both fields, as a committed built-in rule
(`ignore_network_request_timing`).
- The added metadata is charged to the event budgets as other metadata is.
@@ -36,5 +39,6 @@ scenario capture learns the clock a HAR does.
- No change to HAR captures, to how the state uses times, or to what a
record's timing means for overlap or clock rules.
- No retroactive timing of captures made before this change.
- No browser start times from response timing events: `observed_at` is the
provider's observation, a few milliseconds after the browser started.
- No browser start for a request that never ended: its record starts at
`observed_at`, which can trail the browser's start by tens of milliseconds
while the provider reads other responses, with no duration.