Implement real LAIN cognition engine with 8 lane processors
New modules: - gx_lain/lane_processors.py: 8 symbolic lane processors * Lane 0: structural_logic (control flow, constraints) * Lane 1: semantic_flow (core meaning, narrative) * Lane 2: compression_residue (artifacts, hints) * Lane 3: symbolic_metadata (tags, annotations) * Lane 4: execution_hints (runtime guards, priorities) * Lane 5: predictive_scaffolding (hypotheses, priors) * Lane 6: contributor_imprint (author style, bias) * Lane 7: epoch_resonance (temporal context) - gx_lain/runtime.py (updated): Real cognition loop * execute_with_lain(): Process all 8 lanes, capture timings * fuse_lanes(): Merge lane results into final symbol * compute_resonance(): Per-lane resonance metrics * render_output_text(): Mode-based output formatting Features: - Structured lane processing with error recovery - Cognition trace with per-lane timing - Resonance metrics (1.0 if lane has content) - Fused symbol with deduplication - Mode-aware output (ANALYZE vs SYNTHESIZE) - No mutations, deterministic execution All 18 integration tests pass unchanged.
This commit is contained in:
+206
-47
@@ -246,11 +246,137 @@ def build_envelope(
|
||||
return envelope
|
||||
|
||||
|
||||
def execute_with_lain(envelope: dict) -> dict:
|
||||
"""Execute ExecutionEnvelope through (stub) LAIN engine.
|
||||
def fuse_lanes(lane_results: Dict[int, dict]) -> dict:
|
||||
"""Fuse lane results into final fused_symbol.
|
||||
|
||||
This is a stub implementation that simulates LAIN cognition.
|
||||
In production, this would call the real LAIN runtime.
|
||||
Merges summaries, key_points, constraints, and open_questions
|
||||
from all lanes into a single coherent representation.
|
||||
|
||||
Args:
|
||||
lane_results: Dict[lane_id, lane_result]
|
||||
|
||||
Returns:
|
||||
Fused symbol dict with summary, key_points, constraints, open_questions
|
||||
"""
|
||||
summaries = []
|
||||
all_key_points = []
|
||||
all_constraints = []
|
||||
all_questions = []
|
||||
|
||||
for lane_id in sorted(lane_results.keys()):
|
||||
result = lane_results[lane_id]
|
||||
|
||||
# Collect summaries
|
||||
if result.get("summary"):
|
||||
summaries.append(result["summary"])
|
||||
|
||||
# Collect key points
|
||||
all_key_points.extend(result.get("key_points", []))
|
||||
|
||||
# Collect constraints
|
||||
all_constraints.extend(result.get("constraints", []))
|
||||
|
||||
# Collect open questions
|
||||
all_questions.extend(result.get("open_questions", []))
|
||||
|
||||
# Merge summary
|
||||
if summaries:
|
||||
combined_summary = " | ".join(summaries)
|
||||
else:
|
||||
combined_summary = "No lanes processed"
|
||||
|
||||
# Deduplicate and limit key points
|
||||
unique_key_points = list(dict.fromkeys(all_key_points))[:10]
|
||||
|
||||
# Deduplicate constraints
|
||||
unique_constraints = list(dict.fromkeys(all_constraints))
|
||||
|
||||
# Deduplicate questions
|
||||
unique_questions = list(dict.fromkeys(all_questions))
|
||||
|
||||
return {
|
||||
"summary": combined_summary,
|
||||
"key_points": unique_key_points,
|
||||
"constraints": unique_constraints,
|
||||
"open_questions": unique_questions,
|
||||
}
|
||||
|
||||
|
||||
def compute_resonance(lane_results: Dict[int, dict], context: Dict[str, Any]) -> dict:
|
||||
"""Compute resonance metrics for lanes.
|
||||
|
||||
Simple rule: resonance[lane] = 1.0 if lane produced content, else 0.0
|
||||
|
||||
Args:
|
||||
lane_results: Dict[lane_id, lane_result]
|
||||
context: Execution context
|
||||
|
||||
Returns:
|
||||
Dict[str, float] with resonance metrics
|
||||
"""
|
||||
resonance = {}
|
||||
|
||||
for lane_id in sorted(lane_results.keys()):
|
||||
result = lane_results[lane_id]
|
||||
|
||||
# Lane has content if it produced a non-empty summary
|
||||
has_content = bool(result.get("summary", "").strip())
|
||||
resonance[f"lane_{lane_id}"] = 1.0 if has_content else 0.0
|
||||
|
||||
return resonance
|
||||
|
||||
|
||||
def render_output_text(fused_symbol: dict, context: Dict[str, Any]) -> str:
|
||||
"""Render human-facing output text from fused_symbol.
|
||||
|
||||
Format varies by cognitive_mode.
|
||||
|
||||
Args:
|
||||
fused_symbol: Fused symbol dict
|
||||
context: Execution context
|
||||
|
||||
Returns:
|
||||
Human-readable output string
|
||||
"""
|
||||
mode = context.get("cognitive_mode", "analyze")
|
||||
|
||||
mode_label = mode.upper()
|
||||
summary = fused_symbol.get("summary", "No summary")
|
||||
|
||||
lines = [
|
||||
f"[{mode_label}]",
|
||||
f"{summary}",
|
||||
]
|
||||
|
||||
key_points = fused_symbol.get("key_points", [])
|
||||
if key_points:
|
||||
lines.append("")
|
||||
lines.append("Key Points:")
|
||||
for point in key_points[:5]:
|
||||
lines.append(f" • {point}")
|
||||
|
||||
constraints = fused_symbol.get("constraints", [])
|
||||
if constraints:
|
||||
lines.append("")
|
||||
lines.append("Constraints:")
|
||||
for constraint in constraints[:5]:
|
||||
lines.append(f" • {constraint}")
|
||||
|
||||
questions = fused_symbol.get("open_questions", [])
|
||||
if questions:
|
||||
lines.append("")
|
||||
lines.append("Open Questions:")
|
||||
for question in questions[:5]:
|
||||
lines.append(f" ? {question}")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def execute_with_lain(envelope: dict) -> dict:
|
||||
"""Execute ExecutionEnvelope through LAIN cognition engine.
|
||||
|
||||
Real implementation: iterate through lanes, process each via lane processors,
|
||||
fuse results, and return full ExecutionResult.
|
||||
|
||||
Contract:
|
||||
- Does not mutate input envelope
|
||||
@@ -263,6 +389,8 @@ def execute_with_lain(envelope: dict) -> dict:
|
||||
Returns:
|
||||
ExecutionResult dict with cognition_trace, fused_symbol, output_text, diagnostics
|
||||
"""
|
||||
from .lane_processors import process_lane
|
||||
|
||||
start_time = time.time()
|
||||
|
||||
manifest = envelope.get("manifest", {})
|
||||
@@ -270,18 +398,13 @@ def execute_with_lain(envelope: dict) -> dict:
|
||||
payload = envelope.get("payload", b"")
|
||||
context = envelope.get("context", {})
|
||||
|
||||
# Initialize diagnostics
|
||||
# Initialize tracking
|
||||
lane_timings: Dict[int, float] = {}
|
||||
lane_results: Dict[int, dict] = {}
|
||||
errors: List[dict] = []
|
||||
|
||||
# Stub: simulate processing each lane
|
||||
for lane_id in sorted(lanes.keys()):
|
||||
lane_timings[lane_id] = 0.0
|
||||
|
||||
# Build cognition trace (stub)
|
||||
cognition_trace = []
|
||||
|
||||
# Step 0: Load
|
||||
# Step 0: Load envelope
|
||||
cognition_trace.append({
|
||||
"step": 0,
|
||||
"lane": -1,
|
||||
@@ -293,46 +416,82 @@ def execute_with_lain(envelope: dict) -> dict:
|
||||
"manifest_version": manifest.get("version"),
|
||||
},
|
||||
"output": {},
|
||||
"note": "Loaded ExecutionEnvelope into LAIN stub.",
|
||||
"note": "Loaded ExecutionEnvelope into LAIN cognition engine.",
|
||||
})
|
||||
|
||||
# Step 1: Process lanes
|
||||
num_segments = sum(len(segs) for segs in lanes.values())
|
||||
cognition_trace.append({
|
||||
"step": 1,
|
||||
"lane": -1,
|
||||
"segment_id": None,
|
||||
"operation": "process_lanes",
|
||||
"input": {"lanes": sorted(lanes.keys())},
|
||||
"output": {"processed_segments": num_segments},
|
||||
"note": f"Stub processed {num_segments} segments.",
|
||||
})
|
||||
|
||||
# Synthesize fused_symbol from lanes and segments
|
||||
all_segments = []
|
||||
# Process each lane
|
||||
step_num = 1
|
||||
for lane_id in sorted(lanes.keys()):
|
||||
all_segments.extend(lanes[lane_id])
|
||||
lane_start = time.time()
|
||||
lane_segments = lanes.get(lane_id, [])
|
||||
|
||||
key_points = [seg["id"] for seg in all_segments[:3]]
|
||||
try:
|
||||
# Call lane processor
|
||||
lane_result = process_lane(
|
||||
lane_id,
|
||||
lane_segments,
|
||||
context,
|
||||
manifest,
|
||||
)
|
||||
lane_results[lane_id] = lane_result
|
||||
|
||||
fused_symbol = {
|
||||
"summary": f"GX→LAIN stub: {len(all_segments)} segments, {len(lanes)} lanes",
|
||||
"key_points": key_points,
|
||||
"constraints": [],
|
||||
"open_questions": ["Real LAIN cognition not yet implemented"],
|
||||
}
|
||||
# Record timing
|
||||
lane_elapsed = time.time() - lane_start
|
||||
lane_timings[lane_id] = lane_elapsed
|
||||
|
||||
# Output text
|
||||
contributor = manifest.get("contributor", "unknown")
|
||||
source = manifest.get("source_file", "unknown")
|
||||
output_text = (
|
||||
f"GX→LAIN Runtime Stub v{INTERFACE_VERSION}\n"
|
||||
f"Source: {source}\n"
|
||||
f"Contributor: {contributor}\n"
|
||||
f"Segments: {len(all_segments)}\n"
|
||||
f"Lanes: {len(lanes)}\n"
|
||||
f"Status: Stub execution (replace with real LAIN engine)\n"
|
||||
)
|
||||
# Trace entry
|
||||
cognition_trace.append({
|
||||
"step": step_num,
|
||||
"lane": lane_id,
|
||||
"segment_id": None,
|
||||
"operation": f"process_lane_{lane_id}",
|
||||
"input": {"segments": len(lane_segments)},
|
||||
"output": {
|
||||
"summary_length": len(lane_result.get("summary", "")),
|
||||
"key_points": len(lane_result.get("key_points", [])),
|
||||
},
|
||||
"note": f"Processed lane {lane_id} with {len(lane_segments)} segments in {lane_elapsed:.4f}s.",
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
lane_elapsed = time.time() - lane_start
|
||||
lane_timings[lane_id] = lane_elapsed
|
||||
|
||||
err = make_error(
|
||||
"LaneProcessorError",
|
||||
f"Lane {lane_id} processing failed: {e}",
|
||||
lane=lane_id,
|
||||
recoverable=True,
|
||||
)
|
||||
errors.append(err)
|
||||
|
||||
lane_results[lane_id] = {
|
||||
"summary": f"Error processing lane {lane_id}",
|
||||
"key_points": [],
|
||||
"constraints": [],
|
||||
"open_questions": [],
|
||||
}
|
||||
|
||||
cognition_trace.append({
|
||||
"step": step_num,
|
||||
"lane": lane_id,
|
||||
"segment_id": None,
|
||||
"operation": f"process_lane_{lane_id}",
|
||||
"input": {"segments": len(lane_segments)},
|
||||
"output": {"error": str(e)},
|
||||
"note": f"Lane {lane_id} processing failed (recoverable).",
|
||||
})
|
||||
|
||||
step_num += 1
|
||||
|
||||
# Fuse lane results
|
||||
fused_symbol = fuse_lanes(lane_results)
|
||||
|
||||
# Compute resonance
|
||||
resonance = compute_resonance(lane_results, context)
|
||||
|
||||
# Render output text
|
||||
output_text = render_output_text(fused_symbol, context)
|
||||
|
||||
elapsed = time.time() - start_time
|
||||
|
||||
@@ -340,7 +499,7 @@ def execute_with_lain(envelope: dict) -> dict:
|
||||
diagnostics = {
|
||||
"lane_timings": lane_timings,
|
||||
"errors": errors,
|
||||
"resonance": {},
|
||||
"resonance": resonance,
|
||||
"interface_version": INTERFACE_VERSION,
|
||||
"elapsed": elapsed,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user