Skip to content

iter-140: element targeting — refs, ambiguous selectors, frame diagnostics - #179

Merged
ractive merged 8 commits into
mainfrom
iter-140/element-targeting
Aug 11, 2026
Merged

iter-140: element targeting — refs, ambiguous selectors, frame diagnostics#179
ractive merged 8 commits into
mainfrom
iter-140/element-targeting

Conversation

@ractive

@ractive ractive commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • Fixes --ref (Theme A): refs now resolve to a genuinely-unique CSS selector instead of a bare document.querySelectorAll(sel)[i] expression fed straight into querySelector (which always threw); the daemon's ref store is reusable across calls (fixed a residual bug beyond the starting WIP — same-URL frameUpdate events that Fission emits on almost every RDP round-trip were still clearing the store; the fix now also compares against the last tabNavigated-committed URL); expiry after a real navigation is reported as "expired", not "not registered".
  • Adds --visible / --index N to click/type/styles (Theme B/C) to disambiguate a selector that matches more than one element, and makes both the timeout and fail-fast (display:none/visibility:hidden) error paths name the match count and chosen index instead of an undifferentiated "not found / hidden / unstable".
  • Bounds click's frame-scan error size (was up to 65 KB on a many-frame page) and fixes --frame's miscounted "tried" total (Theme D).
  • Keeps click's frame_url in both results and meta as --help documents, so --jq '.results.frame_url' never throws (Theme E).
  • Makes generated .ffrdp/page-map.json selectors unique (an #id shortcut or tag:nth-child(N) structural path) instead of falling back to a bare tag name that matches every element on the page (Theme F).
  • Fixes a latent bug in the shared ac-fidelity-check.sh script (mirrored at tools/ralph-loop/scripts/ and ~/.claude/skills/ralph-loop/scripts/): a ticked AC quoting a CLI flag starting with - made grep -qF parse it as an option and silently fail.
  • Fixes a CI regression the Theme F change introduced: page_map/mod.rs referenced crate::commands::js_helpers::UNIQUE_SELECTOR_JS_FN directly, but fuzz/fuzz_targets/parse_page_map_str.rs #[path]-includes that file standalone (no commands module in scope), which broke the fuzz CI job. form_extraction_js_template/landmark_extraction_js_template now take the JS snippet as a parameter instead of reaching into crate::commands, keeping page_map/mod.rs dependency-free for the fuzz harness.

Test plan

  • cargo fmt --check, cargo clippy --workspace --all-targets -- -D warnings, cargo test --workspace -q all clean (zero failures, doctests included)
  • cargo check --bin parse_page_map_str (inside fuzz/) — confirms the fuzz harness still compiles standalone
  • cargo run -p xtask -- check-iteration-ready --plan kb/iterations/iteration-140-element-targeting.md --base origin/main — 10/10 PASS
  • All 9 plan ACs backed by named tests, all passing against real headless Firefox (FF_RDP_LIVE_TESTS=1):
    • live_140_ref_click_resolves, live_140_ref_reusable, live_140_ref_expiry_message
    • live_140_ambiguous_selector_reports_count, live_140_visible_flag_targets_visible
    • live_140_frame_error_bounded, live_140_frame_filter_count_accurate
    • live_140_page_map_selectors_unique
    • click_frame_url_present_in_both_results_and_meta / click_jq_results_frame_url_does_not_throw (e2e, for e2e_click_frame_url_in_results)
  • Every theme's mechanism verified on the wire (RUST_LOG=debug against real Firefox 153) before writing tests/fixes, per the plan's run-guidance rule 1 — see the new test file's module doc comment for the exact repro that caught the residual ref-store bug

🤖 Generated with Claude Code## Claims vs code
<generated 2026-08-11T10:58:38Z by ralph-loop>

  • UNIQUE_SELECTOR_JS_FN → ✅ matched in diff
  • frame-scan → ✅ matched in diff

ractive and others added 8 commits August 11, 2026 11:03
…d agents

INCOMPLETE. Salvaged from six implement agents that were killed by the
harness after stalling (no model output for 180s each). cargo check
--workspace --all-targets passes, but this is NOT finished:
no live tests added yet, gates not run, ACs unverified.

A resuming agent must treat this as a starting point, not as done work:
re-read the plan, verify each theme against the actual diff, and add the
live daemon-path tests the plan requires.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…fast diagnostics, live tests

Completes the iter-140 element-targeting plan on top of the salvaged WIP
(refs as real CSS selectors, --visible/--index disambiguation, bounded
frame-scan errors, frame_url in both results and meta, unique page-map
selectors):

- daemon/server.rs: the WIP's frameUpdate{isTopLevel:true} navigation
  heuristic still cleared the ref store on same-URL frameUpdate events that
  Fission emits on almost every RDP round-trip (confirmed live with
  RUST_LOG=debug — a fresh childN/windowGlobalTargetN actor pair per call,
  same committed URL). Now also compares the frame's URL against the last
  tabNavigated-committed URL; only a genuinely different URL invalidates
  refs, closing the "second resolve fails" symptom for good.
- js_helpers.rs: autowait's immediate-exception path (display:none /
  visibility:hidden on the DOM-order-0 match) used to return the bare JS
  message with no match count, bypassing diagnose_selector_failure entirely.
  Routed through the same diagnostic so both the timeout and fail-fast paths
  report match count / chosen index identically.
- Added crates/ff-rdp-cli/tests/live/live_140_element_targeting.rs covering
  all 8 live_140_* ACs against real Firefox (daemon-parity, FixtureServer-
  based, no network dependency), plus two e2e tests in tests/e2e/click.rs
  for the frame_url-in-both-results-and-meta AC.
- args.rs: documented --visible/--index on click/type/styles in --help.

Verified every theme on the wire per run-guidance rule 1 before writing
tests — see the new test file's module doc comment for the exact repro.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…mbols

ac-fidelity-check.sh's backtick-symbol heuristics ran `grep -qF "$sym"`
with no `--`, so a ticked AC quoting a CLI flag (e.g. `--jq
'.results.frame_url'`) made grep parse the pattern as an option and error
out — silently scored as "no evidence found" since the failure happens
inside an `if` condition, invisible to `set -e`. Add `--` to both call
sites so any literal symbol is always treated as a pattern. Mirrored to
~/.claude/skills/ralph-loop/scripts/ per CLAUDE.md's edit-both rule.

Also ticks off iteration 140's 9 acceptance criteria with evidence
(all live_140_*/e2e_ tests pass) and moves the plan to status: in-progress.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The fuzz target fuzz/fuzz_targets/parse_page_map_str.rs #[path]-includes
page_map/mod.rs standalone (independent of the ff-rdp-cli binary crate's
module tree). iter-140 Theme F added a reference from that file to
crate::commands::js_helpers::UNIQUE_SELECTOR_JS_FN, which doesn't exist
in the fuzz crate's module tree — breaking the CI fuzz job with
"cannot find `commands` in the crate root".

Parameterize form_extraction_js_template/landmark_extraction_js_template
to take the JS snippet as an argument instead; the one real caller
(commands/index.rs) passes crate::commands::js_helpers::UNIQUE_SELECTOR_JS_FN.
review-pr: the defensive mutual-exclusivity check in from_flags (for
programmatic callers that bypass clap's conflicts_with) had no direct
unit test. Cover all four flag combinations.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
All 9 ACs are ticked and backed by passing live tests (verified against
real headless Firefox during review). Status was left at "in-progress"
by the branch author; every checkbox in this PR's diff is genuinely
done, so completed is accurate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Run guidance rule 1: add iter-140's ref-invalidation misdiagnosis
  (isTopLevel-only frameUpdate handling looked sufficient, but Fission's
  same-URL actor churn needed a URL-comparison fix on top) as a fourth
  confirmed case of "the plan's stated root cause was incomplete or wrong".
- Notes: point Theme A at middle_ellipsis (now used a second time in
  iter-140's click.rs frame-error bounding) instead of a third bespoke
  truncation helper, and flag Theme F's field-shape bugs as the same
  class as iter-140's frame_url .remove()-vs-clone bug, caught by
  literally running the --jq filter --help advertises.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ractive
ractive merged commit 3a456f6 into main Aug 11, 2026
10 checks passed
@ractive
ractive deleted the iter-140/element-targeting branch August 11, 2026 11:13
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