fix(navigate): short-circuit FF152 events wait; honest elapsed_ms + committed_url - #161
Conversation
On Firefox 152 the `dom-complete` document-event never fires for some static pages and SPAs, so a default `navigate` burned the full ~7s events budget before the readystate fallback rescued it. Two derived defects also surfaced: `elapsed_ms` reported only the ~1ms readystate-poll duration, and `committed_url` rendered as `about:blank` for SPAs that never fired a `dom-loading` with a URL. - Theme A: the default `both` strategy now interleaves a lightweight, freshness-guarded `document.readyState` probe (`ReadyStateProbe` + `probe_readystate_complete`) into the `wait_for_doc_complete` drain loop, returning as soon as the page reports `complete` instead of waiting out the events budget. Pages that do fire `dom-complete` promptly keep the richer event path (300ms head start, 250ms cadence). - Theme B: thread the navigate-start `Instant` through both phases so `elapsed_ms` reflects true wall-clock; resolve `committed_url` via `window.location.href` (`eval_location_href`) when a committing event carries no URL, instead of emitting `about:blank`. Tests: 2 new unit tests (readystate-probe short-circuit, empty-URL href fallback) + 3 AC-named live tests (live_navigate_default_fast, live_navigate_elapsed_matches_wall, live_navigate_spa_committed_url). Docs: --wait-strategy help, WaitStrategy doc-comments, watcher.md kb note. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Reviewer request (orchestrator): the three AC checkboxes name live tests but the PR shows no live-run output. Before merging, please run the navigate live suite against real FF152 and paste the result here: FF_RDP_LIVE_TESTS=1 cargo test -p ff-rdp-cli --test live_navigate_default_fast -- --include-ignoredExpected: |
…allback Local review found two correctness bugs in the iter-122 Theme A/B fast path: 1. The interleaved readystate probe fired regardless of wait_level, so `--wait loading`/`--wait interactive` combined with `--wait-strategy both` could short-circuit with ready_state: "complete" instead of resolving on the requested dom-loading/dom-interactive event. The probe can only ever observe readyState === 'complete', so it is now gated to wait_level == Complete. 2. The WaitLevel::Loading early-return path returned the raw (possibly empty) dom-loading event URL directly, missing the Theme B eval_location_href fallback applied to the Interactive/Complete paths — reintroducing the empty-URL/about:blank bug Theme B was meant to fix, for --wait loading specifically. Adds unit_navigate_probe_ignored_for_non_complete_wait_level to cover (1). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Local code review (medium effort, local-only mode)Ran a local review over
Both fixed in 428f888: probe now gated to |
iter-122's task/AC checkboxes already matched the merged diff exactly, so none needed re-ticking. Adds a Review notes section documenting the two bugs found and fixed during /review-pr (probe ignoring wait_level, Loading path missing the Theme B URL fallback). Adds a brief carry-forward note to iter-123's plan about gating fast paths on caller-requested parameters, learned from the iter-122 review; no scope change to iter-123 itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Summary
dom-completedocument-event never fires for some static pages and SPAs, so a defaultnavigateburned the full ~7s events budget before the readystate fallback rescued it (example.com ~7.26s vs--no-wait0.06s). Theme A: the defaultbothstrategy now interleaves a lightweight, freshness-guardeddocument.readyStateprobe (ReadyStateProbe+probe_readystate_complete) into thewait_for_doc_completedrain loop and returns as soon as the page reportscomplete. Pages that do firedom-completepromptly keep the richer event path (300ms head start, 250ms probe cadence).Instant(nav_start) is threaded through both the events and readystate phases soelapsed_msreflects true wall-clock instead of only the ~1ms readystate-poll duration.document-eventcarries nourl(SPA case),committed_urlis resolved viawindow.location.href(eval_location_href) rather than surfaced asabout:blank.--wait-strategyhelp text,WaitStrategy::Both/WaitAfterNavdoc-comments, and a newkb/rdp/actors/watcher.mdnote documenting the FF152 quirk and mitigation.Test plan
unit_navigate_readystate_probe_short_circuits— probe returns acompleteCommitInfowithcommitted_urlfromlocation.hrefwhen nodom-completeever arrives, well inside the events budget (mock server).unit_navigate_dom_complete_empty_url_falls_back_to_href— empty-URLdom-completeback-fillscommitted_urlfromlocation.href, never empty/about:blank.live_navigate_default_fast— default navigate returns in wall-clock< timeout/2.live_navigate_elapsed_matches_wall—results.elapsed_mswithin ±750ms of measured wall-clock.live_navigate_spa_committed_url—committed_urlis the real landed URL, neverabout:blank/empty.cargo fmt/cargo clippy --workspace --all-targets -- -D warnings/cargo test --workspace -qall clean.cargo xtask check-iteration-ready— 10/10 discipline gates pass (withFF_RDP_LIVE_TESTS=1).🤖 Generated with Claude Code## Claims vs code
<generated 2026-07-19T11:36:11Z by ralph-loop>
dom-complete→ ✅ matched in diffdom-loading→ ✅ matched in diff