test(RED): expose story view detection gap — ScreenIdentity returns UNKNOWN

Bug evidence from run 2026-04-27_23-46-57:
- Bot started on a story (reel_viewer_media_layout, 'Like Story')
- ScreenIdentity classified it as UNKNOWN
- GOAP chose 'scroll down' 4 times (stories don't scroll)
- Bot was trapped in infinite scroll loop

Captured real XML fixture: story_view_full.xml
1 test FAILS (screen_identity → UNKNOWN instead of STORY_VIEW)
This commit is contained in:
2026-04-27 23:51:04 +02:00
parent c051c3a4c3
commit 2b992cf2a8
2 changed files with 219 additions and 0 deletions

View File

@@ -293,3 +293,73 @@ class TestSAERealFixturePerception:
@pytest.mark.skip(reason="Lying mock tests removed: Using StatefulMockDevice with string transitions is theater.")
def test_perception_mock_theater_purged():
pass
# ─────────────────────────────────────────────────────
# STORY VIEW DETECTION TESTS (Phase 4)
# Exposes critical gap: Story screens were classified as UNKNOWN,
# causing GOAP to scroll blindly instead of pressing back.
# ─────────────────────────────────────────────────────
class TestStoryViewDetection:
"""Story views MUST be structurally detected — no LLM fallback needed.
Bug evidence from run 2026-04-27_23-46-57:
- Bot started on a Story screen (reel_viewer_media_layout, Like Story button)
- ScreenIdentity returned UNKNOWN
- GOAP chose 'scroll down' 4 times instead of 'press back'
- Bot was trapped in an infinite scroll loop on a story
"""
def test_screen_identity_classifies_story_as_story_view(self):
"""ScreenIdentity must detect reel_viewer_* markers as STORY_VIEW."""
from GramAddict.core.perception.screen_identity import ScreenIdentity, ScreenType
si = ScreenIdentity(bot_username="marisaundmarc")
xml = _load_fixture("story_view_full.xml")
result = si.identify(xml)
assert result["screen_type"] == ScreenType.STORY_VIEW, (
f"Story view misclassified as {result['screen_type']}! "
f"Expected STORY_VIEW but ScreenIdentity returned {result['screen_type'].name}."
)
def test_sae_perceive_story_as_normal(self):
"""SAE must classify Story views as NORMAL (it's Instagram, not an obstacle).
The bot's reaction to a Story should be: press back → navigate away.
But first, SAE must NOT flag it as an obstacle.
"""
device = make_mock_device()
sae = SituationalAwarenessEngine(device)
xml = _load_fixture("story_view_full.xml")
result = sae.perceive(xml)
assert result == SituationType.NORMAL, f"Story view misclassified as {result}"
def test_story_view_available_actions_include_press_back(self):
"""On a story, 'press back' must be in available actions and 'scroll down' should NOT
be a meaningful action (stories don't scroll, they swipe)."""
from GramAddict.core.perception.screen_identity import ScreenIdentity, ScreenType
si = ScreenIdentity(bot_username="marisaundmarc")
xml = _load_fixture("story_view_full.xml")
result = si.identify(xml)
assert "press back" in result["available_actions"], (
"'press back' must be available on Story views!"
)
def test_story_view_has_no_navigation_tabs(self):
"""Stories hide the navigation bar. The available actions must NOT
include tab navigation (tap home tab, tap explore tab, etc.)."""
from GramAddict.core.perception.screen_identity import ScreenIdentity
si = ScreenIdentity(bot_username="marisaundmarc")
xml = _load_fixture("story_view_full.xml")
result = si.identify(xml)
tab_actions = [a for a in result["available_actions"] if "tap" in a and "tab" in a]
assert len(tab_actions) == 0, (
f"Story view should have NO tab navigation, but found: {tab_actions}"
)