Repository navigation
Controls batch 18: stored mute automation, and following sends that track it in render - #1715
Merged
Merged
Conversation
…specs Amend #1651, #1652 and #1653 with a batch 18 spec check on ad03780: anchors, batch 17 code (fader cells, the event driver, the carry, the conservative fallback flag), decision 17 rules, gates at Simd8 and Simd4, and the authorized paths. Remove the specs of #1646-#1650 and #1709, closed in batch 17. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d mute (#1652a) A route whose source strip has an automated mute lane gets its own lane type: the open transform, one flags word (route mute, follows_mute, terms L/R, automated L/R) and the ramp, in a LatestCell<7>, with a boxed render state beside LiveRoute so a six-word route keeps its bytes and bits. The record refuses unknown flag bits, a non-finite transform word and an over-long ramp. The route charge counts each kind on its own and the activity table once. graph gains a normal automation dependency (policy pin and fixture updated); route_values is public. No render behaviour yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
T1) mute_channel returns at once when the requested mute equals the channel's current mute state, so a repeated SetMute (an operation or the live set_mute) no longer restarts a fader ramp in flight or starts a mute ramp that holds the fader events. Gate a_repeated_mute_leaves_the_stage_as_it_was (Simd4, Simd8, scalar; quanta 128 and 100) is red on the old code. Four tests that ended an unmute ramp with a repeated unmute are rewritten to the new rule (the three batch 17 hold-release gates now free the lane with a live fader write). audit capi pcm_digest unchanged (bffc21e857b5e134). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(#1652b)
A following route reads its seven-word cell at block entry, then walks
its source lanes' mute cells in the tap's node time (node_span at
a(tap)), composes the gate with RouteFollowFlags::gate and
gated_route_coefficients, and retargets only when the coefficients'
bits change: a new indexed ramp from coefficients_at(position) at the
event's offset over the session mute length (exact on a seek). A route
inactive at block entry that opens inside the block mixes the rest.
Graph takes the mute length rule from host-core and never spells the
row. Six-word routes keep their code, bytes and bits. Gate 3 (split at
o in {1,63,64,127} at q=128 and in a block of 100) and five focused
tests, each red under a named mutation. Realtime policy 164 -> 165.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
controls::fader_row names the strip fader row. The readers that mean the fader (fader_automation, model_fader_offsets, mask_fader_offsets and the conservative B17-R14 fallback predicate) now test it, so the mute row that T3a renders gives no lane a hand offset, turns no fader edit into an offsets write and flags no mute-only rebuild (R18-4: a mute adoption never stretches a live move). automation_row_renders is still the fader row alone; no rendered bit moves. Gate a_mute_entry_reaches_no_fader_only_reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, graph side) A live route carries its ramp state by route ID whatever its kind in either plan (six->seven, seven->seven, seven->six). Follow cursors are not carried: the successor seeds them at its own node time, applies the join's record first, then compares its composed target with the adopted ramp's target and retargets over the mute length only when the bits differ. A seven->six successor makes the same comparison against its prepared target on its first block, so removing the curve never leaves a send muted. Six->six keeps LiveRoute::adopt and its bits. The swap-block allocation half of gate 4 stays with the host-core gate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A free live fader write discharges the owed move (self.owed = false), and no test turns red when that line is deleted. #1711 reworks the same owed and hold machinery, so it now owns proving the discharge observable and gating it, or proving it unobservable and deleting it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Row 6 renders. Mute cells go into the plan's one program after every fader cell (a fader-only session builds the same program and bits). The stage mute of an automated lane is curve || terms, terms being the effective strip mute (OQ1 = C); the drain routes the live Mute value to the lane slot's terms and composes at the block boundary. The one FaderEventDriver walks mute cursors and pushes a SetMute only when the composed mute changes, at its exact sample over the session mute length; a seek sets it exactly and a seek that leaves the mute unchanged lets the ramp finish (R18-1). The scalar oracle runs the same slot and driver. A mute entry change is a rebuild on both hosts; the superseded #1648 gate 1 mute asserts and the parity mute branch are rewritten. PreparedBuiltinsSession::strip_mute_cells exports the program and the mute cell indices for #1652. Lane slot 304 -> 392 B; realtime policy 161; pcm_digest unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…check) a_live_write_that_frees_a_held_lane_releases_its_hold had been green under its own mutation (no release) since the D1.2 removal: the drain gives the cell no hold. It now puts an offsets write under a long unmute, so the cell holds and owes a move, and frees the lane later. It is red under no-release and under release-only-when-nothing-owed. The gap of a free write that keeps the owed flag moves to #1711. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A lane with fader and mute automation renders each fader channel's block in pieces that end at the D1.6 cut at E, at the channel's next mute event, or at the block end. At a pushed SetMute the next piece takes the stage's hold: muted holds to the block end; an unmute over M sets E = o + M (a cut inside the block, due at entry at the block end, read from the stage past it). Fader events at an offset go first, under the old hold. One driver serves both bank forms, the fused fallback and the scalar oracle. Gate 2 and the in-block hold cases (E inside, at, past the block end; unmute and re-mute in one block; offsets 0 and q-1) are red under the named mutations. Fader-only bits unchanged; pcm_digest unchanged; realtime policy 161. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- MAJOR-1: a following route that opens inside a block records its activation offset; its destination reduces [0, o) without it, so no signed zero reaches the bus. - R18-5 (MAJOR-2, MINOR-1): per-column ramps. One indexed ramp per source column; only a column whose target bits change retargets, so an open column's live move keeps its length across a carry and per-lane curve steps each end with the strip's mute length. One new lane kernel entry, route_mix_column_ramps_block, with the six-word kernel's vector shape; with equal ramps it is that kernel bit for bit. - MAJOR-3: a carried first block applies the join's record with the heard curve first, then the successor's curve jumps over J; a six-word successor does the same and then reopens. - MINOR-2: adopt_predecessor finishes a pending route carry first. - MINOR-3: RouteCarryStep is back to 8 B; following-route checks live in a side table sized for those moves only. Realtime policy 166 -> 167. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every plan gives a route into a submix whose source strip has a mute entry a seven-word lane, sourced from the strip's mute cells, the tap's floored arrival and the session mute length rule, with flags seeded from the effective strip mute. The swap join writes a seven-word record through the follow producer only when a word changes (never on a change of kind alone). Until #1653 lands in this batch, a live edit of such a send rebuilds. Gates: no leak on both hosts and host-core at every width; the send gates on the strip's timeline sample with the same length; a rebuild adding or removing the entry keeps or reopens the send allocation-free; the charge covers the attach; the realtime binary. pcm_digest unchanged; realtime policy 167. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…652a) The builtins policy forbids the word builtins in graph's manifest; the #1652a comment named the strip compiler crate. Reworded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts: the follow pair's doc (the fold's text, without the dead_code expect that #1652c removed) and the #1652 decision records (both kept). The attach passes the plan's route count as activity_routes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…automated (#1651 T5, R18-2) - R18-2: the control listing marks a mute row automated on each lane a mute entry drives, on both hosts; the row's value stays the hand mute. - Gate 1: a curve mutes at its exact samples over the session mute length and is bit-identical to the static plan from the next block boundary; a seek into a muted span mutes exactly. Quanta 128, 100, 37. - Gate 3: solo, a VCA mute and a hand mute compose with the curve (curve || terms) on both hosts. - Gate 4: a mute entry change rebuilds; hand and VCA mutes give one Mute record each (the terms write); fader edits stay fader records. - Gate 5: control-plane mute_automation_realtime renders the script allocation-free through the shared commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
LaneFaderAutomation::adopt adopts the mute channels by address; bits 2 and 3 of continued_cells carry the mute lanes. A carried channel keeps its cell state and terms and repositions when its table changed, its arrival moved or a reposition is still owed; a gained channel repositions. The swap block composes curve || terms once at node time and lands a SetMute over the mute length only when it differs from the stage. A lost mute cell gets a Mute record of the lane's effective mute. R18-4 holds for the strip: a mute adoption keeps the fader move in flight for the unmute. Gate 8 (add, remove, change, each mid-play; Simd8, Simd4, scalar oracle post-ramp) and the combined send-and-strip rebuild now adopt over one length. pcm_digest unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rnel's panic path (#1652, fold 2) - MAJOR-A: a rebuild that carries a following route into a six-word route reports TransitionFallback on both hosts (the route join sets it; the shared commit reads it). Conservative: it can over-report on a rebuild that removes a strip's last mute automation while a following send exists; TBD51 (placeholder) carries the columns exactly and removes it. - MINOR-B: route_mix_column_ramps_block clamps its split, so the wasm f32x4 instantiation has no panic site; no bits move. - MINOR-C: the activation-offset gate also runs into the session output; NIT-D: a heard curve on a lane the successor no longer automates is forgotten; NIT-E: a successor of a plan that never rendered takes its pending comparison (host-core gate). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An edit that changes a following route's gate writes its seven-word cell through the live path on both hosts: a route gain, matrix or mute edit, a follows_mute toggle, and a change of the source lane's terms (hand mute, VCA mute, solo) re-send the cell, only when a word's bits change, and no folded follow record is emitted. Before the first write the commit refuses (Internal) a record with no producer of its kind or with automated bits that disagree with the plan; the strip's terms and the route's cell share the transaction's stamp. control-plane keeps the follow route producers. The #1652c rebuild stopgap is replaced; its gate is rewritten in place. In-place commit equals the full path. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The spec becomes 1713-carry-a-following-routes-column-moves-exactly- into-a-six-word-successor.md, filed by root from batch 18; the public doc text (C header, abi.rs, C ABI qualification, both .d.ts copies, still identical) and the code comments name #1713. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- MAJOR-2: a hand or VCA mute committed with a mute curve rebuild lands as committed. A cell that owes a reposition composes the record with the curve at the block's first node time and applies SetMute over the record's own ramp; the adoption landing then pushes only a change the curve itself makes, over M. R18-4 is withdrawn for the strip; the records say why the adoption now lands as committed. - MAJOR-1: an in-block curve unmute ends an older fader-cell hold (release node; shorten-only CellState::release_hold_by in automation, path approved by root), so a ride under an offsets hold no longer freezes when the mute length is 0. - MINOR-3: a mute-curve rebuild with a live fader move in flight completes Exact on both hosts. MINOR-4: a composed stored mute and a seek render the same bits on both hosts. MINOR-5: the hold-release gate frees the lane with the production trigger (an exact unmute). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # crates/control-plane/src/control.rs
- U2b MINOR-1: a muted following route stays silent from its seed. - U2b MINOR-2: a rebuild that hand-mutes the source ramps the send over the edit's own length (the join's before terms). - U2b NIT-2: the realtime binary toggles follows_mute live. - Fold-2 NIT-1: a fader ride rebuild inside J after a flagged seven->six adoption reports EXACT (the narrowed landing window). - Fold-2 NIT-2: the refused adopting render allocates nothing. - Fold-2 NIT-3 and U2b NIT-1: doc wording of the seven->six rule, and the +96 B of capi_retained (a 16 B follow-routes box in six provider epochs) recorded in #1653. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TBD52: skip the grid walk for step-only automation cells (mute cells and the following route's walk of them; weekly performance pass). #1710: the per-owner index also serves the mute row and the following-route predicate. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Documentation job: two public docs in graph linked private items and one host-core doc had a redundant link target. - The MINOR-4 cross-host gate keeps the following send (its follows_mute override, needed only before #1653, is removed) and its test-value sentence names the adapter as the unique catch. - The M > 0 release arm of rehold is marked defensive; the #1651 record notes the resolved solo refusal and the P3 landing rule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Controls batch 18: stored mute automation and the sends that follow it (the R2 must-land group). A session's mute automation now renders on both hosts: a strip lane mutes and unmutes at the exact samples the session names, over the session mute length, and composes with solo, VCA mutes and a hand mute (OQ1 = C: the stage mute is
curve || terms). Every send into a submix that follows an automated mute follows the curve at its tap's arrival, so it mutes exactly the audio the strip mutes, latency included. Live edits of such a send write its route cell from the shared commit.Closes #1651
Closes #1652
Closes #1653
What changed
SetMutethat repeats the lane's mute state leaves the fader stage as it was (the batch 13b rule): it no longer restarts a fader ramp in flight or holds fader events.controls::fader_rowsplits the fader row from the rendered rows, so a mute entry gives no lane a hand offset, turns no fader edit into an offsets write and flags no mute-only rebuild.SetMuteonly whencurve || termschanges, at the exact sample over the session mute length. A seek sets it exactly; a seek that leaves the mute unchanged lets the ramp finish (R18-1). The bank forms, the fused fallback and the scalar oracle share the driver.CellState::release_hold_by, shorten-only, incrates/automation; path approved by root).Muterecord the shared commit already sends is the terms write; no new record type.Muterecord of the effective mute.automated, on both hosts.timeline(r + ΣP - a(tap))and retargets only when the coefficients' bits change, over the session mute length (exact on a seek).route_mix_column_ramps_block, has the six-word kernel's vector shape (simd128, NEON, AVX2, outlined scalar tail; 0 panic sites in the wasm instantiation); with equal ramps it is that kernel bit for bit.[0, o)without it (no signed zero reaches the bus or the session output).crates/automation(R18-3; a leaf crate). The graph policy pin and its fixture gainautomationin the same commit.CandidateOutcome::TransitionFallback, so the watermark reportsOUTCOME_TRANSITION_FALLBACK, neverEXACT, for it. It is conservative: it is set whether or not a column moves at the swap. The doc text (abi.rs, the C header comment,docs/C_ABI_V1_QUALIFICATION.md, both d.ts) says so. Carry a following route's column moves exactly into a six-word successor #1713 carries the columns exactly and deletes the flag.follows_mutetoggle, and a change of the source's terms (hand mute, VCA mute, solo) write the seven-word cell through the live path on both hosts, only when a word's bits change; no folded follow record. The strip's terms and the route's cell share one stamp.Internal) a record with no producer of its kind or withautomatedbits that disagree with the plan (never an ack before a drop). The in-place commit equals the full path (R17-1).Evidence
audit capipcm_digestbffc21e857b5e134, unchanged across the batch (the audit session has no stored automation). 0 violations, 0 allocations.ColumnRamps, the mute-drainapply_mute_value,follow_mute_jump, cursors). No file undercrates/engine/src/realtime/was edited.automationadded to graph's dependency pin and fixture (R18-3). The builtins policy scan stays clean.check-capi-abi.shpasses.LIVE_FOLLOW_ROUTE_OWNER_BYTES352 B (a following route only);LIVE_ROUTE_OWNER_BYTES72 B unchanged;RouteCarryStep8 B unchanged (following-route checks live in a side table);RouteActivity64 -> 80 B once per plan with live or gated routes (the activation offsets box, charged bysize_of; root accepted). The charge test covers the attach (the_following_route_charge_covers_its_attach_and_bind).batch-gates.shall green on codex/controls-batch-18r at e7938ee except the Documentation job (two private intra-doc links in graph, one redundant link in host-core), fixed in a6574be. That commit and the Skip the grid walk for step-only automation cells #1714/Index the automation entries per strip once per build #1710 docs commit change only doc comments, one parity test and specs; on the final tree 782a0a3 these were re-run green: fmt; realtime policy 168; workspace clippy -D warnings; no-feature release and debug checks; the whole doc job; workspace tests (all features); check-sdk-generated; check-capi-abi; check-cross-targets; check-host-core-policy; CI path routing; script reachability; test-support CI. The e7938ee run also passed: bench policy; host-core clippy default / no-default / all features and the loom spectrum handoff; builtins, console and effect-runtime fixtures; graph determinism; effect contract; protocol wasm parity; SDK types; protocol allocation audit; builtins and builtins-graph trace audits; test-web-audioworklet; web build, check-web-audioworklet, SDK headless; browser expected resources, SDK deletions, command reason and kind vocabularies; fuzz check;audit capipcm_digestbffc21e857b5e134, 0 allocations.--check-matrix --self-test-mutations) all pass at e7938ee (no render change after it).Review
Fresh opus-high adversarial reviewers, one per review unit, then a focused verification of every fold that touched render.
crates/automationpath forrelease_hold_by.Placeholders to file
.github/ISSUE_SPECS/1714-skip-the-grid-walk-for-step-only-automation-cells.md; weekly performance pass, phase 2).effective_mutereadback reports the terms (static, VCA, solo), notcurve || terms.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.