For agents, on top of README.md, which they read first.

Notes for agents

Stop playback before playing song.js. Its section masks count from cycle 0.

The words are oASTEROIDo's: change none. The lyrics are his, verbatim, and the brief is his. A sung line joins two or three of his lines or is one of them; never reword, reorder, add or repeat one. The only thing in the song that is not his is the dog's "This is fine". What is typed to the speech voice may differ (a comma, "knott") only to be heard right; samples/README.md records each.

Nothing heavy before the snap, and no drum. The brief says "no gradual heaviness": no distortion, bass, kick or hat plays in bars 1–48 or in the hold (soft hats from the pre-build were removed, 2026-10-04: his heading calls the edge "the float at its stillest"). Do not add a riser, a fill or an energy question to "improve" the approach to the snap: the two bars of near silence are the approach.

No way back after the snap. The form's only choice is the fuse, after the bridge (the edge, or the hold and then the edge). A way from any later section to an earlier one breaks "[S↑ irreversible]".

The edge is sung once, and the snap follows it. Do not give the edge a way back to itself: it replayed three of his lines, "Then." and the dog (rev 1). The wait is the hold, before the edge, without words.

The hold sits past a gap, at bars 105–112, outside once. walk reads what follows a section as written from where it sits (at + 8): at bar 97 the outro would be "followed by the hold as written" and walk refuses the form. So the hold's parts (holdWash, holdStrain) carry their own mask and stack beside once(…), not inside it, and the play-once mask stays the song's written length, 96.

Jev has the fuse and the strain, nothing else. Part levels were removed (rev 2): asked, Jev could empty the snap, halve the sub and silence the float, and it put the sung lines at "back" in every section (2026-10-03). Parts go on their named orbits directly.

The strain is written flat; Jev's level is all of its growth. Rev 1 wrote a ramp and Jev read the ramp back. dj.strain.score.round() picks the gain (×¼, ×½, ×1, ×2) and the filter. Two things keep that working, both in song.js: atOnset reads the level where the eight-bar note begins (read over the whole note, the next section's question goes out as this one starts), and strainLevel.mask("0") in the stack reads it every bar, intro included (unread during the intro, verse 1's question was asked as verse 1 began and its drone played the fallback for all eight bars).

A patterned .late() goes after the mask, on a grid that matches the notes. .late(rand.range(0, .01).segment(8)) on eighths, .segment(16) on sixteenths: each note keeps its onset inside its own step. A smooth signal (perlin) moved the wash as a block and could drop a note. The probe: every bar of the wash has 8 onsets and each tapped line 16.

rand is the same for the same time. Two parts given rand drift together; each gets its own .seed(n).

The harmony moves every two bars on purpose. Each sung line's melody is on one chord (score.abc; ck<section><a-d> are E, C#m, A, B in that order).

score.abc follows song.js. The same chords, the same bars, the same lines, the same tapped figures; change one and change the other. The sung lines are rendered from it (vocode --melody), so a changed melody means re-rendered samples.

Re-measure after any level change, twice. measured: holds only for the song.js whose hash it records, and two runs differ by about a dB a part. The spec's Mix rules (the snap at least 9 dB over the edge and within 1 dB of the impact, words within 2 dB of the guitars) are checked against it.

Re-time a line's lyrics when its clip changes. Each samples/ck*/ck*.lyrics.json holds the line's syllables and where each starts in that file; a re-rendered or re-trimmed clip needs vocode --syllables run again (tools/vocals/).