bce6b6fa37
This commit completes the comprehensive glyph resonance awareness upgrade
with queryable resonance metrics, new instruction, and formal specification.
## Changes
### Phase 3: New GET_GLYPH_RESONANCE Instruction
- Added op_GET_GLYPH_RESONANCE to xic_ops.py for querying glyph resonance data
- Supports metrics: report, global, dominant, weight, lineage, contributor, frequency, grammar
- Results printed with [XIC-RESONANCE] prefix and stored in ctx._state
- Handles both full pipeline result (preferred) and fallback to resonance_metrics dict
- Updated OP_TABLE to include 10th operation
### Phase 4: Formal Specification & Demo
#### XIC_SEMANTICS_v1_5.md Updates
- Added comprehensive "Glyph Resonance Structure" section documenting:
- FusedSymbol dataclass with summary, glyph_ids, resonance_map
- GlyphResonanceMap with resonances dict and utility methods
- GlyphResonanceMetrics (weight, lineage_score, contributor_score, frequency_score, grammar_score)
- Example JSON structure from LAIN cognition
- Added "GET_GLYPH_RESONANCE" instruction semantics with:
- Signature and preconditions/postconditions
- Metric table describing all query types
- Detailed side effects and remarks
- Data access patterns
#### New Demo Program
- Created programs/demo_glyph_resonance.gx.json
- Two-chain demonstration:
- Chain 1: compression_theory glyph with report, global, dominant, weight queries
- Chain 2: neural_dynamics glyph with individual metric queries (lineage, contributor, frequency, grammar)
- Full instrumentation with CHAIN markers and LOG statements
#### Comprehensive Report
- Created XIC_GLYPH_RESONANCE_REPORT.md documenting:
- Executive summary of resonance awareness upgrade
- Detailed explanation of all components
- Architecture and data flow diagrams
- All 10 validation test results
- Usage examples and design decisions
- Backward compatibility guarantees
- Future extensibility notes
## Implementation Details
### Enhanced Data Structures (glyphos/symbolic_pipeline.py)
- GlyphResonanceMetrics: 5-dimensional resonance scoring
- GlyphResonanceMap: with get_glyph_resonance(), get_top_glyphs(), get_average_resonance()
- FusedSymbol.from_lain_result(): parses LAIN output structure
### Glyph Resonance Utilities
- extract_glyph_resonances(): extract per-glyph metrics from pipeline result
- get_dominant_glyphs(n): rank glyphs by weight
- format_glyph_resonance_report(): human-readable resonance output
### Enhanced CALL_GLYPH
- Now stores comprehensive resonance data in ctx._state["glyph_{glyph_id}"]
- Captures output_text, fused_symbol, resonance_metrics, global_resonance_score, steps
- Also stores full SymbolicPipelineResult for direct access
### New op_GET_GLYPH_RESONANCE
- Query stored resonance metrics with flexible metric selection
- Integrates with symbolic_pipeline utilities for full introspection
- Prints results and stores in ctx._state for programmatic access
## Exports (glyphos/__init__.py)
- GlyphResonanceMetrics
- GlyphResonanceMap
- extract_glyph_resonances
- get_dominant_glyphs
- format_glyph_resonance_report
## Testing
All 10 validation tests pass:
✅ GlyphResonanceMetrics instantiation
✅ GlyphResonanceMap methods (get_glyph_resonance, get_top_glyphs, get_average_resonance)
✅ FusedSymbol.from_lain_result() parsing
✅ extract_glyph_resonances() functionality
✅ get_dominant_glyphs() ranking
✅ format_glyph_resonance_report() generation
✅ OP_TABLE has GET_GLYPH_RESONANCE
✅ op_GET_GLYPH_RESONANCE callable
✅ demo_glyph_resonance.gx.json valid
✅ All exports available from glyphos
## Backward Compatibility
- Zero breaking changes
- All XIC v1 and v1.5 programs work unchanged
- New resonance features are additive
- Existing instruction signatures preserved
- Compressed mode execution unaffected
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
349 lines
14 KiB
Python
349 lines
14 KiB
Python
from dataclasses import dataclass, field
|
|
from typing import Dict, Any, Optional
|
|
from runtime_executor.runner import execute_gx, ExecutionError
|
|
|
|
|
|
@dataclass
|
|
class XICContext:
|
|
model_path: Optional[str] = None
|
|
mode: str = "chat"
|
|
params: Dict[str, Any] = field(default_factory=dict)
|
|
_state: Dict[str, Any] = field(default_factory=dict)
|
|
symbolic_mode: bool = False
|
|
|
|
|
|
def op_LOAD_MODEL(ctx: XICContext, *args):
|
|
"""LOAD_MODEL <path>: Load a .gx model file."""
|
|
if not args:
|
|
raise ValueError("LOAD_MODEL requires a path argument")
|
|
model_path = args[0]
|
|
ctx.model_path = str(model_path)
|
|
print(f"[XIC] Model loaded: {ctx.model_path}")
|
|
|
|
|
|
def op_SET_MODE(ctx: XICContext, *args):
|
|
"""SET_MODE <mode>: Set execution mode (chat, eval, benchmark, symbolic)."""
|
|
if not args:
|
|
raise ValueError("SET_MODE requires a mode argument")
|
|
ctx.mode = str(args[0])
|
|
if ctx.mode == "symbolic":
|
|
ctx.symbolic_mode = True
|
|
print(f"[XIC] Mode set to: {ctx.mode}")
|
|
|
|
|
|
def op_SET_PARAM(ctx: XICContext, *args):
|
|
"""SET_PARAM <key> <value>: Set a parameter."""
|
|
if len(args) < 2:
|
|
raise ValueError("SET_PARAM requires key and value arguments")
|
|
key = str(args[0])
|
|
value = args[1]
|
|
ctx.params[key] = value
|
|
print(f"[XIC] Parameter {key} = {value}")
|
|
|
|
|
|
def op_RUN_PROMPT(ctx: XICContext, *args):
|
|
"""RUN_PROMPT <prompt>: Execute prompt against loaded model or symbolic cognition.
|
|
|
|
Symbolic behavior (ctx.symbolic_mode=True):
|
|
- Routes through symbolic pipeline (run_symbolic_pipeline).
|
|
- Uses ctx.params["context"] for execution context.
|
|
- Stores full pipeline result in ctx._state["last_symbolic_pipeline"].
|
|
|
|
Compressed behavior (ctx.symbolic_mode=False):
|
|
- Requires model_path to be set via LOAD_MODEL.
|
|
- Routes to execute_gx() for compressed execution.
|
|
- Stores result in ctx._state["last_result"].
|
|
"""
|
|
if not args:
|
|
raise ValueError("RUN_PROMPT requires a prompt argument")
|
|
|
|
prompt = str(args[0])
|
|
|
|
if ctx.symbolic_mode:
|
|
from glyphos.symbolic_pipeline import run_symbolic_pipeline
|
|
pipeline_result = run_symbolic_pipeline(
|
|
prompt=prompt,
|
|
context=ctx.params.get("context")
|
|
)
|
|
print(f"[XIC-SYMBOLIC] {pipeline_result.output_text}")
|
|
ctx._state["last_symbolic_result"] = pipeline_result.output_text
|
|
ctx._state["last_symbolic_pipeline"] = pipeline_result
|
|
return
|
|
|
|
if not ctx.model_path:
|
|
raise ValueError("No model loaded. Use LOAD_MODEL first.")
|
|
|
|
try:
|
|
execution_context = execute_gx(
|
|
ctx.model_path,
|
|
trace=ctx.params.get("trace", False),
|
|
profile=ctx.params.get("profile", False)
|
|
)
|
|
|
|
print(f"[XIC] Execution complete")
|
|
print(f"[XIC] Result: {getattr(execution_context, 'result', 'OK')}")
|
|
ctx._state["last_result"] = execution_context
|
|
|
|
except ExecutionError as e:
|
|
print(f"[XIC] Execution error: {e}")
|
|
raise
|
|
except Exception as e:
|
|
print(f"[XIC] Unexpected error: {e}")
|
|
raise
|
|
|
|
|
|
def op_STREAM(ctx: XICContext, *args):
|
|
"""STREAM <prompt>: Execute and stream output line by line.
|
|
|
|
Symbolic behavior (ctx.symbolic_mode=True):
|
|
- Routes through symbolic pipeline.
|
|
- Streams output_text line by line with [XIC-STREAM] prefix.
|
|
- Stores pipeline result in ctx._state["last_symbolic_pipeline"].
|
|
|
|
Compressed behavior (ctx.symbolic_mode=False):
|
|
- Routes to execute_gx().
|
|
- Streams result line by line with [XIC-STREAM] prefix.
|
|
- Stores result in ctx._state["last_result"].
|
|
"""
|
|
if not args:
|
|
raise ValueError("STREAM requires a prompt argument")
|
|
prompt = str(args[0])
|
|
|
|
if ctx.symbolic_mode:
|
|
from glyphos.symbolic_pipeline import run_symbolic_pipeline
|
|
pipeline_result = run_symbolic_pipeline(
|
|
prompt=prompt,
|
|
context=ctx.params.get("context")
|
|
)
|
|
for chunk in str(pipeline_result.output_text).split("\n"):
|
|
if chunk.strip():
|
|
print(f"[XIC-STREAM] {chunk}")
|
|
ctx._state["last_symbolic_result"] = pipeline_result.output_text
|
|
ctx._state["last_symbolic_pipeline"] = pipeline_result
|
|
return
|
|
|
|
if not ctx.model_path:
|
|
raise ValueError("No model loaded. Use LOAD_MODEL first.")
|
|
|
|
try:
|
|
exec_ctx = execute_gx(
|
|
ctx.model_path,
|
|
trace=ctx.params.get("trace", False),
|
|
profile=ctx.params.get("profile", False),
|
|
)
|
|
result_text = str(getattr(exec_ctx, "result", "OK"))
|
|
for chunk in result_text.split("\n"):
|
|
if chunk.strip():
|
|
print(f"[XIC-STREAM] {chunk}")
|
|
ctx._state["last_result"] = exec_ctx
|
|
except ExecutionError as e:
|
|
print(f"[XIC] Execution error: {e}")
|
|
raise
|
|
except Exception as e:
|
|
print(f"[XIC] Unexpected error: {e}")
|
|
raise
|
|
|
|
|
|
def op_CHAIN(ctx: XICContext, *args):
|
|
"""CHAIN <label>: Mark start of a named chain; passes context forward."""
|
|
if not args:
|
|
raise ValueError("CHAIN requires a label argument")
|
|
label = str(args[0])
|
|
ctx.params["chain_label"] = label
|
|
print(f"[XIC-CHAIN] Entering chain: {label}")
|
|
|
|
|
|
def op_CALL_GLYPH(ctx: XICContext, *args):
|
|
"""CALL_GLYPH <glyph_id> <payload>: Invoke glyph-aware cognition with resonance tracking.
|
|
|
|
Routes through symbolic pipeline with explicit glyph_id parameter.
|
|
The glyph_id is propagated into the pipeline context and used for
|
|
glyph-aware symbolic transformations in the LAIN layer.
|
|
|
|
Stores comprehensive result with key "glyph_{glyph_id}" containing:
|
|
- output_text: Final text from cognition
|
|
- fused_symbol: Fused symbolic representation with glyph_ids and resonance_map
|
|
- resonance_metrics: Extracted per-glyph resonance scores (weight, lineage, contributor, etc.)
|
|
- global_resonance_score: Overall resonance from LAIN
|
|
- steps: List of symbolic pipeline steps
|
|
"""
|
|
if not args:
|
|
raise ValueError("CALL_GLYPH requires glyph_id argument")
|
|
glyph_id = str(args[0])
|
|
payload = str(args[1]) if len(args) > 1 else ""
|
|
|
|
from glyphos.symbolic_pipeline import (
|
|
run_symbolic_pipeline,
|
|
extract_glyph_resonances,
|
|
format_glyph_resonance_report,
|
|
)
|
|
|
|
glyph_context = dict(ctx.params.get("context", {}))
|
|
glyph_context["glyph_id"] = glyph_id
|
|
|
|
pipeline_result = run_symbolic_pipeline(
|
|
prompt=payload,
|
|
context=glyph_context,
|
|
glyph_id=glyph_id,
|
|
)
|
|
|
|
print(f"[XIC-GLYPH] {pipeline_result.output_text}")
|
|
|
|
# Extract resonance metrics
|
|
resonance_metrics = extract_glyph_resonances(pipeline_result)
|
|
global_resonance = 0.0
|
|
if pipeline_result.fused_symbol:
|
|
global_resonance = pipeline_result.fused_symbol.resonance_map.global_resonance_score
|
|
|
|
# Store comprehensive result
|
|
ctx._state[f"glyph_{glyph_id}"] = {
|
|
"output_text": pipeline_result.output_text,
|
|
"fused_symbol": {
|
|
"summary": pipeline_result.fused_symbol.summary if pipeline_result.fused_symbol else None,
|
|
"glyph_ids": pipeline_result.fused_symbol.glyph_ids if pipeline_result.fused_symbol else [],
|
|
} if pipeline_result.fused_symbol else None,
|
|
"resonance_metrics": resonance_metrics,
|
|
"global_resonance_score": global_resonance,
|
|
"steps": [{"name": s.name, "kind": s.kind, "payload": str(s.payload)[:100]}
|
|
for s in pipeline_result.steps],
|
|
}
|
|
|
|
# Also store for direct query access
|
|
ctx._state[f"glyph_{glyph_id}_pipeline_result"] = pipeline_result
|
|
|
|
|
|
def op_SET_CONTEXT(ctx: XICContext, *args):
|
|
"""SET_CONTEXT <key> <value>: Set symbolic/cognitive context key."""
|
|
if len(args) < 2:
|
|
raise ValueError("SET_CONTEXT requires key and value")
|
|
if "context" not in ctx.params:
|
|
ctx.params["context"] = {}
|
|
key = str(args[0])
|
|
value = args[1]
|
|
ctx.params["context"][key] = value
|
|
print(f"[XIC] Context {key} = {value}")
|
|
|
|
|
|
def op_LOG(ctx: XICContext, *args):
|
|
"""LOG <message>: Structured log from XIC program."""
|
|
message = str(args[0]) if args else ""
|
|
print(f"[XIC-LOG] {message}")
|
|
|
|
|
|
def op_GET_GLYPH_RESONANCE(ctx: XICContext, *args):
|
|
"""GET_GLYPH_RESONANCE <glyph_id> [metric]: Query glyph resonance metrics from previous CALL_GLYPH.
|
|
|
|
Retrieves resonance data stored by CALL_GLYPH and provides:
|
|
- No metric arg: Returns formatted resonance report for the glyph
|
|
- metric="weight" | "lineage" | "contributor" | "frequency" | "grammar": Returns specific metric for glyph
|
|
- metric="global": Returns global resonance score
|
|
- metric="dominant": Returns top 5 dominant glyphs by weight
|
|
|
|
Results are printed and stored in ctx._state["resonance_query_<glyph_id>_<metric>"]
|
|
"""
|
|
if not args:
|
|
raise ValueError("GET_GLYPH_RESONANCE requires glyph_id argument")
|
|
|
|
glyph_id = str(args[0])
|
|
metric = str(args[1]) if len(args) > 1 else None
|
|
|
|
# Try to find the stored glyph result
|
|
glyph_key = f"glyph_{glyph_id}"
|
|
if glyph_key not in ctx._state:
|
|
print(f"[XIC-RESONANCE] No resonance data for glyph: {glyph_id}")
|
|
ctx._state[f"resonance_query_{glyph_id}_notfound"] = None
|
|
return
|
|
|
|
glyph_data = ctx._state[glyph_key]
|
|
|
|
# If we have the pipeline result object, use it to regenerate report
|
|
pipeline_key = f"glyph_{glyph_id}_pipeline_result"
|
|
if pipeline_key in ctx._state:
|
|
from glyphos.symbolic_pipeline import (
|
|
format_glyph_resonance_report,
|
|
extract_glyph_resonances,
|
|
get_dominant_glyphs,
|
|
)
|
|
pipeline_result = ctx._state[pipeline_key]
|
|
|
|
if metric is None or metric == "report":
|
|
report = format_glyph_resonance_report(pipeline_result)
|
|
print(f"[XIC-RESONANCE] Report for {glyph_id}:\n{report}")
|
|
ctx._state[f"resonance_query_{glyph_id}_report"] = report
|
|
elif metric == "global":
|
|
if pipeline_result.fused_symbol:
|
|
score = pipeline_result.fused_symbol.resonance_map.global_resonance_score
|
|
print(f"[XIC-RESONANCE] Global resonance for {glyph_id}: {score:.3f}")
|
|
ctx._state[f"resonance_query_{glyph_id}_global"] = score
|
|
else:
|
|
print(f"[XIC-RESONANCE] No fused_symbol for {glyph_id}")
|
|
ctx._state[f"resonance_query_{glyph_id}_global"] = None
|
|
elif metric == "dominant":
|
|
dominant = get_dominant_glyphs(pipeline_result, n=5)
|
|
print(f"[XIC-RESONANCE] Dominant glyphs for {glyph_id}:")
|
|
for glyph, weight in dominant:
|
|
print(f" {glyph}: {weight:.3f}")
|
|
ctx._state[f"resonance_query_{glyph_id}_dominant"] = dominant
|
|
elif metric in ["weight", "lineage", "contributor", "frequency", "grammar"]:
|
|
resonances = extract_glyph_resonances(pipeline_result)
|
|
if glyph_id in resonances:
|
|
metric_val = resonances[glyph_id].get(
|
|
metric if metric != "lineage" else "lineage_score",
|
|
resonances[glyph_id].get(f"{metric}_score") if metric != "weight" else None
|
|
)
|
|
if metric == "lineage":
|
|
metric_val = resonances[glyph_id].get("lineage_score")
|
|
elif metric == "contributor":
|
|
metric_val = resonances[glyph_id].get("contributor_score")
|
|
elif metric == "frequency":
|
|
metric_val = resonances[glyph_id].get("frequency_score")
|
|
elif metric == "grammar":
|
|
metric_val = resonances[glyph_id].get("grammar_score")
|
|
|
|
if metric_val is not None:
|
|
print(f"[XIC-RESONANCE] {metric} for {glyph_id}: {metric_val:.3f}")
|
|
ctx._state[f"resonance_query_{glyph_id}_{metric}"] = metric_val
|
|
else:
|
|
print(f"[XIC-RESONANCE] Metric '{metric}' not found for {glyph_id}")
|
|
ctx._state[f"resonance_query_{glyph_id}_{metric}"] = None
|
|
else:
|
|
print(f"[XIC-RESONANCE] Glyph {glyph_id} not in resonance data")
|
|
ctx._state[f"resonance_query_{glyph_id}_{metric}"] = None
|
|
else:
|
|
print(f"[XIC-RESONANCE] Unknown metric: {metric}")
|
|
ctx._state[f"resonance_query_{glyph_id}_{metric}"] = None
|
|
else:
|
|
# Fallback: use stored resonance_metrics if available
|
|
if "resonance_metrics" in glyph_data:
|
|
resonance_metrics = glyph_data["resonance_metrics"]
|
|
if metric is None:
|
|
print(f"[XIC-RESONANCE] Resonance metrics for {glyph_id}:")
|
|
for glyph, metrics_dict in resonance_metrics.items():
|
|
print(f" {glyph}: weight={metrics_dict.get('weight', 0):.3f}")
|
|
ctx._state[f"resonance_query_{glyph_id}_report"] = resonance_metrics
|
|
elif metric == "global":
|
|
score = glyph_data.get("global_resonance_score", 0.0)
|
|
print(f"[XIC-RESONANCE] Global resonance for {glyph_id}: {score:.3f}")
|
|
ctx._state[f"resonance_query_{glyph_id}_global"] = score
|
|
else:
|
|
print(f"[XIC-RESONANCE] Specific metric query requires pipeline result")
|
|
ctx._state[f"resonance_query_{glyph_id}_{metric}"] = None
|
|
else:
|
|
print(f"[XIC-RESONANCE] No resonance metrics available for {glyph_id}")
|
|
ctx._state[f"resonance_query_{glyph_id}_notfound"] = None
|
|
|
|
|
|
# Operation dispatch table
|
|
OP_TABLE = {
|
|
"LOAD_MODEL": op_LOAD_MODEL,
|
|
"SET_MODE": op_SET_MODE,
|
|
"SET_PARAM": op_SET_PARAM,
|
|
"SET_CONTEXT": op_SET_CONTEXT,
|
|
"RUN_PROMPT": op_RUN_PROMPT,
|
|
"STREAM": op_STREAM,
|
|
"CHAIN": op_CHAIN,
|
|
"CALL_GLYPH": op_CALL_GLYPH,
|
|
"GET_GLYPH_RESONANCE": op_GET_GLYPH_RESONANCE,
|
|
"LOG": op_LOG,
|
|
}
|