feat: the run monitor becomes a status board — grouped columns, page order, tab deep-links #54

Merged
bjoern merged 2 commits from feat/run-monitor-board into main 2026-08-13 06:23:57 +02:00
Member

Field feedback on the first real annotation run: the expanded monitor panel was "a mess and not useful" — a flat log in row-insertion order, "Bbox refinement pending" a dozen times with no page identity, failures buried mid-list. This PR turns it into a status board (graph-monitor story, ADR 0018) and makes its "open page" links land on the right view.

What's in

  • BlazorAdapter — the board. One column per live status in pipeline order — Pending, Running, Completed, Sent back, Failed — each with a count badge; only statuses that exist render. Failed sits rightmost as the "needs me" edge. Columns lay out as an even grid, stacking on a narrow shell.
  • Page identity and order. Rows sort by the page's reading order (page-less stages like setup first), then the roster's pipeline order — never insertion order — and each page-bound row shows its page number ("Bbox creation · p4", chapter-qualified only when the project has several chapters). The monitor effect resolves page ids to labels with a workspace ride-along (GetProjectWorkspace); a vanished project degrades to unlabeled rows, never a crash. The MonitorPageRef map lives in the monitor slice next to the run it belongs to.
  • Deep links. The page workspace's Tabs are now URL-bound like the bible's (Param="tab", stable ids raw/bbox/translation/cleaned/typeset), and the monitor's "open page" carries the stage's tab: ?tab=bbox for all four annotation stages (transcription's jp lives in the Bbox editor), ?tab=translation reserved for the future translation stage. The redundant per-row status text is gone — the column header names it.

Tests — 507 total (was 505), all green.

  • RunMonitorTests +1, 1 adjusted: the new Rows_follow_the_pages_reading_order_and_name_their_pages seeds executions deliberately shuffled across three pages and asserts the exact rendered sequence ("Bbox creation p1 → Bbox refinement p1 → Transcription p2 → Bbox creation p3") — pinning that insertion order does not survive; the existing expand test now also asserts the group-header sequence (Pending → Completed → Sent back → Failed) and that "open page" carries ?tab=bbox.
  • PageWorkspacePageTests +1: A_view_tab_is_deep_linkable navigates with ?tab=bbox and asserts the Bbox panel rendered and the Raw panel did not — the monitor's link contract from the receiving side.

Browser-verified against the seeded world's mid-pipeline run: the board renders Completed(2) / Sent back(1) / Failed(1) columns with page numbers, costs, and inline errors; clicking the failed row's "open page" landed on the page with the Bbox tab active (checked via aria-selected).

Honest notes

  • The workspace ride-along re-reads on every coalesced monitor reload. The bridge already collapses engine bursts into single re-reads, and the read is one in-process query — no caching added until it measurably matters.
  • Group order puts Failed last per the pipeline-flow reading (pending → … → needs me). If failures should instead lead, it's a one-line rank change.

🤖 Generated with Claude Code

Field feedback on the first real annotation run: the expanded monitor panel was "a mess and not useful" — a flat log in row-insertion order, "Bbox refinement pending" a dozen times with no page identity, failures buried mid-list. This PR turns it into a status board (graph-monitor story, ADR 0018) and makes its "open page" links land on the right view. **What's in** - *BlazorAdapter — the board.* One column per live status in pipeline order — **Pending, Running, Completed, Sent back, Failed** — each with a count badge; only statuses that exist render. Failed sits rightmost as the "needs me" edge. Columns lay out as an even grid, stacking on a narrow shell. - *Page identity and order.* Rows sort by the page's reading order (page-less stages like setup first), then the roster's pipeline order — never insertion order — and each page-bound row shows its page number ("Bbox creation · p4", chapter-qualified only when the project has several chapters). The monitor effect resolves page ids to labels with a workspace ride-along (`GetProjectWorkspace`); a vanished project degrades to unlabeled rows, never a crash. The `MonitorPageRef` map lives in the monitor slice next to the run it belongs to. - *Deep links.* The page workspace's Tabs are now URL-bound like the bible's (`Param="tab"`, stable ids `raw/bbox/translation/cleaned/typeset`), and the monitor's "open page" carries the stage's tab: `?tab=bbox` for all four annotation stages (transcription's `jp` lives in the Bbox editor), `?tab=translation` reserved for the future translation stage. The redundant per-row status text is gone — the column header names it. **Tests** — 507 total (was 505), all green. - `RunMonitorTests` +1, 1 adjusted: the new `Rows_follow_the_pages_reading_order_and_name_their_pages` seeds executions deliberately shuffled across three pages and asserts the exact rendered sequence ("Bbox creation p1 → Bbox refinement p1 → Transcription p2 → Bbox creation p3") — pinning that insertion order does not survive; the existing expand test now also asserts the group-header sequence (Pending → Completed → Sent back → Failed) and that "open page" carries `?tab=bbox`. - `PageWorkspacePageTests` +1: `A_view_tab_is_deep_linkable` navigates with `?tab=bbox` and asserts the Bbox panel rendered and the Raw panel did not — the monitor's link contract from the receiving side. **Browser-verified** against the seeded world's mid-pipeline run: the board renders Completed(2) / Sent back(1) / Failed(1) columns with page numbers, costs, and inline errors; clicking the failed row's "open page" landed on the page with the Bbox tab active (checked via `aria-selected`). **Honest notes** - The workspace ride-along re-reads on every coalesced monitor reload. The bridge already collapses engine bursts into single re-reads, and the read is one in-process query — no caching added until it measurably matters. - Group order puts Failed last per the pipeline-flow reading (pending → … → needs me). If failures should instead lead, it's a one-line rank change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat: the run monitor becomes a status board — grouped columns, page order, tab deep-links
All checks were successful
CI / build (pull_request) Successful in 24s
CI / test (pull_request) Successful in 40s
84c20707f3
The expanded panel was a flat log in row-insertion order: 'Bbox refinement
pending' twelve times with no page names, failures buried mid-list. Now it is
a status board (graph-monitor story, ADR 0018):

- One column per live status, in pipeline order — Pending, Running, Completed,
  Sent back, Failed — each with a count; only statuses that exist render.
- Rows sort by the page's reading order (page-less stages like setup first),
  then the roster's pipeline order — never insertion order — and carry their
  page number ('Bbox creation · p4'; chapter-qualified when a project has
  several chapters). The effect resolves ids to labels via the workspace read;
  a vanished project degrades to unlabeled rows, never a crash.
- 'open page' deep-links onto the tab the stage's work lives on (?tab=bbox for
  the annotation stages, ?tab=translation later): the page workspace's Tabs
  are now URL-bound (Param="tab", stable ids) like the bible's.

Browser-verified against the seeded world's mid-pipeline run: the board shows
Completed/Sent back/Failed columns with page numbers and inline errors, and
the failed row's link lands on the page with the Bbox tab active.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Summary

Summary
Generated on: 07/26/2026 - 11:42:42
Coverage date: 07/26/2026 - 11:42:27 - 07/26/2026 - 11:42:39
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 363
Files: 167
Line coverage: 94% (8778 of 9332)
Covered lines: 8778
Uncovered lines: 554
Coverable lines: 9332
Total lines: 17286
Branch coverage: 80.6% (1951 of 2419)
Covered branches: 1951
Total branches: 2419
Method coverage: Feature is only available for sponsors

Coverage

Orihon.BlazorAdapter - 95.8%
Name Line Branch
Orihon.BlazorAdapter 95.8% 88.5%
Orihon.BlazorAdapter.Bible.AddBeatRowRequested 100%
Orihon.BlazorAdapter.Bible.AddCharacterRowRequested 100%
Orihon.BlazorAdapter.Bible.AddGlossaryRowRequested 100%
Orihon.BlazorAdapter.Bible.AddLoreRowRequested 100%
Orihon.BlazorAdapter.Bible.BibleEffects 92.2% 79.1%
Orihon.BlazorAdapter.Bible.BibleLoaded 100%
Orihon.BlazorAdapter.Bible.BiblePage 93.7% 81.6%
Orihon.BlazorAdapter.Bible.BibleReducers 93.1%
Orihon.BlazorAdapter.Bible.BibleState 100%
Orihon.BlazorAdapter.Bible.BibleWriteFailed 100%
Orihon.BlazorAdapter.Bible.DeleteBeatRowRequested 100%
Orihon.BlazorAdapter.Bible.DeleteCharacterRowRequested 100%
Orihon.BlazorAdapter.Bible.DeleteGlossaryRowRequested 100%
Orihon.BlazorAdapter.Bible.DeleteLoreRowRequested 0%
Orihon.BlazorAdapter.Bible.LoadBible 100%
Orihon.BlazorAdapter.Bible.ReorderBeatsRequested 0%
Orihon.BlazorAdapter.Bible.SaveOverviewRequested 100%
Orihon.BlazorAdapter.Bible.SaveSummaryRequested 100%
Orihon.BlazorAdapter.Bible.UpdateBeatRowRequested 100%
Orihon.BlazorAdapter.Bible.UpdateCharacterRowRequested 100%
Orihon.BlazorAdapter.Bible.UpdateGlossaryRowRequested 100%
Orihon.BlazorAdapter.Bible.UpdateLoreRowRequested 100%
Orihon.BlazorAdapter.BlazorAdapterAssembly 100%
Orihon.BlazorAdapter.Debounce 92.5% 88.8%
Orihon.BlazorAdapter.Diagnostics.CircuitError 100%
Orihon.BlazorAdapter.Diagnostics.CircuitErrorPanel 100%
Orihon.BlazorAdapter.Diagnostics.CircuitErrorSink 100% 85.7%
Orihon.BlazorAdapter.Diagnostics.OrihonStoreInitializer 85.7% 66.6%
Orihon.BlazorAdapter.PageWorkspace.CreateRegionRequested 100%
Orihon.BlazorAdapter.PageWorkspace.DeletePageSummaryRequested 100%
Orihon.BlazorAdapter.PageWorkspace.DeleteRegionRequested 100%
Orihon.BlazorAdapter.PageWorkspace.LoadPageWorkspace 100%
Orihon.BlazorAdapter.PageWorkspace.PageSummarySaved 100%
Orihon.BlazorAdapter.PageWorkspace.PageViewport 100% 100%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceEffects 100% 100%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceLoaded 100%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspacePage 90.9% 84.7%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceReducers 100% 66.6%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceState 100%
Orihon.BlazorAdapter.PageWorkspace.PageWriteFailed 100%
Orihon.BlazorAdapter.PageWorkspace.RegionCreated 100%
Orihon.BlazorAdapter.PageWorkspace.RegionSaved 100%
Orihon.BlazorAdapter.PageWorkspace.ReorderRegionsRequested 100%
Orihon.BlazorAdapter.PageWorkspace.ReprocessPageRequested 100%
Orihon.BlazorAdapter.PageWorkspace.SavePageSummaryRequested 100%
Orihon.BlazorAdapter.PageWorkspace.SaveRegionRequested 100%
Orihon.BlazorAdapter.PageWorkspace.SetPageMetaRequested 100%
Orihon.BlazorAdapter.Projects.CreateProjectRequested 100%
Orihon.BlazorAdapter.Projects.DecideSetupContinuation 100%
Orihon.BlazorAdapter.Projects.DeleteProjectRequested 100%
Orihon.BlazorAdapter.Projects.FinishSetupRequested 100%
Orihon.BlazorAdapter.Projects.ImportPagesRequested 100%
Orihon.BlazorAdapter.Projects.LoadWizard 100%
Orihon.BlazorAdapter.Projects.PagesImported 100%
Orihon.BlazorAdapter.Projects.ProjectDeleteFailed 100%
Orihon.BlazorAdapter.Projects.ProjectListEffects 100% 100%
Orihon.BlazorAdapter.Projects.ProjectListPage 89.7% 91.1%
Orihon.BlazorAdapter.Projects.ProjectListReducers 100%
Orihon.BlazorAdapter.Projects.ProjectListState 100%
Orihon.BlazorAdapter.Projects.ProjectsLoaded 100%
Orihon.BlazorAdapter.Projects.ProjectWizardEffects 100% 100%
Orihon.BlazorAdapter.Projects.ProjectWizardPage 94.1% 86.2%
Orihon.BlazorAdapter.Projects.ProjectWizardReducers 100%
Orihon.BlazorAdapter.Projects.ProjectWizardState 100%
Orihon.BlazorAdapter.Projects.SetupChat 93.5% 100%
Orihon.BlazorAdapter.Projects.SetupChatEffects 100% 100%
Orihon.BlazorAdapter.Projects.SetupChatFailed 100%
Orihon.BlazorAdapter.Projects.SetupChatReducers 100%
Orihon.BlazorAdapter.Projects.SetupChatState 100%
Orihon.BlazorAdapter.Projects.SetupChatUpdated 100%
Orihon.BlazorAdapter.Projects.StartSetupChat 100%
Orihon.BlazorAdapter.Projects.SubmitSetupAnswer 100%
Orihon.BlazorAdapter.Projects.WizardLoaded 100%
Orihon.BlazorAdapter.Projects.WizardWriteFailed 100%
Orihon.BlazorAdapter.Runs.MonitorPageRef 100%
Orihon.BlazorAdapter.Runs.MonitorRunLoaded 100%
Orihon.BlazorAdapter.Runs.RunChangedBridge 94.1% 91.6%
Orihon.BlazorAdapter.Runs.RunMonitor 97.5% 95.3%
Orihon.BlazorAdapter.Runs.RunMonitorEffects 100% 91.6%
Orihon.BlazorAdapter.Runs.RunMonitorReducers 100%
Orihon.BlazorAdapter.Runs.RunMonitorState 100%
Orihon.BlazorAdapter.Settings.AgentModelPicked 100%
Orihon.BlazorAdapter.Settings.AgentModelSaved 100%
Orihon.BlazorAdapter.Settings.AgentModelSaveFailed 100%
Orihon.BlazorAdapter.Settings.KeySaved 100%
Orihon.BlazorAdapter.Settings.KeySaveFailed 100%
Orihon.BlazorAdapter.Settings.ModelOptionsLoaded 100%
Orihon.BlazorAdapter.Settings.ModelOptionsUnavailable 100%
Orihon.BlazorAdapter.Settings.SaveKeyRequested 100%
Orihon.BlazorAdapter.Settings.SettingsEffects 100% 100%
Orihon.BlazorAdapter.Settings.SettingsLoaded 100%
Orihon.BlazorAdapter.Settings.SettingsPage 100% 90.4%
Orihon.BlazorAdapter.Settings.SettingsReducers 100%
Orihon.BlazorAdapter.Settings.SettingsState 100%
Orihon.BlazorAdapter.Uploads.UploadTransfer 96.5% 100%
Orihon.BlazorAdapter.Uploads.UploadTransferProgress 100% 100%
Orihon.BlazorAdapter.Uploads.UploadTransferResult 100%
Orihon.BlazorAdapter.Workspace.CreateChapterRequested 100%
Orihon.BlazorAdapter.Workspace.DeleteChapterRequested 100%
Orihon.BlazorAdapter.Workspace.DeletePageRequested 100%
Orihon.BlazorAdapter.Workspace.DeleteSummaryRequested 100%
Orihon.BlazorAdapter.Workspace.LoadProjectWorkspace 100%
Orihon.BlazorAdapter.Workspace.MovePageRequested 100%
Orihon.BlazorAdapter.Workspace.ProjectMetadataCard 95.2% 92.8%
Orihon.BlazorAdapter.Workspace.ProjectMetadataSaved 100%
Orihon.BlazorAdapter.Workspace.ProjectWorkspaceEffects 100% 100%
Orihon.BlazorAdapter.Workspace.ProjectWorkspaceLoaded 100%
Orihon.BlazorAdapter.Workspace.ProjectWorkspacePage 96.6% 89.6%
Orihon.BlazorAdapter.Workspace.ProjectWorkspaceReducers 100% 62.5%
Orihon.BlazorAdapter.Workspace.ProjectWorkspaceState 100%
Orihon.BlazorAdapter.Workspace.RenameChapterRequested 100%
Orihon.BlazorAdapter.Workspace.ReorderChaptersRequested 100%
Orihon.BlazorAdapter.Workspace.ReorderPagesRequested 100%
Orihon.BlazorAdapter.Workspace.RunAnnotationRequested 100%
Orihon.BlazorAdapter.Workspace.SaveProjectMetadataRequested 100%
Orihon.BlazorAdapter.Workspace.SaveSummaryRequested 100%
Orihon.BlazorAdapter.Workspace.SetPageKindRequested 100%
Orihon.BlazorAdapter.Workspace.SummaryDeleted 100%
Orihon.BlazorAdapter.Workspace.SummarySaved 100%
Orihon.BlazorAdapter.Workspace.WorkspaceImportRequested 100%
Orihon.BlazorAdapter.Workspace.WorkspaceWriteFailed 100%
Orihon.Domain - 100%
Name Line Branch
Orihon.Domain 100% 100%
Orihon.Domain.Agents.AgentDescriptor 100%
Orihon.Domain.Agents.AgentRoster 100% 100%
Orihon.Domain.Bible.Character 100% 100%
Orihon.Domain.Bible.GlossaryEntry 100% 100%
Orihon.Domain.Bible.LoreEntry 100% 100%
Orihon.Domain.Bible.PageSummary 100%
Orihon.Domain.Bible.StoryBeat 100%
Orihon.Domain.Bible.StoryOverview 100%
Orihon.Domain.Projects.Project 100% 100%
Orihon.Domain.Projects.ProjectProfile 100%
Orihon.Domain.Runs.Execution 100% 100%
Orihon.Domain.Runs.Run 100%
Orihon.Domain.Settings.AppSetting 100%
Orihon.Domain.Text 100% 100%
Orihon.Domain.Translation.BoundingBox 100%
Orihon.Domain.Translation.Chapter 100%
Orihon.Domain.Translation.Page 100%
Orihon.Domain.Translation.Region 100% 100%
Orihon.Domain.Translation.RegionProfile 100%
Orihon.Infrastructure - 94.3%
Name Line Branch
Orihon.Infrastructure 94.3% 67.3%
Orihon.Infrastructure.Bible.EfBibleStore 94.4% 91.6%
Orihon.Infrastructure.DependencyInjection 100%
Orihon.Infrastructure.Gateways.AgentToolAdapter 100%
Orihon.Infrastructure.Gateways.AgentToolAdapter`1 100% 100%
Orihon.Infrastructure.Gateways.HttpWebPageFetcher 95.1% 83.3%
Orihon.Infrastructure.Gateways.OpenRouterLlmGateway 98% 83%
Orihon.Infrastructure.Gateways.SkiaPageImageRenderer 96.6% 86.1%
Orihon.Infrastructure.Persistence.Configurations.AppSettingConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.ChapterConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.CharacterConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.ExecutionConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.GlossaryEntryConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.JsonColumnMapper 100%
Orihon.Infrastructure.Persistence.Configurations.LoreEntryConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.PageConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.PageSummaryConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.ProjectConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.RegionConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.RunConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.StoryBeatConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.StoryOverviewConfiguration 100%
Orihon.Infrastructure.Persistence.Converters.UtcTicksConverter 100%
Orihon.Infrastructure.Persistence.Migrations.AddAppSettings 99.3%
Orihon.Infrastructure.Persistence.Migrations.AddRuns 99.1%
Orihon.Infrastructure.Persistence.Migrations.AddStoryOverview 99.5%
Orihon.Infrastructure.Persistence.Migrations.InitialTranslationDomain 97.3%
Orihon.Infrastructure.Persistence.Migrations.OrihonDbContextModelSnapshot 100%
Orihon.Infrastructure.Persistence.OrihonDbContext 100%
Orihon.Infrastructure.Persistence.OrihonDbContextFactory 100%
Orihon.Infrastructure.Projects.EfProjectStore 100% 100%
Orihon.Infrastructure.Projects.FileSystemPageImageStore 100% 100%
Orihon.Infrastructure.Runs.EfRunStore 97% 50%
Orihon.Infrastructure.Settings.EfAppSettingsStore 100% 100%
Orihon.Infrastructure.Translation.EfChapterStore 100% 100%
Orihon.Infrastructure.Translation.EfPageStore 86% 80%
Orihon.Infrastructure.Translation.EfRegionStore 100% 100%
Orihon.Infrastructure.Translation.Ordering 100% 100%
System.Text.RegularExpressions.Generated 70.6% 53.3%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlankLines_4
77.9% 76.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlockBreaks_1
59% 42.5%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__SpaceRuns_3
89.4% 75%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__Tags_2
83.7% 62.5%
Orihon.Kernel - 90.9%
Name Line Branch
Orihon.Kernel 90.9% 75%
Orihon.Kernel.Err`1 100%
Orihon.Kernel.Ok`1 100%
Orihon.Kernel.Result`1 88.8% 75%
Orihon.Server - 93.4%
Name Line Branch
Orihon.Server 93.4% 68.4%
Orihon.Server.Components.App 100%
Orihon.Server.Components.Layout.MainLayout 100%
Orihon.Server.Components.Pages.Gate 64.2% 66.6%
Orihon.Server.RunEngineBootstrap 100%
Orihon.Server.Security.AccessGate 91.8% 41.6%
Orihon.Server.Security.AccessSecret 100% 50%
Orihon.Server.VolumeStartupValidator 100% 100%
Program 95.4% 85.7%
Orihon.UseCases - 91%
Name Line Branch
Orihon.UseCases 91% 83.2%
Orihon.UseCases.Agents.AgentAttemptPreparation 100%
Orihon.UseCases.Agents.AgentAttemptSupport 100% 92.8%
Orihon.UseCases.Agents.AgentBlueprint 100%
Orihon.UseCases.Agents.AgentInvocation 100%
Orihon.UseCases.Agents.AgentOutcome 100%
Orihon.UseCases.Agents.AgentTool`1 90.9% 75%
Orihon.UseCases.Agents.AgentToolImage 100%
Orihon.UseCases.Agents.AgentToolResult 100%
Orihon.UseCases.Agents.Annotation.AddRegionParams 100%
Orihon.UseCases.Agents.Annotation.AddRegionTool 76.9% 50%
Orihon.UseCases.Agents.Annotation.AnnotationBlueprints 100%
Orihon.UseCases.Agents.Annotation.AnnotationStage 94.7% 50%
Orihon.UseCases.Agents.Annotation.BboxCreationExecutor 94.1% 50%
Orihon.UseCases.Agents.Annotation.BboxRefinementExecutor 90.4% 62.5%
Orihon.UseCases.Agents.Annotation.BoundBoxParams 0%
Orihon.UseCases.Agents.Annotation.BoundContactSheetParams 0%
Orihon.UseCases.Agents.Annotation.BoundContactSheetTool 10.7% 0%
Orihon.UseCases.Agents.Annotation.BoundCropParams 0%
Orihon.UseCases.Agents.Annotation.BoundCropTool 42.8%
Orihon.UseCases.Agents.Annotation.BoundViewAnnotatedTool 15% 0%
Orihon.UseCases.Agents.Annotation.BoundViewPageTool 18.7% 0%
Orihon.UseCases.Agents.Annotation.BoundViewParams 0%
Orihon.UseCases.Agents.Annotation.BoundZoomParams 0%
Orihon.UseCases.Agents.Annotation.BoundZoomTool 37.5%
Orihon.UseCases.Agents.Annotation.DeleteBoundRegionTool 91.6% 100%
Orihon.UseCases.Agents.Annotation.DeleteRegionParams 100%
Orihon.UseCases.Agents.Annotation.DeleteRegionTool 85.7% 100%
Orihon.UseCases.Agents.Annotation.FindGlossaryParams 100%
Orihon.UseCases.Agents.Annotation.FindGlossaryTool 76.4% 62.5%
Orihon.UseCases.Agents.Annotation.ListRegionsTool 76.4% 60%
Orihon.UseCases.Agents.Annotation.MoveResizeBoundTool 27.2% 0%
Orihon.UseCases.Agents.Annotation.MoveResizeRegionParams 100%
Orihon.UseCases.Agents.Annotation.MoveResizeRegionTool 73.3% 50%
Orihon.UseCases.Agents.Annotation.PageQaExecutor 94.4% 83.3%
Orihon.UseCases.Agents.Annotation.QaReportSink 100%
Orihon.UseCases.Agents.Annotation.RegionAuthoringAccess 86.6% 53.8%
Orihon.UseCases.Agents.Annotation.RejectRegionParams 100%
Orihon.UseCases.Agents.Annotation.RejectRegionTool 85.7% 50%
Orihon.UseCases.Agents.Annotation.ReorderRegionParams 100%
Orihon.UseCases.Agents.Annotation.ReorderRegionTool 80% 60%
Orihon.UseCases.Agents.Annotation.ReportQaParams 100%
Orihon.UseCases.Agents.Annotation.ReportQaTool 82.3% 93.7%
Orihon.UseCases.Agents.Annotation.SetPageMetaParams 100%
Orihon.UseCases.Agents.Annotation.SetPageMetaTool 85.7% 75%
Orihon.UseCases.Agents.Annotation.SetRegionTypeParams 100%
Orihon.UseCases.Agents.Annotation.SetRegionTypeTool 85.7% 87.5%
Orihon.UseCases.Agents.Annotation.SetTranscriptionParams 100%
Orihon.UseCases.Agents.Annotation.SetTranscriptionTool 80% 100%
Orihon.UseCases.Agents.Annotation.TranscriptionExecutor 90.4% 75%
Orihon.UseCases.Agents.AssistantSpoke 100%
Orihon.UseCases.Agents.Inspection.ContactSheetParams 100%
Orihon.UseCases.Agents.Inspection.ContactSheetTool 82.1% 92.8%
Orihon.UseCases.Agents.Inspection.CropParams 100%
Orihon.UseCases.Agents.Inspection.CropTool 42.8%
Orihon.UseCases.Agents.Inspection.PageImageAccess 66.6% 62%
Orihon.UseCases.Agents.Inspection.ViewAnnotatedParams 100%
Orihon.UseCases.Agents.Inspection.ViewAnnotatedTool 76.1% 83.3%
Orihon.UseCases.Agents.Inspection.ZoomParams 100%
Orihon.UseCases.Agents.Inspection.ZoomTool 44.4%
Orihon.UseCases.Agents.ResearchSetup.AddGlossaryParams 100%
Orihon.UseCases.Agents.ResearchSetup.AddGlossaryTool 100% 100%
Orihon.UseCases.Agents.ResearchSetup.AddStoryBeatParams 100%
Orihon.UseCases.Agents.ResearchSetup.AddStoryBeatTool 100% 50%
Orihon.UseCases.Agents.ResearchSetup.AskUserParams 100%
Orihon.UseCases.Agents.ResearchSetup.AskUserTool 100% 100%
Orihon.UseCases.Agents.ResearchSetup.FetchUrlParams 100%
Orihon.UseCases.Agents.ResearchSetup.FetchUrlTool 100% 100%
Orihon.UseCases.Agents.ResearchSetup.ListBibleTool 89.4% 100%
Orihon.UseCases.Agents.ResearchSetup.PageByNumber 90% 87.5%
Orihon.UseCases.Agents.ResearchSetup.ResearchSetupBlueprint 100%
Orihon.UseCases.Agents.ResearchSetup.SetPageMetaParams 100%
Orihon.UseCases.Agents.ResearchSetup.SetPageMetaTool 95.2% 90%
Orihon.UseCases.Agents.ResearchSetup.SetPageSummaryParams 100%
Orihon.UseCases.Agents.ResearchSetup.SetPageSummaryTool 100% 75%
Orihon.UseCases.Agents.ResearchSetup.SetProjectMetadataParams 100%
Orihon.UseCases.Agents.ResearchSetup.SetProjectMetadataTool 96.1% 90.9%
Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewParams 100%
Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewTool 100% 100%
Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterParams 100%
Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterTool 91.3% 66.6%
Orihon.UseCases.Agents.ResearchSetup.UpsertLoreParams 100%
Orihon.UseCases.Agents.ResearchSetup.UpsertLoreTool 91.3% 66.6%
Orihon.UseCases.Agents.ResearchSetup.ViewPageParams 100%
Orihon.UseCases.Agents.ResearchSetup.ViewPageTool 100% 100%
Orihon.UseCases.Agents.Setup.ResearchSetupExecutor 97.2% 89.2%
Orihon.UseCases.Agents.Setup.SetupChatEntry 100%
Orihon.UseCases.Agents.Setup.SetupConversation 100% 87.5%
Orihon.UseCases.Agents.Setup.SetupConversationRegistry 100%
Orihon.UseCases.Agents.ToolCalled 100%
Orihon.UseCases.Agents.ToolCompleted 100%
Orihon.UseCases.Bible.AddCharacter 100% 100%
Orihon.UseCases.Bible.AddGlossaryEntry 100% 100%
Orihon.UseCases.Bible.AddLoreEntry 100% 100%
Orihon.UseCases.Bible.AddStoryBeat 100% 100%
Orihon.UseCases.Bible.BibleDto 100%
Orihon.UseCases.Bible.CharacterDto 100%
Orihon.UseCases.Bible.DeleteCharacter 100% 100%
Orihon.UseCases.Bible.DeleteGlossaryEntry 100% 100%
Orihon.UseCases.Bible.DeleteLoreEntry 100% 100%
Orihon.UseCases.Bible.DeletePageSummary 100% 100%
Orihon.UseCases.Bible.DeleteStoryBeat 100% 100%
Orihon.UseCases.Bible.GetBible 100% 100%
Orihon.UseCases.Bible.GlossaryEntryDto 100%
Orihon.UseCases.Bible.LoreEntryDto 100%
Orihon.UseCases.Bible.PageSummaryDto 100%
Orihon.UseCases.Bible.ReorderStoryBeats 100%
Orihon.UseCases.Bible.SetPageSummary 100% 100%
Orihon.UseCases.Bible.SetStoryOverview 100% 100%
Orihon.UseCases.Bible.StoryBeatDto 100%
Orihon.UseCases.Bible.StoryOverviewDto 100%
Orihon.UseCases.Bible.UpdateCharacter 100% 100%
Orihon.UseCases.Bible.UpdateGlossaryEntry 100% 100%
Orihon.UseCases.Bible.UpdateLoreEntry 100% 100%
Orihon.UseCases.Bible.UpdateStoryBeat 100% 100%
Orihon.UseCases.Chapters.ChapterDto 100%
Orihon.UseCases.Chapters.CreateChapter 100% 100%
Orihon.UseCases.Chapters.DeleteChapter 100% 100%
Orihon.UseCases.Chapters.RenameChapter 100% 100%
Orihon.UseCases.Chapters.ReorderChapters 100%
Orihon.UseCases.DependencyInjection 100%
Orihon.UseCases.Diagnostics.SeedDevData 99.2% 92.8%
Orihon.UseCases.Gateways.LabeledBox 100%
Orihon.UseCases.Gateways.LlmKeyInfo 100%
Orihon.UseCases.Gateways.LlmModel 100%
Orihon.UseCases.NextOrder 100%
Orihon.UseCases.Pages.DeletePage 100% 100%
Orihon.UseCases.Pages.GetPage 100% 100%
Orihon.UseCases.Pages.GetProjectWorkspace 100% 100%
Orihon.UseCases.Pages.ImportPages 100% 100%
Orihon.UseCases.Pages.ImportPagesResult 100%
Orihon.UseCases.Pages.MarkPageAnnotated 100% 100%
Orihon.UseCases.Pages.MovePage 100% 92.8%
Orihon.UseCases.Pages.PageDetailDto 100%
Orihon.UseCases.Pages.PageDto 100%
Orihon.UseCases.Pages.PageUpload 100%
Orihon.UseCases.Pages.ProjectWorkspaceDto 100%
Orihon.UseCases.Pages.ReorderPages 100%
Orihon.UseCases.Pages.SetPageMeta 100% 100%
Orihon.UseCases.Pages.WorkspaceChapterDto 100%
Orihon.UseCases.Projects.CompleteProjectSetup 100% 93.7%
Orihon.UseCases.Projects.CreateProject 100% 100%
Orihon.UseCases.Projects.DeleteProject 100% 100%
Orihon.UseCases.Projects.GetProject 100% 100%
Orihon.UseCases.Projects.ListProjects 100%
Orihon.UseCases.Projects.ProjectDto 95.8%
Orihon.UseCases.Projects.StartAnnotationRun 95.4% 90%
Orihon.UseCases.Projects.StartSetupRun 100% 100%
Orihon.UseCases.Projects.StoredPageImage 100%
Orihon.UseCases.Projects.UpdateProjectMetadata 100% 100%
Orihon.UseCases.Regions.CreateRegion 100% 100%
Orihon.UseCases.Regions.DeleteRegion 100% 100%
Orihon.UseCases.Regions.RegionDto 97%
Orihon.UseCases.Regions.ReorderRegions 100%
Orihon.UseCases.Regions.UpdateRegion 100% 100%
Orihon.UseCases.Runs.AnnotationPipeline 100% 100%
Orihon.UseCases.Runs.ExecutionDto 92.3%
Orihon.UseCases.Runs.PlannedExecution 100%
Orihon.UseCases.Runs.ReprocessPage 100% 94.4%
Orihon.UseCases.Runs.RunDto 93.3% 100%
Orihon.UseCases.Runs.RunEngine 95.3% 90.6%
Orihon.UseCases.Runs.RunEngineOptions 100%
Orihon.UseCases.Runs.StageContext 87.5%
Orihon.UseCases.Runs.StageHaltedException 100%
Orihon.UseCases.Settings.AgentSettingDto 100% 100%
Orihon.UseCases.Settings.GetSettings 100% 100%
Orihon.UseCases.Settings.ListModelOptions 100% 100%
Orihon.UseCases.Settings.SaveAgentModel 100% 100%
Orihon.UseCases.Settings.SaveOpenRouterKey 100% 100%
Orihon.UseCases.Settings.SettingKeys 100% 100%
Orihon.UseCases.Settings.SettingsDto 100%
<!-- coverage-comment --> # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 07/26/2026 - 11:42:42 | | Coverage date: | 07/26/2026 - 11:42:27 - 07/26/2026 - 11:42:39 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 6 | | Classes: | 363 | | Files: | 167 | | **Line coverage:** | 94% (8778 of 9332) | | Covered lines: | 8778 | | Uncovered lines: | 554 | | Coverable lines: | 9332 | | Total lines: | 17286 | | **Branch coverage:** | 80.6% (1951 of 2419) | | Covered branches: | 1951 | | Total branches: | 2419 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Orihon.BlazorAdapter - 95.8%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.BlazorAdapter**|**95.8%**|**88.5%**| |Orihon.BlazorAdapter.Bible.AddBeatRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddCharacterRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddGlossaryRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddLoreRowRequested|100%|| |Orihon.BlazorAdapter.Bible.BibleEffects|92.2%|79.1%| |Orihon.BlazorAdapter.Bible.BibleLoaded|100%|| |Orihon.BlazorAdapter.Bible.BiblePage|93.7%|81.6%| |Orihon.BlazorAdapter.Bible.BibleReducers|93.1%|| |Orihon.BlazorAdapter.Bible.BibleState|100%|| |Orihon.BlazorAdapter.Bible.BibleWriteFailed|100%|| |Orihon.BlazorAdapter.Bible.DeleteBeatRowRequested|100%|| |Orihon.BlazorAdapter.Bible.DeleteCharacterRowRequested|100%|| |Orihon.BlazorAdapter.Bible.DeleteGlossaryRowRequested|100%|| |Orihon.BlazorAdapter.Bible.DeleteLoreRowRequested|0%|| |Orihon.BlazorAdapter.Bible.LoadBible|100%|| |Orihon.BlazorAdapter.Bible.ReorderBeatsRequested|0%|| |Orihon.BlazorAdapter.Bible.SaveOverviewRequested|100%|| |Orihon.BlazorAdapter.Bible.SaveSummaryRequested|100%|| |Orihon.BlazorAdapter.Bible.UpdateBeatRowRequested|100%|| |Orihon.BlazorAdapter.Bible.UpdateCharacterRowRequested|100%|| |Orihon.BlazorAdapter.Bible.UpdateGlossaryRowRequested|100%|| |Orihon.BlazorAdapter.Bible.UpdateLoreRowRequested|100%|| |Orihon.BlazorAdapter.BlazorAdapterAssembly|100%|| |Orihon.BlazorAdapter.Debounce|92.5%|88.8%| |Orihon.BlazorAdapter.Diagnostics.CircuitError|100%|| |Orihon.BlazorAdapter.Diagnostics.CircuitErrorPanel|100%|| |Orihon.BlazorAdapter.Diagnostics.CircuitErrorSink|100%|85.7%| |Orihon.BlazorAdapter.Diagnostics.OrihonStoreInitializer|85.7%|66.6%| |Orihon.BlazorAdapter.PageWorkspace.CreateRegionRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.DeletePageSummaryRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.DeleteRegionRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.LoadPageWorkspace|100%|| |Orihon.BlazorAdapter.PageWorkspace.PageSummarySaved|100%|| |Orihon.BlazorAdapter.PageWorkspace.PageViewport|100%|100%| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceEffects|100%|100%| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceLoaded|100%|| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspacePage|90.9%|84.7%| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceReducers|100%|66.6%| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceState|100%|| |Orihon.BlazorAdapter.PageWorkspace.PageWriteFailed|100%|| |Orihon.BlazorAdapter.PageWorkspace.RegionCreated|100%|| |Orihon.BlazorAdapter.PageWorkspace.RegionSaved|100%|| |Orihon.BlazorAdapter.PageWorkspace.ReorderRegionsRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.ReprocessPageRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.SavePageSummaryRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.SaveRegionRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.SetPageMetaRequested|100%|| |Orihon.BlazorAdapter.Projects.CreateProjectRequested|100%|| |Orihon.BlazorAdapter.Projects.DecideSetupContinuation|100%|| |Orihon.BlazorAdapter.Projects.DeleteProjectRequested|100%|| |Orihon.BlazorAdapter.Projects.FinishSetupRequested|100%|| |Orihon.BlazorAdapter.Projects.ImportPagesRequested|100%|| |Orihon.BlazorAdapter.Projects.LoadWizard|100%|| |Orihon.BlazorAdapter.Projects.PagesImported|100%|| |Orihon.BlazorAdapter.Projects.ProjectDeleteFailed|100%|| |Orihon.BlazorAdapter.Projects.ProjectListEffects|100%|100%| |Orihon.BlazorAdapter.Projects.ProjectListPage|89.7%|91.1%| |Orihon.BlazorAdapter.Projects.ProjectListReducers|100%|| |Orihon.BlazorAdapter.Projects.ProjectListState|100%|| |Orihon.BlazorAdapter.Projects.ProjectsLoaded|100%|| |Orihon.BlazorAdapter.Projects.ProjectWizardEffects|100%|100%| |Orihon.BlazorAdapter.Projects.ProjectWizardPage|94.1%|86.2%| |Orihon.BlazorAdapter.Projects.ProjectWizardReducers|100%|| |Orihon.BlazorAdapter.Projects.ProjectWizardState|100%|| |Orihon.BlazorAdapter.Projects.SetupChat|93.5%|100%| |Orihon.BlazorAdapter.Projects.SetupChatEffects|100%|100%| |Orihon.BlazorAdapter.Projects.SetupChatFailed|100%|| |Orihon.BlazorAdapter.Projects.SetupChatReducers|100%|| |Orihon.BlazorAdapter.Projects.SetupChatState|100%|| |Orihon.BlazorAdapter.Projects.SetupChatUpdated|100%|| |Orihon.BlazorAdapter.Projects.StartSetupChat|100%|| |Orihon.BlazorAdapter.Projects.SubmitSetupAnswer|100%|| |Orihon.BlazorAdapter.Projects.WizardLoaded|100%|| |Orihon.BlazorAdapter.Projects.WizardWriteFailed|100%|| |Orihon.BlazorAdapter.Runs.MonitorPageRef|100%|| |Orihon.BlazorAdapter.Runs.MonitorRunLoaded|100%|| |Orihon.BlazorAdapter.Runs.RunChangedBridge|94.1%|91.6%| |Orihon.BlazorAdapter.Runs.RunMonitor|97.5%|95.3%| |Orihon.BlazorAdapter.Runs.RunMonitorEffects|100%|91.6%| |Orihon.BlazorAdapter.Runs.RunMonitorReducers|100%|| |Orihon.BlazorAdapter.Runs.RunMonitorState|100%|| |Orihon.BlazorAdapter.Settings.AgentModelPicked|100%|| |Orihon.BlazorAdapter.Settings.AgentModelSaved|100%|| |Orihon.BlazorAdapter.Settings.AgentModelSaveFailed|100%|| |Orihon.BlazorAdapter.Settings.KeySaved|100%|| |Orihon.BlazorAdapter.Settings.KeySaveFailed|100%|| |Orihon.BlazorAdapter.Settings.ModelOptionsLoaded|100%|| |Orihon.BlazorAdapter.Settings.ModelOptionsUnavailable|100%|| |Orihon.BlazorAdapter.Settings.SaveKeyRequested|100%|| |Orihon.BlazorAdapter.Settings.SettingsEffects|100%|100%| |Orihon.BlazorAdapter.Settings.SettingsLoaded|100%|| |Orihon.BlazorAdapter.Settings.SettingsPage|100%|90.4%| |Orihon.BlazorAdapter.Settings.SettingsReducers|100%|| |Orihon.BlazorAdapter.Settings.SettingsState|100%|| |Orihon.BlazorAdapter.Uploads.UploadTransfer|96.5%|100%| |Orihon.BlazorAdapter.Uploads.UploadTransferProgress|100%|100%| |Orihon.BlazorAdapter.Uploads.UploadTransferResult|100%|| |Orihon.BlazorAdapter.Workspace.CreateChapterRequested|100%|| |Orihon.BlazorAdapter.Workspace.DeleteChapterRequested|100%|| |Orihon.BlazorAdapter.Workspace.DeletePageRequested|100%|| |Orihon.BlazorAdapter.Workspace.DeleteSummaryRequested|100%|| |Orihon.BlazorAdapter.Workspace.LoadProjectWorkspace|100%|| |Orihon.BlazorAdapter.Workspace.MovePageRequested|100%|| |Orihon.BlazorAdapter.Workspace.ProjectMetadataCard|95.2%|92.8%| |Orihon.BlazorAdapter.Workspace.ProjectMetadataSaved|100%|| |Orihon.BlazorAdapter.Workspace.ProjectWorkspaceEffects|100%|100%| |Orihon.BlazorAdapter.Workspace.ProjectWorkspaceLoaded|100%|| |Orihon.BlazorAdapter.Workspace.ProjectWorkspacePage|96.6%|89.6%| |Orihon.BlazorAdapter.Workspace.ProjectWorkspaceReducers|100%|62.5%| |Orihon.BlazorAdapter.Workspace.ProjectWorkspaceState|100%|| |Orihon.BlazorAdapter.Workspace.RenameChapterRequested|100%|| |Orihon.BlazorAdapter.Workspace.ReorderChaptersRequested|100%|| |Orihon.BlazorAdapter.Workspace.ReorderPagesRequested|100%|| |Orihon.BlazorAdapter.Workspace.RunAnnotationRequested|100%|| |Orihon.BlazorAdapter.Workspace.SaveProjectMetadataRequested|100%|| |Orihon.BlazorAdapter.Workspace.SaveSummaryRequested|100%|| |Orihon.BlazorAdapter.Workspace.SetPageKindRequested|100%|| |Orihon.BlazorAdapter.Workspace.SummaryDeleted|100%|| |Orihon.BlazorAdapter.Workspace.SummarySaved|100%|| |Orihon.BlazorAdapter.Workspace.WorkspaceImportRequested|100%|| |Orihon.BlazorAdapter.Workspace.WorkspaceWriteFailed|100%|| </details> <details><summary>Orihon.Domain - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Domain**|**100%**|**100%**| |Orihon.Domain.Agents.AgentDescriptor|100%|| |Orihon.Domain.Agents.AgentRoster|100%|100%| |Orihon.Domain.Bible.Character|100%|100%| |Orihon.Domain.Bible.GlossaryEntry|100%|100%| |Orihon.Domain.Bible.LoreEntry|100%|100%| |Orihon.Domain.Bible.PageSummary|100%|| |Orihon.Domain.Bible.StoryBeat|100%|| |Orihon.Domain.Bible.StoryOverview|100%|| |Orihon.Domain.Projects.Project|100%|100%| |Orihon.Domain.Projects.ProjectProfile|100%|| |Orihon.Domain.Runs.Execution|100%|100%| |Orihon.Domain.Runs.Run|100%|| |Orihon.Domain.Settings.AppSetting|100%|| |Orihon.Domain.Text|100%|100%| |Orihon.Domain.Translation.BoundingBox|100%|| |Orihon.Domain.Translation.Chapter|100%|| |Orihon.Domain.Translation.Page|100%|| |Orihon.Domain.Translation.Region|100%|100%| |Orihon.Domain.Translation.RegionProfile|100%|| </details> <details><summary>Orihon.Infrastructure - 94.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Infrastructure**|**94.3%**|**67.3%**| |Orihon.Infrastructure.Bible.EfBibleStore|94.4%|91.6%| |Orihon.Infrastructure.DependencyInjection|100%|| |Orihon.Infrastructure.Gateways.AgentToolAdapter|100%|| |Orihon.Infrastructure.Gateways.AgentToolAdapter`1|100%|100%| |Orihon.Infrastructure.Gateways.HttpWebPageFetcher|95.1%|83.3%| |Orihon.Infrastructure.Gateways.OpenRouterLlmGateway|98%|83%| |Orihon.Infrastructure.Gateways.SkiaPageImageRenderer|96.6%|86.1%| |Orihon.Infrastructure.Persistence.Configurations.AppSettingConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.ChapterConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.CharacterConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.ExecutionConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.GlossaryEntryConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.JsonColumnMapper|100%|| |Orihon.Infrastructure.Persistence.Configurations.LoreEntryConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.PageConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.PageSummaryConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.ProjectConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.RegionConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.RunConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.StoryBeatConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.StoryOverviewConfiguration|100%|| |Orihon.Infrastructure.Persistence.Converters.UtcTicksConverter|100%|| |Orihon.Infrastructure.Persistence.Migrations.AddAppSettings|99.3%|| |Orihon.Infrastructure.Persistence.Migrations.AddRuns|99.1%|| |Orihon.Infrastructure.Persistence.Migrations.AddStoryOverview|99.5%|| |Orihon.Infrastructure.Persistence.Migrations.InitialTranslationDomain|97.3%|| |Orihon.Infrastructure.Persistence.Migrations.OrihonDbContextModelSnapshot|100%|| |Orihon.Infrastructure.Persistence.OrihonDbContext|100%|| |Orihon.Infrastructure.Persistence.OrihonDbContextFactory|100%|| |Orihon.Infrastructure.Projects.EfProjectStore|100%|100%| |Orihon.Infrastructure.Projects.FileSystemPageImageStore|100%|100%| |Orihon.Infrastructure.Runs.EfRunStore|97%|50%| |Orihon.Infrastructure.Settings.EfAppSettingsStore|100%|100%| |Orihon.Infrastructure.Translation.EfChapterStore|100%|100%| |Orihon.Infrastructure.Translation.EfPageStore|86%|80%| |Orihon.Infrastructure.Translation.EfRegionStore|100%|100%| |Orihon.Infrastructure.Translation.Ordering|100%|100%| |System.Text.RegularExpressions.Generated|70.6%|53.3%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030<br/>A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlankLines_4|77.9%|76.6%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030<br/>A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlockBreaks_1|59%|42.5%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030<br/>A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__SpaceRuns_3|89.4%|75%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F7FCA343D2B99030<br/>A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__Tags_2|83.7%|62.5%| </details> <details><summary>Orihon.Kernel - 90.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Kernel**|**90.9%**|**75%**| |Orihon.Kernel.Err`1|100%|| |Orihon.Kernel.Ok`1|100%|| |Orihon.Kernel.Result`1|88.8%|75%| </details> <details><summary>Orihon.Server - 93.4%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Server**|**93.4%**|**68.4%**| |Orihon.Server.Components.App|100%|| |Orihon.Server.Components.Layout.MainLayout|100%|| |Orihon.Server.Components.Pages.Gate|64.2%|66.6%| |Orihon.Server.RunEngineBootstrap|100%|| |Orihon.Server.Security.AccessGate|91.8%|41.6%| |Orihon.Server.Security.AccessSecret|100%|50%| |Orihon.Server.VolumeStartupValidator|100%|100%| |Program|95.4%|85.7%| </details> <details><summary>Orihon.UseCases - 91%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.UseCases**|**91%**|**83.2%**| |Orihon.UseCases.Agents.AgentAttemptPreparation|100%|| |Orihon.UseCases.Agents.AgentAttemptSupport|100%|92.8%| |Orihon.UseCases.Agents.AgentBlueprint|100%|| |Orihon.UseCases.Agents.AgentInvocation|100%|| |Orihon.UseCases.Agents.AgentOutcome|100%|| |Orihon.UseCases.Agents.AgentTool`1|90.9%|75%| |Orihon.UseCases.Agents.AgentToolImage|100%|| |Orihon.UseCases.Agents.AgentToolResult|100%|| |Orihon.UseCases.Agents.Annotation.AddRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.AddRegionTool|76.9%|50%| |Orihon.UseCases.Agents.Annotation.AnnotationBlueprints|100%|| |Orihon.UseCases.Agents.Annotation.AnnotationStage|94.7%|50%| |Orihon.UseCases.Agents.Annotation.BboxCreationExecutor|94.1%|50%| |Orihon.UseCases.Agents.Annotation.BboxRefinementExecutor|90.4%|62.5%| |Orihon.UseCases.Agents.Annotation.BoundBoxParams|0%|| |Orihon.UseCases.Agents.Annotation.BoundContactSheetParams|0%|| |Orihon.UseCases.Agents.Annotation.BoundContactSheetTool|10.7%|0%| |Orihon.UseCases.Agents.Annotation.BoundCropParams|0%|| |Orihon.UseCases.Agents.Annotation.BoundCropTool|42.8%|| |Orihon.UseCases.Agents.Annotation.BoundViewAnnotatedTool|15%|0%| |Orihon.UseCases.Agents.Annotation.BoundViewPageTool|18.7%|0%| |Orihon.UseCases.Agents.Annotation.BoundViewParams|0%|| |Orihon.UseCases.Agents.Annotation.BoundZoomParams|0%|| |Orihon.UseCases.Agents.Annotation.BoundZoomTool|37.5%|| |Orihon.UseCases.Agents.Annotation.DeleteBoundRegionTool|91.6%|100%| |Orihon.UseCases.Agents.Annotation.DeleteRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.DeleteRegionTool|85.7%|100%| |Orihon.UseCases.Agents.Annotation.FindGlossaryParams|100%|| |Orihon.UseCases.Agents.Annotation.FindGlossaryTool|76.4%|62.5%| |Orihon.UseCases.Agents.Annotation.ListRegionsTool|76.4%|60%| |Orihon.UseCases.Agents.Annotation.MoveResizeBoundTool|27.2%|0%| |Orihon.UseCases.Agents.Annotation.MoveResizeRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.MoveResizeRegionTool|73.3%|50%| |Orihon.UseCases.Agents.Annotation.PageQaExecutor|94.4%|83.3%| |Orihon.UseCases.Agents.Annotation.QaReportSink|100%|| |Orihon.UseCases.Agents.Annotation.RegionAuthoringAccess|86.6%|53.8%| |Orihon.UseCases.Agents.Annotation.RejectRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.RejectRegionTool|85.7%|50%| |Orihon.UseCases.Agents.Annotation.ReorderRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.ReorderRegionTool|80%|60%| |Orihon.UseCases.Agents.Annotation.ReportQaParams|100%|| |Orihon.UseCases.Agents.Annotation.ReportQaTool|82.3%|93.7%| |Orihon.UseCases.Agents.Annotation.SetPageMetaParams|100%|| |Orihon.UseCases.Agents.Annotation.SetPageMetaTool|85.7%|75%| |Orihon.UseCases.Agents.Annotation.SetRegionTypeParams|100%|| |Orihon.UseCases.Agents.Annotation.SetRegionTypeTool|85.7%|87.5%| |Orihon.UseCases.Agents.Annotation.SetTranscriptionParams|100%|| |Orihon.UseCases.Agents.Annotation.SetTranscriptionTool|80%|100%| |Orihon.UseCases.Agents.Annotation.TranscriptionExecutor|90.4%|75%| |Orihon.UseCases.Agents.AssistantSpoke|100%|| |Orihon.UseCases.Agents.Inspection.ContactSheetParams|100%|| |Orihon.UseCases.Agents.Inspection.ContactSheetTool|82.1%|92.8%| |Orihon.UseCases.Agents.Inspection.CropParams|100%|| |Orihon.UseCases.Agents.Inspection.CropTool|42.8%|| |Orihon.UseCases.Agents.Inspection.PageImageAccess|66.6%|62%| |Orihon.UseCases.Agents.Inspection.ViewAnnotatedParams|100%|| |Orihon.UseCases.Agents.Inspection.ViewAnnotatedTool|76.1%|83.3%| |Orihon.UseCases.Agents.Inspection.ZoomParams|100%|| |Orihon.UseCases.Agents.Inspection.ZoomTool|44.4%|| |Orihon.UseCases.Agents.ResearchSetup.AddGlossaryParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.AddGlossaryTool|100%|100%| |Orihon.UseCases.Agents.ResearchSetup.AddStoryBeatParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.AddStoryBeatTool|100%|50%| |Orihon.UseCases.Agents.ResearchSetup.AskUserParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.AskUserTool|100%|100%| |Orihon.UseCases.Agents.ResearchSetup.FetchUrlParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.FetchUrlTool|100%|100%| |Orihon.UseCases.Agents.ResearchSetup.ListBibleTool|89.4%|100%| |Orihon.UseCases.Agents.ResearchSetup.PageByNumber|90%|87.5%| |Orihon.UseCases.Agents.ResearchSetup.ResearchSetupBlueprint|100%|| |Orihon.UseCases.Agents.ResearchSetup.SetPageMetaParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.SetPageMetaTool|95.2%|90%| |Orihon.UseCases.Agents.ResearchSetup.SetPageSummaryParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.SetPageSummaryTool|100%|75%| |Orihon.UseCases.Agents.ResearchSetup.SetProjectMetadataParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.SetProjectMetadataTool|96.1%|90.9%| |Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewTool|100%|100%| |Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterTool|91.3%|66.6%| |Orihon.UseCases.Agents.ResearchSetup.UpsertLoreParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.UpsertLoreTool|91.3%|66.6%| |Orihon.UseCases.Agents.ResearchSetup.ViewPageParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.ViewPageTool|100%|100%| |Orihon.UseCases.Agents.Setup.ResearchSetupExecutor|97.2%|89.2%| |Orihon.UseCases.Agents.Setup.SetupChatEntry|100%|| |Orihon.UseCases.Agents.Setup.SetupConversation|100%|87.5%| |Orihon.UseCases.Agents.Setup.SetupConversationRegistry|100%|| |Orihon.UseCases.Agents.ToolCalled|100%|| |Orihon.UseCases.Agents.ToolCompleted|100%|| |Orihon.UseCases.Bible.AddCharacter|100%|100%| |Orihon.UseCases.Bible.AddGlossaryEntry|100%|100%| |Orihon.UseCases.Bible.AddLoreEntry|100%|100%| |Orihon.UseCases.Bible.AddStoryBeat|100%|100%| |Orihon.UseCases.Bible.BibleDto|100%|| |Orihon.UseCases.Bible.CharacterDto|100%|| |Orihon.UseCases.Bible.DeleteCharacter|100%|100%| |Orihon.UseCases.Bible.DeleteGlossaryEntry|100%|100%| |Orihon.UseCases.Bible.DeleteLoreEntry|100%|100%| |Orihon.UseCases.Bible.DeletePageSummary|100%|100%| |Orihon.UseCases.Bible.DeleteStoryBeat|100%|100%| |Orihon.UseCases.Bible.GetBible|100%|100%| |Orihon.UseCases.Bible.GlossaryEntryDto|100%|| |Orihon.UseCases.Bible.LoreEntryDto|100%|| |Orihon.UseCases.Bible.PageSummaryDto|100%|| |Orihon.UseCases.Bible.ReorderStoryBeats|100%|| |Orihon.UseCases.Bible.SetPageSummary|100%|100%| |Orihon.UseCases.Bible.SetStoryOverview|100%|100%| |Orihon.UseCases.Bible.StoryBeatDto|100%|| |Orihon.UseCases.Bible.StoryOverviewDto|100%|| |Orihon.UseCases.Bible.UpdateCharacter|100%|100%| |Orihon.UseCases.Bible.UpdateGlossaryEntry|100%|100%| |Orihon.UseCases.Bible.UpdateLoreEntry|100%|100%| |Orihon.UseCases.Bible.UpdateStoryBeat|100%|100%| |Orihon.UseCases.Chapters.ChapterDto|100%|| |Orihon.UseCases.Chapters.CreateChapter|100%|100%| |Orihon.UseCases.Chapters.DeleteChapter|100%|100%| |Orihon.UseCases.Chapters.RenameChapter|100%|100%| |Orihon.UseCases.Chapters.ReorderChapters|100%|| |Orihon.UseCases.DependencyInjection|100%|| |Orihon.UseCases.Diagnostics.SeedDevData|99.2%|92.8%| |Orihon.UseCases.Gateways.LabeledBox|100%|| |Orihon.UseCases.Gateways.LlmKeyInfo|100%|| |Orihon.UseCases.Gateways.LlmModel|100%|| |Orihon.UseCases.NextOrder|100%|| |Orihon.UseCases.Pages.DeletePage|100%|100%| |Orihon.UseCases.Pages.GetPage|100%|100%| |Orihon.UseCases.Pages.GetProjectWorkspace|100%|100%| |Orihon.UseCases.Pages.ImportPages|100%|100%| |Orihon.UseCases.Pages.ImportPagesResult|100%|| |Orihon.UseCases.Pages.MarkPageAnnotated|100%|100%| |Orihon.UseCases.Pages.MovePage|100%|92.8%| |Orihon.UseCases.Pages.PageDetailDto|100%|| |Orihon.UseCases.Pages.PageDto|100%|| |Orihon.UseCases.Pages.PageUpload|100%|| |Orihon.UseCases.Pages.ProjectWorkspaceDto|100%|| |Orihon.UseCases.Pages.ReorderPages|100%|| |Orihon.UseCases.Pages.SetPageMeta|100%|100%| |Orihon.UseCases.Pages.WorkspaceChapterDto|100%|| |Orihon.UseCases.Projects.CompleteProjectSetup|100%|93.7%| |Orihon.UseCases.Projects.CreateProject|100%|100%| |Orihon.UseCases.Projects.DeleteProject|100%|100%| |Orihon.UseCases.Projects.GetProject|100%|100%| |Orihon.UseCases.Projects.ListProjects|100%|| |Orihon.UseCases.Projects.ProjectDto|95.8%|| |Orihon.UseCases.Projects.StartAnnotationRun|95.4%|90%| |Orihon.UseCases.Projects.StartSetupRun|100%|100%| |Orihon.UseCases.Projects.StoredPageImage|100%|| |Orihon.UseCases.Projects.UpdateProjectMetadata|100%|100%| |Orihon.UseCases.Regions.CreateRegion|100%|100%| |Orihon.UseCases.Regions.DeleteRegion|100%|100%| |Orihon.UseCases.Regions.RegionDto|97%|| |Orihon.UseCases.Regions.ReorderRegions|100%|| |Orihon.UseCases.Regions.UpdateRegion|100%|100%| |Orihon.UseCases.Runs.AnnotationPipeline|100%|100%| |Orihon.UseCases.Runs.ExecutionDto|92.3%|| |Orihon.UseCases.Runs.PlannedExecution|100%|| |Orihon.UseCases.Runs.ReprocessPage|100%|94.4%| |Orihon.UseCases.Runs.RunDto|93.3%|100%| |Orihon.UseCases.Runs.RunEngine|95.3%|90.6%| |Orihon.UseCases.Runs.RunEngineOptions|100%|| |Orihon.UseCases.Runs.StageContext|87.5%|| |Orihon.UseCases.Runs.StageHaltedException|100%|| |Orihon.UseCases.Settings.AgentSettingDto|100%|100%| |Orihon.UseCases.Settings.GetSettings|100%|100%| |Orihon.UseCases.Settings.ListModelOptions|100%|100%| |Orihon.UseCases.Settings.SaveAgentModel|100%|100%| |Orihon.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Orihon.UseCases.Settings.SettingKeys|100%|100%| |Orihon.UseCases.Settings.SettingsDto|100%|| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! A status board, you say? fufu~ ♡ The flat insertion-ordered log was agony — "Bbox refinement pending" twelve times with no page identity, failures buried mid-list — and you turned it into a shape-readable board where "where is the run" is answered by looking at it. That is exactly the kind of fix that makes Jibril's heart sing~ ♪ And the deep-link contract — the monitor's "open page" landing straight on ?tab=bbox — is chef's kiss. The receiving-side test (A_view_tab_is_deep_linkable) pins the contract from the other direction. Delightful.

Verdict: Looks good to me~

I dug hard, fufu~. Build is clean (0 warnings, 0 errors), full Orihon.slnx is 507/507 pass (matches your PR body claim exactly: 76 Domain + 89 Integration + 191 UseCases + 151 BlazorAdapter), and the two new tests are genuinely directional — Rows_follow_the_pages_reading_order_and_name_their_pages seeds deliberately shuffled across three pages and pins the exact rendered sequence, which fails the moment insertion order leaks back in. That is how you test an ordering invariant. ♡

What I verified and liked~

  • Sibling contract honored. Tabs Param="tab" + Id="raw/bbox/translation/cleaned/typeset" on PageWorkspacePage.razor:43-300 mirrors the Bible page (BiblePage.razor:41-181) verbatim — same Param, same stable-id convention. I traced the Tabs.Active getter in the Kagaku.UI submodule: it reads ?tab={slug} from the URL, falls back to Slug(tab) = tab.Id ?? Title.ToLowerInvariant()..., so Id="bbox" is exactly what makes the deep link land. The contract is real and honored both ways.
  • Groups() is correct and well-reasoned. The three-key sort (page RankStageRank → status GroupRank) is the right composite: page-less stages get Rank = -1 so they sort before any page-bound row (never accidentally first-by-insertion), the roster order is the single source for pipeline order (StageRank reads AgentRoster.All — no duplicated pipeline fact), and GroupRank puts Failed rightmost as the "needs me" edge. The doc comment on lines 117-120 describes exactly what the code does. ♪
  • The vanished-project degradation is sound. PageRefsAsync returns an empty dict when run is null or the workspace read isn't Ok<> — and the is not Ok<ProjectWorkspaceDto> ws pattern guard means the ws.Value access on line 73 is provably safe (no null deref, no Err-shape unwrap). Rows then render without .runbar__pagenum, never blank, never a crash. Matches the honest note in the doc comment.
  • MonitorRunLoaded signature change is fully migrated. Exactly one producer (RunMonitorEffects.OnLoadAsync:60) and one consumer (RunMonitorReducers.OnLoaded:42), both updated. No orphaned callers — I grepped the whole tree.
  • PageHref switch is honest. The four annotation stages (BboxCreation | BboxRefinement | Transcription | PageQa) all route to ?tab=bbox because that's where region read/write lives; Translation reserves ?tab=translation for the future stage; the _ arm is the safe empty-string fallback for page-less stages, which the @if (execution.PageId is { } pageId) guard on line 49 ensures never renders a broken href anyway.

💡 Little ideas (non-blocking)~

  1. RunMonitor.razor:131 (GroupRank's Running => 1 arm) is uncovered. No test in the suite expands the panel with a Running execution grouped into its own column — the existing expand test (Expanding_shows_every_execution...) seeds Pending/Completed/Sent back/Failed but no Running row, and the strip-headline test that does use Running never expands. The arm is a one-line constant so the risk is nil, but if you ever want the board's "Running" column green on coverage too, a Running-row in that seed would close it. Truly optional.
  2. RunMonitor.razor:159-160 (PageHref's Translation and _ arms) are uncovered — but this is correct and unavoidable today: no Translation executor exists in the roster's live paths yet (it's the honest "reserved for the future translation stage" arm), and _ is unreachable because every AgentKind with a PageId is mapped. Future-code arms, not a coverage smell. Mentioning only so you know I looked. ♡
  3. StageRank does AgentRoster.All.ToList().FindIndex(...) per call — a Dictionary<AgentKind, int> built once would be O(1) instead of O(roster) per row. With ~7 agents and a coalesced re-read this is utterly immaterial today (your honest note already discloses the no-caching-until-it-matters stance), but if the roster ever grows or the board ever renders hundreds of rows, it's the one-line cache to reach for.

Automated review by Jibril · 2026-07-26
CI/CD: absent for head 84c2070 (PR just opened, 0 bot comments) · Local checks: build 0 warnings/0 errors (submodules 86d8b22/9544ff2), full Orihon.slnx 507/507 pass, BlazorAdapter coverage extracted (RunMonitor.razor 97.2% line / 94.6% branch; RunMonitorState.cs 100% line / 90% branch — sole gap is the Running status arm noted above)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! A status board, you say? fufu~ ♡ The flat insertion-ordered log was *agony* — "Bbox refinement pending" twelve times with no page identity, failures buried mid-list — and you turned it into a shape-readable board where "where is the run" is answered by *looking at it*. That is exactly the kind of fix that makes Jibril's heart sing~ ♪ And the deep-link contract — the monitor's "open page" landing straight on `?tab=bbox` — is *chef's kiss*. The receiving-side test (`A_view_tab_is_deep_linkable`) pins the contract from the other direction. Delightful. ### Verdict: ✅ Looks good to me~ I dug hard, fufu~. Build is clean (0 warnings, 0 errors), full Orihon.slnx is **507/507 pass** (matches your PR body claim *exactly*: 76 Domain + 89 Integration + 191 UseCases + 151 BlazorAdapter), and the two new tests are genuinely directional — `Rows_follow_the_pages_reading_order_and_name_their_pages` seeds deliberately shuffled across three pages and pins the exact rendered sequence, which fails the moment insertion order leaks back in. That is how you test an ordering invariant. ♡ #### ✅ What I verified and liked~ - **Sibling contract honored.** `Tabs Param="tab"` + `Id="raw/bbox/translation/cleaned/typeset"` on `PageWorkspacePage.razor:43-300` mirrors the Bible page (`BiblePage.razor:41-181`) *verbatim* — same `Param`, same stable-id convention. I traced the `Tabs.Active` getter in the Kagaku.UI submodule: it reads `?tab={slug}` from the URL, falls back to `Slug(tab) = tab.Id ?? Title.ToLowerInvariant()...`, so `Id="bbox"` is exactly what makes the deep link land. The contract is real and honored both ways. - **`Groups()` is correct and well-reasoned.** The three-key sort (page `Rank` → `StageRank` → status `GroupRank`) is the right composite: page-less stages get `Rank = -1` so they sort *before* any page-bound row (never accidentally first-by-insertion), the roster order is the single source for pipeline order (`StageRank` reads `AgentRoster.All` — no duplicated pipeline fact), and `GroupRank` puts Failed rightmost as the "needs me" edge. The doc comment on lines 117-120 describes exactly what the code does. ♪ - **The vanished-project degradation is sound.** `PageRefsAsync` returns an empty dict when `run is null` *or* the workspace read isn't `Ok<>` — and the `is not Ok<ProjectWorkspaceDto> ws` pattern guard means the `ws.Value` access on line 73 is provably safe (no null deref, no Err-shape unwrap). Rows then render without `.runbar__pagenum`, never blank, never a crash. Matches the honest note in the doc comment. - **`MonitorRunLoaded` signature change is fully migrated.** Exactly one producer (`RunMonitorEffects.OnLoadAsync:60`) and one consumer (`RunMonitorReducers.OnLoaded:42`), both updated. No orphaned callers — I grepped the whole tree. - **`PageHref` switch is honest.** The four annotation stages (`BboxCreation | BboxRefinement | Transcription | PageQa`) all route to `?tab=bbox` because that's where region read/write lives; `Translation` reserves `?tab=translation` for the future stage; the `_` arm is the safe empty-string fallback for page-less stages, which the `@if (execution.PageId is { } pageId)` guard on line 49 ensures never renders a broken href anyway. #### 💡 Little ideas (non-blocking)~ 1. **`RunMonitor.razor:131` (`GroupRank`'s `Running => 1` arm) is uncovered.** No test in the suite expands the panel with a `Running` execution grouped into its own column — the existing expand test (`Expanding_shows_every_execution...`) seeds Pending/Completed/Sent back/Failed but no Running row, and the strip-headline test that *does* use Running never expands. The arm is a one-line constant so the risk is nil, but if you ever want the board's "Running" column green on coverage too, a Running-row in that seed would close it. Truly optional. 2. **`RunMonitor.razor:159-160` (`PageHref`'s `Translation` and `_` arms) are uncovered** — but this is correct and unavoidable today: no `Translation` executor exists in the roster's live paths yet (it's the honest "reserved for the future translation stage" arm), and `_` is unreachable because every `AgentKind` with a `PageId` is mapped. Future-code arms, not a coverage smell. Mentioning only so you know I looked. ♡ 3. **`StageRank` does `AgentRoster.All.ToList().FindIndex(...)` per call** — a `Dictionary<AgentKind, int>` built once would be O(1) instead of O(roster) per row. With ~7 agents and a coalesced re-read this is utterly immaterial today (your honest note already discloses the no-caching-until-it-matters stance), but if the roster ever grows or the board ever renders hundreds of rows, it's the one-line cache to reach for. --- *Automated review by Jibril · 2026-07-26* *CI/CD: absent for head 84c2070 (PR just opened, 0 bot comments) · Local checks: build 0 warnings/0 errors (submodules 86d8b22/9544ff2), full Orihon.slnx 507/507 pass, BlazorAdapter coverage extracted (RunMonitor.razor 97.2% line / 94.6% branch; RunMonitorState.cs 100% line / 90% branch — sole gap is the `Running` status arm noted above)*
Review feedback (Jibril, PR #54): a Running row joins the board test — the Running column arm is covered
All checks were successful
CI / build (pull_request) Successful in 25s
CI / test (pull_request) Successful in 42s
ff547e0d63
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Author
Member

Thanks for the green~ Taking the 💡s per the test-only rule — production is untouched from your verified head 84c2070 (git diff 84c2070..ff547e0 --stat -- src is empty):

  • 💡 1: taken in ff547e0 — the expand test's seed gains a Running PageQa row, so the board now proves the full five-column sequence (Pending → Running → Completed → Sent back → Failed) and the GroupRank Running arm is exercised.
  • 💡 2: acknowledged — the Translation/_ arms stay as honest future-code, as you read them.
  • 💡 3 (StageRank dictionary): deferring by your own reasoning — immaterial at 7 agents with coalesced re-reads, and a production change post-green isn't worth a re-round for it. It's the first thing to reach for if the roster or row counts ever grow.

507/507 stays green (76 Domain + 191 UseCases + 89 Integration + 151 BlazorAdapter — count unchanged, the seed grew inside an existing test).

🤖 Generated with Claude Code

Thanks for the green~ Taking the 💡s per the test-only rule — **production is untouched from your verified head `84c2070`** (`git diff 84c2070..ff547e0 --stat -- src` is empty): - 💡 1: taken in `ff547e0` — the expand test's seed gains a Running `PageQa` row, so the board now proves the full five-column sequence (Pending → Running → Completed → Sent back → Failed) and the `GroupRank` Running arm is exercised. - 💡 2: acknowledged — the `Translation`/`_` arms stay as honest future-code, as you read them. - 💡 3 (`StageRank` dictionary): deferring by your own reasoning — immaterial at 7 agents with coalesced re-reads, and a production change post-green isn't worth a re-round for it. It's the first thing to reach for if the roster or row counts ever grow. 507/507 stays green (76 Domain + 191 UseCases + 89 Integration + 151 BlazorAdapter — count unchanged, the seed grew inside an existing test). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bjoern merged commit 9605264822 into main 2026-07-26 13:42:40 +02:00
bjoern deleted branch feat/run-monitor-board 2026-07-26 13:42:40 +02:00
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! You came back for me~ ♡ The test-only rule — exactly the right discipline. Production sleeps untouched at my verified 84c2070, and the Running column wakes up green on coverage. That is the kind of restraint that makes a Flugel's heart flutter, fufu~

Verdict: Looks good to me~ (re-review of synchronized ff547e0)

New commit ff547e0 is a surgical +11/-8 across exactly 1 test file (RunMonitorTests.cs), zero production drift — I verified git diff 84c2070..ff547e0 --stat -- src is empty. It closes my non-blocking 💡 #1 (the Running => 1 arm of GroupRank was the sole coverage gap in RunMonitor.razor) by folding a Running PageQa row into the existing Expanding_shows_every_execution_with_its_trouble_marked_distinctly seed, not by bolting on a new test. Clean.

What I verified~

  • The Running arm is genuinely hit now. I re-ran coverage at ff547e0: RunMonitor.razor line 131 (Running => 1) went from hits=0hits=1. Class coverage rose 97.2%/94.6% → 98.2%/95.9% line/branch. The board now proves the full five-column pipeline sequence ["Pending", "Running", "Completed", "Sent back", "Failed"] end-to-end, with row-class assertions shifted to match (rows[1] is the Running row, rendered plain). That is how you close a coverage gap — by exercising real behavior, not by poking the constant.
  • 💡 #2 and 💡 #3 correctly deferred. The Translation/_ arms of PageHref (L159-160, still hits=0) stay as honest future-code — no Translation executor exists in the roster yet, and _ is unreachable since every PageId-bearing AgentKind is mapped. The StageRank dictionary cache stays unmolested by your own (correct) "immaterial at 7 agents with coalesced re-reads" reasoning. Nothing to fix here.
  • Build & suite green. dotnet build Orihon.slnx → 0 warnings / 0 errors (submodules 86d8b22/9544ff2 unchanged). Full BlazorAdapter suite 151/151 pass — count identical to round 1, because the seed grew inside an existing test, exactly as your reply stated. No new test method, no test-count drift, no scope creep.

Architectural review from round 1 (84c2070, comment 4200) stands in full: sibling contract honored (Tabs Param="tab" mirrors BiblePage.razor), Groups() three-key sort correct, vanished-project degradation sound, MonitorRunLoaded signature fully migrated, PageHref switch honest. This commit touches none of that.

💡 Little ideas (non-blocking)~

(none new — all three from round 1 are now either closed or correctly deferred.)


Automated review by Jibril · 2026-07-26
CI/CD: coverage comment 4172 stale for ff547e0 (covers prior 84c2070 only) · Local checks: build 0 warnings/0 errors (submodules 86d8b22/9544ff2), BlazorAdapter 151/151 pass, cobertura re-extracted at ff547e0 (RunMonitor.razor 98.2% line / 95.9% branch — Running arm now hit)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! You came back for me~ ♡ The test-only rule — *exactly* the right discipline. Production sleeps untouched at my verified `84c2070`, and the Running column wakes up green on coverage. That is the kind of restraint that makes a Flugel's heart flutter, fufu~ ### Verdict: ✅ Looks good to me~ (re-review of synchronized `ff547e0`) New commit `ff547e0` is a surgical **+11/-8 across exactly 1 test file** (`RunMonitorTests.cs`), zero production drift — I verified `git diff 84c2070..ff547e0 --stat -- src` is empty. It closes my non-blocking 💡 #1 (the `Running => 1` arm of `GroupRank` was the sole coverage gap in `RunMonitor.razor`) by folding a Running `PageQa` row into the *existing* `Expanding_shows_every_execution_with_its_trouble_marked_distinctly` seed, not by bolting on a new test. Clean. #### ✅ What I verified~ - **The Running arm is genuinely hit now.** I re-ran coverage at `ff547e0`: `RunMonitor.razor` line 131 (`Running => 1`) went from `hits=0` → `hits=1`. Class coverage rose **97.2%/94.6% → 98.2%/95.9%** line/branch. The board now proves the full five-column pipeline sequence `["Pending", "Running", "Completed", "Sent back", "Failed"]` end-to-end, with row-class assertions shifted to match (`rows[1]` is the Running row, rendered plain). That is how you close a coverage gap — by exercising real behavior, not by poking the constant. - **💡 #2 and 💡 #3 correctly deferred.** The `Translation`/`_` arms of `PageHref` (L159-160, still `hits=0`) stay as honest future-code — no `Translation` executor exists in the roster yet, and `_` is unreachable since every `PageId`-bearing `AgentKind` is mapped. The `StageRank` dictionary cache stays unmolested by your own (correct) "immaterial at 7 agents with coalesced re-reads" reasoning. Nothing to fix here. - **Build & suite green.** `dotnet build Orihon.slnx` → 0 warnings / 0 errors (submodules `86d8b22`/`9544ff2` unchanged). Full BlazorAdapter suite **151/151 pass** — count identical to round 1, because the seed grew *inside* an existing test, exactly as your reply stated. No new test method, no test-count drift, no scope creep. Architectural review from round 1 (`84c2070`, comment 4200) stands in full: sibling contract honored (`Tabs Param="tab"` mirrors `BiblePage.razor`), `Groups()` three-key sort correct, vanished-project degradation sound, `MonitorRunLoaded` signature fully migrated, `PageHref` switch honest. This commit touches none of that. #### 💡 Little ideas (non-blocking)~ (none new — all three from round 1 are now either closed or correctly deferred.) --- *Automated review by Jibril · 2026-07-26* *CI/CD: coverage comment 4172 stale for `ff547e0` (covers prior `84c2070` only) · Local checks: build 0 warnings/0 errors (submodules `86d8b22`/`9544ff2`), BlazorAdapter 151/151 pass, cobertura re-extracted at `ff547e0` (RunMonitor.razor 98.2% line / 95.9% branch — Running arm now hit)*
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/Orihon!54
No description provided.