forked from genewildish/Mainline
feat(integration): Complete feature rewrite with pipeline architecture, effects system, and display improvements
Major changes: - Pipeline architecture with capability-based dependency resolution - Effects plugin system with performance monitoring - Display abstraction with multiple backends (terminal, null, websocket) - Camera system for viewport scrolling - Sensor framework for real-time input - Command-and-control system via ntfy - WebSocket display backend for browser clients - Comprehensive test suite and documentation Issue #48: ADR for preset scripting language included This commit consolidates 110 individual commits into a single feature integration that can be reviewed and tested before further refinement.
This commit is contained in:
223
docs/PIPELINE.md
Normal file
223
docs/PIPELINE.md
Normal file
@@ -0,0 +1,223 @@
|
||||
# Mainline Pipeline
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
The Mainline pipeline uses a **Stage-based architecture** with **capability-based dependency resolution**. Stages declare capabilities (what they provide) and dependencies (what they need), and the Pipeline resolves dependencies using prefix matching.
|
||||
|
||||
```
|
||||
Source Stage → Render Stage → Effect Stages → Display Stage
|
||||
↓
|
||||
Camera Stage (provides camera.state capability)
|
||||
```
|
||||
|
||||
### Capability-Based Dependency Resolution
|
||||
|
||||
Stages declare capabilities and dependencies:
|
||||
- **Capabilities**: What the stage provides (e.g., `source`, `render.output`, `display.output`, `camera.state`)
|
||||
- **Dependencies**: What the stage needs (e.g., `source`, `render.output`, `camera.state`)
|
||||
|
||||
The Pipeline resolves dependencies using **prefix matching**:
|
||||
- `"source"` matches `"source.headlines"`, `"source.poetry"`, etc.
|
||||
- `"camera.state"` matches the camera state capability provided by `CameraClockStage`
|
||||
- This allows flexible composition without hardcoding specific stage names
|
||||
|
||||
### Minimum Capabilities
|
||||
|
||||
The pipeline requires these minimum capabilities to function:
|
||||
- `"source"` - Data source capability (provides raw items)
|
||||
- `"render.output"` - Rendered content capability
|
||||
- `"display.output"` - Display output capability
|
||||
- `"camera.state"` - Camera state for viewport filtering
|
||||
|
||||
These are automatically injected if missing by the `ensure_minimum_capabilities()` method.
|
||||
|
||||
### Stage Registry
|
||||
|
||||
The `StageRegistry` discovers and registers stages automatically:
|
||||
- Scans `engine/stages/` for stage implementations
|
||||
- Registers stages by their declared capabilities
|
||||
- Enables runtime stage discovery and composition
|
||||
|
||||
## Stage-Based Pipeline Flow
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph Stages["Stage Pipeline"]
|
||||
subgraph SourceStage["Source Stage (provides: source.*)"]
|
||||
Headlines[HeadlinesSource]
|
||||
Poetry[PoetrySource]
|
||||
Pipeline[PipelineSource]
|
||||
end
|
||||
|
||||
subgraph RenderStage["Render Stage (provides: render.*)"]
|
||||
Render[RenderStage]
|
||||
Canvas[Canvas]
|
||||
Camera[Camera]
|
||||
end
|
||||
|
||||
subgraph EffectStages["Effect Stages (provides: effect.*)"]
|
||||
Noise[NoiseEffect]
|
||||
Fade[FadeEffect]
|
||||
Glitch[GlitchEffect]
|
||||
Firehose[FirehoseEffect]
|
||||
Hud[HudEffect]
|
||||
end
|
||||
|
||||
subgraph DisplayStage["Display Stage (provides: display.*)"]
|
||||
Terminal[TerminalDisplay]
|
||||
Pygame[PygameDisplay]
|
||||
WebSocket[WebSocketDisplay]
|
||||
Null[NullDisplay]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph Capabilities["Capability Map"]
|
||||
SourceCaps["source.headlines<br/>source.poetry<br/>source.pipeline"]
|
||||
RenderCaps["render.output<br/>render.canvas"]
|
||||
EffectCaps["effect.noise<br/>effect.fade<br/>effect.glitch"]
|
||||
DisplayCaps["display.output<br/>display.terminal"]
|
||||
end
|
||||
|
||||
SourceStage --> RenderStage
|
||||
RenderStage --> EffectStages
|
||||
EffectStages --> DisplayStage
|
||||
|
||||
SourceStage --> SourceCaps
|
||||
RenderStage --> RenderCaps
|
||||
EffectStages --> EffectCaps
|
||||
DisplayStage --> DisplayCaps
|
||||
|
||||
style SourceStage fill:#f9f,stroke:#333
|
||||
style RenderStage fill:#bbf,stroke:#333
|
||||
style EffectStages fill:#fbf,stroke:#333
|
||||
style DisplayStage fill:#bfb,stroke:#333
|
||||
```
|
||||
|
||||
## Stage Adapters
|
||||
|
||||
Existing components are wrapped as Stages via adapters:
|
||||
|
||||
### Source Stage Adapter
|
||||
- Wraps `HeadlinesDataSource`, `PoetryDataSource`, etc.
|
||||
- Provides `source.*` capabilities
|
||||
- Fetches data and outputs to pipeline buffer
|
||||
|
||||
### Render Stage Adapter
|
||||
- Wraps `StreamController`, `Camera`, `render_ticker_zone`
|
||||
- Provides `render.output` capability
|
||||
- Processes content and renders to canvas
|
||||
|
||||
### Effect Stage Adapter
|
||||
- Wraps `EffectChain` and individual effect plugins
|
||||
- Provides `effect.*` capabilities
|
||||
- Applies visual effects to rendered content
|
||||
|
||||
### Display Stage Adapter
|
||||
- Wraps `TerminalDisplay`, `PygameDisplay`, etc.
|
||||
- Provides `display.*` capabilities
|
||||
- Outputs final buffer to display backend
|
||||
|
||||
## Pipeline Mutation API
|
||||
|
||||
The Pipeline supports dynamic mutation during runtime:
|
||||
|
||||
### Core Methods
|
||||
- `add_stage(name, stage, initialize=True)` - Add a stage
|
||||
- `remove_stage(name, cleanup=True)` - Remove a stage and rebuild execution order
|
||||
- `replace_stage(name, new_stage, preserve_state=True)` - Replace a stage
|
||||
- `swap_stages(name1, name2)` - Swap two stages
|
||||
- `move_stage(name, after=None, before=None)` - Move a stage in execution order
|
||||
- `enable_stage(name)` / `disable_stage(name)` - Enable/disable stages
|
||||
|
||||
### Safety Checks
|
||||
- `can_hot_swap(name)` - Check if a stage can be safely hot-swapped
|
||||
- `cleanup_stage(name)` - Clean up specific stage without removing it
|
||||
|
||||
### WebSocket Commands
|
||||
The mutation API is accessible via WebSocket for remote control:
|
||||
```json
|
||||
{"action": "remove_stage", "stage": "stage_name"}
|
||||
{"action": "swap_stages", "stage1": "name1", "stage2": "name2"}
|
||||
{"action": "enable_stage", "stage": "stage_name"}
|
||||
{"action": "cleanup_stage", "stage": "stage_name"}
|
||||
```
|
||||
|
||||
## Camera Modes
|
||||
|
||||
The Camera supports the following modes:
|
||||
|
||||
- **FEED**: Single item view (static or rapid cycling)
|
||||
- **SCROLL**: Smooth vertical scrolling (movie credits style)
|
||||
- **HORIZONTAL**: Left/right movement
|
||||
- **OMNI**: Combination of vertical and horizontal
|
||||
- **FLOATING**: Sinusoidal/bobbing motion
|
||||
- **BOUNCE**: DVD-style bouncing off edges
|
||||
- **RADIAL**: Polar coordinate scanning (radar sweep)
|
||||
|
||||
Note: Camera state is provided by `CameraClockStage` (capability: `camera.state`) which updates independently of data flow. The `CameraStage` applies viewport transformations (capability: `camera`).
|
||||
|
||||
## Animation & Presets
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Preset["Preset"]
|
||||
PP[PipelineParams]
|
||||
AC[AnimationController]
|
||||
end
|
||||
|
||||
subgraph AnimationController["AnimationController"]
|
||||
Clock[Clock]
|
||||
Events[Events]
|
||||
Triggers[Triggers]
|
||||
end
|
||||
|
||||
subgraph Triggers["Trigger Types"]
|
||||
TIME[TIME]
|
||||
FRAME[FRAME]
|
||||
CYCLE[CYCLE]
|
||||
COND[CONDITION]
|
||||
MANUAL[MANUAL]
|
||||
end
|
||||
|
||||
PP --> AC
|
||||
Clock --> AC
|
||||
Events --> AC
|
||||
Triggers --> Events
|
||||
```
|
||||
|
||||
## Camera Modes State Diagram
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Vertical
|
||||
Vertical --> Horizontal: mode change
|
||||
Horizontal --> Omni: mode change
|
||||
Omni --> Floating: mode change
|
||||
Floating --> Trace: mode change
|
||||
Trace --> Vertical: mode change
|
||||
|
||||
state Vertical {
|
||||
[*] --> ScrollUp
|
||||
ScrollUp --> ScrollUp: +y each frame
|
||||
}
|
||||
|
||||
state Horizontal {
|
||||
[*] --> ScrollLeft
|
||||
ScrollLeft --> ScrollLeft: +x each frame
|
||||
}
|
||||
|
||||
state Omni {
|
||||
[*] --> Diagonal
|
||||
Diagonal --> Diagonal: +x, +y each frame
|
||||
}
|
||||
|
||||
state Floating {
|
||||
[*] --> Bobbing
|
||||
Bobbing --> Bobbing: sin(time) for x,y
|
||||
}
|
||||
|
||||
state Trace {
|
||||
[*] --> FollowPath
|
||||
FollowPath --> FollowPath: node by node
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user