refactor(perception): Purge legacy coordinate hacks from feed and telepathic engines

This commit is contained in:
2026-04-29 09:54:02 +02:00
parent 4e91db01c9
commit 6abb519e3b
4 changed files with 4 additions and 278 deletions

View File

@@ -64,8 +64,8 @@ def extract_post_content(context_xml: str) -> dict:
# 1. Learn/extract post author dynamically
author_node = telepath.find_best_node(context_xml, "post author username header", min_confidence=0.75)
# 🛡️ Anti-Hallucination Guard: The author header is always near the top. Ignore names in the comment section.
if author_node and author_node.get("y", 0) < 1000 and author_node.get("original_attribs", {}).get("text"):
# 🛡️ Anti-Hallucination Guard: Ensure we actually found text.
if author_node and author_node.get("original_attribs", {}).get("text"):
result["username"] = author_node["original_attribs"]["text"].strip()
# 2. Learn/extract post media description dynamically

View File

@@ -128,7 +128,6 @@ class TelepathicEngine:
nodes = self._parser.get_clickable_nodes(root)
return [self._translate_node(n) for n in nodes]
# ──────────────────────────────────────────────
# Action Memory Delegation
# ──────────────────────────────────────────────
@@ -202,31 +201,9 @@ class TelepathicEngine:
y = node.get("y", 0)
semantic = (node.get("semantic_string", "") or "").lower()
# 1. Navigation Tab Guard (Must be at the bottom)
nav_intents = [
"tap direct message icon inbox",
"tap inbox",
"tap heart icon notifications",
"tap home tab",
"tap explore tab",
"tap reels tab",
"tap profile tab",
"tap messages tab",
]
is_nav_intent = any(n in intent for n in nav_intents)
if is_nav_intent:
if y < screen_height * 0.85:
return False
return True
# 2. Block non-nav intents from clicking in the nav zone
if y >= screen_height * 0.85:
# Not a nav intent, but trying to click the nav bar
return False
# 3. Post Username Guard
# 1. Post Username Guard
if "post username" in intent:
if "story" in semantic and y < screen_height * 0.2:
if "story" in semantic:
# E.g. "Your Story" circle at the top
return False
# Prevent tapping a search list item when looking for a post username

View File

@@ -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."
)

View File

@@ -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'."