feat: the Leslie, a two-rotor rotary speaker with drive ahead of the crossover #169

Merged
bcox merged 20 commits from leslie into main 2026-10-06 17:28:44 +00:00
Owner

Adds dsp::LeslieLayer, a two-rotor rotary speaker, as the thirteenth LayerKind (format 2.10), with two factory patches.

What it is

  • The cabinet. A one-pole crossover splits a mono input; the high band goes to a horn and the low band to a drum. Each rotor has a short line in the slot's cold storage, read once per microphone at a time and a level that follow one cosine: Doppler and tremolo. The rotors counter-rotate.
  • Speed. One speed field from -1 to +1 covers brake, slow and fast. Each rotor's rate slews toward its target at its own rise and fall, so the horn arrives while the drum is still accelerating.
  • Drive, ahead of the crossover. dsp/shaper.h's soft clip at twice the rate on the mono input, with drive and asymmetry (the shaper's bias), so the amplifier's harmonics are split by band and thrown by the rotors. The stage is AC-coupled and has unity gain where the curve does not bend. A patch that does not engage it pays nothing and stays bit-exact against the undriven engine.
  • Registration. resolve/leslie.h, format/leslie.h (LESL, LESH, two ROTR), patchdiff/walk_leslie.h, an editor page, a voice test.
  • Patches. leslie-return, a channel-scope Leslie on the external input; tonewheel-leslie, the tonewheel organ through one, macro 1 on speed. The bank is 65.

Outside the Leslie

  • Program::Init now resets slot strips and channel LFOs. It reset neither. tonewheel-leslie is the first factory patch to author a strip gain, which is how the bank test found the first; the review found the second. Before this, a new document in the editor kept the previous document's channel LFOs and a save wrote them.
  • format/project_test.cc: a project has 64 channels and the bank no longer fits in one. The fixture is the first 64 patches, and the round-trip case runs a second project so every patch is held by one of the two.
  • format/exchange_test.cc: a layer at gain zero is silent when soloed. The test asserts the import carried the zero, then compares at unity.

No file on the plan's read-only list changed: nothing under fabric/, rtl/ or hps/, and not dsp/layer.h, dsp/shaper.h, dsp/decimator.h, dsp/svf.h or dsp/va_*.h. sizeof(VoiceType), the patch size and the allocator size did not move. No golden moved.

Verified

On 954ac36a, once each: bazel test //... and --config=opt //..., 329 of 329; --config=asan //... and --config=ubsan //..., 329 of 329; --config=tsan over the five scoped targets, 5 of 5. The only commit after that is a ledger note.

Each task's tests were checked by injection, and an independent review re-ran 29 of those injections and wrote 28 of its own. Four of its own failed nothing at first; each became a test. The ledger has every one.

Known and left

  • //patches:patches_test's build entry asks for per-shard ASan times. The lane passed; the per-shard figures were not captured and the entry is still owed them.
  • //plugin:preset_race_test failed its anti-vacuity floor once in the review's first full run (47 adoptions against 48) and passed in every run since, the sanitizer lanes included. Its own comment attributes that to a loaded machine.
  • The cabinet's figures in the default and factory patches are the commonly quoted ones, written from memory and checked against no source.
  • The editor page has not been looked at on a screen.
  • A released voice with drive engaged is held about 14,000 samples at 48 kHz while the blocker empties. bcox has heard the engine and left this, the midpoint upsampler and the blocker's per-rate gain as built.
  • The phaser's and shifter's format tests have the matrix-leaf hole the review closed for the Leslie. Not changed here.
  • A tube curve is #149, deferred.

Design: docs/superpowers/specs/2026-10-05-leslie-layer-design.md. Ledger, with every measurement, injection and open item: docs/superpowers/ledgers/2026-10-05-leslie-layer.md.

🤖 Generated with Claude Code

Adds `dsp::LeslieLayer`, a two-rotor rotary speaker, as the thirteenth `LayerKind` (format 2.10), with two factory patches. ## What it is - **The cabinet.** A one-pole crossover splits a mono input; the high band goes to a horn and the low band to a drum. Each rotor has a short line in the slot's cold storage, read once per microphone at a time and a level that follow one cosine: Doppler and tremolo. The rotors counter-rotate. - **Speed.** One `speed` field from -1 to +1 covers brake, slow and fast. Each rotor's rate slews toward its target at its own rise and fall, so the horn arrives while the drum is still accelerating. - **Drive, ahead of the crossover.** `dsp/shaper.h`'s soft clip at twice the rate on the mono input, with `drive` and `asymmetry` (the shaper's bias), so the amplifier's harmonics are split by band and thrown by the rotors. The stage is AC-coupled and has unity gain where the curve does not bend. A patch that does not engage it pays nothing and stays bit-exact against the undriven engine. - **Registration.** `resolve/leslie.h`, `format/leslie.h` (`LESL`, `LESH`, two `ROTR`), `patchdiff/walk_leslie.h`, an editor page, a voice test. - **Patches.** `leslie-return`, a channel-scope Leslie on the external input; `tonewheel-leslie`, the tonewheel organ through one, macro 1 on speed. The bank is 65. ## Outside the Leslie - **`Program::Init` now resets slot strips and channel LFOs.** It reset neither. `tonewheel-leslie` is the first factory patch to author a strip gain, which is how the bank test found the first; the review found the second. Before this, a new document in the editor kept the previous document's channel LFOs and a save wrote them. - **`format/project_test.cc`**: a project has 64 channels and the bank no longer fits in one. The fixture is the first 64 patches, and the round-trip case runs a second project so every patch is held by one of the two. - **`format/exchange_test.cc`**: a layer at gain zero is silent when soloed. The test asserts the import carried the zero, then compares at unity. No file on the plan's read-only list changed: nothing under `fabric/`, `rtl/` or `hps/`, and not `dsp/layer.h`, `dsp/shaper.h`, `dsp/decimator.h`, `dsp/svf.h` or `dsp/va_*.h`. `sizeof(VoiceType)`, the patch size and the allocator size did not move. No golden moved. ## Verified On `954ac36a`, once each: `bazel test //...` and `--config=opt //...`, 329 of 329; `--config=asan //...` and `--config=ubsan //...`, 329 of 329; `--config=tsan` over the five scoped targets, 5 of 5. The only commit after that is a ledger note. Each task's tests were checked by injection, and an independent review re-ran 29 of those injections and wrote 28 of its own. Four of its own failed nothing at first; each became a test. The ledger has every one. ## Known and left - `//patches:patches_test`'s build entry asks for per-shard ASan times. The lane passed; the per-shard figures were not captured and the entry is still owed them. - `//plugin:preset_race_test` failed its anti-vacuity floor once in the review's first full run (47 adoptions against 48) and passed in every run since, the sanitizer lanes included. Its own comment attributes that to a loaded machine. - The cabinet's figures in the default and factory patches are the commonly quoted ones, written from memory and checked against no source. - The editor page has not been looked at on a screen. - A released voice with drive engaged is held about 14,000 samples at 48 kHz while the blocker empties. bcox has heard the engine and left this, the midpoint upsampler and the blocker's per-rate gain as built. - The phaser's and shifter's format tests have the matrix-leaf hole the review closed for the Leslie. Not changed here. - A tube curve is #149, deferred. Design: `docs/superpowers/specs/2026-10-05-leslie-layer-design.md`. Ledger, with every measurement, injection and open item: `docs/superpowers/ledgers/2026-10-05-leslie-layer.md`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bcox added 19 commits 2026-10-06 17:14:07 +00:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dsp/leslie_layer.h: a one-pole split, each band written to a 512-frame
line of its own in the slot's cold storage, and each of two microphones
reading each line at 1 + depth * (1 - cos) frames and scaling the read by
1 - tremolo * (1 - cos) / 2. A rotor is a phase and a rate that slews to
its target by a fixed step a sample and lands on it; the horn's phase adds
and the drum's subtracts. The engine is not registered as a layer kind
yet, and its tests build the resolved form by hand.

The header was in the working tree, untracked, when the task began. It
was read against the spec and kept with four small changes, which the
ledger lists.

dsp/leslie_layer_test.cc is 40 cases in one small target. 66 injections
were run against the header one at a time by a script; 64 fail a named
case. The two that fail nothing are the crossover's term in IsActive,
which the ledger shows can never be what holds a voice, and the matrix
reset at note-on, which Evaluate repeats. A third failed nothing until a
case was written for it: a fresh note released before any input.

The ledger is started with the task's decisions, measurements and the
injection table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drive and the shaper's asymmetry join the design at bcox's direction: a
soft clip at twice the rate on the mono input, engaged per note. The tube
curve is #149. The spec no longer says the crossover alone can hold a
voice; Task 1 showed that state is unreachable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cabinet's amplifier, inside the engine and ahead of the split, so what
a clip adds is divided between the rotors with everything else.
dsp/shaper.h's soft clip with its bias as `asymmetry`, each sample shaped
together with the midpoint between it and the one before, and
Decimator<2, 129> bringing the pair back to one. Resolved gains `drive` and
`asymmetry`; Destination gains kDrive.

A note engages the stage when its drive is above zero or an entry with a
nonzero amount is on kDrive (EngagesDrive, read at every NoteOn). Not
engaged, the input reaches the crossover untouched and Task 1's render is
bit for bit what it was. Engaged, the stage's delay is 32 frames at every
drive. The filter's history is hot state; it is cleared wherever the stage
starts, a fresh note or a legato engagement, and nowhere else. A nonzero
word into the filter resets the quiet count as one into a line does, and a
static_assert holds the filter's length under the count's reach.

One Task 1 case is edited: ALaneTouchedAtZeroOffsetRendersBitIdentically
walked every destination, and a nonzero amount on kDrive engages the stage
by the spec's rule, so that lane has a case of its own.

//dsp:leslie_drive_candidates_test (medium) measures the midpoint against
a hold and against dsp/interpolator.h, which the spec says the tree does
not have. The ledger's Task 2 section holds the table, the decision, and
three things the spec did not expect: an asymmetry leaves a mean while a
signal is in the curve, engaging the stage at a drive of zero is +3.5 dB,
and the midpoint costs 4 dB at 20 kHz.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two things after the drive stage's decimator, in the engaged stage only.

The curve's output is scaled by the reciprocal of its slope at its center,
read from ShaperCurve at note-on and not written as a constant, so a
signal the curve does not bend leaves the engaged stage at the level it
has with the stage off: a patch that reaches drive only through a lane is
no louder for the lane, and drive rises from the undriven level. The
curve's rail now sits at that reciprocal of full scale.

A one-pole then takes the mean out ahead of the crossover: dsp/svf.h's
OnePoleFilter at a gain of 2^-11, given directly because the corner is
under SvfOnePoleGain's floor, the output being the scaled sample less its
lowpass, saturating. An asymmetry left a mean of a quarter of the
fundamental under a signal, which the drum's tremolo would have turned
into a signal at the drum's rate. The blocker joins the stage's reset and
needs no term in IsActive: once the decimator is empty, a blocker that
holds anything puts a nonzero word into the crossover.

A released driven voice is held for the blocker's state to run down, and
the delay case holds an impulse's two sides to a bound and no longer raw
for raw, since the blocker is not symmetric. The ledger's Task 2b section
has the corner's table, the measurements and the injections; the spec is
brought to what stands, the upsampler it said the tree lacked among it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kLeslie goes last before kLayerKindCount and LeslieLayerType last in
VoiceType's list, so no existing kind's index moves. sizeof(VoiceType),
its Patch and ResolvedPatch, and the allocator are measured unchanged; the
Leslie's layer is pinned at 928 bytes, its patch at 904 and its store at
4,096, under the chorus's line, which goes on sizing a slot's storage.

resolve/leslie.h resolves the patch at one rate: the crossover as an
increment inside the one-pole's band, each rotor's two speeds in
RotorRate's units held at the engine's fastest, its rise and fall as
accelerations over the greater of the two, never under one unit and a jump
at zero, its depth and the Doppler lanes' span in frames held inside the
line. The patch names its rotors and the resolved form indexes them, and a
test moves each field on one rotor alone.

format/leslie.h reads and writes LESL at minor 2.10: a LESH leaf, a ROTR
leaf for the horn and one for the drum, and the matrix. The drive and the
asymmetry are LESH's last two words, so a leaf that stops before them
reads as an undriven cabinet, by the grammar's own rule for a shorter
header. No field refuses: the reader holds each inside the range the
resolver does, with the same helpers. A ROTR past the second is skipped.
The wrapper holds no LFO leaf, because the engine has no LFOs.

patchdiff/walk_leslie.h names every field the writer serializes, and the
editor gains the page, its matrix labels and kLeslieShape. The page has no
LFO block and reads no meter; the ledger lists every site that assumes a
layer has LFOs and what each needed, which was nothing.

There is no factory Leslie until the next task, so the patch-diff name
test and the coverage sweep's case add one to moog-lead.

Through the allocator: a panic clears a held Leslie's lines, a refresh
leaves its rotors turning and takes the field that was edited, a
note-scope Leslie frees its voice with the drive stage off and engaged,
and each note of a voice-scope one has lines of its own.

Sites outside the -Werror=switch net: plugin/state_census.cc's engine
names, program_resolve_test's door lists, patch_test's bare-layer fixture,
the coverage test's engine list, the size pins and editor/edit_sink.h. The
ledger has the sizes, the decisions and the injections.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
leslie-return is a channel-scope Leslie on the external input, beside the
other returns: the slow speed, the microphones a quarter turn apart, a
little drive entered a little off center. tonewheel-leslie is the
tonewheel organ with a channel-scope Leslie reading its slot, macro 1 on
the speed, and the organ's own strip at a gain of zero, so the cabinet is
the only thing heard: a tap is taken after the strip and before its gain.
Starting values nobody has heard.

LeslieReturn.ThrowsEachBandAtItsOwnRotorsRate sends two sines, one either
side of the crossover, and reads each one's sidebands at the horn's rate
and at the drum's. It is the first test that tells the horn from the drum
through the resolver. TonewheelLeslie's three cases hold that the organ is
silent without the cabinet's tap, that macro 1 moves the level's rate from
the drum's slow speed to its fast one, and that the cabinet is
leslie-return's but for its drive.

Three things the patches turned up:

Program::Init did not reset a slot's strip. tonewheel-leslie is the first
factory patch to author one, and the patch built after it on the same
instrument, as //patches:install builds them, kept slot 0 at a gain of
zero. Bank.EveryBlobIsTheSameBuiltAloneOrAfterTheWholeBank caught it; Init
resets the strips now.

The bank is 65 patches and a project has 64 channels, which
format/project_test.cc's fixture asserted it would never be. The fixture
takes a first patch, and the round trip runs over two projects that hold
the bank between them.

A layer at a gain of zero is silent soloed, which
Exchange.EveryFactoryLayerImportsAndPlaysAsItDidInItsSource refuses. It
holds that the import brought the zero and then compares both sides at
unity.

patchdiff's LESL coverage case and its name test read leslie-return now
that a factory patch holds a Leslie; the name test moves from diff_test to
cli_test, beside the phaser's and the shifter's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
instrument_bench gains the Leslie's rows in the phaser's shape, the
default patch, which never runs the drive stage, and the same patch with
the stage engaged. The ledger takes a summary of what was built, the
decisions the spec did not anticipate, what is open and unheld and the
list of things to hear and see by hand; Task 4's section, with the two
patches' values and measurements, how the organ's dry path is silenced,
the three findings the patches turned up, every injection and the case it
failed; three runs of both benches with the chorus's, the phaser's and
the shifter's rows from the same runs; and the two lanes of the suite
that were run. The sanitizer lanes were not run and the ledger says so.
CLAUDE.md names the Leslie in the dsp/ paragraph and format/leslie.h in
format/'s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AFullScaleSquareClipsAtTheHighBandAndAtTheOutputSum parked the cabinet
where a fresh note leaves it, facing the left microphone. There the left
side reads both bands at one frame, the bands sum to the input, and the
left sum never leaves the sample range: only the right sum clipped. A
left sum that wraps, the right left saturating, failed nothing.

The case now also turns the horn half round in silence and parks it
there by a legato note-on, so the left microphone is the far one and the
left sum clips 1,599 times in the run. The wrap on the left alone fails
it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing held that a legato note-on keeps the quiet count with the lines
it counts for. A legato note-on that reset the count, as a fresh note's
does, failed nothing: every legato case renders after the note-on, and
the first render with anything in the crossover puts the count back.

ALegatoNoteReleasedAtOnceStillRingsOut lets the crossover empty with the
lines still full, takes a legato note-on and a release with no sample
between, and holds that the voice stays until the far microphone has
read what the lines hold. The reset fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sign of the asymmetry was held by DriveModel and by the clip case
that happens to depend on it, and by nothing that reads what an
asymmetry is: the model is a second copy of the stage's ten lines,
written from the same headers by what wrote the stage.

APositiveAsymmetryClipsTheUpperHalfFirst drives a sine onto both rails
in the first cycles of a note, before the blocker has moved the mean,
and holds that a positive asymmetry leaves the lower excursion more than
twice the upper, a negative one the other way, and none leaves them
level. A negated asymmetry fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ALegatoNoteOnThatEngagesTheStageStartsItEmpty runs a driven note on the
fixture's layer before the clean one, so everything a note sets up when
it starts the stage was already there. A legato note-on that left the
scale on the curve's output unset -- at the unity a new layer holds --
failed nothing. That is the path a held channel-scope Leslie takes when
its drive is first turned up.

ALegatoNoteOnEngagesAStageThatHasNeverRun starts a new layer clean,
engages it by a legato note-on, and holds its render to a fresh driven
note's, sample for sample. The unset scale fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The truncation and header-size cases named the cabinet's leaf and the two
rotors' and left the matrix's out. A reader that ignored ReadMatrix's
refusal and went on with the rest failed nothing: the only case that cut
into the matrix leaf cut the wrapper with it, and the wrapper's own walk
refused first.

AHeaderSizePastTheLeafRefuses takes the matrix leaf as its fourth. It is
the wrapper's last child, so its reader is all that meets the lie. The
ignored refusal fails it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
IsActive kept `|| !crossover_.IsQuiet()` after Task 1 showed the term is
dead: a sample that leaves the one-pole's state nonzero wrote a nonzero
word, so the quiet count is at zero whenever the crossover holds
anything. The spec's "Active and gate" already said the crossover needs
no term; the code had one and the comment said it was asked and never
decides. It also hid things: a NoteOff that threw the count away still
reported active through it for one more sample.

The term is gone and the comment says why none is needed, and what the
argument leans on: a gain of no more than a half, which SvfOnePoleGain
keeps. ACrossoverThatHoldsAnythingWroteANonzeroWord holds the argument
over its 100,000 samples, and a count that reads one line only still
fails it. AReleasedVoiceReachesExactZeroAndFrees now also holds, at the
sample each voice first reports inactive, that its crossover is empty;
no injection short of breaking the one-pole reaches that assertion, and
it is there as the statement of what replaced the term.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The blocker took its gain as one power of two, 2^-11, at every rate, so
its corner was a fraction of the rate: 7.46 Hz at 48 kHz and twice that
at 96 kHz, where it took 0.96 dB from a 30 Hz sine against the 0.26 dB
the corner was chosen for. Only 48 kHz had been run. The ledger's "The
blocker" said the choice "keeps that at twice the rate"; by its own
table it does not. Every other field of the Leslie resolves to the same
hertz, seconds and milliseconds at every rate, and the spec's testing
list says so.

Resolved gains `blocker_gain`, the one-pole's gain at the rate, and
resolve/leslie.h forms it in double: G = g / (1 + g) for the corner that
2^-11 makes at 48 kHz, which is derived and written nowhere. At 48 kHz
the resolved gain is the engine's own to the bit, so nothing rendered
there moves; a resolved form built by hand holds that gain until it says
otherwise. NoteOn holds the gain between 2^-16 and 2^-6 and takes it on
a legato note-on with every other field. The floor is the one that
matters: at a gain of none the blocker never lets go of a mean, and a
released voice never frees.

A gain is a multiply where a shift was free, which is the price of
44.1 kHz matching: a shift a rate would have put 44.1 kHz at 48's shift
and its corner 8% under.

Measured, a 30 Hz sine at 0.01 through the stage engaged at no drive,
against the stage off: -0.2610, -0.2612 and -0.2612 dB at 44.1, 48 and
96 kHz. A voice released at the slowest gain frees in 321,787 samples.

Tests: LeslieResolve.TheBlockersCornerIsTheSameHertzAtEachRate,
.TheBlockersGainIsHeldInsideTheEnginesRange and
.TheBlockerTakesTheSameFromALowSineAtEachRate, which renders at the
three rates; LeslieDriveTest.TheBlockersCornerIsTheResolvedFormsGain,
.ALegatoNoteOnTakesTheBlockersGain and
.NoteOnHoldsAHostileBlockerGainInsideItsRange. Nine injections, each
failing at least one: the engine ignoring the resolved gain, NoteOn not
clamping it, the clamp without its floor, the gain taken by a fresh note
only, the resolver giving one gain at every rate, a whole shift a rate,
the gain not held in the engine's range, the tangent in place of
g / (1 + g), and a rate that is not positive taking the fastest.

sizeof(LeslieLayerType) is 936, from 928: the gain is a word of the
layer's own. Still under the slot's largest alternative; VoiceType's pin
did not move.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Task 4 made Init reset every slot's strip, after tonewheel-leslie left
the next patch built on the same instrument with slot 0 at a gain of
zero. Asked whether that fix was complete: it was not. Init reset the
voice's two LFOs and left the channel's two, which are patch data on the
same terms -- a CLFO leaf in the file, a target of their own in the
editor -- so PatchDocument::New kept the last document's channel LFOs,
and a save wrote them. No factory patch authors one, so
Bank.EveryBlobIsTheSameBuiltAloneOrAfterTheWholeBank could not see it,
and no blob moves with the fix.

Init clears them. Instrument.InitResetsTheChannelLfos fails without the
line, and also fails when the voice LFOs' own reset is taken out, which
nothing in this target held either.

The strip reset was held only by the bank's order of building: take
tonewheel-leslie out, or build it last, and nothing fails.
Instrument.InitResetsEverySlotsStrip holds it on its own and fails with
the reset removed.

Everything else Voice::Patch holds, Init already resets: the layers, the
switches, the key ranges, the scopes, the count, the trim, the voice
mode and the glide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header and the spec both said the stage's ceiling is "the curve's
rail times that reciprocal, under full scale". That was measured at an
asymmetry of zero and stated without one. Entered off its center the
curve has further to its further rail, and the branch's own clip case
already asserted a sample over full scale at an asymmetry of -1 without
anything saying the stage could reach one.

Measured here: a held full-scale input at full drive and an asymmetry of
-1 comes out at 1.3286, twice the trim, against 0.7632 at the center.
It is inside a Sample's range and nothing wraps. The header and the spec
say so, and TheStagesCeilingIsTheCurvesRailTimesTheTrim holds the
figure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ledger gains "Review": nine findings and the commit that answers
each, what was read and found sound, the twenty-nine injections re-run
and the twenty-eight made up with what each failed, the tests that hold
less than they read, what //patches:patches_test's BUILD entry asks of
the ASan lane, what is left open, and the suites.

Its summary is brought to the tree where the review changed it: the
crossover's term in IsActive, the blocker's corner, the layer's size,
and who has run the injections. One sentence of "The blocker" that the
table beside it contradicts is marked where it stands.

The spec's status line said everything after Task 2 was proposed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs(leslie): the final lanes, and the decisions taken after listening
Some checks failed
ci / opt (pull_request) Waiting to run
ci / asan (pull_request) Blocked by required conditions
ci / ubsan (pull_request) Blocked by required conditions
ci / tsan (pull_request) Blocked by required conditions
ci / coverage (pull_request) Blocked by required conditions
push / small (push) Has been cancelled
6cc89b57f1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Merge branch 'main' into leslie
Some checks failed
push / small (push) Successful in 36m37s
ci / opt (pull_request) Failing after 44m9s
ci / asan (pull_request) Failing after 1h15m45s
ci / ubsan (pull_request) Failing after 55m38s
ci / tsan (pull_request) Successful in 18m46s
ci / coverage (pull_request) Failing after 56m35s
6d40aedc86
bcox merged commit 12874586a1 into main 2026-10-06 17:28:44 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
bcox/tymbal!169
No description provided.