Repository navigation
Controls batch 13b: stored-automation start (#1635-#1639), core-owned observation addressing and limits (#1676-#1678) - #1687
Merged
Merged
Conversation
A browser observation record (kinds 7 and 8) names its tap by stable key (strip ID, rack, slot or insert ID, tap ID), the key OBSERVATION_ENDED uses; SessionState::resolve_observation_key resolves it on the newest committed plan allocation-free and refuses an unknown key with a typed reason before any write. host-web only decodes the staged bytes; the SDK's index re-addressing, remap and epoch wait are deleted. The record grows to 272 bytes; the ABI mirrors follow. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
TRANSPORT_SET field 2, the snapshot's field 2 and the TRANSPORT_STATE event's field 3 are retired and refused in either flag form; the transport carries its state and effective sample only. The stored position nothing read leaves the host-core provider and the mock. COMPLETE_SCHEMA_HASH 0xcc9a7bcc502c4936 -> 0x331654b324d076e8 (#1635 retires the stored transport position); the capi pcm_digest is unchanged (bf7dcedd1d92621f). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A SET_CONTROL edit may name the native effect it was written for (field 7 of the new SetControlAddress, inserts and console only); the core refuses a mismatch with control.effect.changed before any write, on both hosts through the one SessionStore. The SDK builders send the effect and the client-side effectRowResolver is deleted. COMPLETE_SCHEMA_HASH re-pinned to 0x63ff2e60976e0e21 (#1678 adds the expected-effect field); the capi pcm_digest is unchanged (bf7dcedd1d92621f). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
) The effect contract keeps only Point spans and the Block and None automation rates; automation_segment_value and the Sample rate are deleted and the retired values are refused by the descriptor and span checks, never renumbered. The conformance mock, the randomized generator, the parameter-metadata rate table and the docs follow. No wire frame carries the retired values, so the protocol hash does not move; the capi pcm_digest is unchanged (bf7dcedd1d92621f). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cap is the number of keys one OBSERVATION_ENDED frame carries with both IDs at their longest (3 at 1 KiB, 12 at 4 KiB, 51 at 16 KiB). A batch that would leave more taps armed is refused before any ack; the browser reports it as backpressure at the crossing record. Each ended event cell reserves min(slots, cap) keys at the high-water slot count. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New math-only crate `automation`: evaluates stored segments, builds a per-cell program with a stored discontinuity list, and emits at most 2*ceil(q/64)+3 events per cell per block, invariant to quantum and seek position, with no allocation on the event path. Its scalar f64 pins join the cross-target wasm gate corpus as a width-independent block. Realtime-policy floors move to the tree's counts (31 files, 143 regions). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review fixes: the per-cell event bound is 2*ceil(q/64)+3, plus one for a no_restart cell (CellProgram::max_events, tight on the review's repro); the builder refuses discontinuities closer than 64 samples, as the session does (#1626); a deferral behind a forward span is due at its start, never a wrapped offset; a jump to the in-flight target still lands; the corpus test leaves the digests to G5; realtime regions cover the render-reachable accessors (floors 32 files, 144 regions). Corpus case 2's table moved a step from 3190 to 3180 to meet the spacing rule, so its G5 pin moved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…shipped it The caller resolves the fader row's jump length for each block with LiveRamps::for_row and passes one u32 to CellEvents::new; #1637 stores no Word(Fader) key (root, 2026-10-15). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A deferred no_restart jump that comes due takes the same lane check as a discontinuity: while a ramp the caller reported later is in flight, it waits for the ramp's last sample plus one (D4). The bound test again proves its tables stress the bound; the spec's D4 and gate 3 state the no_restart +1. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#1676) Root ruling 2026-10-15: a cap refusal is never BACKPRESSURE. New command reason 15 observationLimit (result UNSUPPORTED, not retried by the SDK) in every reason list; the reason gates allow the retired gap 12-14 and require the values otherwise dense. One core entry point, admit_and_push_observation_batch, checks the cap, then the queue room, then pushes; the single push is crate-private. The core test uses 127-byte IDs; a refusal at a record after the first is tested on both the core and the browser; the SDK names the cap in its error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… seek landing on a busy lane Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ission The core refuses a second naming of one tap in a batch (ObservationRefusal::Duplicate; the browser answers MALFORMED as before), so no caller can arm past the cap by naming a tap twice. Admission counts per producer in scratch built with the plan's observation slots, O(n) and allocation-free. MUTATIONS.md rows follow the self-tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
FaderRampStage::process_with splits a block at each operation offset (RetargetGain, SetGain, SetMute, RememberGain) and runs the existing plane kernel over each piece, bit-equal to split blocks. A per-lane flag marks a mute ramp toward 0; a gain change while muted or during it only remembers the gain, for timed operations and, per the amendment, for the live setter too. No production path calls process_with yet. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1638) Review fold, no rendered change: the decision record states the unmute- ramp hold's successor obligation, and #1647 gains D1.6 and gate 8 (a remembered Jump or Set is reissued as one RetargetGain at the held ramp's end). FaderOperationSource states its contract; a block that stops pulling on a non-rising offset counts fader_operations_stopped. The fused settled path's decline has its test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s reported, the reissue's own hold, a moving-curve gate Docs only (attempt 3 of #1638, record fold). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every graph plan holds one latest-target cell of the session's fader, mute and pan ramp lengths. Render reads it once per block at block entry. A control_smoothing change on a session whose automation reads a length is a live edit that writes the cell under the transaction's stamp. Re-pinned plan byte rows, each "the jump-length cell, #1639 D1". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…(root ruling) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s cell Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…measured, a successor seed test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s review fold and #1648's amendment Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- The SDK coalescing key carries the expected effect (m1). - Test claims match their assertions (m2); an export check is deleted (m3). - The observation admission refuses a change with no slot, terminally, before any push (m7); the redundant strip fallback is gone. - The browser charges its producer-to-instance table (m8). - The SDK cap error carries observationLimit as a diagnostic code (m9). - An empty record ID is malformed (m11). - The scalar fader's gain_held and ramp_remaining return None past lane 1 (m13). - A stored automation target refuses the expected-effect field (root ruling). - Stale names and comments after #1635, #1636 and #1678. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- #1647 gate 8 gets its acceptance criteria back, with constraint 7; #1638 points at cases (c) and (e). - #1648: jump lengths follow a rebuild on rows that render (root wording), release cells carry the D1.6 obligation, the CellState seed is authorized (also for #1646). - One integrated COMPLETE_SCHEMA_HASH re-pin is recorded in #1635, #1678 and the conformance record. - The SDK README describes the core's control.effect.changed refusal. - Stale prose after #1635 and #1636; #1676's attempt-1 text marked superseded; #1584 and #1651 amendments; #1637's reposition wording. - Placeholders TBD32 (exact-byte observation admission) and TBD33 (remove the redundant span kind and end). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ated tree 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 13b: stored automation gets its compiler, the fader stage gets timed operations, and every plan holds the session's jump lengths. The protocol retires the stored transport position and the unused span kinds. Observation taps are addressed by stable key and capped in the core, and an effect-row edit whose effect changed is refused in the core, on both hosts.
Closes #1635
Closes #1636
Closes #1637
Closes #1638
Closes #1639
Closes #1676
Closes #1677
Closes #1678
What changed
TRANSPORT_SETfield 2, the snapshot's field 2 and theTRANSPORT_STATEevent's field 3 (the stored transport position) are retired. A retired field is refused at decode in both flag forms (UNKNOWN_REQUIRED_FIELDmandatory,MALFORMED_FRAMEoptional), before any change and before any event is reserved.retired_code_rows()gains the twoTRANSPORT_SETrows.AutomationSpanKindis{Point}andAutomationRateis{Block, None}. The retired values are refused and never reallocated.automation_segment_valueand theSamplerate are deleted. The protocol half was already gone, so nothing on the wire moved.crates/automation(no_std+alloc, depends onmathonly). It compiles stored automation into per-cell programs (ProgramBuilder,CellProgram) and generates events in node time on render (CellState,NodeSpan,CellEvents), allocation-free. The G5 scalar corpus is appended to the wasm gate corpus.FaderOperation, a fixed-sizeFaderOperationSinkon the render stack, and the pull traitFaderOperationSource.process_withcuts the block at each offset, so a split moves no bit. A lane's gain is held during a mute or unmute ramp (mute_ramp, carried across a swap). The live F22 rule:set_fader_gainon a muted lane only remembers the gain. New counterfader_operations_stopped. Nothing feeds timed operations to the fader stage until Render moving stored fader automation, seeks and latency #1647: no caller ofprocess_withortry_process_settled_with_matrix_and_operationsexists outsidecrates/builtins(checked on the integrated tree). Root ruled that Apply timed operations inside a block on the strip fader stage #1638 closes on its rescoped record: the unmute-ramp reissue mechanism is Render moving stored fader automation, seeks and latency #1647's design (its batch 13b amendment: requirement, constraints 1-7, gate 8 cases (a)-(e)), and Classify fader automation edits as carried rebuilds #1648 carries it.GraphJumpLengths). Render reads it once per block at block entry, after the live snapshot. Acontrol_smoothingchange on a session whose automation reads a length is aliveedit that writes the cell under the transaction's stamp, after every fallible check and before publication. Preparation refuses a handle set without the writer, so every epoch holds one.OBSERVATION_ENDEDframe holds with maximum IDs (1 KiB: 3, 4 KiB: 12, the browser's 16 KiB: 51). A batch is admitted whole byadmit_and_push_observation_batchbefore any push. The browser refuses past the cap with the new command reason 15observationLimit(RESULT_UNSUPPORTED, never backpressure; reasons 12-14 stay retired), and the SDK does not retry it. A tap named twice in one batch is refused. The ended-event reserve is charged bymin(slots, cap)keys, not by the frame size.SessionState::resolve_observation_keyon the newest committed plan. The record is 272 bytes (was 48); the command staging grows from 12,288 to 69,632 bytes, allocated at boot. The SDK's index remapping is deleted.SET_CONTROL's address is its own message with an optional field 7, the effect the edit was written for. The core refuses a stale edit withcontrol.effect.changedon both hosts (MisoControlRefusalin the SDK). The SDK'seffectRowResolveris deleted. A stored automation target refuses field 7 in every section (review fold, root ruling).Evidence
batch-gates.sh: fmt, bench and realtime policies, the host-core feature matrix and loom, workspace clippy, the workspace tests, the doc job, everycheck-*script, the cross targets, the web build, the SDK headless suite, the fuzz check) passes on the integrated tree (head cddff37), with the SDK headless suite at 559 of 559. A first run on 4bbbcb2, before the review fold, was green too.--check-matrix --self-test-mutationson cddff37: chromium 151.0.7922.34, firefox 153.0 and webkit 26.5 each print "all qualification gates passed". Render allocations are 0 in every row,observation-armedandobservation-disarmedamong them.audit capi:pcm_digestbf7dcedd1d92621f(unchanged from main), 0 allocations, 0 locks, 0 syscalls.process_with(1,000 blocks) allocate and free nothing (bench_support::allocthread counters).fader_rampgate 2 holds the rule for the timed operations and the live setter.f64corpus pins) and Apply timed operations inside a block on the strip fader stage #1638 (Simd4 on NEON) run only in CI: this host has no AArch64 toolchain.Re-pins (each from a measurement)
COMPLETE_SCHEMA_HASH, once for Retire the protocol's stored transport position #1635 and Refuse an effect-row edit whose effect changed, in the core #1678 together:0xcc9a_7bcc_502c_4936to0x0c71_96f8_6abe_6d57. Each branch alone gave0x3316_54b3_24d0_76e8(Retire the protocol's stored transport position #1635) and0x63ff_2e60_976e_0e21(Refuse an effect-row edit whose effect changed, in the core #1678); neither stood on main. The parity strings,fuzz/corpus/complete-schema-manifest.mdanddocs/CONTROL_PROTOCOL_CONFORMANCE.mdfollow. The corpus stays 46 frames.capi_retained_bytesceiling 205,312 to 182,400 (Cap the observation bindings by what one ended event holds #1676: the reserve is charged by slots, not by the frame). Measured 165,782 on the W lane, 165,934 on the integrated tree (+168, Hold the automation jump lengths in a plan cell #1639's cell), within the ceiling.the_graph_row_counts_the_plans_gate_and_a_count_it_made_and_holds: no strip controls 72 to 264; the preparation's own count 96 to 264; the session's count 72 to 240.live_send_lanes_are_charged_against_the_graph_cap: live less idle is the route lanes only (was route lanes + 24); the live total is 118,304 on the head.the_graph_row_charges_the_plans_gate_and_not_the_sessions_superseded_count: 72 to 240.graph_session_plus_plan_bytesmeasures 315,966 (main 315,798, +168), within its ceiling of 346,432.bridgeRetainedBytesis 1,542,682 of 1,667,648 andgraphSessionPlusPlanBytes30,370 of 35,648. The review fold charges Address observation records by stable key in the core #1677's producer-to-instance table in the arm table (producer_slots); no exact row moved.crates/protocol/tests/fixtures/set-control-frames.json(Refuse an effect-row edit whose effect changed, in the core #1678'sexpectedEffect), the C ABI transport vectors (Retire the protocol's stored transport position #1635), and the generated SDK tables and.d.tscopies (Cap the observation bindings by what one ended event holds #1676 reason 15, Address observation records by stable key in the core #1677 record layout).Review
Per-issue adversarial reviews (opus-high): #1637 PASS at attempt 3; #1638 three record FAILs and then the root rescope; #1676 PASS at attempt 2 with three minors folded; #1639 PASS with five minors folded (a typed writer, the cell's bytes measured, a C ABI test that a successor is seeded from the committed model, red on a constant seed).
One opus-high batch review of origin/main...4bbbcb2: FAIL on docs only. The code held: render stays allocation-, lock- and syscall-free; no ack precedes a drop on any new path (#1635 decode refusal, #1678 prepare refusal, #1676 whole-batch admission before any push, #1639 write after every fallible step); the hosts share the core; no placeholder code. Folded in 94a953f (code) and cddff37 (docs):
Ereplaces any cell gain operation there). Apply timed operations inside a block on the strip fader stage #1638's record names gate 8 cases (c) and (e).gain_held/ramp_remainingreturnNonepast lane 1; the SDK cap error carries a diagnostic code; test claims match their assertions; stale prose after Retire the protocol's stored transport position #1635/Retire the automation span kinds and the sample rate that no producer uses #1636/Refuse an effect-row edit whose effect changed, in the core #1678; Cap the observation bindings by what one ended event holds #1676's attempt-1 text is marked superseded; Subscribe to an effect's observation tap with a transaction edit #1584, Prepare stored fader automation and render it flat #1646, Render stored mute automation on the strip #1651 amendments.Recorded for root, no change here: #1676's cap assumes two 127-byte IDs per key (#1685 below). A
SetMutethat does not change the mute state still retargets the fader ramp (now a #1651 constraint).Departures recorded in the specs
UNKNOWN_REQUIRED_FIELD/MALFORMED_FRAME, as for the retired track fields, notINVALID_FIELD.NodeSpan::new, builder limits,repositiondrops the held event).automation_jump_row; every plan charges its own superseded count; acontrol_smoothingchange with no reading automation writes nothing (closed by Classify fader automation edits as carried rebuilds #1648's rebuild rule).observationLimit(root ruling); no C ABI parity row, because the C ABI observe edit is Subscribe to an effect's observation tap with a transaction edit #1584.SetControlAddressmessage, not on the shared control address.Issues to file from this batch's specs
admit-observation-bindings-by-the-exact-encoded-bytes-of-the-ended-event(root: first K slice of batch 14).remove-the-redundant-span-kind-and-end-from-prepared-automation-spans.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.