The seed is a station now, and what it leaves out keeps rolling - #47
Merged
Conversation
`tag:n[:genre][:vibe]`. Absent means rolled — an omitted genre or vibe is derived from (tag, n) and changes with every song — and present means pinned, so you can pin a vibe and let genres roll, pin a genre and let vibes roll, or pin both and move only n. The two roll from separate streams, so pinning one never moves the other. Malformed is an error with a sentence attached, never a coerced string: a seed that quietly becomes a different seed is worse than one that is refused, because the person who sent it never finds out. The significant part is the vibe. It was a per-genre grid whose first char was the genre and whose instrument rows meant different things in different genres, which made a pinned vibe nonsense the moment the genre changed under it. It is now ONE global grid — nine voices x four columns, 36 hex chars, the same width and the same meaning in every genre, whether or not that genre plays the instrument. A genre chooses which cells it shows as sliders and what to call them, and nothing else; the ranges are global too, because the per-genre floor under each drive knob already lives in Guitar.cs, Lead.cs and Keys.cs, and two places to put a genre's character is one too many. Genre swapping mid-song therefore keeps the vibe: the same 36 knobs through a different band, which is what reaching for the dropdown is asking for. The parser is SeedCodec, in the engine, and the web asks the wasm for it rather than keeping a second one — a seed is exactly the thing two people have to agree about. `shuffle` stops meaning "a different vibe every song" (a seed with nothing pinned already does that, and it needs no attribute) and starts meaning what NEXT is: the next song of this station, or a whole new station at song 0. Those stations are derived from the root rather than drawn fresh, so Prev still replays what was heard and a reload does not lose the line. UI: the genre dropdown gains Random, the knobs collapse behind a tinker button with their own way back to rolling, reroll is a fresh station rather than a fresh taste, and there are two copy buttons — this song, or this station. Old seeds break, as the plan says they may. The s&box driver compiles and drives the new format; its panel's UI follows in row 98.
Three of the four buttons over the sliders were never about the sliders: genre, reroll and shuffle change the seed, and tinker only opens the box. Sitting in the panel header they read as part of the mixer and vanished for everyone who never opened it. They move to a row of their own on the board, and the panel is now only the matrix and the two buttons that act on it. The die in there also did not do what a die on a mixer is expected to do. It was an UNPIN — hand the vibe back to the station — which moves nothing at all when nothing was pinned, so pressing it mostly looked broken. There are now two: `🎲 randomize` draws a fresh vibe and pins it, so it moves every slider every time; `↺ random each song` is the unpin, worded as what it actually changes (the songs after this one) and disabled when there is no pin to drop. `controls` had to learn that a section can be more than one node, since `vibe` is now a strip of buttons and the panel they open. Its own hidden flag and tinker's now settle in one place, because both were reaching for `hidden` on the same element.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes PLAN row 99.
The format
tag:n[:genre][:vibe]— genre and vibe optional and order-free, told apart by length (1 hex char = genre, 36 = vibe).Absent means rolled, present means pinned. An omitted part is derived deterministically from
(tag, n)and so changes with every song; a written-down one is pinned and every song plays it. Genre and vibe roll from separate PRNG streams, so pinning one never moves the other.gamah:0gamah:0:3gamah:0:8a4c…gamah:0:3:8a4c…nkeeps its job: Prev/Next aren±1, the queue walks an ordered timeline, andnis what reaches a song fifty ago that nothing remembers.Malformed is refused with a sentence and changes nothing — typed mid-session the music carries on, arriving from a link the widget stays silent. There is no "apply the part I understood".
The vibe is one global grid
This is the substantive change. The vibe was a per-genre grid whose first char was the genre and whose instrument rows meant different things per genre — a pinned vibe rolling across genres would have been nonsense.
It is now 9 voices × 4 columns = 36 hex chars, the same width and the same meaning in every genre, whether or not that genre plays the instrument. Identity is the voice, not the label: ska's
LEADis MELODY and pop'sLEADis LEAD GTR; pop'sSYNTHis rock's KEYS.Ranges are global too. The per-genre floor under each drive knob already lives in
Guitar.cs/Lead.cs/Keys.cs, and two places to hold a genre's character is one too many. The wire carries a normalised level, so the same digit is the same fraction of travel everywhere.Genre swapping mid-song keeps the vibe — the same 36 knobs through a different band, which is what reaching for the dropdown mid-song is asking for.
Parsing lives in
Engine/SeedCodec.csand the web asks the wasm for it rather than keeping a second parser.shuffleStops meaning "a different vibe every song" — a seed with nothing pinned already does that, and it needs no attribute. It now decides what next means: the next song of this station (
off, the new default) or a whole new station at song 0 (on). Those stations are derived from the root, so Prev still replays what was heard and a reload does not lose the line.UI
Genre dropdown gains Random; knobs collapse behind a tinker button and have their own "random vibe" way back out (a knob drag pins the whole grid, so there has to be one); reroll is a fresh station rather than a fresh taste; two copy buttons — this song fully resolved, or the station as it stands; refusals appear inline under the seed box.
Verified here
make test-engine556 checks, all six node suites,test/dist-single.mjs, andcheck-bundleagainst a fresh AOT re-stage (committed). Render digests re-blessed — audio changes, which the plan allows.Not verified here: anything s&box.
SkafinityPlayer.csand the Razor panel are ported by review and grep only — they compile against the new API as far as that can tell, and the panel's UI (collapsed knobs, Random genre, two copy affordances, seed-only reroll) is deliberately row 98.Also updates rows 98 and 12, which referenced 99.