From b2404068ddaefa41b32769936084760e6fbb3c5b Mon Sep 17 00:00:00 2001 From: David Gwilliam Date: Fri, 20 Mar 2026 03:39:33 -0700 Subject: [PATCH] docs: Add ADR for preset scripting language (Issue #48) --- .../adr-preset-scripting-language.md | 217 ++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 docs/proposals/adr-preset-scripting-language.md diff --git a/docs/proposals/adr-preset-scripting-language.md b/docs/proposals/adr-preset-scripting-language.md new file mode 100644 index 0000000..fe72118 --- /dev/null +++ b/docs/proposals/adr-preset-scripting-language.md @@ -0,0 +1,217 @@ +# ADR: Preset Scripting Language for Mainline + +## Status: Draft + +## Context + +We need to evaluate whether to add a scripting language for authoring presets in Mainline, replacing or augmenting the current TOML-based preset system. The goals are: + +1. **Expressiveness**: More powerful than TOML for describing dynamic, procedural, or dataflow-based presets +2. **Live coding**: Support hot-reloading of presets during runtime (like TidalCycles or Sonic Pi) +3. **Testing**: Include assertion language to package tests alongside presets +4. **Toolchain**: Consider packaging and build processes + +### Current State + +The current preset system uses TOML files (`presets.toml`) with a simple structure: + +```toml +[presets.demo-base] +description = "Demo: Base preset for effect hot-swapping" +source = "headlines" +display = "terminal" +camera = "feed" +effects = [] # Demo script will add/remove effects dynamically +camera_speed = 0.1 +viewport_width = 80 +viewport_height = 24 +``` + +This is declarative and static. It cannot express: +- Conditional logic based on runtime state +- Dataflow between pipeline stages +- Procedural generation of stage configurations +- Assertions or validation of preset behavior + +### Problems with TOML + +- No way to express dependencies between effects or stages +- Cannot describe temporal/animated behavior +- No support for sensor bindings or parametric animations +- Static configuration cannot adapt to runtime conditions +- No built-in testing/assertion mechanism + +## Approaches + +### 1. Visual Dataflow Language (PureData-style) + +Inspired by Pure Data (Pd), Max/MSP, and TouchDesigner: + +**Pros:** +- Intuitive for creative coding and live performance +- Strong model for real-time parameter modulation +- Matches the "patcher" paradigm already seen in pipeline architecture +- Rich ecosystem of visual programming tools + +**Cons:** +- Complex to implement from scratch +- Requires dedicated GUI editor +- Harder to version control (binary/graph formats) +- Mermaid diagrams alone aren't sufficient for this + +**Tools to explore:** +- libpd (Pure Data bindings for other languages) +- Node-based frameworks (node-red, various DSP tools) +- TouchDesigner-like approaches + +### 2. Textual DSL (TidalCycles-style) + +Domain-specific language focused on pattern transformation: + +**Pros:** +- Lightweight, fast iteration +- Easy to version control (text files) +- Can express complex patterns with minimal syntax +- Proven in livecoding community + +**Cons:** +- Learning curve for non-programmers +- Less visual than PureData approach + +**Example (hypothetical):** +``` +preset my-show { + source: headlines + + every 8s { + effect noise: intensity = (0.5 <-> 1.0) + } + + on mic.level > 0.7 { + effect glitch: intensity += 0.2 + } +} +``` + +### 3. Embed Existing Language + +Embed Lua, Python, or JavaScript: + +**Pros:** +- Full power of general-purpose language +- Existing tooling, testing frameworks +- Easy to integrate (many embeddable interpreters) + +**Cons:** +- Security concerns with running user code +- May be overkill for simple presets +- Testing/assertion system must be built on top + +**Tools:** +- Lua (lightweight, fast) +- Python (rich ecosystem, but heavier) +- QuickJS (small, embeddable JS) + +### 4. Hybrid Approach + +Visual editor generates textual DSL that compiles to Python: + +**Pros:** +- Best of both worlds +- Can start with simple DSL and add editor later + +**Cons:** +- More complex initial implementation + +## Requirements Analysis + +### Must Have +- [ ] Express pipeline stage configurations (source, effects, camera, display) +- [ ] Support parameter bindings to sensors +- [ ] Hot-reloading during runtime +- [ ] Integration with existing Pipeline architecture + +### Should Have +- [ ] Basic assertion language for testing +- [ ] Ability to define custom abstractions/modules +- [ ] Version control friendly (text-based) + +### Could Have +- [ ] Visual node-based editor +- [ ] Real-time visualization of dataflow +- [ ] MIDI/OSC support for external controllers + +## User Stories (Proposed) + +### Spike Stories (Investigation) + +**Story 1: Evaluate DSL Parsing Tools** +> As a developer, I want to understand the available Python DSL parsing libraries (Lark, parsy, pyparsing) so that I can choose the right tool for implementing a preset DSL. +> +> **Acceptance**: Document pros/cons of 3+ parsing libraries with small proof-of-concept experiments + +**Story 2: Research Livecoding Languages** +> As a developer, I want to understand how TidalCycles, Sonic Pi, and PureData handle hot-reloading and pattern generation so that I can apply similar techniques to Mainline. +> +> **Acceptance**: Document key architectural patterns from 2+ livecoding systems + +**Story 3: Prototype Textual DSL** +> As a preset author, I want to write presets in a simple textual DSL that supports basic conditionals and sensor bindings. +> +> **Acceptance**: Create a prototype DSL that can parse a sample preset and convert to PipelineConfig + +**Story 4: Investigate Assertion/Testing Approaches** +> As a quality engineer, I want to include assertions with presets so that preset behavior can be validated automatically. +> +> **Acceptance**: Survey testing patterns in livecoding and propose assertion syntax + +### Implementation Stories (Future) + +**Story 5: Implement Core DSL Parser** +> As a preset author, I want to write presets in a textual DSL that supports sensors, conditionals, and parameter bindings. +> +> **Acceptance**: DSL parser handles the core syntax, produces valid PipelineConfig + +**Story 6: Hot-Reload System** +> As a performer, I want to edit preset files and see changes reflected in real-time without restarting. +> +> **Acceptance**: File watcher + pipeline mutation API integration works + +**Story 7: Assertion Language** +> As a preset author, I want to include assertions that validate sensor values or pipeline state. +> +> **Acceptance**: Assertions can run as part of preset execution and report pass/fail + +**Story 8: Toolchain/Packaging** +> As a preset distributor, I want to package presets with dependencies for easy sharing. +> +> **Acceptance**: Can create, build, and install a preset package + +## Decision + +**Recommend: Start with textual DSL approach (Option 2/4)** + +Rationale: +- Lowest barrier to entry (text files, version control) +- Can evolve to hybrid later if visual editor is needed +- Strong precedents in livecoding community (TidalCycles, Sonic Pi) +- Enables hot-reloading naturally +- Assertion language can be part of the DSL syntax + +**Not recommending Mermaid**: Mermaid is excellent for documentation and visualization, but it's a diagramming tool, not a programming language. It cannot express the logic, conditionals, and sensor bindings we need. + +## Next Steps + +1. Execute Spike Stories 1-4 to reduce uncertainty +2. Create minimal viable DSL syntax +3. Prototype hot-reloading with existing preset system +4. Evaluate whether visual editor adds sufficient value to warrant complexity + +## References + +- Pure Data: https://puredata.info/ +- TidalCycles: https://tidalcycles.org/ +- Sonic Pi: https://sonic-pi.net/ +- Lark parser: https://lark-parser.readthedocs.io/ +- Mainline Pipeline Architecture: `engine/pipeline/` +- Current Presets: `presets.toml`