Skip to content

feat(editor): redline ⌥↩ and ⌥⌫ move to the next change, and the arrows loop - #28

Closed
JnBrymn wants to merge 9 commits into
gregce:mainfrom
JnBrymn:feat/redline-accept-advance
Closed

JnBrymn wants to merge 9 commits into
gregce:mainfrom
JnBrymn:feat/redline-accept-advance

Conversation

@JnBrymn

@JnBrymn JnBrymn commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

I modified the red redlining navigation. Now if you push ⌥-Return or ⌥-Delete it automatically navigates to the next edit point. Additionally if you push ⌥-Down or ⌥-Up it "wraps" - if you push up on the top edit point then it goes to the bottom one. If you push down on the bottom edit point it goes to the top one.

Tested locally manually by yours truly.

Accept advances to the next change (the operator's ask of 2026-09-16)

He asked for this in his own words: "I want it to automatically forward to
the next edit so I can do just keep doing option return if I want to keep
approving... right now after I do option return I have to push option down to
get the next edit, that's extra keystrokes." An accept moved the baseline, the
change under the keyboard left the picture with it, and the person was left
standing on the document with nothing current — so the change that followed
was reachable only by a ⌥↓ that restored the place the accept had just taken
away.

THE INDEX IS READ BEFORE THE PRESS AND SPENT AFTER THE REDRAW. An accept
removes exactly the change it names and leaves every other one in order, so
the change that FOLLOWED the accepted one sits at the index the accepted one
stood at once the baseline has moved. The view reads that index off the drawn
wrapper (the same element the press is bound to, read once as an element so
the identity and the place are one reading) and arms it only on a landed
PER-CHANGE accept: a refusal must not move the person, and accept-all leaves
no change to move to. A layout effect on the recompose takes the element at
that index, makes it current and focuses it — the same two acts ⌥↓ performs,
in its own order, so an accepted change and a stepped-to change leave the view
in the same state, chip included. `indexAfterAccept` in ./redline-current
bounds the index, and the end of the document is the end: ⌥↩ on the last
change leaves the keyboard on the scroller and a further ⌥↩ is a no-op rather
than a wrap to the top of prose somebody just approved. The generation is a
dependency beside the picture, because an accept that lands on bytes the
baseline already held leaves the composed string untouched while the
generation still moves; without it the armed index would ride on until some
later recompose moved the person for no reason.

MEASURED IN THE RUNNING APP, ONE Electron on a scratch profile, a scratch
HOME and its own tmux socket, over a repository it builds itself with eight
changes written by a plain /bin/sh: `npm run probe:redlineaccept` reads 15 of
15. After one ⌥↓ and one ⌥↩ the picture drops from 8 to 7, the change that
followed ("bravo") is current, the keyboard is ON it and the chip is drawn;
the SECOND ⌥↩ with no ⌥↓ in between takes it to 6 and lands on "charlie";
⌥↓ then steps to "delta"; accepting forward from the first remaining change
empties the document; the press past the last change draws nothing; and not
one byte of the file moves across the whole run.

THE PARENT COMMIT c1fe5fd, same probe, `ACCEPT_ADVANCE_PARENT=1`, and the
reported defect is what the reading shows: the first accept still drops the
picture to 7 changes, and then NOTHING is current, the keyboard is back on the
scroller, the chip is gone, and the second ⌥↩ with no ⌥↓ accepts nothing — 7
changes in, 7 changes out — which is the extra keystroke. The ⌥↓ that follows
lands on index 0, the change that followed, which is exactly the keystroke he
had to add by hand. Both runs count the operator's own `-L gmux` server before
and after (21 sessions, unmoved) and touch nothing outside GMUX_HARNESS_DIR.

`conformance:redline` gains rule 40, a scan of the shipping view, because the
suite cannot see this: the tree carries no jsdom and no test focuses an
element or reads the state a recompose leaves behind. The scan reads the
accept callback by matching parentheses and refuses an arming outside the
accepted guard, an arming without the per-change clause, an armed index
nothing reads or one read outside a layout effect, and an effect that does not
ask the redrawn picture, does not bound the index, never makes the change
current, never focuses it, or does not clear the index it spent. Nine fixtures
including the shipping shape, eight of which must fail, and all nine behave.
`p239-anchored-controls.test.tsx` gains the arithmetic itself, four arms over
`indexAfterAccept` including the end of the list and the ablation that `at + 1`
would pass over the change that follows.

The keymap's own explanation moves with the behaviour, because it is where the
chord is explained to a person: "Stops marking the change under focus and
moves to the next change, so pressing ⌥↩ again accepts that one. The file is
not touched." The Edit menu is unchanged — the verb is the same verb.

WHAT IS NOT TRUE, and it is deliberate rather than forgotten: the REWIND does
not move on. ⌥⌫ restores a change and the file is written, so its picture
arrives through the watcher rather than in this tick; the same index would
have to wait across an unbounded gap and would move the person on some later
recompute if the write never changed the picture at all. It is recorded beside
the accept in ./RedlineDocument with that reason. There is no wrap at the end
of the document, for the reason `indexAfterAccept` states. And the chip's
buttons are unchanged: they run the same command this chord runs, so they
advance too, and the chip has always been drawn only for the change the
controls belong to.

Gates, all foreground on the committed bytes: typecheck 0 at 1308 production
files with 0 boundary violations and 0 runtime cycles; build 0 with the
contract inventory byte for byte and the Electron helper floor raised 138 to
139 for the new probe; `conformance:redline` every rule with rule 40 added;
`npm test` 14,455 passed and 46 skipped, with two `resolve.test.ts` fork-deadline
tests failing under the loaded parallel run and passing in isolation at both
this tree and the parent c1fe5fd, so they are the runner and not this change.
One line at the end of the running log, where the operator tails it: the ask
in his words, the mechanism, the two app runs (15 of 15 at HEAD and the
defect's own reading at the parent c1fe5fd), the gate that pins the wiring,
and what is deliberately not true — the rewind does not move on, and there is
no wrap at the end of the document.
A press moves on, and the picture loops (the operator's asks of 2026-09-16)

He asked for three things over two sittings, the first after using the accept
this branch already ships: "I want it to automatically forward to the next
edit so I can do just keep doing option return if I want to keep approving...
right now after I do option return I have to push option down to get the next
edit", then "when I press option delete, it should still go to the next
available edit point, not just option return", and then "If I keep going past
the end... I want it to flip over and go to the first edit point at the top of
the document... And in reverse... to the last edit point so that it forms a
loop instead of just hitting the end."

THE ARROWS LOOP, in one line and with the old clamp kept as the ablation:
`stepIndex` answers `(at + delta + count) % count`, so ⌥↓ past the last change
comes round to the first and ⌥↑ before the first comes round to the last. A
document with one change loops onto itself rather than moving; an empty one
still answers null and the arrows do nothing. The chip's own Next and Previous
buttons run the same two commands, so they loop with the chords.

THE REWIND MOVES ON, and the rule it shares with the accept is now one
function rather than two. Both verbs take exactly the change they name out of
the picture — an accept moves the baseline to the inserted bytes, a rewind
writes the baseline's own bytes back over them — and both leave every other
change in order, so the change that followed the pressed one sits at the index
the pressed one sat at. `indexAfterRemoval` answers that index and, at or past
the end, comes round to the first remaining change, so a run that started in
the middle of a document does not strand the changes above it. The view arms
it from a landed per-change accept, and from a rewind only once its write has
landed.

TWO GUARDS, and the rewind needs both. The first is that the person must still
be standing on the change the press acted on; a move made while a rewind's
redraw was in flight is theirs and the armed move is dropped rather than
overriding it. The second is that the picture must have LET THAT CHANGE GO: an
accept removes it in the same tick, while a rewind's picture arrives through
the watcher, and until it does the element at the index is still the pressed
change, so the move waits rather than stepping onto the change it just
rewound. That wait is also what closes the rewind's own recorded limit — its
keyboard used to be dropped when the watcher replaced the wrapper it was on,
and the same layout effect now focuses the change it moved to in that commit.

MEASURED IN THE RUNNING APP, ONE Electron on a scratch profile, a scratch HOME
and its own tmux socket over a repository it builds itself with eight changes
written by a plain /bin/sh: `npm run probe:redlinemoveon` reads 19 of 19. One
⌥↓ marks the first change; ⌥↑ from there comes round to the LAST (index 7 of
8) and ⌥↓ comes back to the first; an accept drops the picture to 7, moves not
one byte of the file, and leaves "bravo" current with the keyboard on it and
the chip drawn; a SECOND ⌥↩ with no ⌥↓ takes it to 6 and lands on "charlie";
⌥⌫ writes the file (digest moved) and leaves "delta" current with the keyboard
on it; the arrows still loop after a press; accepting forward empties the
document; no later accept moved a byte; and a ⌥↩ past the last change, and the
arrows on an empty redline, draw nothing.

THE PARENT f6108e9, the build he reported against, same probe,
`ACCEPT_ADVANCE_PARENT=1`, and every claim this round makes is a reading it
cannot produce: ⌥↑ at the first change stays on index 0 and nine ⌥↓ presses
stop on index 7 (HEAD reads 7 and 1); the first accept leaves NO change
marked, the keyboard on the scroller and no chip; the second ⌥↩ with no ⌥↓
accepts NOTHING (7 changes in, 7 out); and the rewind writes the file and
leaves nothing marked. The run also corrected one of this probe's own arms:
with a pointer click before the rewind the old build's caret restore can land
inside the next change and mark it, so the parent arm is driven by the chords
the operator actually uses and the reading it grades is "nothing marked"
rather than "nothing focused" — the difference is recorded in the probe.

`conformance:redline` rule 18's ends arm becomes the loop, with the shipped
clamp as its ablation, over the same twelve arms and twelve ablations; rule 18a
now names `pressedElement`, which is the read the accept and the rewind share
and the one that keeps the focused wrapper and the caret fallback; and rule 40
is rewritten for both verbs — the accept arming inside its accepted guard
behind the per-change clause, the rewind arming after its write and never for
an undo, and the effect carrying both guards — over thirteen fixtures of which
twelve must fail. `p239-anchored-controls.test.tsx` gains the loop's five
positions and the wrap at both ends of `indexAfterRemoval`, and the keymap's
own explanations of the three chords move with the behaviour.

WHAT IS NOT TRUE. The loop is a loop WITHIN the picture: an empty redline has
nothing to come round to and every chord is a no-op. A rewind's move arrives
with its redraw rather than with the press, because the picture it changes
arrives through the watcher, so the chip sits on the change it is rewinding
until the write lands; and a move the person makes inside that window drops
the armed move. Undo arms nothing, deliberately: it puts a change back, and
the next place to be is where the person already is. The probe is renamed
`probe:redlinemoveon` and the old `probe:redlineaccept` name goes with it.

Gates, all foreground on the committed bytes: typecheck 0 at 1308 production
files with 0 boundary violations and 0 runtime cycles; build 0 with the
contract inventory byte for byte and the Electron helper floor at 139;
`conformance:redline` every rule, with rule 18's 12 of 12 ablations and rule
40's 13 of 13 fixtures; the probe's own `--self-test` 11 of 11 graders; and
`npm test` 14,455 passed with the two `resolve.test.ts` fork-deadline tests
failing under the loaded run and passing in isolation at both this tree and
the parent, which is the runner and not this change.
The running log's own entry for this round, appended last, and the earlier
entry's two superseded clauses corrected in place above it: the rewind does
not move on at f6108e9, and there is no wrap at the end of the document, both
of which this round changes. The CHANGELOG's Unreleased item now covers both
verbs and the loop.
…r notices

A rewind redraws at once (the operator's report of 2026-09-16)

"the only problem now is that when I option delete instead of option return,
the delete takes a little bit of time, and I don't know why. Option return is
instantaneous, which is what I would expect option delete to be."

WHY IT WAS SLOW, MEASURED RATHER THAN GUESSED. An accept moves the baseline
in memory, so its redraw is React's own next commit; a rewind writes the file
through the guarded door and then WAITED FOR THE FILE WATCHER to notice the
change and re-read a file the view had just written. `probe:redlinemoveon`
gained a stopwatch (arm H8b) started at the keydown and polled until the
picture dropped: at the commit before this one it read 35 ms for the accept
and 1,139 ms for the rewind. After this commit the same arm reads 6 ms and
23 ms, and the 17 ms that is left is the guarded write itself — the IPC round
trip to main, the compare-and-swap and the rename.

THE BYTES ARE ALREADY KNOWN, SO THEY ARE ADOPTED. `applyRewind` now returns
what it wrote (`contents`) beside what it read (`was`); `pressRedline` carries
both through; and the view hands them to the tab the moment the write lands.
`tab-io`'s `adoptWritten` patches `savedContents` and replaces the working
model, which is what makes the redline recompose in that tick.

THE MODEL HALF IS NOT OPTIONAL, and it is the reason this is not a one line
patch: a tab whose File view has ever mounted (or whose redline has been typed
into) keeps a Monaco working model, and with that model left holding the old
text the next ⌘S would write the old text back over the bytes this door just
wrote, with `savedContents` as its precondition and therefore nothing to
refuse it. `resetWorkingModel` moves it with the bytes it names.

TWO REFUSALS, and they are the difference between "the file holds these bytes"
and "the file held these bytes when the press was made". A tab that has become
DIRTY has a buffer newer than the plan — a keystroke can land inside the
write's own round trip, which is precisely the window this opens — and a tab
whose saved contents MOVED has a save, a watcher tick or a read of its own to
believe. Either way the watcher is the honest reader and the adoption does
nothing; the move-on then waits for the watcher exactly as it did before,
which is the graceful path rather than the loss.

AND THE LAST 150 ms WAS SOMEWHERE ELSE. `useLiveTabText` returned its debounced
snapshot of the model, so even after the adoption a tab WITH a model would
draw the old text until the debounce expired. The debounce is a re-render
throttle, not a claim about the text: the hook now reads the model at the call
and keeps the state as the trigger, so a render caused by anything else — a
store patch, a parent's state — draws what the model holds now. The diff and
the preview read the same hook and get the same fresher answer.

PINNED THREE WAYS, because a later round can undo this with one deleted line.
`npm run conformance:redline` rule 40 now refuses a landed write that the tab
does not adopt, over fourteen planted shapes of which thirteen must fail.
`src/renderer/editor/__tests__/adopt-written.test.ts` pins the action itself:
one patch carrying `savedContents` and nothing else, the model moving with it,
and NEITHER moving for a dirty tab, for a tab whose saved contents are not
`was`, or for a tab that is gone. And the app run's stopwatch holds the two
verbs against each other — the rewind must redraw within 500 ms of the accept,
which is what goes red at the commit before this one (1,139 against 35).

Gates, all foreground on the committed bytes: typecheck 0 at 1308 production
files with 0 boundary violations and 0 runtime cycles; build 0 with the
contract inventory byte for byte and the Electron helper floor at 139;
`conformance:redline` every rule with rule 40's 14 of 14 fixtures;
`conformance:redline-write` 30 readings and 17 of 17 ablations red, which is
the door this now reads its own bytes back from, unchanged;
`npm run probe:redlinemoveon` 19 of 19 at 6 ms and 23 ms; and `npm test` 14,459
passed with the two `resolve.test.ts` fork-deadline tests failing under the
loaded run and passing in isolation at both this tree and the parent, which is
the runner and not this change.

WHAT IS NOT TRUE: the two verbs are not identical, because one of them writes a
file. 23 ms against 6 ms is the guarded write, and a machine under load will
stretch both. Nothing else waits, and no byte of the redraw depends on the
watcher any more.
The running log's own entry for the fix, appended last, and the move-on
entry's clause about the rewind's move arriving with its redraw corrected in
place above it, with the 1,139 ms against 35 ms pair it was measured with.
The CHANGELOG gains the Fixed item for the same thing.
@gregce

gregce commented Sep 17, 2026

Copy link
Copy Markdown
Owner

I will have my build workflow be the final judge

Phase 282: the press that moves on

Main has moved nine commits since this branch was cut at c1fe5fd, among
them Phase 277's save pipeline in the same tab-io.ts and store.ts this
branch edits, so the fixes are built on it rather than beside it.
CHANGELOG.md keeps one Unreleased section: this branch's Changed item,
main's Fixed list, and this branch's rewind item appended to it.
docs/BACKLOG.md takes main's file, which now holds the Phase 282 entry;
this branch's three running-log lines are superseded by that entry and
by the line that lands with the phase.
…g stays whole

Phase 282: the press that moves on

A four-lens review of this branch merged onto main found one blocking
defect and six more, each reproduced by its reviewer and then again by an
independent skeptic using a different method. This is the fix round for
all of them, built to build/p282/SPEC.md.

BLOCKING, and measured in the app. live-text.ts read the working model at
render, and the redline's typing path writes that model after an await, so
every keystroke's render read a model one keystroke behind, the typing
effect took it for an outside write, and the characters came out
scrambled; a save then wrote that to disk. `npm run probe:p237` on this
branch failed five checks ("rely\n lathro" for a word typed and Enter) and
passes with the line put back to what main has. The line bought nothing:
the adoption and the typing hook's own model listener already redraw at
once, and probe:redlinemoveon still reads the rewind at 25 ms without it.

THE MOVE CARRIED AN INDEX, so an agent's write landing above the pressed
change sent the next press onto a change the person had kept, and a redraw
that merged neighbours did the same with no outside write at all. A press
now records the FOLLOWER's identity and finds it after the redraw, shifted
by the accepted change's own length when the follower came after it, with
the index only as the fallback. It waits on off, del AND ins, so an agent's
new change at the same span no longer parks the move.

ONE PRESS AT A TIME. A rewind holds its change from the press until its
result is handled. Inside that window a rewind of the same change and every
accept on the tab are refused with a sentence, because an accept moves the
baseline under the rewind and a per-change accept has no undo. A rewind of
a different change, undo and the arrows still go ahead. A held key repeats
only the two arrows: a repeated keydown never writes and never accepts.

THE REWIND KEEPS THE KEYBOARD. When it writes and the keyboard is inside a
change wrapper, the host takes focus before the adoption, so rewinding the
only change leaves ⌥⇧⌫ working without a click.

TYPING IS VISIBLE BEFORE ITS AWAIT. The redline's typing path marks the tab
dirty synchronously, builds the model from the tab's saved contents read
after the chunk load, and never applies a text computed from a picture the
view has since replaced. Before this, a rewind landing inside the first
chunk load of a session was adopted over a keystroke in transit, and the
next ⌘S or auto save wrote the pre-rewind text back with no question.

REFRESHREPO DROPS A READ WHOSE BASELINE MOVED. A watcher read that opened
the file before the rewind's rename and answered after the adoption rolled
the tab back to the pre-rewind text; 37 of 500 interleavings over the real
main handlers, and 0 of 500 without the adoption. It now records the
baseline before its read, beside Phase 277's clean-tab and model-identity
checks.

The gates carry all of it. conformance:save gains rules 25, 26 and 27:
adoptWritten reads the live tab and refuses a dirty one and a moved
baseline before it patches or replaces the buffer; refreshRepo's new
clause; and the typing path's synchronous dirty mark. ablation:p268 goes
from 18 arms to 27, each red on the rule that owns it. conformance:redline
rule 40 is rewritten to read what this round built, with 11 ablations of
the shipping source, made on strings in memory with the three files'
sha256 compared in a finally; at this branch's head it reports 26 findings.
HELPER_USER_FLOOR rises to 140, which is the count two branches each raised
to 139 for a different probe. CLAUDE.md's conformance:redline row gains
live-text.ts, because rule 40's live-text clause is the one that would
notice the blocking defect coming back and nothing else would trigger it.

probe:redlinemoveon gains five arms inside the one Electron it already
starts: an outside write above the current change the moment before ⌥⌫, a
rewind of the only change followed by ⌥⇧⌫, ⌥⌫ and ⌥↩ back to back, a held
⌥⌫ with six auto-repeats, and a typing burst at 30 ms a key followed by
⌘S. It reads 25 of 25 with the rewind redrawing in 25 ms.

Credit. The requests this branch quotes are its author's, John Berryman's,
and every place that called them the operator's is corrected in the log,
the commit bodies to come, the source comments and the probe.

Gates and runs, all in one tree: typecheck, build, 926 files and 14,648
tests, smoke:t1, conformance:save, conformance:redline,
conformance:redline-write, ablation:p268 27 of 27, gate:electron 140 of
140, gate:checks, gate:background, probe:p237, probe:p277 and
probe:redlinemoveon.

One reading is not explained. probe:p268's arm G, which holds that a file
outside every project is never written by the auto-save timer, failed once
on this branch, immediately after two other probes with the load average
near 20: the file was written and the tab read clean. It has not
reproduced in five further runs here, in one run at this branch's head, in
one on main, or with this branch and main running the probe side by side
under the same load. The skip list itself is untouched by this round. It is
recorded here rather than explained away, and queued as its own entry.
Phase 282: the press that moves on

The verification round found three defects in this phase's own fixes, each
reproduced by its verifier and then again by the fix round using a
different rig. All three are fixed here.

A HOLD COULD FREEZE FOR THE LIFE OF THE MOUNT. When the tab trailed disk —
the ordinary state of a file an agent is writing — a rewind's adoption
refused, and the hold landed waiting for a redraw. The person saw nothing
happen, so they typed; this phase's own rule marks the tab dirty at once,
refreshRepo skips a dirty tab by rule, so the bytes the hold waits on could
never move and the change stayed drawn. Every accept on that tab then
answered "A change in <name> is still being rewound" although nothing was.
A landed hold is now released as soon as the tab is dirty: a rewind is
already refused on a dirty tab, so a hold buys nothing there, and that is
exactly the state where the redraw it waits for never comes. A hold whose
write is still in the air is deliberately NOT released, because that window
is the one the hold exists for.

TWO READS OF ONE FILE COULD BE IN THE AIR AT ONCE, and the baseline clause
this phase added then dropped the NEWER one and left the tab on the older
bytes with nothing scheduled to read again — the editor silently stopped
following an agent's edits until the next file event in that repo. The
clause is right about the fact it names; the wrong part was the
concurrency. refreshRepo is now serialized per project: one walk at a time,
at most one more queued, the walk itself unchanged byte for byte so the
gate still reads it by name. Proved over real files with a descriptor held
open across a rename, which is a shape the phase's own rig could not drive.

THE LANDING FALLBACK WAS REACHED BY AN ORDINARY SHAPE. A whole-line
deletion re-cut by the redraw put the follower back at the offset the
accept had just vacated, and with an agent's line arriving in the same
redraw the person landed on the AGENT'S new change. The follower is now
matched by baseline offset alone, which names at most one change in a drawn
picture.

The verifiers also cleared things this round need not touch: the landing
agreed with an offset-free oracle on 35 of 35 agent-write cases; the
auto-save skip list answered correctly over 20,000 generated tabs with
repoPath, the roots, the remote flag and the read-only answer each moved
underneath it, and tab-io carries a second guard besides; the synchronous
dirty mark never marks a tab that has no edit; and a hold in the air is not
released by a draw.

conformance:redline rule 40 gains the release effect's dirty dependency,
with a scanner fixture and an ablation of the shipping source.
build/p282/SPEC.md gains a corrections section recording each ruling that
moved and the test that is red without it.

Gates and runs after the fix: typecheck, build, 927 files and 14,655 tests,
smoke:t1, conformance:save, conformance:redline, conformance:redline-write,
ablation:p268 27 of 27, gate:electron 140 of 140, probe:p237, probe:p268,
probe:p277 and probe:redlinemoveon 25 of 25.
@gregce

gregce commented Sep 17, 2026

Copy link
Copy Markdown
Owner

Landed on main, thank you John — this is a good feature and I use it constantly now.

It went in as three commits: your feature under your name (d8debd9), then two rounds of fixes from the build workflow (3ea54ad, 117e7a8). The full write-up is the Phase 282 entry in docs/BACKLOG.md.

What the review turned up, so you know what changed under your branch:

  • The live-text.ts read of the working model at render scrambled typing in the Redline view, and a save then wrote the scrambled text to the file. npm run probe:p237 fails five checks with that line in and passes with it out. The adoption alone already redraws at once, so the line wasn't buying the speed-up — the rewind still measures 25 ms without it.
  • The move carried the pressed change's index. If an agent wrote to the file around the same moment, the next ⌥⌫ landed on a change the person had deliberately kept and rewrote it. It now carries the following change's identity, with the index only as a fallback.
  • A second chord inside the rewind's write acted on the change being rewound; that's now refused with a sentence. A held key repeats only the arrows.
  • Rewinding the only change dropped the keyboard, so ⌥⇧⌫ did nothing until you clicked.

Two of the fixes then needed fixing themselves, which the verifiers caught: a hold that one keystroke could freeze, and a watcher guard that made the editor stop following an agent's edits.

The gates carry all of it now: conformance:save rules 25 to 27c, ablation:p268 at 27 arms, conformance:redline rule 40 rewritten with 11 ablations, and five new arms in probe:redlinemoveon.

Closing this in favour of the landed commits.

@gregce gregce closed this Sep 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants