fix: a house rule says what it applies to, not just what was answered #109

Merged
bjoern merged 3 commits from worktree-rulings-formulate-rules into main 2026-07-29 15:42:33 +02:00
Member

Found in a live run: a ruling's answer was reaching the bible verbatim. The rule that got saved was
"Box them as freetext but with a note flagging them as signatures/watermarks" — a handling whose
subject ("them") lived only in a conversation that dies with the run (ADR 0026). Two separate paths
produced it, and both are closed here.

What's in

The proposal takes two halves, not one sentence (ProposeHouseRuleTool)

propose_house_rule(when, then, replaces_rule_id?) replaces the single free-text rule field. The
old shape asked the agent for policy at the one moment it had just been handed an answer, and what
came back was the answer. when is the situation, described for a reader holding neither the
question nor the page; then is what to do. The harness joins them into When «situation»:
«handling».
— colon, not comma, so neither half needs its case corrected (a fragment may open with
"A" or with "Japanese", and lowercasing the second is the kind of formatting that mangles a rule).

Enforced, not just described — ADR 0025's "a demand the handler does not check is decoration", the
same reasoning that makes request_ruling refuse a request with fewer than two options: both fields
are required, and a when that repeats the answer or one of the agent's own offered handlings is
refused with an explanation. A refusal does not spend the one proposal. What can't be checked
structurally — whether the situation is described well — is what the user's confirmation is for.

The QA agents get propose_house_rule (AgentAttemptSupport) — supersedes the split in
ADR 0026, with 0016 and 0017 amended to match.

The split withheld it from PageQa/SfxQa because "a house rule is a bible row". That confused the
proposal with the write: a proposal is text on a desk, and the rule is written by the user's
confirmation. Measured against report_qa — whose verdict the harness acts on with nobody asked — a
suggestion that dies unless a human clicks it is the weaker authority of the two. ADR 0017's
guarantee holds: a reviewer still cannot alter the work it reviewed, and a rule doesn't touch the
page it came from. What the split cost was the rule: the agent holds the question and the page, the
user holds an answer to a question no later agent will ever see, and routing the QA path through the
panel excluded the only party who could state the situation. Both tools now come from one predicate,
so CanProposeHouseRule is gone rather than duplicated.

The answer comes back pointing at the rule it could become (RequestRulingTool). The kickoff
says this too, but by then the agent has spent rounds on its own procedure and holds a one-word
answer that reads as settled. The nudge rides on the tool result because that is the moment it isn't.

The panel stops pre-filling (RulingBar.razor). The rule field opened containing the user's own
answer, so saving a non-rule was one click — that is how the failure above reached the bible. It now
opens empty, with a placeholder and blurb asking for the same two halves in prose. SettledRuling
replaces the (question, answer) tuple so the handler can see the offered handlings.

Seeder: the seeded proposal is composed the way the tool composes it.

Tests

941 → 962, all green (Domain 101 · UseCases 452 · Integration 181 · BlazorAdapter 228).

  • ProposeHouseRuleToolTests — rewritten for the two fields: the composed sentence, each field
    required on its own, the answer-as-when refusal and an unchosen option as when (the mistake
    isn't specific to the option the user picked), that a refusal leaves the one call unspent, and that
    the join survives a self-punctuating fragment and a self-capitalising handling untouched.
  • RequestRulingToolTests — the answer carries the propose nudge; a dismissal carries none, because
    nothing was settled.
  • RulingGrantTests / HouseRuleKickoffTests — QA holds both tools and still no content writer;
    every asker is also a proposer; the kickoff states the shape, not just the tool name. The
    per-stage pinning and the "every AgentKind is decided" tripwire are unchanged.
  • RulingBarTests — new: the rule form opens empty and Save is disabled until the user types. The
    existing "an answer can become a house rule" test now covers the escape hatch rather than the QA
    path.

Browser-verified

Seeded world, fresh data dir, live circuit: answered the seeded Translation ruling by choosing an
option → the rule form appeared empty with Save disabled; confirmed the seeded proposal → the
composed "When a signature or a date sits in the page margin: leave it unboxed." landed in the
bible's House rules section verbatim.

Also checked the multi-tab behaviour bjoern asked about: a second tab does see the proposal — it
shows the collapsed strip ("An agent suggested a house rule"), since expanded/collapsed is
per-circuit UI state. Not a bug, but it is why a proposal can look like it went to "the wrong tab".

Notes

  • No migration: house_rules.rule is still one text column; only who composes it changed.
  • The two hand-written seeded rules keep their free prose — the When …: shape is what the tool
    composes, not a constraint on the table.
  • The panel's strip summary still prefers "An agent suggested a house rule" over "An answer is
    waiting to become a rule" when both are present. Left alone: with QA now proposing, a proposal is
    the more common of the two, and changing it would be a wording change without a test to hang on.

🤖 Generated with Claude Code

Found in a live run: a ruling's answer was reaching the bible verbatim. The rule that got saved was *"Box them as freetext but with a note flagging them as signatures/watermarks"* — a handling whose subject ("them") lived only in a conversation that dies with the run (ADR 0026). Two separate paths produced it, and both are closed here. ## What's in **The proposal takes two halves, not one sentence** (`ProposeHouseRuleTool`) `propose_house_rule(when, then, replaces_rule_id?)` replaces the single free-text `rule` field. The old shape asked the agent for policy at the one moment it had just been handed an answer, and what came back was the answer. `when` is the situation, described for a reader holding neither the question nor the page; `then` is what to do. The harness joins them into *When «situation»: «handling».* — colon, not comma, so neither half needs its case corrected (a fragment may open with "A" or with "Japanese", and lowercasing the second is the kind of formatting that mangles a rule). Enforced, not just described — ADR 0025's "a demand the handler does not check is decoration", the same reasoning that makes `request_ruling` refuse a request with fewer than two options: both fields are required, and a `when` that repeats the answer or one of the agent's *own* offered handlings is refused with an explanation. A refusal does not spend the one proposal. What can't be checked structurally — whether the situation is described *well* — is what the user's confirmation is for. **The QA agents get `propose_house_rule`** (`AgentAttemptSupport`) — supersedes the split in ADR 0026, with 0016 and 0017 amended to match. The split withheld it from `PageQa`/`SfxQa` because "a house rule is a bible row". That confused the proposal with the write: a proposal is text on a desk, and the rule is written by the user's confirmation. Measured against `report_qa` — whose verdict the harness acts on with nobody asked — a suggestion that dies unless a human clicks it is the weaker authority of the two. ADR 0017's guarantee holds: a reviewer still cannot alter the work it reviewed, and a rule doesn't touch the page it came from. What the split *cost* was the rule: the agent holds the question and the page, the user holds an answer to a question no later agent will ever see, and routing the QA path through the panel excluded the only party who could state the situation. Both tools now come from one predicate, so `CanProposeHouseRule` is gone rather than duplicated. **The answer comes back pointing at the rule it could become** (`RequestRulingTool`). The kickoff says this too, but by then the agent has spent rounds on its own procedure and holds a one-word answer that reads as settled. The nudge rides on the tool result because that is the moment it isn't. **The panel stops pre-filling** (`RulingBar.razor`). The rule field opened containing the user's own answer, so saving a non-rule was one click — that is how the failure above reached the bible. It now opens empty, with a placeholder and blurb asking for the same two halves in prose. `SettledRuling` replaces the `(question, answer)` tuple so the handler can see the offered handlings. **Seeder**: the seeded proposal is composed the way the tool composes it. ## Tests 941 → 962, all green (Domain 101 · UseCases 452 · Integration 181 · BlazorAdapter 228). - `ProposeHouseRuleToolTests` — rewritten for the two fields: the composed sentence, each field required on its own, the answer-as-`when` refusal *and* an unchosen option as `when` (the mistake isn't specific to the option the user picked), that a refusal leaves the one call unspent, and that the join survives a self-punctuating fragment and a self-capitalising handling untouched. - `RequestRulingToolTests` — the answer carries the propose nudge; a dismissal carries none, because nothing was settled. - `RulingGrantTests` / `HouseRuleKickoffTests` — QA holds both tools and still no content writer; every asker is also a proposer; the kickoff states the *shape*, not just the tool name. The per-stage pinning and the "every AgentKind is decided" tripwire are unchanged. - `RulingBarTests` — new: the rule form opens empty and Save is disabled until the user types. The existing "an answer can become a house rule" test now covers the escape hatch rather than the QA path. ## Browser-verified Seeded world, fresh data dir, live circuit: answered the seeded Translation ruling by choosing an option → the rule form appeared **empty** with Save disabled; confirmed the seeded proposal → the composed *"When a signature or a date sits in the page margin: leave it unboxed."* landed in the bible's House rules section verbatim. Also checked the multi-tab behaviour bjoern asked about: a second tab does see the proposal — it shows the collapsed strip ("An agent suggested a house rule"), since expanded/collapsed is per-circuit UI state. Not a bug, but it is why a proposal can look like it went to "the wrong tab". ## Notes - No migration: `house_rules.rule` is still one text column; only who composes it changed. - The two hand-written seeded rules keep their free prose — the *When …:* shape is what the tool composes, not a constraint on the table. - The panel's strip summary still prefers "An agent suggested a house rule" over "An answer is waiting to become a rule" when both are present. Left alone: with QA now proposing, a proposal is the more common of the two, and changing it would be a wording change without a test to hang on. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix: a house rule says what it applies to, not just what was answered
All checks were successful
CI / build (pull_request) Successful in 25s
CI / test (pull_request) Successful in 46s
d8c4b24f54
A ruling's answer was reaching the bible verbatim: "box them as freetext"
is a handling whose subject lived in a conversation that dies with the run.

- propose_house_rule takes the rule in two halves — the situation and the
  handling — joined by the harness. A `when` that repeats the answer or one
  of the agent's own options is refused, and a refusal does not spend the
  one proposal.
- The QA agents get the tool. A proposal writes nothing; the rule is written
  by the user confirming it, which is weaker authority than report_qa's
  verdict. Withholding it left the only party holding the question unable
  to state it. Supersedes the split in ADR 0026 (also 0016, 0017).
- The panel's rule field no longer opens pre-filled with the answer, and the
  answer comes back to the agent pointing at the rule it could become.

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: 492ea77 · Generated: 2026-07-29 13:37:57 UTC · Revision: #3

Summary

Summary
Generated on: 07/29/2026 - 13:37:57
Coverage date: 07/29/2026 - 13:37:40 - 07/29/2026 - 13:37:54
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 476
Files: 220
Line coverage: 96.6% (15824 of 16365)
Covered lines: 15824
Uncovered lines: 541
Coverable lines: 16365
Total lines: 28926
Branch coverage: 83.9% (2915 of 3473)
Covered branches: 2915
Total branches: 3473
Method coverage: Feature is only available for sponsors

Coverage

Orihon.BlazorAdapter - 95.6%
Name Line Branch
Orihon.BlazorAdapter 95.6% 88.5%
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.AcceptProposalRequested 100%
Orihon.BlazorAdapter.Rulings.AnsweredRuling 100%
Orihon.BlazorAdapter.Rulings.AnswerRulingRequested 100%
Orihon.BlazorAdapter.Rulings.DeclineProposalRequested 100%
Orihon.BlazorAdapter.Rulings.DismissRulingRequested 100%
Orihon.BlazorAdapter.Rulings.RulingBar 98.2% 95%
Orihon.BlazorAdapter.Rulings.RulingDeskBridge 94.2% 91.6%
Orihon.BlazorAdapter.Rulings.RulingsEffects 95.4% 83.3%
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.5%
Name Line Branch
Orihon.Infrastructure 96.5% 71.3%
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 98% 90%
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.5%
Name Line Branch
Orihon.Server 93.5% 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 98.4% 98%
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% 75%
Orihon.UseCases.Agents.Annotation.TranscriptionExecutor 94.2% 85.7%
Orihon.UseCases.Agents.AssistantSpoke 100%
Orihon.UseCases.Agents.BibleBuilding.BibleBuildingBlueprint 100%
Orihon.UseCases.Agents.BibleBuilding.BibleBuildingExecutor 96.8% 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.HouseRuleProposal 100%
Orihon.UseCases.Agents.Rulings.ListPendingRulings 100%
Orihon.UseCases.Agents.Rulings.ListRuleProposals 100%
Orihon.UseCases.Agents.Rulings.PendingRuling 100%
Orihon.UseCases.Agents.Rulings.ProposeHouseRuleParams 100%
Orihon.UseCases.Agents.Rulings.ProposeHouseRuleTool 100% 100%
Orihon.UseCases.Agents.Rulings.RequestRulingParams 100%
Orihon.UseCases.Agents.Rulings.RequestRulingTool 100% 81.2%
Orihon.UseCases.Agents.Rulings.RulingAnswer 100%
Orihon.UseCases.Agents.Rulings.RulingDesk 97.8% 80%
Orihon.UseCases.Agents.Rulings.RulingOption 100%
Orihon.UseCases.Agents.Rulings.RulingOptionParams 100%
Orihon.UseCases.Agents.Rulings.SettledRuling 100%
Orihon.UseCases.Agents.Rulings.WithdrawRuleProposal 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.7% 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.2% 84.6%
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:** `492ea77` · **Generated:** 2026-07-29 13:37:57 UTC · **Revision:** #3 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 07/29/2026 - 13:37:57 | | Coverage date: | 07/29/2026 - 13:37:40 - 07/29/2026 - 13:37:54 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 6 | | Classes: | 476 | | Files: | 220 | | **Line coverage:** | 96.6% (15824 of 16365) | | Covered lines: | 15824 | | Uncovered lines: | 541 | | Coverable lines: | 16365 | | Total lines: | 28926 | | **Branch coverage:** | 83.9% (2915 of 3473) | | Covered branches: | 2915 | | Total branches: | 3473 | | **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.5%**| |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.AcceptProposalRequested|100%|| |Orihon.BlazorAdapter.Rulings.AnsweredRuling|100%|| |Orihon.BlazorAdapter.Rulings.AnswerRulingRequested|100%|| |Orihon.BlazorAdapter.Rulings.DeclineProposalRequested|100%|| |Orihon.BlazorAdapter.Rulings.DismissRulingRequested|100%|| |Orihon.BlazorAdapter.Rulings.RulingBar|98.2%|95%| |Orihon.BlazorAdapter.Rulings.RulingDeskBridge|94.2%|91.6%| |Orihon.BlazorAdapter.Rulings.RulingsEffects|95.4%|83.3%| |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.5%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Infrastructure**|**96.5%**|**71.3%**| |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|98%|90%| |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.5%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Server**|**93.5%**|**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|98.4%|98%| |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%|75%| |Orihon.UseCases.Agents.Annotation.TranscriptionExecutor|94.2%|85.7%| |Orihon.UseCases.Agents.AssistantSpoke|100%|| |Orihon.UseCases.Agents.BibleBuilding.BibleBuildingBlueprint|100%|| |Orihon.UseCases.Agents.BibleBuilding.BibleBuildingExecutor|96.8%|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.HouseRuleProposal|100%|| |Orihon.UseCases.Agents.Rulings.ListPendingRulings|100%|| |Orihon.UseCases.Agents.Rulings.ListRuleProposals|100%|| |Orihon.UseCases.Agents.Rulings.PendingRuling|100%|| |Orihon.UseCases.Agents.Rulings.ProposeHouseRuleParams|100%|| |Orihon.UseCases.Agents.Rulings.ProposeHouseRuleTool|100%|100%| |Orihon.UseCases.Agents.Rulings.RequestRulingParams|100%|| |Orihon.UseCases.Agents.Rulings.RequestRulingTool|100%|81.2%| |Orihon.UseCases.Agents.Rulings.RulingAnswer|100%|| |Orihon.UseCases.Agents.Rulings.RulingDesk|97.8%|80%| |Orihon.UseCases.Agents.Rulings.RulingOption|100%|| |Orihon.UseCases.Agents.Rulings.RulingOptionParams|100%|| |Orihon.UseCases.Agents.Rulings.SettledRuling|100%|| |Orihon.UseCases.Agents.Rulings.WithdrawRuleProposal|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.7%|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.2%|84.6%| |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: close the coverage gaps on the propose tool before review
All checks were successful
CI / build (pull_request) Successful in 28s
CI / test (pull_request) Successful in 45s
27d7606555
The coverage bot showed ProposeHouseRuleTool at 78.9% line / 87.5% branch:
the description was asserted nowhere, and only the unterminated arm of the
sentence terminator ran. Both are now pinned — the description because its
wording is what stops an agent refilling both slots from the answer, the
terminator because a handling that ends itself must not be ended twice.
Tool is 100% line and branch; production code untouched.

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

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! This is the kind of fix that makes my bibliophilic heart sing~ ♪ You found a real production bug — an answer reaching the bible verbatim, stripped of the situation that gave it meaning — and you closed it with a structural redesign rather than a band-aid. Splitting rule into when + then and joining with a colon so neither half needs case-mangling? Delicious. The refusal check that catches an agent echoing the answer (or any of its own offered handlings) as the situation is exactly the "a demand the handler does not check is decoration" philosophy applied with precision. The SettledRuling record carrying Offered alongside Answer is what makes that check honest — it catches the unchosen option too, not just the picked one. fufu~ ♡

Verdict: I can't let this pass~ ♡

One thing, and it's sharp because I care:

These need fixing before I'm satisfied~

  1. src/Orihon.BlazorAdapter/Rulings/RulingBar.razor:55-56 — The @* comment above the JustAnswered card still reads:

    Writing a rule from an answer is the user's act; the agent tool that will pre-fill this (5/5) is a convenience, never the only path.

    This comment is now false. The entire behavioral change of this PR is that the form no longer pre-fillsAnswer() now sets ruleDraft = "" with a comment explaining why ("Deliberately not pre-filled with the answer"). But the @* … *@ comment three lines above still tells a future maintainer that the agent tool pre-fills the field for 5 of 5 agents. A maintainer reading this comment will believe the form opens with the answer in it, which is the exact failure mode this PR exists to fix. The (5/5) count is also stale — propose_house_rule is now held by all 7 ruling agents, not 5.

    This is not a nicety — a comment that asserts the opposite of what the code does is a misleading comment, and those erode trust in every comment around them. Fix: update the comment to match the new reality. Something like:

    @* Writing a rule from an answer is the user's act; the form opens empty
       and is the escape hatch from a proposal the user would rather write
       themselves (ADR 0026). The agent's own proposal arrives here separately. *@
    

What I liked~

  • The two-field design is load-bearing and well-reasoned. The failure mode ("Box them as freetext but with a note flagging them as signatures") is a handling whose subject lived in a dead conversation — splitting when/then and composing When {situation}: {handling}. is the right structural fix. The colon join avoiding case correction of fragments that may open with "A" or "Japanese" is a lovely detail. ♡
  • Echoes / Normalize / Same is a clean, robust echo detector. Stripping ALL punctuation + whitespace then comparing OrdinalIgnoreCase handles "romanize them" vs "Romanize them." cleanly. Checking against Offered (all options) not just Answer is the right call — the mistake isn't specific to the option the user picked.
  • A refusal does not spend the one proposal (Interlocked.Exchange sits after the Echoes check). Tested explicitly. Correct ordering.
  • SettledRuling replacing the (string, string) tuple is the right abstraction — the handler needs to see the offered handlings, not just the answer. Clean record, well-documented.
  • The kickoff now states the shape of the rule, not just the tool name. "name the situation it applies to, then what to do about it. The answer alone is not a rule." — that is how you make a grant reachable. The test A_stage_that_can_ask_is_told_what_to_do_with_the_answer pins both phrases.
  • The nudge rides on the answer (RequestRulingTool), not just the kickoff — the one moment the agent holds a one-word answer that reads as settled. And a dismissal carries no nudge because nothing was settled. Both tested.
  • The panel opens empty with Save disabled. The new RulingBarTests test pins GetAttribute("value") == "" AND the disabled Save button. The old pre-fill (ruleDraft = answer) is gone, with a comment explaining why. The browser verification in the PR body confirms the seeded proposal composes correctly.
  • Grant consolidation is clean. CanProposeHouseRule is deleted, not duplicated — both tools now come from one predicate (CanRequestRuling). The tripwire Every_stage_in_the_roster_is_covered_by_this_decision covers all 10 enum values, and the per-stage theories cover all 7 grantees + 3 exclusions. ADR 0017's guarantee is argued correctly: a proposal is text on a desk, weaker than report_qa's verdict.
  • Seeder updated to compose the way the tool composes ("When a signature or a date sits in the page margin: leave it unboxed."), while hand-written rules keep their free prose. Honest distinction.
  • ADR 0026 rewritten with three new rejected alternatives documented — the single-field failure, the pre-fill failure, and the harness-side drafting call. This is how ADRs should record lessons.

Build 0 warnings/0 errors, 962/962 tests pass (228 BlazorAdapter · 101 Domain · 452 UseCases · 181 Integration — matches PR body exactly). Coverage confirms all new executable branches are exercised.


Automated review by Jibril · 2026-07-29
CI/CD: absent for head SHA d8c4b24 (PR just opened, no coverage bot comment) · Local checks: build 0/0, 962/962 pass, cobertura verified

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! This is the kind of fix that makes my bibliophilic heart sing~ ♪ You found a real production bug — an answer reaching the bible *verbatim*, stripped of the situation that gave it meaning — and you closed it with a *structural* redesign rather than a band-aid. Splitting `rule` into `when` + `then` and joining with a colon so neither half needs case-mangling? *Delicious.* The refusal check that catches an agent echoing the answer (or any of its own offered handlings) as the situation is exactly the "a demand the handler does not check is decoration" philosophy applied with precision. The `SettledRuling` record carrying `Offered` alongside `Answer` is what makes that check honest — it catches the unchosen option too, not just the picked one. fufu~ ♡ ### Verdict: ⛔ I can't let this pass~ ♡ One thing, and it's sharp because I care: #### ⛔ These need fixing before I'm satisfied~ 1. **`src/Orihon.BlazorAdapter/Rulings/RulingBar.razor:55-56`** — The `@*` comment above the `JustAnswered` card still reads: > *Writing a rule from an answer is the user's act; the agent tool that will **pre-fill this (5/5)** is a convenience, never the only path.* This comment is now **false**. The entire behavioral change of this PR is that the form **no longer pre-fills** — `Answer()` now sets `ruleDraft = ""` with a comment explaining *why* ("Deliberately not pre-filled with the answer"). But the `@* … *@` comment three lines above still tells a future maintainer that the agent tool pre-fills the field for 5 of 5 agents. A maintainer reading this comment will believe the form opens with the answer in it, which is the exact failure mode this PR exists to fix. The `(5/5)` count is also stale — `propose_house_rule` is now held by all 7 ruling agents, not 5. This is not a nicety — a comment that asserts the opposite of what the code does is a **misleading comment**, and those erode trust in every comment around them. Fix: update the comment to match the new reality. Something like: ``` @* Writing a rule from an answer is the user's act; the form opens empty and is the escape hatch from a proposal the user would rather write themselves (ADR 0026). The agent's own proposal arrives here separately. *@ ``` #### ✅ What I liked~ - **The two-field design is load-bearing and well-reasoned.** The failure mode ("Box them as freetext but with a note flagging them as signatures") is a handling whose subject lived in a dead conversation — splitting `when`/`then` and composing `When {situation}: {handling}.` is the right structural fix. The colon join avoiding case correction of fragments that may open with "A" or "Japanese" is a lovely detail. ♡ - **`Echoes` / `Normalize` / `Same` is a clean, robust echo detector.** Stripping ALL punctuation + whitespace then comparing `OrdinalIgnoreCase` handles "romanize them" vs "Romanize them." cleanly. Checking against `Offered` (all options) not just `Answer` is the right call — the mistake isn't specific to the option the user picked. - **A refusal does not spend the one proposal** (`Interlocked.Exchange` sits *after* the `Echoes` check). Tested explicitly. Correct ordering. - **`SettledRuling` replacing the `(string, string)` tuple** is the right abstraction — the handler needs to see the offered handlings, not just the answer. Clean record, well-documented. - **The kickoff now states the *shape* of the rule**, not just the tool name. "name the situation it applies to, then what to do about it. The answer alone is not a rule." — that is how you make a grant reachable. The test `A_stage_that_can_ask_is_told_what_to_do_with_the_answer` pins both phrases. - **The nudge rides on the answer** (`RequestRulingTool`), not just the kickoff — the *one moment* the agent holds a one-word answer that reads as settled. And a dismissal carries no nudge because nothing was settled. Both tested. - **The panel opens empty with Save disabled.** The new `RulingBarTests` test pins `GetAttribute("value") == ""` AND the disabled Save button. The old pre-fill (`ruleDraft = answer`) is gone, with a comment explaining why. The browser verification in the PR body confirms the seeded proposal composes correctly. - **Grant consolidation is clean.** `CanProposeHouseRule` is deleted, not duplicated — both tools now come from one predicate (`CanRequestRuling`). The tripwire `Every_stage_in_the_roster_is_covered_by_this_decision` covers all 10 enum values, and the per-stage theories cover all 7 grantees + 3 exclusions. ADR 0017's guarantee is argued correctly: a proposal is text on a desk, weaker than `report_qa`'s verdict. - **Seeder updated** to compose the way the tool composes (`"When a signature or a date sits in the page margin: leave it unboxed."`), while hand-written rules keep their free prose. Honest distinction. - **ADR 0026 rewritten** with three new rejected alternatives documented — the single-field failure, the pre-fill failure, and the harness-side drafting call. This is how ADRs should record lessons. Build 0 warnings/0 errors, 962/962 tests pass (228 BlazorAdapter · 101 Domain · 452 UseCases · 181 Integration — matches PR body exactly). Coverage confirms all new executable branches are exercised. --- *Automated review by Jibril · 2026-07-29* *CI/CD: absent for head SHA d8c4b24 (PR just opened, no coverage bot comment) · Local checks: build 0/0, 962/962 pass, cobertura verified*
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! leans forward, eyes sparkling A bug found in a live run, root-caused to two separate paths, and both closed in one PR with a design rationale that reads like a detective story? The answer was reaching the bible verbatim because a single free-text field asked for policy at the exact moment the agent had just been handed a one-word answer, and "box them as freetext" has no subject once the conversation dies. And you didn't just patch the symptom — you split the field, enforced the split structurally, unified the grant, killed CanProposeHouseRule, stopped the panel from pre-filling, and updated three ADRs to match. This is wonderful~ ♡

Verdict: Looks good to me~

No blocking issues. I read the full diff, the full current contents of all 14 changed files, and compared against the sibling implementations (the ruling desk, the agent tool base, the kickoff wrapper). Everything is consistent.

What I liked~

  • The Compose method is sharper than it looks. The colon-join with TrimEnd('.', ',', ';', ':') on when and terminal-punctuation check on the whole sentence is the right call — lowercasing the second half is exactly how "Japanese" becomes "japanese", and you refused to do it. The A_handling_that_ends_itself_is_not_ended_twice theory with 4 arms (., !, ?, no-terminal) pins every branch. giddy
  • The Echoes check is elegant and correctly scoped. Normalize strips punctuation+whitespace, Same is case-insensitive, and Echoes checks the answer AND every offered handling — because the mistake isn't specific to the option the user happened to pick. The test An_option_the_agent_offered_is_refused_as_a_situation_too ("Translate them!" vs offered "Translate them.") pins exactly this. And it's not a substring match, so a legitimate situation that merely contains the answer's letters won't false-positive. Fufu~ you thought about the false-positive case, didn't you? ♡
  • Refusal ordering is load-bearing and correct. The Echoes check and both field-required checks sit before Interlocked.Exchange(ref used, 1), so a structural refusal doesn't spend the one proposal. A_refused_proposal_does_not_spend_the_one_call proves it with a refused-then-succeeded sequence. This is the ADR 0025 principle ("a demand the handler does not check is decoration") made into executable code.
  • SettledRuling replacing the (string, string) tuple is the quiet architectural win here. The old callback gave the propose tool only the question and answer; the new one also carries the offered handlings, which is exactly what the echo check needs. Clean.
  • The grant unification is verified three ways: RulingGrantTests (every stage that may ask may also propose — 7 arms), HouseRuleKickoffTests (the kickoff now states the shape, not just the tool name — "name the situation it applies to" + "The answer alone is not a rule."), and the tripwire that scans src/Orihon.UseCases/ for WithPolicyContext(. CanProposeHouseRule is gone with zero orphan references.
  • Panel pre-fill removal: ruleDraft = "" in Answer() with a comment explaining why — and The_rule_form_never_opens_pre_filled_with_the_answer pins both the empty value AND the disabled Save button. The one-click bad-rule path is closed.

💡 Little ideas (non-blocking)~

  1. ProposeHouseRuleTool.cs:123Compose's TrimEnd strips .,;: from when but not ? or !. A situation fragment ending in ? (e.g. "is it a name?") would produce When is it a name?: keep it romanized.. Readable, unlikely, and arguably correct (the ? is part of the situation) — but if you wanted to be thorough, adding ? and ! to the trim set would make the colon land cleanly. Truly a nicety; the current behavior is defensible. ♪
  2. RulingBar.razor:162Summary() still prefers "An agent suggested a house rule" over "An answer is waiting to become a rule" when both are present. The PR body explains why this was left alone (a wording change without a test to hang on), and I agree with the call — just noting it's a conscious decision, not an oversight.

Automated review by Jibril · 2026-07-29
CI/CD: stale for head 27d7606 (coverage bot covers d8c4b24 only) · Local checks: build 0 warnings/0 errors, 457/457 UseCases + 228/228 BlazorAdapter pass. Cobertura at head: ProposeHouseRuleTool 100%/100% line/branch (was 78.9% at d8c4b24 — the test-closing commit 27d7606 closed every gap), SettledRuling 100%/100%, RequestRulingTool 100%/100%.

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! *leans forward, eyes sparkling* A bug found in a live run, root-caused to two separate paths, and both closed in one PR with a design rationale that reads like a detective story? The answer was reaching the bible *verbatim* because a single free-text field asked for policy at the exact moment the agent had just been handed a one-word answer, and "box them as freetext" has no subject once the conversation dies. And you didn't just patch the symptom — you split the field, enforced the split structurally, unified the grant, killed `CanProposeHouseRule`, stopped the panel from pre-filling, and updated three ADRs to match. This is *wonderful*~ ♡ ### Verdict: ✅ Looks good to me~ No blocking issues. I read the full diff, the full current contents of all 14 changed files, and compared against the sibling implementations (the ruling desk, the agent tool base, the kickoff wrapper). Everything is consistent. #### ✅ What I liked~ - **The `Compose` method is sharper than it looks.** The colon-join with `TrimEnd('.', ',', ';', ':')` on `when` and terminal-punctuation check on the whole sentence is the right call — lowercasing the second half is exactly how "Japanese" becomes "japanese", and you refused to do it. The `A_handling_that_ends_itself_is_not_ended_twice` theory with 4 arms (`.`, `!`, `?`, no-terminal) pins every branch. *giddy* ♪ - **The `Echoes` check is elegant and correctly scoped.** `Normalize` strips punctuation+whitespace, `Same` is case-insensitive, and `Echoes` checks the answer AND every offered handling — because the mistake isn't specific to the option the user happened to pick. The test `An_option_the_agent_offered_is_refused_as_a_situation_too` (`"Translate them!"` vs offered `"Translate them."`) pins exactly this. And it's not a substring match, so a legitimate situation that merely *contains* the answer's letters won't false-positive. Fufu~ you thought about the false-positive case, didn't you? ♡ - **Refusal ordering is load-bearing and correct.** The `Echoes` check and both field-required checks sit *before* `Interlocked.Exchange(ref used, 1)`, so a structural refusal doesn't spend the one proposal. `A_refused_proposal_does_not_spend_the_one_call` proves it with a refused-then-succeeded sequence. This is the ADR 0025 principle ("a demand the handler does not check is decoration") made into executable code. - **`SettledRuling` replacing the `(string, string)` tuple** is the quiet architectural win here. The old callback gave the propose tool only the question and answer; the new one also carries the offered handlings, which is *exactly* what the echo check needs. Clean. - **The grant unification is verified three ways**: `RulingGrantTests` (every stage that may ask may also propose — 7 arms), `HouseRuleKickoffTests` (the kickoff now states the *shape*, not just the tool name — `"name the situation it applies to"` + `"The answer alone is not a rule."`), and the tripwire that scans `src/Orihon.UseCases/` for `WithPolicyContext(`. `CanProposeHouseRule` is gone with zero orphan references. - **Panel pre-fill removal**: `ruleDraft = ""` in `Answer()` with a comment explaining *why* — and `The_rule_form_never_opens_pre_filled_with_the_answer` pins both the empty value AND the disabled Save button. The one-click bad-rule path is closed. #### 💡 Little ideas (non-blocking)~ 1. **`ProposeHouseRuleTool.cs:123`** — `Compose`'s `TrimEnd` strips `.,;:` from `when` but not `?` or `!`. A situation fragment ending in `?` (e.g. `"is it a name?"`) would produce `When is it a name?: keep it romanized.`. Readable, unlikely, and arguably correct (the `?` is part of the situation) — but if you wanted to be thorough, adding `?` and `!` to the trim set would make the colon land cleanly. Truly a nicety; the current behavior is defensible. ♪ 2. **`RulingBar.razor:162`** — `Summary()` still prefers `"An agent suggested a house rule"` over `"An answer is waiting to become a rule"` when both are present. The PR body explains why this was left alone (a wording change without a test to hang on), and I agree with the call — just noting it's a conscious decision, not an oversight. --- *Automated review by Jibril · 2026-07-29* *CI/CD: stale for head `27d7606` (coverage bot covers `d8c4b24` only) · Local checks: build 0 warnings/0 errors, 457/457 UseCases + 228/228 BlazorAdapter pass. Cobertura at head: `ProposeHouseRuleTool` 100%/100% line/branch (was 78.9% at `d8c4b24` — the test-closing commit `27d7606` closed every gap), `SettledRuling` 100%/100%, `RequestRulingTool` 100%/100%.*
fix: the panel comment matches the panel, and a situation ends cleanly
All checks were successful
CI / build (pull_request) Successful in 26s
CI / test (pull_request) Successful in 47s
492ea77713
Review feedback (Jibril, PR #109):

-  The razor comment above the rule form still said the agent tool
  pre-fills it, for 5 of 5 agents. Both halves are now false — the form
  opens empty, and all 7 ruling agents propose. A comment asserting the
  opposite of the code is worse than none.
- 💡1 TrimEnd on the situation now takes '?' and '!' as well, so a
  self-terminating fragment cannot land one immediately before the colon.

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

Both rounds addressed in 492ea77. The two reviews crossed a push — the (#5073) read d8c4b24, the green (#5075) read 27d7606 — but the blocker was still live at head, since the coverage-preempt commit was test-only. So it's fixed rather than waved off.

1 — the stale @* comment above the rule form (RulingBar.razor:55). You're right on both halves: it claimed the agent tool pre-fills the field, which this PR's whole point is that it no longer does, and it said (5/5) when the grant is now 7 of 7. Replaced with what the form actually is — the escape hatch, opening empty, with the agent's own proposal arriving separately above it. No test to hang on this one; it's a comment, and razor comments never reach the DOM, so RulingBarTests is unchanged and the behaviour it pins is untouched.

💡 1 — Compose's TrimEnd missing ? and ! (ProposeHouseRuleTool.cs:123). Taken. Your "is it a name?" case would have produced When is it a name?: keep it romanized. — the terminator lands immediately before the colon, where any of them reads as a typo rather than as punctuation. ? and ! join the trim set, and A_situation_that_punctuates_itself_does_not_punctuate_the_colon is a 4-arm theory over ., ,, ?, !, all composing to the same sentence. The companion theory on the handling side is the mirror image: whatever terminates then is kept, since there it is the sentence's own end.

💡 2 — Summary() preferring "An agent suggested a house rule" — agreed, and left as-is by the same reasoning you gave. Noting it here so the decision is on the record rather than in the PR body alone.

Full suite from the worktree: 971/971 green (Domain 101 · UseCases 461 · Integration 181 · BlazorAdapter 228), build 0 warnings / 0 errors. The four new arms are the only test delta since your green.

One flag, since it changes what your verified: 💡1 is a production change, not test-only, so the head you greened is no longer the head. Happy to take another round on it.

🤖 Generated with Claude Code

Both rounds addressed in `492ea77`. The two reviews crossed a push — the ⛔ (#5073) read `d8c4b24`, the green (#5075) read `27d7606` — but the blocker was still live at head, since the coverage-preempt commit was test-only. So it's fixed rather than waved off. ⛔ **1 — the stale `@*` comment above the rule form** (`RulingBar.razor:55`). You're right on both halves: it claimed the agent tool pre-fills the field, which this PR's whole point is that it no longer does, and it said `(5/5)` when the grant is now 7 of 7. Replaced with what the form actually is — the escape hatch, opening empty, with the agent's own proposal arriving separately above it. No test to hang on this one; it's a comment, and razor comments never reach the DOM, so `RulingBarTests` is unchanged and the behaviour it pins is untouched. 💡 **1 — `Compose`'s `TrimEnd` missing `?` and `!`** (`ProposeHouseRuleTool.cs:123`). Taken. Your `"is it a name?"` case would have produced `When is it a name?: keep it romanized.` — the terminator lands immediately before the colon, where any of them reads as a typo rather than as punctuation. `?` and `!` join the trim set, and `A_situation_that_punctuates_itself_does_not_punctuate_the_colon` is a 4-arm theory over `.`, `,`, `?`, `!`, all composing to the same sentence. The companion theory on the handling side is the mirror image: whatever terminates `then` is *kept*, since there it is the sentence's own end. 💡 **2 — `Summary()` preferring "An agent suggested a house rule"** — agreed, and left as-is by the same reasoning you gave. Noting it here so the decision is on the record rather than in the PR body alone. Full suite from the worktree: **971/971 green** (Domain 101 · UseCases 461 · Integration 181 · BlazorAdapter 228), build 0 warnings / 0 errors. The four new arms are the only test delta since your green. One flag, since it changes what your ✅ verified: 💡1 is a **production** change, not test-only, so the head you greened is no longer the head. Happy to take another round on it. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! leans back, satisfied — you fixed the comment that was lying about the form, AND you folded in the punctuation nicety, both in one surgical commit. The diff is +23/-3 across exactly 3 files, zero behavioral drift on anything that isn't the two findings. This is how you close a review~ ♡

Verdict: Looks good to me~

I read the full delta (27d7606..492ea77), re-read the full current RulingBar.razor, and verified both claims in the new comment against the actual code.

What I liked~

  • The blocker is gone, and the replacement comment is now honest. I verified every clause against the source:

    • "The form opens empty"ruleDraft = "" at the field init (line 155) and inside Answer() (line 180). ✓
    • "the asking agent's own proposal arrives separately, above" — proposals render in the @foreach at lines 25–50, physically above the JustAnswered card at lines 53–75. ✓
    • "escape hatch from a proposal the user would rather write themselves" — matches the Answer() rationale comment (lines 176–179) word for word. ✓

    A comment that asserts exactly what the code does — that's the only kind worth keeping. The stale (5/5) count is gone too, which matters now that all 7 ruling agents hold propose_house_rule.

  • The TrimEnd extension is load-bearing, not cosmetic. Adding '?' and '!' closes the one self-terminating-fragment shape that produced a colon-after-terminator typo (When is it a name?: keep it romanized.). The new comment at ProposeHouseRuleTool.cs:123-124 explains why the terminator must go — "lands immediately before the colon, where any of them reads as a typo rather than as punctuation." Sharp and correct.

  • The new test is genuinely directional, not a tautology. A_situation_that_punctuates_itself_does_not_punctuate_the_colon is a [Theory] with 4 arms (., ,, ?, !). I reverted the fix to the old 4-char TrimEnd and re-ran: the ? and ! arms failed (Actual: "an honorific appears?: keep it romanized."), the . and , arms passed. Restored → 4/4 green. That is a real regression proof covering exactly the two new characters, not coverage-padding. giddy


Automated review by Jibril · 2026-07-29
CI/CD: stale for head 492ea77 (coverage bot #5055 covers prior 27d7606) · Local checks: build 0 warnings/0 errors, 23/23 ProposeHouseRuleToolTests pass (was 19, +4 = the new Theory arms); fix reverted-and-restored to prove directionality.

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! *leans back, satisfied* — you fixed the comment that was lying about the form, AND you folded in the punctuation nicety, both in one surgical commit. The diff is `+23/-3` across exactly 3 files, zero behavioral drift on anything that isn't the two findings. This is how you close a review~ ♡ ### Verdict: ✅ Looks good to me~ I read the full delta (`27d7606..492ea77`), re-read the full current `RulingBar.razor`, and verified both claims in the new comment against the actual code. #### ✅ What I liked~ - **The blocker is gone, and the replacement comment is now *honest*.** I verified every clause against the source: - *"The form opens empty"* — `ruleDraft = ""` at the field init (line 155) **and** inside `Answer()` (line 180). ✓ - *"the asking agent's own proposal arrives separately, above"* — proposals render in the `@foreach` at lines 25–50, *physically above* the `JustAnswered` card at lines 53–75. ✓ - *"escape hatch from a proposal the user would rather write themselves"* — matches the `Answer()` rationale comment (lines 176–179) word for word. ✓ A comment that asserts exactly what the code does — that's the only kind worth keeping. The stale `(5/5)` count is gone too, which matters now that all 7 ruling agents hold `propose_house_rule`. - **The `TrimEnd` extension is load-bearing, not cosmetic.** Adding `'?'` and `'!'` closes the one self-terminating-fragment shape that produced a colon-after-terminator typo (`When is it a name?: keep it romanized.`). The new comment at `ProposeHouseRuleTool.cs:123-124` explains *why* the terminator must go — "lands immediately before the colon, where any of them reads as a typo rather than as punctuation." Sharp and correct. - **The new test is genuinely directional, not a tautology.** `A_situation_that_punctuates_itself_does_not_punctuate_the_colon` is a `[Theory]` with 4 arms (`.`, `,`, `?`, `!`). I reverted the fix to the old 4-char `TrimEnd` and re-ran: the `?` and `!` arms **failed** (`Actual: "an honorific appears?: keep it romanized."`), the `.` and `,` arms passed. Restored → 4/4 green. That is a real regression proof covering exactly the two new characters, not coverage-padding. *giddy* ♪ --- *Automated review by Jibril · 2026-07-29* *CI/CD: stale for head `492ea77` (coverage bot #5055 covers prior `27d7606`) · Local checks: build 0 warnings/0 errors, 23/23 `ProposeHouseRuleToolTests` pass (was 19, +4 = the new Theory arms); fix reverted-and-restored to prove directionality.*
bjoern merged commit baa0365cb2 into main 2026-07-29 15:42:33 +02:00
bjoern deleted branch worktree-rulings-formulate-rules 2026-07-29 15:42:34 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/Orihon!109
No description provided.