iter-140: element targeting — refs, ambiguous selectors, frame diagnostics - #179
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--ref(Theme A): refs now resolve to a genuinely-unique CSS selector instead of a baredocument.querySelectorAll(sel)[i]expression fed straight intoquerySelector(which always threw); the daemon's ref store is reusable across calls (fixed a residual bug beyond the starting WIP — same-URLframeUpdateevents that Fission emits on almost every RDP round-trip were still clearing the store; the fix now also compares against the lasttabNavigated-committed URL); expiry after a real navigation is reported as "expired", not "not registered".--visible/--index Ntoclick/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".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).click'sframe_urlin bothresultsandmetaas--helpdocuments, so--jq '.results.frame_url'never throws (Theme E)..ffrdp/page-map.jsonselectors unique (an#idshortcut ortag:nth-child(N)structural path) instead of falling back to a bare tag name that matches every element on the page (Theme F).ac-fidelity-check.shscript (mirrored attools/ralph-loop/scripts/and~/.claude/skills/ralph-loop/scripts/): a ticked AC quoting a CLI flag starting with-madegrep -qFparse it as an option and silently fail.page_map/mod.rsreferencedcrate::commands::js_helpers::UNIQUE_SELECTOR_JS_FNdirectly, butfuzz/fuzz_targets/parse_page_map_str.rs#[path]-includes that file standalone (nocommandsmodule in scope), which broke thefuzzCI job.form_extraction_js_template/landmark_extraction_js_templatenow take the JS snippet as a parameter instead of reaching intocrate::commands, keepingpage_map/mod.rsdependency-free for the fuzz harness.Test plan
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings,cargo test --workspace -qall clean (zero failures, doctests included)cargo check --bin parse_page_map_str(insidefuzz/) — confirms the fuzz harness still compiles standalonecargo run -p xtask -- check-iteration-ready --plan kb/iterations/iteration-140-element-targeting.md --base origin/main— 10/10 PASSFF_RDP_LIVE_TESTS=1):live_140_ref_click_resolves,live_140_ref_reusable,live_140_ref_expiry_messagelive_140_ambiguous_selector_reports_count,live_140_visible_flag_targets_visiblelive_140_frame_error_bounded,live_140_frame_filter_count_accuratelive_140_page_map_selectors_uniqueclick_frame_url_present_in_both_results_and_meta/click_jq_results_frame_url_does_not_throw(e2e, fore2e_click_frame_url_in_results)🤖 Generated with Claude Code## Claims vs code
<generated 2026-08-11T10:58:38Z by ralph-loop>
UNIQUE_SELECTOR_JS_FN→ ✅ matched in diffframe-scan→ ✅ matched in diff