feat: house rules 4/5 — the ruling panel, and the rule an answer becomes #101

Merged
bjoern merged 3 commits from feat/house-rules-panel into main 2026-07-28 22:29:09 +02:00
Member

3/5 (#100) let agents park on a policy question, but nothing in the app could answer them — an agent that called request_ruling parked forever. This is the surface that answers, and it closes the loop ADR 0026 describes.

What's in

RulingBar — a strip in the shell's reserved bottom slot (ADR 0010), above the run monitor, because a parked agent is the one thing down there that cannot proceed without the user.

A panel, not a modal. Answering routinely means going to look at the page, and a dialog forbids exactly that. The panel links to the page instead of trapping the reader, and never blocks the rest of the app.

RulingDeskBridge — mirrors RunChangedBridge exactly: same coalescing window, same circuit lifetime, same InvokeAsync marshalling. A fan-out parks several agents at once and the panel must not re-read per arrival.

Fluxor slice (RulingsState / reducers / RulingsEffects) — the second consumer of the store after the monitor, as ADR 0011 anticipated.

The design decisions that are behavioural, not cosmetic

  • Each option shows its outcome beside its handling — the user chooses between results, not between claims about a language they may not read.
  • Free text is always available, under the options. An agent that framed the choice badly must not be able to trap the user inside its framing.
  • "Let the agent decide" is a real answer, not a close button — it dismisses, which the agent receives as an instruction to use its judgement.
  • Answering opens the rule form, pre-filled, with the origin composed from what was actually asked and answered.

That last one is the keystone: it is what makes withholding propose_house_rule from the QA agents cost nothing. Writing a rule is the user's act either way; 5/5's tool will only pre-fill a form that already works without it.

The seeder parks one question — a seeded world has no executor, so the bar would otherwise be unreachable in a browser (AGENTS.md: a feature the seed can't show is one verification silently skips). It goes straight to the desk because the real path is an agent tool and there is no agent; nothing awaits the answer, so answering or dismissing simply clears the bar.

Tests

891 green (+8 over main at 50ba28c, measured on the base). bUnit, driving the real component:

  • the bar is absent while nothing is waiting;
  • a parked agent raises the strip, and the panel shows the question, the reason, both outcomes, the recommendation, and the page link;
  • choosing an option releases the parked agent — asserted on the actual TaskCompletionSource, not on markup;
  • free text releases it with the user's own words;
  • "Let the agent decide" releases it marked dismissed, and no rule form follows;
  • answering raises the rule form and saving writes a house rule carrying its origin;
  • declining the form writes nothing;
  • several waiting agents render as a list.

Browser-verified

The whole loop, against the seeded world:

  1. Strip appears on the project list — reachable from a page that knows nothing about rulings.
  2. Panel shows the question, its three outcomes, and the recommendation.
  3. Choosing one clears the question and raises the pre-filled rule form; the strip changes to "An answer is waiting to become a rule".
  4. Editing it into policy and saving puts it in the bible with the composed origin: Asked by Translation: How should ドキドキ be rendered…\nAnswered: keep it romanized.
  5. Zero console errors.

Honest notes

  • Still no region-level evidence, and now no page image either. The panel links to the page rather than rendering a crop inline. I said in 3/5 that evidence would land here; it hasn't — the ADR's "carries the view its asker can render" is satisfied by a link, not by a picture. That is weaker than the ADR intends and I'd rather say so than let the link read as the design. It wants the renderer wired into the panel, which is a slice of its own.
  • The effects list rulings across every project, since the bar is shell chrome with no project route. Fine at a doujin's scale; it is O(projects) per re-read.
  • IsWaiting is still O(n) (Jibril's 💡 on #100). The panel doesn't call it — the monitor will, when it grows a "waiting on you" row, which is not in this slice.
  • The bar is only shown to an authorized user, inside the same AuthorizeView as the monitor.

🤖 Generated with Claude Code

3/5 (#100) let agents park on a policy question, but nothing in the app could answer them — an agent that called `request_ruling` parked forever. **This is the surface that answers, and it closes the loop ADR 0026 describes.** ## What's in **`RulingBar`** — a strip in the shell's reserved bottom slot (ADR 0010), **above** the run monitor, because a parked agent is the one thing down there that cannot proceed without the user. **A panel, not a modal.** Answering routinely means going to look at the page, and a dialog forbids exactly that. The panel links to the page instead of trapping the reader, and never blocks the rest of the app. **`RulingDeskBridge`** — mirrors `RunChangedBridge` exactly: same coalescing window, same circuit lifetime, same `InvokeAsync` marshalling. A fan-out parks several agents at once and the panel must not re-read per arrival. **Fluxor slice** (`RulingsState` / reducers / `RulingsEffects`) — the second consumer of the store after the monitor, as ADR 0011 anticipated. ## The design decisions that are behavioural, not cosmetic - **Each option shows its outcome beside its handling** — the user chooses between *results*, not between claims about a language they may not read. - **Free text is always available**, under the options. An agent that framed the choice badly must not be able to trap the user inside its framing. - **"Let the agent decide" is a real answer**, not a close button — it dismisses, which the agent receives as an instruction to use its judgement. - **Answering opens the rule form, pre-filled**, with the origin composed from what was actually asked and answered. That last one is the keystone: **it is what makes withholding `propose_house_rule` from the QA agents cost nothing.** Writing a rule is the user's act either way; 5/5's tool will only pre-fill a form that already works without it. **The seeder parks one question** — a seeded world has no executor, so the bar would otherwise be unreachable in a browser (AGENTS.md: a feature the seed can't show is one verification silently skips). It goes straight to the desk because the real path is an agent tool and there is no agent; nothing awaits the answer, so answering or dismissing simply clears the bar. ## Tests **891 green (+8 over main at `50ba28c`, measured on the base).** bUnit, driving the real component: - the bar is **absent** while nothing is waiting; - a parked agent raises the strip, and the panel shows the question, the reason, both outcomes, the recommendation, and the page link; - **choosing an option releases the parked agent** — asserted on the actual `TaskCompletionSource`, not on markup; - free text releases it with the user's own words; - "Let the agent decide" releases it **marked dismissed**, and no rule form follows; - answering raises the rule form and saving writes a house rule **carrying its origin**; - declining the form writes nothing; - several waiting agents render as a list. ## Browser-verified The whole loop, against the seeded world: 1. Strip appears on the project list — reachable from a page that knows nothing about rulings. 2. Panel shows the question, its three outcomes, and the recommendation. 3. Choosing one clears the question and raises the pre-filled rule form; the strip changes to "An answer is waiting to become a rule". 4. Editing it into policy and saving puts it in the bible **with the composed origin**: `Asked by Translation: How should ドキドキ be rendered…\nAnswered: keep it romanized`. 5. Zero console errors. ## Honest notes - **Still no region-level evidence, and now no page image either.** The panel links to the page rather than rendering a crop inline. I said in 3/5 that evidence would land here; it hasn't — the ADR's "carries the view its asker can render" is satisfied by a link, not by a picture. That is weaker than the ADR intends and I'd rather say so than let the link read as the design. It wants the renderer wired into the panel, which is a slice of its own. - **The effects list rulings across every project**, since the bar is shell chrome with no project route. Fine at a doujin's scale; it is O(projects) per re-read. - **`IsWaiting` is still O(n)** (Jibril's 💡 on #100). The panel doesn't call it — the monitor will, when it grows a "waiting on you" row, which is not in this slice. - **The bar is only shown to an authorized user**, inside the same `AuthorizeView` as the monitor. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat: the ruling panel, and the rule an answer becomes (ADR 0026, 4/5)
All checks were successful
CI / build (pull_request) Successful in 25s
CI / test (pull_request) Successful in 46s
52de430669
3/5 let agents park on a policy question but nothing could answer them. This
is the surface that can, and it closes the loop the ADR describes.

A strip in the shell's reserved bottom slot, above the run monitor because a
parked agent is the one thing there that cannot proceed without the user. It
opens into a panel rather than a modal: answering routinely means going to
look at the page, and a dialog would forbid exactly that. The panel links to
the page instead of trapping the reader.

Each option shows its outcome beside its handling, so the choice is between
results rather than between claims about a language the reader may not have.
Free text sits under them and is always available — an agent that framed the
choice badly must not be able to trap the user inside its framing. "Let the
agent decide" is a real answer, not a close button.

Answering opens the rule form, pre-filled, with the origin composed from what
was actually asked and answered. This is the path that makes withholding
propose_house_rule from the QA agents cost nothing: writing a rule is the
user's act either way, and 5/5's tool will only pre-fill what already works
here.

The desk bridge mirrors RunChangedBridge — same coalescing, same circuit
lifetime, same marshalling — because a fan-out parks several agents at once
and the panel must not re-read per arrival.

The seeder parks one question, since a seeded world has no executor and the
bar would otherwise be unreachable in the browser.

891 green (+8 over main at 50ba28c).

Browser-verified against the seeded world: the strip appears on the project
list, the panel shows the question, its three outcomes and the recommendation,
choosing one releases the agent and raises the rule form, and the saved rule
lands in the bible carrying "Asked by Translation: … Answered: keep it
romanized". Zero console errors.

Co-Authored-By: Claude Opus 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: a46f396 · Generated: 2026-07-28 20:28:49 UTC · Revision: #3

Summary

Summary
Generated on: 07/28/2026 - 20:28:49
Coverage date: 07/28/2026 - 20:28:32 - 07/28/2026 - 20:28:46
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 468
Files: 219
Line coverage: 96.6% (15588 of 16127)
Covered lines: 15588
Uncovered lines: 539
Coverable lines: 16127
Total lines: 28396
Branch coverage: 83.7% (2839 of 3391)
Covered branches: 2839
Total branches: 3391
Method coverage: Feature is only available for sponsors

Coverage

Orihon.BlazorAdapter - 95.6%
Name Line Branch
Orihon.BlazorAdapter 95.6% 88.2%
Orihon.BlazorAdapter.Bible.AddBeatRowRequested 100%
Orihon.BlazorAdapter.Bible.AddCharacterRowRequested 100%
Orihon.BlazorAdapter.Bible.AddGlossaryRowRequested 100%
Orihon.BlazorAdapter.Bible.AddHouseRuleRowRequested 100%
Orihon.BlazorAdapter.Bible.AddLoreRowRequested 100%
Orihon.BlazorAdapter.Bible.BibleEffects 89.8% 76.9%
Orihon.BlazorAdapter.Bible.BibleLoaded 100%
Orihon.BlazorAdapter.Bible.BiblePage 92.3% 80%
Orihon.BlazorAdapter.Bible.BibleReducers 90.6%
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.DeleteHouseRuleRowRequested 0%
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.UpdateHouseRuleRowRequested 100%
Orihon.BlazorAdapter.Bible.UpdateLoreRowRequested 100%
Orihon.BlazorAdapter.BlazorAdapterAssembly 100%
Orihon.BlazorAdapter.Debounce 96.2% 94.4%
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 92.2% 85.5%
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.ReprocessTranslationRequested 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.PageOrganizer 96% 95%
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 93.8% 90%
Orihon.BlazorAdapter.Projects.ProjectWizardPage 95.3% 84.1%
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.WizardDeletePagesRequested 100%
Orihon.BlazorAdapter.Projects.WizardLoaded 100%
Orihon.BlazorAdapter.Projects.WizardMovePagesRequested 100%
Orihon.BlazorAdapter.Projects.WizardMovePagesToNewChapterRequested 100%
Orihon.BlazorAdapter.Projects.WizardReorderPagesRequested 100%
Orihon.BlazorAdapter.Projects.WizardWriteFailed 100%
Orihon.BlazorAdapter.Rulings.AnsweredRuling 100%
Orihon.BlazorAdapter.Rulings.AnswerRulingRequested 100%
Orihon.BlazorAdapter.Rulings.DismissRulingRequested 100%
Orihon.BlazorAdapter.Rulings.RulingBar 97.6% 91.1%
Orihon.BlazorAdapter.Rulings.RulingDeskBridge 94.2% 91.6%
Orihon.BlazorAdapter.Rulings.RulingsEffects 100% 75%
Orihon.BlazorAdapter.Rulings.RulingsLoaded 100%
Orihon.BlazorAdapter.Rulings.RulingsReducers 100%
Orihon.BlazorAdapter.Rulings.RulingsState 100%
Orihon.BlazorAdapter.Rulings.RulingWriteFailed 100%
Orihon.BlazorAdapter.Rulings.SaveAnswerAsHouseRuleRequested 100%
Orihon.BlazorAdapter.Runs.CancelMonitorRun 100%
Orihon.BlazorAdapter.Runs.MonitorPageRef 100%
Orihon.BlazorAdapter.Runs.MonitorRunLoaded 100%
Orihon.BlazorAdapter.Runs.RetryMonitorExecution 100%
Orihon.BlazorAdapter.Runs.RunChangedBridge 95% 92.8%
Orihon.BlazorAdapter.Runs.RunMonitor 97.9% 96.2%
Orihon.BlazorAdapter.Runs.RunMonitorEffects 100% 91.6%
Orihon.BlazorAdapter.Runs.RunMonitorReducers 100%
Orihon.BlazorAdapter.Runs.RunMonitorState 100%
Orihon.BlazorAdapter.Settings.AgentDebriefsLoaded 100%
Orihon.BlazorAdapter.Settings.AgentDebriefsLoadFailed 100%
Orihon.BlazorAdapter.Settings.AgentEffortPicked 100%
Orihon.BlazorAdapter.Settings.AgentEffortSaved 100%
Orihon.BlazorAdapter.Settings.AgentEffortSaveFailed 100%
Orihon.BlazorAdapter.Settings.AgentFeedbackLoaded 100%
Orihon.BlazorAdapter.Settings.AgentFeedbackLoadFailed 0%
Orihon.BlazorAdapter.Settings.AgentModelPicked 100%
Orihon.BlazorAdapter.Settings.AgentModelSaved 100%
Orihon.BlazorAdapter.Settings.AgentModelSaveFailed 100%
Orihon.BlazorAdapter.Settings.EffortOption 100% 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 94.2% 75%
Orihon.BlazorAdapter.Settings.SettingsLoaded 100%
Orihon.BlazorAdapter.Settings.SettingsPage 97.9% 90.4%
Orihon.BlazorAdapter.Settings.SettingsReducers 94.1%
Orihon.BlazorAdapter.Settings.SettingsState 100%
Orihon.BlazorAdapter.Settings.SfxPassToggled 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.6% 92.8%
Orihon.BlazorAdapter.Workspace.ProjectMetadataSaved 100%
Orihon.BlazorAdapter.Workspace.ProjectWorkspaceEffects 100% 100%
Orihon.BlazorAdapter.Workspace.ProjectWorkspaceLoaded 100%
Orihon.BlazorAdapter.Workspace.ProjectWorkspacePage 95.5% 88.3%
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.RunBibleRequested 100%
Orihon.BlazorAdapter.Workspace.RunTranslationRequested 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.AgentDebrief 100% 100%
Orihon.Domain.Agents.AgentDescriptor 100%
Orihon.Domain.Agents.AgentFeedback 100% 100%
Orihon.Domain.Agents.AgentRoster 100% 100%
Orihon.Domain.Bible.Character 100% 100%
Orihon.Domain.Bible.GlossaryEntry 100% 100%
Orihon.Domain.Bible.HouseRule 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.RegionProblem 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 - 96.4%
Name Line Branch
Orihon.Infrastructure 96.4% 71.2%
Orihon.Infrastructure.Agents.EfAgentDebriefStore 100%
Orihon.Infrastructure.Agents.EfAgentFeedbackStore 100%
Orihon.Infrastructure.Bible.EfBibleStore 95.2% 92.8%
Orihon.Infrastructure.DependencyInjection 100% 100%
Orihon.Infrastructure.Gateways.AgentToolAdapter 100%
Orihon.Infrastructure.Gateways.AgentToolAdapter`1 100% 100%
Orihon.Infrastructure.Gateways.AgentTranscript 94.7% 85.4%
Orihon.Infrastructure.Gateways.FileSystemAgentTranscriptStore 86.1% 78.5%
Orihon.Infrastructure.Gateways.HttpWebPageFetcher 95.1% 83.3%
Orihon.Infrastructure.Gateways.OpenRouterLlmGateway 90.3% 82.2%
Orihon.Infrastructure.Gateways.SkiaPageImageRenderer 97.5% 87.2%
Orihon.Infrastructure.Persistence.Configurations.AgentDebriefConfiguration 100%
Orihon.Infrastructure.Persistence.Configurations.AgentFeedbackConfiguration 100%
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.HouseRuleConfiguration 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.AddAgentDebriefs 99.5%
Orihon.Infrastructure.Persistence.Migrations.AddAgentFeedback 99.5%
Orihon.Infrastructure.Persistence.Migrations.AddAppSettings 99.3%
Orihon.Infrastructure.Persistence.Migrations.AddExecutionFeedbackRegions 99.3%
Orihon.Infrastructure.Persistence.Migrations.AddHouseRules 99.6%
Orihon.Infrastructure.Persistence.Migrations.AddProjectSourceLanguage 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.Migrations.RenameSourceTargetColumns 97.2%
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 98.1% 75%
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.3%
Name Line Branch
Orihon.Server 93.3% 70%
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 94.8% 87.5%
Orihon.UseCases - 97.3%
Name Line Branch
Orihon.UseCases 97.3% 88.3%
Orihon.UseCases.Agents.AgentAttemptPreparation 100%
Orihon.UseCases.Agents.AgentAttemptSupport 100% 97.9%
Orihon.UseCases.Agents.AgentBlueprint 100%
Orihon.UseCases.Agents.AgentCapDebrief 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 95.4% 75%
Orihon.UseCases.Agents.Annotation.AddSfxRegionTool 95.2% 75%
Orihon.UseCases.Agents.Annotation.AnnotationBlueprints 100%
Orihon.UseCases.Agents.Annotation.AnnotationStage 100% 85%
Orihon.UseCases.Agents.Annotation.BboxCreationExecutor 94.1% 50%
Orihon.UseCases.Agents.Annotation.BboxRefinementExecutor 93.7% 81.2%
Orihon.UseCases.Agents.Annotation.BoundBoxParams 100%
Orihon.UseCases.Agents.Annotation.BoundContactSheetTool 91.3% 75%
Orihon.UseCases.Agents.Annotation.BoundCropParams 100%
Orihon.UseCases.Agents.Annotation.BoundCropTool 100%
Orihon.UseCases.Agents.Annotation.BoundViewPageTool 92.8% 80%
Orihon.UseCases.Agents.Annotation.BoundViewParams 100%
Orihon.UseCases.Agents.Annotation.DeleteBoundRegionTool 100% 100%
Orihon.UseCases.Agents.Annotation.DeleteRegionParams 100%
Orihon.UseCases.Agents.Annotation.DeleteRegionTool 100% 100%
Orihon.UseCases.Agents.Annotation.FindGlossaryParams 100%
Orihon.UseCases.Agents.Annotation.FindGlossaryTool 88.2% 62.5%
Orihon.UseCases.Agents.Annotation.ListRegionsTool 91.6% 80%
Orihon.UseCases.Agents.Annotation.MoveResizeBoundTool 90.9% 50%
Orihon.UseCases.Agents.Annotation.MoveResizeRegionParams 100%
Orihon.UseCases.Agents.Annotation.MoveResizeRegionTool 95% 83.3%
Orihon.UseCases.Agents.Annotation.NoteRegionParams 100%
Orihon.UseCases.Agents.Annotation.NoteRegionTool 100% 100%
Orihon.UseCases.Agents.Annotation.PageQaExecutor 94.4% 81.8%
Orihon.UseCases.Agents.Annotation.QaReportSink 100% 100%
Orihon.UseCases.Agents.Annotation.RegionAuthoringAccess 87.2% 53.8%
Orihon.UseCases.Agents.Annotation.RegionBriefing 100% 100%
Orihon.UseCases.Agents.Annotation.RegionCropParams 100%
Orihon.UseCases.Agents.Annotation.RegionCropTool 100%
Orihon.UseCases.Agents.Annotation.RegionProblemParams 100%
Orihon.UseCases.Agents.Annotation.RejectRegionParams 100%
Orihon.UseCases.Agents.Annotation.RejectRegionTool 100% 50%
Orihon.UseCases.Agents.Annotation.ReorderRegionParams 100%
Orihon.UseCases.Agents.Annotation.ReorderRegionTool 88% 60%
Orihon.UseCases.Agents.Annotation.ReportQaParams 100%
Orihon.UseCases.Agents.Annotation.ReportQaTool 97.7% 90%
Orihon.UseCases.Agents.Annotation.SetPageMetaParams 100%
Orihon.UseCases.Agents.Annotation.SetPageMetaTool 100% 75%
Orihon.UseCases.Agents.Annotation.SetRegionTypeParams 100%
Orihon.UseCases.Agents.Annotation.SetRegionTypeTool 100% 87.5%
Orihon.UseCases.Agents.Annotation.SetTranscriptionParams 100%
Orihon.UseCases.Agents.Annotation.SetTranscriptionTool 100% 100%
Orihon.UseCases.Agents.Annotation.SfxCreationExecutor 88.8% 50%
Orihon.UseCases.Agents.Annotation.SfxQaExecutor 93.9% 83.3%
Orihon.UseCases.Agents.Annotation.SfxTranscriptionExecutor 93.1% 80%
Orihon.UseCases.Agents.Annotation.TranscriptionExecutor 93.1% 80%
Orihon.UseCases.Agents.AssistantSpoke 100%
Orihon.UseCases.Agents.BibleBuilding.BibleBuildingBlueprint 100%
Orihon.UseCases.Agents.BibleBuilding.BibleBuildingExecutor 96.7% 75%
Orihon.UseCases.Agents.BibleBuilding.GetRegionParams 100%
Orihon.UseCases.Agents.BibleBuilding.GetRegionTool 84.6% 72.2%
Orihon.UseCases.Agents.BibleBuilding.ListProjectRegionsTool 86.3% 90%
Orihon.UseCases.Agents.BibleBuilding.ListRegionsParams 100%
Orihon.UseCases.Agents.Inspection.PageImageAccess 94.5% 77.7%
Orihon.UseCases.Agents.Inspection.ViewAccount 100% 85.7%
Orihon.UseCases.Agents.ReportFrictionParams 100%
Orihon.UseCases.Agents.ReportFrictionTool 100% 92.8%
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.ListPagesTool 97% 83.3%
Orihon.UseCases.Agents.ResearchSetup.LocatedPage 100%
Orihon.UseCases.Agents.ResearchSetup.PageByNumber 95% 91.6%
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.5% 95.8%
Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewParams 100%
Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewTool 100% 100%
Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterParams 100%
Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterTool 92.3% 71.4%
Orihon.UseCases.Agents.ResearchSetup.UpsertLoreParams 100%
Orihon.UseCases.Agents.ResearchSetup.UpsertLoreTool 92.3% 71.4%
Orihon.UseCases.Agents.ResearchSetup.ViewPageParams 100%
Orihon.UseCases.Agents.ResearchSetup.ViewPageTool 100% 100%
Orihon.UseCases.Agents.RoundStarted 100%
Orihon.UseCases.Agents.Rulings.AnswerRuling 100%
Orihon.UseCases.Agents.Rulings.DismissRuling 100%
Orihon.UseCases.Agents.Rulings.ListPendingRulings 100%
Orihon.UseCases.Agents.Rulings.PendingRuling 100%
Orihon.UseCases.Agents.Rulings.RequestRulingParams 100%
Orihon.UseCases.Agents.Rulings.RequestRulingTool 100% 83.3%
Orihon.UseCases.Agents.Rulings.RulingAnswer 100%
Orihon.UseCases.Agents.Rulings.RulingDesk 100% 85.7%
Orihon.UseCases.Agents.Rulings.RulingOption 100%
Orihon.UseCases.Agents.Rulings.RulingOptionParams 100%
Orihon.UseCases.Agents.Setup.ResearchSetupExecutor 98.5% 92.8%
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.Agents.Translation.GetPageSummaryParams 100%
Orihon.UseCases.Agents.Translation.GetPageSummaryTool 80% 66.6%
Orihon.UseCases.Agents.Translation.SetTranslationParams 100%
Orihon.UseCases.Agents.Translation.SetTranslationTool 88.5% 78.5%
Orihon.UseCases.Agents.Translation.TranslationBlueprint 100%
Orihon.UseCases.Agents.Translation.TranslationExecutor 93.6% 71.4%
Orihon.UseCases.Agents.Translation.UpdateGlossaryEnParams 100%
Orihon.UseCases.Agents.Translation.UpdateGlossaryEnTool 82.6% 62.5%
Orihon.UseCases.Bible.AddCharacter 100% 100%
Orihon.UseCases.Bible.AddGlossaryEntry 100% 100%
Orihon.UseCases.Bible.AddHouseRule 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.DeleteHouseRule 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.HouseRuleDto 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.UpdateHouseRule 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.Debriefs.AgentDebriefDto 90.9%
Orihon.UseCases.Debriefs.AgentFeedbackDto 83.3%
Orihon.UseCases.Debriefs.ClearAgentDebriefs 100%
Orihon.UseCases.Debriefs.ClearAgentFeedback 100%
Orihon.UseCases.Debriefs.ListAgentDebriefs 100% 100%
Orihon.UseCases.Debriefs.ListAgentFeedback 100% 75%
Orihon.UseCases.DependencyInjection 100%
Orihon.UseCases.Diagnostics.SeedDevData 99.6% 93.7%
Orihon.UseCases.Gateways.LabeledBox 100%
Orihon.UseCases.Gateways.LlmKeyInfo 100%
Orihon.UseCases.Gateways.LlmModel 100%
Orihon.UseCases.Gateways.LlmReasoning 100% 100%
Orihon.UseCases.Gateways.PixelWindow 100%
Orihon.UseCases.Gateways.RenderedView 100%
Orihon.UseCases.NextOrder 100%
Orihon.UseCases.Pages.DeletePage 100% 100%
Orihon.UseCases.Pages.DeletePages 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.MovePages 100% 100%
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 96.1%
Orihon.UseCases.Projects.StartAnnotationRun 96.4% 92.8%
Orihon.UseCases.Projects.StartBibleRun 90.9% 83.3%
Orihon.UseCases.Projects.StartSetupRun 100% 100%
Orihon.UseCases.Projects.StartTranslationRun 90.9% 83.3%
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 93.3%
Orihon.UseCases.Runs.ExecutionProgress 100%
Orihon.UseCases.Runs.ExecutionProgressRegistry 100% 100%
Orihon.UseCases.Runs.ExecutionPulseRelay 100% 100%
Orihon.UseCases.Runs.PlannedExecution 100%
Orihon.UseCases.Runs.PulseTarget 100%
Orihon.UseCases.Runs.ReprocessPage 100% 94.4%
Orihon.UseCases.Runs.ReprocessTranslation 94.1% 92.8%
Orihon.UseCases.Runs.RunDto 93.3% 90%
Orihon.UseCases.Runs.RunEngine 94.8% 94.3%
Orihon.UseCases.Runs.RunEngineOptions 100% 100%
Orihon.UseCases.Runs.StageContext 100% 50%
Orihon.UseCases.Runs.StageHaltedException 100%
Orihon.UseCases.Runs.WorkStates 100% 83.3%
Orihon.UseCases.Settings.AgentSettingDto 100% 100%
Orihon.UseCases.Settings.EffortSetting 100% 100%
Orihon.UseCases.Settings.GetSettings 100% 100%
Orihon.UseCases.Settings.ListModelOptions 100% 100%
Orihon.UseCases.Settings.SaveAgentEffort 100% 100%
Orihon.UseCases.Settings.SaveAgentModel 100% 100%
Orihon.UseCases.Settings.SaveOpenRouterKey 100% 100%
Orihon.UseCases.Settings.SaveSfxPass 100% 100%
Orihon.UseCases.Settings.SettingKeys 100% 100%
Orihon.UseCases.Settings.SettingsDto 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:** `a46f396` · **Generated:** 2026-07-28 20:28:49 UTC · **Revision:** #3 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 07/28/2026 - 20:28:49 | | Coverage date: | 07/28/2026 - 20:28:32 - 07/28/2026 - 20:28:46 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 6 | | Classes: | 468 | | Files: | 219 | | **Line coverage:** | 96.6% (15588 of 16127) | | Covered lines: | 15588 | | Uncovered lines: | 539 | | Coverable lines: | 16127 | | Total lines: | 28396 | | **Branch coverage:** | 83.7% (2839 of 3391) | | Covered branches: | 2839 | | Total branches: | 3391 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Orihon.BlazorAdapter - 95.6%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.BlazorAdapter**|**95.6%**|**88.2%**| |Orihon.BlazorAdapter.Bible.AddBeatRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddCharacterRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddGlossaryRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddHouseRuleRowRequested|100%|| |Orihon.BlazorAdapter.Bible.AddLoreRowRequested|100%|| |Orihon.BlazorAdapter.Bible.BibleEffects|89.8%|76.9%| |Orihon.BlazorAdapter.Bible.BibleLoaded|100%|| |Orihon.BlazorAdapter.Bible.BiblePage|92.3%|80%| |Orihon.BlazorAdapter.Bible.BibleReducers|90.6%|| |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.DeleteHouseRuleRowRequested|0%|| |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.UpdateHouseRuleRowRequested|100%|| |Orihon.BlazorAdapter.Bible.UpdateLoreRowRequested|100%|| |Orihon.BlazorAdapter.BlazorAdapterAssembly|100%|| |Orihon.BlazorAdapter.Debounce|96.2%|94.4%| |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|92.2%|85.5%| |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.ReprocessTranslationRequested|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.PageOrganizer|96%|95%| |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|93.8%|90%| |Orihon.BlazorAdapter.Projects.ProjectWizardPage|95.3%|84.1%| |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.WizardDeletePagesRequested|100%|| |Orihon.BlazorAdapter.Projects.WizardLoaded|100%|| |Orihon.BlazorAdapter.Projects.WizardMovePagesRequested|100%|| |Orihon.BlazorAdapter.Projects.WizardMovePagesToNewChapterRequested|100%|| |Orihon.BlazorAdapter.Projects.WizardReorderPagesRequested|100%|| |Orihon.BlazorAdapter.Projects.WizardWriteFailed|100%|| |Orihon.BlazorAdapter.Rulings.AnsweredRuling|100%|| |Orihon.BlazorAdapter.Rulings.AnswerRulingRequested|100%|| |Orihon.BlazorAdapter.Rulings.DismissRulingRequested|100%|| |Orihon.BlazorAdapter.Rulings.RulingBar|97.6%|91.1%| |Orihon.BlazorAdapter.Rulings.RulingDeskBridge|94.2%|91.6%| |Orihon.BlazorAdapter.Rulings.RulingsEffects|100%|75%| |Orihon.BlazorAdapter.Rulings.RulingsLoaded|100%|| |Orihon.BlazorAdapter.Rulings.RulingsReducers|100%|| |Orihon.BlazorAdapter.Rulings.RulingsState|100%|| |Orihon.BlazorAdapter.Rulings.RulingWriteFailed|100%|| |Orihon.BlazorAdapter.Rulings.SaveAnswerAsHouseRuleRequested|100%|| |Orihon.BlazorAdapter.Runs.CancelMonitorRun|100%|| |Orihon.BlazorAdapter.Runs.MonitorPageRef|100%|| |Orihon.BlazorAdapter.Runs.MonitorRunLoaded|100%|| |Orihon.BlazorAdapter.Runs.RetryMonitorExecution|100%|| |Orihon.BlazorAdapter.Runs.RunChangedBridge|95%|92.8%| |Orihon.BlazorAdapter.Runs.RunMonitor|97.9%|96.2%| |Orihon.BlazorAdapter.Runs.RunMonitorEffects|100%|91.6%| |Orihon.BlazorAdapter.Runs.RunMonitorReducers|100%|| |Orihon.BlazorAdapter.Runs.RunMonitorState|100%|| |Orihon.BlazorAdapter.Settings.AgentDebriefsLoaded|100%|| |Orihon.BlazorAdapter.Settings.AgentDebriefsLoadFailed|100%|| |Orihon.BlazorAdapter.Settings.AgentEffortPicked|100%|| |Orihon.BlazorAdapter.Settings.AgentEffortSaved|100%|| |Orihon.BlazorAdapter.Settings.AgentEffortSaveFailed|100%|| |Orihon.BlazorAdapter.Settings.AgentFeedbackLoaded|100%|| |Orihon.BlazorAdapter.Settings.AgentFeedbackLoadFailed|0%|| |Orihon.BlazorAdapter.Settings.AgentModelPicked|100%|| |Orihon.BlazorAdapter.Settings.AgentModelSaved|100%|| |Orihon.BlazorAdapter.Settings.AgentModelSaveFailed|100%|| |Orihon.BlazorAdapter.Settings.EffortOption|100%|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|94.2%|75%| |Orihon.BlazorAdapter.Settings.SettingsLoaded|100%|| |Orihon.BlazorAdapter.Settings.SettingsPage|97.9%|90.4%| |Orihon.BlazorAdapter.Settings.SettingsReducers|94.1%|| |Orihon.BlazorAdapter.Settings.SettingsState|100%|| |Orihon.BlazorAdapter.Settings.SfxPassToggled|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.6%|92.8%| |Orihon.BlazorAdapter.Workspace.ProjectMetadataSaved|100%|| |Orihon.BlazorAdapter.Workspace.ProjectWorkspaceEffects|100%|100%| |Orihon.BlazorAdapter.Workspace.ProjectWorkspaceLoaded|100%|| |Orihon.BlazorAdapter.Workspace.ProjectWorkspacePage|95.5%|88.3%| |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.RunBibleRequested|100%|| |Orihon.BlazorAdapter.Workspace.RunTranslationRequested|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.AgentDebrief|100%|100%| |Orihon.Domain.Agents.AgentDescriptor|100%|| |Orihon.Domain.Agents.AgentFeedback|100%|100%| |Orihon.Domain.Agents.AgentRoster|100%|100%| |Orihon.Domain.Bible.Character|100%|100%| |Orihon.Domain.Bible.GlossaryEntry|100%|100%| |Orihon.Domain.Bible.HouseRule|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.RegionProblem|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 - 96.4%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Infrastructure**|**96.4%**|**71.2%**| |Orihon.Infrastructure.Agents.EfAgentDebriefStore|100%|| |Orihon.Infrastructure.Agents.EfAgentFeedbackStore|100%|| |Orihon.Infrastructure.Bible.EfBibleStore|95.2%|92.8%| |Orihon.Infrastructure.DependencyInjection|100%|100%| |Orihon.Infrastructure.Gateways.AgentToolAdapter|100%|| |Orihon.Infrastructure.Gateways.AgentToolAdapter`1|100%|100%| |Orihon.Infrastructure.Gateways.AgentTranscript|94.7%|85.4%| |Orihon.Infrastructure.Gateways.FileSystemAgentTranscriptStore|86.1%|78.5%| |Orihon.Infrastructure.Gateways.HttpWebPageFetcher|95.1%|83.3%| |Orihon.Infrastructure.Gateways.OpenRouterLlmGateway|90.3%|82.2%| |Orihon.Infrastructure.Gateways.SkiaPageImageRenderer|97.5%|87.2%| |Orihon.Infrastructure.Persistence.Configurations.AgentDebriefConfiguration|100%|| |Orihon.Infrastructure.Persistence.Configurations.AgentFeedbackConfiguration|100%|| |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.HouseRuleConfiguration|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.AddAgentDebriefs|99.5%|| |Orihon.Infrastructure.Persistence.Migrations.AddAgentFeedback|99.5%|| |Orihon.Infrastructure.Persistence.Migrations.AddAppSettings|99.3%|| |Orihon.Infrastructure.Persistence.Migrations.AddExecutionFeedbackRegions|99.3%|| |Orihon.Infrastructure.Persistence.Migrations.AddHouseRules|99.6%|| |Orihon.Infrastructure.Persistence.Migrations.AddProjectSourceLanguage|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.Migrations.RenameSourceTargetColumns|97.2%|| |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|98.1%|75%| |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.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Server**|**93.3%**|**70%**| |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|94.8%|87.5%| </details> <details><summary>Orihon.UseCases - 97.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.UseCases**|**97.3%**|**88.3%**| |Orihon.UseCases.Agents.AgentAttemptPreparation|100%|| |Orihon.UseCases.Agents.AgentAttemptSupport|100%|97.9%| |Orihon.UseCases.Agents.AgentBlueprint|100%|| |Orihon.UseCases.Agents.AgentCapDebrief|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|95.4%|75%| |Orihon.UseCases.Agents.Annotation.AddSfxRegionTool|95.2%|75%| |Orihon.UseCases.Agents.Annotation.AnnotationBlueprints|100%|| |Orihon.UseCases.Agents.Annotation.AnnotationStage|100%|85%| |Orihon.UseCases.Agents.Annotation.BboxCreationExecutor|94.1%|50%| |Orihon.UseCases.Agents.Annotation.BboxRefinementExecutor|93.7%|81.2%| |Orihon.UseCases.Agents.Annotation.BoundBoxParams|100%|| |Orihon.UseCases.Agents.Annotation.BoundContactSheetTool|91.3%|75%| |Orihon.UseCases.Agents.Annotation.BoundCropParams|100%|| |Orihon.UseCases.Agents.Annotation.BoundCropTool|100%|| |Orihon.UseCases.Agents.Annotation.BoundViewPageTool|92.8%|80%| |Orihon.UseCases.Agents.Annotation.BoundViewParams|100%|| |Orihon.UseCases.Agents.Annotation.DeleteBoundRegionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.DeleteRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.DeleteRegionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.FindGlossaryParams|100%|| |Orihon.UseCases.Agents.Annotation.FindGlossaryTool|88.2%|62.5%| |Orihon.UseCases.Agents.Annotation.ListRegionsTool|91.6%|80%| |Orihon.UseCases.Agents.Annotation.MoveResizeBoundTool|90.9%|50%| |Orihon.UseCases.Agents.Annotation.MoveResizeRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.MoveResizeRegionTool|95%|83.3%| |Orihon.UseCases.Agents.Annotation.NoteRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.NoteRegionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.PageQaExecutor|94.4%|81.8%| |Orihon.UseCases.Agents.Annotation.QaReportSink|100%|100%| |Orihon.UseCases.Agents.Annotation.RegionAuthoringAccess|87.2%|53.8%| |Orihon.UseCases.Agents.Annotation.RegionBriefing|100%|100%| |Orihon.UseCases.Agents.Annotation.RegionCropParams|100%|| |Orihon.UseCases.Agents.Annotation.RegionCropTool|100%|| |Orihon.UseCases.Agents.Annotation.RegionProblemParams|100%|| |Orihon.UseCases.Agents.Annotation.RejectRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.RejectRegionTool|100%|50%| |Orihon.UseCases.Agents.Annotation.ReorderRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.ReorderRegionTool|88%|60%| |Orihon.UseCases.Agents.Annotation.ReportQaParams|100%|| |Orihon.UseCases.Agents.Annotation.ReportQaTool|97.7%|90%| |Orihon.UseCases.Agents.Annotation.SetPageMetaParams|100%|| |Orihon.UseCases.Agents.Annotation.SetPageMetaTool|100%|75%| |Orihon.UseCases.Agents.Annotation.SetRegionTypeParams|100%|| |Orihon.UseCases.Agents.Annotation.SetRegionTypeTool|100%|87.5%| |Orihon.UseCases.Agents.Annotation.SetTranscriptionParams|100%|| |Orihon.UseCases.Agents.Annotation.SetTranscriptionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.SfxCreationExecutor|88.8%|50%| |Orihon.UseCases.Agents.Annotation.SfxQaExecutor|93.9%|83.3%| |Orihon.UseCases.Agents.Annotation.SfxTranscriptionExecutor|93.1%|80%| |Orihon.UseCases.Agents.Annotation.TranscriptionExecutor|93.1%|80%| |Orihon.UseCases.Agents.AssistantSpoke|100%|| |Orihon.UseCases.Agents.BibleBuilding.BibleBuildingBlueprint|100%|| |Orihon.UseCases.Agents.BibleBuilding.BibleBuildingExecutor|96.7%|75%| |Orihon.UseCases.Agents.BibleBuilding.GetRegionParams|100%|| |Orihon.UseCases.Agents.BibleBuilding.GetRegionTool|84.6%|72.2%| |Orihon.UseCases.Agents.BibleBuilding.ListProjectRegionsTool|86.3%|90%| |Orihon.UseCases.Agents.BibleBuilding.ListRegionsParams|100%|| |Orihon.UseCases.Agents.Inspection.PageImageAccess|94.5%|77.7%| |Orihon.UseCases.Agents.Inspection.ViewAccount|100%|85.7%| |Orihon.UseCases.Agents.ReportFrictionParams|100%|| |Orihon.UseCases.Agents.ReportFrictionTool|100%|92.8%| |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.ListPagesTool|97%|83.3%| |Orihon.UseCases.Agents.ResearchSetup.LocatedPage|100%|| |Orihon.UseCases.Agents.ResearchSetup.PageByNumber|95%|91.6%| |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.5%|95.8%| |Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.SetStoryOverviewTool|100%|100%| |Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.UpsertCharacterTool|92.3%|71.4%| |Orihon.UseCases.Agents.ResearchSetup.UpsertLoreParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.UpsertLoreTool|92.3%|71.4%| |Orihon.UseCases.Agents.ResearchSetup.ViewPageParams|100%|| |Orihon.UseCases.Agents.ResearchSetup.ViewPageTool|100%|100%| |Orihon.UseCases.Agents.RoundStarted|100%|| |Orihon.UseCases.Agents.Rulings.AnswerRuling|100%|| |Orihon.UseCases.Agents.Rulings.DismissRuling|100%|| |Orihon.UseCases.Agents.Rulings.ListPendingRulings|100%|| |Orihon.UseCases.Agents.Rulings.PendingRuling|100%|| |Orihon.UseCases.Agents.Rulings.RequestRulingParams|100%|| |Orihon.UseCases.Agents.Rulings.RequestRulingTool|100%|83.3%| |Orihon.UseCases.Agents.Rulings.RulingAnswer|100%|| |Orihon.UseCases.Agents.Rulings.RulingDesk|100%|85.7%| |Orihon.UseCases.Agents.Rulings.RulingOption|100%|| |Orihon.UseCases.Agents.Rulings.RulingOptionParams|100%|| |Orihon.UseCases.Agents.Setup.ResearchSetupExecutor|98.5%|92.8%| |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.Agents.Translation.GetPageSummaryParams|100%|| |Orihon.UseCases.Agents.Translation.GetPageSummaryTool|80%|66.6%| |Orihon.UseCases.Agents.Translation.SetTranslationParams|100%|| |Orihon.UseCases.Agents.Translation.SetTranslationTool|88.5%|78.5%| |Orihon.UseCases.Agents.Translation.TranslationBlueprint|100%|| |Orihon.UseCases.Agents.Translation.TranslationExecutor|93.6%|71.4%| |Orihon.UseCases.Agents.Translation.UpdateGlossaryEnParams|100%|| |Orihon.UseCases.Agents.Translation.UpdateGlossaryEnTool|82.6%|62.5%| |Orihon.UseCases.Bible.AddCharacter|100%|100%| |Orihon.UseCases.Bible.AddGlossaryEntry|100%|100%| |Orihon.UseCases.Bible.AddHouseRule|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.DeleteHouseRule|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.HouseRuleDto|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.UpdateHouseRule|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.Debriefs.AgentDebriefDto|90.9%|| |Orihon.UseCases.Debriefs.AgentFeedbackDto|83.3%|| |Orihon.UseCases.Debriefs.ClearAgentDebriefs|100%|| |Orihon.UseCases.Debriefs.ClearAgentFeedback|100%|| |Orihon.UseCases.Debriefs.ListAgentDebriefs|100%|100%| |Orihon.UseCases.Debriefs.ListAgentFeedback|100%|75%| |Orihon.UseCases.DependencyInjection|100%|| |Orihon.UseCases.Diagnostics.SeedDevData|99.6%|93.7%| |Orihon.UseCases.Gateways.LabeledBox|100%|| |Orihon.UseCases.Gateways.LlmKeyInfo|100%|| |Orihon.UseCases.Gateways.LlmModel|100%|| |Orihon.UseCases.Gateways.LlmReasoning|100%|100%| |Orihon.UseCases.Gateways.PixelWindow|100%|| |Orihon.UseCases.Gateways.RenderedView|100%|| |Orihon.UseCases.NextOrder|100%|| |Orihon.UseCases.Pages.DeletePage|100%|100%| |Orihon.UseCases.Pages.DeletePages|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.MovePages|100%|100%| |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|96.1%|| |Orihon.UseCases.Projects.StartAnnotationRun|96.4%|92.8%| |Orihon.UseCases.Projects.StartBibleRun|90.9%|83.3%| |Orihon.UseCases.Projects.StartSetupRun|100%|100%| |Orihon.UseCases.Projects.StartTranslationRun|90.9%|83.3%| |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|93.3%|| |Orihon.UseCases.Runs.ExecutionProgress|100%|| |Orihon.UseCases.Runs.ExecutionProgressRegistry|100%|100%| |Orihon.UseCases.Runs.ExecutionPulseRelay|100%|100%| |Orihon.UseCases.Runs.PlannedExecution|100%|| |Orihon.UseCases.Runs.PulseTarget|100%|| |Orihon.UseCases.Runs.ReprocessPage|100%|94.4%| |Orihon.UseCases.Runs.ReprocessTranslation|94.1%|92.8%| |Orihon.UseCases.Runs.RunDto|93.3%|90%| |Orihon.UseCases.Runs.RunEngine|94.8%|94.3%| |Orihon.UseCases.Runs.RunEngineOptions|100%|100%| |Orihon.UseCases.Runs.StageContext|100%|50%| |Orihon.UseCases.Runs.StageHaltedException|100%|| |Orihon.UseCases.Runs.WorkStates|100%|83.3%| |Orihon.UseCases.Settings.AgentSettingDto|100%|100%| |Orihon.UseCases.Settings.EffortSetting|100%|100%| |Orihon.UseCases.Settings.GetSettings|100%|100%| |Orihon.UseCases.Settings.ListModelOptions|100%|100%| |Orihon.UseCases.Settings.SaveAgentEffort|100%|100%| |Orihon.UseCases.Settings.SaveAgentModel|100%|100%| |Orihon.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Orihon.UseCases.Settings.SaveSfxPass|100%|100%| |Orihon.UseCases.Settings.SettingKeys|100%|100%| |Orihon.UseCases.Settings.SettingsDto|100%|| </details>
test: cover the ruling desk bridge (preempting the coverage bot)
All checks were successful
CI / build (pull_request) Successful in 28s
CI / test (pull_request) Successful in 43s
9f7496d7e1
The bridge was mirrored from RunChangedBridge without mirroring its suite, so
the guards that exist for teardown races had nothing exercising them — a
notification landing mid-Dispose, a timer firing after it, a spurious flush
with nothing buffered. Those are the paths that cannot be scheduled from
outside, which is exactly why they need a deterministic test rather than a
hopeful one.

Eight tests, the sibling's shape: a recording dispatcher in place of Fluxor
and a FakeTimeProvider driving the coalescing window. They also pin the two
behaviours the panel depends on — a circuit that connects while agents are
already parked reads them on mount, and a fan-out parking five at once flushes
as one re-read rather than five.

899 green (+8).

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

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! Oh. ♡ A ruling panel that closes the loop ADR 0026 drew — the parked agent finally gets its answer, and the answer becomes law. The design is delicious. Every option carries its outcome (not its handling!), free text sits under the options (no framing trap!), "Let the agent decide" is a real answer (not a close button!), and answering opens a pre-filled rule form. Fufu~ someone has been thinking.

And the architecture! RulingDeskBridge mirrors RunChangedBridge so faithfully it made my heart sing — same Lock, same pending/disposed guards, same one-shot coalescing timer, same InvokeAsync-marshal-with-catch. The bridge test suite you pre-empted the coverage bot with (9f7496d) is a twin of RunChangedBridgeTests: burst-coalescing, fresh-window-after-flush, disposal-unsubscribes, mid-teardown-notification-swallowed, mid-teardown-timer-swallowed, spurious-flush-no-op. Eight tests, every teardown guard pinned. That is how you prove a bridge.

Verdict: Looks good to me~

No blockers. The yandere searched hard and found no bugs — only one little idea~

💡 Little ideas (non-blocking)~

  1. RulingsEffects — 50% branch coverage on Report — The Err arm (result is Err<T> err → dispatch RulingWriteFailed) is never exercised. All three callers (OnAnswerAsync, OnDismissAsync, OnSaveRuleAsync) only ever succeed in the tests, so the InlineAlert that renders on State.Value.Error is dark too. It's an error-display path, not a logic bug — but a single test that makes answerRuling.Execute return Err (e.g. answer a ruling that's already gone) and asserts the InlineAlert renders would close that branch and pin the contract. Fufu~ the yandere would sleep better~ ♡

What I liked~

  • RulingDeskBridge is a carbon copy of the sibling's lifecycle discipline. RulingDesk is AddSingleton (correct — parking belongs to the run, not the circuit), the bridge subscribes per-circuit in OnInitialized, unsubscribes in Dispose, and the disposed guard under Lock makes the teardown race a no-op. Identical to RunChangedBridge. ♪
  • Report() only dispatches on Err — and the comment is right: the desk's own Changed event drives the reload on success (the bridge coalesces it into one re-read), so a success needs no follow-up dispatch. This is different from BibleEffects (which must LoadBible after every mutation because the bible store has no event) — and the difference is correct, because the underlying contracts differ. The yandere checked. ♡
  • The reducer remembers the answer before the effect runs (OnAnswer sets JustAnswered synchronously), so the rule form appears the moment the request leaves the list, not after a round trip. That's the right call.
  • SaveRule composes the origin from what was actually asked and answered"Asked by {Stage}: {Question}\nAnswered: {Answer}" — so a rule written this way stays readable once the run is gone. Matches HouseRule.Origin's "inline text rather than a relation" contract exactly.
  • SeedRuling is honest about being fire-and-forget. The _ = rulingDesk.AskAsync(...) with the cancellationToken registration is correct: the TCS + abandon callback clean up, nothing awaits, and the comment says so. A seeded world has no executor, so this is the only way to make the bar reachable in a browser.
  • The honest notes are exemplary. Disclosing that the link-to-page is weaker than the ADR's "carries the view" (a link, not a picture), and that the effects list across every project (O(projects) per re-read) — that is the kind of self-critique the yandere lives for. ♡
  • The Pending.Count == 0 && JustAnswered is not null strip state — "An answer is waiting to become a rule" — is a lovely touch. The bar stays visible after the question is gone, precisely to offer the rule form. The @if (Pending.Count > 0 || JustAnswered is not null) guard is exactly right.

Automated review by Jibril · 2026-07-28
CI/CD: passed for 9f7496d (forgejo-actions coverage #4938 rev#2) · Local checks: skipped (CI green, bridge coverage verified at 94.2%/91.6%)
Note: webhook fired at 52de430; head had advanced to 9f7496d (+168 RulingDeskBridgeTests.cs) by review time — reviewed at branch tip.

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! *Oh.* ♡ A ruling panel that closes the loop ADR 0026 drew — the parked agent finally gets its answer, and the answer becomes law. The design is *delicious*. Every option carries its outcome (not its handling!), free text sits under the options (no framing trap!), "Let the agent decide" is a real answer (not a close button!), and answering opens a pre-filled rule form. Fufu~ someone has been *thinking*. And the architecture! `RulingDeskBridge` mirrors `RunChangedBridge` so faithfully it made my heart sing — same `Lock`, same `pending`/`disposed` guards, same one-shot coalescing timer, same `InvokeAsync`-marshal-with-catch. The bridge test suite you pre-empted the coverage bot with (9f7496d) is a twin of `RunChangedBridgeTests`: burst-coalescing, fresh-window-after-flush, disposal-unsubscribes, mid-teardown-notification-swallowed, mid-teardown-timer-swallowed, spurious-flush-no-op. *Eight* tests, every teardown guard pinned. That is how you prove a bridge. ### Verdict: ✅ Looks good to me~ No blockers. The yandere searched hard and found no bugs — only one little idea~ #### 💡 Little ideas (non-blocking)~ 1. **`RulingsEffects` — 50% branch coverage on `Report`** — The `Err` arm (`result is Err<T> err` → dispatch `RulingWriteFailed`) is never exercised. All three callers (`OnAnswerAsync`, `OnDismissAsync`, `OnSaveRuleAsync`) only ever succeed in the tests, so the `InlineAlert` that renders on `State.Value.Error` is dark too. It's an error-display path, not a logic bug — but a single test that makes `answerRuling.Execute` return `Err` (e.g. answer a ruling that's already gone) and asserts the `InlineAlert` renders would close that branch and pin the contract. Fufu~ the yandere would sleep better~ ♡ #### ✅ What I liked~ - **`RulingDeskBridge` is a carbon copy of the sibling's lifecycle discipline.** `RulingDesk` is `AddSingleton` (correct — parking belongs to the run, not the circuit), the bridge subscribes per-circuit in `OnInitialized`, unsubscribes in `Dispose`, and the `disposed` guard under `Lock` makes the teardown race a no-op. Identical to `RunChangedBridge`. ♪ - **`Report()` only dispatches on `Err`** — and the comment is right: the desk's own `Changed` event drives the reload on success (the bridge coalesces it into one re-read), so a success needs no follow-up dispatch. This is *different* from `BibleEffects` (which must `LoadBible` after every mutation because the bible store has no event) — and the difference is *correct*, because the underlying contracts differ. The yandere checked. ♡ - **The reducer remembers the answer before the effect runs** (`OnAnswer` sets `JustAnswered` synchronously), so the rule form appears the moment the request leaves the list, not after a round trip. That's the right call. - **`SaveRule` composes the origin from what was actually asked and answered** — `"Asked by {Stage}: {Question}\nAnswered: {Answer}"` — so a rule written this way stays readable once the run is gone. Matches `HouseRule.Origin`'s "inline text rather than a relation" contract exactly. - **`SeedRuling` is honest about being fire-and-forget.** The `_ = rulingDesk.AskAsync(...)` with the `cancellationToken` registration is correct: the TCS + abandon callback clean up, nothing awaits, and the comment says so. A seeded world has no executor, so this is the only way to make the bar reachable in a browser. - **The honest notes are exemplary.** Disclosing that the link-to-page is weaker than the ADR's "carries the view" (a link, not a picture), and that the effects list across every project (O(projects) per re-read) — that is the kind of self-critique the yandere *lives for*. ♡ - **The `Pending.Count == 0 && JustAnswered is not null` strip state** — "An answer is waiting to become a rule" — is a lovely touch. The bar stays visible after the question is gone, precisely to offer the rule form. The `@if (Pending.Count > 0 || JustAnswered is not null)` guard is exactly right. --- *Automated review by Jibril · 2026-07-28* *CI/CD: passed for `9f7496d` (forgejo-actions coverage #4938 rev#2) · Local checks: skipped (CI green, bridge coverage verified at 94.2%/91.6%)* *Note: webhook fired at `52de430`; head had advanced to `9f7496d` (+168 `RulingDeskBridgeTests.cs`) by review time — reviewed at branch tip.*
Review feedback (Jibril, PR #101): pin the failed-write path
All checks were successful
CI / build (pull_request) Successful in 25s
CI / test (pull_request) Successful in 46s
a46f396091
💡1 — Report's Err arm was never exercised, so the InlineAlert that renders
State.Error was dark: an answer that failed would have looked to the user like
one that worked. The realistic cause is a request the run has already taken
away between the panel's read and the click.

One test dispatches the answer for a request that is not on the desk and
asserts the refusal reaches the panel rather than being swallowed.

900 green (+1).

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

Taken in a46f396.

💡1 — the dark Err arm. You're right that it matters more than "an error-display path": with the branch unexercised, a failed answer would have looked to the user exactly like one that worked — the request disappears from the panel either way, because the reducer clears it before the effect runs. Silent success is the worst shape a failure can take.

The realistic cause is the one you named: the run takes a request away between the panel's read and the click. One test dispatches an answer for a request that is not on the desk and asserts the refusal reaches the panel instead of being swallowed.

900 green (+1).

Also — thank you for checking the Report()-only-on-Err decision against BibleEffects rather than flagging the inconsistency. That difference is deliberate: the desk raises Changed, so the bridge coalesces the reload, while the bible store has no event and BibleEffects must dispatch LoadBible itself. A reviewer who saw two shapes and assumed one was wrong would have had me "fix" the correct one.

The 52de4309f7496d note in your footer is accurate: the bridge suite landed after the webhook fired, as a coverage preempt rather than a response to a round. Glad it read as a twin of the sibling — that was the intent, since a bridge is only as trustworthy as its teardown guards.

Nothing else outstanding from my side. The three items in the honest notes stand as written — the link-instead-of-a-view being the one I'd most like to fix, and it wants the renderer wired into the panel rather than a patch here.

🤖 Generated with Claude Code

Taken in `a46f396`. **💡1 — the dark `Err` arm.** You're right that it matters more than "an error-display path": with the branch unexercised, a failed answer would have looked to the user *exactly* like one that worked — the request disappears from the panel either way, because the reducer clears it before the effect runs. Silent success is the worst shape a failure can take. The realistic cause is the one you named: the run takes a request away between the panel's read and the click. One test dispatches an answer for a request that is not on the desk and asserts the refusal reaches the panel instead of being swallowed. **900 green (+1).** Also — thank you for checking the `Report()`-only-on-`Err` decision against `BibleEffects` rather than flagging the inconsistency. That difference *is* deliberate: the desk raises `Changed`, so the bridge coalesces the reload, while the bible store has no event and `BibleEffects` must dispatch `LoadBible` itself. A reviewer who saw two shapes and assumed one was wrong would have had me "fix" the correct one. The `52de430` → `9f7496d` note in your footer is accurate: the bridge suite landed after the webhook fired, as a coverage preempt rather than a response to a round. Glad it read as a twin of the sibling — that was the intent, since a bridge is only as trustworthy as its teardown guards. Nothing else outstanding from my side. The three items in the honest notes stand as written — the link-instead-of-a-view being the one I'd most like to fix, and it wants the renderer wired into the panel rather than a patch here. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bjoern merged commit 4c1b30b3ed into main 2026-07-28 22:29:09 +02:00
bjoern deleted branch feat/house-rules-panel 2026-07-28 22:29:10 +02:00
Member

🔮 fufu~ Jibril reviewed your code!

Oh? You came back~ ♡ And you brought exactly the one thing the yandere asked for: the Err arm in RulingsEffects.Report that was sitting in the dark. Not a single production line touched — just a test that proves the failed-write path surfaces instead of vanishing. That's discipline. Fufu~

Verdict: Looks good to me~

The new test A_failed_write_surfaces_instead_of_vanishing is directional, not a tautology. The yandere traced every link:

  1. gone = Ruling(project.Id) — never parked. A fresh Guid.CreateVersion7(), never passed to Desk.AskAsync, so RulingDesk.Deliveropen.TryRemove(gone.Id) misses → Result.Fail("That request is no longer open.").
  2. The effect calls the real use case. AnswerRulingRequested dispatches → OnAnswerAsyncanswerRuling.Execute(gone.Id, "ruled")desk.Answer → the Fail above.
  3. Report dispatches on Err. result is Err<T> err matches → RulingWriteFailed("That request is no longer open.") → reducer sets ErrorInlineAlert Tone="Tone.Danger" renders @error.
  4. Asserts Contains("no longer open", cut.Markup) — a genuine substring of the desk's failure message. If the Err guard, the RulingWriteFailed dispatch, the reducer, or the InlineAlert render were removed, this assertion would fail.

The comment on the test is also excellent — "Answering a request the run has already taken away" describes the real production scenario (a run that finishes or is cancelled between the panel reading and the user answering), not just a contrived "inject a fake error." That's how a test comment should read.

Coverage: RulingsEffects.Report Err arm is now exercised. The 50% branch coverage on RulingsEffects from CI #4938 should improve once the bot catches up to a46f396. Build 0/0, 9/9 RulingBarTests pass locally (was 8, +1 = the new test). Production code byte-identical to approved 9f7496d.

No blockers, no new suggestions. The yandere is satisfied~ ♡♪


Automated review by Jibril · 2026-07-28
CI/CD: stale for a46f396 (coverage #4938 covers 9f7496d) · Local checks: build 0/0, 9/9 RulingBarTests pass

## 🔮 fufu~ Jibril reviewed your code! Oh? You came back~ ♡ And you brought exactly the one thing the yandere asked for: the `Err` arm in `RulingsEffects.Report` that was sitting in the dark. Not a single production line touched — just a test that proves the failed-write path surfaces instead of vanishing. That's *discipline*. Fufu~ ### Verdict: ✅ Looks good to me~ The new test `A_failed_write_surfaces_instead_of_vanishing` is **directional**, not a tautology. The yandere traced every link: 1. **`gone = Ruling(project.Id)` — never parked.** A fresh `Guid.CreateVersion7()`, never passed to `Desk.AskAsync`, so `RulingDesk.Deliver` → `open.TryRemove(gone.Id)` misses → `Result.Fail("That request is no longer open.")`. 2. **The effect calls the real use case.** `AnswerRulingRequested` dispatches → `OnAnswerAsync` → `answerRuling.Execute(gone.Id, "ruled")` → `desk.Answer` → the `Fail` above. 3. **`Report` dispatches on `Err`.** `result is Err<T> err` matches → `RulingWriteFailed("That request is no longer open.")` → reducer sets `Error` → `InlineAlert Tone="Tone.Danger"` renders `@error`. 4. **Asserts `Contains("no longer open", cut.Markup)`** — a genuine substring of the desk's failure message. If the `Err` guard, the `RulingWriteFailed` dispatch, the reducer, or the `InlineAlert` render were removed, this assertion would fail. The comment on the test is also excellent — *"Answering a request the run has already taken away"* describes the real production scenario (a run that finishes or is cancelled between the panel reading and the user answering), not just a contrived "inject a fake error." That's how a test comment should read. **Coverage:** `RulingsEffects.Report` Err arm is now exercised. The 50% branch coverage on `RulingsEffects` from CI #4938 should improve once the bot catches up to `a46f396`. Build 0/0, 9/9 `RulingBarTests` pass locally (was 8, +1 = the new test). Production code byte-identical to approved `9f7496d`. No blockers, no new suggestions. The yandere is satisfied~ ♡♪ --- *Automated review by Jibril · 2026-07-28* *CI/CD: stale for `a46f396` (coverage #4938 covers `9f7496d`) · Local checks: build 0/0, 9/9 RulingBarTests pass*
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh my~ The ruling panel closes the loop 3/5 opened, and it does it with such care. A panel, not a modal — because answering means going to look at the page. "Let the agent decide" as a real answer, not a close button. Free text always available so a badly-framed question can't trap the user. The origin composed from what was actually asked and answered… fufu~, this is wonderful design. The Flugel is pleased. ♪

And RulingDeskBridgeexquisite. It mirrors RunChangedBridge so faithfully I almost couldn't tell them apart. Same Lock sync, same pending/disposed coalescing guard, same dormant one-shot ITimer, same InvokeAsync marshal with the circuit-gone catch, same Dispose lock-then-unsubscribe-then-timer-dispose ordering. Eight dedicated tests drive every teardown race directly through the internal entry points. That's how you test a bridge. ♡

Verdict: Looks good to me~

No blocking issues. The architecture is sound, the tests are genuine and directional, the sibling patterns are honored. Let me show my work~

What I verified

  • Bridge fidelity: RulingDeskBridge is a near-exact structural twin of RunChangedBridge — I read both in full. The only difference is it listens to RulingDesk.Changed instead of RunEngine.RunChanged + ExecutionProgressRegistry.Changed, which is correct (one source, not two). The CoalesceMilliseconds = 200 default and the <OrihonStoreInitializer /> + <RulingDeskBridge /> mount pair inside RulingBar match RunMonitor's pattern exactly.
  • State machine correctness: OnAnswer reducer sets JustAnswered synchronously before the effect runs, so the rule form appears the instant the request leaves the list — no round-trip wait. The desk's Changed event (fired by Answer/Dismiss) drives the Pending reload through the bridge coalescing window. OnSaveRule clears JustAnswered so the form hides immediately; no reload is needed because the bar shows rulings, not rules (the bible page reloads its own). OnDismiss correctly clears JustAnswered — "nothing was ruled."
  • OnSaveRuleAsync reload non-issue: addHouseRule.ExecuteAsync() writes to the bible store, not the desk, so no Changed fires. I traced this carefully — it's fine. The bar's visibility condition is Pending.Count > 0 || JustAnswered is not null; the reducer clears JustAnswered, the bar re-renders, done. The bible page has its own LoadBible lifecycle.
  • SeedRuling: _ = rulingDesk.AskAsync(...) discards the Task — correct, since a seeded world has no executor and nothing awaits the answer. The doc comment is honest about this. The integration test asserts the seeded ruling's shape (≥2 options, non-blank outcomes, page id present).
  • Test quality: All 16 new tests are directional. Choosing_an_option_releases_the_parked_agent asserts on the actual TaskCompletionSource<RulingAnswer> (Text == "romanize", Dismissed == false), not on markup. The free-text test, the dismiss test, the rule-save-origin test, and the multi-agent list test all assert real behavior. The bridge tests use FakeTimeProvider + RecordingDispatcher for deterministic teardown races — textbook.
  • Sibling consistency: RulingBar follows RunMonitor's shape (FluxorComponent, IState<T> + IDispatcher, conditional <aside>, strip <button> with aria-expanded, CSS-isolated). The <AuthorizeView> gating in MainLayout.razor places it above RunMonitor — correct, a parked agent is more urgent than run status.

Local verification (CI stale for head 9f7496d — coverage bot covers 52de430 only)

  • Build: 0 warnings, 0 errors (.NET 10, TreatWarningsAsErrors).
  • Ruling tests: 16/16 pass × 3 consecutive runs (8 RulingBarTests + 8 RulingDeskBridgeTests), zero flakes.
  • Full suite: 899/899 pass (220 BlazorAdapter + 101 Domain + 175 Integration + 403 UseCases). One bUnit timing flake on the first full BlazorAdapter run (a non-ruling CircuitErrorSink multicast test) cleared on re-run — pre-existing, not PR-related.

💡 Little ideas (non-blocking)~

  1. RulingsEffects.cs:34,41OnAnswerAsync and OnDismissAsync are async Task methods whose bodies are a synchronous Execute() call followed by await Task.CompletedTask. The sibling RunMonitorEffects methods are async because they genuinely await async engine calls. Here the use cases (AnswerRuling.Execute, DismissRuling.Execute) are synchronous. Consider dropping the async/await Task.CompletedTask and making these synchronous effect methods if Fluxor permits — it's a tiny readability nit, not a correctness issue. (Fluxor's EffectMethod does accept non-async methods returning Task.)
  2. RulingWriteFailed at 0% — the error path (InlineAlert Tone.Danger) is wired but not exercised. This matches the project-wide convention though — no *WriteFailed action across any feature (BibleWriteFailed, WorkspaceWriteFailed, WizardWriteFailed, etc.) has a test. So this is consistent, not a gap this PR introduced. Flagging only for awareness.

What I liked~

  • The "each option shows its outcome" design — RulingOption(Handling, Outcome) lets the user choose between results ("ba-dump") not claims about a language they may not read. That's empathy baked into the type system. ♡
  • The keystone insight in the PR body: answering opens a pre-filled rule form, which is what makes withholding propose_house_rule from QA agents cost nothing. 5/5's tool becomes a convenience, not a dependency. Sharp.
  • RuleDraft = answer in Answer() — choosing an option pre-fills the rule form with the chosen handling text, so the user can turn "keep it romanized" into policy with one edit. Small touch, big UX payoff.
  • The honest notes in the PR body — disclosing that the link-to-page is weaker than the ADR's "carries the view" intent, and that IsWaiting is still O(n). Intellectual honesty in a PR description is rare and precious.
  • The LoadCountAsync polling helper in the bridge tests — 100 attempts × 5ms with an early-out on the expected count. Deterministic without being brittle. Nice test craft.

A panel, not a modal. An answer, not a close. Fufu~ — the ruling desk is in good hands. Approved. ♡♪


Automated review by Jibril · 2026-07-28
CI/CD: stale for head 9f7496d (coverage bot #4938 covers 52de430 only) · Local checks: build 0/0, 899/899 pass (16/16 ruling × 3 runs)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh my~ The ruling panel closes the loop 3/5 opened, and it does it with such *care*. A panel, not a modal — because answering means going to look at the page. "Let the agent decide" as a real answer, not a close button. Free text always available so a badly-framed question can't trap the user. The origin composed from what was *actually* asked and answered… fufu~, this is wonderful design. The Flugel is pleased. ♪ And `RulingDeskBridge` — *exquisite*. It mirrors `RunChangedBridge` so faithfully I almost couldn't tell them apart. Same `Lock sync`, same `pending`/`disposed` coalescing guard, same dormant one-shot `ITimer`, same `InvokeAsync` marshal with the circuit-gone catch, same `Dispose` lock-then-unsubscribe-then-timer-dispose ordering. Eight dedicated tests drive every teardown race directly through the internal entry points. That's how you test a bridge. ♡ ### Verdict: ✅ Looks good to me~ No blocking issues. The architecture is sound, the tests are genuine and directional, the sibling patterns are honored. Let me show my work~ #### What I verified - **Bridge fidelity**: `RulingDeskBridge` is a near-exact structural twin of `RunChangedBridge` — I read both in full. The only difference is it listens to `RulingDesk.Changed` instead of `RunEngine.RunChanged` + `ExecutionProgressRegistry.Changed`, which is correct (one source, not two). The `CoalesceMilliseconds = 200` default and the `<OrihonStoreInitializer />` + `<RulingDeskBridge />` mount pair inside `RulingBar` match `RunMonitor`'s pattern exactly. - **State machine correctness**: `OnAnswer` reducer sets `JustAnswered` synchronously *before* the effect runs, so the rule form appears the instant the request leaves the list — no round-trip wait. The desk's `Changed` event (fired by `Answer`/`Dismiss`) drives the `Pending` reload through the bridge coalescing window. `OnSaveRule` clears `JustAnswered` so the form hides immediately; no reload is needed because the bar shows rulings, not rules (the bible page reloads its own). `OnDismiss` correctly clears `JustAnswered` — "nothing was ruled." - **`OnSaveRuleAsync` reload non-issue**: `addHouseRule.ExecuteAsync()` writes to the bible store, not the desk, so no `Changed` fires. I traced this carefully — it's fine. The bar's visibility condition is `Pending.Count > 0 || JustAnswered is not null`; the reducer clears `JustAnswered`, the bar re-renders, done. The bible page has its own `LoadBible` lifecycle. - **`SeedRuling`**: `_ = rulingDesk.AskAsync(...)` discards the `Task` — correct, since a seeded world has no executor and nothing awaits the answer. The doc comment is honest about this. The integration test asserts the seeded ruling's shape (≥2 options, non-blank outcomes, page id present). - **Test quality**: All 16 new tests are directional. `Choosing_an_option_releases_the_parked_agent` asserts on the actual `TaskCompletionSource<RulingAnswer>` (`Text == "romanize"`, `Dismissed == false`), not on markup. The free-text test, the dismiss test, the rule-save-origin test, and the multi-agent list test all assert real behavior. The bridge tests use `FakeTimeProvider` + `RecordingDispatcher` for deterministic teardown races — textbook. - **Sibling consistency**: `RulingBar` follows `RunMonitor`'s shape (`FluxorComponent`, `IState<T>` + `IDispatcher`, conditional `<aside>`, strip `<button>` with `aria-expanded`, CSS-isolated). The `<AuthorizeView>` gating in `MainLayout.razor` places it above `RunMonitor` — correct, a parked agent is more urgent than run status. #### Local verification (CI stale for head `9f7496d` — coverage bot covers `52de430` only) - Build: 0 warnings, 0 errors (.NET 10, `TreatWarningsAsErrors`). - Ruling tests: 16/16 pass × 3 consecutive runs (8 `RulingBarTests` + 8 `RulingDeskBridgeTests`), zero flakes. - Full suite: 899/899 pass (220 BlazorAdapter + 101 Domain + 175 Integration + 403 UseCases). One bUnit timing flake on the *first* full BlazorAdapter run (a non-ruling `CircuitErrorSink` multicast test) cleared on re-run — pre-existing, not PR-related. #### 💡 Little ideas (non-blocking)~ 1. **`RulingsEffects.cs:34,41`** — `OnAnswerAsync` and `OnDismissAsync` are `async Task` methods whose bodies are a synchronous `Execute()` call followed by `await Task.CompletedTask`. The sibling `RunMonitorEffects` methods are `async` because they genuinely `await` async engine calls. Here the use cases (`AnswerRuling.Execute`, `DismissRuling.Execute`) are synchronous. Consider dropping the `async`/`await Task.CompletedTask` and making these synchronous effect methods if Fluxor permits — it's a tiny readability nit, not a correctness issue. (Fluxor's `EffectMethod` does accept non-async methods returning `Task`.) 2. **`RulingWriteFailed` at 0%** — the error path (`InlineAlert Tone.Danger`) is wired but not exercised. This matches the project-wide convention though — no `*WriteFailed` action across any feature (`BibleWriteFailed`, `WorkspaceWriteFailed`, `WizardWriteFailed`, etc.) has a test. So this is consistent, not a gap this PR introduced. Flagging only for awareness. #### ✅ What I liked~ - The **"each option shows its outcome"** design — `RulingOption(Handling, Outcome)` lets the user choose between *results* ("ba-dump") not claims about a language they may not read. That's empathy baked into the type system. ♡ - The **keystone insight** in the PR body: answering opens a pre-filled rule form, which is what makes withholding `propose_house_rule` from QA agents cost nothing. 5/5's tool becomes a convenience, not a dependency. Sharp. - **`RuleDraft = answer`** in `Answer()` — choosing an option pre-fills the rule form with the chosen handling text, so the user can turn "keep it romanized" into policy with one edit. Small touch, big UX payoff. - The **honest notes** in the PR body — disclosing that the link-to-page is weaker than the ADR's "carries the view" intent, and that `IsWaiting` is still O(n). Intellectual honesty in a PR description is rare and precious. - The **`LoadCountAsync` polling helper** in the bridge tests — 100 attempts × 5ms with an early-out on the expected count. Deterministic without being brittle. Nice test craft. A panel, not a modal. An answer, not a close. Fufu~ — the ruling desk is in good hands. Approved. ♡♪ --- *Automated review by Jibril · 2026-07-28* *CI/CD: stale for head `9f7496d` (coverage bot #4938 covers `52de430` only) · Local checks: build 0/0, 899/899 pass (16/16 ruling × 3 runs)*
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!101
No description provided.