docs(graph): Add DSL documentation and examples

Add comprehensive documentation for the graph-based pipeline DSL:

- docs/graph-dsl.md: Complete DSL reference with TOML, Python, and CLI syntax
- docs/GRAPH_SYSTEM_SUMMARY.md: Implementation overview and architecture
- examples/graph_dsl_demo.py: Demonstrates imperative Python API usage
- examples/test_graph_integration.py: Integration test verifying pipeline execution

The documentation follows a wiki-like approach with navigable structure:
- Overview section explaining the concept
- Syntax examples for each format (TOML, Python, CLI)
- Node type reference table
- Advanced features section
- Comparison with old XYZStage approach

This provides users with multiple entry points to understand and use the
new graph-based pipeline system.
This commit is contained in:
2026-03-21 19:26:59 -07:00
parent 19fe87573d
commit 915598629a
5 changed files with 853 additions and 0 deletions

136
examples/graph_dsl_demo.py Normal file
View File

@@ -0,0 +1,136 @@
#!/usr/bin/env python3
"""
Demo script showing the new graph-based DSL for pipeline configuration.
This demonstrates how to define pipelines using the graph abstraction,
which is more intuitive than the verbose XYZStage naming convention.
"""
from engine.effects.plugins import discover_plugins
from engine.pipeline.graph import Graph, NodeType
from engine.pipeline.graph_adapter import graph_to_pipeline, dict_to_pipeline
def demo_imperative_api():
"""Demo: Imperative Python API for building graphs."""
print("=== Imperative Python API ===")
graph = Graph()
graph.node("source", NodeType.SOURCE, source="headlines")
graph.node("camera", NodeType.CAMERA, mode="scroll", speed=1.0)
graph.node("noise", NodeType.EFFECT, effect="noise", intensity=0.3)
graph.node("display", NodeType.DISPLAY, backend="null")
# Connect nodes in a chain
graph.chain("source", "camera", "noise", "display")
# Validate the graph
errors = graph.validate()
if errors:
print(f"Validation errors: {errors}")
return
# Convert to pipeline
pipeline = graph_to_pipeline(graph, viewport_width=80, viewport_height=24)
print(f"Pipeline created with {len(pipeline._stages)} stages:")
for name, stage in pipeline._stages.items():
print(f" - {name}: {stage.__class__.__name__}")
return pipeline
def demo_dict_api():
"""Demo: Dictionary-based API for building graphs."""
print("\n=== Dictionary API ===")
data = {
"nodes": {
"source": "headlines",
"camera": {"type": "camera", "mode": "scroll", "speed": 1.0},
"noise": {"type": "effect", "effect": "noise", "intensity": 0.5},
"fade": {"type": "effect", "effect": "fade", "intensity": 0.8},
"display": {"type": "display", "backend": "null"},
},
"connections": ["source -> camera -> noise -> fade -> display"],
}
pipeline = dict_to_pipeline(data, viewport_width=80, viewport_height=24)
print(f"Pipeline created with {len(pipeline._stages)} stages:")
for name, stage in pipeline._stages.items():
print(f" - {name}: {stage.__class__.__name__}")
return pipeline
def demo_graph_validation():
"""Demo: Graph validation."""
print("\n=== Graph Validation ===")
# Create a graph with a cycle
graph = Graph()
graph.node("a", NodeType.SOURCE)
graph.node("b", NodeType.CAMERA)
graph.node("c", NodeType.DISPLAY)
graph.connect("a", "b")
graph.connect("b", "c")
graph.connect("c", "a") # Creates cycle
errors = graph.validate()
print(f"Cycle detection errors: {errors}")
# Create a valid graph
graph2 = Graph()
graph2.node("source", NodeType.SOURCE, source="headlines")
graph2.node("display", NodeType.DISPLAY, backend="null")
graph2.connect("source", "display")
errors2 = graph2.validate()
print(f"Valid graph errors: {errors2}")
def demo_node_types():
"""Demo: Different node types."""
print("\n=== Node Types ===")
graph = Graph()
# Source node
graph.node("headlines", NodeType.SOURCE, source="headlines")
print("✓ Source node created")
# Camera node with different modes
graph.node("camera_scroll", NodeType.CAMERA, mode="scroll", speed=1.0)
graph.node("camera_feed", NodeType.CAMERA, mode="feed", speed=0.5)
graph.node("camera_horizontal", NodeType.CAMERA, mode="horizontal", speed=1.0)
print("✓ Camera nodes created (scroll, feed, horizontal)")
# Effect nodes
graph.node("noise", NodeType.EFFECT, effect="noise", intensity=0.3)
graph.node("fade", NodeType.EFFECT, effect="fade", intensity=0.8)
print("✓ Effect nodes created (noise, fade)")
# Positioning node
graph.node("position", NodeType.POSITION, mode="mixed")
print("✓ Positioning node created")
# Display nodes
graph.node("terminal", NodeType.DISPLAY, backend="terminal")
graph.node("null", NodeType.DISPLAY, backend="null")
print("✓ Display nodes created")
print(f"\nTotal nodes: {len(graph.nodes)}")
if __name__ == "__main__":
# Discover effect plugins first
discover_plugins()
# Run demos
demo_imperative_api()
demo_dict_api()
demo_graph_validation()
demo_node_types()
print("\n=== Demo Complete ===")