Design notes — Part XV — v3.0, Phase 16: the lab, the books and the 3.0 release (step 92: the lessons' fold, Kessho on the web, the Suzu lab v2, the books; then the release candidates, the wave and `v3.0.0`)
Opened 2026-10-26, the day Phase 15’s last step shipped (DECISIONS_14 #5); merged into DECISIONS.md as Part XV at the arc’s fold. The spec is PROJECT_SPEC.md (v5) with the arc’s draft TO_PROJECT_SPEC.md (the fold into spec v6 is the author’s); the roadmap is ROADMAP_6.md step 92 (“all machines, docs first; the step splits if the session runs long”). THE CORE IS FROZEN (libsumi 1.12.0) and so is Voxo at 0.31.0 for this step: nothing below the web’s glue changed — the step is the lessons, the marble, the lab and the books. The release itself (the v3.0.0-rc.N tags on both tracks, the wave’s questions, the final RC promoted with zero code changes, the store builds, the fold) is the author’s, as every release has been.
#1 — Step 92, the first session: the lessons’ fold, Kessho on the web, the Suzu lab v2, the books (2026-10-26; no engine change; evidence docs/evidence/step92)
Section titled “#1 — Step 92, the first session: the lessons’ fold, Kessho on the web, the Suzu lab v2, the books (2026-10-26; no engine change; evidence docs/evidence/step92)”What the roadmap asked (ROADMAP_6.md step 92): the marble with ?medium=2 on every scene (shipped at step 67), ?mineral=<id> on the Kessho scenes, the scenes arnold, braid and chord_wave (check.mjs’s list to twenty), the Poincaré panel in the scope demo; the lab’s panels for the membrane, the Toda ring, the Boris gyroscope, the billiard and the Dirac network under suzu_lab_gate.mjs; the books — Kessho and the harmony operators in the operator book, the Minerals page with the crystal-drop theorem’s one-line proof and the selenite sign test as a reader’s exercise, the new voices in the Suzu book with their panels, the sampler’s coverage and the compat page, the chart’s rows for CTL 20–23 and the three modes, the settings reference’s mineral panel; and, the author’s word of 2026-10-25, THE LESSONS folded into the book with the review’s checks, links and fixes applied. Gates: check.mjs green with the new scenes embedded, suzu_lab_gate.mjs green, the wasm flatness demo ≤ 1e-3 at the fp16 web tier, chart_check.py green, the docs’ URLs resolving.
-
The lessons are in the book (
site/src/content/docs/lessons/:index.mdandmodule-01.md…module-06.md; the six labs as static pagessite/public/lessons/module_0N_lab.html, linked from each module; a Lessons group in the sidebar after Suzu’s; a card on the home page). The drafts stay insite/drafts/lessons/— the author removes drafts, as the operator drafts’ rule says. The conversion is a scripted fold (fold_lessons.pyin the session’s scratchpad, the whole list of replacements asserting one occurrence each) from the drafts as reviewed: every module keeps its structure, its mathematics and its problem sets; what changed is what the review of 2026-10-25 (site/drafts/lessons/REVIEW_modules_02-06.md) found against the engine. Everywhere:DECISIONS_13.md→DECISIONS.mdPart XIII cited asDECISIONS_13 #n;tests/suzu_test.cpp/physics_test.cpp→tests/voxo_suzu_tests.cppand, for the free braid’s invariants,tests/normalizer_tests.cpp;advect_fs/composite_fs/kessho_fs/sumi_invert_deform_point→deform.glsl’s per-operator*_fs,composite.glsl’skessho_col, and the exact inverse of a Chladni step as the negated shears in reversed order held by the soak, not a function; everyvoxo/src/suzu.hline number dropped for the struct’s or the gate’s name (the lines did not survive step 87, as the review said); “Layer A stores the displacement” → the ping-pong displacement texture, RGBA16F by default (RGBA32F behind a desktop flag), the Jacobian by central differences over texels. Module 2: the Chladni listing replaced by the shader’s one wave per pass (P_src = P + ½ψ·weight·sin(s)·(wy, −wx), stage 0 then 1) and the invented “3.1e-8 round trip” dropped; the braid’s circulationΓ_k = sign(C_k)·Γ_vel·(0.3 + 0.7|C_k|)with Γ_vel 0.036, the regulariserrc2[j][k],braid_mode = SUMI_BRAID_FREE(the D key), the fixed point at 1e-15 in at most sixteen rounds, the test a consonant triad for 72 000 steps at 1/120 s with |dH/H| < 1e-6 and the impulses within 1e-9; the wake’s fold at a/2 said to be the lesson’s own derivation, the Stokesletwake_profile1 and the inviscid doublet the DEFAULT (verified in the header: 0 is listed first and is the default); gate 59 as it is (twelve random skew J, n 6..16, |gain_q − 1| < 1e-9, measured 2e-16) and “dim x = 2m + 3 is odd” VERIFIED againstDirac::chain(nn = (masses + 1) + masses + 2: m + 1 extensions, m momenta, the bridge’s two — the lesson now says where the count comes from); Gromov’s theorem stated as the non-squeezing obstruction, the sum of projected areas as plain ω-preservation; RK4’s determinant 1 − ε⁶/72 + ε⁸/576 (three places; the derivation checked: (1 − ε²/2 + ε⁴/24)² + (ε − ε³/6)² = 1 − (3 − 2)ε⁶/72 + ε⁸/576); the Störmer–Verlet shadow ½[(1 − ε²/4)x² + y²] with the factor on the drifted variable; the “+14 dBFS breaker” → the bus breaker cuts a non-finite block, the lab’s worklet mutes at full scale (the standalone lab’s own breaker relabelled as the lab’s); thelive_capred control → a development finding of step 83 never shipped (the lab’s own control), the ring’s shipped redtoda_gate0 (+19 dB in a second at C8, gate 52);toda_expa degree-11 Taylor after Cody–Waite; the stability bounds each voice’s own (string_cfls ≤ 1 with 1.05 red, the ring’s k·cap ≤ 0.9 and √k·ĉ·b ≤ 0.15, f < 1.9 the SVF’s); the membrane §13.9, the Mathieu / Floquet reading and the growth presented as the lesson’s interpretation, the record’s measurement quoted (−0.00016 dB on the 8 × 6 grid at 96 k). Module 3: §3.1.2 rewritten on the shipped observables — Layer B the trace discriminant Δ = (tr J)² − 4 and the caustic det(I + z∇d) = 1 + z(1 − z)(tr J − 2) with its iso-trace fold at three depths, the conical ring where |Δ| < 0.15 and σ > 0.05 as a stylisation, no heightfield and no curvature in the medium;kessho_coland the spec draft’s §10.7; the rosette r₀(1 + 0.6 cos⁸ mθ)/(1 + 0.6·35/128) mixed toward the circle;Cell::retunekeeps the x-AMPLITUDE, not the action (the orbit encloses πA²√(1 − ε²/4)), the plain retune’s change phase-dependent, Problem 3.3(2)‘s matrix given its true determinant 1/√(1 − ε²/4) — not a symplectomorphism, the conjugation that makes the ellipse a circle; the Toda pickup REVERSED: the Eulerian reading was the one rejected at step 83 (−43 dB of aliasing content), the pickup stands still against the mean drift. Module 4: the Toda ring near-integrable as the discrete ring (a modified H, not the Lax invariants — why the shape gate), Hénon–Flaschka kept for the continuous lattice; the suite’s strobe is the (x₁, x₂) pair at the bass phasor (24 of 576 cells, 66 393 collisions lossless within 2.4e-12 dB), the (s, sin ψ) collision map the lesson’s own coordinate. Module 5: the secondary resonance’s width K/2 in both places (2√K + K/2 = π ⟹ 1.46); Greene cited for K_c, not the tree (the engine caps a canvas throw at K = 1.25 a step and the rotor’s at 2.5). Module 6:braid_modeFREE and n ≤ 16; the lattice’s gate quoted (−0.0026 dB over ten minutes, the partials within 0.08 cent), “machine precision” returned to the Dirac network. Module 1 (already adapted,ADAPTATION_NOTES.md) changed only in its links. For the author, from the notes, still open: the glide-number discrepancy between the cells chapter’s 0.63 dB and the suite’s printed plain-form figures (0.057 / 0.062), and the spec draft’s §10.7.8 rosette formula against the shader’s. -
Kessho on the web (
web/sumi_web.cpp,web/site/sumi-host.js,web/site/scenes.js; the marble’s wasm rebuilt, the lab’s too).sumi_web_mineral_preset(inst, id)sets a library mineral — its optical half throughsumi_set_mineral, its mechanical half (the habit, the roundness, the blades, the cleavage profile) on the params as the desktop pairs them (app_mineral_preset,DECISIONS_10 #8: the table is COPIED into the web glue — a shared table would live inpresets/or the core, both frozen; carried) — andsumi_web_mineral_getreads the id back; the preset capture carries the mineral (sumi_preset_t::mineral,mineral_id,mineral_present, schema 3) through the one serializer. The web’s parameter ids grow in the struct’s order:polarizer_mode45,braid_mode46,kessho_retard…kessho_caustic47–51,drop_habit,habit_roundness,habit_blades,tine_profile52–55 (clamped as the desktop clamps them). The host’s Medium menu gains Kessho; under it a Mineral row (the six by name), the exposure, the backlight, the regime tint, the caustic, the facet grain, the polarizer (one analyzer / per voice) and the braid vortices (pinned / free) rows, and the drop’s and tine’s shape rows for every medium; the palette folder hides under Kessho (a mineral replaces it). The three routing menus gain Kessho’s consumers — Braid consonance (bend 5), Arnol’d tongue lock (press 3), Polarizer angle (slide 3).?mineral=<id>on any scene is honoured by the host (applied after the dip, before the scene’s script); the three Kessho scenes carry it as a slider (◇) as well. The scenesarnold,braidandchord_waveare the mapper’s routes driven as a controller would — no new gesture export: the MPE zone, a bass note and its interval on member channels, then the channel pressure (the lock: K as a fraction of K_max, the bend in cents for the just or the tempered interval), a held chord withbraid_modefrom the F slider (two clusters of ink laid first), the poly pressure ramped on one to three notes a fifth apart at an octave (the bands, the lattice, the crossing) — each defaulting to medium 2 and completing underpace=0for the sweep.check.mjs’s list is twenty and every scene is embedded. -
The Suzu lab v2 (
web/suzu/,tools/suzu_lab_gate.mjs,site/src/components/Lab.astro,check.mjs). THE STROBE ON THE WEB:sw_strobe(v, clock),sw_strobe_poll(v, max_voices, max_points)into flat records of 8 + 4 × 32 floats (channel, note, kind, held, serial, count, total, hz, then x, y, u, w —sw_strobe_stride,sw_strobe_ptr),sw_strobe_hz;suzu-engine.js’sstrobe()/strobePoll()/strobeHz(); the worklet’sstrobeoption (the clock, re-applied after a restart) and the snapshot’sstrobefield, the returns since the last snapshot;Lab’sstrobeoption andsetStrobe(),offlineRun’sstrobe; the exports listed inweb/CMakeLists.txtwith the two strike exports of steps 79–80 that the list had missed (theusedattribute had carried them).lab-core.jsgainspeakScan(the strongest line between two frequencies by a Goertzel scan over a Hann window — the gyro’s doublet to a fiftieth of a hertz, the gong’s landing) and the five pages inPAGES(the index’s cards follow). THE FIVE PANELS, each on the patch table’s values, with a red control where the engine has one and the Poincaré strobe beside its own view:membrane— the sheet node by node from the displacement array, the leapfrog’s invariant (k[7]) on the strip, λ₂D at E_max and E/E_max read live, the gong button (swell 0.8), the reddrum_cfl_gate0 withdrum_cfl1.3 (λ₂D at 1.3 × the bar);toda— the ring’s nodes drawn out by their bond’s compression, the resolution rule’s readouts (the inner steps, the b asked / applied / ceiling, the compression’s peak), H on the strip, the press as the nonlinearity, the redtoda_gate0;gyro— the spirograph (x₁, x₂) from the ring, the strobe on the voice’s own clock (the cyclotron period, clock 2), the doublet the scheme sounds against the continuous one, the two lines marked on the spectrum, the press as the field (the poly pressure), the redboris_prewarp0;billiard— the table (the two half-ellipses and the straight walls from k[1..3]) with the orbit inside, the strobe at the bass with its cell count of 576, the bounce measured against (π/2)/asin(1/v) with v = √(2H) from the engine’s own k[4], the wheel and CC 74, the redbill_exact0;dirac— every state the Cayley step rotates (the extensions, the momenta, the bridge’s two), the ledger drawn as it accrues (H, the stop’s losses, the bow’s gain, their sum), the step’s Q-norm gain and the stop’s hits live, the bow by the breath and the press. The checks (?gate=<page>, the gate’s table below): the membrane’s gong lands sharp and settles (+73 cents in the first 300 ms, +2 at 1.2–1.9 s at velocity 127; +2 at velocity 30; the drum −1), the invariant 6.5e-6 dB over 2.7 s, the red caught at the first block; the Toda ring’s linear line +0.0 cents, the train +642 cents over the second from 0.5 s (the rule at two inner steps, b 2.40 of 2.40 at A3), H’s second-mean −0.0004 dB, the red a blow-up at 0.03 s at C8; the gyroscope’s doublet 452.16 / 428.16 Hz against the formula’s 452.16 / 428.16 (−0.00 / −0.00 cents; the engine’s own k[4..5] the same), the mono line −0.00, H within 0.033 dB (the known ±0.031 breathing), the raw prewarp +1.21 cents at B6 against the prewarped −0.00; the billiard’s sine −0.0 cents under the wall, the bounce 3.817× at v 2.50 and 2.583× at v 1.75 both 0.00 % off the geometry (2468 collisions), the strobe 10 cells of 576 on the circle against 188 on the stadium, the red 1.45 % off at A3 and 4.73 % at A5; the network −0.39 cents plucked with H flat to 0 dB over 2.8 s and gain_q 1.000000000, the ledger’s residual 4.3e-7 of H over 78 snapshots under the bow with the stop (640 hits), the gain never above the work, the tone +3.9 cents.Lab.astro’s union andcheck.mjs’sLAB_PAGESare eleven; the five chapters embed their panels; the lab index’s table has the five rows and names the strobe. -
The books (
site/).reference/compat.md— the compat report’s eight sentences (the table asvoxo/COMPAT_REPORT.mdhas it), what plays since 3.0 by step, what stays out of scope — in the Reference group. The MIDI chart (site/src/data/midi-chart.json): the per-note bend, press and slide rows now list every consumer each mode has (the Anod modes 2–4 had never been written in) and Kessho’s defaults — bend 5 the braid’s consonance, press 3 the Arnol’d lock, slide 3 the polarizer’s angle; the poly-pressure row names the chord wave under Kessho (and the Chladni stir under Anod); the GlobalCtl row names CTL 20–23 (a mineral is not a dimension — it is a setting).chart_check.py: 52 ok, 0 failed, THE CHART MATCHES THE BYTE LOGS — the existing logs: the rows are input-side (the normalizer’s contract, verified by its suite) and the modes change no output byte, so the Play-mode logs of step 26 still verify every output row; fresh logs from the 3.0 store builds are the RC round’s to record, for the author. The Minerals page: the crystal-drop theorem’s one-line proof in the mechanical half (in (ρ, θ) the area form is dρ ∧ dθ and a translation of ρ by a function of θ alone is a shear), the selenite sign test as the reader’s exercise (the four quadrants, the analyzer’s quarter turn, the tine’s diagonals, Quartz as the control) with a live Selenite drop under Kessho (mineral=5on the embed’s address); the three harmony pages embed their scenes before Ownership; the medium guide names the third medium, its bindings and its mineral; the web guide names the twenty scenes,medium=0|1|2andmineral=0…5; the settings reference’s mineral panel was in place since step 76b.check.mjsafter the fold: 96 built pages from 89 sources, 20/20 scenes and 11/11 lab pages embedded via/marble/, every link resolving (the lessons’ own links climb two levels —../../operators/,../../suzu/— and the labs beside them one). -
The flatness reading at the web tier (
tools/kessho_flat_web.mjs, new): the desktop’s--kessho-flatestimator on the marble’s field dump — |det J − 1| of the pre-image u = x + dx, v = y + dy by central differences over ±1, ±2 and ±3 texels, the interior 16 texels in, a stencil straddling a drop’s rim (the ink band’s parity) masked, and two masks the desktop’s soak scenes never needed, counted and printed: fresh ink (the five taps sharing one pre-image) and the sampler’s clamp (the pre-image constant along one axis —CLAMP_TO_EDGEwhere an operator’s tail reaches past the sheet) — read on the §4.6 canonical script thattools/web_gate.mjsdumps. The reading: the median 8.3e-3 at ±1, 4.6e-3 at ±2, 3.4e-3 at ±3 (224 636 texels, 5 592 masked at the rims, 172 at the clamp; the rims’ neighbourhoods own the maximum, 9–29, and the 99th percentile, as the drops’ finite-difference singularity does on the desktop). AGAINST THE ROADMAP’S BAR OF 1e-3 THE READING IS OVER: it is the tier’s floor — the fp16 field under the WebGPU resampler reads a thousandth or two above the Metal tier’s 2e-3 at ±3 — exactly the situation of step 71, where the desktop’s gate 2 could not hold the proposal’s 1e-4 and was re-based on the floor as measured (DECISIONS_10 #4). Recorded as measured, the tool exiting 3 against the bar it was given, for the author: the bar at the web tier is the floor, or it is nothing.
5b. The Poincaré panel, read. The roadmap’s “the Poincaré panel in the scope demo” is taken as the lab’s scope pages: the strobe’s exports are generic and the five new pages each carry a strobe panel beside their own view (the gyroscope on its own clock, the four others at the bass); the six older pages keep their sections as built (the chaos page builds Chirikov’s section from the recent trace, which the engine’s clock-2 strobe would also give) — a panel on any of them is one strobe option and a Portrait away, at the author’s call.
5c. The six captures. The Minerals page shows the six at ship as the web build draws them — the drop scene under Kessho, four drops, mineral=0…5 — captured through tools/web_gate.mjs --fullshots at a 1600-wide window (the scene’s own panel in the corner, the address it documents) and placed as 900-pixel JPEGs in site/src/assets/operators/; the desktop’s --mineral <id> renders and the author’s viewings remain the record of the minerals’ look (git show of step 71b’s evidence).
- Found on the way. (a) A scripted edit of
web/site/sumi-host.jsleftPARAM_ID’s closing brace behind a trailing comment: the marble loaded nothing, and the web gate read it as “no field dump within 60 s … WebGPU unavailable” with an empty console while the scene sweep retried every scene;node --input-type=module --checknamed the line — a web script is syntax-checked after every scripted edit now, before a gate. (b) The Toda ring’s pitch is not a period: a period detector on the linear ring reads a beat (the modes are the lattice’s sin(mπ/N), not harmonics) and on the train reads a sub-multiple; the suite’s measure — the spectral peak within ±100 cents of the note, within ±700 for the train, over the second from 0.5 s — is the lab’s too. (c) The billiard’s quantised bounce is a bigger share of the period as the note rises: the naive reflection is 1.45 % off at A3 and 4.73 % at A5 (the suite’s 3.8 % its worst over A3–A5); the lab’s red reads A5. (d) THE DIRAC NETWORK HAS NO RED OF ITS OWN, and the strings’ red does not reach it: the naive bow solve at the force 2.0, which breaks the chain’s ledger in the suite (gate 60’s RED on kind 2), stays in bound on the network — the bow acts through the chain’s own kick scale (SUZU_DIRAC_KF) and the ledger still closes to 1.5e-6 with the gain under the work. The page says so, offers the naive solve as the strings’ red for the reader to watch, and its check gates the measured fact; the voice’s safety is the Cayley step’s arithmetic, read live. (e) The web build’s export list for the lab wasm had carried the two strike exports of steps 79–80 only through theusedattribute; they are listed now.
The gates (docs/evidence/step92): check.mjs — 96 built pages from 89 sources, 20/20 scenes and 11/11 lab pages embedded via /marble/, every link resolving, ok; suzu_lab_gate.mjs — GREEN on eleven pages (the five new pages’ figures in item 3; the first runs kept, recording the three measurement corrections of item 6); web_gate.mjs --scenes — 20/20 scenes ran clean; web_gate.mjs --compare — PASS, max 9.77e-4 and mean 3.96e-9 against the Metal fixture with the new exports; kessho_flat_web.mjs — the medians 8.3e-3 / 4.6e-3 / 3.4e-3 at ±1 / ±2 / ±3, OVER the roadmap’s 1e-3 as the tier’s floor (item 5, for the author); suzu_web_gate.mjs — GREEN, every kind as at step 91; chart_check.py — 52 ok, 0 failed; the Debug ctest — 14 / 14 in 408 s. No tablet was touched: nothing below the web’s glue changed.
- Carried. The RC tags, the beta wave, the store builds and the fold (Parts X–XV, the roadmap to
ROADMAP.mdPart 10, the spec draft to spec v6) are the author’s; fresh byte logs from the 3.0 store builds; the mineral pairing table in two places (the desktop’s and the web’s — a shared home is a core or preset change, frozen); the Tab’s audio-thread placement (DECISIONS_13 #4); the glide-number discrepancy and the rosette formula from the lessons’ notes (item 1).
Phase close — 2026-10-26, the first session
Section titled “Phase close — 2026-10-26, the first session”Step 92’s first session shipped (#1): the lessons in the book, Kessho on the web, the Suzu lab v2 and the books — no engine change. Folded on the author’s word of 2026-10-26 together with the arc’s roadmap (ROADMAP.md Part 10). The release itself — the v3.0.0-rc.N tags on both tracks, the wave’s questions, the store builds, the final RC promoted with zero code changes, the transcription of the spec draft into spec v6 — is the author’s; what it records, if an entry is needed, continues this part.
midi-sink 2.0.0 · AGPL-3.0 · source
