complete_bing_daily_set indexed [0] [1] [2] on whatever wait_for_element returned first. The panel hydrates progressively, so that can be a single activity, and the task died with IndexError before touching the other two. Wait for the full set, fall back to what is there, and re-read per index since a click can re-render the panel.
read_search_points ran into the default 10s timeout because it starts after the earlier tasks navigated away, so the earn page re-renders from scratch first. That skipped the whole search task while points were still available.
The card loop fired fixed 100px scroll events back to back with no pauses, which is the jumpy scrolling, and its while-not-in-viewport loop was unbounded, so a card that never fits the viewport completely would hang the run forever. The way back up unwound a counted number of steps, which lands wrong when the page height changes while cards update.
Scrolling is now wheel input with varying step sizes and short pauses, bounded, aimed at centering the target. The return reads the actual scroll position instead of counting.
searches_needed was computed once as (max - earned) // 5 and never re-checked. Two assumptions fail in practice: some markets award 3 points per search rather than 5, and the daily maximum itself is not stable, observed as 15, 30 and 60 on one account within a day with the counter resetting. The run therefore stopped around 18/30 and still reported success.
Search in rounds instead: measure, run a batch sized on the lower known rate, measure again, stop when the quota is full or a round gains nothing, and warn instead of claiming success when it is not filled.
Also give the ollama client a timeout and bound the empty-response retry, since both were unbounded and an unattended run hung for 14 minutes with 2.3 CPU-seconds. The bare while-not-response loop spins forever on empty responses.
check_selectors.py walks every selector and prints what resolved, what is absent and what broke, along with browser, driver, page language and the earn section ids. Absent is a normal result for a task a variant does not ship. It completes no activities and claims nothing, so it is safe to run for a bug report.
complete_explore_on_bing_tasks now raises when the section is missing instead of returning quietly, which made complete_all_tasks print [OK] for a task that never ran.
The visible labels the lookups match on are collected in one Labels class. The selectors are market independent but still language dependent, and this makes that explicit and fixable in one place.
Absolute XPaths break outside en-US, where an extra exploreonbing section shifts every positional section index, so every task failed before it started.
Select by visible text, id suffix and visibility instead of position, take the visible copy of ids that are emitted twice for responsive layout, and raise NoSuchElementException for tasks a variant does not ship so the run skips them instead of aborting.