Skip to content

Swang (Swan Language): deterministic musical DSL, fractal pattern algebra and script-generating composers #108

Description

@PhysShell

Classification

  • Change type: enhancement / authoring language, deterministic composition and research tooling
  • Priority: P2 strategic — high differentiating value, but must land as bounded vertical slices rather than a compiler-shaped side quest
  • Expected value: very high for rapid idea testing, reproducible experiments, human-in-the-loop editing and explainable generation
  • Estimated effort: high overall; low-to-medium per staged slice
  • Implementation risk: high if Swang invents a competing score model, hides non-determinism, or grows into a general-purpose language
  • Recommendation: YES — adopt as a roadmap direction, beginning with a minimal pattern/rhythm slice
  • Stage ownership: candidate for the next append-only stage after S15, tentatively S16; the number becomes canonical only through the normal stage/ADR update
  • Dependencies: canonical Score, S6 generation, RhythmTemplate; richer pitch/fretboard realization can consume ADR-0018/0019 work later
  • Related future consumers: S7 graph/DP, S8 preview/cockpit, S9 feedback, S11 region regeneration, S13 ComplementArranger, S15 TonalContext after its frozen contracts are explicitly reopened
  • TonalContext status: Phase 1 remains ACCEPTED / CLOSED / FROZEN; this issue must not smuggle automatic scope selection, confidence thresholds or generation integration into Swang

Thesis

Add Swang (Swan Language), a deterministic musical authoring DSL for Griff:

high-level musical intent
  -> typed structural/pattern operations
  -> exact canonical events where needed
  -> Griff validation, scoring and physical guitar realization

Swang should be to Griff what a high-level assembler is to machine code:

  • expressive constructs for generation, arrangement and transformation;
  • deterministic lowering into inspectable operations;
  • an exact escape hatch for notes, rests, groups, techniques and positions;
  • no replacement for Griff's canonical Score model.

The immediate product value is not “write an entire programming language”. It is replacing unrepeatable walls of UI knobs with readable, diffable, executable musical recipes.

- depth 2
- density_decay 0.90
+ depth 3
+ density_decay 0.72

A saved script should fully explain and reproduce the experiment.

Why Griff

Griff already has the correct execution substrate:

Score -> MasterBar -> Track -> Voice -> EventGroup -> AtomEvent

It also already separates:

  • MIDI/GP adapters from the model;
  • rhythm templates from pitch strategies;
  • generation from reranking;
  • relation-as-spec from ComplementArranger execution;
  • musical pitch from later fretboard realization;
  • measured facts from uncertain tonal inference.

Swang should compose these capabilities. It must not create SwangNote, SwangBar, and SwangScore as a second permanent domain hierarchy that then drifts from griff-core until both require diplomatic relations.

Language levels

L2 — musical intent / executable recipes

part guitar_b = complement guitar_a {
    relation rhythm_lock
    register below 12st
    density 0.65
    contour contrary
    technique_overlap max 0.25
    seed 42
}

L2 compiles relative intent into existing absolute requests and policies:

ComplementSpec / RelationMode
GenerationAsk / RuleGenerationRequest
RhythmTemplate palette
pitch/register constraints
scoring policy
validation and provenance

L1 — pattern algebra and bounded transformations

pattern seed = ascii {
    X . X
    X X .
    . X X
}

pattern expanded = seed
    |> fractalize(depth = 3, density_decay = 0.8, budget = 1024)
    |> linearize(snake)
    |> fit(bars = 4)
    |> preserve(downbeats)

Initial algebra candidates:

repeat
rotate
mirror
stretch / compress
interleave
mask / subtract / overlay
thin
accent
quantize
fractalize

Every operator must be pure or explicitly seeded, typed, bounded and independently testable.

L0 — exact escape hatch

exact guitar_b bar 6 voice 0 {
    replace beat 3..4 with {
        at 3.0 note string 6 fret 7 length 1/16 marks [palm_mute]
        at 3.25 note string 5 fret 9 length 1/16 marks [slide]
        at 3.50 rest length 1/8
    }
}

L0 lowers directly into canonical EventGroup / AtomEvent structures. Raw MIDI bytes are not an escape hatch; MIDI remains a boundary adapter.

Fractal pattern algebra

The first distinctive Swang operator should be fractalize.

Given a base occupancy kernel:

X . X
X X .
. X X

expansion semantics are:

active parent -> transformed/scaled copy of the base kernel
empty parent  -> an equally-sized empty subtree/block

X is an active structural position, not a note. Separate stages decide:

structure
  -> traversal / linearization
  -> time mapping
  -> tonal mapping
  -> velocity and articulation mapping
  -> fretboard realization

This separation is mandatory. A fractal operator choosing MIDI pitches, strings and articulations by itself would do more jobs than a single parent on three shifts.

Required fractal controls

depth
expansion transform
stable density decay / pruning
cell/event budget
anchors
traversal
mode = rhythm | pitch | both (rhythm first)

Deterministic density decay

density_decay = 0.8 must not invoke ambient randomness. Valid strategies include:

  • stable path hash under an explicit seed;
  • stable rank-based pruning;
  • explicit rule-based pruning.

Identical input, semantic version and seed must produce identical output.

Hard budgets

Fractal growth is exponential and must be bounded before realization:

max_depth
max_cells
max_events
min_duration
max_polyphony

The compiler must either reject the expansion with a source-located diagnostic or apply an explicitly selected deterministic budget policy such as prune_deepest or preserve_anchors.

No silent truncation.

ASCII semantics

A two-dimensional pattern has no implicit musical meaning. The script must declare or derive its interpretation:

semantic = substitution_kernel
traversal = row_major | snake | depth_first | morton

The recommended default design is:

2-D kernel -> expansion tree -> explicit linearizer -> musical mapping

Do not silently assume that rows are voices or columns are time.

Text as a structural seed

Swang should support deterministic text-to-structure without primitive letter-to-note mapping:

pattern glyph = text("glass hands")
    |> encode(graphemes, seed = 17)
    |> fold(width = 5)
    |> mask(threshold = 0.52)
    |> fractalize(depth = 2)

Text may control:

  • occupancy and silence;
  • branching and cycle length;
  • accents and boundaries;
  • traversal choices;
  • hierarchical repetition.

Pitch is assigned later by a tonal mapping. One structural seed may therefore produce related clean, heavy and lead realizations.

All encoders must pin their semantics/version. Unicode normalization, grapheme segmentation or phonetic dictionaries changing underneath an old script must not rewrite its music by surprise.

Generator as a Swang program writer

A generator should eventually be able to emit a program rather than only a final Score:

part riff = motif "seed_17"
    |> fractalize(depth = 2, density_decay = 0.84)
    |> map_rhythm(unit = 1/16)
    |> map_pitch(material = E_minor, contour = rise_then_fall)
    |> articulate(short = palm_mute, downbeat = accent)

The normal Swang compiler then:

  1. parses and type-checks the program;
  2. lowers it into a deterministic execution plan;
  3. invokes Griff generators/transforms;
  4. validates musical and playability constraints;
  5. scores/reranks candidates;
  6. produces canonical Score plus provenance.

Benefits:

  • generation decisions are inspectable;
  • users edit a few structural parameters instead of hundreds of events;
  • evolutionary search mutates meaningful AST nodes;
  • crossover can combine rhythm, pitch and articulation pipelines separately;
  • S9 feedback can learn preferences over declared decisions, not only opaque final notes.

No LLM is required for the first implementation. Rule-based and evolutionary script synthesis must establish the contract first.

Compiler architecture

Swang source
  -> surface AST
  -> name/type/unit resolution
  -> bounded execution plan
  -> Griff generators and transforms
  -> canonical Score
  -> validation / scoring / export

Proposed crate direction:

griff-core <- griff-swang <- griff-cli / UI frontends

griff-core must remain independent of Swang syntax.

The execution plan is ephemeral orchestration, not a second canonical musical model.

Proposed roadmap slices

Slice 0 — design contract and ADR

  • define Swang's role versus canonical Score;
  • reserve .swg only after naming review;
  • define determinism/versioning/error rules;
  • define allowed units (bar, beat, tick, st, string, fret);
  • define limits and non-goals;
  • decide whether this becomes formal S16.

No parser and no production behavior change in this slice.

Slice 1 — pure Pattern Core

Add domain-neutral structural primitives:

Pattern / Cell
PatternTree / NodePath
FractalSpec
Traversal
ActivitySequence

Required operations:

fractalize
linearize
stable prune/budget

No pitch, no TonalContext, no fretboard and no generator integration yet.

Slice 2 — Pattern to RhythmTemplate

ActivitySequence
  -> typed grid/time mapping
  -> placed (offset, duration) RhythmTemplate

Integrate only through the existing S6 source_rhythms seam. Existing generation strategies, reranking and canonical output remain unchanged.

This is the first musically useful vertical slice.

Slice 3 — minimal Swang parser and canonical formatter

Support only:

pattern
ascii
fractalize
linearize
map_rhythm
generate
export

Suggested CLI:

griff swang check riff.swg
griff swang fmt riff.swg
griff swang expand riff.swg
griff swang build riff.swg --output riff.mid
griff swang explain riff.swg

expand must emit an inspectable normalized form or execution plan.

Slice 4 — exact GriffScore text and patches

  • canonical textual projection of Score;
  • semantic round-trip tests;
  • exact, replace, overlay, delete;
  • source-located validation diagnostics;
  • Guitar Pro/MIDI losses remain explicit through LossReport.

Desired laws:

parse(format(score)) ~= score
format(parse(text)) == canonical_text

The first equality is semantic canonical-model equivalence, not byte equality with the source container.

Slice 5 — recipe layer

Add bounded L2 constructs:

source
generate
complement
named patterns
named policies
section/bar scopes
seed

Compile into existing S6/S13 requests. No general-purpose loops, recursion or arbitrary host-language execution.

Slice 6 — tonal, gesture and fretboard mappings

Only after their individual contracts are accepted:

map_pitch
map_dynamics
map_articulation
solve_fretboard

Tonal inference remains diagnostic until S15 explicitly accepts scope/confidence/fallback semantics for generation.

Slice 7 — script synthesis and human-in-the-loop

  • deterministic program mutation;
  • AST-aware crossover;
  • candidate script provenance;
  • pairwise comparisons where declared axes differ;
  • user edits preserved as explicit patches/constraints.

LLM script writing is an optional later client, not part of the core contract.

Slice 8 — S7 graph/DP recipes

After S7 exists, permit explicit route objectives and versioned weight vectors:

route phrase_graph {
    length 16 bars
    optimize {
        harmonic_fit 1.0
        rhythm_complement 0.8
        playability 1.2
        repetition_penalty 1.0
        fret_jump_penalty 0.9
        mud_penalty 1.3
    }
    tie_break lowest_candidate_index
}

Swang exposes data already consumed by DP; it must not implement a second traversal engine.

First killer demo

A deliberately narrow proof:

word or short phrase
  -> versioned grapheme mask
  -> fractalize depth 2
  -> snake traversal
  -> 1/16 RhythmTemplate
  -> existing S6 pitch strategy in an explicit key/material
  -> existing/future fretboard realization
  -> MIDI
  -> normalized Swang expansion and provenance

Suggested example:

swang 0.1

pattern p = text("glass hands")
    |> encode(graphemes, seed = 17)
    |> fold(width = 5)
    |> mask(threshold = 0.52)
    |> fractalize(depth = 2, density_decay = 0.8, budget = 512)
    |> linearize(snake)
    |> map_rhythm(unit = 1/16, bars = 4)

generate {
    rhythm p
    source "seed.gp5"
    bars 4
    seed 42
}

export "out.mid"

The demo is successful only if a user can change depth, traversal or density_decay, rebuild, inspect the exact structural delta and reproduce it later.

Required controls

  1. Identical source, semantic version and seed produce byte-stable normalized expansion and semantically identical Score.
  2. Empty parents produce entirely empty descendants.
  3. Expansion never exceeds declared budgets.
  4. Budget/pruning policy is deterministic and reported.
  5. Invalid depth, dimensions, durations or units fail with source spans and actionable hints.
  6. Two-dimensional ASCII patterns have explicit traversal/semantics.
  7. Pattern Core contains no MIDI, tonal, fretboard or UI dependencies.
  8. Pattern-to-rhythm integration enters S6 only through RhythmTemplate/approved generation inputs.
  9. griff-core does not depend on the parser crate.
  10. expand exposes every high-level lowering step needed to explain the result.
  11. Exact patches cannot silently create out-of-range pitches, invalid positions, overlaps or zero durations.
  12. Text encoders pin normalization/segmentation/algorithm versions.
  13. Fuzzing covers parser inputs, expansion limits and exact patch boundaries.
  14. Existing MIDI/GP import/export and generation behavior remain unchanged unless a slice explicitly changes and validates them.
  15. TonalContext Phase 1 remains frozen until a separate accepted scope reopens it.

Acceptance for the first implementation milestone

  • ADR/design contract establishes Swang as an authoring frontend over canonical Score, not a replacement model.
  • Pure deterministic Pattern/PatternTree core exists with fractalize, traversal and bounded pruning.
  • Pattern output maps into placed RhythmTemplate values.
  • A minimal CLI can parse/check/format/build the restricted first grammar.
  • One checked-in .swg fixture produces a stable four-bar MIDI result and normalized expansion artifact.
  • Changing one declared parameter produces an inspectable deterministic delta.
  • Property tests cover fractal invariants and budget guarantees.
  • Parser/expander fuzz targets exist.
  • No competing score/event model is introduced.
  • No automatic TonalContext generation integration is introduced.

Non-goals

  • No general-purpose programming language.
  • No arbitrary while, recursion, filesystem access or host-code execution.
  • No raw MIDI-byte blocks.
  • No hidden ambient randomness.
  • No claim that fractal structure is automatically musical.
  • No direct string/fret choice inside the fractal operator.
  • No immediate replacement of cockpit controls; UI may later edit and serialize the same AST.
  • No neural generation prerequisite.
  • No full Guitar Pro textual round-trip requirement in the first slices.
  • No S7 DP implementation inside Swang.
  • No automatic key inference consumption while S15 semantics are frozen.

Architectural red lines

Reject the design if it does any of the following:

  • adds a permanent second musical model parallel to Score;
  • lets operators silently exceed resource/event budgets;
  • gives ASCII dimensions implicit undocumented musical semantics;
  • turns fractalize into a rhythm, pitch, articulation and fingering god-object;
  • stores UI state separately from the script with no canonical serialization;
  • allows generator clients to emit unversioned scripts whose meaning can drift;
  • treats an inferred tonal winner as fact without an accepted confidence/scope contract.

Expected long-term result

Swang says what to build and how to transform it.
Griff executes, analyzes, validates, ranks and physically realizes it.

This makes Swang simultaneously:

  • a faster test surface than thousands of knobs;
  • a deterministic composition playground for mathcore/swancore structures;
  • a reproducible experiment format;
  • an editable target for rule-based, evolutionary and later neural/LLM generators;
  • a human-readable bridge between high-level intent and exact canonical guitar events.

Mathcore, but with provenance, budgets and error handling. Civilization advances in strange directions.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions