Commit Graph

169 Commits

Author SHA1 Message Date
832eb8d45b feat(ai): integrate Meta AI chip selection for automated commenting
- Updated QNavGraph.do to accept **kwargs and forward them to GOAP.
- Added explicit 'type and post comment' intent handler in GoalExecutor.
- Implemented smart VLM-driven Meta AI tone selection. If 'Supportive', 'Funny', or other Meta AI chips are visible on the comment keyboard, the bot uses the VLM to pick the best tone chip and lets Meta AI write the comment, falling back to manual typing if no chips are found.
2026-05-04 10:39:34 +02:00
a67072eec4 fix(perception): correct device hierarchy method and add TDD guard
- Fixed AttributeError where device.get_hierarchy() was called instead of dump_hierarchy()
- Replaced MagicMock with a real DummyDeviceForKeyboardTest in E2E tests to adhere to the strict mock ban policy.
- Verified TelepathicEngine actively calls device.back() when keyboard is open on non-typing intents.
2026-05-04 10:27:34 +02:00
59ba330029 fix(perception): active keyboard dismiss guard and POST_DETAIL structural share button
- Added active Keyboard Dismiss logic to TelepathicEngine.find_best_node():
  If the keyboard is open and the intent is NOT typing-related (e.g., 'tap post username'),
  the bot automatically issues a back press to close the keyboard and re-fetches the UI state.
- Broadened structural fast-path for 'tap send post button' in IntentResolver to
  also match 'direct_share_button' or 'send'/'share' desc, preventing VLM fallback
  on POST_DETAIL screens (Bug #3).
2026-05-04 10:18:27 +02:00
6f9da50ae2 fix(perception): add keyboard contamination guard to IntentResolver
Production Bug 2026-05-04: VLM clicked comment_composer → keyboard
opened → 30+ keyboard key nodes flooded candidate pool → VLM
hallucinated 'N' as 'tap post username' → cascading failure.

- Extract pre_filter_candidates() from _visual_discovery inline filter
- Add 'inputmethod' package exclusion to filter keyboard nodes at O(1)
- Add has_keyboard_open() detection helper for downstream recovery
- _visual_discovery() delegates to pre_filter_candidates()
- TDD: 4 new tests proving keyboard isolation and share button parity
2026-05-04 10:14:57 +02:00
720841103d purge: remove ALL hardcoded model/URL defaults across 11 modules
TDD cycle (RED → GREEN):

2 new codebase-wide enforcement tests:
- test_no_getattr_with_hardcoded_model_defaults_outside_config
  Catches getattr(args, 'ai_xxx', 'HARDCODED_DEFAULT') anti-pattern
- test_no_bare_localhost_url_string_literals_outside_config
  Catches bare 'localhost:11434' string literals in non-SSOT files

Purged 24 getattr-default violations and 14 bare-URL violations across:
- compiler_engine.py: ai_telepathic_model/url defaults
- screen_identity.py: ai_telepathic_model/url defaults
- intent_resolver.py: ai_telepathic_model/url defaults (2 spots)
- semantic_evaluator.py: ai_telepathic_model/url defaults
- brain.py: ai_model/url defaults
- dm_engine.py: ai_condenser_model/url defaults
- resonance_engine.py: ai_condenser_model/url defaults
- qdrant_memory.py: ai_embedding_model/url defaults
- bot_flow.py: ai_condenser_model/url defaults
- interaction.py: ai_writer_model/url defaults
- llm_provider.py: fallback model/url 'last resort' defaults

Architecture: Config() (config.py) is the SSOT for ALL AI model config.
Every other module reads from Config().args WITHOUT default values.
If Config() is uninitialized, the system crashes (Fail Fast).

Tests: 11 new, 121 passing, 0 regressions
2026-05-04 00:28:40 +02:00
c98e2caaa1 purge: remove ALL hardcoded UI markers + model defaults from SAE
TDD cycle (RED → GREEN):

SAE perceive() — Zero Maintenance:
- Removed ALL hardcoded marker tuples (instagram_modal_markers,
  creation_flow_markers, dismiss_button_patterns, blocked_markers)
- Removed ALL hardcoded model names (llava:latest, qwen3.5:latest)
- Removed ALL hardcoded URLs (localhost:11434)
- Removed naked except blocks with model fallback defaults

New autonomous flow (zero hardcoded UI identifiers):
1. Package-based foreign app detection (Android-level, not app-specific)
2. Qdrant semantic cache (O(1) recall of learned screen types)
3. ScreenIdentity structural delegation (MODAL/FOREIGN_APP)
4. LLM autonomous classification (first-encounter learning then cached)

GOAP smart UI polling:
- Replaced static random.uniform(1.6, 2.8) sleep with MAX_POLLS=5
  polling loop that detects actual UI transitions

Model config centralized via _get_model_config():
- ALL model/URL lookups go through Config() SSOT
- Fail Fast - no silent hardcoded fallbacks

Tests: 9 new, 119 passing, 0 regressions
2026-05-04 00:07:16 +02:00
32731ed7ec fix: structural hardening for grid selection and Reel author resolution 2026-05-03 23:41:00 +02:00
8a6c8a2249 fix: restrict grid candidates to valid area size to prevent clicking fullscreen background containers 2026-05-03 23:36:36 +02:00
f384fbb749 feat: purge ALL remaining German/localized strings from action_memory, telepathic_engine, darwin_engine, resonance_engine — enforce zero-maintenance structural determinism with TDD compliance tests 2026-05-03 23:33:28 +02:00
565bdaa568 chore: purge garbage scripts from repo and harden .gitignore 2026-05-03 23:29:14 +02:00
c641204a6b feat: enforce zero-maintenance autonomous navigation by purging hardcoded string searches and localized translations; harden VLM perception via robust JSON fallback; fix OTHER_PROFILE topological routing 2026-05-03 23:28:00 +02:00
4b645c6fb2 Hardening: Centralized zero-trust CognitiveStack validation and removed synthetic e2e test mocks 2026-05-03 20:30:30 +02:00
c7c7ce29f8 fix(qdrant): increase embedding API timeout to 30s to allow Ollama VRAM cold-starts 2026-05-03 18:38:27 +02:00
b36dde77d8 fix(navigation): harden autonomous perimeter guards against Play Store trap 2026-05-03 18:29:25 +02:00
93b2140844 docs: update ARCHITECTURE.md with SAE 3-layer modal cascade
Ensuring 100% code-documentation parity per strict architectural rules.
2026-05-03 17:15:16 +02:00
67c3d464e0 fix(navigation): harden ScreenIdentity priority cascade and GOAP structural action detection
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.
2026-05-03 17:00:27 +02:00
d298f03891 fix(sae): structural fast-path for Instagram survey/interstitial modal detection
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
2026-05-03 16:59:52 +02:00
604f2d7341 fix(perception): avoid skipping first highlight story by differentiating from home feed tray 2026-05-03 16:38:02 +02:00
cd8f35056c fix(perception): structural fast-path skips own profile story ring on home feed to prevent modal traps 2026-05-03 16:35:59 +02:00
800fb1da98 fix(perception): replace string matching with structural feed marker check for perfect snapping 2026-05-03 16:31:32 +02:00
6cd068f951 test(curiosity): force CHECK_CURIOSITY triggering and harden HD Map routing 2026-05-03 16:20:18 +02:00
f46b0b7bcb chore: harden verify_success fallbacks to Fail-Fast and apply aggressive GOAP penalty 2026-05-03 15:42:09 +02:00
5fbbe3d273 feat(e2e): ACHIEVED ABSOLUTE REALISM - 100% Production Parity Purge. Removed all synthetic guards and mocks from core. Enabled honest Qdrant and Disk I/O in tests. Empty KNOWN_DIVERGENCES. 2026-05-03 14:44:01 +02:00
f85d0a8a76 test(e2e): eliminate create_emulator_facade monkeypatching and replace with make_real_device_with_xml where applicable 2026-05-03 13:44:58 +02:00
f0a54d4e20 test(e2e): enforce 100% production-parity in dm_engine and follow verification tests 2026-05-03 11:24:25 +02:00
0a73c35809 purge: eliminate last MagicMock and all lambda dump_hierarchy overrides
- 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).
2026-05-03 10:21:23 +02:00
e535c10b65 fix(perception): structural fast-path and VLM bounds extraction for Reels 2026-05-02 23:17:12 +02:00
91effbc843 test: add E2E coverage for GOAP trap recovery and restart state reset 2026-05-02 23:11:31 +02:00
3da3849ca1 fix: purge GOAP tracking state when Instagram is forced to restart 2026-05-02 22:50:57 +02:00
51ee7a6793 refactor: remove mock_semantic_engine from q_nav_graph production code 2026-05-02 22:44:53 +02:00
936da47f61 test: SAE execution loop coverage 2026-05-02 22:40:52 +02:00
d1e0995148 test: e2e regression suite for SAE structural fast-paths 2026-05-02 22:40:20 +02:00
2f8eebb7e9 fix: stochastic failure in test_autonomous_goals.py 2026-05-02 22:37:34 +02:00
9c6f80de9d test: add 63-test GOAP navigation engine suite
Production bug 2026-05-02 22:30: Bot got trapped in a restart loop:
  1. 'tap reels tab' → VLM clicked wrong element → EXPLORE_GRID
  2. After 2 failures → action masked
  3. HD Map: 'REELS_FEED unreachable due to masked edges'
  4. GOAP: 'completely trapped' → force Instagram restart
  5. Repeat forever

ALL TESTS WERE GREEN because NONE of this logic was tested.

NEW: test_system_goap_navigation.py — 63 tests across 8 contracts:

CONTRACT 1: Screen Identification from XML (16 tests)
  - Home, Explore, Reels, Profile, DM, Story, Modal, Foreign App
  - Post detail vs Home feed (action_bar discriminator)
  - Reels full-screen (no tab bar, structural markers only)

CONTRACT 2: Available Actions Extraction (4 tests)
  - All 5 tab actions present on home feed
  - Screen-specific actions (first post on Explore)

CONTRACT 3: HD Map BFS Routing (7 tests)
  - Direct routes, multi-step routes, already-there
  - Masked edges, all-edges-masked → None

CONTRACT 4: Goal → Target Screen Mapping (14 tests)
  - All navigation goals + non-navigation goals return None

CONTRACT 5: Action Failure Masking (4 tests)
  - Mask after MAX_RETRIES, no mask under threshold
  - Full production chain reproduction

CONTRACT 6: Goal Achievement Detection (9 tests)
  - Screen-based, context-based, non-nav goals

CONTRACT 7: Structural Action Protection (4 tests)
  - HD Map actions are structural, random actions are not

CONTRACT 8: Step-Aware Navigation Validation (5 tests)
  - Expected screen for action, mismatch detection
2026-05-02 22:34:45 +02:00
cff7e976e0 fix: Tab Height Guard false-positive on author intent with 'tab' substring
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.
2026-05-02 22:28:03 +02:00
f6f15ebd9a test: expand LLM perception suite to 80 tests — 3 new contracts
CONTRACT 6: extract_json() — LLM Response Sanitizer (9 tests)
Previously COMPLETELY untested. Every single LLM response in the entire
system passes through this function. Tests:
- Clean JSON, markdown fences (json+plain), thinking block purge
- Text prefix before JSON, truncated JSON fuzzy recovery
- Garbage/empty/None resilience

CONTRACT 7: _visual_discovery Pre-Filters (8 tests)
The guards INSIDE _visual_discovery() that run BEFORE the VLM ever
sees the candidates. If they fail, the VLM gets garbage and hallucinates.
Tests:
- Area filter: tiny nodes (<200px²) and huge containers (>400000px²)
- SystemUI filter: Android system elements, notifications, battery
- Strict Button Guard: long text captions excluded for button intents
- Grid Item Guard: non-grid elements excluded, fallthrough on no match
- Author/Username Guard: nav tabs excluded for author intents

CONTRACT 8: verify_success Structural Delta (8 tests)
The post-click verification logic that decides if a click actually worked.
Tests:
- Toggle massive XML shift = navigation error (False)
- Toggle small diff = success (True)
- Toggle zero diff = inconclusive (None)
- Follow success with 'Requested' marker (private accounts)
- Follow success with German locale ('Abonniert')
- View post with clips_viewer marker (Reels)
- View post still on grid = inconclusive (None)
- Semantic gate blocks wrong toggle element (caption != like button)
2026-05-02 22:10:57 +02:00
1cc367697e test: add 55-test LLM perception pipeline integrity suite
Validates the deterministic processing logic around the VLM without
needing a real LLM. Five contracts covering the full perception stack:

1. VLM Response Parsing (20 parametrized formats):
   Tests _parse_yes_no against every response format observed in production:
   clean YES/NO, JSON variants, explanations, edge cases (now/not/nothing),
   empty strings, free-form JSON. Documents the startswith('yes') early-exit
   behavior for ambiguous responses.

2. Box Index Extraction (7 formats):
   Validates JSON parsing of VLM box selections across all observed key
   variants: 'box', 'selected_index', 'box_index', 'index', null, and
   out-of-range values.

3. Structural Guards (11 tests):
   Tests every hallucination prevention guard in IntentResolver:
   - Tab intent excludes Back button (bug 2026-04-30)
   - Back intent preserves Back button
   - Tab height guard (y > 85% screen)
   - Author intent excludes nav tabs (bug 2026-05-01)
   - Structural fast-paths (message input, send, author, comment)
   - Abstract goals return None
   - Semantic quoted-target guard

4. Semantic Match Validation (10 tests):
   Prevents memory poisoning via _intent_matches_node:
   - Correct matches (follow/like/save + German locale)
   - Poisoning attempts: Reel thumbnails, photo content, comments
   - Non-toggle intents always pass through

5. ActionMemory Lifecycle (7 tests):
   Full track → confirm/reject cycle with FakeUIMemoryDB:
   - Correct follow stores in memory
   - Poisoned follow is BLOCKED (production bug reproduction)
   - Rejected click triggers confidence decay
   - No-track confirm is noop
   - Mismatched intent is ignored
   - Follow/view-post structural verification
2026-05-02 22:07:12 +02:00
738a59ac8d test: add E2E coverage gate and full lifecycle integration test
Two critical test additions:

1. test_system_full_lifecycle.py — Full A-to-Z integration test:
   Exercises the ENTIRE bot pipeline across 4 screen types (HomeFeed →
   Explore → Post Detail → Profile) with a real InstagramEmulator state
   machine. Validates plugin execution, session state accumulation,
   cognitive stack survival, dopamine session timeout, and post-session
   serialization. This is the single most important test in the suite.

2. test_system_coverage_gate.py — Critical Path Coverage Enforcement:
   Reads coverage_e2e.json and enforces minimum coverage thresholds on
   production-critical modules. Each threshold is tied to a real production
   incident. If persistent_list.py drops below 20% coverage, the build
   fails — because that's exactly how the sessions.json corruption
   bug went undetected.

   Usage: pytest tests/e2e --cov=GramAddict.core \
     --cov-report=json:coverage_e2e.json

   Critical paths enforced:
   - session_state.py (>=50%): serialization crash prevention
   - persistent_list.py (>=20%): persist() path must be tested
   - dopamine_engine.py (>=40%): session timeout logic
   - screen_identity.py (>=60%): screen identification
   - spatial_parser.py (>=70%): UI element parsing
   - intent_resolver.py (>=50%): click decision logic
   - q_nav_graph.py (>=25%): navigation integrity
   - device_facade.py (>=40%): device interface
2026-05-02 21:56:19 +02:00
cd6cecbe27 test: add proactive system integrity contracts
Replaces reactive bug-specific tests with 4 structural CONTRACTS
that make entire categories of bugs impossible:

1. Serialization Contract (13 parametrized hostile payloads):
   Proves SessionStateEncoder NEVER crashes regardless of what
   gets injected onto args (datetime, lambda, bytes, inf, nan, etc.)

2. Persistence Contract:
   Forces the REAL persist() path by removing PYTEST_CURRENT_TEST guard.
   Validates write → read round-trip with poisoned sessions.

3. Production Parity Contract:
   Scans ALL GramAddict source for pytest/test-mode divergence guards.
   Any unaudited divergence point fails the build. New guards require
   explicit justification in KNOWN_DIVERGENCES registry.

4. Import Integrity Contract:
   Imports every single GramAddict module to catch syntax errors,
   circular imports, and missing dependencies at test time.

This addresses the root systemic failure: tests were running in a
parallel universe where serialization was silently skipped, allowing
a datetime injection to corrupt sessions.json and kill production.
2026-05-02 20:15:35 +02:00
4af4ddb060 fix: prevent SessionStateEncoder crash from non-serializable datetime on args
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
2026-05-02 19:57:33 +02:00
f32ee46d8c test: finalize E2E timeout verification and purge global state leaks 2026-05-02 18:59:35 +02:00
d2de5f91de test(e2e): Fix DM Engine E2E test XML sequences to eliminate Alien Context drift 2026-05-02 00:26:31 +02:00
9a13216064 test: enforce real VLM execution in explore tab guard and disable fallback hallucination 2026-05-01 23:41:51 +02:00
aa5184786e test(e2e): Fix LLM mock hallucinations to use structurally merged search string for 100% truthful navigation tests 2026-05-01 22:27:38 +02:00
2e1edec56a fix(perception): 3 production bug regressions from 2026-05-01 run
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
2026-05-01 21:57:56 +02:00
df18a48a84 build(deps): bump requests version to fix urllib3 warning 2026-05-01 16:57:03 +02:00
f1a8573be8 test(e2e): eliminate lying tests via behavioral truth assertions 2026-05-01 16:55:53 +02:00
da7201117c fix(tests): purge MagicMock, fix ad fixtures, improve pre-commit E2E fallback
- test_device_connection.py: replace MagicMock with SimpleNamespace to satisfy mock ban
- test_is_ad_substring.py: add feed context markers — is_ad only checks exact labels in feed context
- pre_commit_tests.sh: smart E2E test discovery by module name words, preventing false coverage failures
- conftest.py: fix profile tab visual discovery regex (case-insensitive desc match)
- test_production_bug_regression.py: fix TelepathicEngine singleton poisoning via monkeypatch
2026-05-01 12:09:18 +02:00
fddf14fd67 test(e2e): purge FakeSAENormal and instantiate real Cognitive Stack
PRODUCTION FIX 2026-04-30 12:45:
The entire E2E suite was systematically lying by testing a shell of the bot:
1. FakeSAENormal was masking the actual SituationalAwarenessEngine, meaning structural perception failures (like the 'stuck on Other Profile' bug) were completely invisible to tests.
2. The e2e_cognitive_stack was hardcoded to return None for 80% of engines (NavGraph, ZeroEngine, Telepathic, Darwin, ActiveInference), causing plugins to silently bypass their core logic during tests.
3. get_screenshot_b64 and screenshot() returned None, preventing the VLM stack from even running structural fallback code.

Fix:
- Systematically stripped FakeSAENormal from all 29 E2E workflow tests.
- Built e2e_cognitive_stack_factory to instantiate the REAL Cognitive Stack (GrowthBrain, QNavGraph, ZeroLatencyEngine, etc.) just like in bot_flow.py.
- Patched ONLY the external LLM network requests in conftest.py via mock_llm_network_calls so that structural execution stays 100% real but avoids non-deterministic LLM timeouts.
- Injected a valid 1x1 black image for screenshots.

All 29 E2E tests now execute the true production logic path and pass in 49 seconds.
2026-04-30 12:46:01 +02:00
392abff313 fix(intent_resolver): add Nav Conflict Guard — Back button never valid for tab intents
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.
2026-04-30 12:10:44 +02:00