ROOT CAUSE:
The bot would permanently softlock itself on UNKNOWN screens (like Trending Audio/Reels)
because 'is_trap' had NO time-decay, and UNKNOWN screen traps persisted forever.
Once 'press back' was trapped on an UNKNOWN screen, the bot was permanently blocked
from escaping any future UNKNOWN screen, causing endless restart loops.
FIXES:
1. Trap Time-Decay: 'is_trap' now forgives Qdrant-persisted traps older than 30 minutes.
This mirrors ContextMemory and prevents permanent dead-ends.
2. UNKNOWN Guard: 'learn_trap' now REFUSES to persist traps for UNKNOWN screens to Qdrant.
They only live in-memory to prevent breaking global navigation.
3. In-Memory Purge: 'force start instagram' now properly calls 'clear_traps()' to wipe
the planner's in-memory traps. Previously they survived restarts, immediately
re-trapping the bot.
Purged 6 ancient traps from Qdrant (one was 8 days old!).
TDD: 3 new tests, full suite 113/114 (1 infra flake)
FOLLOW PLUGIN SAFETY GUARD:
- Added pre-click XML guard: checks button text before clicking
- If button says 'Following'/'Requested'/'Message' → SKIP
(prevents opening dangerous Unfollow/Add-to-Favorites bottom sheet)
- Changed intent from 'tap Follow or Following button' to 'tap follow button'
- This was the root cause of adding users to Close Friends/Favorites
VLM VERIFICATION RESILIENCE:
- VLM false no longer shortcircuits to return False
- VLM verdict is now a SOFT SIGNAL that falls through to structural
delta verification as ground-truth tiebreaker
- Small local VLMs (7B llava) systematically return false for everything
- This was THE root cause of memory poisoning: every action got penalized
because VLM always said 'failed', regardless of actual screen state
- 22 total poisoned Qdrant entries purged across two sessions
ROOT CAUSE CHAIN:
VLM always says false → penalties on every action → confidence < 0.2 →
circuit breaker blocks ALL core actions → bot can't like/follow/comment
→ bot clicks random things → adds to favorites, opens bottom sheets
TDD: 4 new tests, full suite 110/111 (1 infra flake)
CLOSE FRIENDS GUARD:
- Replaced broken text-only detection ('enge freunde'/'close friend')
with STRUCTURAL resource-id marker detection:
* friendly_bubbles_component (feed posts)
* profile_header_close_friend (profile view)
* close_friends_badge (Reels)
* close_friends_star (green star)
- Kept legacy text fallback for edge cases
- TDD: 5 tests including meta-test enforcing structural detection
CONTEXT MEMORY CIRCUIT BREAKER:
- Old system: single failure permanently blocks action (confidence < 0.2 = dead)
- New system: time-based decay — failures older than 1 hour are auto-forgiven
and the poisoned entry is DELETED, allowing re-exploration
- This prevents catastrophic self-sabotage where the bot blocks its own
core actions (tap like, tap follow, tap comment) permanently
- Purged 14 poisoned entries from live Qdrant that were blocking ALL
fundamental interactions
- TDD: 2 meta-tests enforcing time-decay and no permanent blocking
Full suite: 106/107 passed (1 infra flake)
- Removed hardcoded (540,150) fallback in _plan_escape_via_llm
- Added _find_structural_dismiss_target: scans raw XML for clickable
dismiss/cancel/close buttons and extracts coords from bounds attrs
- LLM repeat detection now falls back to structural scan (not magic numbers)
- Temperature increases progressively when LLM is stubborn (0.1 → 0.7)
- Failure history injected as CRITICAL block into LLM system prompt
- Extended pre-commit test discovery to include tests/tdd/
- TDD: 7 new tests including meta-tests proving zero hardcoded coords
- Full suite: 100/100 passed
1. Add long_clickable and class_name to SpatialNode and box_legend.
2. Inject strict guardrails into the SoM prompt to prevent EditText, Recents gallery, and long_clickable hallucinations.
3. Update text-based resolver with equivalent extreme fallback rules.
4. Ensures VLM explicitly rejects non-deterministic edge cases (e.g., Select Album).
- 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.
- Fixed .gitignore to correctly handle __pycache__ even when inside whitelisted directories (like tests/).
- Moved pycache ignore patterns to the end of the file to ensure they take absolute precedence over any directory-level whitelists.
- Purged all previously tracked .pyc and __pycache__ files from the git index.
- Cleaned up .hypothesis and .pytest_cache artifacts.
This enforces 'Militärische Git-Disziplin' (Rule 7) and keeps the repo clean of environment-specific junk.
- 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
- device_emulator.py: Replace MagicMock(watcher) with explicit WatcherStub
that implements exact u2 watcher chain (when/click/start). Any API drift
now causes AttributeError instead of silent acceptance.
- test_system_sae.py: Inject XML into emulator state instead of bypassing
dump_hierarchy with lambda
- test_behavior_ad_guard.py: Pass XML to fixture, remove lambda override
- test_behavior_scrape_profile.py: Pass XML to fixture, remove lambda override
Result: ZERO unittest.mock imports, ZERO MagicMock instances,
ZERO dump_hierarchy lambdas across entire E2E suite (50 files).