feat: complete modular plugin refactor with 100% E2E coverage for interactions

This commit is contained in:
2026-04-25 20:58:07 +02:00
parent 77e8251aa7
commit 144d6401b5
232 changed files with 66259 additions and 5410 deletions

View File

@@ -7,16 +7,16 @@ not just specific examples. Think of them as mathematical proofs of correctness.
Tesla validates that steering never exceeds max torque for ANY speed —
we validate that scroll never exceeds screen bounds for ANY device size.
"""
import pytest
import re
from hypothesis import given, strategies as st, settings, assume
from tests.chaos import VALID_FEED_XML
import pytest
from hypothesis import assume, given, settings
from hypothesis import strategies as st
# ──────────────────────────────────────────────────
# XML Parsing Properties
# ──────────────────────────────────────────────────
@pytest.mark.property
class TestXMLParsingProperties:
"""Universal properties of the XML extraction pipeline."""
@@ -29,11 +29,23 @@ class TestXMLParsingProperties:
def test_extracted_nodes_always_have_valid_coordinates(self, text, desc):
"""PROPERTY: Any extracted node must have integer x, y >= 0."""
from unittest.mock import MagicMock, patch
# Escape XML special chars
safe_text = text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;").replace("'", "&apos;")
safe_desc = desc.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;").replace("'", "&apos;")
safe_text = (
text.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace('"', "&quot;")
.replace("'", "&apos;")
)
safe_desc = (
desc.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace('"', "&quot;")
.replace("'", "&apos;")
)
xml = (
f'<hierarchy rotation="0">'
f'<node index="0" text="{safe_text}" '
@@ -43,12 +55,18 @@ class TestXMLParsingProperties:
f'content-desc="{safe_desc}" '
f'clickable="true" '
f'bounds="[100,200][300,400]" />'
f'</hierarchy>'
f"</hierarchy>"
)
with patch("GramAddict.core.qdrant_memory.QdrantBase.__init__", return_value=None), \
patch("GramAddict.core.qdrant_memory.QdrantBase.is_connected", new_callable=lambda: property(lambda self: False)):
with (
patch("GramAddict.core.qdrant_memory.QdrantBase.__init__", return_value=None),
patch(
"GramAddict.core.qdrant_memory.QdrantBase.is_connected",
new_callable=lambda: property(lambda self: False),
),
):
from GramAddict.core.telepathic_engine import TelepathicEngine
TelepathicEngine._instance = None
engine = TelepathicEngine.__new__(TelepathicEngine)
engine.ui_memory = MagicMock()
@@ -57,20 +75,20 @@ class TestXMLParsingProperties:
engine.positive_memory.is_connected = False
engine._edge_model = None
engine._edge_tokenizer = None
try:
nodes = engine._extract_semantic_nodes(xml)
except Exception:
# If the generated text breaks XML parsing, that's OK —
# the parser should return empty list, not crash
nodes = []
for node in nodes:
assert isinstance(node["x"], int)
assert isinstance(node["y"], int)
assert node["x"] >= 0
assert node["y"] >= 0
TelepathicEngine._instance = None
@given(
@@ -84,10 +102,10 @@ class TestXMLParsingProperties:
"""PROPERTY: Calculated center must lie within the bounding rectangle."""
right = min(left + width, 2160)
bottom = min(top + height, 3200)
center_x = (left + right) // 2
center_y = (top + bottom) // 2
assert left <= center_x <= right
assert top <= center_y <= bottom
@@ -96,6 +114,7 @@ class TestXMLParsingProperties:
# SAE Compression Properties
# ──────────────────────────────────────────────────
@pytest.mark.property
class TestSAECompressionProperties:
"""Universal properties of XML compression."""
@@ -107,14 +126,16 @@ class TestSAECompressionProperties:
def test_compression_output_bounded(self, n_nodes):
"""PROPERTY: Compressed output must ALWAYS be <= 3000 characters."""
from unittest.mock import MagicMock
from GramAddict.core.situational_awareness import SituationalAwarenessEngine
SituationalAwarenessEngine.reset()
device = MagicMock()
device.deviceV2 = MagicMock()
device.deviceV2.info = {"screenOn": True}
sae = SituationalAwarenessEngine(device)
# Generate XML with n_nodes
parts = ['<hierarchy rotation="0">']
for i in range(n_nodes):
@@ -125,12 +146,12 @@ class TestSAECompressionProperties:
f'package="com.instagram.android" '
f'clickable="true" bounds="[0,{i*50}][100,{i*50+40}]" />'
)
parts.append('</hierarchy>')
parts.append("</hierarchy>")
xml = "".join(parts)
result = sae._compress_xml(xml)
assert len(result) <= 3000
SituationalAwarenessEngine.reset()
@given(
@@ -141,20 +162,22 @@ class TestSAECompressionProperties:
def test_different_inputs_produce_different_hashes(self, text1, text2):
"""PROPERTY: Distinct inputs should (almost always) produce distinct hashes."""
assume(text1 != text2)
from unittest.mock import MagicMock
from GramAddict.core.situational_awareness import SituationalAwarenessEngine
SituationalAwarenessEngine.reset()
device = MagicMock()
device.deviceV2 = MagicMock()
device.deviceV2.info = {"screenOn": True}
sae = SituationalAwarenessEngine(device)
hash1 = sae._compute_situation_hash(text1)
hash2 = sae._compute_situation_hash(text2)
assert hash1 != hash2
SituationalAwarenessEngine.reset()
@@ -162,6 +185,7 @@ class TestSAECompressionProperties:
# Active Inference Properties
# ──────────────────────────────────────────────────
@pytest.mark.property
class TestActiveInferenceProperties:
"""Universal properties of the Active Inference engine."""
@@ -174,8 +198,9 @@ class TestActiveInferenceProperties:
def test_free_energy_always_non_negative(self, predicted, observed):
"""PROPERTY: Free energy must NEVER go negative."""
from GramAddict.core.active_inference import ActiveInferenceEngine
ai = ActiveInferenceEngine("test_user")
result = ai.calculate_surprise(predicted, observed)
assert result >= 0.0
@@ -187,8 +212,9 @@ class TestActiveInferenceProperties:
def test_policy_always_valid(self, predicted, observed):
"""PROPERTY: Policy must always be one of the valid states."""
from GramAddict.core.active_inference import ActiveInferenceEngine
ai = ActiveInferenceEngine("test_user")
ai.calculate_surprise(predicted, observed)
assert ai.policy in ("STABLE", "CAUTIOUS", "DORMANT")
@@ -199,10 +225,11 @@ class TestActiveInferenceProperties:
def test_sleep_modifier_always_bounded(self, modifier_count):
"""PROPERTY: Sleep modifier must always be in [1.0, 5.0] range."""
from GramAddict.core.active_inference import ActiveInferenceEngine
ai = ActiveInferenceEngine("test_user")
for _ in range(modifier_count):
ai.calculate_surprise(1.0, 0.0) # Max surprise
mod = ai.get_sleep_modifier()
assert 1.0 <= mod <= 5.0