Vibrai v1.6.2
Vibrai could already set a level, a pan and a send. This release is about telling you what to set them to — a starting mix per part, the reasoning attached, and a reference you can ask when a mix is muddy and you don't know whether that wants EQ, compression or automation. Alongside it: generate stops silently doubling your tracks, and bar.beat positions finally land on your bar lines.
A starting mix, with the reasoning attached
A mix profile answers, per part type, two questions: where does this sit and what belongs on its chain.
vibrai mix profiles # what's available
vibrai mix suggest --chains # placement + chain advice for the open set
vibrai mix apply-profile --dry-run # what would be written, and why
vibrai mix apply-profile --reverb-return A-ReverbOn MCP those are list_mix_profiles, suggest_mix and apply_mix_profile.
Placement is a starting level, a pan position, and a depth tier on the front↔back axis, expressed as a reverb send. Chain advice is the corrective EQ moves and compressor settings that belong on that part — each with its reason, so you can disagree with it. Profile-wide rules cover headroom, the 2–5 kHz harsh band and return tracks, next to technique notes on serial vs parallel compression, compressor setup, harshness checking and drum impact.
apply-profile writes the placement half only. The EQ and compressor numbers stay advice on purpose: a Live parameter's real range is only knowable from an open set, so a profile cannot honestly pre-compute what to send. mix suggest --chains prints them, and vibrai device set-param (MCP set_device_param) applies them, reporting back the display_value that actually landed.
A part whose depth calls for a send, on a set where you named no --reverb-return (reverb_return), still gets its level and pan — and then warns. Vibrai will not invent a return track for you.
Drop a file at ~/.vibrai/mix-profiles/<name>.yaml to add a profile or shadow a built-in one.
What to reach for, and a compressor set up for you
Hearing that a mix is muddy is easy. Knowing whether that wants EQ, compression, a dynamic EQ or automation is the hard part.
vibrai mix advice # the index
vibrai mix advice compression --for kick # a source
vibrai mix advice compression --for bd # a part type that maps to one
vibrai mix advice reverb --for pre_delay # an entry idmix advice (MCP get_mix_advice) answers from four topics — compression (starting points per source, and the fast/slow attack continuum), reverb (what each parameter does to the tail), low_end (the five ways kick and bass fight, and the fix for each) and tool_choice.
vibrai mix compress 3 Compressor --for bass --dry-run # track 3, the device named Compressormix compress (MCP apply_compression_preset) writes a source's Attack, Release and Ratio onto a compressor already on the track. Threshold is never written — it depends on the incoming level, which no table can know. Any parameter whose units don't match the table, or that the device doesn't expose, is skipped with a warning rather than clamped; the call fails only if nothing is writable.
One honest limit, and it matters most here: mix compress does not yet reach Live's own Compressor or Glue Compressor. The starting points are in milliseconds and plain ratios; measured against Live 12.4.3, both devices report those parameters as normalized 0–1 instead, and Vibrai refuses a value it cannot send honestly rather than guessing. So on the two most obvious targets the command currently writes nothing and tells you why. It works on a compressor that reports real units, and closing the gap needs a value↔display mapping per device — tracked as #777. That refusal is the feature working, not failing: parked at a Release of 1.0 and asked for the bass preset, a Glue Compressor still reads 1.0 afterwards. Nothing pinned, nothing clamped.
~/.vibrai/mix-advice/<topic>.yaml shadows a topic.
generate asks before doubling your tracks
This one changes what an existing command does. On a set that already has MIDI tracks, vibrai generate used to silently append a second set alongside them. It now stops and asks:
vibrai generate --on-existing-tracks replace # delete them and render fresh
vibrai generate --on-existing-tracks append # add alongsideThe MCP generate tool has always refused this way, and both wizards already did on both surfaces — the CLI was the one place a duplicate track set could appear without you asking for it. A script that relied on the old silent append needs the flag added.
bar.beat lands on your bar lines
automation write, get and clear, arrangement place and delete, and seek — on both surfaces — took a bar to be 4 beats regardless of the meter. On a 7/8 project, bar 2 started at beat 4.0 while generation, arrangement and rendering all put it at 3.5. All six now resolve the meter the same way generation does: your project's declared time signature first, then Live's transport, then 4/4. They also take an optional --project / project_path so the declared meter can win, matching every other project-aware command.
The song wizards had the same disagreement with themselves. start_genre_song, start_first_song and vibrai start … resolved the meter after laying out the composition, so on a non-4/4 set the plan and the render disagreed about where bars fell. They plan at your meter now.
device_id says what it takes
Seven MCP tools described the argument as "Device ID or 1-based position number", but any number is read as a 1-based position — so the device_id that list_devices reports (which is 0-based) addressed the device before the one you meant, silently. The descriptions now say 1-based position and warn about that field explicitly, and passing 0 gets an error naming the trap. Behaviour is unchanged, deliberately: every command, every doc example and the whole CLI are 1-based.
Also fixed
- An unseeded
Wandercurve sounds the same on every run. It fell back to a fresh random seed each call, so identical inputs produced a different envelope every time — and forapply_automation_templatethe empty seed persisted into the.vibrai, leaving a file that looked identical while the output moved. "Auto if omitted" now means "auto but stable": varying per target, repeating for the same one. - Reading notes back from an arrangement clip retries like its session-view twin. A single transient bridge failure could report a clip as empty.
brew install vibraiwarns when an older standalone install shadows it onPATH. The install would appear to succeed whilevibraikept resolving to the previous binary.
Under the hood
The bulk of this release is making the test suite mean what it says: nine fail-open and vacuous-pass sites closed, each one a place a green run had been proving nothing. A bare test run can no longer reach the 44 live classes that mutate an open set; genre extraction has a live witness for the first time; and the release gate now blocks on a red m4l or python suite, not just .NET.
All merged pull requests
What's Changed
- docs(launch): T-2 status refresh — v1.6.1 shipped, tool count 115, board drift corrected by @gitizenme in cssllcio/Vibrai#720
- docs(g1): rewrite the shot list against a real v1.6.1 session, typed by typeclip by @gitizenme in cssllcio/Vibrai#721
- docs(plan): v1.6.2 release spec + implementation plan by @gitizenme in cssllcio/Vibrai#722
- docs(g1): shoot driver, playback from section 3, full-film table, and the narration split by @gitizenme in cssllcio/Vibrai#723
- docs(g1): note edits must be re-placed in the arrangement by @gitizenme in cssllcio/Vibrai#724
- docs(g1): shot 10 asked for an outcome, so Claude chose automation by @gitizenme in cssllcio/Vibrai#725
- docs(g1): harden shot 9a, and the ScreenFlow production workflow by @gitizenme in cssllcio/Vibrai#726
- docs(g1): shot lengths in the Window column, and the total they actually sum to by @gitizenme in cssllcio/Vibrai#727
- docs(g1): sync the shoot-day prompt changes across all three surfaces by @gitizenme in cssllcio/Vibrai#728
- docs(launch): T-0 → Tue 2026-08-25, and what the shoot taught about non-determinism by @gitizenme in cssllcio/Vibrai#729
- Mix profiles: placement + corrective-chain advice on both surfaces by @gitizenme in cssllcio/Vibrai#736
- docs(plan): v1.6.2 re-scope — the staleness signal was lying, so it becomes Task 18 (#744) by @gitizenme in cssllcio/Vibrai#745
- feat(mix): encode mixing knowledge as an engine library with both surfaces by @gitizenme in cssllcio/Vibrai#746
- docs(changelog): record the mix-advice feature in [Unreleased] by @gitizenme in cssllcio/Vibrai#754
- fix(harness): close four fail-open paths in the test runners (#687) by @gitizenme in cssllcio/Vibrai#753
- docs(triage): milestone plan for the 15 unmilestoned issues, plus the v1.6.2 version waiver by @gitizenme in cssllcio/Vibrai#757
- docs(plan): v1.6.2 — Tasks 19 and 20, and the patch ruling is falsified (#747, #756) by @gitizenme in cssllcio/Vibrai#758
- fix(tests): gate the integration suite on a live bridge; fail restarts hard (#681, #686, #684) by @gitizenme in cssllcio/Vibrai#759
- fix(tests): replace vacuous passes with established preconditions (#682, #718, #760) by @gitizenme in cssllcio/Vibrai#761
- fix(tests): express automation values as fractions of each param's range (#717) by @gitizenme in cssllcio/Vibrai#762
- fix(tests): deterministic RepoRoot, and gate the LiveBridge collection (#683, #693) by @gitizenme in cssllcio/Vibrai#763
- fix: arp test asserts its own name; jest coverage tax; release gate polls both (#386, #691, #688) by @gitizenme in cssllcio/Vibrai#764
- fix(automation): resolve the project meter on write/get/clear, both surfaces (#552) by @gitizenme in cssllcio/Vibrai#766
- fix(wizard): resolve the meter before planning, not after (#648) by @gitizenme in cssllcio/Vibrai#767
- fix(timing): position bar.beat on the resolved meter everywhere (#765) by @gitizenme in cssllcio/Vibrai#768
- fix: seed wander deterministically, gate CLI generate, correct device_id wording (#653, #658, #492) by @gitizenme in cssllcio/Vibrai#771
- fix: retry arrangement note reads; warn when a second vibrai shadows PATH (#599, #519) by @gitizenme in cssllcio/Vibrai#772
- docs: re-validate cssllcio org-migration plan against current repo state by @gitizenme in cssllcio/Vibrai#770
- docs(review): #494 idle-server investigation — a negative, and an instrument (Task 17) by @gitizenme in cssllcio/Vibrai#773
- fix(release): NOT_PLANNED closures are not orphan release content (#756) by @gitizenme in cssllcio/Vibrai#775
- docs(plan): v1.6.2 ships under an explicit version waiver (maintainer ruling) by @gitizenme in cssllcio/Vibrai#776
- test(mix): witness apply_compression_preset against real Live compressors (#747) by @gitizenme in cssllcio/Vibrai#778
- docs(changelog): redraft the mix-advice entries in house style by @gitizenme in cssllcio/Vibrai#779
- docs(changelog): mix compress does not reach Live's stock compressors (#747, #777) by @gitizenme in cssllcio/Vibrai#780
- fix(tests): integration CLI generate calls need the explicit --on-existing-tracks (#781) by @gitizenme in cssllcio/Vibrai#782
- ci: run the non-integration suite once, in coverage.yml only by @gitizenme in cssllcio/Vibrai#784
- fix(tests): curve inputs are normalized [0,1]; only read-backs are native (#717) by @gitizenme in cssllcio/Vibrai#787
- test(automation): the gap-fill diagnostic printed native, compared fraction (#717) by @gitizenme in cssllcio/Vibrai#788
- chore(release): v1.6.2 by @gitizenme in cssllcio/Vibrai#789
Full Changelog: cssllcio/Vibrai@v1.6.1...v1.6.2