# Evolving loops

An evolving recipe turns a loop into a repeatable musical process. Start with
music that already works, protect its important notes, then audition changes at
different rates. A seed and logical cycle reproduce the same phrase. Saving the
recipe keeps that behavior; capturing a passage keeps ordinary editable notes.

Use the checked `soundfish evolve` commands. A recipe uses a separate `#e1`
address and `soundfish.evolution/v1` JSON. Ordinary loops remain `#s1`, and
captured songs remain `#a1`. Never put rules into a loop's descriptive metadata,
rewrite a fragment by hand, or pass an evolving recipe to ordinary loop-edit
operations.

## Start and shape the rules

```sh
soundfish evolve create '<loop-url>' --seed 42 > recipe.url
soundfish evolve inspect recipe.url > recipe.json
```

The JSON contains the complete original loop in `base`, a seed, and one rule per
selected track in `rules`. Keep `schema`, `profile`, and `evaluatorSha256`
unchanged: they identify the supported behavior and the checked ALGAL runtime.
The evaluator runs locally and has no network or clock input.

Edit the returned JSON, preserving unrelated rules and source events, then use:

```sh
soundfish evolve import-json recipe.json > final.url
soundfish evolve inspect final.url > checked-recipe.json
```

For drums, choose `rotate` or `cellular`. Rotation shifts hits around available
positions; cellular makes bounded relocations influenced by neighboring hits.
For pitched tracks, `motif` changes a bounded selection of notes in a register
and scale. These algorithms derive each phrase from the source loop; the cellular
preset does not evolve an accumulated automaton state.

| Field | Meaning |
| --- | --- |
| `seed` | Whole-recipe unsigned integer, 0–4,294,967,295. |
| `trackId` | Existing stable source track ID. One rule per track. |
| `every` | Change interval, 1–64 complete loop cycles. |
| `amount` | 1–8: rotation displacement, cellular relocation-attempt cap, or motif pitch-change cap. |
| `returnEvery` | Return to the source every 1–256 generations; 0 disables this explicit return. One generation lasts `every` cycles. |
| `pinnedEventIds` | Source event IDs to preserve exactly. |
| `pitchClasses` | Unique pitch classes 0–11 for motif movement; C is 0. |
| `minPitch`, `maxPitch` | Inclusive MIDI register, 0–127, with at least one allowed scale pitch. |
| `respondTo` | Optional different track ID whose generated rhythm accents aligned unpinned notes, separately from the amount limit. |

Amount bounds compare each phrase with the original source, not the preceding
generated phrase. Unruled tracks remain fixed. Existing pins and unchanged-note fallback can
retain source pitches outside a requested move range. Evolution preserves
instruments, event identities and counts, source production, and automation.
Use pins to keep the kick, backbeat, motif opening, or cadence recognizable.
Cycle zero is the original loop. Returns are periodic; endless novelty is not
promised.

## Compare, capture, and listen

```sh
soundfish evolve compare recipe.json --count 8 --probe-cycles 0,3,5,8,13,21
soundfish evolve render recipe.json --start-cycle 3 --cycles 8 --midi --out take.mid
soundfish evolve render recipe.json --start-cycle 3 --cycles 8 --json --out take.json
```

Compare samples at most 32 variations at 16 explicit cycles each. It reports
unique sampled phrases, unchanged phrases, event change and count, and fuel.
Results include each variant's seed, rate, and amount. Ranking favors sampled
variety, then moderate change; audition before choosing. These diagnostics do
not measure musical quality.

Render requires a finite 1–128 cycles, starting at cycle 0 by default. Logical
cycles cannot exceed 1,000,000,000. Existing loop and song byte, event, automation,
and duration limits also apply; shorten the take when necessary. One cycle
produces a loop; several produce a verified song with cycle markers. MIDI carries
the realized notes, not executable rules. Multi-cycle capture assigns fresh
position-based event IDs so equivalent music can share a song section.

To keep editing a finite capture, run `soundfish import-json take.json`, then
use the ordinary inspect, lint, song, and handoff paths. A CLI render follows the
ideal trajectory; it does not reproduce unrecorded live holds or missed deadlines.

In the browser, **Capture recent cycles** keeps whole phrases that playback has
started, including held repeats and the current phrase in full. Pausing midway
does not trim that phrase. This captures notes, not a partial audio recording;
an unplayed preview is available through **Keep this phrase** instead.

## Save and deliver

`evolve inspect` verifies a recipe link's transport digest and content identity
before printing its lossless JSON. Retain its exact `final.url` and checked JSON,
then return the complete CLI-produced link unchanged. The ordinary `handoff`
command applies to captured loops and songs; it does not accept recipe links.

Recipe files are limited to 128 KiB and links to a 64 KiB fragment. If a valid
recipe exceeds the link budget, use `evolve create '<loop-url>' --out recipe.json`
or `evolve export-json recipe.json --out saved-recipe.json`, and return the file.
Existing output files are never overwritten. Every evolve command accepts
`--format json` and `--base-url`; URL output also accepts `--fragment-only`.
All inputs accept a local file, a URL, or `-` for standard input.
