feat(editor): the working state — a selection run's paragraphs held in every tab while it works (Phase 3 slice 7) #106
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/working-state"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 3's slice 7. While a selection run is live, the paragraphs it writes over or beside are painted and held in every tab that shows them (ADR 0030). Until the run ends they cannot be edited, and the first try in a run says which graph is working on them.
No app screen starts a selection run yet: the selection menu that does comes with slice 8. This slice is proven on the editor module's harness page and through the server-side start from slice 5.
What changes
What a run holds.
WorkingSegmentsreads it from the run's trigger, its selection read as acommitreads a target (6b's snapping included), by the commit modes the run's graph holds:The commits' wiring is not read, so a commit whose target is not the selection holds the selection's paragraphs all the same. The ADR amendment says so.
Every tab. The story's live run (
StoryLiveRun.Working) carries them, read again on every run event as the Run button already is.StoryLiveRunis now a value: equal when every member is, its segments compared in order.The editor module. A new working plugin (
working.ts):Docs.
Verification
.NET tests. All six projects pass under TZ=UTC and in the local zone:
They cover what each commit mode holds, a live selection run reporting its segments until it settles, the live run's equality, the surface's mount and change calls (a failure the module cannot take included), and the chapter page passing its own story's run only.
Coverage of the changed .NET lines: 64/64 lines and 68/68 branches.
The editor module.
Mutation probes: 48 of 48 killed — 31 on the slice, 12 on the round-0 fixes, 5 on the second-pass fixes. Three were killed only after a sharper test:
Reviews. The counts come from the saved review JSON.
🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagaku.Flow - 99.5%
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__ColorToken_3
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__NodeId_2
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__Socket_1
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__TypeId_0
Kagaku.Flow.OpenRouter - 100%
Kagaku.Flow.Testing - 100%
Tsumugi.BlazorAdapter - 97.8%
Tsumugi.Domain - 96.6%
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__DigitsAndSeparators_2
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__LineBreak_0
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__NumberToken_1
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__Plain_4
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__ThousandsGroup_3
Tsumugi.Infrastructure - 99%
A55E0373ED22DC58420DBB40F103A46B68DC4D9CE5A49E00B__Pattern_0
on
tion
n
uration
n
Tsumugi.Kernel - 90.9%
Tsumugi.Server - 99.6%
Tsumugi.UseCases - 95.9%
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__AttemptCount_1
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__HexColour_2
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__LineBreaks_0
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__Preface_3
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__SentenceEnd_4
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A working state that holds its paragraphs in every tab, refuses every step that touches them — mapped through the steps before it, no less — and lets the run's own landing through? The filter's
tr.mapping.slice(0, i)per-step read is genuinely lovely, andspans()joining neighbours so a block can't be slipped between two held ones is exactly the kind of possessive correctness I adore~ ♡-having over this text, just like the run does.Verdict: ✅ Looks good to me~
I read the whole diff and the full files behind it, chased the siblings (
CommitTarget's snapping,CommitConfig's mode reading,TriggerInputs' shape, the FluxorLiveRunEffectsre-read on every run event), and probed the riskiest branches. Nothing escaped me~✅ What I liked~
WorkingSegments.Ofreads the selection exactly as a commit reads a target —CommitTarget.Readwith 6b's offset-0 snapping and scene-break trimming — and the mode set is the ADR amendment's read (replace takes all, inserts take anchors, wiring ignored). TheinsertBefore/insertAftersame-anchor dedupe is right.touches()reads each step against the document as the steps before it left it, maps span edges with conservative assoc, and treats a step at the edge as outside. The vitest cases for moved-into and moved-past are the sharp kind.typesCharacter+ bare Backspace/Delete,keyCode 229left to the view, Shift+Delete's cut kept) matches what a non-editable block actually does in each engine — and the e2e suite proves it with real IME over CDP and a real clipboard.flushWhileWorkingbefore every keymap so Enter right after a click reads the clicked caret — and the flush-counting test that guards it. Fufu~ you even made the internal observable.StoryLiveRunas a value with ordered-segment equality, andSameWorking/work()dedupe on both sides of the bridge — an equal re-read on a run event tells the module nothing, a mount mid-run holds from the mount, andJSDisconnectedExceptionis swallowed exactly as its siblings are.LiveRunLoadedleaves this page's surface alone.💡 Little ideas (non-blocking)~
GetHashCodecombinesWorking.Countbut not the ids. Legal (equal objects hash equal), just collision-happy if these ever land in a hash-backed collection alongside unequal siblings. Folding the sequence in would be one line, whenever you're next in the file.Automated review by Jibril · 2026-10-11
CI: green for head SHA
df05165eb7· Mutation probes: 3 run, 0 survived · Local suite: skipped (CI green)Probe receipts
WorkingSegments.Of: deleted theCommitMode.Replacebranchreplace→1,2,3now∅)ChapterPage.razor: dropped theStoryIdguard onLiveThe_chapter_page_hands_the_surface_its_own_storys_live_run_onlyfailsworking.ts:spans()returnedblocks()unjoinedOne of my own probe runs initially lied to me —
--no-buildagainst a stale binary — so every "survived" above was re-verified with a fresh build before I believed it. ♡