Files
sideline/.opencode/skills/mainline-sensors/SKILL.md
David Gwilliam b926b346ad fix: resolve terminal display wobble and effect dimension stability
- Fix TerminalDisplay: add screen clear each frame (cursor home + erase down)
- Fix CameraStage: use set_canvas_size instead of read-only viewport properties
- Fix Glitch effect: preserve visible line lengths, remove cursor positioning
- Fix Fade effect: return original line when fade=0 instead of empty string
- Fix Noise effect: use input line length instead of terminal_width
- Remove HUD effect from all presets (redundant with border FPS display)
- Add regression tests for effect dimension stability
- Add docs/ARCHITECTURE.md with Mermaid diagrams
- Add mise tasks: diagram-ascii, diagram-validate, diagram-check
- Move markdown docs to docs/ (ARCHITECTURE, Refactor, hardware specs)
- Remove redundant requirements files (use pyproject.toml)
- Add *.dot and *.png to .gitignore

Closes #25
2026-03-18 03:37:53 -07:00

2.8 KiB

name, description, compatibility, metadata
name description compatibility metadata
mainline-sensors Sensor framework for real-time input in Mainline opencode
audience source_type
developers codebase

What This Skill Covers

This skill covers Mainline's sensor framework - how to use, create, and integrate sensors for real-time input.

Key Concepts

Sensor Base Class (engine/sensors/init.py)

class Sensor(ABC):
    name: str
    unit: str = ""
    
    @property
    def available(self) -> bool:
        """Whether sensor is currently available"""
        return True
    
    @abstractmethod
    def read(self) -> SensorValue | None:
        """Read current sensor value"""
        ...
    
    def start(self) -> None:
        """Initialize sensor (optional)"""
        pass
    
    def stop(self) -> None:
        """Clean up sensor (optional)"""
        pass

SensorValue Dataclass

@dataclass
class SensorValue:
    sensor_name: str
    value: float
    timestamp: float
    unit: str = ""

SensorRegistry

Discovers and manages sensors globally:

from engine.sensors import SensorRegistry
registry = SensorRegistry()
sensor = registry.get("mic")

SensorStage

Pipeline adapter that provides sensor values to effects:

from engine.pipeline.adapters import SensorStage
stage = SensorStage(sensor_name="mic")

Built-in Sensors

Sensor File Description
MicSensor sensors/mic.py Microphone input (RMS dB)
OscillatorSensor sensors/oscillator.py Test sine wave generator
PipelineMetricsSensor sensors/pipeline_metrics.py FPS, frame time, etc.

Param Bindings

Effects declare sensor-to-param mappings:

class GlitchEffect(EffectPlugin):
    param_bindings = {
        "intensity": {"sensor": "mic", "transform": "linear"},
    }

Transform Functions

  • linear - Direct mapping to param range
  • exponential - Exponential scaling
  • threshold - Binary on/off

Adding a New Sensor

  1. Create engine/sensors/my_sensor.py
  2. Inherit from Sensor ABC
  3. Implement required methods
  4. Register in SensorRegistry

Example:

class MySensor(Sensor):
    name = "my-sensor"
    unit = "units"
    
    def read(self) -> SensorValue | None:
        return SensorValue(
            sensor_name=self.name,
            value=self._read_hardware(),
            timestamp=time.time(),
            unit=self.unit
        )

Using Sensors in Effects

Access sensor values via EffectContext:

def process(self, buf, ctx):
    mic_level = ctx.get_sensor_value("mic")
    if mic_level and mic_level > 0.5:
        # Apply intense effect
        ...

Or via param_bindings (automatic):

# If intensity is bound to "mic", it's automatically 
# available in self.config.intensity