Skip to content

fix(navigate): short-circuit FF152 events wait; honest elapsed_ms + committed_url - #161

Merged
ractive merged 3 commits into
mainfrom
iter-122/navigate-dom-complete-ff152
Jul 19, 2026
Merged

fix(navigate): short-circuit FF152 events wait; honest elapsed_ms + committed_url#161
ractive merged 3 commits into
mainfrom
iter-122/navigate-dom-complete-ff152

Conversation

@ractive

@ractive ractive commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • 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 (example.com ~7.26s vs --no-wait 0.06s). 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 and returns as soon as the page reports complete. Pages that do fire dom-complete promptly keep the richer event path (300ms head start, 250ms probe cadence).
  • Theme B (timing): the single navigate-start Instant (nav_start) is threaded through both the events and readystate phases so elapsed_ms reflects true wall-clock instead of only the ~1ms readystate-poll duration.
  • Theme B (URL): when a committing document-event carries no url (SPA case), committed_url is resolved via window.location.href (eval_location_href) rather than surfaced as about:blank.
  • Docs: --wait-strategy help text, WaitStrategy::Both / WaitAfterNav doc-comments, and a new kb/rdp/actors/watcher.md note documenting the FF152 quirk and mitigation.

Test plan

  • unit_navigate_readystate_probe_short_circuits — probe returns a complete CommitInfo with committed_url from location.href when no dom-complete ever arrives, well inside the events budget (mock server).
  • unit_navigate_dom_complete_empty_url_falls_back_to_href — empty-URL dom-complete back-fills committed_url from location.href, never empty/about:blank.
  • live_navigate_default_fast — default navigate returns in wall-clock < timeout/2.
  • live_navigate_elapsed_matches_wallresults.elapsed_ms within ±750ms of measured wall-clock.
  • live_navigate_spa_committed_urlcommitted_url is the real landed URL, never about:blank/empty.
  • cargo fmt / cargo clippy --workspace --all-targets -- -D warnings / cargo test --workspace -q all clean.
  • cargo xtask check-iteration-ready — 10/10 discipline gates pass (with FF_RDP_LIVE_TESTS=1).

🤖 Generated with Claude Code## Claims vs code
<generated 2026-07-19T11:36:11Z by ralph-loop>

  • dom-complete → ✅ matched in diff
  • dom-loading → ✅ matched in diff

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>
@ractive

ractive commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

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-ignored

Expected: live_navigate_default_fast, live_navigate_elapsed_matches_wall, live_navigate_spa_committed_url all PASS. If any fail or Firefox can't be launched, do not merge — report instead.

…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>
@ractive

ractive commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

Local code review (medium effort, local-only mode)

Ran a local review over git diff main...HEAD. Copilot review was skipped per invocation mode.

# File:Line Issue Source
1 crates/ff-rdp-cli/src/commands/navigate.rs:369 (pre-fix) Interleaved readystate probe ignored wait_level, so --wait loading/--wait interactive + --wait-strategy both could short-circuit with ready_state: "complete" instead of resolving on the requested dom event Local
2 crates/ff-rdp-cli/src/commands/navigate.rs:279-287 (pre-fix) WaitLevel::Loading early-return skipped the Theme B eval_location_href fallback applied to Interactive/Complete, so --wait loading could still emit an empty/about:blank committed_url for SPAs — the exact bug Theme B claims to fix Local

Both fixed in 428f888: probe now gated to wait_level == WaitLevel::Complete, and the Loading path applies the same URL fallback as Interactive/Complete. Added unit_navigate_probe_ignored_for_non_complete_wait_level regression test. cargo fmt, cargo clippy --workspace --all-targets -- -D warnings, and cargo test --workspace -q all pass after the fix.

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>
@ractive
ractive merged commit 4783328 into main Jul 19, 2026
10 checks passed
@ractive
ractive deleted the iter-122/navigate-dom-complete-ff152 branch July 19, 2026 11:52
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.

1 participant