refactor(perception): Purge legacy coordinate hacks from feed and telepathic engines
This commit is contained in:
@@ -1,101 +0,0 @@
|
||||
"""
|
||||
🔴 RED TDD: DM Structural Guard Self-Sabotage Fix
|
||||
|
||||
Reproduces Bug 2: The intent 'tap direct message icon inbox' is NOT classified
|
||||
as a nav intent, causing the Structural Guard to reject the correct VLM match
|
||||
in the nav bar zone.
|
||||
|
||||
These tests MUST FAIL before the fix and PASS after.
|
||||
"""
|
||||
|
||||
from GramAddict.core.telepathic_engine import TelepathicEngine
|
||||
|
||||
|
||||
class TestNavIntentClassification:
|
||||
"""Verifies that all navigation-related intents are correctly classified."""
|
||||
|
||||
def test_dm_intent_is_classified_as_nav_intent(self):
|
||||
"""
|
||||
The intent 'tap direct message icon inbox' MUST be treated as a nav intent
|
||||
so the structural guard allows clicking elements in the nav bar zone.
|
||||
"""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
# DM icon is in the nav bar zone (top right, but the 'direct tab'
|
||||
# element is at the bottom nav bar on some Instagram layouts)
|
||||
dm_node = {
|
||||
"semantic_string": "description: 'Message', id context: 'direct tab'",
|
||||
"y": int(screen_height * 0.95), # Bottom nav bar zone
|
||||
"area": 3000,
|
||||
"class_name": "android.widget.ImageView",
|
||||
"resource_id": "direct_tab",
|
||||
}
|
||||
|
||||
intent = "tap direct message icon inbox"
|
||||
|
||||
# The node should be viable — it's a nav intent targeting the nav bar
|
||||
is_valid = engine._structural_sanity_check(dm_node, intent, screen_height)
|
||||
|
||||
assert is_valid is True, (
|
||||
"Structural Guard rejected 'direct tab' for DM intent. "
|
||||
"This is the exact bug: 'tap direct message icon inbox' is not classified as nav intent."
|
||||
)
|
||||
|
||||
def test_inbox_intent_is_classified_as_nav_intent(self):
|
||||
"""Variant: 'tap inbox' should also be treated as navigation."""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
inbox_node = {
|
||||
"semantic_string": "description: 'Inbox', id context: 'direct_inbox'",
|
||||
"y": int(screen_height * 0.95),
|
||||
"area": 2500,
|
||||
"class_name": "android.widget.ImageView",
|
||||
"resource_id": "direct_inbox",
|
||||
}
|
||||
|
||||
intent = "tap inbox"
|
||||
|
||||
is_valid = engine._structural_sanity_check(inbox_node, intent, screen_height)
|
||||
assert is_valid is True, "Structural Guard rejected inbox node for 'tap inbox' intent."
|
||||
|
||||
def test_notification_intent_is_classified_as_nav_intent(self):
|
||||
"""'tap heart icon notifications' should also be treated as navigation."""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
notification_node = {
|
||||
"semantic_string": "description: 'Activity', id context: 'notification_tab'",
|
||||
"y": int(screen_height * 0.95),
|
||||
"area": 2500,
|
||||
"class_name": "android.widget.ImageView",
|
||||
"resource_id": "notification_tab",
|
||||
}
|
||||
|
||||
intent = "tap heart icon notifications"
|
||||
|
||||
is_valid = engine._structural_sanity_check(notification_node, intent, screen_height)
|
||||
assert is_valid is True, "Structural Guard rejected notification node for heart icon intent."
|
||||
|
||||
def test_regular_post_intent_still_blocked_in_nav_zone(self):
|
||||
"""
|
||||
Non-nav intents (like 'tap like button') targeting elements in the nav bar
|
||||
zone must STILL be rejected. We're not weakening the guard.
|
||||
"""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
misplaced_like_node = {
|
||||
"semantic_string": "description: 'Like', id context: 'some_like_button'",
|
||||
"y": int(screen_height * 0.95),
|
||||
"area": 2000,
|
||||
"class_name": "android.widget.ImageView",
|
||||
}
|
||||
|
||||
intent = "tap like button"
|
||||
|
||||
is_valid = engine._structural_sanity_check(misplaced_like_node, intent, screen_height)
|
||||
assert is_valid is False, (
|
||||
"Structural Guard allowed a like button in the nav bar zone. " "Non-nav intents should still be blocked."
|
||||
)
|
||||
@@ -1,150 +0,0 @@
|
||||
from GramAddict.core.telepathic_engine import TelepathicEngine
|
||||
|
||||
|
||||
def test_structural_guard_rejects_own_story_for_post_username():
|
||||
"""
|
||||
TDD Test: Reproduces the bug where Telepathic Engine might select the user's
|
||||
OWN profile picture ("Your Story" in the Home Feed tray) when the intent
|
||||
is to tap the post author's username.
|
||||
"""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
# Mock node representing the user's "Your Story" circle at the top
|
||||
# It contains "story" or "your story", has low Y (top of screen)
|
||||
your_story_node = {
|
||||
"semantic_string": "description: 'Your Story', id context: 'row feed photo profile imageview'",
|
||||
"y": 250, # Top story tray
|
||||
"class_name": "android.widget.ImageView",
|
||||
}
|
||||
|
||||
# Intent
|
||||
intent = "tap post username"
|
||||
|
||||
# Expected behavior: Structural sanity check must REJECT this node to prevent
|
||||
# clicking our own story/profile
|
||||
is_valid = engine._structural_sanity_check(your_story_node, intent, screen_height)
|
||||
|
||||
assert is_valid is False, "Structural Guard failed to reject 'Your Story' when looking for 'post username'."
|
||||
|
||||
|
||||
def test_structural_guard_accepts_actual_post_username():
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
actual_post_node = {
|
||||
"semantic_string": "text: 'estherabad9', id context: 'row feed photo profile name'",
|
||||
"y": 1200, # Middle of screen (feed post header)
|
||||
"area": 5000,
|
||||
"class_name": "android.widget.TextView",
|
||||
}
|
||||
|
||||
intent = "tap post username"
|
||||
|
||||
is_valid = engine._structural_sanity_check(actual_post_node, intent, screen_height)
|
||||
|
||||
assert is_valid is True, "Structural Guard incorrectly rejected the actual post username."
|
||||
|
||||
|
||||
def test_structural_guard_rejects_own_username_story():
|
||||
"""
|
||||
TDD Test: Reproduces 2026-04-16 23:18 bug where bot selected 'marisaundmarc's story'
|
||||
instead of an unseen story from ANOTHER user.
|
||||
"""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
# Simulate current user is marisaundmarc
|
||||
engine._get_current_username = lambda: "marisaundmarc"
|
||||
|
||||
# Mock node representing the user's OWN story, which contains their username
|
||||
own_story_node = {
|
||||
"semantic_string": "description: 'marisaundmarc\\'s story, 0 of 27, Unseen.', id context: 'avatar image view'",
|
||||
"y": 250, # Top story tray
|
||||
"class_name": "android.widget.ImageView",
|
||||
}
|
||||
|
||||
intent = "profile picture avatar story ring"
|
||||
|
||||
# Should reject the user's own profile because clicking it means we edit/view our own story
|
||||
# instead of doing interactions with prospects.
|
||||
is_valid = engine._structural_sanity_check(own_story_node, intent, screen_height)
|
||||
|
||||
assert is_valid is False, "Structural Guard failed to reject the bot's OWN username story."
|
||||
|
||||
|
||||
def test_structural_reels_first_grid_item_y_coords():
|
||||
"""
|
||||
TDD Test: Reels viewer layout has grid items that are structurally valid.
|
||||
Ensures that relative Y coordinates (percentage of screen height) correctly
|
||||
allow valid grid items and block hallucinations.
|
||||
"""
|
||||
engine = TelepathicEngine()
|
||||
screen_height = 2400
|
||||
|
||||
# Valid first grid item in a profile's reel tab, usually around y=700 to 1200
|
||||
valid_grid_node = {
|
||||
"semantic_string": "description: 'reel, 1 of 20', id context: 'image button'",
|
||||
"y": 800, # well within safe zone, ~33%
|
||||
"area": 40000,
|
||||
"class_name": "android.widget.ImageView",
|
||||
}
|
||||
|
||||
# Hallucinated navigation tab node pretending to be "Home" around y=1200 (middle of screen)
|
||||
hallucinated_nav_node = {
|
||||
"semantic_string": "description: 'Home', id context: 'tab'",
|
||||
"y": 1200, # 50% height
|
||||
"area": 1000,
|
||||
"class_name": "android.view.View",
|
||||
}
|
||||
|
||||
intent_grid = "first grid item"
|
||||
intent_nav = "tap home tab"
|
||||
|
||||
is_valid_grid = engine._structural_sanity_check(valid_grid_node, intent_grid, screen_height)
|
||||
assert is_valid_grid is True, "Structural Guard rejected a valid reels grid item."
|
||||
|
||||
# The hallucinated nav node should be rejected because navigation tabs belong at the bottom!
|
||||
# Currently it might fail if we don't have relative coordinate checks!
|
||||
is_valid_nav = engine._structural_sanity_check(hallucinated_nav_node, intent_nav, screen_height)
|
||||
assert (
|
||||
is_valid_nav is False
|
||||
), "Structural Guard failed to reject a hallucinated navigation tab in the middle of the screen."
|
||||
|
||||
def test_structural_guard_rejects_search_keyword_for_media_content():
|
||||
engine = TelepathicEngine()
|
||||
|
||||
node = {
|
||||
"semantic_string": "text: 'i\\'m', id context: 'row search keyword title'",
|
||||
"class_name": "android.widget.TextView",
|
||||
"y": 500
|
||||
}
|
||||
|
||||
is_valid = engine._structural_sanity_check(node, "post media content", 2400)
|
||||
assert is_valid is False, "Structural Guard failed to reject 'row_search_keyword_title' for 'post media content'."
|
||||
|
||||
|
||||
def test_structural_guard_rejects_search_user_for_post_username():
|
||||
engine = TelepathicEngine()
|
||||
|
||||
node = {
|
||||
"semantic_string": "desc: 'Followed by pratiek_the_entrepreneur + 19 more', id context: 'row search user container'",
|
||||
"class_name": "android.widget.LinearLayout",
|
||||
"y": 800
|
||||
}
|
||||
|
||||
is_valid = engine._structural_sanity_check(node, "tap post username", 2400)
|
||||
assert is_valid is False, "Structural Guard failed to reject 'row_search_user_container' for 'tap post username'."
|
||||
|
||||
|
||||
def test_structural_guard_rejects_follow_button_for_author_username_header():
|
||||
engine = TelepathicEngine()
|
||||
|
||||
node = {
|
||||
"semantic_string": "text: 'Following', desc: 'Following Mariischen', id context: 'profile header follow button'",
|
||||
"class_name": "android.widget.Button",
|
||||
"y": 600
|
||||
}
|
||||
|
||||
is_valid = engine._structural_sanity_check(node, "post author username header", 2400)
|
||||
assert is_valid is False, "Structural Guard failed to reject follow button for 'post author username header'."
|
||||
Reference in New Issue
Block a user