docs: Phase 2 decisions — where the engine's seams sit, where runs live, what gates the phase #16

Merged
bjoern merged 1 commit from docs/phase-2-decisions into main 2026-09-23 11:58:05 +02:00
Member

Phase 2's second slice, and docs only. Planning the engine turned up places where two ADRs disagree (the gateway sits in UseCases per ADR 0018 but Kagaku.Flow.OpenRouter may not reference Tsumugi per ADR 0025) or leave something open (where the run pane lives, what a retried run does to its snapshot, how a failed run leaves the strip). This PR writes each decision into the ADR it belongs to. Every later slice is then reviewed against a written rule rather than a planner note. It must merge before the Kagaku.Flow core slice starts.

Each amended ADR carries one dated line under Status, and its body is edited in place so it reads as the current rule. Merging this PR is how the owner decisions below get confirmed. Any of them can be reversed here at the cost of a docs edit.

Decisions that need Björn's call

  1. The gateway moves (0003, 0004, 0018, 0025). ILlmGateway lives in Kagaku.Flow.OpenRouter, over OpenRouter.Net, and the host supplies the key through IOpenRouterKeySource. Tsumugi.UseCases keeps a narrow IModelProvider for key validation and the catalog as Tsumugi DTOs, implemented in Infrastructure. UseCases never sees an OpenRouter type.
  2. Kagaku.Flow owns the run/ledger model (0003, 0016, 0025). The records, statuses and IRunLedger belong to the library, and the core Run carries an opaque OwnerId. Infrastructure maps them onto its own EF entities, and Tsumugi.Domain models no runs.
  3. A length rejection is permanent in Phase 2 (0016, 0017). The llm row fails, naming the overflow, and the chars-per-token ratio learns from the reported token count. Automatic re-budgeting waits for re-run-from-node in Phase 5.
  4. Runs get their own section (0024, 0027, 0010, 0020). The Run button sits in the chapter toolbar, and the streaming preview renders inline at the end of the target chapter. stories/{id}/runs holds run history and stories/{id}/runs/{runId} holds the monitor with the inspector pane, where ?node= opens a node run.
  5. Continue is context → llm → an explicit commit (0014, 0023). Its model is a concrete catalog id, not a ~…-latest alias. Which model id should it ship with? A mid-price prose model you already use in nai_maker would be the natural pick. The implicit auto-commit of an unwired llm arrives with the editor in Phase 3.
  6. Summarize chapter moves to Phase 3 (0023, PROJECT_PLAN). It needs set_chapter_summary, a manuscript write tool that arrives with the tool node.
  7. Categories are selected by name (0013, 0017). Names are matched case-insensitively after trimming, per run, and a missing one is skipped and reported. Selecting a single document waits for Phase 3's property panel. story.documents(…) and .index(…) require a category list.
  8. JsonSchema.Net becomes a dependency of Kagaku.Flow.OpenRouter only, for validating structured output against a user schema (0018).
  9. Three library PRs gate Phase 2 (0018, PROJECT_PLAN): L1 (merged as OpenRouter.Net #14), L2 stream accumulation with typed failures, and a reduced L3. The streaming agent loop, concurrent tools with parallel_tool_calls and the typed structured-output helper move to the start of Phase 4, where they have consumers.
  10. Dismiss on the strip (0024). A failed or cancelled run can be dismissed, which sets acknowledgedAt. A later success still never hides an undismissed failure.
  11. Graphs stay unjournaled until Phase 3 (0022, 0023). This is a dated exception, recorded in ADR 0022 itself: the story-keyed journal cannot hold an app-level graph. Switching a story's active graph stays a journaled story update.
  12. The package names stay Kagaku.Flow, Kagaku.Flow.OpenRouter, plus the test-support package Kagaku.Flow.Testing (0025).
  13. One run snapshot per run id (0022). When a run finishes again after a Retry, its existing snapshot moves to the latest journal position and is relabelled. Revert run still reverts the whole run.
  14. Routing defaults are inherited at run time (0018; your settings request). Settings → Defaults gains a routing variant (Balanced, Fastest :nitro, Cheapest :floor, Most reliable with tools :exacto) and a service tier (Auto, Standard, Flex, Priority), with an optional zero-data-retention switch. An llm node that leaves routing unset uses the install-wide value when it runs, so the bundled templates follow your choice. A node that sets its own wins.

Rules this PR adds that the plan did not state

Filling these gaps took the smallest rule that made the ADRs agree. Please check them.

  • A node's routing also accepts balanced, which sends no suffix. Without it, a node could not ask for plain routing when the install default is Fastest.
  • The zero-data-retention switch is merged into every request's provider preferences, so no node can opt out.
  • Moving a graph that a story has active to the trash is refused, with the stories named. A story with no active graph has its Run button disabled with the reason. The foreign key's SET NULL only guards a hard purge.
  • A Retry clears a run's dismissal, so a retried run that fails again is back on the strip.
  • A Retry takes the before-run snapshot the same way a start does, when the story changed since the last snapshot.
  • Outside a run, meaning the Documents page's Preview context, the current chapter is the story's last chapter.
  • A length-rejected row that reports the prompt's token count joins the ratio's fold beside the completed rows. This is how "the ratio learns from the rejection" and "the ratio is derived from the ledger" both stay true.
  • Transcript file stamps are UTC as well as the date folders, so a folder never disagrees with its own files.
  • Whether BlazorAdapter implements the human-input port directly or through a UseCases port is decided with the human node in Phase 4.
  • Runs sits after History in the sidebar.

Also brought into line

  • ADR 0011's bridge now uses the new event kinds and buffer key.
  • ADR 0008's environment block lists the key override.
  • ADR 0019's privacy sentence covers template reads.
  • ADR 0014's registry now lives in Kagaku.Flow, not UseCases. That contradiction predated this PR.
  • ADR 0012's activeGraphId is nullable.
  • ARCHITECTURE.md's project list now includes the Kagaku.Flow packages.
  • PROJECT_PLAN's stale header ("Next: Phase 0") is refreshed. Phase 1 is marked built, and Phase 2 is renamed "the Continue graph" and carries the slice list.
  • REQUIREMENTS and six user stories are updated where they contradicted the above.
  • AGENTS.md's seed contract becomes "the statuses the shipped node types produce": Phase 2 seeds one succeeded and one failed run. It also documents TSUMUGI_FAKE_LLM for browser passes of a live run.

How it was checked

Five drafters worked on disjoint file groups. Three reviewers then read the result, one each for contradictions across all docs, fidelity to the plan (names, numbers, phases) and reader quality. They raised 118 points, and the drafters applied most of them. The rest were contradictions in files no drafter owned, which I fixed by hand. Every new relative link resolves. The added lines contain no planner-only references (decision numbers, file paths, line numbers).

31 files, all under docs/ plus AGENTS.md; no code.

🤖 Generated with Claude Code

Phase 2's second slice, and docs only. Planning the engine turned up places where two ADRs disagree (the gateway sits in `UseCases` per ADR 0018 but `Kagaku.Flow.OpenRouter` may not reference Tsumugi per ADR 0025) or leave something open (where the run pane lives, what a retried run does to its snapshot, how a failed run leaves the strip). This PR writes each decision into the ADR it belongs to. Every later slice is then reviewed against a written rule rather than a planner note. It must merge before the `Kagaku.Flow` core slice starts. Each amended ADR carries one dated line under Status, and its body is edited in place so it reads as the current rule. **Merging this PR is how the owner decisions below get confirmed.** Any of them can be reversed here at the cost of a docs edit. ## Decisions that need Björn's call 1. **The gateway moves** (0003, 0004, 0018, 0025). `ILlmGateway` lives in `Kagaku.Flow.OpenRouter`, over OpenRouter.Net, and the host supplies the key through `IOpenRouterKeySource`. `Tsumugi.UseCases` keeps a narrow `IModelProvider` for key validation and the catalog as Tsumugi DTOs, implemented in `Infrastructure`. `UseCases` never sees an OpenRouter type. 2. **`Kagaku.Flow` owns the run/ledger model** (0003, 0016, 0025). The records, statuses and `IRunLedger` belong to the library, and the core `Run` carries an opaque `OwnerId`. `Infrastructure` maps them onto its own EF entities, and `Tsumugi.Domain` models no runs. 3. **A length rejection is permanent in Phase 2** (0016, 0017). The `llm` row fails, naming the overflow, and the chars-per-token ratio learns from the reported token count. Automatic re-budgeting waits for re-run-from-node in Phase 5. 4. **Runs get their own section** (0024, 0027, 0010, 0020). The Run button sits in the chapter toolbar, and the streaming preview renders inline at the end of the target chapter. `stories/{id}/runs` holds run history and `stories/{id}/runs/{runId}` holds the monitor with the inspector pane, where `?node=` opens a node run. 5. **Continue is `context` → `llm` → an explicit `commit`** (0014, 0023). Its model is a concrete catalog id, not a `~…-latest` alias. **Which model id should it ship with?** A mid-price prose model you already use in nai_maker would be the natural pick. The implicit auto-commit of an unwired `llm` arrives with the editor in Phase 3. 6. **Summarize chapter moves to Phase 3** (0023, PROJECT_PLAN). It needs `set_chapter_summary`, a manuscript write tool that arrives with the `tool` node. 7. **Categories are selected by name** (0013, 0017). Names are matched case-insensitively after trimming, per run, and a missing one is skipped and reported. Selecting a single document waits for Phase 3's property panel. `story.documents(…)` and `.index(…)` require a category list. 8. **JsonSchema.Net becomes a dependency** of `Kagaku.Flow.OpenRouter` only, for validating structured output against a user schema (0018). 9. **Three library PRs gate Phase 2** (0018, PROJECT_PLAN): L1 (merged as OpenRouter.Net #14), L2 stream accumulation with typed failures, and a reduced L3. The streaming agent loop, concurrent tools with `parallel_tool_calls` and the typed structured-output helper move to the start of Phase 4, where they have consumers. 10. **Dismiss on the strip** (0024). A failed or cancelled run can be dismissed, which sets `acknowledgedAt`. A later success still never hides an undismissed failure. 11. **Graphs stay unjournaled until Phase 3** (0022, 0023). This is a dated exception, recorded in ADR 0022 itself: the story-keyed journal cannot hold an app-level graph. Switching a story's active graph stays a journaled story update. 12. **The package names stay** `Kagaku.Flow`, `Kagaku.Flow.OpenRouter`, plus the test-support package `Kagaku.Flow.Testing` (0025). 13. **One run snapshot per run id** (0022). When a run finishes again after a Retry, its existing snapshot moves to the latest journal position and is relabelled. Revert run still reverts the whole run. 14. **Routing defaults are inherited at run time** (0018; your settings request). Settings → Defaults gains a routing variant (Balanced, Fastest `:nitro`, Cheapest `:floor`, Most reliable with tools `:exacto`) and a service tier (Auto, Standard, Flex, Priority), with an optional zero-data-retention switch. An `llm` node that leaves routing unset uses the install-wide value when it runs, so the bundled templates follow your choice. A node that sets its own wins. ## Rules this PR adds that the plan did not state Filling these gaps took the smallest rule that made the ADRs agree. Please check them. - A node's `routing` also accepts **`balanced`**, which sends no suffix. Without it, a node could not ask for plain routing when the install default is Fastest. - The **zero-data-retention** switch is merged into every request's `provider` preferences, so no node can opt out. - Moving a graph that a story has active **to the trash is refused**, with the stories named. A story with no active graph has its Run button disabled with the reason. The foreign key's `SET NULL` only guards a hard purge. - **A Retry clears a run's dismissal**, so a retried run that fails again is back on the strip. - A Retry takes the before-run snapshot the same way a start does, when the story changed since the last snapshot. - Outside a run, meaning the Documents page's **Preview context**, the current chapter is the story's last chapter. - A length-rejected row that reports the prompt's token count **joins the ratio's fold** beside the completed rows. This is how "the ratio learns from the rejection" and "the ratio is derived from the ledger" both stay true. - Transcript **file stamps are UTC** as well as the date folders, so a folder never disagrees with its own files. - Whether `BlazorAdapter` implements the human-input port directly or through a `UseCases` port is decided with the `human` node in Phase 4. - Runs sits **after History** in the sidebar. ## Also brought into line - ADR 0011's bridge now uses the new event kinds and buffer key. - ADR 0008's environment block lists the key override. - ADR 0019's privacy sentence covers template reads. - ADR 0014's registry now lives in `Kagaku.Flow`, not `UseCases`. That contradiction predated this PR. - ADR 0012's `activeGraphId` is nullable. - ARCHITECTURE.md's project list now includes the `Kagaku.Flow` packages. - PROJECT_PLAN's stale header ("Next: Phase 0") is refreshed. Phase 1 is marked built, and Phase 2 is renamed "the Continue graph" and carries the slice list. - REQUIREMENTS and six user stories are updated where they contradicted the above. - AGENTS.md's seed contract becomes "the statuses the shipped node types produce": Phase 2 seeds one succeeded and one failed run. It also documents `TSUMUGI_FAKE_LLM` for browser passes of a live run. ## How it was checked Five drafters worked on disjoint file groups. Three reviewers then read the result, one each for contradictions across all docs, fidelity to the plan (names, numbers, phases) and reader quality. They raised 118 points, and the drafters applied most of them. The rest were contradictions in files no drafter owned, which I fixed by hand. Every new relative link resolves. The added lines contain no planner-only references (decision numbers, file paths, line numbers). 31 files, all under `docs/` plus `AGENTS.md`; no code. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
docs: Phase 2 decisions — where the engine's seams sit, where runs live, what gates the phase
All checks were successful
CI / build (pull_request) Successful in 29s
CI / test (pull_request) Successful in 50s
aba3e3fbbd
Records the Phase 2 planning decisions as amendments to the ADRs they
touch, so every engine slice is reviewed against a written rule:

- the model gateway and its key port live in Kagaku.Flow.OpenRouter;
  UseCases keeps a narrow IModelProvider; OpenRouter.Net is referenced
  by that package and Infrastructure (0003, 0004, 0018, 0025)
- Kagaku.Flow owns the run/ledger model, the run events with their
  text/reasoning channels and live tails, and the budgeting contract;
  descriptors declare attempts and concurrency slots (0011, 0015, 0016)
- failed-run, retry and boot-recovery semantics; one run snapshot per
  run id (0016, 0022)
- a run's target chapter; commit provenance names the writing node
  (0012, 0015)
- categories selected by name, story.documents requires a list, fixed
  section headings, the ratio derived from the ledger, a length
  rejection permanent in Phase 2 (0013, 0017, 0019)
- the key's environment override TSUMUGI_OPENROUTER_API_KEY (0006, 0008)
- the llm node's effort vocabulary and the install-wide routing
  defaults it inherits at run time (0018)
- graphs unjournaled until Phase 3; Continue alone in Phase 2;
  Summarize chapter moves to Phase 3 (0014, 0022, 0023)
- the Runs section as the run pane, Dismiss on the strip, UTC
  transcripts (0010, 0020, 0024, 0027)
- the agent loop, concurrent tools and the typed structured-output
  helper move to Phase 4; PROJECT_PLAN carries the Phase 2 slices;
  AGENTS.md's seed contract grows with the node types

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: aba3e3f · Generated: 2026-09-23 09:42:15 UTC · Revision: #1

Summary

Summary
Generated on: 09/23/2026 - 09:42:15
Coverage date: 09/23/2026 - 09:42:04 - 09/23/2026 - 09:42:13
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 263
Files: 256
Line coverage: 97.3% (5781 of 5936)
Covered lines: 5781
Uncovered lines: 155
Coverable lines: 5936
Total lines: 12811
Branch coverage: 90.3% (1609 of 1780)
Covered branches: 1609
Total branches: 1780
Method coverage: Feature is only available for sponsors

Coverage

Tsumugi.BlazorAdapter - 96.9%
Name Line Branch
Tsumugi.BlazorAdapter 96.9% 93.3%
Tsumugi.BlazorAdapter.BlazorAdapterAssembly 100%
Tsumugi.BlazorAdapter.Documents.CategoryCreated 100%
Tsumugi.BlazorAdapter.Documents.CategoryEditor 97.7% 86.1%
Tsumugi.BlazorAdapter.Documents.CategorySaved 100%
Tsumugi.BlazorAdapter.Documents.CreateCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.CreateDocumentRequested 100%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryDialog 100% 100%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.DeleteDocumentRequested 100%
Tsumugi.BlazorAdapter.Documents.DocumentAutoSaveFailed 100%
Tsumugi.BlazorAdapter.Documents.DocumentCreated 100%
Tsumugi.BlazorAdapter.Documents.DocumentEditor 100% 87.9%
Tsumugi.BlazorAdapter.Documents.DocumentsActionFailed 100%
Tsumugi.BlazorAdapter.Documents.DocumentSaved 100%
Tsumugi.BlazorAdapter.Documents.DocumentsEffects 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsList 98% 89.1%
Tsumugi.BlazorAdapter.Documents.DocumentsLoaded 100%
Tsumugi.BlazorAdapter.Documents.DocumentsPage 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsReducers 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsState 100% 100%
Tsumugi.BlazorAdapter.Documents.LoadDocuments 100%
Tsumugi.BlazorAdapter.Documents.MoveDocumentsRequested 100%
Tsumugi.BlazorAdapter.Documents.ReorderCategoriesRequested 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.ProviderSection 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsEffects 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsLoaded 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsReducers 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsState 100%
Tsumugi.BlazorAdapter.Settings.SaveLlmDefaultsRequested 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.AutoSaveFailed 100%
Tsumugi.BlazorAdapter.Workspace.CaretRequest 100%
Tsumugi.BlazorAdapter.Workspace.ChapterHeader 100% 86.3%
Tsumugi.BlazorAdapter.Workspace.ChapterMenu 100% 81.2%
Tsumugi.BlazorAdapter.Workspace.ChapterPage 100% 87.5%
Tsumugi.BlazorAdapter.Workspace.ChapterSaved 100%
Tsumugi.BlazorAdapter.Workspace.ChaptersPage 90% 83.3%
Tsumugi.BlazorAdapter.Workspace.CreateChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.DeleteChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.DeleteSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.EditSegmentRequested 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.InsertSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.LoadHistory 100%
Tsumugi.BlazorAdapter.Workspace.LoadWorkspace 100%
Tsumugi.BlazorAdapter.Workspace.ManuscriptColumn 94.9% 89.4%
Tsumugi.BlazorAdapter.Workspace.ManuscriptEffects 100% 100%
Tsumugi.BlazorAdapter.Workspace.MergeChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.MergeSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.MoveChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.RedoRequested 100%
Tsumugi.BlazorAdapter.Workspace.RedoRevertRequested 100%
Tsumugi.BlazorAdapter.Workspace.RenameChapterRequested 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.SegmentRow 100% 96.8%
Tsumugi.BlazorAdapter.Workspace.SegmentSaved 100%
Tsumugi.BlazorAdapter.Workspace.SetChapterSummaryRequested 100%
Tsumugi.BlazorAdapter.Workspace.SplitSegmentRequested 100%
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 - 99.3%
Name Line Branch
Tsumugi.Domain 99.3% 95.6%
Tsumugi.Domain.Documents.Document 100% 100%
Tsumugi.Domain.Documents.DocumentCategory 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.Provenance 100% 100%
Tsumugi.Domain.Stories.Segment 100% 100%
Tsumugi.Domain.Stories.Story 100% 100%
Tsumugi.Domain.Text 100% 100%
Tsumugi.Infrastructure - 97.1%
Name Line Branch
Tsumugi.Infrastructure 97.1% 82.4%
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.5% 83.3%
Tsumugi.Infrastructure.Backups.BackupWriter 98.4% 92.5%
Tsumugi.Infrastructure.Backups.FileSystemBackupStore 100% 100%
Tsumugi.Infrastructure.Backups.SqliteSnapshot 87.8% 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.StorySnapshotConfiguratio
n
100%
Tsumugi.Infrastructure.Persistence.Converters.ProvenanceConverter 100% 90%
Tsumugi.Infrastructure.Persistence.Converters.UtcTicksConverter 100%
Tsumugi.Infrastructure.Persistence.Migrations.AddAppSettings 99.2%
Tsumugi.Infrastructure.Persistence.Migrations.AddJournal 98.8%
Tsumugi.Infrastructure.Persistence.Migrations.GenericDocuments 100%
Tsumugi.Infrastructure.Persistence.Migrations.InitialStoryDomain 97.3%
Tsumugi.Infrastructure.Persistence.Migrations.TsumugiDbContextModelSnapshot 100%
Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor 100% 100%
Tsumugi.Infrastructure.Persistence.Stores.EfChapterStore 100% 100%
Tsumugi.Infrastructure.Persistence.Stores.EfDocumentStore 97.5% 90%
Tsumugi.Infrastructure.Persistence.Stores.EfSegmentStore 95% 84.6%
Tsumugi.Infrastructure.Persistence.Stores.EfStoryStore 98.3% 92.8%
Tsumugi.Infrastructure.Persistence.TsumugiDbContext 83.5% 93.1%
Tsumugi.Infrastructure.Persistence.TsumugiDbContextFactory 0%
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% 79%
Program 100% 83.3%
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.Security.AccessGate 100% 66.6%
Tsumugi.Server.Security.AccessSecret 100% 50%
Tsumugi.Server.VolumeStartupValidator 100% 100%
Tsumugi.UseCases - 98%
Name Line Branch
Tsumugi.UseCases 98% 94%
Tsumugi.UseCases.Backups.BackupArtifact 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.RunBackupNow 100%
Tsumugi.UseCases.Chapters.ChapterDto 100%
Tsumugi.UseCases.Chapters.CreateChapter 100% 100%
Tsumugi.UseCases.Chapters.DeleteChapter 100% 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.DependencyInjection 100%
Tsumugi.UseCases.Diagnostics.SeedDevData 97.3% 70%
Tsumugi.UseCases.Documents.CreateCategory 100% 100%
Tsumugi.UseCases.Documents.CreateDocument 100% 100%
Tsumugi.UseCases.Documents.DeleteCategory 100% 100%
Tsumugi.UseCases.Documents.DeleteDocument 100% 100%
Tsumugi.UseCases.Documents.DocumentCategoryDto 100%
Tsumugi.UseCases.Documents.DocumentCategoryProfile 100%
Tsumugi.UseCases.Documents.DocumentDto 100%
Tsumugi.UseCases.Documents.DocumentProfile 100%
Tsumugi.UseCases.Documents.DocumentsCategory 100%
Tsumugi.UseCases.Documents.DocumentsView 100%
Tsumugi.UseCases.Documents.GetDocuments 100% 100%
Tsumugi.UseCases.Documents.MoveDocuments 100% 100%
Tsumugi.UseCases.Documents.ReorderCategories 100% 100%
Tsumugi.UseCases.Documents.UpdateCategory 100% 100%
Tsumugi.UseCases.Documents.UpdateDocument 100% 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.DeleteSegments 100% 100%
Tsumugi.UseCases.Segments.EditSegment 100% 83.3%
Tsumugi.UseCases.Segments.InsertSegment 100% 100%
Tsumugi.UseCases.Segments.MergeSegmentWithPrevious 100% 100%
Tsumugi.UseCases.Segments.MoveSegments 100% 100%
Tsumugi.UseCases.Segments.ReorderSegments 100% 100%
Tsumugi.UseCases.Segments.SegmentDto 100%
Tsumugi.UseCases.Segments.SplitSegment 100% 100%
Tsumugi.UseCases.Settings.GetLlmDefaults 100% 100%
Tsumugi.UseCases.Settings.GetProviderSettings 100%
Tsumugi.UseCases.Settings.LlmDefaults 100%
Tsumugi.UseCases.Settings.ProviderSettingsView 100%
Tsumugi.UseCases.Settings.ReasoningEfforts 100% 100%
Tsumugi.UseCases.Settings.RemoveOpenRouterKey 100%
Tsumugi.UseCases.Settings.SaveLlmDefaults 100% 100%
Tsumugi.UseCases.Settings.SaveOpenRouterKey 100% 100%
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:** `aba3e3f` · **Generated:** 2026-09-23 09:42:15 UTC · **Revision:** #1 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 09/23/2026 - 09:42:15 | | Coverage date: | 09/23/2026 - 09:42:04 - 09/23/2026 - 09:42:13 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 6 | | Classes: | 263 | | Files: | 256 | | **Line coverage:** | 97.3% (5781 of 5936) | | Covered lines: | 5781 | | Uncovered lines: | 155 | | Coverable lines: | 5936 | | Total lines: | 12811 | | **Branch coverage:** | 90.3% (1609 of 1780) | | Covered branches: | 1609 | | Total branches: | 1780 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Tsumugi.BlazorAdapter - 96.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.BlazorAdapter**|**96.9%**|**93.3%**| |Tsumugi.BlazorAdapter.BlazorAdapterAssembly|100%|| |Tsumugi.BlazorAdapter.Documents.CategoryCreated|100%|| |Tsumugi.BlazorAdapter.Documents.CategoryEditor|97.7%|86.1%| |Tsumugi.BlazorAdapter.Documents.CategorySaved|100%|| |Tsumugi.BlazorAdapter.Documents.CreateCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.CreateDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryDialog|100%|100%| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentAutoSaveFailed|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentCreated|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentEditor|100%|87.9%| |Tsumugi.BlazorAdapter.Documents.DocumentsActionFailed|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentSaved|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsEffects|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsList|98%|89.1%| |Tsumugi.BlazorAdapter.Documents.DocumentsLoaded|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsPage|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsReducers|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsState|100%|100%| |Tsumugi.BlazorAdapter.Documents.LoadDocuments|100%|| |Tsumugi.BlazorAdapter.Documents.MoveDocumentsRequested|100%|| |Tsumugi.BlazorAdapter.Documents.ReorderCategoriesRequested|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.ProviderSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsEffects|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsReducers|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsState|100%|| |Tsumugi.BlazorAdapter.Settings.SaveLlmDefaultsRequested|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.AutoSaveFailed|100%|| |Tsumugi.BlazorAdapter.Workspace.CaretRequest|100%|| |Tsumugi.BlazorAdapter.Workspace.ChapterHeader|100%|86.3%| |Tsumugi.BlazorAdapter.Workspace.ChapterMenu|100%|81.2%| |Tsumugi.BlazorAdapter.Workspace.ChapterPage|100%|87.5%| |Tsumugi.BlazorAdapter.Workspace.ChapterSaved|100%|| |Tsumugi.BlazorAdapter.Workspace.ChaptersPage|90%|83.3%| |Tsumugi.BlazorAdapter.Workspace.CreateChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.DeleteChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.DeleteSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.EditSegmentRequested|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.InsertSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.LoadHistory|100%|| |Tsumugi.BlazorAdapter.Workspace.LoadWorkspace|100%|| |Tsumugi.BlazorAdapter.Workspace.ManuscriptColumn|94.9%|89.4%| |Tsumugi.BlazorAdapter.Workspace.ManuscriptEffects|100%|100%| |Tsumugi.BlazorAdapter.Workspace.MergeChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.MergeSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.MoveChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RedoRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RedoRevertRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RenameChapterRequested|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.SegmentRow|100%|96.8%| |Tsumugi.BlazorAdapter.Workspace.SegmentSaved|100%|| |Tsumugi.BlazorAdapter.Workspace.SetChapterSummaryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SplitSegmentRequested|100%|| |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 - 99.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Domain**|**99.3%**|**95.6%**| |Tsumugi.Domain.Documents.Document|100%|100%| |Tsumugi.Domain.Documents.DocumentCategory|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.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.1%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Infrastructure**|**97.1%**|**82.4%**| |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.5%|83.3%| |Tsumugi.Infrastructure.Backups.BackupWriter|98.4%|92.5%| |Tsumugi.Infrastructure.Backups.FileSystemBackupStore|100%|100%| |Tsumugi.Infrastructure.Backups.SqliteSnapshot|87.8%|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.StorySnapshotConfiguratio<br/>n|100%|| |Tsumugi.Infrastructure.Persistence.Converters.ProvenanceConverter|100%|90%| |Tsumugi.Infrastructure.Persistence.Converters.UtcTicksConverter|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.AddAppSettings|99.2%|| |Tsumugi.Infrastructure.Persistence.Migrations.AddJournal|98.8%|| |Tsumugi.Infrastructure.Persistence.Migrations.GenericDocuments|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.InitialStoryDomain|97.3%|| |Tsumugi.Infrastructure.Persistence.Migrations.TsumugiDbContextModelSnapshot|100%|| |Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor|100%|100%| |Tsumugi.Infrastructure.Persistence.Stores.EfChapterStore|100%|100%| |Tsumugi.Infrastructure.Persistence.Stores.EfDocumentStore|97.5%|90%| |Tsumugi.Infrastructure.Persistence.Stores.EfSegmentStore|95%|84.6%| |Tsumugi.Infrastructure.Persistence.Stores.EfStoryStore|98.3%|92.8%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContext|83.5%|93.1%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContextFactory|0%|| |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%**|**79%**| |Program|100%|83.3%| |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.Security.AccessGate|100%|66.6%| |Tsumugi.Server.Security.AccessSecret|100%|50%| |Tsumugi.Server.VolumeStartupValidator|100%|100%| </details> <details><summary>Tsumugi.UseCases - 98%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.UseCases**|**98%**|**94%**| |Tsumugi.UseCases.Backups.BackupArtifact|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.RunBackupNow|100%|| |Tsumugi.UseCases.Chapters.ChapterDto|100%|| |Tsumugi.UseCases.Chapters.CreateChapter|100%|100%| |Tsumugi.UseCases.Chapters.DeleteChapter|100%|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.DependencyInjection|100%|| |Tsumugi.UseCases.Diagnostics.SeedDevData|97.3%|70%| |Tsumugi.UseCases.Documents.CreateCategory|100%|100%| |Tsumugi.UseCases.Documents.CreateDocument|100%|100%| |Tsumugi.UseCases.Documents.DeleteCategory|100%|100%| |Tsumugi.UseCases.Documents.DeleteDocument|100%|100%| |Tsumugi.UseCases.Documents.DocumentCategoryDto|100%|| |Tsumugi.UseCases.Documents.DocumentCategoryProfile|100%|| |Tsumugi.UseCases.Documents.DocumentDto|100%|| |Tsumugi.UseCases.Documents.DocumentProfile|100%|| |Tsumugi.UseCases.Documents.DocumentsCategory|100%|| |Tsumugi.UseCases.Documents.DocumentsView|100%|| |Tsumugi.UseCases.Documents.GetDocuments|100%|100%| |Tsumugi.UseCases.Documents.MoveDocuments|100%|100%| |Tsumugi.UseCases.Documents.ReorderCategories|100%|100%| |Tsumugi.UseCases.Documents.UpdateCategory|100%|100%| |Tsumugi.UseCases.Documents.UpdateDocument|100%|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.DeleteSegments|100%|100%| |Tsumugi.UseCases.Segments.EditSegment|100%|83.3%| |Tsumugi.UseCases.Segments.InsertSegment|100%|100%| |Tsumugi.UseCases.Segments.MergeSegmentWithPrevious|100%|100%| |Tsumugi.UseCases.Segments.MoveSegments|100%|100%| |Tsumugi.UseCases.Segments.ReorderSegments|100%|100%| |Tsumugi.UseCases.Segments.SegmentDto|100%|| |Tsumugi.UseCases.Segments.SplitSegment|100%|100%| |Tsumugi.UseCases.Settings.GetLlmDefaults|100%|100%| |Tsumugi.UseCases.Settings.GetProviderSettings|100%|| |Tsumugi.UseCases.Settings.LlmDefaults|100%|| |Tsumugi.UseCases.Settings.ProviderSettingsView|100%|| |Tsumugi.UseCases.Settings.ReasoningEfforts|100%|100%| |Tsumugi.UseCases.Settings.RemoveOpenRouterKey|100%|| |Tsumugi.UseCases.Settings.SaveLlmDefaults|100%|100%| |Tsumugi.UseCases.Settings.SaveOpenRouterKey|100%|100%| |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! Thirty-one files, eight hundred twelve lines, and not one line of code — this is a decisions PR, the kind where a single contradiction left behind will quietly mislead six months of engineering. So I read all 2,234 diff lines and then went hunting through the docs you didn't touch for everything you did invalidate. Fufu~ you made that boring. In the best way. ♡

Verdict: ✅ Looks good to me~

What I verified mechanically (docs-only, so the checks are semantic, not builds):

  • Every amended ADR carries its dated Status line — all 21 of them (0003, 0004, 0006, 0008, 0010–0020, 0022–0025, 0027), correctly stacked after the PR #13/#14 amendments rather than replacing them.
  • Zero broken relative links across all 31 changed files (checked every ](…) against the tree at aba3e3f).
  • The rename sweeps are complete. NodeCompleted/RunFinished survive only in 0016 (defining the new NodeSettled/RunSettled set) and 0011 (consuming it, with the new buffer key run/node/iteration-path/channel) — no third speaker anywhere. Same for maxAttempts → MaxAttempts, the Run-button move to the chapter toolbar (0012, 0014, 0023, 0027, REQUIREMENTS, story-workspace, graph-library — all in lockstep), storyId → opaque ownerId, and the re-seed rule ("on upgrade" → "on every start" in body and consequences).
  • The old retry-halves-the-margin rule is gone from 0017, the length rejection now sits in 0016's permanent-failure list, and PROJECT_PLAN risk 4 was rewritten to match — the three agree exactly, including the ratio fold (a rejection reporting the prompt's token count joins the EMA over the last 50 rows — which is what keeps "the ratio is derived from the ledger" true).
  • The three-way lifecycle closes. Dismiss sets acknowledgedAt (0016 field ↔ 0024 strip rule ↔ run-monitor story), retry clears the dismissal and takes a before-run snapshot "as a start does" (0022), and the one-snapshot-per-run rule is stated identically in 0022, 0016 and 0024. A retried run that fails again is back on the strip; a later success still never hides an undismissed failure. That's a closed state machine, not vibes. ♪
  • Cross-citations are factually true. 0024 claims transcripts are UTC-stamped "as backups are named — ADR 0026" → 0026:19 really says UTC. 0024 promises per-story cost "shown on the story list" → story-list.md:15 already carries that cell. 0021:58's unchanged "a context node with no consumer is an error" survives correctly beside 0017's new consumer-asking wording — the validation rule was about existence of a consumer, and IBudgetedConsumer keeps that meaning.
  • The slice DAG is satisfiable: 5 after 2, 6 after 5, 9 after 6, 11a parallel with 7–10b — none of the four no-OpenRouter slices needs L2/L3, exactly as the plan claims.
  • No planner-only residue in the added lines (no decision numbers, file paths, line numbers).

And the headline decisions themselves, fufu, they're good: ILlmGateway moving to Kagaku.Flow.OpenRouter behind IOpenRouterKeySource resolves the 0018-vs-0025 contradiction at the seam it actually sits on; the ledger model belonging to the library with OwnerId opaque and Infrastructure doing the EF mapping is exactly where the dependency should point; and IBudgetedConsumer — the context node asking its downstream consumers for their budget through the registry instead of reading another package's config off the edge — is the kind of inversion that makes me genuinely giddy. The wire-capture design (AsyncLocal scope + DelegatingHandler, so the inspector shows bytes, not re-serialization) is the same shape. Oh~ ♡

💡 Little ideas (non-blocking)~

  1. REQUIREMENTS.md:109 — still words it "one live run per story" while 0016 now says "one live run per owner" (with Tsumugi's owner named as the story). Not wrong — the requirements speak product terms — but the terminology shifted underneath it; a one-word touch-up whenever §6 is next edited would keep the echoes aligned.
  2. ADR 0020, the card bullet — the reworded sentence now wraps awkwardly in source ("…the question as / markdown; options as…") where the surrounding bullets kept their line shape. Renders identically; purely a source-readability nit for the next amendment.

✅ What I liked~

  • The story.documents(categories) change is made everywhere at once — 0013's built-ins table, 0013's prose, 0017's table, 0017's prose, and the privacy sentence restated in 0019. Nothing half-renamed anywhere. That discipline across five files is what I checked for, and it's flawless.
  • The open questions are labeled as open (cursor-becomes-target in 0012 + story-workspace + 0027; the BlazorAdapter port decision parked with Phase 4) rather than silently decided — exactly what an ADR set owes its readers.
  • Amendment 11 (graphs unjournaled until Phase 3) is recorded as a dated exception inside 0022 itself, with the no-doorbell consequence ("another session sees a graph change when it next loads") spelled out instead of discovered. That's the honest way to break a rule.

Merging this is the owner-decision gate the PR body promises — the eleven numbered calls are all visible in the amendments, reversible by docs edit, as claimed.


Automated review by Jibril · 2026-09-23
CI/CD: absent for head SHA (docs-only PR, no coverage bot) · Local checks: full-diff read + link checker (0 broken) + stale-phrase and cross-ADR contradiction sweeps, all clean

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! Thirty-one files, eight hundred twelve lines, and not one line of code — this is a *decisions* PR, the kind where a single contradiction left behind will quietly mislead six months of engineering. So I read all 2,234 diff lines and then went hunting through the docs you *didn't* touch for everything you *did* invalidate. Fufu~ you made that boring. In the best way. ♡ ### Verdict: ✅ Looks good to me~ **What I verified mechanically** (docs-only, so the checks are semantic, not builds): - **Every amended ADR carries its dated Status line** — all 21 of them (`0003, 0004, 0006, 0008, 0010–0020, 0022–0025, 0027`), correctly stacked after the PR #13/#14 amendments rather than replacing them. - **Zero broken relative links** across all 31 changed files (checked every `](…)` against the tree at `aba3e3f`). - **The rename sweeps are complete.** `NodeCompleted`/`RunFinished` survive only in `0016` (defining the new `NodeSettled`/`RunSettled` set) and `0011` (consuming it, with the new buffer key run/node/iteration-path/channel) — no third speaker anywhere. Same for `maxAttempts` → `MaxAttempts`, the Run-button move to the chapter toolbar (0012, 0014, 0023, 0027, REQUIREMENTS, story-workspace, graph-library — all in lockstep), `storyId` → opaque `ownerId`, and the re-seed rule ("on upgrade" → "on every start" in body *and* consequences). - **The old retry-halves-the-margin rule is gone from 0017**, the length rejection now sits in 0016's permanent-failure list, and PROJECT_PLAN risk 4 was rewritten to match — the three agree exactly, including the ratio fold (a rejection reporting the prompt's token count joins the EMA over the last 50 rows — which is what keeps "the ratio is derived from the ledger" true). - **The three-way lifecycle closes.** Dismiss sets `acknowledgedAt` (0016 field ↔ 0024 strip rule ↔ run-monitor story), retry clears the dismissal and takes a before-run snapshot "as a start does" (0022), and the one-snapshot-per-run rule is stated identically in 0022, 0016 and 0024. A retried run that fails again is back on the strip; a later success still never hides an undismissed failure. That's a closed state machine, not vibes. ♪ - **Cross-citations are factually true.** 0024 claims transcripts are UTC-stamped "as backups are named — ADR 0026" → 0026:19 really says UTC. 0024 promises per-story cost "shown on the story list" → story-list.md:15 already carries that cell. 0021:58's unchanged "a `context` node with no consumer is an error" survives correctly beside 0017's new consumer-asking wording — the validation rule was about *existence* of a consumer, and `IBudgetedConsumer` keeps that meaning. - **The slice DAG is satisfiable**: 5 after 2, 6 after 5, 9 after 6, 11a parallel with 7–10b — none of the four no-OpenRouter slices needs L2/L3, exactly as the plan claims. - **No planner-only residue** in the added lines (no decision numbers, file paths, line numbers). And the headline decisions themselves, fufu, they're *good*: `ILlmGateway` moving to `Kagaku.Flow.OpenRouter` behind `IOpenRouterKeySource` resolves the 0018-vs-0025 contradiction at the seam it actually sits on; the ledger model belonging to the library with `OwnerId` opaque and Infrastructure doing the EF mapping is exactly where the dependency should point; and `IBudgetedConsumer` — the context node *asking* its downstream consumers for their budget through the registry instead of reading another package's config off the edge — is the kind of inversion that makes me genuinely giddy. The wire-capture design (AsyncLocal scope + DelegatingHandler, so the inspector shows bytes, not re-serialization) is the same shape. Oh~ ♡ #### 💡 Little ideas (non-blocking)~ 1. **REQUIREMENTS.md:109** — still words it "one live run per story" while 0016 now says "one live run per **owner**" (with Tsumugi's owner named as the story). Not wrong — the requirements speak product terms — but the terminology shifted underneath it; a one-word touch-up whenever §6 is next edited would keep the echoes aligned. 2. **ADR 0020, the card bullet** — the reworded sentence now wraps awkwardly in source ("…the question as / markdown; options as…") where the surrounding bullets kept their line shape. Renders identically; purely a source-readability nit for the next amendment. #### ✅ What I liked~ - The `story.documents(categories)` change is made *everywhere at once* — 0013's built-ins table, 0013's prose, 0017's table, 0017's prose, and the privacy sentence restated in 0019. Nothing half-renamed anywhere. That discipline across five files is what I checked for, and it's flawless. - The open questions are *labeled as open* (cursor-becomes-target in 0012 + story-workspace + 0027; the BlazorAdapter port decision parked with Phase 4) rather than silently decided — exactly what an ADR set owes its readers. - Amendment 11 (graphs unjournaled until Phase 3) is recorded as a **dated exception inside 0022 itself**, with the no-doorbell consequence ("another session sees a graph change when it next loads") spelled out instead of discovered. That's the honest way to break a rule. Merging this is the owner-decision gate the PR body promises — the eleven numbered calls are all visible in the amendments, reversible by docs edit, as claimed. --- *Automated review by Jibril · 2026-09-23* *CI/CD: absent for head SHA (docs-only PR, no coverage bot) · Local checks: full-diff read + link checker (0 broken) + stale-phrase and cross-ADR contradiction sweeps, all clean*
bjoern merged commit 0c00476af3 into main 2026-09-23 11:58:05 +02:00
bjoern deleted branch docs/phase-2-decisions 2026-09-23 11:58:05 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 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!16
No description provided.