Defect
9a80450 fixed a real bug in packages/browser-control/src/task/CDPBrowserBackend.ts: buildNode returned null for any node whose role is in IGNORED_ROLES (:62 — "none", "generic", "ignored", "InlineTextBox") or that CDP marked ignored, and dropped its whole subtree. Chrome hangs a document off one or two such wrappers, so BrowserSnapshotTask returned a near-empty tree for most real pages. The fix is right, and the reasoning is stated at :95-99.
The new buildNodes (:101-118) returns an array and splices a meaningless node's children in where it stood. But the single caller does this — :175:
const built = buildNodes(rootNode)[0];
When rootNode is itself one of those wrappers, buildNodes returns N spliced children and [0] keeps the first, silently discarding the other N−1. That is precisely the case the change exists to handle: the old code could not hit it (it returned one node or null), the new code can.
rootNode is picked at :88-92 as the node no other node claims as a child (nodes.find((n) => !childIds.has(n.nodeId)) ?? nodes[0]), so it is whatever the CDP payload happens to root at — not guaranteed to be a RootWebArea.
Evidence
packages/browser-control/src/task/CDPBrowserBackend.ts:62 — IGNORED_ROLES
packages/browser-control/src/task/CDPBrowserBackend.ts:101-118 — buildNodes returns MutableAccessibilityNode[]
packages/browser-control/src/task/CDPBrowserBackend.ts:175 — buildNodes(rootNode)[0]
No test covers it, because there are none: find packages/browser-control -name "*.test.ts" → 0, and grep -rln "parseCDPAXTree\|queryAXTree" packages/test/src --include=*.test.ts → nothing.
Proposed fix
const built = buildNodes(rootNode);
if (built.length === 1) return built[0] as AccessibilityNode;
if (built.length > 1) {
const ref = `e${++refCounter.count}`;
refMap.set(ref, null);
return { ref, role: "document", name: "", children: built };
}
// existing empty-tree fallback
…plus the first test in this package: a recorded Accessibility.getFullAXTree payload rooted at a generic wrapper with two meaningful children, asserting both survive. That fixture needs no browser and would also have caught the original subtree-dropping bug.
Why it matters
BrowserSnapshotTask's output is the only thing an agent sees of a page. Losing a sibling subtree is invisible — the snapshot looks plausible, just smaller — and there is no detector anywhere in the repo (see #875 and #701 for why the surrounding tests do not run).
Found during the 2026-08-31 review. Snapshot: workglow-dev/prd → analysis/grades/2026-08-31/libs-providers.md.
Defect
9a80450fixed a real bug inpackages/browser-control/src/task/CDPBrowserBackend.ts:buildNodereturnednullfor any node whose role is inIGNORED_ROLES(:62—"none","generic","ignored","InlineTextBox") or that CDP markedignored, and dropped its whole subtree. Chrome hangs a document off one or two such wrappers, soBrowserSnapshotTaskreturned a near-empty tree for most real pages. The fix is right, and the reasoning is stated at:95-99.The new
buildNodes(:101-118) returns an array and splices a meaningless node's children in where it stood. But the single caller does this —:175:When
rootNodeis itself one of those wrappers,buildNodesreturns N spliced children and[0]keeps the first, silently discarding the other N−1. That is precisely the case the change exists to handle: the old code could not hit it (it returned one node ornull), the new code can.rootNodeis picked at:88-92as the node no other node claims as a child (nodes.find((n) => !childIds.has(n.nodeId)) ?? nodes[0]), so it is whatever the CDP payload happens to root at — not guaranteed to be aRootWebArea.Evidence
packages/browser-control/src/task/CDPBrowserBackend.ts:62—IGNORED_ROLESpackages/browser-control/src/task/CDPBrowserBackend.ts:101-118—buildNodesreturnsMutableAccessibilityNode[]packages/browser-control/src/task/CDPBrowserBackend.ts:175—buildNodes(rootNode)[0]No test covers it, because there are none:
find packages/browser-control -name "*.test.ts"→ 0, andgrep -rln "parseCDPAXTree\|queryAXTree" packages/test/src --include=*.test.ts→ nothing.Proposed fix
…plus the first test in this package: a recorded
Accessibility.getFullAXTreepayload rooted at agenericwrapper with two meaningful children, asserting both survive. That fixture needs no browser and would also have caught the original subtree-dropping bug.Why it matters
BrowserSnapshotTask's output is the only thing an agent sees of a page. Losing a sibling subtree is invisible — the snapshot looks plausible, just smaller — and there is no detector anywhere in the repo (see #875 and #701 for why the surrounding tests do not run).Found during the 2026-08-31 review. Snapshot:
workglow-dev/prd→analysis/grades/2026-08-31/libs-providers.md.