- Updated e2e_workflow_ctx in conftest to structurally parse screen_type
- Fixed StoryViewPlugin to gracefully handle pre-existing story screens
- Resolved 'LIE DETECTED' failure in story test suite
- Validated structural path transitions for story ring and story exit
P0-2: Kill blank_start: true in config — the nuclear option that wipes ALL learned
knowledge on every run. Replaced with memory_hygiene() selective amnesia that
prunes low-confidence entries while preserving high-confidence learned patterns.
P0-3: Purge all root-level garbage scripts (scratch.py, test_run.py, profile_dump.xml,
resp_dump.json, pytest_output.log, test_output.log, coverage.xml, coverage_e2e.json).
Updated .gitignore to prevent reaccumulation.
P2-2: Replace piecemeal BANNED_SCREENS/REQUIRED_MARKERS with complete Action
Compatibility Matrix (VALID_SCREENS whitelist). Every interaction intent now has
an explicit set of valid screens. Covers like, comment, follow, unfollow, save,
repost across all 14 screen types.
P2-3: Remove non-deterministic 'press back' transitions from HD Map topology for
OTHER_PROFILE, POST_DETAIL, and SEARCH_RESULTS. Add tab transitions to POST_DETAIL.
P2-4: Replace ScreenMemoryDB nuclear 200-entry wipe with LRU eviction.
store_screen() now accepts confidence parameter.
TDD: 22 new tests (all GREEN), 240 unit/tdd/integration passed, 0 regressions.
E2E: 288 passed (+2 fixed), 6 pre-existing LIE DETECTED failures.
- Raised ContentMemoryDB cache threshold from 0.95 to 0.98 to prevent cross-post poisoning.
- Implemented continuous resonance scoring by storing and retrieving 'resonance_score'
in ContentMemoryDB.
- ResonanceEngine now prioritizes high-fidelity raw scores from cache over
discrete 'high/medium/low' mapping.
TDD: 3 tests verifying threshold and scoring logic integrity.
- Raised similarity_threshold from 0.90 to 0.95 in get_screen_type() to eliminate
POST_DETAIL false-positives caused by embedding saturation.
- Implemented purge_stale_screens() with 24h TTL to remove layout drift.
- Added collection size cap (200 points) to store_screen() with automatic wipe
when saturated to clear overfitting bias.
- Triggered purge_stale_screens() on ScreenIdentity initialization.
TDD: 3 new tests for threshold defaults and purge method integrity.
1. ScreenIdentity: Restructured priority cascade to prevent Qdrant semantic
cache from overriding deterministic structural heuristics. Cached types
now resolve AFTER structural checks (Priority 3) instead of before.
Story/Reels hallucinations from both cache and VLM are rejected if
structural markers are absent.
2. bot_flow: Added error handling for story ring avatar tap and curiosity
HomeFeed navigation failures — prevents silent continuation into
undefined states.
3. GOAP: Extended is_navigation detection to include ScreenTopology
structural actions, ensuring HD Map routes are correctly classified.
4. action_memory: Tightened _parse_yes_no to prevent JSON fall-through
into ambiguous text matching. Structured responses with 'success'
boolean are now handled directly.
The SAE perceive() had no structural fast-path for Instagram-internal
modal overlays (surveys, rating prompts, interstitials). These modals
live inside com.instagram.android and were invisible to the foreign-app
detector. The LLM fallback frequently misclassified them as NORMAL,
causing the bot to get trapped in survey dialogs.
Added two O(1) structural detection layers:
1. Resource-ID markers: survey_overlay_container, interstitial_container,
mystery_interstitial, nux_overlay, rating_prompt, feedback_dialog
2. Dismiss-button heuristic: cross-validates dismiss text with overlay
container structure to prevent caption false positives
Also removed dead code: xml_dump.lower() no-op.
Fixes: test_perceive_instagram_survey_modal
Zero regressions: 464 passed, 6 pre-existing failures
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.
Root cause: bot_flow.py injected configs.args.global_start_time = datetime.now()
which polluted the args namespace. SessionStateEncoder blindly serialized
args.__dict__ via json.dump, which crashed mid-write on the datetime object,
leaving sessions.json truncated/corrupt. Every subsequent restart failed.
Fixes:
- Remove global_start_time from configs.args (only lives on engine class vars)
- Harden SessionStateEncoder with _sanitize_value() to convert any
non-JSON-serializable type (datetime, timedelta, arbitrary objects) to strings
- Add test_system_session_persistence.py with 4 tests covering the exact
production crash scenario (datetime injection → json.dumps → round-trip)
- Fix test_engine_timeout.py broken GoalExecutor module reference
Bug 1 — VLM Profile Tab Hallucination:
- VLM confused 'Profile' nav tab with post author username
- Added Author Tab Guard to filter_navigation_conflicts()
- Fixed mock LLM to use structural row_feed_photo_profile matching
instead of hardcoded username (was the test lie)
Bug 2 — Like Button 1-Byte Delta Kill:
- Toggle actions (like/save) produce 1-byte XML deltas
- GOAP's MIN_UI_CHANGE_BYTES=50 threshold killed them as 'no change'
- Split interaction gate: interactions use ANY xml diff, navigations
keep the 50-byte threshold
Bug 3 — Empty Username Silently Accepted:
- PostDataExtraction returned 'Post by @' with no warning
- Added 'username_missing' reliability flag to result dict
- Downstream consumers can now detect degraded data quality
Cleanup:
- Removed all debug print() statements from production code
- Replaced with structured logger.debug() calls
PRODUCTION BUG 2026-04-30 11:50:
VLM returned action_bar_button_back (desc='Back') for 'tap profile tab'
intent on OTHER_PROFILE screen. This caused account_switcher to navigate
AWAY from the profile instead of opening the account selector bottom
sheet, halting the session.
Root cause: _visual_discovery pre-filter did not exclude navigation
buttons (Back, Close) when the intent was for a tab element.
Fix:
- Added filter_navigation_conflicts() method to IntentResolver
- Guards tab intents by excluding nodes with 'back' in resource_id
or content_desc == 'Back'
- Does NOT apply for 'tap back button' or 'press back' intents
TDD:
- RED: test_intent_resolver_back_guard.py — 2 tests that call
filter_navigation_conflicts on real OTHER_PROFILE XML
- GREEN: filter_navigation_conflicts method + wired into _visual_discovery
- E2E: test_workflow_account_switch.py, test_workflow_vlm_tab_confusion.py
31/31 tests passing.
🔴 RED: Tests proved obstacle_guard silently ignored system permission dialogs
and foreign app overlays, causing the bot to get stuck on Android modals.
🟢 GREEN: obstacle_guard now dismisses OBSTACLE_SYSTEM and OBSTACLE_FOREIGN_APP
with immediate back-press, preventing the interaction chain from running
against non-Instagram UI elements.
🔵 REFACTOR: Fixed broken import in resonance_evaluator (was importing
humanized_scroll from utils instead of physics.humanized_input).
- Resolved Bug #5: Fixed list vs str parsing in ResonanceEvaluator
- Resolved Bug #6: Use 'should_like' key for vibe score
- Resolved Bug #7: Guard TelepathicEngine against 'Follow' nodes for post media
- Resolved Bug #8: Implemented failed_bounds exclusion loop breaker in PerfectSnapping
- Resolved Bug #10: Corrected available_actions string parsing
- Validated with E2E regression suite (100% green)
🔴 RED → 🟢 GREEN for 4 critical bugs found in production run 2026-04-29:
1. ResonanceEvaluator: Add null-guard for evaluate_post_vibe() return.
When VLM returns truncated JSON, the function returns None. The caller
now handles this gracefully instead of crashing with AttributeError.
2. ScreenIdentity POST_DETAIL: Replace broken 'and not selected_tab'
condition with structural differentiator using main_feed_action_bar.
Posts opened from feed retain feed_tab selected, which was causing
misclassification as HOME_FEED → LLM fallback → OWN_PROFILE hallucination
→ permanent Qdrant cache poisoning.
3. ActionMemory VLM verification: When VLM returns JSON instead of YES/NO,
treat as inconclusive (fall through to structural delta) rather than
hard failure. Only return False when response explicitly contains 'no'.
4 new E2E regression tests, 75/75 pass, zero regressions.
- GrowthBrain.select_task() uses weighted random from concrete Task objects
- Removed self.goals from Config (no longer reads goals: from config.yml)
- Mission + plugins are now the SSOT for bot behavior
The bot no longer receives abstract strings like 'Nurture my community' that
the LLM Brain can't operationalize. Instead, the GoalDecomposer generates
Task(browse_feed, HomeFeed, budget=7) which routes to concrete feed loops.
18/18 TDD tests passing.
Introduces the GoalDecomposer class that bridges mission.strategy + plugin
capabilities into concrete, weighted Task objects. Each Task has a target
screen, budget, weight, and human-readable intent.
Key design decisions:
- Pure logic, zero LLM/device dependencies
- Strategy weights (aggressive_growth, community_builder, etc.) drive selection
- Plugins declare which screens they operate on (multi-screen map)
- Screens need BOTH an action route AND active plugin to be viable
- Frozen dataclass ensures Task immutability
12/12 TDD tests passing.
Removed the hardcoded structural fallback bypasses for bottom navigation tabs to ensure 100% autonomous visual inference. Expanded the VLM intent resolution prompt with explicit spatial heuristics for bottom navigation (e.g., 'profile tab is the avatar icon at the bottom right') to prevent LLaVA hallucinations without resorting to XML resource-id hacks. Added E2E visual test proof.