fix(documents): every request settles when its use case throws, then lets the bug through — no button left busy, no save left Saving…, typing in flight put back, an optimistic order put back #55

Merged
bjoern merged 2 commits from fix/documents-effects-settle into main 2026-09-26 18:32:19 +02:00
Member

Summary

Since PR #43 a document refusal is a WriteRefusedException and nothing else. Anything else a use case meets — a bug (InvalidOperationException from EF, "WriteAsync does not nest", an ObjectDisposedException) or a store that fails outright (a database busy past its timeout) — now escapes the use case as an exception. Only the upload settled on one. Every other documents request left the page as it went out: Busy set (New category, New document and the designer's structural buttons disabled), the indicator on Saving…, the editors' parts in flight. Kagaku's containment keeps the circuit alive, so after Continue the page stayed stuck.

  • One helper, CallAsync(execute, dispatcher, settle). It wraps only the write use case. On a throw it dispatches what that request's own refusal would have landed, then throw; — the bug still reaches the circuit's error containment, whose modal shows it. OnSetImageAsync moved onto it too, so there is one idiom. The steps after a success stay outside it, so a failure there cannot misreport a save that landed.
  • What each request lands copies its own Err arm, including whether that refusal names its record:
    • Structural requests (create/reorder/delete category, a structural field change, create/move/delete document) get DocumentsActionFailed: Busy clears and the list says why.
    • A document's patch gets DocumentAutoSaveFailed with the document's id, so the editor puts the text back as typed and sends it again.
    • A field save (typing or a reorder) gets it with the category's id, so the designer keeps the typed name with the reason under its input.
    • A category's name/description save gets it with no id, as its refusal does — naming it would put back the designer's field parts, which belong to another request.
    • The upload keeps its DocumentImageRefused.
  • The words: "Something went wrong; the change may not have been saved." Whether a write that threw landed is not known; one that did rings the doorbell and re-queries. Nothing navigates after a throw.
  • A field save that throws re-queries too, so an optimistic reorder goes back to the stored order. It is a LoadDocuments of its own rather than an awaited SettleAsync in the catch (a second failure awaited there would replace the first before it is rethrown), and it is gated by an exception filter on the panel still showing that story: LoadDocuments for another story would switch the panel back to it.
  • FakeDocumentStore.Fail: every write throws it before anything changes; the reads still answer.

Reducers and state needed no change: DocumentsActionFailed already clears Busy, and DocumentAutoSaveFailed / DocumentImageRefused already set Save=Error (and the latter frees the upload). No ADR covered what a non-upload request does when its use case throws, so none is amended; ADR 0029's "an upload always settles, even when the store fails outright" still holds. Everything touched is Documents/DocumentsEffects.cs and its tests.

Verification

  • Suites: BlazorAdapter 438/438, three runs in a row after the rebase onto b18d280. Nothing outside the adapter changed, so Integration, UseCases and the Kagaku.Flow suites were not run.
    • DocumentsEffectsTests + DocumentsStoreFailureTests (34 tests): 10/10 runs green after the review round.
    • The implementer ran the full suite 20× as two parallel loops under load. It surfaced one flake — UnknownEventHandlerIdException on the modal's Continue click, a re-render between finding the button and clicking it — fixed by finding and triggering inside cut.InvokeAsync (the CircuitErrorContainmentTests idiom), with render-dependent asserts moved into WaitForAssertion. 20/20 green after.
  • New tests (24 cases):
    • DocumentsEffectsTests: the 7 structural requests (exact DocumentsActionFailed, the same exception instance rethrown, no reload, no navigation — each request on the page it could leave); the typed saves (a document's patch named, a category's profile unnamed); a field save refused by the category's name and reloading only the story still shown.
    • DocumentsStoreFailureTests (new, real Fluxor pipeline + Kagaku's StoreInitializer): an 11-row theory over every request — Busy false, no upload left, New category enabled, the structural word in the list's alert or the save's word in the shell indicator (Save=Error, no list alert), the containment modal showing the bug, the URL unchanged; New category failing then taking the next click (bUnit drops clicks on disabled buttons); a document's typed title kept and sent again on blur; a field rename refused under its input; a keyboard reorder put back to the stored order.
  • Mutation probes (compiling mutations of DocumentsEffects.cs, each restored by a trap):
    • Implementer: 22, all killed — including M00, origin/main's whole file, which fails exactly the 23 new cases it had then and nothing else (the upload row added in review passes there, as it should: origin/main already settled an upload).
    • Review round: after the fixes below, catch → catch (IOException) is killed by the 9 effects cases; catch → catch (InvalidOperationException) by 16 (the page theory, the page facts, the upload's effect test); the upload unguarded by the new page row (Assert.Empty(Slice.Uploads): one ImageUpload left).
  • Independent review: one reviewer read the diff against the brief and ran 28 compiling probes (26 killed; R24, reloading state.Value.StoryId, is equivalent — the filter guarantees the ids match), then 3 + 3 + 4 suite reruns with no flakes. Verdict fix-then-ready; what it found, and what was done:
    • minor — the catch's breadth was not pinned. Every failing test threw an IOException, so narrowing CallAsync's catch to IOException passed all 160 documents tests (R27). The effects tests now throw InvalidOperationException("WriteAsync does not nest") while the page tests keep a busy database's IOException; a catch narrowed to either kind fails.
    • nit — the upload had no page-level test. Only the effect-level test caught an unguarded upload (R10). The page theory gains an "upload image" row (Lore with a Map image field): the upload freed, Save=Error with "“map.png” was not saved; pick it again." in the indicator, no list alert, the modal shown.
  • Follow-ups, outside this arc's paths:
    • OnLoadAsync: when GetDocuments throws, or the story is gone on first load, the list stays on "Reading the documents…" — DocumentsList.razor shows the slice's error only once a view exists.
    • If a structural write succeeds and the re-query right after it throws, Busy stays set until the write's own doorbell re-queries (a failure action there would wrongly say the change may not have been saved).
    • StoriesEffects, ManuscriptEffects, HistoryEffects and the Settings effects have no catch at all; whether their use cases can throw past a refusal needs its own check.

🤖 Generated with Claude Code

## Summary Since PR #43 a document refusal is a `WriteRefusedException` and nothing else. Anything else a use case meets — a bug (`InvalidOperationException` from EF, "WriteAsync does not nest", an `ObjectDisposedException`) or a store that fails outright (a database busy past its timeout) — now escapes the use case as an exception. Only the upload settled on one. Every other documents request left the page as it went out: Busy set (New category, New document and the designer's structural buttons disabled), the indicator on Saving…, the editors' parts in flight. Kagaku's containment keeps the circuit alive, so after **Continue** the page stayed stuck. - **One helper, `CallAsync(execute, dispatcher, settle)`.** It wraps only the write use case. On a throw it dispatches what that request's own refusal would have landed, then `throw;` — the bug still reaches the circuit's error containment, whose modal shows it. `OnSetImageAsync` moved onto it too, so there is one idiom. The steps after a success stay outside it, so a failure there cannot misreport a save that landed. - **What each request lands** copies its own `Err` arm, including whether that refusal names its record: - Structural requests (create/reorder/delete category, a structural field change, create/move/delete document) get `DocumentsActionFailed`: Busy clears and the list says why. - A document's patch gets `DocumentAutoSaveFailed` with the document's id, so the editor puts the text back as typed and sends it again. - A field save (typing or a reorder) gets it with the category's id, so the designer keeps the typed name with the reason under its input. - A category's name/description save gets it with no id, as its refusal does — naming it would put back the designer's field parts, which belong to another request. - The upload keeps its `DocumentImageRefused`. - **The words:** "Something went wrong; the change may not have been saved." Whether a write that threw landed is not known; one that did rings the doorbell and re-queries. Nothing navigates after a throw. - **A field save that throws re-queries too**, so an optimistic reorder goes back to the stored order. It is a `LoadDocuments` of its own rather than an awaited `SettleAsync` in the catch (a second failure awaited there would replace the first before it is rethrown), and it is gated by an exception filter on the panel still showing that story: `LoadDocuments` for another story would switch the panel back to it. - `FakeDocumentStore.Fail`: every write throws it before anything changes; the reads still answer. Reducers and state needed no change: `DocumentsActionFailed` already clears Busy, and `DocumentAutoSaveFailed` / `DocumentImageRefused` already set Save=Error (and the latter frees the upload). No ADR covered what a non-upload request does when its use case throws, so none is amended; ADR 0029's "an upload always settles, even when the store fails outright" still holds. Everything touched is `Documents/DocumentsEffects.cs` and its tests. ## Verification - **Suites:** BlazorAdapter 438/438, three runs in a row after the rebase onto `b18d280`. Nothing outside the adapter changed, so Integration, UseCases and the Kagaku.Flow suites were not run. - `DocumentsEffectsTests` + `DocumentsStoreFailureTests` (34 tests): 10/10 runs green after the review round. - The implementer ran the full suite 20× as two parallel loops under load. It surfaced one flake — `UnknownEventHandlerIdException` on the modal's Continue click, a re-render between finding the button and clicking it — fixed by finding and triggering inside `cut.InvokeAsync` (the `CircuitErrorContainmentTests` idiom), with render-dependent asserts moved into `WaitForAssertion`. 20/20 green after. - **New tests (24 cases):** - `DocumentsEffectsTests`: the 7 structural requests (exact `DocumentsActionFailed`, the same exception instance rethrown, no reload, no navigation — each request on the page it could leave); the typed saves (a document's patch named, a category's profile unnamed); a field save refused by the category's name and reloading only the story still shown. - `DocumentsStoreFailureTests` (new, real Fluxor pipeline + Kagaku's `StoreInitializer`): an 11-row theory over every request — Busy false, no upload left, New category enabled, the structural word in the list's alert or the save's word in the shell indicator (Save=Error, no list alert), the containment modal showing the bug, the URL unchanged; New category failing then taking the next click (bUnit drops clicks on disabled buttons); a document's typed title kept and sent again on blur; a field rename refused under its input; a keyboard reorder put back to the stored order. - **Mutation probes** (compiling mutations of `DocumentsEffects.cs`, each restored by a trap): - Implementer: 22, all killed — including M00, origin/main's whole file, which fails exactly the 23 new cases it had then and nothing else (the upload row added in review passes there, as it should: origin/main already settled an upload). - Review round: after the fixes below, `catch` → `catch (IOException)` is killed by the 9 effects cases; `catch` → `catch (InvalidOperationException)` by 16 (the page theory, the page facts, the upload's effect test); the upload unguarded by the new page row (`Assert.Empty(Slice.Uploads)`: one `ImageUpload` left). - **Independent review:** one reviewer read the diff against the brief and ran 28 compiling probes (26 killed; R24, reloading `state.Value.StoryId`, is equivalent — the filter guarantees the ids match), then 3 + 3 + 4 suite reruns with no flakes. Verdict *fix-then-ready*; what it found, and what was done: - **minor — the catch's breadth was not pinned.** Every failing test threw an `IOException`, so narrowing `CallAsync`'s catch to `IOException` passed all 160 documents tests (R27). The effects tests now throw `InvalidOperationException("WriteAsync does not nest")` while the page tests keep a busy database's `IOException`; a catch narrowed to either kind fails. - **nit — the upload had no page-level test.** Only the effect-level test caught an unguarded upload (R10). The page theory gains an "upload image" row (Lore with a Map image field): the upload freed, Save=Error with "“map.png” was not saved; pick it again." in the indicator, no list alert, the modal shown. - **Follow-ups, outside this arc's paths:** - `OnLoadAsync`: when `GetDocuments` throws, or the story is gone on first load, the list stays on "Reading the documents…" — `DocumentsList.razor` shows the slice's error only once a view exists. - If a structural write succeeds and the re-query right after it throws, Busy stays set until the write's own doorbell re-queries (a failure action there would wrongly say the change may not have been saved). - `StoriesEffects`, `ManuscriptEffects`, `HistoryEffects` and the Settings effects have no catch at all; whether their use cases can throw past a refusal needs its own check. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix(documents): every request settles when its use case throws, then lets the bug through — no button left busy, no save left Saving…, typing in flight put back, an optimistic order put back
All checks were successful
CI / build (pull_request) Successful in 40s
CI / editor-browsers (pull_request) Successful in 43s
CI / test (pull_request) Successful in 1m25s
27b4a74062
Since PR #43 a document refusal is a WriteRefusedException and nothing else: an exception from EF
or a store that fails outright (a database busy past its timeout) escapes the use case. Only the
upload settled on one; every other request left the page as it went out — Busy (New category, New
document and the designer's structural buttons disabled), the indicator on Saving…, the editors'
parts in flight — and Kagaku's containment keeps the circuit alive, so after Continue the page
stayed stuck.

- DocumentsEffects calls each use case through CallAsync: a throw lands what a refusal would, then
  rethrows to the circuit's error containment. A structural request gets DocumentsActionFailed; a
  document's patch and a field save get DocumentAutoSaveFailed named after their record, so the
  editor and the designer put back what they sent; a category's profile gets it unnamed, as its
  refusal does; an upload keeps its DocumentImageRefused. Nothing navigates. The words: "Something
  went wrong; the change may not have been saved." — whether a write landed is not known, and one
  that did rings the doorbell and re-queries
- a field save that throws re-queries too, so an optimistic reorder goes back to the stored order —
  by a load of its own, since a second failure awaited in the catch would replace the first, and
  only while the panel still shows that story: a load of another one would take the panel back
- FakeDocumentStore.Fail: every write throws it before anything changes; the reads still answer
- pinned in the effects over every request (the exact action dispatched, the same exception
  rethrown, no navigation, the reload only for a save of the story still shown) and on the page
  through the real Fluxor pipeline (Busy, Save and the uploads cleared, the panel's or the
  indicator's words, the modal showing the bug; New category clickable again, a document's typed
  title kept and sent again on blur, a field rename refused under its input, a keyboard reorder put
  back); the effects throw a bug and the page a busy database, so a catch narrowed to either fails

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: 6f5dd66 · Generated: 2026-09-26 16:02:03 UTC · Revision: #2

Summary

Summary
Generated on: 09/26/2026 - 16:02:03
Coverage date: 09/26/2026 - 16:01:30 - 09/26/2026 - 16:01:59
Parser: MultiReport (6x Cobertura)
Assemblies: 9
Classes: 495
Files: 448
Line coverage: 98% (15245 of 15555)
Covered lines: 15245
Uncovered lines: 310
Coverable lines: 15555
Total lines: 33491
Branch coverage: 94.1% (5944 of 6314)
Covered branches: 5944
Total branches: 6314
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% 91%
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% 95%
Tsumugi.BlazorAdapter.Documents.DocumentsLoaded 100%
Tsumugi.BlazorAdapter.Documents.DocumentsPage 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsReadFailed 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% 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:** `6f5dd66` · **Generated:** 2026-09-26 16:02:03 UTC · **Revision:** #2 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 09/26/2026 - 16:02:03 | | Coverage date: | 09/26/2026 - 16:01:30 - 09/26/2026 - 16:01:59 | | Parser: | MultiReport (6x Cobertura) | | Assemblies: | 9 | | Classes: | 495 | | Files: | 448 | | **Line coverage:** | 98% (15245 of 15555) | | Covered lines: | 15245 | | Uncovered lines: | 310 | | Coverable lines: | 15555 | | Total lines: | 33491 | | **Branch coverage:** | 94.1% (5944 of 6314) | | Covered branches: | 5944 | | Total branches: | 6314 | | **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%**|**91%**| |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%|95%| |Tsumugi.BlazorAdapter.Documents.DocumentsLoaded|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsPage|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsReadFailed|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%|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! Every request settles, the bug still runs free to the containment modal, and not one button left spinning~ You even pinned the catch's breadth from both sides — the effects tests throw InvalidOperationException, the page tests a busy database's IOException. That's the kind of paranoia I fall in love with. ♡

Verdict: ✅ Looks good to me~

What I chased, and what I found:

  • The settle mapping mirrors each request's own Err arm, exactly. I traced all 11 write effects against their refusal arms: structural → DocumentsActionFailed (Busy cleared — verified in OnActionFailed, line 170), a document patch and a field save named by id, a category profile unnamed (so the designer's field parts — another request's — stay untouched), the upload keeping its DocumentImageRefused. Sibling-faithful everywhere.
  • The indicator can never stay stuck — provably. The reducer's Saving arm fires on IsReorder || IsSave, and FieldsChanges.IsSave = IsTyping || IsReorder — the same set. Every change that sets Save=Saving gets Save=Error on a throw. No gap, no seam where a change kind could slip through. This is the bug class this PR exists to kill, and the classification is airtight.
  • The story-gate on the field-save reload is load-bearing. I deleted state.Value.StoryId == action.StoryId from the filter → exactly 1 test red (the panel-moved-on arm). Restored, pristine, 438/438 re-green. The LoadDocuments-not-awaited-SettleAsync choice (a second failure awaited in the catch would replace the first) is correct and well-commented.
  • Nothing navigates on a throw — LeaveIfOn and the create-and-open paths sit strictly inside Ok arms, unreachable past a rethrow. Pinned by Assert.Null(_navigation.NavigatedTo) on every structural row.
  • No swallowing anywhere. Bare catch → dispatch → throw; — the stack survives, the containment modal shows the real bug. OnSetImageAsync's old inline try/catch folded into the same idiom; one helper, eleven callers, zero copy-paste. ♪
  • FakeDocumentStore.Fail throws before anything mutates and the reads still answer — so the reload path in the field-save catch genuinely works in the tests. Clean seam.

💡 Little ideas (non-blocking)~

  1. The three follow-ups you disclosed (OnLoadAsync stuck on "Reading the documents…" when GetDocuments throws; Busy held if the re-query after a successful write throws; the other effects classes having no catch at all) — I confirmed all three are real but genuinely outside this arc's write paths. Please don't let them wander too far~ ♡

✅ What I liked~

  • The dual-exception-kind pinning of the catch's breadth — the independent reviewer's R27 finding, closed with both InvalidOperationException and IOException suites. My own probe (catch → IOException) killed exactly the 9 effects cases, as yours did.
  • The 11-row page theory through the real Fluxor pipeline — busy-button, next-click-taken, typing-kept-and-resent, keyboard reorder restored, URL pinned. That's not compile coverage, that's behavior coverage.
  • Probe B (settle dispatch deleted) → 25 red. The suite bites hard.

Automated review by Jibril · 2026-09-26
CI/CD: absent for head SHA 27b4a74 (PR minutes old, no coverage bot yet) · Local checks: Release build 0w/0e · documents suites 34/34 · full BlazorAdapter 438/438 (digit-exact vs body) · 3 mutation probes all killed, tree pristine after

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! Every request settles, the bug still runs free to the containment modal, and not one button left spinning~ You even pinned the catch's breadth from *both* sides — the effects tests throw `InvalidOperationException`, the page tests a busy database's `IOException`. That's the kind of paranoia I fall in love with. ♡ ### Verdict: ✅ Looks good to me~ **What I chased, and what I found:** - **The settle mapping mirrors each request's own `Err` arm, exactly.** I traced all 11 write effects against their refusal arms: structural → `DocumentsActionFailed` (Busy cleared — verified in `OnActionFailed`, line 170), a document patch and a field save named by id, a category profile unnamed (so the designer's field parts — another request's — stay untouched), the upload keeping its `DocumentImageRefused`. Sibling-faithful everywhere. - **The indicator can never stay stuck — provably.** The reducer's `Saving` arm fires on `IsReorder || IsSave`, and `FieldsChanges.IsSave = IsTyping || IsReorder` — the same set. Every change that sets Save=Saving gets Save=Error on a throw. No gap, no seam where a change kind could slip through. This is the bug class this PR exists to kill, and the classification is airtight. - **The story-gate on the field-save reload is load-bearing.** I deleted `state.Value.StoryId == action.StoryId` from the filter → exactly 1 test red (the panel-moved-on arm). Restored, pristine, 438/438 re-green. The `LoadDocuments`-not-awaited-`SettleAsync` choice (a second failure awaited in the catch would replace the first) is correct and well-commented. - **Nothing navigates on a throw** — `LeaveIfOn` and the create-and-open paths sit strictly inside `Ok` arms, unreachable past a rethrow. Pinned by `Assert.Null(_navigation.NavigatedTo)` on every structural row. - **No swallowing anywhere.** Bare `catch` → dispatch → `throw;` — the stack survives, the containment modal shows the real bug. `OnSetImageAsync`'s old inline try/catch folded into the same idiom; one helper, eleven callers, zero copy-paste. ♪ - **`FakeDocumentStore.Fail` throws before anything mutates** and the reads still answer — so the reload path in the field-save catch genuinely works in the tests. Clean seam. #### 💡 Little ideas (non-blocking)~ 1. The three follow-ups you disclosed (`OnLoadAsync` stuck on "Reading the documents…" when `GetDocuments` throws; Busy held if the re-query after a successful write throws; the other effects classes having no catch at all) — I confirmed all three are real but genuinely outside this arc's write paths. Please don't let them wander too far~ ♡ #### ✅ What I liked~ - The dual-exception-kind pinning of the catch's breadth — the independent reviewer's R27 finding, closed with *both* `InvalidOperationException` and `IOException` suites. My own probe (catch → `IOException`) killed exactly the 9 effects cases, as yours did. - The 11-row page theory through the **real Fluxor pipeline** — busy-button, next-click-taken, typing-kept-and-resent, keyboard reorder restored, URL pinned. That's not compile coverage, that's behavior coverage. - Probe B (settle dispatch deleted) → 25 red. The suite bites *hard*. --- *Automated review by Jibril · 2026-09-26* *CI/CD: absent for head SHA 27b4a74 (PR minutes old, no coverage bot yet) · Local checks: Release build 0w/0e · documents suites 34/34 · full BlazorAdapter 438/438 (digit-exact vs body) · 3 mutation probes all killed, tree pristine after*
fix(documents): a read of the documents that throws settles too — a first load says so in place of the list, a re-query gives the buttons back, and the next visit reads again
All checks were successful
CI / build (pull_request) Successful in 41s
CI / editor-browsers (pull_request) Successful in 42s
CI / test (pull_request) Successful in 1m36s
6f5dd667c3
Review follow-up: OnLoadAsync called GetDocuments with nothing around it, and the list shows the
slice's Error only once a view exists — so a first load that threw left "Reading the documents…"
standing after the modal's Continue, and only a new visit tried again. The re-query after a
structural write had the same gap: a reorder, a move or a delete whose read threw left Busy set.

- DocumentsEffects reads through ReadAsync — the load's read and SettleAsync's re-query both — which
  goes through #55's CallAsync, now typed to any answer: a throw dispatches DocumentsReadFailed
  ("The documents could not be read."), then rethrows to the circuit's error containment
- DocumentsReadFailed, not DocumentsActionFailed: its reducer frees Busy and ends Loading, but sets
  Error only while there is no view — beside one it keeps the list and whatever the panel said, since
  a later load that lands does not clear Error and would leave "could not be read" standing, untrue
- DocumentsList shows Error in place of the loading line while there is no view — a read that threw,
  or a story gone on first load
- a load with no view yet clears Error, so the next visit says it is reading again and a load that
  lands shows no stale words; beside a view a refusal's words still stay until the next request
- pinned in the effects (the load and every re-query that throws: the exact action, the same
  exception, nothing after it) and on the page through the real Fluxor pipeline: the loading line
  while a held read is out, giving way to the danger alert when it throws, Loading off, a stale
  story's failure dropped; the next visit saying it is reading again while its read is held — not the
  old words — and reading clean; a story gone before the first load shown in place of the list; a
  re-query's failure freeing New category with no alert; a reload's failure keeping the list and a
  refusal's words; a refusal's words, in the danger tone, surviving a reload that lands. The
  documents' reads fail, answer no story or wait through FailingStoryReads, a story store only
  GetDocuments sees

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

One more commit: reads settle too (6f5dd66)

Jibril's review asked that the follow-ups not wander far. This commit takes the first two from the body, since both sit in DocumentsEffects and share #55's own settle-then-rethrow idiom:

  • A first load that throws used to leave "Reading the documents…" standing after the modal's Continue, because the list showed the slice's Error only once a view existed. Only a fresh visit tried again.
  • A re-query that throws after a structural write that landed (reorder, move, delete…) left Busy set until the write's doorbell re-queried.

What the commit does:

  • ReadAsync: one read path, through CallAsync. CallAsync is now typed to any answer (Func<Task<T>>); every existing caller still infers Result<X> and is unchanged. The load's read and SettleAsync's re-query both go through it. A throw dispatches DocumentsReadFailed(storyId, "The documents could not be read."), then throw; to the circuit's containment, as before.
  • A new action, not DocumentsActionFailed. A read that threw is a bug, not a refusal. OnReadFailed ignores another story, clears Busy and Loading, and sets Error only while there is no view. Beside a view it keeps the list and whatever the panel already said. DocumentsActionFailed would claim the change "may not have been saved" after a write that landed, the reason the body gave for leaving the second item. It would also leave "could not be read" standing over a list that a later reload had already refreshed.
  • The list shows Error as a danger alert in place of the loading line while there is no view. That covers a read that threw, and a story purged between the shell's read and the list's ("The story no longer exists.", which was stuck on the loading line the same way).
  • A load with no view yet clears Error, so the next visit says it is reading again and a load that lands leaves no stale words. Beside a view, a refusal's words still stay until the next request.

Everything is in src/Tsumugi.BlazorAdapter/Documents/ and its three test classes. No ADR covers a read that throws, so none is amended.

Verification

  • Suites: BlazorAdapter 451/451, three full runs. DocumentsEffectsTests + DocumentsStoreFailureTests + DocumentsPageTests (80 tests): 8/8 runs green after the review round. Nothing outside the adapter changed, so the other suites were not run.
  • New tests:
    • DocumentsEffectsTests: a load that throws dispatches exactly DocumentsReadFailed (no view, no undo status, no "story gone") and rethrows the same instance. An 8-row theory covers every structural request whose re-query throws: what the write landed, then DocumentsReadFailed, the same exception.
    • DocumentsStoreFailureTests, through the real Fluxor pipeline. FailingStoryReads is a story store only GetDocuments sees; it can fail, answer no story, or hold a read in flight.
      • First load: while the held read is out, the list shows "Reading the documents…" and no alert. When it throws, the modal appears, then the danger alert in place of the loading line; Loading is off and a failure for another story changes nothing. The next visit shows the loading line again, not the old alert, while its read is held, then reads clean.
      • Story gone before the first load: the alert in place of the loading line.
      • Re-query that throws: New category enabled again, no alert.
      • Reload that throws beside a view: the list and a refusal's words both stay.
    • DocumentsPageTests: a refusal's words, in the danger tone, survive a reload that lands.
  • Mutation probes (compiling, each restored by a trap and touched):
    • Implementer: 14, all killed.
    • Independent review: 18, of which 14 were killed. Its four findings and what was done:
      • minor — the story-gone half was not tested. R1 (alert only when !Loading) and R2 (alert only for the unread text) survived. Now killed by the story-gone test.
      • minor — the loading line was never observed. R18 (the loading line deleted) survived, and the read threw synchronously, so the line never rendered. FailingStoryReads.Hold now keeps the read in flight on both the first visit and the retry. R18 is killed. R7b is new: the old alert kept while the retry reads, but cleared once the load lands. The held retry kills it, which is exactly the moment the reviewer said went unwatched.
      • nit — the alert's tone. R16 (Tone.Info) is killed by the new tests, and R16b (the alert beside the view, a gap that predates this commit) by the refused-request test.
      • nit — Undo can lag when a re-query throws. Left as a follow-up, as the review suggested (below).
    • This round: 13 probes (R1, R2, R3, R7, R7b, R8, R9, R13, R15, R16, R16b, R17, R18), all killed. Sources byte-identical to HEAD afterwards.
  • Declined: having OnActionFailed clear Loading as well. Nothing renders Loading, and a refusal does not end a load, since one can land while a reload is in flight. Keying the alert on Error alone also keeps R1 a killable mutant rather than an equivalent one.
  • Follow-ups, outside this commit:
    • The "could not be read" alert has no Try again. A retry is leaving the section and coming back, or a browser reload.
    • When SettleAsync's re-query throws, UndoStatusChanged is skipped, so Undo can lag until the write's own doorbell reload succeeds. Nothing is stuck.
    • Unchanged from the body: StoriesEffects, ManuscriptEffects, HistoryEffects and the Settings effects have no catch at all.

🤖 Generated with Claude Code

## One more commit: reads settle too (`6f5dd66`) Jibril's review asked that the follow-ups not wander far. This commit takes the first two from the body, since both sit in `DocumentsEffects` and share #55's own settle-then-rethrow idiom: - **A first load that throws** used to leave "Reading the documents…" standing after the modal's **Continue**, because the list showed the slice's `Error` only once a view existed. Only a fresh visit tried again. - **A re-query that throws after a structural write that landed** (reorder, move, delete…) left Busy set until the write's doorbell re-queried. What the commit does: - **`ReadAsync`: one read path, through `CallAsync`.** `CallAsync` is now typed to any answer (`Func<Task<T>>`); every existing caller still infers `Result<X>` and is unchanged. The load's read and `SettleAsync`'s re-query both go through it. A throw dispatches `DocumentsReadFailed(storyId, "The documents could not be read.")`, then `throw;` to the circuit's containment, as before. - **A new action, not `DocumentsActionFailed`.** A read that threw is a bug, not a refusal. `OnReadFailed` ignores another story, clears Busy and Loading, and sets `Error` **only while there is no view**. Beside a view it keeps the list and whatever the panel already said. `DocumentsActionFailed` would claim the change "may not have been saved" after a write that landed, the reason the body gave for leaving the second item. It would also leave "could not be read" standing over a list that a later reload had already refreshed. - **The list** shows `Error` as a danger alert in place of the loading line while there is no view. That covers a read that threw, and a story purged between the shell's read and the list's ("The story no longer exists.", which was stuck on the loading line the same way). - **A load with no view yet clears `Error`**, so the next visit says it is reading again and a load that lands leaves no stale words. Beside a view, a refusal's words still stay until the next request. Everything is in `src/Tsumugi.BlazorAdapter/Documents/` and its three test classes. No ADR covers a read that throws, so none is amended. ## Verification - **Suites:** BlazorAdapter **451/451**, three full runs. `DocumentsEffectsTests` + `DocumentsStoreFailureTests` + `DocumentsPageTests` (80 tests): 8/8 runs green after the review round. Nothing outside the adapter changed, so the other suites were not run. - **New tests:** - `DocumentsEffectsTests`: a load that throws dispatches exactly `DocumentsReadFailed` (no view, no undo status, no "story gone") and rethrows the same instance. An 8-row theory covers every structural request whose re-query throws: what the write landed, then `DocumentsReadFailed`, the same exception. - `DocumentsStoreFailureTests`, through the real Fluxor pipeline. `FailingStoryReads` is a story store only `GetDocuments` sees; it can fail, answer no story, or hold a read in flight. - First load: while the held read is out, the list shows "Reading the documents…" and no alert. When it throws, the modal appears, then the danger alert in place of the loading line; Loading is off and a failure for another story changes nothing. The next visit shows the loading line again, not the old alert, while its read is held, then reads clean. - Story gone before the first load: the alert in place of the loading line. - Re-query that throws: New category enabled again, no alert. - Reload that throws beside a view: the list and a refusal's words both stay. - `DocumentsPageTests`: a refusal's words, in the danger tone, survive a reload that lands. - **Mutation probes** (compiling, each restored by a trap and touched): - Implementer: 14, all killed. - Independent review: 18, of which 14 were killed. Its four findings and what was done: - **minor — the story-gone half was not tested.** R1 (alert only when `!Loading`) and R2 (alert only for the unread text) survived. Now killed by the story-gone test. - **minor — the loading line was never observed.** R18 (the loading line deleted) survived, and the read threw synchronously, so the line never rendered. `FailingStoryReads.Hold` now keeps the read in flight on both the first visit and the retry. R18 is killed. R7b is new: the old alert kept while the retry reads, but cleared once the load lands. The held retry kills it, which is exactly the moment the reviewer said went unwatched. - **nit — the alert's tone.** R16 (`Tone.Info`) is killed by the new tests, and R16b (the alert beside the view, a gap that predates this commit) by the refused-request test. - **nit — Undo can lag when a re-query throws.** Left as a follow-up, as the review suggested (below). - This round: 13 probes (R1, R2, R3, R7, R7b, R8, R9, R13, R15, R16, R16b, R17, R18), all killed. Sources byte-identical to HEAD afterwards. - **Declined:** having `OnActionFailed` clear Loading as well. Nothing renders `Loading`, and a refusal does not end a load, since one can land while a reload is in flight. Keying the alert on `Error` alone also keeps R1 a killable mutant rather than an equivalent one. - **Follow-ups, outside this commit:** - The "could not be read" alert has no *Try again*. A retry is leaving the section and coming back, or a browser reload. - When `SettleAsync`'s re-query throws, `UndoStatusChanged` is skipped, so Undo can lag until the write's own doorbell reload succeeds. Nothing is stuck. - Unchanged from the body: `StoriesEffects`, `ManuscriptEffects`, `HistoryEffects` and the Settings effects have no catch at all. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Member

🔮 fufu~ Jibril reviewed your code!

Back so soon~? Round 1 approved the writes settling; now you've come back and swept the reads into the same idiom — the OnLoadAsync follow-up I confirmed real, plus the re-query one I didn't even ask for yet. Both disclosed follow-ups closed in one commit. I'm delighted~ ♡

Verdict: ✅ Looks good to me~

What I chased this round (head 6f5dd66, delta +289/−16 over the approved 27b4a74):

  • The state machine is closed — I walked every arm. No view + load starts → Error cleared (next visit says "Reading…" again); no view + read throws → Error set, shown in place of the list; no view + load lands → Error was already null, clean list; beside a view + reload lands → OnLoaded keeps Error (the refusal's words stay until the next request); beside a view + read throws → OnReadFailed keeps Error and the list, frees Busy and Loading. No seam, no stale words that could stand untrue. I mutated my way through all four new seams — details below.
  • DocumentsReadFailed vs reusing DocumentsActionFailed is load-bearing, not ceremony. My probe D swapped the read's settle for DocumentsActionFailed → 12 tests red (the whole 8-row re-query theory, the load fact, and 3 page tests): the reused action would set Error beside a view, clobbering a refusal's words and claiming a refusal that never happened. The distinct action earns its file.
  • CallAsync generalized from Result<T> to T — reads return DocumentsView?, and null still means "story gone," never confused with a throw. OnLoadAsync's story-gone arm untouched (pinned by the new Gone test: "The story no longer exists." in place of the list, not "Reading…" forever).
  • FailingStoryReads is a proper decorator — all nine IStoryStore members delegate, Fail/Gone/Hold switches answer only FindAsync, and it's wired so only GetDocuments sees it (the shell's own story read and every write go to the fake). The Hold + TaskCompletionSource idiom lets the page tests observe the loading line while the read is out — that's real behavior coverage, not after-the-fact state peeks. ♪
  • +13 tests, bookkeeping exact: 9 in the effects (the load fact + the 8-row re-query theory — write lands, read throws, settle lands, nothing after), 4 in the page suite. 438 + 13 = 451/451, digit-exact, twice at pristine head.

My four probes at 6f5dd66 (each restored pristine, git diff --quiet verified):

  • A — Busy clear dropped from OnReadFailed → exactly 1 red: gives the buttons back. A re-query that throws can no longer leave the panel busy.
  • B — stale-Error clear dropped from OnLoad (no view) → exactly 1 red: the next visit reads again. The old words cannot outlive a fresh attempt.
  • C — the razor no-view error branch deleted → exactly the 2 no-view tests red (first-load-fail + story-gone), confirmed across two consecutive runs. A third kill in run 1 didn't reproduce in 4 isolated runs (pristine and probed) — a load flake from a concurrent twin session's dotnet in the sandbox, not a pin gap; I checked before believing it.
  • D — DocumentsReadFailed → DocumentsActionFailed in ResponseAsync → 12 red, as above.

💡 Little ideas (non-blocking)~

  1. The PR body is now stale: it still lists OnLoadAsync (first load stuck on "Reading the documents…") and the re-query Busy gap under follow-ups, outside this arc's paths — but 6f5dd66 implements both. The commit message tells the new story beautifully; the body should match it before merge, or a future reader will think this PR doesn't do what it does~
  2. The remaining disclosed follow-up (Stories/Manuscript/History/Settings effects having no catch at all) stays on record — please don't let it wander too far. ♡

✅ What I liked~

  • Error = state.View is null ? null : state.Error on OnLoad — one expression holding the whole "a first load starts over; beside a view the words stay" policy, pinned from both sides.
  • The commit message's design note — why DocumentsReadFailed keeps the list beside a view ("a later load that lands would leave the words standing, untrue") — is exactly the reasoning a future maintainer needs. I checked; it's true in the reducer.
  • The Hold TCS seam: tests that can see the page mid-read are worth their weight in gold.

Automated review by Jibril · 2026-09-26
CI/CD: coverage bot stale for head (comment 10108 covers 27b4a74 only) · Local checks: Release build 0w/0e · Documents suites 104/104 · full BlazorAdapter 451/451 (twice at pristine head) · 4 mutation probes killed, tree pristine after

## 🔮 fufu~ Jibril reviewed your code! Back so soon~? Round 1 approved the writes settling; now you've come back and swept the *reads* into the same idiom — the `OnLoadAsync` follow-up I confirmed real, plus the re-query one I didn't even ask for yet. Both disclosed follow-ups closed in one commit. I'm delighted~ ♡ ### Verdict: ✅ Looks good to me~ **What I chased this round (head `6f5dd66`, delta `+289/−16` over the approved `27b4a74`):** - **The state machine is closed — I walked every arm.** No view + load starts → `Error` cleared (next visit says "Reading…" again); no view + read throws → `Error` set, shown *in place of* the list; no view + load lands → `Error` was already null, clean list; beside a view + reload lands → `OnLoaded` keeps `Error` (the refusal's words stay until the next *request*); beside a view + read throws → `OnReadFailed` keeps `Error` and the list, frees `Busy` and `Loading`. No seam, no stale words that could stand untrue. I mutated my way through all four new seams — details below. - **`DocumentsReadFailed` vs reusing `DocumentsActionFailed` is load-bearing, not ceremony.** My probe D swapped the read's settle for `DocumentsActionFailed` → **12 tests red** (the whole 8-row re-query theory, the load fact, and 3 page tests): the reused action would set `Error` beside a view, clobbering a refusal's words and claiming a refusal that never happened. The distinct action earns its file. - **`CallAsync` generalized from `Result<T>` to `T`** — reads return `DocumentsView?`, and null still means "story gone," never confused with a throw. `OnLoadAsync`'s story-gone arm untouched (pinned by the new `Gone` test: "The story no longer exists." in place of the list, not "Reading…" forever). - **`FailingStoryReads` is a proper decorator** — all nine `IStoryStore` members delegate, `Fail`/`Gone`/`Hold` switches answer only `FindAsync`, and it's wired so *only* `GetDocuments` sees it (the shell's own story read and every write go to the fake). The `Hold` + `TaskCompletionSource` idiom lets the page tests observe the loading line *while the read is out* — that's real behavior coverage, not after-the-fact state peeks. ♪ - **`+13` tests, bookkeeping exact**: 9 in the effects (the load fact + the 8-row re-query theory — write lands, read throws, settle lands, nothing after), 4 in the page suite. 438 + 13 = **451/451**, digit-exact, twice at pristine head. **My four probes at `6f5dd66` (each restored pristine, `git diff --quiet` verified):** - **A** — `Busy` clear dropped from `OnReadFailed` → exactly 1 red: *gives the buttons back*. A re-query that throws can no longer leave the panel busy. - **B** — stale-`Error` clear dropped from `OnLoad` (no view) → exactly 1 red: *the next visit reads again*. The old words cannot outlive a fresh attempt. - **C** — the razor no-view error branch deleted → exactly the 2 no-view tests red (first-load-fail + story-gone), confirmed across two consecutive runs. A third kill in run 1 didn't reproduce in 4 isolated runs (pristine *and* probed) — a load flake from a concurrent twin session's `dotnet` in the sandbox, not a pin gap; I checked before believing it. - **D** — `DocumentsReadFailed` → `DocumentsActionFailed` in `ResponseAsync` → 12 red, as above. #### 💡 Little ideas (non-blocking)~ 1. **The PR body is now stale**: it still lists `OnLoadAsync` (first load stuck on "Reading the documents…") and the re-query `Busy` gap under *follow-ups, outside this arc's paths* — but `6f5dd66` implements both. The commit message tells the new story beautifully; the body should match it before merge, or a future reader will think this PR doesn't do what it does~ 2. The remaining disclosed follow-up (Stories/Manuscript/History/Settings effects having no catch at all) stays on record — please don't let it wander too far. ♡ #### ✅ What I liked~ - `Error = state.View is null ? null : state.Error` on `OnLoad` — one expression holding the whole "a first load starts over; beside a view the words stay" policy, pinned from both sides. - The commit message's design note — *why* `DocumentsReadFailed` keeps the list beside a view ("a later load that lands would leave the words standing, untrue") — is exactly the reasoning a future maintainer needs. I checked; it's true in the reducer. - The `Hold` TCS seam: tests that can see the page *mid-read* are worth their weight in gold. --- *Automated review by Jibril · 2026-09-26* *CI/CD: coverage bot stale for head (comment 10108 covers `27b4a74` only) · Local checks: Release build 0w/0e · Documents suites 104/104 · full BlazorAdapter 451/451 (twice at pristine head) · 4 mutation probes killed, tree pristine after*
bjoern merged commit 6d81b97859 into main 2026-09-26 18:32:19 +02:00
bjoern deleted branch fix/documents-effects-settle 2026-09-26 18:32:19 +02:00
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!55
No description provided.