From 2b992cf2a89e68006824a1ce0ee7d383d9a3e20f Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Mon, 27 Apr 2026 23:51:04 +0200 Subject: [PATCH] =?UTF-8?q?test(RED):=20expose=20story=20view=20detection?= =?UTF-8?q?=20gap=20=E2=80=94=20ScreenIdentity=20returns=20UNKNOWN?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- tests/e2e/test_engine_perception.py | 70 +++++++++++++ tests/fixtures/story_view_full.xml | 149 ++++++++++++++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 tests/fixtures/story_view_full.xml diff --git a/tests/e2e/test_engine_perception.py b/tests/e2e/test_engine_perception.py index 871014f..f599d90 100644 --- a/tests/e2e/test_engine_perception.py +++ b/tests/e2e/test_engine_perception.py @@ -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}" + ) diff --git a/tests/fixtures/story_view_full.xml b/tests/fixtures/story_view_full.xml new file mode 100644 index 0000000..d1d25a4 --- /dev/null +++ b/tests/fixtures/story_view_full.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file