feat: progressive skeleton traversal with ref-rooted drill-down#20
feat: progressive skeleton traversal with ref-rooted drill-down#20
Conversation
Add children_count, root_ref, skeleton fields to core types. Add get_subtree() to PlatformAdapter trait. Add remove_by_root_ref() and write-side size check to RefMap. No behavioral changes yet.
…down Add --skeleton and --root flags to snapshot command for token-efficient accessibility tree exploration. Skeleton mode clamps depth to 3 levels and annotates truncated containers with children_count, allowing AI agents to discover regions before drilling into them. Named containers at skeleton boundaries (via name or description) receive refs as drill-down targets. The --root flag starts traversal from a previous ref with scoped invalidation — only refs from that drill-down are replaced on re-drill. Key changes: - New ref_alloc.rs: shared ref helpers (INTERACTIVE_ROLES, actions_for_role, ref_entry_from_node, is_collapsible) extracted from snapshot.rs - New snapshot_ref.rs: drill-down logic with DrillDownConfig, scoped invalidation via root_ref tagging on RefEntry - macOS count_children() uses raw CFArrayGetCount without materializing AXElement wrappers for performance at skeleton boundaries - RefMap write-side size check prevents >1MB files - Skeleton anchors consider both name and description for Electron compat
Add skeleton traversal as Phase 1 objective P1-O10. Document --skeleton and --root flags, get_subtree() trait method, new core modules, and platform-agnostic notes for Phase 2/3. Update risk mitigations and performance optimizations table.
Update SKILL.md observe-act loop to skeleton-first approach. Add progressive skeleton traversal as the primary workflow pattern. Update anti-patterns, key principles, and command quick reference to lead with --skeleton + --root. Full snapshot remains documented as fallback for simple apps.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Free Tier Details
You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
Autofix Details
Bugbot Autofix prepared fixes for both issues found in the latest run.
- ✅ Fixed:
count_childrendisagrees withcopy_childrenchild source- Shared the macOS child-attribute selection between counting and traversal so skeleton anchors use the same child source as drill-down.
- ✅ Fixed: Missing
children_countguard in drill-down interactive filter- Added the missing
children_countguard in drill-down pruning and covered it with a regression test for truncated containers.
- Added the missing
Skeleton snapshots now load the existing refmap and remove only skeleton-level refs (root_ref: None), preserving drill-down refs accumulated via --root. Previously, build() always created a fresh RefMap, breaking the skeleton → drill → act → skeleton(verify) workflow by wiping all drill-down refs on the verify step.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Skeleton depth clamp silently truncates drill-down results
- Snapshot drill-downs now keep the requested max depth even when
--skeletonis also set, preventing silent subtree truncation.
- Snapshot drill-downs now keep the requested max depth even when
| args.max_depth.min(3) | ||
| } else { | ||
| args.max_depth | ||
| }; |
There was a problem hiding this comment.
Skeleton depth clamp silently truncates drill-down results
Medium Severity
When --skeleton and --root @ref are both passed, the effective_depth clamp to min(max_depth, 3) applies unconditionally before the root_ref branch is taken. The clamped opts.max_depth is then sent to get_subtree, which hardcodes skeleton: false. This means the drill-down tree gets silently capped at 3 levels deep with no children_count annotations to explain the truncation — children beyond depth 3 just vanish. The depth clamp should not apply when --root is set, or both flags together should be rejected as invalid.


Summary
--skeletonflag: shallow 3-level overview withchildren_counton truncated containers, giving AI agents a high-level map before drilling into specific regions--root @refflag: start traversal from a previously-discovered ref instead of window root, with scoped invalidation (only that ref's subtree refs are replaced on re-drill)descriptionfromaria-label)New files
crates/core/src/ref_alloc.rs— shared ref-allocation helpers extracted from snapshot.rscrates/core/src/snapshot_ref.rs— drill-down logic withDrillDownConfigand scoped invalidationKey changes
get_subtree()added toPlatformAdaptertrait (defaultnot_supported)count_children()uses rawCFArrayGetCountwithout materializing AXElement wrappers--skeletonTest plan
--root @ref --surface menureturns INVALID_ARGSNote
Medium Risk
Changes snapshot output shape and ref persistence behavior, and adds a new adapter API (
get_subtree) that affects platform implementations. While mostly additive, it can impact downstream consumers expecting prior snapshot/refmap semantics.Overview
Adds progressive skeleton traversal to
snapshot:--skeletonclamps traversal depth (to 3) and emitschildren_counton truncated containers, while--root @refre-snapshots a previously discovered container’s subtree and only replaces refs for that root (scoped invalidation).This extends the core model and ref persistence to support drill-down (
AccessibilityNode.children_count,RefEntry.root_ref, refmap pruning, and a 1MB write guard), factors shared ref-allocation intoref_alloc.rs, and introducessnapshot_ref::run_from_refbacked by a newPlatformAdapter::get_subtreemethod (implemented on macOS, including tree-builder updates to count children efficiently). CLI/batch parsing and documentation are updated accordingly, and stale-ref guidance now mentionssnapshot --skeleton.Written by Cursor Bugbot for commit 1ebc865. This will update automatically on new commits. Configure here.