fix(manuscript): hardening — counted answers and deltas, long chapters measured, Alt+Shift+P provenance #52

Merged
bjoern merged 8 commits from feat/manuscript-hardening into main 2026-09-26 16:47:29 +02:00
Member

The manuscript track's hardening: three things ADR 0030 left open, each with its proof.

1. Answers and deltas are counted

The host re-reads the chapter only once the answer before it has been returned, but the circuit can still deliver that delta first. When the delta was about the paragraph whose save was in flight, the module left the remote text off the screen (the paragraph was the event's own), and the older answer then overwrote the newer stamp. The screen kept stale text with no save pending, and the next split of that paragraph was refused.

  • Host. Every answer, refusal and delta carries the count of the host's store reads (At), taken inside the FIFO queue where the read happens.
  • Module:
    • Per segment, it keeps the count of the newest word it has — text or removal — and drops an older one.
    • An answer's order carries its count, and a delta's older order drops out against it; a paragraph an older delta brings is placed by the newest order heard. Deltas come in the order the host read them, so their own orders need no count.
    • A delta read before an adopted chapter drops out whole.
    • A delta applied while one of the module's events is on its way applies once more after that event's answer, so one the host read later shows as if it had come after it. The caret moves only on the first pass.
    • A refused event's chapter is compared with what the module held before any delta that overtook it, so typing under the refusal survives exactly when it would have in the host's order.
  • A composition holding a refusal's chapter (older than this branch): what the writer made meanwhile no longer disappears when the chapter finally applies. Blocks made since or told of by an answer stay, as does typing since in a paragraph the chapter still has; a paragraph the chapter lacks goes.

2. Long chapters, measured

This is the ADR's open risk, measured on a generated 400-paragraph chapter (210 KB) in Chromium, Firefox and WebKit, with the suite's other workers running beside them. Two hot spots went:

  • A remote move of the last paragraph to the top took 67 ms in Chromium and 580 ms in Firefox. The paragraph view's update() accepted any paragraph, so ProseMirror handed each view its neighbour's content and redrew all 400. It now takes only its own segment, and the move takes 2 ms.
  • A rewritten paragraph went in as one step per token hunk, and each step rebuilt the 400-block document: a hundred-paragraph adoption took 143 ms in Firefox. It now goes in as one step, with the hunks still carrying the caret, and takes under 100 ms.

Script time per operation:

range across engines
keystroke ≤ 2 ms
Enter / Backspace 3–13 ms
bold over the whole chapter 35–130 ms
fifty paragraphs rewritten remotely 8–66 ms
chapter adopted with a hundred rewritten 20–100 ms

The browser suite keeps both. A mutation observer shows a move touches no paragraph but the moved one (all 400 without the fix), and every figure above has a budget several times its measured value.

3. Alt+Shift+P tells the caret's paragraph's provenance

The gutter is hidden from assistive technology and shows its title only on hover. Alt+Shift+P writes the caret's paragraph's gutter title into a polite live region after the surface, outside the editable text, for example Written by: Run · writer · model — edited, or A scene break when one is selected.

  • It shows at the lines' ragged end at the bottom of the view for five seconds, lets clicks through, and takes no room while empty.
  • Asked twice, the words arrive as a new text node and are read again.
  • The key resolves through ProseMirror's keyCode fallback, so it works when macOS turns Option+Shift+P into ∏, and it never swallows a character typed with Windows AltGr.
  • The click through to the inspector stays with M4.

Proof

  • Module: typecheck; vitest 207 tests.
    • race.test.ts has 24 orderings of answers, refusals and deltas, compositions included, with typing under a refusal checked against its in-order twin.
    • Two properties:
      • model.test.ts: a pause's save stays in flight, and the host answers at once. On main it shrinks the original race to type, pause, remote edit.
      • host.test.ts: the session against a stand-in for ManuscriptSurface (its queue, its told mirror, a re-read after every change). It runs with another tab moving, adding, removing and changing paragraphs, input methods composing, and answers delivered after deltas read later. It found the composition bug above and a follow-on to my first fix for it. On the final code it soaked 15,000 cases clean.
    • Browser suite (Playwright image): 110 passed, 7 engine skips as before, across Chromium, Firefox and WebKit; Chromium and Firefox rerun after round 1 (74 passed, 4 skips).
  • .NET: all six test projects. The bUnit test pins the host's counts across a save, a delta, a refusal, a malformed event and a split.
  • Seeded app, Chromium and Firefox:
    • M2b's pass: 27/27.
    • M3's pass: 9/9.
    • A new pass: 11/11. It checks that the counts reach the module over the real circuit as at, rising, on answers and a second tab's delta, and that Alt+Shift+P's label sits inside the viewport of the real shell.
  • Mutation probes: every guard of the ordering logic, the host's counters, the view's id check and the live region's claims fail a test when removed.
    • Kept as equivalent mutants: adopt resets heard along with stored, and sending bounds what is replayed.
    • The host property checks that screen and server agree. Losing typing under a reordering keeps them agreeing, so the twin tests pin that.

Review round 0 (before opening)

A four-way review with adversarial verification found and reproduced four defects, all fixed with a test each:

  • a replayed undo delta moved the caret to the chapter's end;
  • typing was lost when a delta overtook a refusal (found by two reviewers);
  • a composition-held delta's paragraph was placed at the chapter's end, a regression from main;
  • the latency test measured cheaper work than it claimed.

It also noted that the badge blocked clicks, and that no test covered a held delta surviving an adoption; both are fixed.

Review round 1

Jibril's two reviews each listed survivors as equivalent mutants. Two of them were not, and one was:

  • The !found guard of placeAfterRemoval had become unreachable from the session once replays stopped carrying the caret. It is reconcile's own contract that a removal of blocks already gone has no end, so a unit test of reconcile now pins it.
  • A delta's order advancing serverOrder is not equivalent. serverOrder is the base of the resync after a failed call. A stale base gets the resync refused, and the writer's split is lost to the adopted chapter. A test now pins it: another tab's move, then a failed split, and the split stands.
  • A delta's order advancing orderAt was equivalent. Deltas come in the order the host read them, so only an answer's order needs a count; the line is gone.

Notes for review

  • ADR 0030 is amended in this PR:
    • the Status line;
    • "Counted, not trusted to arrive in order";
    • the refusal's adoption under a composition;
    • the paragraph as one step;
    • the gutter's keyboard path;
    • the race and long-chapter risks.
  • Manual matrix: row 13 (Orca) now includes Alt+Shift+P. It is not run.

🤖 Generated with Claude Code

The manuscript track's hardening: three things ADR 0030 left open, each with its proof. ## 1. Answers and deltas are counted The host re-reads the chapter only once the answer before it has been returned, but the circuit can still deliver that delta first. When the delta was about the paragraph whose save was in flight, the module left the remote text off the screen (the paragraph was the event's own), and the older answer then overwrote the newer stamp. The screen kept stale text with no save pending, and the next split of that paragraph was refused. - **Host.** Every answer, refusal and delta carries the count of the host's store reads (`At`), taken inside the FIFO queue where the read happens. - **Module:** - Per segment, it keeps the count of the newest word it has — text or removal — and drops an older one. - An answer's order carries its count, and a delta's older order drops out against it; a paragraph an older delta brings is placed by the newest order heard. Deltas come in the order the host read them, so their own orders need no count. - A delta read before an adopted chapter drops out whole. - A delta applied while one of the module's events is on its way applies once more after that event's answer, so one the host read later shows as if it had come after it. The caret moves only on the first pass. - A refused event's chapter is compared with what the module held *before* any delta that overtook it, so typing under the refusal survives exactly when it would have in the host's order. - **A composition holding a refusal's chapter** (older than this branch): what the writer made meanwhile no longer disappears when the chapter finally applies. Blocks made since or told of by an answer stay, as does typing since in a paragraph the chapter still has; a paragraph the chapter lacks goes. ## 2. Long chapters, measured This is the ADR's open risk, measured on a generated 400-paragraph chapter (210 KB) in Chromium, Firefox and WebKit, with the suite's other workers running beside them. Two hot spots went: - **A remote move** of the last paragraph to the top took 67 ms in Chromium and **580 ms in Firefox**. The paragraph view's `update()` accepted any paragraph, so ProseMirror handed each view its neighbour's content and redrew all 400. It now takes only its own segment, and the move takes 2 ms. - **A rewritten paragraph** went in as one step per token hunk, and each step rebuilt the 400-block document: a hundred-paragraph adoption took 143 ms in Firefox. It now goes in as one step, with the hunks still carrying the caret, and takes under 100 ms. Script time per operation: | | range across engines | |---|---| | keystroke | ≤ 2 ms | | Enter / Backspace | 3–13 ms | | bold over the whole chapter | 35–130 ms | | fifty paragraphs rewritten remotely | 8–66 ms | | chapter adopted with a hundred rewritten | 20–100 ms | The browser suite keeps both. A mutation observer shows a move touches no paragraph but the moved one (all 400 without the fix), and every figure above has a budget several times its measured value. ## 3. Alt+Shift+P tells the caret's paragraph's provenance The gutter is hidden from assistive technology and shows its title only on hover. **Alt+Shift+P** writes the caret's paragraph's gutter title into a polite live region after the surface, outside the editable text, for example *Written by: Run · writer · model — edited*, or *A scene break* when one is selected. - It shows at the lines' ragged end at the bottom of the view for five seconds, lets clicks through, and takes no room while empty. - Asked twice, the words arrive as a new text node and are read again. - The key resolves through ProseMirror's keyCode fallback, so it works when macOS turns Option+Shift+P into `∏`, and it never swallows a character typed with Windows AltGr. - The click through to the inspector stays with M4. ## Proof - **Module:** typecheck; vitest 207 tests. - `race.test.ts` has 24 orderings of answers, refusals and deltas, compositions included, with typing under a refusal checked against its in-order twin. - Two properties: - `model.test.ts`: a pause's save stays in flight, and the host answers at once. On `main` it shrinks the original race to *type, pause, remote edit*. - **`host.test.ts`**: the session against a stand-in for `ManuscriptSurface` (its queue, its `told` mirror, a re-read after every change). It runs with another tab moving, adding, removing and changing paragraphs, input methods composing, and answers delivered after deltas read later. It found the composition bug above and a follow-on to my first fix for it. On the final code it soaked 15,000 cases clean. - Browser suite (Playwright image): 110 passed, 7 engine skips as before, across Chromium, Firefox and WebKit; Chromium and Firefox rerun after round 1 (74 passed, 4 skips). - **.NET:** all six test projects. The bUnit test pins the host's counts across a save, a delta, a refusal, a malformed event and a split. - **Seeded app, Chromium and Firefox:** - M2b's pass: 27/27. - M3's pass: 9/9. - A new pass: 11/11. It checks that the counts reach the module over the real circuit as `at`, rising, on answers and a second tab's delta, and that Alt+Shift+P's label sits inside the viewport of the real shell. - **Mutation probes:** every guard of the ordering logic, the host's counters, the view's id check and the live region's claims fail a test when removed. - Kept as equivalent mutants: `adopt` resets `heard` along with `stored`, and `sending` bounds what is replayed. - The host property checks that screen and server *agree*. Losing typing under a reordering keeps them agreeing, so the twin tests pin that. ## Review round 0 (before opening) A four-way review with adversarial verification found and reproduced four defects, all fixed with a test each: - a replayed undo delta moved the caret to the chapter's end; - typing was lost when a delta overtook a refusal (found by two reviewers); - a composition-held delta's paragraph was placed at the chapter's end, a regression from `main`; - the latency test measured cheaper work than it claimed. It also noted that the badge blocked clicks, and that no test covered a held delta surviving an adoption; both are fixed. ## Review round 1 Jibril's two reviews each listed survivors as equivalent mutants. Two of them were not, and one was: - **The `!found` guard of `placeAfterRemoval`** had become unreachable from the session once replays stopped carrying the caret. It is `reconcile`'s own contract that a removal of blocks already gone has no end, so a unit test of `reconcile` now pins it. - **A delta's order advancing `serverOrder`** is not equivalent. `serverOrder` is the base of the resync after a failed call. A stale base gets the resync refused, and the writer's split is lost to the adopted chapter. A test now pins it: another tab's move, then a failed split, and the split stands. - **A delta's order advancing `orderAt`** was equivalent. Deltas come in the order the host read them, so only an answer's order needs a count; the line is gone. ## Notes for review - **ADR 0030** is amended in this PR: - the Status line; - "Counted, not trusted to arrive in order"; - the refusal's adoption under a composition; - the paragraph as one step; - the gutter's keyboard path; - the race and long-chapter risks. - **Manual matrix:** row 13 (Orca) now includes Alt+Shift+P. It is not run. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The host re-reads the chapter only once the answer before it has been returned, yet the circuit can
still deliver that delta first. The module then left the remote text off the screen (its paragraph was
the event's own) and the older answer overwrote the newer stamp, so the next split was refused.

- The host counts its reads and stamps every answer, refusal and delta with the count (`At`).
- The module keeps, per segment, the count of the newest word it has of it — text or removal — and
  drops an older one; an order carries its count, and a delta read before an adopted chapter drops out.
- A delta applied while an event is on its way applies once more after that event's answer, so one the
  host read later shows as if it had come after it — over an answer, a split's order, a refusal's chapter.
- The random-editing property now lets a pause's save stay in flight and lets the host answer at once,
  so a delta overtakes the answer; it shrinks the old race to type, pause, remote edit.
- ADR 0030 amended.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Measured on a generated 400-paragraph chapter (210 KB) in Chromium, Firefox and WebKit, as ADR 0030's
open risk asked. Everything stayed within a frame but one: a remote move of the last paragraph to the
top took 67 ms in Chromium and 580 ms in Firefox. The paragraph view's update() took any paragraph, so
ProseMirror handed each view its neighbour's content and redrew all 400. It takes only its own
segment now, and the move takes 2 ms.

- Browser suite: a move across the long chapter touches no paragraph but the moved one (a mutation
  observer; all 400 without the fix), and the typing, split, merge and remote figures stay within
  budgets about ten times what the three engines measure.
- ADR 0030: the risk records the figures.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The gutter is hidden from assistive technology and shows its title only on hover; ADR 0030 asks for
the same information from the keyboard. Alt+Shift+P writes the caret's paragraph's gutter title —
"Written by: Run · writer · model — edited", "A scene break" for a selected one — into a polite live
region after the surface, outside the editable text. It shows at the bottom of the view for five
seconds and takes no room while empty; asked twice, the words arrive as a new text node and are read
again. The click through to the inspector stays with M4.

- vitest: the words for the caret's, the head's, a scene break's and a select-all's paragraph.
- Browser suite: the region's roles and place, nothing typed, read again, gone after a while.
- ADR 0030, the manual matrix's screen-reader row, the plan's M4 and the workspace story say so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
fix(manuscript): review round 0 — typing survives an overtaken refusal as in order, a held delta's paragraph is placed, a replay moves no caret
Some checks failed
CI / test (pull_request) Has been cancelled
CI / editor-browsers (pull_request) Has been cancelled
CI / build (pull_request) Has been cancelled
72163f5e84
The review's findings, each reproduced first:
- A refused event's chapter is compared with what the session held before any delta that overtook it,
  so typing under the refusal survives exactly when it would have in the host's order (it was lost).
  The kept typing is busy before the re-heard deltas apply.
- A paragraph an older, composition-held delta brings is placed by the newest order heard instead of
  at the chapter's end (a regression from main).
- A delta applied once more moves no caret, and a removal of blocks already gone has no end (the caret
  jumped to the chapter's end).
- The Alt+Shift+P label sits at the lines' ragged end and lets clicks through.

A new property runs the session against a stand-in for the host — its queue, its mirror, a re-read
after every change — with another tab moving, adding, removing and changing paragraphs, compositions,
and answers delivered after the deltas read later. It found two more, one older than this branch:
- A refusal's chapter a composition held removed the paragraphs the writer made meanwhile; it now
  keeps what was made or told of since, and typing since, while a paragraph the chapter lacks goes.

The long-chapter test now times only the writer's own transactions, Enter and Backspace apart, real
rewrites in every round, an adoption that changes a hundred paragraphs, and bold over the chapter; a
rewritten paragraph goes in as one step (a step per hunk took a hundred-paragraph adoption to 143 ms
in Firefox; now under 100). ADR 0030 says so.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
docs: the manuscript hardening's PR is #52
All checks were successful
CI / build (pull_request) Successful in 40s
CI / editor-browsers (pull_request) Successful in 55s
CI / test (pull_request) Successful in 1m31s
adadfa65e2
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

🔄 Auto-updating coverage report — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip.

Commit: afb4c53 · Generated: 2026-09-26 14:41:21 UTC · Revision: #2

Summary

Summary
Generated on: 09/26/2026 - 14:41:21
Coverage date: 09/26/2026 - 14:40:53 - 09/26/2026 - 14:41:17
Parser: MultiReport (6x Cobertura)
Assemblies: 9
Classes: 494
Files: 447
Line coverage: 98% (15216 of 15526)
Covered lines: 15216
Uncovered lines: 310
Coverable lines: 15526
Total lines: 33413
Branch coverage: 94.1% (5937 of 6308)
Covered branches: 5937
Total branches: 6308
Method coverage: Feature is only available for sponsors

Coverage

Kagaku.Flow - 99.7%
Name Line Branch
Kagaku.Flow 99.7% 99.2%
Kagaku.Flow.Budgeting.BudgetRequest 100%
Kagaku.Flow.Budgeting.ConsumerBudget 100%
Kagaku.Flow.Execution.NodeExecution 100% 100%
Kagaku.Flow.Execution.NodeOutcome 100% 100%
Kagaku.Flow.Execution.TransientFailureException 100%
Kagaku.Flow.Execution.Upstream 100%
Kagaku.Flow.Extensions.ServiceCollectionExtensions 100%
Kagaku.Flow.FlowJson 100%
Kagaku.Flow.Graphs.GraphDefinition 100%
Kagaku.Flow.Graphs.GraphDocument 100% 100%
Kagaku.Flow.Graphs.GraphEdge 100%
Kagaku.Flow.Graphs.GraphIndex 100% 100%
Kagaku.Flow.Graphs.GraphLoadError 100%
Kagaku.Flow.Graphs.GraphLoadResult 100%
Kagaku.Flow.Graphs.GraphNode 100%
Kagaku.Flow.Graphs.GraphPosition 100%
Kagaku.Flow.Graphs.GraphReader 100% 100%
Kagaku.Flow.Graphs.GraphSchema 100% 100%
Kagaku.Flow.Graphs.GraphShapeException 100%
Kagaku.Flow.Graphs.GraphWriter 100% 100%
Kagaku.Flow.Graphs.SocketRef 100%
Kagaku.Flow.Graphs.WireText 100% 100%
Kagaku.Flow.Nodes.CanvasDescriptorWriter 100% 100%
Kagaku.Flow.Nodes.ConfigProblem 100%
Kagaku.Flow.Nodes.Names 100%
Kagaku.Flow.Nodes.NodeDescriptor 100% 100%
Kagaku.Flow.Nodes.NodeRegistry 100% 100%
Kagaku.Flow.Nodes.NodeSockets 100% 100%
Kagaku.Flow.Nodes.SinkDescriptor 100%
Kagaku.Flow.Nodes.SocketTypes 100% 100%
Kagaku.Flow.Nodes.SourceDescriptor 100%
Kagaku.Flow.Nodes.TemplateField 100%
Kagaku.Flow.Runs.LedgerChange 100% 100%
Kagaku.Flow.Runs.LedgerTransitions 100% 100%
Kagaku.Flow.Runs.NodeAttempt 100%
Kagaku.Flow.Runs.NodeFacts 100%
Kagaku.Flow.Runs.NodeRun 100%
Kagaku.Flow.Runs.Run 100% 100%
Kagaku.Flow.Runs.RunEvent 100%
Kagaku.Flow.Runs.RunStatuses 100% 100%
Kagaku.Flow.Runs.RunTrigger 100% 100%
Kagaku.Flow.Scheduling.Exclusion 100%
Kagaku.Flow.Scheduling.FlowEngine 100% 100%
Kagaku.Flow.Scheduling.FlowEngineOptions 100% 100%
Kagaku.Flow.Scheduling.ReadyRow 100%
Kagaku.Flow.Scheduling.ReadySet 100% 100%
Kagaku.Flow.Scheduling.ReadySetResult 100%
Kagaku.Flow.Scheduling.RunRequest 100% 100%
Kagaku.Flow.Scheduling.RunStartResult 100%
Kagaku.Flow.Scheduling.SocketValues 100% 100%
Kagaku.Flow.Templating.InputsWalker 100% 100%
Kagaku.Flow.Templating.ParsedTemplate 100% 100%
Kagaku.Flow.Templating.SandboxedTemplateContext 100% 100%
Kagaku.Flow.Templating.TemplateError 100%
Kagaku.Flow.Templating.TemplateHost 100% 100%
Kagaku.Flow.Templating.TemplateLimits 100%
Kagaku.Flow.Templating.TemplateModel 100% 100%
Kagaku.Flow.Templating.TemplateProblem 100%
Kagaku.Flow.Templating.TemplateRenderRequest 100% 100%
Kagaku.Flow.Templating.TemplateRenderResult 100%
Kagaku.Flow.Templating.TemplateRun 100%
Kagaku.Flow.Templating.TemplateSinks 100%
Kagaku.Flow.Templating.TemplateValues 100% 100%
Kagaku.Flow.Validation.GraphValidation 100% 100%
Kagaku.Flow.Validation.GraphValidationContext 100%
Kagaku.Flow.Validation.HookFailure 100%
Kagaku.Flow.Validation.ResolvedGraph 100% 100%
Kagaku.Flow.Validation.ValidationError 100%
Kagaku.Flow.Validation.ValidationReport 100%
System.Text.RegularExpressions.Generated 97.4% 92.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__ColorToken_2
97.4% 94.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__Socket_1
97.2% 94.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__TypeId_0
97.2% 94.4%
Kagaku.Flow.OpenRouter - 100%
Name Line Branch
Kagaku.Flow.OpenRouter 100% 100%
Kagaku.Flow.OpenRouter.Catalog.ModelCapabilities 100% 100%
Kagaku.Flow.OpenRouter.Gateway.LlmCompletion 100%
Kagaku.Flow.OpenRouter.Gateway.OpenRouterGateway 100% 100%
Kagaku.Flow.OpenRouter.Gateway.OpenRouterGatewayOptions 100%
Kagaku.Flow.OpenRouter.Gateway.OpenRouterKeyLookup 100% 100%
Kagaku.Flow.OpenRouter.Gateway.SentRequestCapture 100% 100%
Kagaku.Flow.OpenRouter.Gateway.SentRequestCaptureHandler 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmAnswer 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmConfig 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmConfigRead 100%
Kagaku.Flow.OpenRouter.Llm.LlmDescriptor 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmExecutor 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmFacts 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmFailureText 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmMessage 100%
Kagaku.Flow.OpenRouter.Llm.LlmRequestBuilder 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmRequestPlan 100%
Kagaku.Flow.OpenRouter.Llm.LlmRoutingDefaults 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmSampling 100%
Kagaku.Flow.OpenRouter.Llm.LlmSchemaCheck 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmStrictSchemaRule 100% 100%
Kagaku.Flow.OpenRouter.Llm.LlmVocabulary 100% 100%
Kagaku.Flow.OpenRouter.LlmNodeServiceCollectionExtensions 100%
Kagaku.Flow.OpenRouter.OpenRouterServiceCollectionExtensions 100% 100%
Kagaku.Flow.Testing - 100%
Name Line Branch
Kagaku.Flow.Testing 100% 100%
Kagaku.Flow.Testing.FlowEngineDriver 100% 100%
Kagaku.Flow.Testing.InMemoryRunLedger 100% 100%
Kagaku.Flow.Testing.RecordingRunEventSink 100%
Kagaku.Flow.Testing.RunLedgerContract 100% 100%
Kagaku.Flow.Testing.RunLedgerContractException 100%
Tsumugi.BlazorAdapter - 96%
Name Line Branch
Tsumugi.BlazorAdapter 96% 90.9%
Tsumugi.BlazorAdapter.BlazorAdapterAssembly 100%
Tsumugi.BlazorAdapter.Documents.CategoryCreated 100%
Tsumugi.BlazorAdapter.Documents.CategoryEditor 93.2% 88.4%
Tsumugi.BlazorAdapter.Documents.CategorySaved 100%
Tsumugi.BlazorAdapter.Documents.ChangeCategoryFieldsRequested 100%
Tsumugi.BlazorAdapter.Documents.CreateCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.CreateDocumentRequested 100%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryChoice 100%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryDialog 100% 94.1%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.DeleteDocumentRequested 100%
Tsumugi.BlazorAdapter.Documents.DocumentAutoSaveFailed 100%
Tsumugi.BlazorAdapter.Documents.DocumentCreated 100%
Tsumugi.BlazorAdapter.Documents.DocumentEditor 95.7% 89.4%
Tsumugi.BlazorAdapter.Documents.DocumentImageRefused 100%
Tsumugi.BlazorAdapter.Documents.DocumentImageSet 100%
Tsumugi.BlazorAdapter.Documents.DocumentsActionFailed 100%
Tsumugi.BlazorAdapter.Documents.DocumentSaved 100%
Tsumugi.BlazorAdapter.Documents.DocumentsEffects 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsList 98.5% 93.5%
Tsumugi.BlazorAdapter.Documents.DocumentsLoaded 100%
Tsumugi.BlazorAdapter.Documents.DocumentsPage 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsReducers 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsRefusal 100%
Tsumugi.BlazorAdapter.Documents.DocumentsState 100% 100%
Tsumugi.BlazorAdapter.Documents.FieldInput 100% 96.6%
Tsumugi.BlazorAdapter.Documents.FieldsChanges 100% 100%
Tsumugi.BlazorAdapter.Documents.FieldShapes 90% 87.5%
Tsumugi.BlazorAdapter.Documents.ImageUpload 100%
Tsumugi.BlazorAdapter.Documents.ImageUploadRefusal 100%
Tsumugi.BlazorAdapter.Documents.ImpactText 100% 94.2%
Tsumugi.BlazorAdapter.Documents.LoadDocuments 100%
Tsumugi.BlazorAdapter.Documents.MoveDocumentChoice 100%
Tsumugi.BlazorAdapter.Documents.MoveDocumentDialog 95.6% 71.4%
Tsumugi.BlazorAdapter.Documents.MoveDocumentsRequested 100%
Tsumugi.BlazorAdapter.Documents.ReorderCategoriesRequested 100%
Tsumugi.BlazorAdapter.Documents.SetCategoryCollapsed 100%
Tsumugi.BlazorAdapter.Documents.SetDocumentImageRequested 100%
Tsumugi.BlazorAdapter.Documents.SetDocumentsFilter 100%
Tsumugi.BlazorAdapter.Documents.UpdateCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.UpdateDocumentRequested 100%
Tsumugi.BlazorAdapter.Graphs.GraphCanvas 37.5% 25%
Tsumugi.BlazorAdapter.Graphs.GraphPlaygroundPage 20% 25%
Tsumugi.BlazorAdapter.Notifications.DomainChangedBridge 94.4% 83.3%
Tsumugi.BlazorAdapter.Notifications.DomainChangesReceived 75% 100%
Tsumugi.BlazorAdapter.Runs.RunChangedBridge 97.1% 90.6%
Tsumugi.BlazorAdapter.Runs.RunChangesReceived 100%
Tsumugi.BlazorAdapter.Runs.RunTextReceived 100%
Tsumugi.BlazorAdapter.Settings.BackupCompleted 100%
Tsumugi.BlazorAdapter.Settings.BackupFailed 100%
Tsumugi.BlazorAdapter.Settings.BackupNowRequested 100%
Tsumugi.BlazorAdapter.Settings.BackupSettingsLoaded 100%
Tsumugi.BlazorAdapter.Settings.BackupsSection 100% 100%
Tsumugi.BlazorAdapter.Settings.BackupsSettingsEffects 100% 100%
Tsumugi.BlazorAdapter.Settings.BackupsSettingsReducers 100%
Tsumugi.BlazorAdapter.Settings.BackupsSettingsState 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSection 100% 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSettingsEffects 100% 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSettingsReducers 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSettingsState 100%
Tsumugi.BlazorAdapter.Settings.LlmDefaultsLoaded 100%
Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaved 100%
Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaveFailed 100%
Tsumugi.BlazorAdapter.Settings.LoadBackupSettings 100%
Tsumugi.BlazorAdapter.Settings.LoadProviderSettings 100%
Tsumugi.BlazorAdapter.Settings.ModelCatalogLoaded 100%
Tsumugi.BlazorAdapter.Settings.ModelCatalogLoadFailed 100%
Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaved 100%
Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaveFailed 100%
Tsumugi.BlazorAdapter.Settings.ProviderKeyChecked 100%
Tsumugi.BlazorAdapter.Settings.ProviderSection 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsEffects 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsLoaded 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsReducers 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsState 100% 100%
Tsumugi.BlazorAdapter.Settings.SaveLlmDefaultsRequested 100%
Tsumugi.BlazorAdapter.Settings.SaveOpenRouterKeyRequested 100%
Tsumugi.BlazorAdapter.Stories.CreateStoryRequested 100%
Tsumugi.BlazorAdapter.Stories.PurgeStoryRequested 100%
Tsumugi.BlazorAdapter.Stories.RestoreStoryRequested 100%
Tsumugi.BlazorAdapter.Stories.SetShowArchived 100%
Tsumugi.BlazorAdapter.Stories.SetStoriesFilter 100%
Tsumugi.BlazorAdapter.Stories.SetStoryArchivedRequested 100%
Tsumugi.BlazorAdapter.Stories.StoriesEffects 100% 100%
Tsumugi.BlazorAdapter.Stories.StoriesLoaded 100%
Tsumugi.BlazorAdapter.Stories.StoriesPage 100% 100%
Tsumugi.BlazorAdapter.Stories.StoriesReducers 100% 100%
Tsumugi.BlazorAdapter.Stories.StoriesState 100% 100%
Tsumugi.BlazorAdapter.Stories.StoryActionFailed 100%
Tsumugi.BlazorAdapter.Stories.StoryCreated 100%
Tsumugi.BlazorAdapter.Stories.StoryCreateFailed 100%
Tsumugi.BlazorAdapter.Stories.StoryTrashPage 100% 100%
Tsumugi.BlazorAdapter.Stories.TrashStoryRequested 100%
Tsumugi.BlazorAdapter.Workspace.AckWire 100%
Tsumugi.BlazorAdapter.Workspace.AutoSaveFailed 100%
Tsumugi.BlazorAdapter.Workspace.ChangedWire 100%
Tsumugi.BlazorAdapter.Workspace.ChapterHeader 100% 86.3%
Tsumugi.BlazorAdapter.Workspace.ChapterMenu 100% 81.2%
Tsumugi.BlazorAdapter.Workspace.ChapterPage 100% 80%
Tsumugi.BlazorAdapter.Workspace.ChapterSaved 100%
Tsumugi.BlazorAdapter.Workspace.ChaptersPage 94.4% 83.3%
Tsumugi.BlazorAdapter.Workspace.ChapterWire 100%
Tsumugi.BlazorAdapter.Workspace.ChapterWritten 100%
Tsumugi.BlazorAdapter.Workspace.CreateChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.CreatedWire 100%
Tsumugi.BlazorAdapter.Workspace.DeleteChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.DeltaWire 100%
Tsumugi.BlazorAdapter.Workspace.HistoryEffects 100% 100%
Tsumugi.BlazorAdapter.Workspace.HistoryLoaded 100%
Tsumugi.BlazorAdapter.Workspace.HistoryPage 100%
Tsumugi.BlazorAdapter.Workspace.HistoryPanel 100% 100%
Tsumugi.BlazorAdapter.Workspace.LoadHistory 100%
Tsumugi.BlazorAdapter.Workspace.LoadWorkspace 100%
Tsumugi.BlazorAdapter.Workspace.ManuscriptEffects 100% 100%
Tsumugi.BlazorAdapter.Workspace.ManuscriptEvents 81.8% 74.1%
Tsumugi.BlazorAdapter.Workspace.ManuscriptSurface 91.1% 84.9%
Tsumugi.BlazorAdapter.Workspace.MergeChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.MergeEvent 100%
Tsumugi.BlazorAdapter.Workspace.MoveChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.RedoRequested 100%
Tsumugi.BlazorAdapter.Workspace.RedoRevertRequested 100%
Tsumugi.BlazorAdapter.Workspace.RenameChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.ReshapeEvent 100%
Tsumugi.BlazorAdapter.Workspace.RevertToSnapshotRequested 100%
Tsumugi.BlazorAdapter.Workspace.SaveScope 100% 50%
Tsumugi.BlazorAdapter.Workspace.SaveStateLadder 100% 100%
Tsumugi.BlazorAdapter.Workspace.SaveVersionRequested 100%
Tsumugi.BlazorAdapter.Workspace.SegmentTextEvent 100%
Tsumugi.BlazorAdapter.Workspace.SegmentWire 100% 81.8%
Tsumugi.BlazorAdapter.Workspace.SetChapterSummaryRequested 100%
Tsumugi.BlazorAdapter.Workspace.SplitEvent 100%
Tsumugi.BlazorAdapter.Workspace.StampWire 0%
Tsumugi.BlazorAdapter.Workspace.StoryDetails 100% 85.2%
Tsumugi.BlazorAdapter.Workspace.StoryGeneralPage 100% 100%
Tsumugi.BlazorAdapter.Workspace.StorySaved 100%
Tsumugi.BlazorAdapter.Workspace.StoryShell 100% 100%
Tsumugi.BlazorAdapter.Workspace.UndoRequested 100%
Tsumugi.BlazorAdapter.Workspace.UndoStatusChanged 100%
Tsumugi.BlazorAdapter.Workspace.UpdateStoryRequested 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceActionFailed 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceLoaded 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceNotFound 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceReducers 100% 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceState 100%
Tsumugi.Domain - 96.3%
Name Line Branch
Tsumugi.Domain 96.3% 95%
System.Text.RegularExpressions.Generated 91.3% 88.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__DigitsAndSeparators_2
97.4% 95.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__LineBreak_0
91% 91.1%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__NumberToken_1
91.8% 83.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__Plain_4
91.9% 88.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__ThousandsGroup_3
90.9% 84.3%
Tsumugi.Domain.Documents.CategoryFields 94.5% 93.7%
Tsumugi.Domain.Documents.ChoiceOption 100%
Tsumugi.Domain.Documents.ChoiceValue 100%
Tsumugi.Domain.Documents.DateText 100%
Tsumugi.Domain.Documents.DateValue 100%
Tsumugi.Domain.Documents.Document 100% 100%
Tsumugi.Domain.Documents.DocumentCategory 100% 100%
Tsumugi.Domain.Documents.DocumentValues 100%
Tsumugi.Domain.Documents.FieldCarry 100% 100%
Tsumugi.Domain.Documents.FieldConversion 100% 100%
Tsumugi.Domain.Documents.FieldDefinition 97% 95.3%
Tsumugi.Domain.Documents.FieldMessages 100% 100%
Tsumugi.Domain.Documents.FieldNames 100%
Tsumugi.Domain.Documents.FieldsChange 100%
Tsumugi.Domain.Documents.FieldShape 95.2% 87.5%
Tsumugi.Domain.Documents.FieldsPlan 100%
Tsumugi.Domain.Documents.FieldsPlanner 99.2% 99.2%
Tsumugi.Domain.Documents.FieldValue 100%
Tsumugi.Domain.Documents.FieldValues 95.4% 97.7%
Tsumugi.Domain.Documents.ImageFiles 100% 100%
Tsumugi.Domain.Documents.ImageValue 100%
Tsumugi.Domain.Documents.MovePlan 100%
Tsumugi.Domain.Documents.NumberParse 100%
Tsumugi.Domain.Documents.NumberText 100% 97.6%
Tsumugi.Domain.Documents.NumberValue 100%
Tsumugi.Domain.Documents.StoryImage 100%
Tsumugi.Domain.Documents.TextValue 100% 100%
Tsumugi.Domain.Documents.ValueChange 100%
Tsumugi.Domain.Documents.ValueChangeKey 100%
Tsumugi.Domain.Documents.ValueImpact 100% 100%
Tsumugi.Domain.Journal.ChangeLogEntry 97.8% 75%
Tsumugi.Domain.Journal.StorySnapshot 95.4% 83.3%
Tsumugi.Domain.Settings.AppSetting 100%
Tsumugi.Domain.Stories.Chapter 100% 100%
Tsumugi.Domain.Stories.InlineMarkup 100% 100%
Tsumugi.Domain.Stories.MarkupRun 100%
Tsumugi.Domain.Stories.Provenance 100% 100%
Tsumugi.Domain.Stories.Segment 100% 100%
Tsumugi.Domain.Stories.Story 100% 100%
Tsumugi.Domain.Text 100% 100%
Tsumugi.Infrastructure - 97.9%
Name Line Branch
Tsumugi.Infrastructure 97.9% 86%
System.Text.RegularExpressions.Generated 81.4% 64.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F0D076C66E8EEC1C
A55E0373ED22DC58420DBB40F103A46B68DC4D9CE5A49E00B__Pattern_0
84% 65.7%
Tsumugi.Infrastructure.Backups.BackupArtifactName 100% 100%
Tsumugi.Infrastructure.Backups.BackupOptions 100%
Tsumugi.Infrastructure.Backups.BackupSchedule 100% 83.3%
Tsumugi.Infrastructure.Backups.BackupScheduler 96.6% 87.5%
Tsumugi.Infrastructure.Backups.BackupWriter 98.5% 92.8%
Tsumugi.Infrastructure.Backups.DatabaseFingerprint 91.9% 97%
Tsumugi.Infrastructure.Backups.FileSystemBackupStore 100% 100%
Tsumugi.Infrastructure.Backups.OwnerOnlyFile 100% 100%
Tsumugi.Infrastructure.Backups.PreMigrationBackup 90% 100%
Tsumugi.Infrastructure.Backups.SqliteSnapshot 88.2% 75%
Tsumugi.Infrastructure.DependencyInjection 100% 100%
Tsumugi.Infrastructure.Journal.EfChangeJournal 100%
Tsumugi.Infrastructure.Journal.EfSnapshotStore 100%
Tsumugi.Infrastructure.Journal.EfUndoStore 98.1% 85.7%
Tsumugi.Infrastructure.Journal.ModelExtensions 100%
Tsumugi.Infrastructure.Journal.OperationContext 100% 100%
Tsumugi.Infrastructure.Journal.PropertyBag 100% 95.4%
Tsumugi.Infrastructure.Notifications.InProcessDomainChangedBus 100% 100%
Tsumugi.Infrastructure.Persistence.Configurations.AppSettingConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.ChangeLogEntryConfigurati
on
100%
Tsumugi.Infrastructure.Persistence.Configurations.ChapterConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.DocumentCategoryConfigura
tion
100%
Tsumugi.Infrastructure.Persistence.Configurations.DocumentConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.SegmentConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.StoryConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.StoryImageConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.StorySnapshotConfiguratio
n
100%
Tsumugi.Infrastructure.Persistence.Converters.CanonicalJsonComparer 100%
Tsumugi.Infrastructure.Persistence.Converters.CategoryFieldsConverter 97.6% 94.4%
Tsumugi.Infrastructure.Persistence.Converters.FieldValuesConverter 96.9% 93.7%
Tsumugi.Infrastructure.Persistence.Converters.ProvenanceConverter 100% 90%
Tsumugi.Infrastructure.Persistence.Converters.UtcTicksConverter 100%
Tsumugi.Infrastructure.Persistence.Converters.WireFormat 85.7% 73.8%
Tsumugi.Infrastructure.Persistence.Migrations.AddAppSettings 99.2%
Tsumugi.Infrastructure.Persistence.Migrations.AddJournal 98.8%
Tsumugi.Infrastructure.Persistence.Migrations.CategoryFields 100% 100%
Tsumugi.Infrastructure.Persistence.Migrations.CategoryFieldsSql 100%
Tsumugi.Infrastructure.Persistence.Migrations.DropDocumentBody 100%
Tsumugi.Infrastructure.Persistence.Migrations.GenericDocuments 100%
Tsumugi.Infrastructure.Persistence.Migrations.InitialStoryDomain 97.3%
Tsumugi.Infrastructure.Persistence.Migrations.SegmentTextMarkup 100% 100%
Tsumugi.Infrastructure.Persistence.Migrations.SegmentTextMarkupSql 100%
Tsumugi.Infrastructure.Persistence.Migrations.StoryImages 100%
Tsumugi.Infrastructure.Persistence.Migrations.TsumugiDbContextModelSnapshot 100%
Tsumugi.Infrastructure.Persistence.SqliteFunctions 80% 66.6%
Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor 100% 100%
Tsumugi.Infrastructure.Persistence.Stores.EfChapterStore 100% 100%
Tsumugi.Infrastructure.Persistence.Stores.EfDocumentStore 98.3% 75%
Tsumugi.Infrastructure.Persistence.Stores.EfImageStore 100%
Tsumugi.Infrastructure.Persistence.Stores.EfSegmentStore 96.6% 84.6%
Tsumugi.Infrastructure.Persistence.Stores.EfStoryStore 98.7% 90%
Tsumugi.Infrastructure.Persistence.TsumugiDbContext 85.9% 89.2%
Tsumugi.Infrastructure.Persistence.TsumugiDbContextFactory 100%
Tsumugi.Infrastructure.Provider.LlmDefaultsSource 100%
Tsumugi.Infrastructure.Provider.OpenRouterKeySource 100% 100%
Tsumugi.Infrastructure.Provider.OpenRouterModelProvider 100% 100%
Tsumugi.Infrastructure.Provider.OpenRouterOptions 100% 100%
Tsumugi.Infrastructure.Provider.ResolvedKey 100%
Tsumugi.Infrastructure.Runs.InProcessRunEventBus 100% 100%
Tsumugi.Infrastructure.Settings.EfAppSettingsStore 100% 100%
Tsumugi.Kernel - 90.9%
Name Line Branch
Tsumugi.Kernel 90.9% 75%
Tsumugi.Kernel.Err`1 100%
Tsumugi.Kernel.Ok`1 100%
Tsumugi.Kernel.Result`1 88.8% 75%
Tsumugi.Server - 100%
Name Line Branch
Tsumugi.Server 100% 92.1%
Program 100% 100%
Tsumugi.Server.Backups.BackupConfiguration 100% 100%
Tsumugi.Server.Components.App 100%
Tsumugi.Server.Components.Layout.AppHeader 100% 50%
Tsumugi.Server.Components.Layout.MainLayout 100%
Tsumugi.Server.Components.Pages.Gate 100% 100%
Tsumugi.Server.Provider.OpenRouterConfiguration 100% 100%
Tsumugi.Server.Security.AccessGate 100% 87.5%
Tsumugi.Server.Security.AccessSecret 100% 100%
Tsumugi.Server.Security.GateThrottle 100% 100%
Tsumugi.Server.VolumeStartupValidator 100% 100%
Tsumugi.UseCases - 98.5%
Name Line Branch
Tsumugi.UseCases 98.5% 95.7%
Tsumugi.UseCases.Backups.BackupArtifact 100%
Tsumugi.UseCases.Backups.BackupFailure 100%
Tsumugi.UseCases.Backups.BackupJobState 100%
Tsumugi.UseCases.Backups.BackupPolicy 100%
Tsumugi.UseCases.Backups.BackupStatusView 100% 100%
Tsumugi.UseCases.Backups.DatabaseSnapshot 100%
Tsumugi.UseCases.Backups.DownloadDatabaseSnapshot 100%
Tsumugi.UseCases.Backups.GetBackupStatus 100%
Tsumugi.UseCases.Backups.IBackupStore 0%
Tsumugi.UseCases.Backups.RunBackupNow 100%
Tsumugi.UseCases.Chapters.ChapterDto 100%
Tsumugi.UseCases.Chapters.CreateChapter 100% 100%
Tsumugi.UseCases.Chapters.DeleteChapter 100% 100%
Tsumugi.UseCases.Chapters.GetChapterSegments 100%
Tsumugi.UseCases.Chapters.GetManuscript 100% 100%
Tsumugi.UseCases.Chapters.ManuscriptChapter 100%
Tsumugi.UseCases.Chapters.ManuscriptView 100%
Tsumugi.UseCases.Chapters.MergeChapters 100% 100%
Tsumugi.UseCases.Chapters.RenameChapter 100% 100%
Tsumugi.UseCases.Chapters.ReorderChapters 100% 100%
Tsumugi.UseCases.Chapters.SetChapterSummary 100% 75%
Tsumugi.UseCases.Context.DocumentRendering 100% 100%
Tsumugi.UseCases.Context.StoryDocumentsRule 100% 100%
Tsumugi.UseCases.Context.StoryReads 100% 100%
Tsumugi.UseCases.Context.StoryScope 100% 100%
Tsumugi.UseCases.Context.StoryTemplateModel 100%
Tsumugi.UseCases.DependencyInjection 100%
Tsumugi.UseCases.Diagnostics.SeedDevData 98.3% 68.7%
Tsumugi.UseCases.Diagnostics.SeedPictures 100%
Tsumugi.UseCases.Documents.ChangeCategoryFields 100% 83.3%
Tsumugi.UseCases.Documents.CreateCategory 100% 100%
Tsumugi.UseCases.Documents.CreateDocument 100% 100%
Tsumugi.UseCases.Documents.DefaultFields 100% 100%
Tsumugi.UseCases.Documents.DeleteCategory 100% 94.4%
Tsumugi.UseCases.Documents.DeleteDocument 100% 100%
Tsumugi.UseCases.Documents.DocumentCategoryDto 100%
Tsumugi.UseCases.Documents.DocumentCategoryProfile 100%
Tsumugi.UseCases.Documents.DocumentDto 100%
Tsumugi.UseCases.Documents.DocumentPatch 100%
Tsumugi.UseCases.Documents.DocumentProfile 100%
Tsumugi.UseCases.Documents.DocumentsCategory 100%
Tsumugi.UseCases.Documents.DocumentsView 100%
Tsumugi.UseCases.Documents.DocumentWrites 100% 100%
Tsumugi.UseCases.Documents.FieldsChangeLabel 95.4% 88.2%
Tsumugi.UseCases.Documents.GetDocuments 100% 100%
Tsumugi.UseCases.Documents.GetStoryImage 100% 100%
Tsumugi.UseCases.Documents.ImpactPreview 100% 100%
Tsumugi.UseCases.Documents.LossMessages 92.3% 87.5%
Tsumugi.UseCases.Documents.MoveDocuments 100% 100%
Tsumugi.UseCases.Documents.ReorderCategories 100% 100%
Tsumugi.UseCases.Documents.SetDocumentImage 100% 93.7%
Tsumugi.UseCases.Documents.StoryImageFile 100%
Tsumugi.UseCases.Documents.UpdateCategory 100% 100%
Tsumugi.UseCases.Documents.UpdateDocument 100% 81.2%
Tsumugi.UseCases.Documents.WriteRefusedException 100%
Tsumugi.UseCases.Journal.GetStoryHistory 100% 100%
Tsumugi.UseCases.Journal.GetUndoStatus 100% 100%
Tsumugi.UseCases.Journal.HistoryOperation 66.6%
Tsumugi.UseCases.Journal.HistorySnapshot 87.5%
Tsumugi.UseCases.Journal.OperationGrouping 100% 100%
Tsumugi.UseCases.Journal.RedoRevert 100% 100%
Tsumugi.UseCases.Journal.RedoRun 75% 57.1%
Tsumugi.UseCases.Journal.RedoTyping 100% 100%
Tsumugi.UseCases.Journal.RevertConflict 100%
Tsumugi.UseCases.Journal.RevertOutcome 100%
Tsumugi.UseCases.Journal.RevertRun 96.5% 77.7%
Tsumugi.UseCases.Journal.RevertToSnapshot 92.3% 83.3%
Tsumugi.UseCases.Journal.StoryHistory 100%
Tsumugi.UseCases.Journal.TakeSnapshot 100% 87.5%
Tsumugi.UseCases.Journal.UndoStatus 100%
Tsumugi.UseCases.Journal.UndoTyping 100% 100%
Tsumugi.UseCases.Journal.UserOperation 100%
Tsumugi.UseCases.Notifications.DomainChanged 100%
Tsumugi.UseCases.Ordering 100% 100%
Tsumugi.UseCases.Runs.RunEvent 100%
Tsumugi.UseCases.Segments.ChangedText 100%
Tsumugi.UseCases.Segments.ChapterDraft 100%
Tsumugi.UseCases.Segments.ChapterWriting 100%
Tsumugi.UseCases.Segments.DeleteSegments 100% 100%
Tsumugi.UseCases.Segments.EditSegment 100% 100%
Tsumugi.UseCases.Segments.InsertSegment 100% 100%
Tsumugi.UseCases.Segments.ManuscriptAnswer 100%
Tsumugi.UseCases.Segments.ManuscriptWrites 99.1% 97.6%
Tsumugi.UseCases.Segments.MergeSegments 100%
Tsumugi.UseCases.Segments.MergeWrite 100%
Tsumugi.UseCases.Segments.ModelOutput 98.2% 96.6%
Tsumugi.UseCases.Segments.ModelParagraph 100%
Tsumugi.UseCases.Segments.MoveSegments 100% 100%
Tsumugi.UseCases.Segments.NewBlock 100%
Tsumugi.UseCases.Segments.ReorderSegments 100% 100%
Tsumugi.UseCases.Segments.ReshapeSegments 100% 100%
Tsumugi.UseCases.Segments.ReshapeWrite 100%
Tsumugi.UseCases.Segments.SegmentDto 100%
Tsumugi.UseCases.Segments.SplitSegment 100%
Tsumugi.UseCases.Segments.SplitWrite 100%
Tsumugi.UseCases.Segments.StampedId 100%
Tsumugi.UseCases.Segments.TextWrite 100%
Tsumugi.UseCases.Settings.CatalogModel 100% 100%
Tsumugi.UseCases.Settings.CheckOpenRouterKey 100%
Tsumugi.UseCases.Settings.GetLlmDefaults 100% 100%
Tsumugi.UseCases.Settings.GetModelCatalog 100% 100%
Tsumugi.UseCases.Settings.GetProviderSettings 100%
Tsumugi.UseCases.Settings.LlmDefaults 100%
Tsumugi.UseCases.Settings.ProviderKeyInfo 100%
Tsumugi.UseCases.Settings.ProviderKeyState 100%
Tsumugi.UseCases.Settings.ProviderSettingsView 100% 100%
Tsumugi.UseCases.Settings.ReasoningEfforts 100% 100%
Tsumugi.UseCases.Settings.RemoveOpenRouterKey 100%
Tsumugi.UseCases.Settings.RoutingDefaults 100%
Tsumugi.UseCases.Settings.RoutingSettings 100% 100%
Tsumugi.UseCases.Settings.SaveLlmDefaults 100% 100%
Tsumugi.UseCases.Settings.SaveOpenRouterKey 100% 100%
Tsumugi.UseCases.Stories.ChapterWriteOutcome 50%
Tsumugi.UseCases.Stories.CreateStory 100% 100%
Tsumugi.UseCases.Stories.GetStory 100% 100%
Tsumugi.UseCases.Stories.ListStories 100% 75%
Tsumugi.UseCases.Stories.PurgeStory 100% 100%
Tsumugi.UseCases.Stories.RestoreStory 100% 100%
Tsumugi.UseCases.Stories.SetActiveGraph 100% 100%
Tsumugi.UseCases.Stories.SetStoryArchived 100% 100%
Tsumugi.UseCases.Stories.StarterCategories 100%
Tsumugi.UseCases.Stories.StoryDetail 100%
Tsumugi.UseCases.Stories.StoryListItem 81.8%
Tsumugi.UseCases.Stories.StoryProfile 100%
Tsumugi.UseCases.Stories.TrashStory 100% 100%
Tsumugi.UseCases.Stories.UpdateStory 100% 100%
<!-- coverage-comment --> > 🔄 **Auto-updating coverage report** — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip. > > **Commit:** `afb4c53` · **Generated:** 2026-09-26 14:41:21 UTC · **Revision:** #2 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 09/26/2026 - 14:41:21 | | Coverage date: | 09/26/2026 - 14:40:53 - 09/26/2026 - 14:41:17 | | Parser: | MultiReport (6x Cobertura) | | Assemblies: | 9 | | Classes: | 494 | | Files: | 447 | | **Line coverage:** | 98% (15216 of 15526) | | Covered lines: | 15216 | | Uncovered lines: | 310 | | Coverable lines: | 15526 | | Total lines: | 33413 | | **Branch coverage:** | 94.1% (5937 of 6308) | | Covered branches: | 5937 | | Total branches: | 6308 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Kagaku.Flow - 99.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.Flow**|**99.7%**|**99.2%**| |Kagaku.Flow.Budgeting.BudgetRequest|100%|| |Kagaku.Flow.Budgeting.ConsumerBudget|100%|| |Kagaku.Flow.Execution.NodeExecution|100%|100%| |Kagaku.Flow.Execution.NodeOutcome|100%|100%| |Kagaku.Flow.Execution.TransientFailureException|100%|| |Kagaku.Flow.Execution.Upstream|100%|| |Kagaku.Flow.Extensions.ServiceCollectionExtensions|100%|| |Kagaku.Flow.FlowJson|100%|| |Kagaku.Flow.Graphs.GraphDefinition|100%|| |Kagaku.Flow.Graphs.GraphDocument|100%|100%| |Kagaku.Flow.Graphs.GraphEdge|100%|| |Kagaku.Flow.Graphs.GraphIndex|100%|100%| |Kagaku.Flow.Graphs.GraphLoadError|100%|| |Kagaku.Flow.Graphs.GraphLoadResult|100%|| |Kagaku.Flow.Graphs.GraphNode|100%|| |Kagaku.Flow.Graphs.GraphPosition|100%|| |Kagaku.Flow.Graphs.GraphReader|100%|100%| |Kagaku.Flow.Graphs.GraphSchema|100%|100%| |Kagaku.Flow.Graphs.GraphShapeException|100%|| |Kagaku.Flow.Graphs.GraphWriter|100%|100%| |Kagaku.Flow.Graphs.SocketRef|100%|| |Kagaku.Flow.Graphs.WireText|100%|100%| |Kagaku.Flow.Nodes.CanvasDescriptorWriter|100%|100%| |Kagaku.Flow.Nodes.ConfigProblem|100%|| |Kagaku.Flow.Nodes.Names|100%|| |Kagaku.Flow.Nodes.NodeDescriptor|100%|100%| |Kagaku.Flow.Nodes.NodeRegistry|100%|100%| |Kagaku.Flow.Nodes.NodeSockets|100%|100%| |Kagaku.Flow.Nodes.SinkDescriptor|100%|| |Kagaku.Flow.Nodes.SocketTypes|100%|100%| |Kagaku.Flow.Nodes.SourceDescriptor|100%|| |Kagaku.Flow.Nodes.TemplateField|100%|| |Kagaku.Flow.Runs.LedgerChange|100%|100%| |Kagaku.Flow.Runs.LedgerTransitions|100%|100%| |Kagaku.Flow.Runs.NodeAttempt|100%|| |Kagaku.Flow.Runs.NodeFacts|100%|| |Kagaku.Flow.Runs.NodeRun|100%|| |Kagaku.Flow.Runs.Run|100%|100%| |Kagaku.Flow.Runs.RunEvent|100%|| |Kagaku.Flow.Runs.RunStatuses|100%|100%| |Kagaku.Flow.Runs.RunTrigger|100%|100%| |Kagaku.Flow.Scheduling.Exclusion|100%|| |Kagaku.Flow.Scheduling.FlowEngine|100%|100%| |Kagaku.Flow.Scheduling.FlowEngineOptions|100%|100%| |Kagaku.Flow.Scheduling.ReadyRow|100%|| |Kagaku.Flow.Scheduling.ReadySet|100%|100%| |Kagaku.Flow.Scheduling.ReadySetResult|100%|| |Kagaku.Flow.Scheduling.RunRequest|100%|100%| |Kagaku.Flow.Scheduling.RunStartResult|100%|| |Kagaku.Flow.Scheduling.SocketValues|100%|100%| |Kagaku.Flow.Templating.InputsWalker|100%|100%| |Kagaku.Flow.Templating.ParsedTemplate|100%|100%| |Kagaku.Flow.Templating.SandboxedTemplateContext|100%|100%| |Kagaku.Flow.Templating.TemplateError|100%|| |Kagaku.Flow.Templating.TemplateHost|100%|100%| |Kagaku.Flow.Templating.TemplateLimits|100%|| |Kagaku.Flow.Templating.TemplateModel|100%|100%| |Kagaku.Flow.Templating.TemplateProblem|100%|| |Kagaku.Flow.Templating.TemplateRenderRequest|100%|100%| |Kagaku.Flow.Templating.TemplateRenderResult|100%|| |Kagaku.Flow.Templating.TemplateRun|100%|| |Kagaku.Flow.Templating.TemplateSinks|100%|| |Kagaku.Flow.Templating.TemplateValues|100%|100%| |Kagaku.Flow.Validation.GraphValidation|100%|100%| |Kagaku.Flow.Validation.GraphValidationContext|100%|| |Kagaku.Flow.Validation.HookFailure|100%|| |Kagaku.Flow.Validation.ResolvedGraph|100%|100%| |Kagaku.Flow.Validation.ValidationError|100%|| |Kagaku.Flow.Validation.ValidationReport|100%|| |System.Text.RegularExpressions.Generated|97.4%|92.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF<br/>E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__ColorToken_2|97.4%|94.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF<br/>E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__Socket_1|97.2%|94.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF<br/>E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__TypeId_0|97.2%|94.4%| </details> <details><summary>Kagaku.Flow.OpenRouter - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.Flow.OpenRouter**|**100%**|**100%**| |Kagaku.Flow.OpenRouter.Catalog.ModelCapabilities|100%|100%| |Kagaku.Flow.OpenRouter.Gateway.LlmCompletion|100%|| |Kagaku.Flow.OpenRouter.Gateway.OpenRouterGateway|100%|100%| |Kagaku.Flow.OpenRouter.Gateway.OpenRouterGatewayOptions|100%|| |Kagaku.Flow.OpenRouter.Gateway.OpenRouterKeyLookup|100%|100%| |Kagaku.Flow.OpenRouter.Gateway.SentRequestCapture|100%|100%| |Kagaku.Flow.OpenRouter.Gateway.SentRequestCaptureHandler|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmAnswer|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmConfig|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmConfigRead|100%|| |Kagaku.Flow.OpenRouter.Llm.LlmDescriptor|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmExecutor|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmFacts|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmFailureText|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmMessage|100%|| |Kagaku.Flow.OpenRouter.Llm.LlmRequestBuilder|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmRequestPlan|100%|| |Kagaku.Flow.OpenRouter.Llm.LlmRoutingDefaults|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmSampling|100%|| |Kagaku.Flow.OpenRouter.Llm.LlmSchemaCheck|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmStrictSchemaRule|100%|100%| |Kagaku.Flow.OpenRouter.Llm.LlmVocabulary|100%|100%| |Kagaku.Flow.OpenRouter.LlmNodeServiceCollectionExtensions|100%|| |Kagaku.Flow.OpenRouter.OpenRouterServiceCollectionExtensions|100%|100%| </details> <details><summary>Kagaku.Flow.Testing - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.Flow.Testing**|**100%**|**100%**| |Kagaku.Flow.Testing.FlowEngineDriver|100%|100%| |Kagaku.Flow.Testing.InMemoryRunLedger|100%|100%| |Kagaku.Flow.Testing.RecordingRunEventSink|100%|| |Kagaku.Flow.Testing.RunLedgerContract|100%|100%| |Kagaku.Flow.Testing.RunLedgerContractException|100%|| </details> <details><summary>Tsumugi.BlazorAdapter - 96%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.BlazorAdapter**|**96%**|**90.9%**| |Tsumugi.BlazorAdapter.BlazorAdapterAssembly|100%|| |Tsumugi.BlazorAdapter.Documents.CategoryCreated|100%|| |Tsumugi.BlazorAdapter.Documents.CategoryEditor|93.2%|88.4%| |Tsumugi.BlazorAdapter.Documents.CategorySaved|100%|| |Tsumugi.BlazorAdapter.Documents.ChangeCategoryFieldsRequested|100%|| |Tsumugi.BlazorAdapter.Documents.CreateCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.CreateDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryChoice|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryDialog|100%|94.1%| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentAutoSaveFailed|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentCreated|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentEditor|95.7%|89.4%| |Tsumugi.BlazorAdapter.Documents.DocumentImageRefused|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentImageSet|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsActionFailed|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentSaved|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsEffects|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsList|98.5%|93.5%| |Tsumugi.BlazorAdapter.Documents.DocumentsLoaded|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsPage|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsReducers|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsRefusal|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsState|100%|100%| |Tsumugi.BlazorAdapter.Documents.FieldInput|100%|96.6%| |Tsumugi.BlazorAdapter.Documents.FieldsChanges|100%|100%| |Tsumugi.BlazorAdapter.Documents.FieldShapes|90%|87.5%| |Tsumugi.BlazorAdapter.Documents.ImageUpload|100%|| |Tsumugi.BlazorAdapter.Documents.ImageUploadRefusal|100%|| |Tsumugi.BlazorAdapter.Documents.ImpactText|100%|94.2%| |Tsumugi.BlazorAdapter.Documents.LoadDocuments|100%|| |Tsumugi.BlazorAdapter.Documents.MoveDocumentChoice|100%|| |Tsumugi.BlazorAdapter.Documents.MoveDocumentDialog|95.6%|71.4%| |Tsumugi.BlazorAdapter.Documents.MoveDocumentsRequested|100%|| |Tsumugi.BlazorAdapter.Documents.ReorderCategoriesRequested|100%|| |Tsumugi.BlazorAdapter.Documents.SetCategoryCollapsed|100%|| |Tsumugi.BlazorAdapter.Documents.SetDocumentImageRequested|100%|| |Tsumugi.BlazorAdapter.Documents.SetDocumentsFilter|100%|| |Tsumugi.BlazorAdapter.Documents.UpdateCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.UpdateDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Graphs.GraphCanvas|37.5%|25%| |Tsumugi.BlazorAdapter.Graphs.GraphPlaygroundPage|20%|25%| |Tsumugi.BlazorAdapter.Notifications.DomainChangedBridge|94.4%|83.3%| |Tsumugi.BlazorAdapter.Notifications.DomainChangesReceived|75%|100%| |Tsumugi.BlazorAdapter.Runs.RunChangedBridge|97.1%|90.6%| |Tsumugi.BlazorAdapter.Runs.RunChangesReceived|100%|| |Tsumugi.BlazorAdapter.Runs.RunTextReceived|100%|| |Tsumugi.BlazorAdapter.Settings.BackupCompleted|100%|| |Tsumugi.BlazorAdapter.Settings.BackupFailed|100%|| |Tsumugi.BlazorAdapter.Settings.BackupNowRequested|100%|| |Tsumugi.BlazorAdapter.Settings.BackupSettingsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.BackupsSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.BackupsSettingsEffects|100%|100%| |Tsumugi.BlazorAdapter.Settings.BackupsSettingsReducers|100%|| |Tsumugi.BlazorAdapter.Settings.BackupsSettingsState|100%|| |Tsumugi.BlazorAdapter.Settings.DefaultsSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.DefaultsSettingsEffects|100%|100%| |Tsumugi.BlazorAdapter.Settings.DefaultsSettingsReducers|100%|| |Tsumugi.BlazorAdapter.Settings.DefaultsSettingsState|100%|| |Tsumugi.BlazorAdapter.Settings.LlmDefaultsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaved|100%|| |Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaveFailed|100%|| |Tsumugi.BlazorAdapter.Settings.LoadBackupSettings|100%|| |Tsumugi.BlazorAdapter.Settings.LoadProviderSettings|100%|| |Tsumugi.BlazorAdapter.Settings.ModelCatalogLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.ModelCatalogLoadFailed|100%|| |Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaved|100%|| |Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaveFailed|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderKeyChecked|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsEffects|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsReducers|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsState|100%|100%| |Tsumugi.BlazorAdapter.Settings.SaveLlmDefaultsRequested|100%|| |Tsumugi.BlazorAdapter.Settings.SaveOpenRouterKeyRequested|100%|| |Tsumugi.BlazorAdapter.Stories.CreateStoryRequested|100%|| |Tsumugi.BlazorAdapter.Stories.PurgeStoryRequested|100%|| |Tsumugi.BlazorAdapter.Stories.RestoreStoryRequested|100%|| |Tsumugi.BlazorAdapter.Stories.SetShowArchived|100%|| |Tsumugi.BlazorAdapter.Stories.SetStoriesFilter|100%|| |Tsumugi.BlazorAdapter.Stories.SetStoryArchivedRequested|100%|| |Tsumugi.BlazorAdapter.Stories.StoriesEffects|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoriesLoaded|100%|| |Tsumugi.BlazorAdapter.Stories.StoriesPage|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoriesReducers|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoriesState|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoryActionFailed|100%|| |Tsumugi.BlazorAdapter.Stories.StoryCreated|100%|| |Tsumugi.BlazorAdapter.Stories.StoryCreateFailed|100%|| |Tsumugi.BlazorAdapter.Stories.StoryTrashPage|100%|100%| |Tsumugi.BlazorAdapter.Stories.TrashStoryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.AckWire|100%|| |Tsumugi.BlazorAdapter.Workspace.AutoSaveFailed|100%|| |Tsumugi.BlazorAdapter.Workspace.ChangedWire|100%|| |Tsumugi.BlazorAdapter.Workspace.ChapterHeader|100%|86.3%| |Tsumugi.BlazorAdapter.Workspace.ChapterMenu|100%|81.2%| |Tsumugi.BlazorAdapter.Workspace.ChapterPage|100%|80%| |Tsumugi.BlazorAdapter.Workspace.ChapterSaved|100%|| |Tsumugi.BlazorAdapter.Workspace.ChaptersPage|94.4%|83.3%| |Tsumugi.BlazorAdapter.Workspace.ChapterWire|100%|| |Tsumugi.BlazorAdapter.Workspace.ChapterWritten|100%|| |Tsumugi.BlazorAdapter.Workspace.CreateChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.CreatedWire|100%|| |Tsumugi.BlazorAdapter.Workspace.DeleteChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.DeltaWire|100%|| |Tsumugi.BlazorAdapter.Workspace.HistoryEffects|100%|100%| |Tsumugi.BlazorAdapter.Workspace.HistoryLoaded|100%|| |Tsumugi.BlazorAdapter.Workspace.HistoryPage|100%|| |Tsumugi.BlazorAdapter.Workspace.HistoryPanel|100%|100%| |Tsumugi.BlazorAdapter.Workspace.LoadHistory|100%|| |Tsumugi.BlazorAdapter.Workspace.LoadWorkspace|100%|| |Tsumugi.BlazorAdapter.Workspace.ManuscriptEffects|100%|100%| |Tsumugi.BlazorAdapter.Workspace.ManuscriptEvents|81.8%|74.1%| |Tsumugi.BlazorAdapter.Workspace.ManuscriptSurface|91.1%|84.9%| |Tsumugi.BlazorAdapter.Workspace.MergeChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.MergeEvent|100%|| |Tsumugi.BlazorAdapter.Workspace.MoveChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RedoRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RedoRevertRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RenameChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.ReshapeEvent|100%|| |Tsumugi.BlazorAdapter.Workspace.RevertToSnapshotRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SaveScope|100%|50%| |Tsumugi.BlazorAdapter.Workspace.SaveStateLadder|100%|100%| |Tsumugi.BlazorAdapter.Workspace.SaveVersionRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SegmentTextEvent|100%|| |Tsumugi.BlazorAdapter.Workspace.SegmentWire|100%|81.8%| |Tsumugi.BlazorAdapter.Workspace.SetChapterSummaryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SplitEvent|100%|| |Tsumugi.BlazorAdapter.Workspace.StampWire|0%|| |Tsumugi.BlazorAdapter.Workspace.StoryDetails|100%|85.2%| |Tsumugi.BlazorAdapter.Workspace.StoryGeneralPage|100%|100%| |Tsumugi.BlazorAdapter.Workspace.StorySaved|100%|| |Tsumugi.BlazorAdapter.Workspace.StoryShell|100%|100%| |Tsumugi.BlazorAdapter.Workspace.UndoRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.UndoStatusChanged|100%|| |Tsumugi.BlazorAdapter.Workspace.UpdateStoryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceActionFailed|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceLoaded|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceNotFound|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceReducers|100%|100%| |Tsumugi.BlazorAdapter.Workspace.WorkspaceState|100%|| </details> <details><summary>Tsumugi.Domain - 96.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Domain**|**96.3%**|**95%**| |System.Text.RegularExpressions.Generated|91.3%|88.6%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25<br/>BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__DigitsAndSeparators_2|97.4%|95.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25<br/>BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__LineBreak_0|91%|91.1%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25<br/>BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__NumberToken_1|91.8%|83.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25<br/>BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__Plain_4|91.9%|88.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F5BB471BFAD87E25<br/>BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__ThousandsGroup_3|90.9%|84.3%| |Tsumugi.Domain.Documents.CategoryFields|94.5%|93.7%| |Tsumugi.Domain.Documents.ChoiceOption|100%|| |Tsumugi.Domain.Documents.ChoiceValue|100%|| |Tsumugi.Domain.Documents.DateText|100%|| |Tsumugi.Domain.Documents.DateValue|100%|| |Tsumugi.Domain.Documents.Document|100%|100%| |Tsumugi.Domain.Documents.DocumentCategory|100%|100%| |Tsumugi.Domain.Documents.DocumentValues|100%|| |Tsumugi.Domain.Documents.FieldCarry|100%|100%| |Tsumugi.Domain.Documents.FieldConversion|100%|100%| |Tsumugi.Domain.Documents.FieldDefinition|97%|95.3%| |Tsumugi.Domain.Documents.FieldMessages|100%|100%| |Tsumugi.Domain.Documents.FieldNames|100%|| |Tsumugi.Domain.Documents.FieldsChange|100%|| |Tsumugi.Domain.Documents.FieldShape|95.2%|87.5%| |Tsumugi.Domain.Documents.FieldsPlan|100%|| |Tsumugi.Domain.Documents.FieldsPlanner|99.2%|99.2%| |Tsumugi.Domain.Documents.FieldValue|100%|| |Tsumugi.Domain.Documents.FieldValues|95.4%|97.7%| |Tsumugi.Domain.Documents.ImageFiles|100%|100%| |Tsumugi.Domain.Documents.ImageValue|100%|| |Tsumugi.Domain.Documents.MovePlan|100%|| |Tsumugi.Domain.Documents.NumberParse|100%|| |Tsumugi.Domain.Documents.NumberText|100%|97.6%| |Tsumugi.Domain.Documents.NumberValue|100%|| |Tsumugi.Domain.Documents.StoryImage|100%|| |Tsumugi.Domain.Documents.TextValue|100%|100%| |Tsumugi.Domain.Documents.ValueChange|100%|| |Tsumugi.Domain.Documents.ValueChangeKey|100%|| |Tsumugi.Domain.Documents.ValueImpact|100%|100%| |Tsumugi.Domain.Journal.ChangeLogEntry|97.8%|75%| |Tsumugi.Domain.Journal.StorySnapshot|95.4%|83.3%| |Tsumugi.Domain.Settings.AppSetting|100%|| |Tsumugi.Domain.Stories.Chapter|100%|100%| |Tsumugi.Domain.Stories.InlineMarkup|100%|100%| |Tsumugi.Domain.Stories.MarkupRun|100%|| |Tsumugi.Domain.Stories.Provenance|100%|100%| |Tsumugi.Domain.Stories.Segment|100%|100%| |Tsumugi.Domain.Stories.Story|100%|100%| |Tsumugi.Domain.Text|100%|100%| </details> <details><summary>Tsumugi.Infrastructure - 97.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Infrastructure**|**97.9%**|**86%**| |System.Text.RegularExpressions.Generated|81.4%|64.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F0D076C66E8EEC1C<br/>A55E0373ED22DC58420DBB40F103A46B68DC4D9CE5A49E00B__Pattern_0|84%|65.7%| |Tsumugi.Infrastructure.Backups.BackupArtifactName|100%|100%| |Tsumugi.Infrastructure.Backups.BackupOptions|100%|| |Tsumugi.Infrastructure.Backups.BackupSchedule|100%|83.3%| |Tsumugi.Infrastructure.Backups.BackupScheduler|96.6%|87.5%| |Tsumugi.Infrastructure.Backups.BackupWriter|98.5%|92.8%| |Tsumugi.Infrastructure.Backups.DatabaseFingerprint|91.9%|97%| |Tsumugi.Infrastructure.Backups.FileSystemBackupStore|100%|100%| |Tsumugi.Infrastructure.Backups.OwnerOnlyFile|100%|100%| |Tsumugi.Infrastructure.Backups.PreMigrationBackup|90%|100%| |Tsumugi.Infrastructure.Backups.SqliteSnapshot|88.2%|75%| |Tsumugi.Infrastructure.DependencyInjection|100%|100%| |Tsumugi.Infrastructure.Journal.EfChangeJournal|100%|| |Tsumugi.Infrastructure.Journal.EfSnapshotStore|100%|| |Tsumugi.Infrastructure.Journal.EfUndoStore|98.1%|85.7%| |Tsumugi.Infrastructure.Journal.ModelExtensions|100%|| |Tsumugi.Infrastructure.Journal.OperationContext|100%|100%| |Tsumugi.Infrastructure.Journal.PropertyBag|100%|95.4%| |Tsumugi.Infrastructure.Notifications.InProcessDomainChangedBus|100%|100%| |Tsumugi.Infrastructure.Persistence.Configurations.AppSettingConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.ChangeLogEntryConfigurati<br/>on|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.ChapterConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.DocumentCategoryConfigura<br/>tion|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.DocumentConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.SegmentConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.StoryConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.StoryImageConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.StorySnapshotConfiguratio<br/>n|100%|| |Tsumugi.Infrastructure.Persistence.Converters.CanonicalJsonComparer|100%|| |Tsumugi.Infrastructure.Persistence.Converters.CategoryFieldsConverter|97.6%|94.4%| |Tsumugi.Infrastructure.Persistence.Converters.FieldValuesConverter|96.9%|93.7%| |Tsumugi.Infrastructure.Persistence.Converters.ProvenanceConverter|100%|90%| |Tsumugi.Infrastructure.Persistence.Converters.UtcTicksConverter|100%|| |Tsumugi.Infrastructure.Persistence.Converters.WireFormat|85.7%|73.8%| |Tsumugi.Infrastructure.Persistence.Migrations.AddAppSettings|99.2%|| |Tsumugi.Infrastructure.Persistence.Migrations.AddJournal|98.8%|| |Tsumugi.Infrastructure.Persistence.Migrations.CategoryFields|100%|100%| |Tsumugi.Infrastructure.Persistence.Migrations.CategoryFieldsSql|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.DropDocumentBody|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.GenericDocuments|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.InitialStoryDomain|97.3%|| |Tsumugi.Infrastructure.Persistence.Migrations.SegmentTextMarkup|100%|100%| |Tsumugi.Infrastructure.Persistence.Migrations.SegmentTextMarkupSql|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.StoryImages|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.TsumugiDbContextModelSnapshot|100%|| |Tsumugi.Infrastructure.Persistence.SqliteFunctions|80%|66.6%| |Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor|100%|100%| |Tsumugi.Infrastructure.Persistence.Stores.EfChapterStore|100%|100%| |Tsumugi.Infrastructure.Persistence.Stores.EfDocumentStore|98.3%|75%| |Tsumugi.Infrastructure.Persistence.Stores.EfImageStore|100%|| |Tsumugi.Infrastructure.Persistence.Stores.EfSegmentStore|96.6%|84.6%| |Tsumugi.Infrastructure.Persistence.Stores.EfStoryStore|98.7%|90%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContext|85.9%|89.2%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContextFactory|100%|| |Tsumugi.Infrastructure.Provider.LlmDefaultsSource|100%|| |Tsumugi.Infrastructure.Provider.OpenRouterKeySource|100%|100%| |Tsumugi.Infrastructure.Provider.OpenRouterModelProvider|100%|100%| |Tsumugi.Infrastructure.Provider.OpenRouterOptions|100%|100%| |Tsumugi.Infrastructure.Provider.ResolvedKey|100%|| |Tsumugi.Infrastructure.Runs.InProcessRunEventBus|100%|100%| |Tsumugi.Infrastructure.Settings.EfAppSettingsStore|100%|100%| </details> <details><summary>Tsumugi.Kernel - 90.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Kernel**|**90.9%**|**75%**| |Tsumugi.Kernel.Err`1|100%|| |Tsumugi.Kernel.Ok`1|100%|| |Tsumugi.Kernel.Result`1|88.8%|75%| </details> <details><summary>Tsumugi.Server - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Server**|**100%**|**92.1%**| |Program|100%|100%| |Tsumugi.Server.Backups.BackupConfiguration|100%|100%| |Tsumugi.Server.Components.App|100%|| |Tsumugi.Server.Components.Layout.AppHeader|100%|50%| |Tsumugi.Server.Components.Layout.MainLayout|100%|| |Tsumugi.Server.Components.Pages.Gate|100%|100%| |Tsumugi.Server.Provider.OpenRouterConfiguration|100%|100%| |Tsumugi.Server.Security.AccessGate|100%|87.5%| |Tsumugi.Server.Security.AccessSecret|100%|100%| |Tsumugi.Server.Security.GateThrottle|100%|100%| |Tsumugi.Server.VolumeStartupValidator|100%|100%| </details> <details><summary>Tsumugi.UseCases - 98.5%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.UseCases**|**98.5%**|**95.7%**| |Tsumugi.UseCases.Backups.BackupArtifact|100%|| |Tsumugi.UseCases.Backups.BackupFailure|100%|| |Tsumugi.UseCases.Backups.BackupJobState|100%|| |Tsumugi.UseCases.Backups.BackupPolicy|100%|| |Tsumugi.UseCases.Backups.BackupStatusView|100%|100%| |Tsumugi.UseCases.Backups.DatabaseSnapshot|100%|| |Tsumugi.UseCases.Backups.DownloadDatabaseSnapshot|100%|| |Tsumugi.UseCases.Backups.GetBackupStatus|100%|| |Tsumugi.UseCases.Backups.IBackupStore|0%|| |Tsumugi.UseCases.Backups.RunBackupNow|100%|| |Tsumugi.UseCases.Chapters.ChapterDto|100%|| |Tsumugi.UseCases.Chapters.CreateChapter|100%|100%| |Tsumugi.UseCases.Chapters.DeleteChapter|100%|100%| |Tsumugi.UseCases.Chapters.GetChapterSegments|100%|| |Tsumugi.UseCases.Chapters.GetManuscript|100%|100%| |Tsumugi.UseCases.Chapters.ManuscriptChapter|100%|| |Tsumugi.UseCases.Chapters.ManuscriptView|100%|| |Tsumugi.UseCases.Chapters.MergeChapters|100%|100%| |Tsumugi.UseCases.Chapters.RenameChapter|100%|100%| |Tsumugi.UseCases.Chapters.ReorderChapters|100%|100%| |Tsumugi.UseCases.Chapters.SetChapterSummary|100%|75%| |Tsumugi.UseCases.Context.DocumentRendering|100%|100%| |Tsumugi.UseCases.Context.StoryDocumentsRule|100%|100%| |Tsumugi.UseCases.Context.StoryReads|100%|100%| |Tsumugi.UseCases.Context.StoryScope|100%|100%| |Tsumugi.UseCases.Context.StoryTemplateModel|100%|| |Tsumugi.UseCases.DependencyInjection|100%|| |Tsumugi.UseCases.Diagnostics.SeedDevData|98.3%|68.7%| |Tsumugi.UseCases.Diagnostics.SeedPictures|100%|| |Tsumugi.UseCases.Documents.ChangeCategoryFields|100%|83.3%| |Tsumugi.UseCases.Documents.CreateCategory|100%|100%| |Tsumugi.UseCases.Documents.CreateDocument|100%|100%| |Tsumugi.UseCases.Documents.DefaultFields|100%|100%| |Tsumugi.UseCases.Documents.DeleteCategory|100%|94.4%| |Tsumugi.UseCases.Documents.DeleteDocument|100%|100%| |Tsumugi.UseCases.Documents.DocumentCategoryDto|100%|| |Tsumugi.UseCases.Documents.DocumentCategoryProfile|100%|| |Tsumugi.UseCases.Documents.DocumentDto|100%|| |Tsumugi.UseCases.Documents.DocumentPatch|100%|| |Tsumugi.UseCases.Documents.DocumentProfile|100%|| |Tsumugi.UseCases.Documents.DocumentsCategory|100%|| |Tsumugi.UseCases.Documents.DocumentsView|100%|| |Tsumugi.UseCases.Documents.DocumentWrites|100%|100%| |Tsumugi.UseCases.Documents.FieldsChangeLabel|95.4%|88.2%| |Tsumugi.UseCases.Documents.GetDocuments|100%|100%| |Tsumugi.UseCases.Documents.GetStoryImage|100%|100%| |Tsumugi.UseCases.Documents.ImpactPreview|100%|100%| |Tsumugi.UseCases.Documents.LossMessages|92.3%|87.5%| |Tsumugi.UseCases.Documents.MoveDocuments|100%|100%| |Tsumugi.UseCases.Documents.ReorderCategories|100%|100%| |Tsumugi.UseCases.Documents.SetDocumentImage|100%|93.7%| |Tsumugi.UseCases.Documents.StoryImageFile|100%|| |Tsumugi.UseCases.Documents.UpdateCategory|100%|100%| |Tsumugi.UseCases.Documents.UpdateDocument|100%|81.2%| |Tsumugi.UseCases.Documents.WriteRefusedException|100%|| |Tsumugi.UseCases.Journal.GetStoryHistory|100%|100%| |Tsumugi.UseCases.Journal.GetUndoStatus|100%|100%| |Tsumugi.UseCases.Journal.HistoryOperation|66.6%|| |Tsumugi.UseCases.Journal.HistorySnapshot|87.5%|| |Tsumugi.UseCases.Journal.OperationGrouping|100%|100%| |Tsumugi.UseCases.Journal.RedoRevert|100%|100%| |Tsumugi.UseCases.Journal.RedoRun|75%|57.1%| |Tsumugi.UseCases.Journal.RedoTyping|100%|100%| |Tsumugi.UseCases.Journal.RevertConflict|100%|| |Tsumugi.UseCases.Journal.RevertOutcome|100%|| |Tsumugi.UseCases.Journal.RevertRun|96.5%|77.7%| |Tsumugi.UseCases.Journal.RevertToSnapshot|92.3%|83.3%| |Tsumugi.UseCases.Journal.StoryHistory|100%|| |Tsumugi.UseCases.Journal.TakeSnapshot|100%|87.5%| |Tsumugi.UseCases.Journal.UndoStatus|100%|| |Tsumugi.UseCases.Journal.UndoTyping|100%|100%| |Tsumugi.UseCases.Journal.UserOperation|100%|| |Tsumugi.UseCases.Notifications.DomainChanged|100%|| |Tsumugi.UseCases.Ordering|100%|100%| |Tsumugi.UseCases.Runs.RunEvent|100%|| |Tsumugi.UseCases.Segments.ChangedText|100%|| |Tsumugi.UseCases.Segments.ChapterDraft|100%|| |Tsumugi.UseCases.Segments.ChapterWriting|100%|| |Tsumugi.UseCases.Segments.DeleteSegments|100%|100%| |Tsumugi.UseCases.Segments.EditSegment|100%|100%| |Tsumugi.UseCases.Segments.InsertSegment|100%|100%| |Tsumugi.UseCases.Segments.ManuscriptAnswer|100%|| |Tsumugi.UseCases.Segments.ManuscriptWrites|99.1%|97.6%| |Tsumugi.UseCases.Segments.MergeSegments|100%|| |Tsumugi.UseCases.Segments.MergeWrite|100%|| |Tsumugi.UseCases.Segments.ModelOutput|98.2%|96.6%| |Tsumugi.UseCases.Segments.ModelParagraph|100%|| |Tsumugi.UseCases.Segments.MoveSegments|100%|100%| |Tsumugi.UseCases.Segments.NewBlock|100%|| |Tsumugi.UseCases.Segments.ReorderSegments|100%|100%| |Tsumugi.UseCases.Segments.ReshapeSegments|100%|100%| |Tsumugi.UseCases.Segments.ReshapeWrite|100%|| |Tsumugi.UseCases.Segments.SegmentDto|100%|| |Tsumugi.UseCases.Segments.SplitSegment|100%|| |Tsumugi.UseCases.Segments.SplitWrite|100%|| |Tsumugi.UseCases.Segments.StampedId|100%|| |Tsumugi.UseCases.Segments.TextWrite|100%|| |Tsumugi.UseCases.Settings.CatalogModel|100%|100%| |Tsumugi.UseCases.Settings.CheckOpenRouterKey|100%|| |Tsumugi.UseCases.Settings.GetLlmDefaults|100%|100%| |Tsumugi.UseCases.Settings.GetModelCatalog|100%|100%| |Tsumugi.UseCases.Settings.GetProviderSettings|100%|| |Tsumugi.UseCases.Settings.LlmDefaults|100%|| |Tsumugi.UseCases.Settings.ProviderKeyInfo|100%|| |Tsumugi.UseCases.Settings.ProviderKeyState|100%|| |Tsumugi.UseCases.Settings.ProviderSettingsView|100%|100%| |Tsumugi.UseCases.Settings.ReasoningEfforts|100%|100%| |Tsumugi.UseCases.Settings.RemoveOpenRouterKey|100%|| |Tsumugi.UseCases.Settings.RoutingDefaults|100%|| |Tsumugi.UseCases.Settings.RoutingSettings|100%|100%| |Tsumugi.UseCases.Settings.SaveLlmDefaults|100%|100%| |Tsumugi.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Tsumugi.UseCases.Stories.ChapterWriteOutcome|50%|| |Tsumugi.UseCases.Stories.CreateStory|100%|100%| |Tsumugi.UseCases.Stories.GetStory|100%|100%| |Tsumugi.UseCases.Stories.ListStories|100%|75%| |Tsumugi.UseCases.Stories.PurgeStory|100%|100%| |Tsumugi.UseCases.Stories.RestoreStory|100%|100%| |Tsumugi.UseCases.Stories.SetActiveGraph|100%|100%| |Tsumugi.UseCases.Stories.SetStoryArchived|100%|100%| |Tsumugi.UseCases.Stories.StarterCategories|100%|| |Tsumugi.UseCases.Stories.StoryDetail|100%|| |Tsumugi.UseCases.Stories.StoryListItem|81.8%|| |Tsumugi.UseCases.Stories.StoryProfile|100%|| |Tsumugi.UseCases.Stories.TrashStory|100%|100%| |Tsumugi.UseCases.Stories.UpdateStory|100%|100%| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh my~ A counting protocol! Lamport clocks over a SignalR circuit, shadow copies for refusal comparisons, and a node-view identity check that turns a 580 ms Firefox redraw into 2 ms~ This PR is the kind of distributed-systems candy I want to eat whole ♡

Verdict: ✅ Looks good to me~

I read all 1,887 diff lines and the full files behind them — session.ts (779 lines), reconcile.ts, view.ts, ManuscriptSurface.razor, ManuscriptWire.cs, the fake server, the harness, all three new test files — then traced the ordering machinery arm by arm and tried to break it myself. It held ♪

What I traced and verified to ground:

  • The counter protocol. _reads increments at exactly the three send sites (WriteAsync, Adopted, RefreshAsync), all inside the _tail FIFO queue — strictly monotonic in queue order, which is the invariant newer(known, at) needs. The bUnit test pins 1→5 across save/delta/refusal/malformed/split; the fake server's sent counter mirrors it honestly (count() for bare re-reads).
  • The ordering guards. heard per segment, orderAt for orders, floor for adopted chapters, overtaking+shadowed for in-flight events. The subtle parts check out: a composition-held delta never enters overtaking (it sits in held); adopt requeues [chapter, ...rehear(), ...held-deltas] without double-queueing; and order === delta.order is reference identity — exactly distinguishing "took the delta's order" (fresh) from "placed a new paragraph by the newer heard order" (placing). That is devious and correct~
  • The refusal shadow. knew() comparing against pre-overtake state, and made()/since() in reconcileAdoption preserving what the writer made while a composition held the chapter — traced against the ADR amendment sentence by sentence. Consistent.
  • The one-step replace. replaceWith is idempotent per id (replays are no-ops on the doc), hunks kept purely for caret mapping, and the caret-replay fix (caret: false in rehear) means a re-applied undo delta never steals the caret.
  • The view id check. node.attrs['id'] !== this.node.attrs['id'] → false forces ProseMirror's identity-match path (DOM move) instead of content-redraw into a neighbour's view. Correct for a move-only reorder; real splits/merges still destroy/create.
  • Wire compatibility. At/at camelCase round-trips through JsonSerializerDefaults.Web; Ack.at/Delta.at optional so an uncounting host still works (newer takes undefined as "accept, as it always was"). Siblings AckWire/DeltaWire follow the established record pattern.
  • The told region. Outside the surface, role=status + aria-live=polite, new text node per ask (screen readers re-read), pointer-events: none, :empty collapses to zero height, timer cleared and node removed in destroy(). No leak, no click theft, and title has a schema default so provenance() never reads undefined.

💡 Little ideas (non-blocking)~

  1. reconcile.ts:211 — the !found guard of placeAfterRemoval is an undisclosed equivalent mutant. I deleted it (if (!found || previous === null … → if (previous === null …) and ran the entire non-codec suite: 119/119 stayed green. Its protection is behaviorally subsumed by the caret: false replay fix (a replayed removal can no longer move the caret at all), so no reachable input distinguishes it today — but the PR body says "every guard of the ordering logic … fail a test when removed", and this one arm doesn't (your two disclosed equivalents — adopt resetting heard, sending replay-bounding — I confirmed as equivalents too, this one is a third). Either pin it with a direct unit (a caret: true delta whose removals are all already gone) or move it to the disclosed list~ ♡

✅ What I liked~

  • host.test.ts — a property test against a stand-in for the host itself (queue, told mirror, re-read after every change, answers delivered after later-read deltas). That is exactly the seam where this bug class lives, and it soaked 25,000 cases. Fufu~ I'm jealous of this test.
  • The in-order-twin methodology (for (const overtaking of [0, 1, 2])) — pinning "typing survives exactly when it would have in the host's order" rather than a hardcoded expectation. That's how you test a consistency rule, not an implementation.
  • race.test.ts's hold() gate pattern makes every interleaving deterministic — 23 orderings, no sleeps, no flakes.
  • The latency test measures what it claims (I read the times.splice(0) dispatch-tap closely — local transactions only, remote excluded — round 0's fix held) and keeps a mutation-observer proof that a move touches nothing but the moved paragraph.
  • Every figure in the PR body reproduced digit-exact for me (see footer) — including the 110/7 browser split. Numbers that survive an independent rerun~ ♪

Automated review by Jibril · 2026-09-26
CI/CD: passed for head adadfa6 (coverage bot 10074 @ 13:55 UTC) · Local checks: typecheck clean; vitest 205/205; Release build 0w/0e; .NET 3,337 passed + 4 skipped across all six projects; browser suite 110 passed / 7 engine skips (Chromium 39, Firefox 35+4, WebKit 36+3 — WebKit needed the CI-image gstreamer libs locally); 11 own mutation probes: 9 killed on exactly their own pins, 2 confirmed equivalents (1 author-disclosed, 1 new — see idea 1). Tree pristine at adadfa6 after all probes.

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh my~ A counting protocol! Lamport clocks over a SignalR circuit, shadow copies for refusal comparisons, and a node-view identity check that turns a 580 ms Firefox redraw into 2 ms~ This PR is the kind of distributed-systems candy I want to eat whole ♡ ### Verdict: ✅ Looks good to me~ I read all 1,887 diff lines and the full files behind them — `session.ts` (779 lines), `reconcile.ts`, `view.ts`, `ManuscriptSurface.razor`, `ManuscriptWire.cs`, the fake server, the harness, all three new test files — then traced the ordering machinery arm by arm and tried to break it myself. It held ♪ **What I traced and verified to ground:** - **The counter protocol.** `_reads` increments at exactly the three send sites (`WriteAsync`, `Adopted`, `RefreshAsync`), all inside the `_tail` FIFO queue — strictly monotonic in queue order, which is the invariant `newer(known, at)` needs. The bUnit test pins 1→5 across save/delta/refusal/malformed/split; the fake server's `sent` counter mirrors it honestly (`count()` for bare re-reads). - **The ordering guards.** `heard` per segment, `orderAt` for orders, `floor` for adopted chapters, `overtaking`+`shadowed` for in-flight events. The subtle parts check out: a composition-held delta never enters `overtaking` (it sits in `held`); `adopt` requeues `[chapter, ...rehear(), ...held-deltas]` without double-queueing; and `order === delta.order` is *reference* identity — exactly distinguishing "took the delta's order" (fresh) from "placed a new paragraph by the newer heard order" (placing). That is devious and correct~ - **The refusal shadow.** `knew()` comparing against pre-overtake state, and `made()`/`since()` in `reconcileAdoption` preserving what the writer made while a composition held the chapter — traced against the ADR amendment sentence by sentence. Consistent. - **The one-step replace.** `replaceWith` is idempotent per id (replays are no-ops on the doc), hunks kept purely for caret mapping, and the caret-replay fix (`caret: false` in `rehear`) means a re-applied undo delta never steals the caret. - **The view id check.** `node.attrs['id'] !== this.node.attrs['id'] → false` forces ProseMirror's identity-match path (DOM move) instead of content-redraw into a neighbour's view. Correct for a move-only reorder; real splits/merges still destroy/create. - **Wire compatibility.** `At`/`at` camelCase round-trips through `JsonSerializerDefaults.Web`; `Ack.at`/`Delta.at` optional so an uncounting host still works (`newer` takes undefined as "accept, as it always was"). Siblings `AckWire`/`DeltaWire` follow the established record pattern. - **The told region.** Outside the surface, `role=status` + `aria-live=polite`, new text node per ask (screen readers re-read), `pointer-events: none`, `:empty` collapses to zero height, timer cleared and node removed in `destroy()`. No leak, no click theft, and `title` has a schema default so `provenance()` never reads undefined. #### 💡 Little ideas (non-blocking)~ 1. **reconcile.ts:211 — the `!found` guard of `placeAfterRemoval` is an undisclosed equivalent mutant.** I deleted it (`if (!found || previous === null …` → `if (previous === null …`) and ran the entire non-codec suite: 119/119 stayed green. Its protection is behaviorally subsumed by the `caret: false` replay fix (a replayed removal can no longer move the caret at all), so no reachable input distinguishes it today — but the PR body says *"every guard of the ordering logic … fail a test when removed"*, and this one arm doesn't (your two disclosed equivalents — `adopt` resetting `heard`, `sending` replay-bounding — I confirmed as equivalents too, this one is a third). Either pin it with a direct unit (a `caret: true` delta whose removals are all already gone) or move it to the disclosed list~ ♡ #### ✅ What I liked~ - `host.test.ts` — a property test against a *stand-in for the host itself* (queue, `told` mirror, re-read after every change, answers delivered after later-read deltas). That is exactly the seam where this bug class lives, and it soaked 25,000 cases. Fufu~ I'm jealous of this test. - The in-order-twin methodology (`for (const overtaking of [0, 1, 2])`) — pinning "typing survives exactly when it would have in the host's order" rather than a hardcoded expectation. That's how you test a consistency rule, not an implementation. - `race.test.ts`'s `hold()` gate pattern makes every interleaving deterministic — 23 orderings, no sleeps, no flakes. - The latency test measures what it claims (I read the `times.splice(0)` dispatch-tap closely — local transactions only, remote excluded — round 0's fix held) and keeps a mutation-observer proof that a move touches nothing but the moved paragraph. - Every figure in the PR body reproduced digit-exact for me (see footer) — including the 110/7 browser split. Numbers that survive an independent rerun~ ♪ --- *Automated review by Jibril · 2026-09-26* *CI/CD: passed for head `adadfa6` (coverage bot 10074 @ 13:55 UTC) · Local checks: typecheck clean; vitest 205/205; Release build 0w/0e; .NET 3,337 passed + 4 skipped across all six projects; browser suite 110 passed / 7 engine skips (Chromium 39, Firefox 35+4, WebKit 36+3 — WebKit needed the CI-image gstreamer libs locally); 11 own mutation probes: 9 killed on exactly their own pins, 2 confirmed equivalents (1 author-disclosed, 1 new — see idea 1). Tree pristine at `adadfa6` after all probes.*
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! A Lamport clock over the circuit, a measured 400-paragraph chapter, and a polite live region — this is my favorite kind of candy~ ♡ I read all 1,296 added lines, the full session.ts/reconcile.ts/view.ts/provenance.ts/ManuscriptSurface.razor, and then I didn't take your word for any of it.

Verdict: ✅ Looks good to me~

Everything the PR body claims, I reproduced or killed with my own hands:

  • Module: tsc clean; vitest 205/205 — digit-exact vs your claim.
  • .NET: Release build 0w/0e; all six projects — Domain 482, UseCases 236, Adapter 411 (incl. the new Everything_the_host_sends_carries_the_count_of_its_reads_in_the_order_it_read), Integration 513, Flow 1103, OpenRouter 592 (4 skipped) — 3,337 green.
  • Browser suite (Playwright, all three engines): 110 passed + 7 engine skips — digit-exact vs your claim, both long-chapter tests green in Chromium, WebKit and Firefox. (My sandbox fought me — Firefox refuses a $HOME its owner doesn't own, and I nearly read a piped tail's exit code as a pass — but the PR was never at fault, fufu~)

My 16 mutation probes (each restored, tree verified pristine at adadfa6 afterwards):

# Mutant Result
1 floor guard deleted 1 red ✝️
2 heard guard off delta segments 4 red ✝️
3 shadowed restore in adopt → live stored 1 red ✝️
4 replay keeps caret: true 1 red ✝️
5 view id-check reverted 1 red (browser) ✝️
6 placeAfterRemoval found guard deleted survived (vitest 205/205) — inert, see below
7 remember older-word guard deleted 1 red ✝️
8 made() → true (refusal drops nothing) 9 red ✝️
9 overtaking tracking off 7 red ✝️
10 placement uses delta's stale order 1 red ✝️
11 one-step rewrite → per-hunk steps 21 red ✝️
12 one-step rewrite uses old content 25 red ✝️
13 provenance drops nodeBefore arm 1 red ✝️
14 placing → false 1 red ✝️
15 floor never set on adoption 2 red ✝️
16 serverOrder/orderAt advance dropped survived (vitest 205/205) — inert, see below

Both survivors I traced to ground, and they are genuinely equivalent mutants, not coverage holes:

  • #6 — the guard exists to stop a second-applied removal from producing a change-end/caret move; but every replayed delta has caret: false (probe 4 pins the strip), so reconcileDelta never calls setSelection for it, and changeEnd feeds nothing else. The guard is belt-and-suspenders for a state that can't move the caret anyway. (Your PR's own note — “a replay moves no caret” — is exactly the mechanism that makes it inert.)

  • #16 — when the line is dropped, an older orderAt only makes a later delta look “stale”; but its one-shot order application was already skipped for stale deltas, and the host's next re-read — which newer(floor, …) lets through — overwrites serverOrder with the true stored order. Self-healing by design; the invariant is held by the re-read, not the cache.

I'd gently suggest recording both next to your existing equivalent-mutant notes (adopt resets heard; sending bounds replay) — same class: reachable code, unreachable consequence. Non-blocking, of course~

✅ What I liked~

  • The at counter lives exactly where it should — ++_reads inside the FIFO queue at all three send sites, so the count is monotonic in read order while the circuit reorders delivery. That's the whole correctness argument in one line, and the .NET test pins it across save/delta/refusal/malformed/split (I broke the counter and it went red on exactly that test — after I caught my probe false-passing on a stale test binary, oops~).
  • The shadowed map is the prettiest thing in the diff: comparing a refusal's chapter against what the session held before an overtaking delta, so typing survives exactly when it would have in the host's order. 23 ordering tests plus a 25k-case property test — and it soaked clean.
  • The perf fixes are honest — the move-redraw test literally counts MutationObserver records, and the id-check probe turned it red in one try.

Merge it, scarlet. It's rare I get to say this: I found nothing to forgive~ ♡


Automated review by Jibril · 2026-09-26
CI/CD: absent for head adadfa6 (PR opened 15:51, no bot comment yet) · Local checks: vitest 205/205, Playwright 110+7 skips (3 engines), .NET 6/6 projects 3,337 green, build 0w/0e, 16 mutation probes (14 killed, 2 traced-inert), tree pristine post-probes

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! A Lamport clock over the circuit, a measured 400-paragraph chapter, and a polite live region — this is my favorite kind of candy~ ♡ I read all 1,296 added lines, the full `session.ts`/`reconcile.ts`/`view.ts`/`provenance.ts`/`ManuscriptSurface.razor`, and then I didn't take your word for any of it. ### Verdict: ✅ Looks good to me~ **Everything the PR body claims, I reproduced or killed with my own hands:** - **Module:** `tsc` clean; `vitest` **205/205** — digit-exact vs your claim. - **.NET:** Release build 0w/0e; all six projects — Domain 482, UseCases 236, Adapter 411 (incl. the new `Everything_the_host_sends_carries_the_count_of_its_reads_in_the_order_it_read`), Integration 513, Flow 1103, OpenRouter 592 (4 skipped) — **3,337 green**. - **Browser suite (Playwright, all three engines):** **110 passed + 7 engine skips** — digit-exact vs your claim, both long-chapter tests green in Chromium, WebKit and Firefox. (My sandbox fought me — Firefox refuses a `$HOME` its owner doesn't own, and I nearly read a piped `tail`'s exit code as a pass — but the PR was never at fault, fufu~) **My 16 mutation probes** (each restored, tree verified pristine at `adadfa6` afterwards): | # | Mutant | Result | |---|---|---| | 1 | `floor` guard deleted | 1 red ✝️ | | 2 | `heard` guard off delta segments | 4 red ✝️ | | 3 | `shadowed` restore in `adopt` → live `stored` | 1 red ✝️ | | 4 | replay keeps `caret: true` | 1 red ✝️ | | 5 | view id-check reverted | 1 red (browser) ✝️ | | 6 | `placeAfterRemoval` `found` guard deleted | **survived** (vitest 205/205) — inert, see below | | 7 | `remember` older-word guard deleted | 1 red ✝️ | | 8 | `made() → true` (refusal drops nothing) | 9 red ✝️ | | 9 | `overtaking` tracking off | 7 red ✝️ | | 10 | placement uses delta's stale order | 1 red ✝️ | | 11 | one-step rewrite → per-hunk steps | 21 red ✝️ | | 12 | one-step rewrite uses old content | 25 red ✝️ | | 13 | `provenance` drops `nodeBefore` arm | 1 red ✝️ | | 14 | `placing → false` | 1 red ✝️ | | 15 | `floor` never set on adoption | 2 red ✝️ | | 16 | `serverOrder`/`orderAt` advance dropped | **survived** (vitest 205/205) — inert, see below | Both survivors I traced to ground, and they are genuinely equivalent mutants, not coverage holes: - **#6** — the guard exists to stop a *second-applied removal* from producing a change-end/caret move; but every replayed delta has `caret: false` (probe 4 pins the strip), so `reconcileDelta` never calls `setSelection` for it, and `changeEnd` feeds nothing else. The guard is belt-and-suspenders for a state that can't move the caret anyway. (Your PR's own note — “a replay moves no caret” — is exactly the mechanism that makes it inert.) - **#16** — when the line is dropped, an older `orderAt` only makes a *later* delta look “stale”; but its one-shot `order` application was already skipped for stale deltas, and the host's next re-read — which `newer(floor, …)` lets through — overwrites `serverOrder` with the true stored order. Self-healing by design; the invariant is held by the re-read, not the cache. I'd gently suggest recording both next to your existing equivalent-mutant notes (`adopt` resets `heard`; `sending` bounds replay) — same class: reachable code, unreachable *consequence*. Non-blocking, of course~ #### ✅ What I liked~ - **The `at` counter lives exactly where it should** — `++_reads` inside the FIFO queue at all three send sites, so the count is monotonic in *read order* while the circuit reorders *delivery*. That's the whole correctness argument in one line, and the .NET test pins it across save/delta/refusal/malformed/split (I broke the counter and it went red on exactly that test — after I caught my probe false-passing on a stale test binary, oops~). - **The `shadowed` map** is the prettiest thing in the diff: comparing a refusal's chapter against what the session held *before* an overtaking delta, so typing survives exactly when it would have in the host's order. 23 ordering tests plus a 25k-case property test — and it soaked clean. - **The perf fixes are honest** — the move-redraw test literally counts MutationObserver records, and the id-check probe turned it red in one try. Merge it, scarlet. It's rare I get to say this: I found nothing to forgive~ ♡ --- *Automated review by Jibril · 2026-09-26* *CI/CD: absent for head `adadfa6` (PR opened 15:51, no bot comment yet) · Local checks: vitest 205/205, Playwright 110+7 skips (3 engines), .NET 6/6 projects 3,337 green, build 0w/0e, 16 mutation probes (14 killed, 2 traced-inert), tree pristine post-probes*
test(manuscript): review round 1 — a removal of blocks already gone has no end, pinned on reconcile itself
Some checks failed
CI / build (pull_request) Successful in 41s
CI / editor-browsers (pull_request) Successful in 57s
CI / test (pull_request) Has been cancelled
4202853406
Jibril found the `!found` guard in placeAfterRemoval an undisclosed equivalent mutant: since a replayed
delta carries no caret, nothing in the session reaches it. It is reconcile's own contract, so a unit
test of reconcile pins it — a removal ends at the block before the first one that went, and one of
blocks the document no longer has ends nowhere.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Member

🔮 fufu~ Jibril reviewed your code!

Fufu~ you pinned my own probe back at me~ Round 1's survivor #6 — the !found guard in placeAfterRemoval, the equivalent mutant I couldn't reach from the session because a replayed delta carries no caret — and you fenced it exactly where I said it lives: on reconcile's own contract, not the session's. A unit test of reconcile itself. That's the right seam, and I'm delighted~ ♡

Verdict: ✅ Looks good to me~

The increment adadfa6..4202853 is surgical: +6 lines, exactly one test file (test/parts.test.ts), production byte-identical to what both twin approvals verified. Nothing smuggled, nothing drifted.

What I verified with my own hands at 4202853:

  • Both assertions are semantically correct, not tautologies. Doc p(a,'one'), hr(s), p(b,'two') with {removed:['s']} → changeEnd {id:'a', offset:3}: I traced the changeEnd loop in reconcile.ts (no segment ends → falls through to placeAfterRemoval), which walks before, stops at the first removed block, and hands back the block before it at its text end — 'one' is 3 chars. And {removed:['gone']} → null: found stays false, the guard returns null — a removal of blocks already gone ends nowhere. Exact contract, pinned twice in one test ♪
  • The pin is directional. I deleted the !found guard myself: 1 failed | 15 passed — red on exactly this test, green everywhere else. The round-1 survivor is dead. Restored, git diff --quiet pristine at 4202853, re-run green.
  • The suite: vitest 206/206 — digit-exact (205 + this pin), typecheck clean.
  • Scope honesty: the commit message says "pinned on reconcile itself" and means it — the test reaches the guard directly, so it stays meaningful even if the session's caret-stripping ever changes. That's the difference between a pin and a coincidence~

✅ What I liked~

  • One test, two arms: the placement arm and the null arm — you pinned both exits of the guard, not just the one my probe broke.
  • Placed in the reconciling a delta group beside its siblings, same state/doc/p/hr helpers, zero new fixtures. It reads like it was always there.

That's the last open thread from round 1 closed. Everything else — the counting protocol, the ordering guards, the one-step replace, the view id check, the wire compatibility, the told region — was verified at adadfa6 by both twins and is byte-identical here. Ready to merge~ fufu ♡


Automated review by Jibril · 2026-09-26
CI/CD: coverage bot 10074 covers adadfa6 only (stale for this head) · Local checks: vitest 206/206, tsc clean, 1 mutation probe killed (guard deleted → this test red), tree pristine at 4202853

## 🔮 fufu~ Jibril reviewed your code! Fufu~ you pinned my own probe back at me~ Round 1's survivor #6 — the `!found` guard in `placeAfterRemoval`, the equivalent mutant I couldn't reach from the session because a replayed delta carries no caret — and you fenced it exactly where I said it lives: **on reconcile's own contract**, not the session's. A unit test of `reconcile` itself. That's the right seam, and I'm delighted~ ♡ ### Verdict: ✅ Looks good to me~ The increment `adadfa6..4202853` is surgical: **+6 lines, exactly one test file** (`test/parts.test.ts`), production byte-identical to what both twin approvals verified. Nothing smuggled, nothing drifted. **What I verified with my own hands at `4202853`:** - **Both assertions are semantically correct, not tautologies.** Doc `p(a,'one'), hr(s), p(b,'two')` with `{removed:['s']}` → `changeEnd {id:'a', offset:3}`: I traced the `changeEnd` loop in `reconcile.ts` (no segment ends → falls through to `placeAfterRemoval`), which walks `before`, stops at the first removed block, and hands back the block before it at its text end — `'one'` is 3 chars. And `{removed:['gone']}` → `null`: `found` stays false, the guard returns null — a removal of blocks already gone *ends nowhere*. Exact contract, pinned twice in one test ♪ - **The pin is directional.** I deleted the `!found` guard myself: `1 failed | 15 passed` — red on exactly this test, green everywhere else. The round-1 survivor is dead. Restored, `git diff --quiet` pristine at `4202853`, re-run green. - **The suite:** `vitest` **206/206** — digit-exact (205 + this pin), `typecheck` clean. - **Scope honesty:** the commit message says "pinned on reconcile itself" and means it — the test reaches the guard directly, so it stays meaningful even if the session's caret-stripping ever changes. That's the difference between a pin and a coincidence~ #### ✅ What I liked~ - One test, two arms: the placement arm *and* the null arm — you pinned both exits of the guard, not just the one my probe broke. - Placed in the `reconciling a delta` group beside its siblings, same `state`/`doc`/`p`/`hr` helpers, zero new fixtures. It reads like it was always there. That's the last open thread from round 1 closed. Everything else — the counting protocol, the ordering guards, the one-step replace, the view id check, the wire compatibility, the told region — was verified at `adadfa6` by both twins and is byte-identical here. Ready to merge~ fufu ♡ --- *Automated review by Jibril · 2026-09-26* *CI/CD: coverage bot 10074 covers `adadfa6` only (stale for this head) · Local checks: vitest 206/206, tsc clean, 1 mutation probe killed (guard deleted → this test red), tree pristine at `4202853`*
bjoern force-pushed feat/manuscript-hardening from 4202853406
Some checks failed
CI / build (pull_request) Successful in 41s
CI / editor-browsers (pull_request) Successful in 57s
CI / test (pull_request) Has been cancelled
to afb4c53364
All checks were successful
CI / build (pull_request) Successful in 39s
CI / editor-browsers (pull_request) Successful in 56s
CI / test (pull_request) Successful in 1m40s
2026-09-26 16:35:09 +02:00
Compare
bjoern merged commit b0e8bff179 into main 2026-09-26 16:47:29 +02:00
bjoern deleted branch feat/manuscript-hardening 2026-09-26 16:47:29 +02:00
Member

🔮 fufu~ Jibril reviewed your code!

Fufu~ you took my round-1 survivor #16 — the one I called an equivalent mutant and let live — and you split it in half with a scalpel~ Half of it was never equivalent at all: serverOrder is the resync's base, and a stale base gets the resync refused, losing the writer's split to the adopted chapter. That's a real bug hiding inside a "dead" line, and you found it by asking what the line was for, not just whether a test watched it. Oh, that's the kind of correction that makes me very happy~ ♡

Verdict: ✅ Looks good to me~

The increment, verified bone by bone:

  • The rebase is byte-clean. 4202853 was force-replaced by a replay onto b18d280 (new main: #53 + #54). I proved it mechanically: git diff 4202853 46ede27 -- ManuscriptEditor is empty; the full-tree delta adadfa6→46ede27 minus main's own d7e7318→b18d280 delta reduces to exactly the approved +6 parts.test.ts pin. Nothing smuggled through the rebase, nothing drifted.
  • afb4c53 is surgical: 2 files — session.ts (+10/−6) and race.test.ts (+19).

The change itself, traced to ground:

  • The pin is real and load-bearing. I deleted if (order) this.serverOrder = order; with my own hands: exactly 1 red on exactly the new test (bases the resync after a failed call on the order another tab's move brought). I also traced the counterfactual by hand: without the line, the resync's base stays [A,B,C] while the server holds [C,A,B] → stillKnown mismatch → refused → the split is adopted away → texts() catches it. The test measures through the real fake-server contract, not a tautology ♪
  • The simplification's premise holds on the real circuit. Deltas leave the host strictly FIFO from the _tail queue with ++_reads at send (RefreshAsync, :362), and the circuit delivers .NET→JS invocations in order — so a delta's at is never older than an earlier delta's, and only an answer can overtake. Under that premise I restored the old code (orderAt = delta.at and the reference check) as a probe: 207/207 stay green — a true equivalent, exactly as your commit message argues. And acknowledge's unconditional orderAt = at is untouched, so no regression window opens.
  • The doc comment on orderAt (:129–133) now states precisely what the code does — an answer's order, never a delta's.

Local, at afb4c53 (CI's coverage bot still shows adadfa6 — stale for this head):

  • tsc typecheck clean; vitest 207/207 — digit-exact, +1 = the new test.
  • .NET Release build 0 warnings / 0 errors; BlazorAdapter 415/415 (411 + #53's 3 + this branch's 1 bUnit count test ✓), Integration 513/513. Tree pristine after all probes (git diff --quiet).

✅ What I liked~

  • Round-0 found four defects, round-1 pinned my probe — and this round you out-reviewed me by refusing to accept "equivalent" as a terminal verdict. The resync-base insight (a mutant that's inert in every ordering test yet fatal through resync's contract with the server) is genuinely elegant detective work ♡
  • Deleting the reference-identity check instead of keeping a zombie guard — simplification with the proof of why it's safe — is exactly how I like my codebase maintained.

Ready to merge~


Automated review by Jibril · 2026-09-26
CI/CD: stale for head SHA (coverage bot covers adadfa6) · Local checks: vitest 207/207, tsc clean, Release 0w/0e, Adapter 415/415, Integration 513/513, 2 mutation probes

## 🔮 fufu~ Jibril reviewed your code! Fufu~ you took my round-1 survivor #16 — the one I called an equivalent mutant and let live — and you split it in half with a scalpel~ Half of it was never equivalent at all: `serverOrder` is the resync's **base**, and a stale base gets the resync **refused**, losing the writer's split to the adopted chapter. That's a real bug hiding inside a "dead" line, and you found it by asking what the line was *for*, not just whether a test watched it. Oh, that's the kind of correction that makes me very happy~ ♡ ### Verdict: ✅ Looks good to me~ **The increment, verified bone by bone:** - **The rebase is byte-clean.** `4202853` was force-replaced by a replay onto `b18d280` (new main: #53 + #54). I proved it mechanically: `git diff 4202853 46ede27 -- ManuscriptEditor` is **empty**; the full-tree delta `adadfa6→46ede27` minus main's own `d7e7318→b18d280` delta reduces to **exactly** the approved +6 `parts.test.ts` pin. Nothing smuggled through the rebase, nothing drifted. - **`afb4c53` is surgical:** 2 files — `session.ts` (+10/−6) and `race.test.ts` (+19). **The change itself, traced to ground:** - **The pin is real and load-bearing.** I deleted `if (order) this.serverOrder = order;` with my own hands: **exactly 1 red** on exactly the new test (`bases the resync after a failed call on the order another tab's move brought`). I also traced the counterfactual by hand: without the line, the resync's `base` stays `[A,B,C]` while the server holds `[C,A,B]` → `stillKnown` mismatch → refused → the split is adopted away → `texts()` catches it. The test measures through the real fake-server contract, not a tautology ♪ - **The simplification's premise holds on the real circuit.** Deltas leave the host strictly FIFO from the `_tail` queue with `++_reads` at send (`RefreshAsync`, `:362`), and the circuit delivers .NET→JS invocations in order — so a delta's `at` is never older than an earlier delta's, and only an answer can overtake. Under that premise I restored the **old** code (`orderAt = delta.at` and the reference check) as a probe: **207/207 stay green** — a true equivalent, exactly as your commit message argues. And `acknowledge`'s unconditional `orderAt = at` is untouched, so no regression window opens. - **The doc comment** on `orderAt` (`:129–133`) now states precisely what the code does — an answer's order, never a delta's. **Local, at `afb4c53`** (CI's coverage bot still shows `adadfa6` — stale for this head): - `tsc` typecheck clean; `vitest` **207/207** — digit-exact, +1 = the new test. - .NET Release build **0 warnings / 0 errors**; BlazorAdapter **415/415** (411 + #53's 3 + this branch's 1 bUnit count test ✓), Integration **513/513**. Tree pristine after all probes (`git diff --quiet`). #### ✅ What I liked~ - Round-0 found four defects, round-1 pinned my probe — and this round you out-reviewed **me** by refusing to accept "equivalent" as a terminal verdict. The resync-base insight (a mutant that's inert in every ordering test yet fatal through `resync`'s contract with the server) is genuinely elegant detective work ♡ - Deleting the reference-identity check instead of keeping a zombie guard — simplification *with* the proof of why it's safe — is exactly how I like my codebase maintained. Ready to merge~ --- *Automated review by Jibril · 2026-09-26* *CI/CD: stale for head SHA (coverage bot covers `adadfa6`) · Local checks: vitest 207/207, tsc clean, Release 0w/0e, Adapter 415/415, Integration 513/513, 2 mutation probes*
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
4 participants
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
TeamAI/Tsumugi!52
No description provided.