1@README.md 2 3## Notes for agents 4 5**Spec first.** Update `SPEC.md` — its body, and a new `revisions` entry — before changing `song.js`, in the same commit. The spec is the source; the song is its output. 6 7**Score each new revision with Jev.** `op-env-run -- node tools/critic/critic.mjs --write --song <theme>/<song>` writes the revision's `art:` (the mean of three runs, with each run in `artRuns:`) and the song's `critic:` into the frontmatter; commit them with the revision. See `tools/critic/`. 8 9**Records, not summaries.** `model` is the exact model ID that did the work (e.g. `claude-opus-5-5`); `prompt` is the instruction that revision carried out, written as a clean, standalone brief of what the user asked for about the music: for a song built from a pitch, rev 1's prompt is its `brief`; never paste the chat message (no session ids, asides, typos or talk about the session); `brief` is the pitch in the user's own words, with typos, casing and punctuation fixed and nothing added or reinterpreted (it shows on the song's page, so a raw chat line with typos does not belong there); `output` names the file a revision wrote, or `null` if a later revision overwrote it. 10 11**A spec may correct its own brief, and must say so.** When a pitch asserted something unverified or collided with another song, the spec's body says what changed and why (see `jev/hey-listen` and `jev/borrow-checker-blues`). Never rewrite the recorded `brief` to say something else; fixing its typos is not a rewrite. 12 13**A revision is a prompt about this song's music.** Session plumbing is not one: "make the X song" or "fork an agent per song" (the pitch is the prompt), and edits across every song such as a sample-path change (git records those). A revisions list shows on the song's page, so noise there is visible. 14 15**Frontmatter must parse as YAML.** Check with PyYAML after editing; `prompt` and `brief` are double-quoted JSON-style strings, so escape inner quotes. 16 17**Every song folder gets a README and a CLAUDE.md,** like every other directory: README says what the song is and maps its files; CLAUDE.md imports it. 18 19**Add to a note pattern with `note()`.** `note(x).add(12)`, `.add(roots)` and `.add(sine…)` silently do nothing: Strudel cannot do arithmetic between a control pattern and bare numbers, and says only "[warn]: Can't do arithmetic on control pattern." Write `.add(note(12))`. Four songs shipped with this bug (2026-09-24); check a new song with `get_logs` for that warning before calling it done. 20 21**Dirt-Samples names lie.** `cr` is six ride cymbals (`RIDED*.wav`), not a crash; `hh27` holds a closed hat (`:0`), a crash (`:1`, `001_hh27crash.wav`) and a hit. The crash measures −29.5 LUFS against the ride's −14.7, so swapping one for the other needs its gain matched by ear. List a folder before trusting its name: `gh api repos/tidalcycles/Dirt-Samples/contents/<name>` (2026-09-25). 22 23**A sung name must be read back by two whisper models.** `nix run .#transcribe -- FILE...` prints each file as `small.en` and `medium.en` hear it (whisper.cpp, one transcription at a time on the machine, so parallel agents cannot exhaust memory); use it rather than loading Whisper yourself. Synthesised "Jev" is the hard case: SAPI's plain "Jev" comes back as Jeff, a vocoded "Jehv" as Jeb, and `base.en` hears Jeff even in the raw speech before vocoding, so check with `small.en` and `medium.en`. What passed (hey-listen, 2026-09-25): speech rate −4, a comma after the name, `vocode --dry 1.5`; spelling it out ("Jev. J, E, V.") reads every time. 24 25**A loop within one kind of section gets a `times`.** A way back inside a groove or a drop (drop2c → drop2b, or a section followed by itself) lets Jev repeat the same material until the form's `max`: borrow-checker-blues could play 56 bars of groove, select-star 80 bars of `keyUp` (2026-09-26). `times: n` on a section is the most it plays in one performance, counted in total, since a loop is a cycle of different sections where none repeats back to back. Put `times: 2` on the section each such loop returns to (once more round at most), then check the longest run of one kind of section a path can still take: where loops chain (a detour out of one loop into another), also cap the loop's last section (`times: 1`, so the repeat is cut short). A way back across kinds (a verse again after drop 2) is the song's form, which `max` bounds. A section that has played its `times`, or whose only ways to an ending run through one that has, is not offered; the written order is never capped. The spec's form table says each `times`. 26 27**A part's level is a whole step.** `dj[name].score.round()`: out (0) is silent, back (1) plays at half velocity, full (2) as written. Masking at `score.gt(.5)` silenced a score of exactly .5, which Jev's own label calls "back" (2026-09-25). A level question named for the part's orbit is asked only about sections where that part plays as written (jevCore `setWrittenParts`), so no song lists that by hand; and every djJev has `forget: ['into']`, because Jev copied its own past "cut" into nearly every section.