370 lines
11 KiB
Python
370 lines
11 KiB
Python
|
|
#!/usr/bin/env python3
|
||
|
|
"""Tests for LAIN ↔ Supercharged Glyph Bridge
|
||
|
|
|
||
|
|
Tests verify:
|
||
|
|
- load_glyph_context loads correct glyphs from registry
|
||
|
|
- inject_glyph_metadata_into_lane adds glyph fields
|
||
|
|
- compute_glyph_resonance returns numeric values
|
||
|
|
- augment_fused_symbol_with_glyphs adds glyph metadata
|
||
|
|
- execute_with_lain integrates glyph bridge into cognition
|
||
|
|
- Glyph metadata appears in lane results, fused symbol, and diagnostics
|
||
|
|
"""
|
||
|
|
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
sys.path.insert(0, str(Path.cwd()))
|
||
|
|
|
||
|
|
from gx_lain.lain_glyph_bridge import (
|
||
|
|
load_glyph_context,
|
||
|
|
inject_glyph_metadata_into_lane,
|
||
|
|
compute_glyph_resonance,
|
||
|
|
augment_fused_symbol_with_glyphs,
|
||
|
|
)
|
||
|
|
from gx_lain.runtime import execute_gx_path
|
||
|
|
|
||
|
|
|
||
|
|
def test_load_glyph_context_no_glyph():
|
||
|
|
"""Test loading glyph context when no glyph is specified."""
|
||
|
|
manifest = {
|
||
|
|
"source_file": "test.py",
|
||
|
|
"version": "1.0.0",
|
||
|
|
}
|
||
|
|
context = {}
|
||
|
|
|
||
|
|
glyph_context = load_glyph_context(manifest, context)
|
||
|
|
|
||
|
|
if not isinstance(glyph_context, dict):
|
||
|
|
print("FAIL: glyph_context is not a dict")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if glyph_context["found"] != False:
|
||
|
|
print("FAIL: Should return found=False when no glyph specified")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if glyph_context["id"] != "none":
|
||
|
|
print("FAIL: Should return id='none' when no glyph found")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: load_glyph_context handles missing glyph")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_load_glyph_context_by_id():
|
||
|
|
"""Test loading glyph context by explicit glyph_id."""
|
||
|
|
manifest = {
|
||
|
|
"source_file": "test.py",
|
||
|
|
"glyph_id": "G001",
|
||
|
|
}
|
||
|
|
context = {}
|
||
|
|
|
||
|
|
glyph_context = load_glyph_context(manifest, context)
|
||
|
|
|
||
|
|
if glyph_context["found"] != True:
|
||
|
|
print("FAIL: Should find glyph G001")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if glyph_context["id"] != "G001":
|
||
|
|
print(f"FAIL: Expected G001, got {glyph_context['id']}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if glyph_context["name"] == "none":
|
||
|
|
print("FAIL: Glyph name should not be 'none'")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if glyph_context["score"] <= 0:
|
||
|
|
print("FAIL: Glyph score should be positive")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print(f"PASS: load_glyph_context found G001 ({glyph_context['name']})")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_load_glyph_context_fields():
|
||
|
|
"""Test that glyph context includes all required fields."""
|
||
|
|
manifest = {"glyph_id": "G001"}
|
||
|
|
context = {}
|
||
|
|
|
||
|
|
glyph_context = load_glyph_context(manifest, context)
|
||
|
|
|
||
|
|
required_fields = [
|
||
|
|
"id", "name", "category", "score", "praw", "originalMetrics",
|
||
|
|
"activation", "lineage", "found"
|
||
|
|
]
|
||
|
|
|
||
|
|
for field in required_fields:
|
||
|
|
if field not in glyph_context:
|
||
|
|
print(f"FAIL: Missing field: {field}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: glyph_context includes all required fields")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_inject_glyph_metadata_into_lane():
|
||
|
|
"""Test injecting glyph metadata into lane result."""
|
||
|
|
lane_result = {
|
||
|
|
"summary": "Test summary",
|
||
|
|
"key_points": ["point1"],
|
||
|
|
"constraints": [],
|
||
|
|
"open_questions": [],
|
||
|
|
}
|
||
|
|
|
||
|
|
manifest = {"glyph_id": "G001"}
|
||
|
|
glyph_context = load_glyph_context(manifest, {})
|
||
|
|
|
||
|
|
augmented = inject_glyph_metadata_into_lane(lane_result, glyph_context)
|
||
|
|
|
||
|
|
# Check that original fields are preserved
|
||
|
|
if augmented["summary"] != "Test summary":
|
||
|
|
print("FAIL: Original summary was overwritten")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check that glyph fields were added
|
||
|
|
if "glyph_id" not in augmented:
|
||
|
|
print("FAIL: glyph_id not added")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if augmented["glyph_id"] != "G001":
|
||
|
|
print(f"FAIL: glyph_id mismatch")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if "glyph_name" not in augmented:
|
||
|
|
print("FAIL: glyph_name not added")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if "glyph_frequency_signature" not in augmented:
|
||
|
|
print("FAIL: glyph_frequency_signature not added")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: inject_glyph_metadata_into_lane works correctly")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_inject_no_glyph():
|
||
|
|
"""Test inject when no glyph is found."""
|
||
|
|
lane_result = {
|
||
|
|
"summary": "Test",
|
||
|
|
"key_points": [],
|
||
|
|
"constraints": [],
|
||
|
|
"open_questions": [],
|
||
|
|
}
|
||
|
|
|
||
|
|
glyph_context = load_glyph_context({}, {}) # No glyph
|
||
|
|
|
||
|
|
augmented = inject_glyph_metadata_into_lane(lane_result, glyph_context)
|
||
|
|
|
||
|
|
# Should return unchanged
|
||
|
|
if augmented != lane_result:
|
||
|
|
print("FAIL: Should return unchanged when no glyph")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: inject handles missing glyph correctly")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_compute_glyph_resonance_no_glyph():
|
||
|
|
"""Test computing resonance when no glyph is found."""
|
||
|
|
glyph_context = load_glyph_context({}, {})
|
||
|
|
|
||
|
|
resonance = compute_glyph_resonance(glyph_context)
|
||
|
|
|
||
|
|
if not isinstance(resonance, dict):
|
||
|
|
print("FAIL: resonance is not a dict")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if resonance["glyph_found"] != False:
|
||
|
|
print("FAIL: Should indicate glyph not found")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if resonance["overall_resonance"] != 0.0:
|
||
|
|
print("FAIL: Should return 0.0 when no glyph")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: compute_glyph_resonance handles missing glyph")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_compute_glyph_resonance_with_glyph():
|
||
|
|
"""Test computing resonance with valid glyph."""
|
||
|
|
glyph_context = load_glyph_context({"glyph_id": "G001"}, {})
|
||
|
|
|
||
|
|
resonance = compute_glyph_resonance(glyph_context)
|
||
|
|
|
||
|
|
if not isinstance(resonance, dict):
|
||
|
|
print("FAIL: resonance is not a dict")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if resonance["glyph_found"] != True:
|
||
|
|
print("FAIL: Should indicate glyph found")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check resonance metrics are numeric
|
||
|
|
for metric in [
|
||
|
|
"activation_resonance",
|
||
|
|
"frequency_resonance",
|
||
|
|
"symbolic_resonance",
|
||
|
|
"overall_resonance",
|
||
|
|
]:
|
||
|
|
if metric not in resonance:
|
||
|
|
print(f"FAIL: Missing metric {metric}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if not isinstance(resonance[metric], float):
|
||
|
|
print(f"FAIL: {metric} is not a float")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if not (0.0 <= resonance[metric] <= 1.0):
|
||
|
|
print(f"FAIL: {metric} out of range [0,1]")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if resonance["glyph_id"] != "G001":
|
||
|
|
print("FAIL: glyph_id mismatch")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print(f"PASS: compute_glyph_resonance returned valid metrics")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_augment_fused_symbol_no_glyph():
|
||
|
|
"""Test augmenting fused symbol when no glyph."""
|
||
|
|
fused_symbol = {
|
||
|
|
"summary": "Fused summary",
|
||
|
|
"key_points": ["p1", "p2"],
|
||
|
|
"constraints": [],
|
||
|
|
"open_questions": [],
|
||
|
|
}
|
||
|
|
|
||
|
|
glyph_context = load_glyph_context({}, {})
|
||
|
|
|
||
|
|
augmented = augment_fused_symbol_with_glyphs(fused_symbol, glyph_context)
|
||
|
|
|
||
|
|
if augmented["glyph_id"] != "none":
|
||
|
|
print("FAIL: Should set glyph_id to 'none'")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if augmented["glyph_found"] != False:
|
||
|
|
print("FAIL: Should mark glyph_found as False")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: augment_fused_symbol handles missing glyph")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_augment_fused_symbol_with_glyph():
|
||
|
|
"""Test augmenting fused symbol with valid glyph."""
|
||
|
|
fused_symbol = {
|
||
|
|
"summary": "Fused summary",
|
||
|
|
"key_points": ["p1", "p2"],
|
||
|
|
"constraints": [],
|
||
|
|
"open_questions": [],
|
||
|
|
}
|
||
|
|
|
||
|
|
glyph_context = load_glyph_context({"glyph_id": "G001"}, {})
|
||
|
|
|
||
|
|
augmented = augment_fused_symbol_with_glyphs(fused_symbol, glyph_context)
|
||
|
|
|
||
|
|
# Check original fields preserved
|
||
|
|
if augmented["summary"] != "Fused summary":
|
||
|
|
print("FAIL: Original summary overwritten")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check glyph fields added
|
||
|
|
glyph_fields = [
|
||
|
|
"glyph_id", "glyph_name", "glyph_category", "glyph_score"
|
||
|
|
]
|
||
|
|
|
||
|
|
for field in glyph_fields:
|
||
|
|
if field not in augmented:
|
||
|
|
print(f"FAIL: Missing field {field}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
if augmented["glyph_id"] != "G001":
|
||
|
|
print("FAIL: glyph_id mismatch")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check key_points were extended
|
||
|
|
if not any("glyph:" in str(kp) for kp in augmented["key_points"]):
|
||
|
|
print("FAIL: Glyph key points not added")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: augment_fused_symbol adds glyph metadata correctly")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def test_execute_with_lain_includes_glyph():
|
||
|
|
"""Test that execute_with_lain includes glyph metadata in result."""
|
||
|
|
# Execute a .gx file and verify glyph integration
|
||
|
|
try:
|
||
|
|
result = execute_gx_path("/home/dave/sample_code.gx")
|
||
|
|
except Exception as e:
|
||
|
|
print(f"FAIL: execute_gx_path failed: {e}")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check cognition_trace includes glyph loading
|
||
|
|
glyph_load_step = None
|
||
|
|
for step in result.get("cognition_trace", []):
|
||
|
|
if step.get("operation") == "glyph_context_loaded":
|
||
|
|
glyph_load_step = step
|
||
|
|
break
|
||
|
|
|
||
|
|
if glyph_load_step is None:
|
||
|
|
print("FAIL: glyph_context_loaded not in trace")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check fused_symbol has glyph fields
|
||
|
|
fused = result.get("fused_symbol", {})
|
||
|
|
if "glyph_id" not in fused:
|
||
|
|
print("FAIL: glyph_id not in fused_symbol")
|
||
|
|
return False
|
||
|
|
|
||
|
|
# Check diagnostics has glyph resonance
|
||
|
|
diags = result.get("diagnostics", {})
|
||
|
|
if "glyph_resonance" not in diags:
|
||
|
|
print("FAIL: glyph_resonance not in diagnostics")
|
||
|
|
return False
|
||
|
|
|
||
|
|
print("PASS: execute_with_lain integrates glyph bridge")
|
||
|
|
return True
|
||
|
|
|
||
|
|
|
||
|
|
def main_test():
|
||
|
|
print("[TEST SUITE] test_lain_glyph_bridge.py")
|
||
|
|
print()
|
||
|
|
|
||
|
|
tests = [
|
||
|
|
("Load glyph context (no glyph)", test_load_glyph_context_no_glyph),
|
||
|
|
("Load glyph context (by ID)", test_load_glyph_context_by_id),
|
||
|
|
("Glyph context fields", test_load_glyph_context_fields),
|
||
|
|
("Inject glyph metadata", test_inject_glyph_metadata_into_lane),
|
||
|
|
("Inject without glyph", test_inject_no_glyph),
|
||
|
|
("Compute resonance (no glyph)", test_compute_glyph_resonance_no_glyph),
|
||
|
|
("Compute resonance (with glyph)", test_compute_glyph_resonance_with_glyph),
|
||
|
|
("Augment symbol (no glyph)", test_augment_fused_symbol_no_glyph),
|
||
|
|
("Augment symbol (with glyph)", test_augment_fused_symbol_with_glyph),
|
||
|
|
("Execute with glyph integration", test_execute_with_lain_includes_glyph),
|
||
|
|
]
|
||
|
|
|
||
|
|
passed = 0
|
||
|
|
failed = 0
|
||
|
|
|
||
|
|
for name, test_func in tests:
|
||
|
|
print(f"Running: {name}...", end=" ")
|
||
|
|
try:
|
||
|
|
if test_func():
|
||
|
|
passed += 1
|
||
|
|
else:
|
||
|
|
failed += 1
|
||
|
|
except Exception as e:
|
||
|
|
print(f"FAIL: {e}")
|
||
|
|
failed += 1
|
||
|
|
|
||
|
|
print()
|
||
|
|
print(f"Results: {passed} passed, {failed} failed")
|
||
|
|
|
||
|
|
return 0 if failed == 0 else 1
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
sys.exit(main_test())
|