fix: keep interactive nodes in snapshot -c; better stale-ref guidance (issue #2/#3)

- snapshot -c (compact) now always keeps lines with an interactive ARIA role
  (button/link/textbox/combobox/option/…), not only `ref=`/`": "` lines — so a
  clickable control can't vanish from compact output and leave the agent clicking
  an empty ref (issue #2 P1). Additive: only ever keeps more. compact tests green.
- stale-ref error now leads with "take a fresh snapshot" and points to the `eval`
  fallback for ref-churning SPAs, and demotes AGENT_BROWSER_VERIFY_REF=0 to a
  flagged last resort instead of presenting it as the fix (issue #3 P1).
This commit is contained in:
leeguooooo
2026-06-11 23:15:37 +09:00
parent d7a0ed85f9
commit 3ac69e822a
2 changed files with 40 additions and 3 deletions
+34 -1
View File
@@ -1305,6 +1305,39 @@ fn render_tree(
}
}
/// True if a snapshot line names an interactive ARIA role. Compaction keeps
/// these even without a `ref=`/`": "` marker, so a clickable control never gets
/// dropped from `-c` output (the dogfood reports saw a button present in the full
/// snapshot vanish from compact, leaving the agent clicking an empty ref).
fn is_interactive_line(line: &str) -> bool {
const ROLES: &[&str] = &[
"button",
"link",
"textbox",
"checkbox",
"radio",
"combobox",
"listbox",
"menuitem",
"menuitemcheckbox",
"menuitemradio",
"option",
"switch",
"slider",
"spinbutton",
"searchbox",
"tab ",
"clickable",
"focusable",
"editable",
];
let t = line.trim_start();
// Lines look like `- button "Label" [ref=e1]`; match the role token after the
// leading "- " marker.
let t = t.strip_prefix("- ").unwrap_or(t);
ROLES.iter().any(|r| t.starts_with(r))
}
fn compact_tree(tree: &str, interactive: bool) -> String {
let lines: Vec<&str> = tree.lines().collect();
if lines.is_empty() {
@@ -1314,7 +1347,7 @@ fn compact_tree(tree: &str, interactive: bool) -> String {
let mut keep = vec![false; lines.len()];
for (i, line) in lines.iter().enumerate() {
if line.contains("ref=") || line.contains(": ") {
if line.contains("ref=") || line.contains(": ") || is_interactive_line(line) {
keep[i] = true;
// Mark ancestors
let my_indent = count_indent(line);