[PR #6967] [MERGED] feat(environment): time browser scenario records so scenario environments learn a write clock #7480

Closed
opened 2026-11-01 21:48:08 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6967
Author: @earakely-scale
Created: 10/24/2026
Status: ✅ Merged
Merged: 10/24/2026
Merged by: @morluto

Base: main ← Head: feat/scenario-request-timing


📝 Commits (8)

  • 67c23ee feat(browser): record when scenario requests were observed and how long they took
  • 0ed402e feat(environment): time browser scenario records so their state learns a write clock
  • 80388de docs(environment): document scenario request times and timed scenario records
  • 8c63c17 fix(environment): start scenario records at the browser's own request start
  • b92a11b docs(environment): document the browser start time, its fallback lag and older readers
  • 2eeb627 docs(environment): record the scenario timing verification
  • ae27520 test(browser): compare timed completion events in the request-time comparison test
  • 374436f fix(environment): integrate scenario timing with current capture workflows

📊 Changes

20 files changed (+685 additions, -20 deletions)

View changed files

📝 .agents/skills/reverse-engineer-anything/SKILL.md (+1 -1)
📝 .agents/skills/reverse-engineer-anything/references/environments.md (+5 -4)
📝 docs/agent-environments.md (+10 -5)
📝 docs/browser-scenario-contract.md (+17 -3)
➕ docs/specs/agent-environments/scenario-timing/plan.md (+22 -0)
➕ docs/specs/agent-environments/scenario-timing/spec.md (+44 -0)
➕ docs/specs/agent-environments/scenario-timing/tasks.md (+13 -0)
➕ docs/specs/agent-environments/scenario-timing/verification.md (+73 -0)
📝 scripts/lib/browser-network-assertions.mjs (+16 -0)
📝 src/browser/network/PlaywrightScenarioNetwork.test.ts (+47 -0)
📝 src/browser/network/PlaywrightScenarioNetwork.ts (+42 -2)
📝 src/domain/analysisView/environmentCoverageView.ts (+1 -1)
➕ src/domain/analysisView/environmentStateScenarioTiming.test.ts (+183 -0)
📝 src/domain/analysisView/scenarioCaptureRecords.ts (+57 -1)
📝 src/domain/browserScenarioCaptureValues.ts (+25 -0)
📝 src/domain/browserScenarioDiff.test.ts (+110 -0)
📝 src/domain/browserScenarioDiff.ts (+1 -1)
📝 src/domain/browserScenarioDiffValues.ts (+1 -0)
📝 src/domain/browserScenarioNetworkComparison.ts (+16 -1)
📝 src/generatedPackageMetadata.ts (+1 -1)

📄 Description

Summary

Browser scenario captures record no request times, so every record a scenario projects is untimed. The
environment-state view then reads a scenario in record order and learns no write clock. Any update whose response
carries a modification time the application sets is withheld as unexplained-change, however carefully it is recorded,
while a HAR of the same session serves it with a clock rule. This was the main gap left in building environments from a
prompt (#6946), where the agent records with a browser scenario: Linkding's and Homebox's edits never served.

This PR records the times and uses them:

  1. Scenario network events carry times:
    • request events get observed_at, when REA observed the request;
    • request-finished and request-failed events get the browser's own started_at and elapsed_ms, which
      Playwright reports once a request ends.
  2. Scenario records are timed as HAR entries are: the browser's start (falling back to observed_at) and its
    duration. A timed scenario gets the recorded-start-time timeline and a write clock.
  3. Comparisons ignore the times: a committed built-in rule, ignore_network_request_timing.

On the same recordings built with and without their times, prompt-recorded Linkding serves 4 writes instead of 1, and
Homebox 3 instead of 2. The Linkding bundle with timed records passes all three of the application's write tasks with
both eval models; the earlier prompt-built Linkding bundles passed none. No capture serves fewer writes with times, and
captures made before this change read exactly as before.

Part of #4933 (agent-environment projection, serving and export).

Problem and expected behavior

  • A scenario capture should time its records as a HAR does, so the state can order and overlap them and learn the clock
    an application's modification times follow.
  • Captures recorded before the change must keep parsing and projecting identically.
  • Scenario comparisons must not report a change because two runs took different times.

Change and scope

  • Events (src/domain/browserScenarioCaptureValues.ts, src/browser/network/PlaywrightScenarioNetwork.ts):
    • optional observed_at on request events;
    • optional started_at and elapsed_ms on request-finished and request-failed events, from Playwright's
      request.timing() (startTime > 0, responseEnd >= 0);
    • the strings are charged to the event budgets like other metadata.
  • Records (src/domain/analysisView/scenarioCaptureRecords.ts):
    • startedDateTime comes from the transaction's single finished or failed started_at, else from observed_at;
    • time comes from its elapsed_ms, or 0 without one;
    • a limitation names the sources.
    • A capture with any untimed request keeps record order, as a HAR with an untimed entry does.
  • Comparison (src/domain/browserScenarioNetworkComparison.ts, browserScenarioDiffValues.ts):
    • the three fields are dropped before fingerprinting;
    • the new built-in rule joins the normalization commitment, so normalization digests differ from earlier
      comparisons (documented, as the storage rule's change was).
  • Docs and spec: the scenario contract's network evidence and comparison sections, the environment docs'
    browser-scenario section, and docs/specs/agent-environments/scenario-timing/.

Not included:

  • re-timing older captures;
  • changes to HAR captures or to how the state uses times;

Contract and boundary impact

  • Semantic owner and earliest changed stage: browser scenario capture events (src/browser/network), scenario
    records for the environment views (src/domain/analysisView), and scenario comparison (src/domain).
  • Contribution scope fit and linked maintainer decision: within the existing scenario-capture and environment
    boundaries. It observes timing the browser already reports; no new target interaction.
  • CLI and MCP/tool-catalog contract:
    • capture_browser_scenario output events gain three optional fields;
    • compare_web_captures gains one built-in normalization rule, so built_in_rules now lists 11.
  • Provider, bridge, target-format, or platform compatibility: Playwright launch and connect.
  • Evidence, artifact, provenance, or reconstruction contract:
    • New scenario Evidence carries the fields. REA versions before this change refuse it, because the event schemas are
      strict; consumers pinned to an older rea-agents cannot read scenario captures made with this one.
    • Earlier Evidence parses and projects byte-identically.
  • Target selection, authority, upstream behavior, and cleanup details: unchanged.
  • Generated metadata, package, or installation impact: output schema additions and packaged skill version 49.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

The same capture with and without its times. Each capture was recorded with this branch, then built as recorded and
with its times removed (the Evidence sealed again as the provider seals it):

Capture Records Writes served without / with times
Linkding, agent-recorded from a prompt 60 1 / 4
Linkding, agent-recorded from a prompt (again) 65 3 / 3
Homebox, agent-recorded from a prompt 263 2 / 3
Homebox, agent-recorded from a prompt (again) 275 2 / 2
Pinry, its published scenario re-recorded 568 0 / 0 (1 clock rule learned)
PhotoPrism, its published scenario re-recorded 273 2 / 2 (2 clock rules learned)
  • What times unlock: Linkding's bookmark and bundle edits and Homebox's tag edit are served only with times, because
    their responses carry server-set modification times. PhotoPrism's served album create now stamps CreatedAt and
    UpdatedAt from the clock instead of replaying the recorded values.
  • When they don't help: the second Linkding and Homebox recordings gain nothing, because their gaps are elsewhere
    (unconfirmed, contradicted).
  • How the prompt-recorded captures were made: with a local, unpushed build of this branch merged with #6946, for its
    request action. Claude Code recorded each app from a one-paragraph prompt on Ubuntu VMs (snap Chromium 155).
  • Write evals:
    • The timed Linkding bundle passes all 3 write tasks with fireworks_ai/gpt-oss-120b and
      fireworks_ai/glm-5p3-flash. Counts are relative to its own state, which holds active and archived bookmarks as
      two types.
    • Homebox passes 2/2 with gpt-oss and 1/2 with GLM (GLM deleted the wrong item).

Stale environments, not republished. Pinry and PhotoPrism are the oldest published environments recorded as
scenarios (0.1.0, replay only). I re-recorded both with this branch and rebuilt them with the publishing pipeline:

App Published 0.1.0 Rebuilt
Pinry 12 tools, replay, retrieval 6/6 and 6/6 12 tools, state and clock, no writes served; retrieval 6/6 and 4/6
PhotoPrism 13 tools, replay, retrieval 10/10 and 10/10 14 tools, state and clock, album create and rename served; retrieval 8/10 and 5/10
  • Neither improves, so I did not update them on Hugging Face.
  • The drops are not from timing: timed and untimed states are identical in every view those tasks read.
  • PhotoPrism: its album list is answered from the state in name order, while the recorded answer that generated the
    task listed another album first. That is a list-order gap in state serving, worth its own issue.
  • Pinry: GLM's two misses are tool calls rejected for numeric limit/offset, under the same tool schemas as the
    published version.

Review. An independent review rebuilt the branch and tried to refute it.

  • Confirmed:

    • views byte-identical for the three published scenario captures on main and this branch;
    • comparisons alike with and without times, including against an untimed capture;
    • each duration taken only from its own transaction;
    • both fields charged to the budgets.
  • Fixed:

    • Records now start at the browser's own start. The provider's observation trailed it by up to 36 ms while other
      responses were read, and mixed two clocks in one interval.
    • Docs now give the fallback's lag, the older-reader refusal and the digest change.
    • Tests now cover the fallbacks, partly untimed captures and comparisons with untimed captures.
  • Tests added:

    • the collector stamps observed_at, started_at and elapsed_ms, and omits what the browser does not report;
    • records prefer the browser's start and fall back for a request that never ended or ended twice;
    • a timed scenario of the book session learns the same clock and verdicts as its HAR, while an untimed or partly
      untimed one keeps record order;
    • comparisons ignore the times, including against an untimed capture;
    • the real-Chrome network lane asserts every request and finished request is timed.
  • User-visible CLI/MCP output: from a real Chrome capture with this branch (a page that PATCHes /api/items/1),
    the transaction's request and completion events now carry:

    {"kind":"request","transaction_id":"request-2","method":"PATCH","observed_at":"2026-10-24T12:19:32.578Z"}
    {"kind":"request-finished","transaction_id":"request-2","started_at":"2026-10-24T12:19:32.576Z","elapsed_ms":0.981}
    

    Its scenario record takes startedDateTime: "2026-10-24T12:19:32.576Z" and time: 0.981, and a comparison lists
    ignore_network_request_timing among normalization.built_in_rules.

  • Remaining proof gaps:

    • a request that never ends has no browser start, so its record starts at the provider's observation, with no
      duration;
    • captures from before this change stay untimed until re-recorded.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

Current integration: 374436ff5, macOS with pinned Node v24.22.1.

  • npm run check: passed, including build, typecheck, format, lint, module boundaries, and architecture guards.
  • Timing, comparison, scenario-record, skill-publication, and verifier-ownership workflows: 7 files, 90 tests passed. This includes all three packaged-verifier tests that failed in the earlier CI run.
  • Coverage and actual MCP schema/client workflows: 3 files, 23 tests passed.
  • npm run docs:check: passed, including 9 documentation tests.
  • npm run verify:browser:network in real Chrome: 10 timed requests, 9 timed completions, CLI and MCP paths verified, no remaining owned descendants. Connected-browser verification remains outside this local lane.

Merged current main to inherit the shared command-ownership and source-loader fixes. The environment skill and coverage wording now distinguish fully timed scenarios from older or partly untimed captures; the packaged skill version is 49.

The earlier application recordings and model evaluations are documented above and in the verification document; they were not rerun during this integration. Hosted CI passed at 374436ff5, including all eight test shards, real-browser, agentenv, the native package baseline, and the required CI gate.

Compatibility, safety, and release

  • Breaking changes or migration steps: none for callers. Older REA versions refuse new scenario captures, so a
    consumer reading scenario Evidence needs this version or later.
  • Real Hopper/Ghidra, browser, or OS coverage: real Chrome on macOS; snap Chromium 155 on Ubuntu 24.04.
  • Package or release metadata impact: packaged skill version 49 for the updated timing guidance.
  • Security, privacy, process, or containment review: the new fields are times only; no values from the page.

Author readiness

Human owner: @earakely-scale

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/6967 **Author:** [@earakely-scale](https://github.com/earakely-scale) **Created:** 10/24/2026 **Status:** ✅ Merged **Merged:** 10/24/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `feat/scenario-request-timing` --- ### 📝 Commits (8) - [`67c23ee`](https://github.com/morluto/rea/commit/67c23eece2086d7c374f646e7e4f239b9d1e74eb) feat(browser): record when scenario requests were observed and how long they took - [`0ed402e`](https://github.com/morluto/rea/commit/0ed402e86806b5f94aa4fe96bbedebae719be149) feat(environment): time browser scenario records so their state learns a write clock - [`80388de`](https://github.com/morluto/rea/commit/80388de4fe75586a0aeeefa209c05dabac0a084c) docs(environment): document scenario request times and timed scenario records - [`8c63c17`](https://github.com/morluto/rea/commit/8c63c17b9325288811cfc4c87f4829231cfc6f9a) fix(environment): start scenario records at the browser's own request start - [`b92a11b`](https://github.com/morluto/rea/commit/b92a11b6d81c5e9355a23a29fd2363b25d8a43d5) docs(environment): document the browser start time, its fallback lag and older readers - [`2eeb627`](https://github.com/morluto/rea/commit/2eeb627ce63dd3966bca88a432c1e7945a0f9f19) docs(environment): record the scenario timing verification - [`ae27520`](https://github.com/morluto/rea/commit/ae27520361293df84cd5d1ae9b866e0ff61c7fc5) test(browser): compare timed completion events in the request-time comparison test - [`374436f`](https://github.com/morluto/rea/commit/374436ff5d0525f8659b9d086965fd58984f6566) fix(environment): integrate scenario timing with current capture workflows ### 📊 Changes **20 files changed** (+685 additions, -20 deletions) <details> <summary>View changed files</summary> 📝 `.agents/skills/reverse-engineer-anything/SKILL.md` (+1 -1) 📝 `.agents/skills/reverse-engineer-anything/references/environments.md` (+5 -4) 📝 `docs/agent-environments.md` (+10 -5) 📝 `docs/browser-scenario-contract.md` (+17 -3) ➕ `docs/specs/agent-environments/scenario-timing/plan.md` (+22 -0) ➕ `docs/specs/agent-environments/scenario-timing/spec.md` (+44 -0) ➕ `docs/specs/agent-environments/scenario-timing/tasks.md` (+13 -0) ➕ `docs/specs/agent-environments/scenario-timing/verification.md` (+73 -0) 📝 `scripts/lib/browser-network-assertions.mjs` (+16 -0) 📝 `src/browser/network/PlaywrightScenarioNetwork.test.ts` (+47 -0) 📝 `src/browser/network/PlaywrightScenarioNetwork.ts` (+42 -2) 📝 `src/domain/analysisView/environmentCoverageView.ts` (+1 -1) ➕ `src/domain/analysisView/environmentStateScenarioTiming.test.ts` (+183 -0) 📝 `src/domain/analysisView/scenarioCaptureRecords.ts` (+57 -1) 📝 `src/domain/browserScenarioCaptureValues.ts` (+25 -0) 📝 `src/domain/browserScenarioDiff.test.ts` (+110 -0) 📝 `src/domain/browserScenarioDiff.ts` (+1 -1) 📝 `src/domain/browserScenarioDiffValues.ts` (+1 -0) 📝 `src/domain/browserScenarioNetworkComparison.ts` (+16 -1) 📝 `src/generatedPackageMetadata.ts` (+1 -1) </details> ### 📄 Description ## Summary Browser scenario captures record no request times, so every record a scenario projects is untimed. The environment-state view then reads a scenario in record order and learns no write clock. Any update whose response carries a modification time the application sets is withheld as `unexplained-change`, however carefully it is recorded, while a HAR of the same session serves it with a clock rule. This was the main gap left in building environments from a prompt (#6946), where the agent records with a browser scenario: Linkding's and Homebox's edits never served. This PR records the times and uses them: 1. **Scenario network events carry times:** - `request` events get `observed_at`, when REA observed the request; - `request-finished` and `request-failed` events get the browser's own `started_at` and `elapsed_ms`, which Playwright reports once a request ends. 2. **Scenario records are timed as HAR entries are:** the browser's start (falling back to `observed_at`) and its duration. A timed scenario gets the recorded-start-time timeline and a write clock. 3. **Comparisons ignore the times:** a committed built-in rule, `ignore_network_request_timing`. On the same recordings built with and without their times, prompt-recorded Linkding serves 4 writes instead of 1, and Homebox 3 instead of 2. The Linkding bundle with timed records passes all three of the application's write tasks with both eval models; the earlier prompt-built Linkding bundles passed none. No capture serves fewer writes with times, and captures made before this change read exactly as before. Part of #4933 (agent-environment projection, serving and export). ## Problem and expected behavior - A scenario capture should time its records as a HAR does, so the state can order and overlap them and learn the clock an application's modification times follow. - Captures recorded before the change must keep parsing and projecting identically. - Scenario comparisons must not report a change because two runs took different times. ## Change and scope - **Events** (`src/domain/browserScenarioCaptureValues.ts`, `src/browser/network/PlaywrightScenarioNetwork.ts`): - optional `observed_at` on `request` events; - optional `started_at` and `elapsed_ms` on `request-finished` and `request-failed` events, from Playwright's `request.timing()` (`startTime > 0`, `responseEnd >= 0`); - the strings are charged to the event budgets like other metadata. - **Records** (`src/domain/analysisView/scenarioCaptureRecords.ts`): - `startedDateTime` comes from the transaction's single finished or failed `started_at`, else from `observed_at`; - `time` comes from its `elapsed_ms`, or 0 without one; - a limitation names the sources. - A capture with any untimed request keeps record order, as a HAR with an untimed entry does. - **Comparison** (`src/domain/browserScenarioNetworkComparison.ts`, `browserScenarioDiffValues.ts`): - the three fields are dropped before fingerprinting; - the new built-in rule joins the normalization commitment, so normalization digests differ from earlier comparisons (documented, as the storage rule's change was). - **Docs and spec:** the scenario contract's network evidence and comparison sections, the environment docs' browser-scenario section, and `docs/specs/agent-environments/scenario-timing/`. **Not included:** - re-timing older captures; - changes to HAR captures or to how the state uses times; ## Contract and boundary impact - **Semantic owner and earliest changed stage:** browser scenario capture events (`src/browser/network`), scenario records for the environment views (`src/domain/analysisView`), and scenario comparison (`src/domain`). - **Contribution scope fit and linked maintainer decision:** within the existing scenario-capture and environment boundaries. It observes timing the browser already reports; no new target interaction. - **CLI and MCP/tool-catalog contract:** - `capture_browser_scenario` output events gain three optional fields; - `compare_web_captures` gains one built-in normalization rule, so `built_in_rules` now lists 11. - **Provider, bridge, target-format, or platform compatibility:** Playwright launch and connect. - **Evidence, artifact, provenance, or reconstruction contract:** - New scenario Evidence carries the fields. REA versions before this change refuse it, because the event schemas are strict; consumers pinned to an older `rea-agents` cannot read scenario captures made with this one. - Earlier Evidence parses and projects byte-identically. - **Target selection, authority, upstream behavior, and cleanup details:** unchanged. - **Generated metadata, package, or installation impact:** output schema additions and packaged skill version 49. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [x] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage **The same capture with and without its times.** Each capture was recorded with this branch, then built as recorded and with its times removed (the Evidence sealed again as the provider seals it): | Capture | Records | Writes served without / with times | | ---------------------------------------------- | ------- | ---------------------------------- | | Linkding, agent-recorded from a prompt | 60 | 1 / 4 | | Linkding, agent-recorded from a prompt (again) | 65 | 3 / 3 | | Homebox, agent-recorded from a prompt | 263 | 2 / 3 | | Homebox, agent-recorded from a prompt (again) | 275 | 2 / 2 | | Pinry, its published scenario re-recorded | 568 | 0 / 0 (1 clock rule learned) | | PhotoPrism, its published scenario re-recorded | 273 | 2 / 2 (2 clock rules learned) | - **What times unlock:** Linkding's bookmark and bundle edits and Homebox's tag edit are served only with times, because their responses carry server-set modification times. PhotoPrism's served album create now stamps `CreatedAt` and `UpdatedAt` from the clock instead of replaying the recorded values. - **When they don't help:** the second Linkding and Homebox recordings gain nothing, because their gaps are elsewhere (`unconfirmed`, `contradicted`). - **How the prompt-recorded captures were made:** with a local, unpushed build of this branch merged with #6946, for its `request` action. Claude Code recorded each app from a one-paragraph prompt on Ubuntu VMs (snap Chromium 155). - **Write evals:** - The timed Linkding bundle passes all 3 write tasks with `fireworks_ai/gpt-oss-120b` and `fireworks_ai/glm-5p3-flash`. Counts are relative to its own state, which holds active and archived bookmarks as two types. - Homebox passes 2/2 with gpt-oss and 1/2 with GLM (GLM deleted the wrong item). **Stale environments, not republished.** Pinry and PhotoPrism are the oldest published environments recorded as scenarios (0.1.0, replay only). I re-recorded both with this branch and rebuilt them with the publishing pipeline: | App | Published 0.1.0 | Rebuilt | | ---------- | ------------------------------------------- | ---------------------------------------------------------------------------------- | | Pinry | 12 tools, replay, retrieval 6/6 and 6/6 | 12 tools, state and clock, no writes served; retrieval 6/6 and 4/6 | | PhotoPrism | 13 tools, replay, retrieval 10/10 and 10/10 | 14 tools, state and clock, album create and rename served; retrieval 8/10 and 5/10 | - Neither improves, so I did not update them on Hugging Face. - The drops are not from timing: timed and untimed states are identical in every view those tasks read. - **PhotoPrism:** its album list is answered from the state in name order, while the recorded answer that generated the task listed another album first. That is a list-order gap in state serving, worth its own issue. - **Pinry:** GLM's two misses are tool calls rejected for numeric `limit`/`offset`, under the same tool schemas as the published version. **Review.** An independent review rebuilt the branch and tried to refute it. - **Confirmed:** - views byte-identical for the three published scenario captures on main and this branch; - comparisons alike with and without times, including against an untimed capture; - each duration taken only from its own transaction; - both fields charged to the budgets. - **Fixed:** - Records now start at the browser's own start. The provider's observation trailed it by up to 36 ms while other responses were read, and mixed two clocks in one interval. - Docs now give the fallback's lag, the older-reader refusal and the digest change. - Tests now cover the fallbacks, partly untimed captures and comparisons with untimed captures. - **Tests added:** - the collector stamps `observed_at`, `started_at` and `elapsed_ms`, and omits what the browser does not report; - records prefer the browser's start and fall back for a request that never ended or ended twice; - a timed scenario of the book session learns the same clock and verdicts as its HAR, while an untimed or partly untimed one keeps record order; - comparisons ignore the times, including against an untimed capture; - the real-Chrome network lane asserts every request and finished request is timed. - **User-visible CLI/MCP output:** from a real Chrome capture with this branch (a page that PATCHes `/api/items/1`), the transaction's request and completion events now carry: ```json {"kind":"request","transaction_id":"request-2","method":"PATCH","observed_at":"2026-10-24T12:19:32.578Z"} {"kind":"request-finished","transaction_id":"request-2","started_at":"2026-10-24T12:19:32.576Z","elapsed_ms":0.981} ``` Its scenario record takes `startedDateTime: "2026-10-24T12:19:32.576Z"` and `time: 0.981`, and a comparison lists `ignore_network_request_timing` among `normalization.built_in_rules`. - **Remaining proof gaps:** - a request that never ends has no browser start, so its record starts at the provider's observation, with no duration; - captures from before this change stay untimed until re-recorded. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed Current integration: 374436ff5, macOS with pinned Node v24.22.1. - `npm run check`: passed, including build, typecheck, format, lint, module boundaries, and architecture guards. - Timing, comparison, scenario-record, skill-publication, and verifier-ownership workflows: 7 files, 90 tests passed. This includes all three packaged-verifier tests that failed in the earlier CI run. - Coverage and actual MCP schema/client workflows: 3 files, 23 tests passed. - `npm run docs:check`: passed, including 9 documentation tests. - `npm run verify:browser:network` in real Chrome: 10 timed requests, 9 timed completions, CLI and MCP paths verified, no remaining owned descendants. Connected-browser verification remains outside this local lane. Merged current main to inherit the shared command-ownership and source-loader fixes. The environment skill and coverage wording now distinguish fully timed scenarios from older or partly untimed captures; the packaged skill version is 49. The earlier application recordings and model evaluations are documented above and in the verification document; they were not rerun during this integration. Hosted CI passed at 374436ff5, including all eight test shards, real-browser, agentenv, the native package baseline, and the required CI gate. ## Compatibility, safety, and release - **Breaking changes or migration steps:** none for callers. Older REA versions refuse new scenario captures, so a consumer reading scenario Evidence needs this version or later. - **Real Hopper/Ghidra, browser, or OS coverage:** real Chrome on macOS; snap Chromium 155 on Ubuntu 24.04. - **Package or release metadata impact:** packaged skill version 49 for the updated timing guidance. - **Security, privacy, process, or containment review:** the new fields are times only; no values from the page. ## Author readiness Human owner: @earakely-scale - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:48:08 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7480
No description provided.