fix: Tab Height Guard false-positive on author intent with 'tab' substring

Production bug 2026-05-02 22:19:
Intent 'post author username text (exclude bottom tabs)' contained the
word 'tab' in its parenthetical qualifier. The old check:
    is_tab_intent = 'tab' in intent_lower
matched this intent as a TAB navigation intent, activating the Tab
Height Guard which excluded ALL nodes with center_y < 85% of screen.

This nuked the actual clips_author_username node at y=2012, leaving
only 4 irrelevant items for the VLM → bot stuck in a loop unable to
find the author username.

Fix: Replace substring match with precise regex patterns that only
match real tab navigation intents:
  - 'tap profile tab', 'tap home tab' (tap + word + tab)
  - 'profile tab', 'explore tab' (word + tab)
  - 'tab ...' at start of intent

TDD: Red test added first, reproducing exact production state.
81 perception tests + 172 total tests pass.
This commit is contained in:
2026-05-02 22:28:03 +02:00
parent f6f15ebd9a
commit cff7e976e0
2 changed files with 53 additions and 3 deletions

View File

@@ -61,10 +61,22 @@ class IntentResolver:
"""
intent_lower = intent_description.lower()
# Only apply for tab-related intents OR generic interaction intents
# We want to aggressively protect against clicking 'Create' / 'Camera' / 'Back' by accident
# Only apply for REAL tab navigation intents.
# REGRESSION FIX 2026-05-02: "tab" as a substring was too broad.
# Intent "post author username text (exclude bottom tabs)" matched
# because it contained "tab" → Tab Height Guard nuked the author node.
# Now we require specific tab navigation patterns:
# - "tap profile tab", "tap home tab", "explore tab"
# - NOT "exclude bottom tabs", "tabbar", random mentions
import re
_TAB_PATTERN = re.compile(
r"\btap\s+\w+\s+tab\b" # "tap profile tab", "tap home tab"
r"|\b\w+\s+tab\b" # "profile tab", "explore tab"
r"|^tab\b", # "tab" at start of intent
re.IGNORECASE,
)
filtered = []
is_tab_intent = "tab" in intent_lower and "back" not in intent_lower
is_tab_intent = bool(_TAB_PATTERN.search(intent_lower)) and "back" not in intent_lower
is_create_intent = "create" in intent_lower or "camera" in intent_lower or "story" in intent_lower
# REGRESSION FIX 2026-05-01: Author/username intents must never pick nav tabs
is_author_intent = any(kw in intent_lower for kw in ["author", "username", "post media"])

View File

@@ -295,6 +295,44 @@ class TestStructuralGuards:
author_nodes = [n for n in filtered if n.text == "photographer_jane"]
assert len(author_nodes) == 1
def test_author_intent_with_exclude_tabs_suffix_preserves_author(self):
"""
Production bug 2026-05-02 22:19: Intent 'post author username text
(exclude bottom tabs)' contains the word 'tab', which falsely
triggers the Tab Height Guard. This nukes the actual author node
(clips_author_username at y=2012) because 2012 < 85% of 2400.
The fix: is_tab_intent must only match REAL tab navigation intents,
not intents that mention 'tab' in a parenthetical exclusion note.
"""
candidates = [
_make_node(
resource_id="com.instagram.android:id/clips_author_username",
content_desc="trenny_m",
center_y=2012,
),
_make_node(
resource_id="com.instagram.android:id/profile_tab",
content_desc="Profile",
center_y=2350,
),
_make_node(
resource_id="com.instagram.android:id/like_button",
content_desc="Like",
center_y=1353,
),
]
filtered = self.resolver.filter_navigation_conflicts(
candidates, "post author username text (exclude bottom tabs)",
screen_height=2400,
)
# The author username at y=2012 MUST survive
author_nodes = [n for n in filtered if n.content_desc == "trenny_m"]
assert len(author_nodes) == 1, (
f"Author node 'trenny_m' was incorrectly filtered out! "
f"Remaining: {[(n.resource_id, n.content_desc) for n in filtered]}"
)
# ── Structural Fast-Paths ──
def test_fast_path_message_input(self):