A swancore-first guitar riff engine. It analyzes, slices, generates, and regenerates guitar parts as a structured symbolic model (MIDI in → MIDI out, no audio synthesis). Long-term target: a MIDI-oriented CLAP plugin with human-in-the-loop curation.
core/— library: musical model, MIDI I/O, slicing, features, generationcli/— binarygriff(import/inspect/export/classify/curate)preview/— headless-testable ratatui preview: piano-roll view + section / structure analysisplugin/— CLAP plugin (S10+, not yet)
docs/SPEC.md— what griff is/isn't, hard rulesdocs/glossary.md— the constitution (terms)docs/preview-guide.md— using the interactive preview TUI (keys, inspector, curation, complexity)docs/stages/— canonical roadmap S0…S16docs/adr/— architecture decisionsAGENTS.md— guide for AI agents
cargo test --workspace
cargo clippy --all-targets -- -D warnings
cargo fmt --all --check
The cockpit generates from an open score alone, or — with a corpus — from curated material: rhythm templates, novelty references, and burst/rest gesture statistics, plus the corpus's tabs as the seed pick-list.
Run the native cockpit over an existing corpus:
cargo run --release -p griff-cockpit -- --corpus /path/to/corpus --out /path/to/keeps
Then: open Generate (g) → pick a seed tab → set seed / bars / candidates
/ gesture → Generate → click the ranked candidates → ▶ to hear them,
drag the tempo, loop a bar range, A/B (b) two of them → Keep
writes the MIDI and a provenance sidecar into --out.
Every candidate you audition — from Generate or from Swang (e) — is
recorded in the session history (y): a newest-first feed where you can
mark a take favorite or rejected (each clears the other), read its
typed provenance at a glance, and re-audition any earlier take (it re-enters
the same playback, so A/B and the playhead keep working). The history is
session-local and in-memory — it is not written to disk — and marking a
favorite does not (yet) steer generation; that feedback loop is S9.
Build a test corpus from a couple of tabs (the generation loader reads the
*.chunk.json records directly; manifest is a coverage check, not required
at runtime):
mkdir -p corpus
cp tabs/song1.gp5 tabs/song2.gp5 corpus/
cargo run --release -p griff-cli -- split corpus/song1.gp5 -o corpus/song1
cargo run --release -p griff-cli -- split corpus/song2.gp5 -o corpus/song2
cargo run --release -p griff-cli -- manifest corpus
cargo run --release -p griff-cockpit -- --corpus corpus --out keeps
Without --corpus, generation uses only the open score — no corpus rhythms,
references, or gesture — so it reads as an honest early rule generator handed
one file.
- Generate panel + corpus: the corpus supplies the rhythm, novelty references, and gesture.
- Swang + corpus: the current native cockpit does not resolve a
corpus for Swang. A program that declares a
corpusis therefore refused outright — the run reports the refusal and produces no candidates at all (remove thecorpusline, or build it withgriff swang build). Only a program with nocorpusline runs, on the kernel's own rhythm. By the frozen precedence **explicit pattern > corpussource first bar** (ADR-0029 §7), once corpus resolution is wired a declared corpus will contribute novelty and gesture but will never replace the kernel's rhythm; the grid always comes from the program.
So to play with a real corpus's rhythms today, use the Generate panel, not Swang. That precedence is frozen and does not change here.
Playback (native MIDI or the browser's Web Audio) is identical for a Generate
candidate and a Swang candidate — both are just a Score.