feat: cleaning 4/12 — ink facts, box flags and the glyph fill, frozen against cleaner.py #167

Merged
bjoern merged 18 commits from feat/cleaning-ink-and-fill into main 2026-10-05 16:55:42 +02:00
Member

This is slice 4 of Phase 5 in PROJECT_PLAN.md: the deterministic half of cleaning from ADR 0027, built on slice 3's raster layer. It covers each region's ink facts and box flags, and the glyph fill with its gate and guards. It also adds the grey rule and the untagged encoder for what goes to the edit model. Everything is a pure read: nothing here writes a page, and nothing calls these ports until the stage arrives (slices 7 and 8).

What's in

UseCases ports, beside the other pixel ports:

  • IRegionInkAnalyzer:
    • AnalyzeAsync returns each region's InkFacts: T (the box in page pixels, by the rounding every view uses), the lettering's own box, the box flags, a suggested box, and the closed balloon's paper and interior.
    • FillAsync returns the fill's would-be pixels over T + 6 as an untagged PNG, with a FillReport giving the gate's paper, flat std, ink left, residue and typed refusals. A refused fill is shown too, because the agent may accept one after looking.
  • ICleaningImages: the grey rule.
    • A page is grey when its mean chroma is below 1.
    • A grey page's window goes up as L (Pillow's luma after Lanczos to the canvas), unless its grown rects hold a colour area. That is the server's own keep_grey test: chroma above 40 on at least max(64 px, 0.2 %).
    • A grey page's raw becomes L except where its chroma is above 40.
    • Every image is an untagged 8-bit PNG, with no iCCP, sRGB, gAMA or cHRM chunk.
  • CleaningRecipe holds every constant and rides in every call, so the adapters only do arithmetic.

Infrastructure: RasterInkAnalyzer and RasterCleaningImages, ports of the lab's cleaner.py on the managed raster layer, from the canonical decode.

  • The box flags. cleaner.py's flags keep its wording: ink past the box, ink touching the border, tiny ink, no ink found, grey ink, outline ring ignored. ADR 0027 adds four checks the rehearsal asked for: a duplicate box, a box over a neighbour's, an oversized bubble box, and an outline inside the box.
  • The suggested box stops at every neighbour's box.
  • The fill's gate is cleaner.py's, with its refusals: no glyph ink, a component spanning the box, blobs left in a closed balloon. ADR 0027 adds two departures:
    • the fill paints with the paper its gate measures, not the median of a ring outside T. This mends the rehearsal's tiny balloon;
    • an undershoot guard refuses a fill that leaves glyph ink within 8 px outside T, with other regions' T + 3 cut out.
  • The raster layer gains numpy's pairwise sum and std, Python's round(x, digits), and the lab's box and mask helpers. The lab's gate rounds a grey std to one decimal before comparing it, so these are needed for parity.

Tests

1,955 green and 1 skipped, against 1,676 on main. Integration has 873 (+279), and the skipped test is the opt-in corpus test below. Domain 132, UseCases 671 and BlazorAdapter 279 are unchanged. (1,953 at the first review; +2 in the review round.) Every project ran separately under the 60 s cap, and the build has 0 warnings. What they pin:

  • Oracle parity. Cleaning/oracle/gen_cleaning_oracle.py imports the lab's own cleaner.py and freezes its outputs on 80 drawn pages (ink.json), plus grey.json and numbers.json. The two departures are written beside the lab code in the generator. A rerun reproduces all three files byte for byte.
  • Thresholds. Thirty-six of the drawn pages sit exactly on one of the lab's limits, so moving a limit by a step changes the answer. The constants that survived mutation each gained a page here.
  • Every recipe field is read. Each field the adapters use is exercised through a non-default recipe, at every site that reads it.
  • Drawn fill cases:
    • the tiny balloon painted with its gate's paper; it fails under cleaner.py's ring paper;
    • a glyph piece just outside T, refused;
    • ink inside a neighbour's T + 3, ignored;
    • bars beside T on each side, which enclose nothing;
    • the fill's soft fringe;
    • a neighbour past the corner, through both the guard and the blob check.
  • The suggested box: each side held off a neighbour; and a neighbour off a corner over two growths, where the top or bottom is pulled back before the side.
  • The grey rule: the Pillow pipeline frozen in grey.json; the colour area at exactly its floor and share; rects beside the window. The encoder's chunk list is read back and compared with a tagged PNG.
  • An opt-in corpus test, skipped unless ORIHON_CLEANLAB_E4 names an export from Cleaning/oracle/export_e4_corpus.py. No scan pixels are committed. Run on the lab's 150 e4 bubbles, with each page's other bubbles as neighbours:
    • 147 verdicts equal the lab's record. The other three flip from refused to passed because of the gate's paper, and the test names them: rj-p22 r2 and r3, and the rehearsal's sc-133705 r3;
    • the flat std and the paper match on all 150;
    • the ink left and the residue match wherever cleaner.py's ring paper equals the gate's paper.

Browser-verified

Nothing to verify in a browser: this slice has no UI, no seed change and no caller.

Honest notes

  • No caller yet. Both ports are registered, and a test checks that they resolve. The stage that calls them arrives in slices 7 and 8.
  • sc-133705 c001. The plan asks for a unit test that freezes it. A scan can't be committed, so a drawn tiny balloon of the same shape stands in for it: 4 px of paper, a 2-px outline, then grey art. The real page runs in the opt-in corpus test, where sc-133705 r3 is one of the three flips.
  • The four new flags' thresholds are not lab-measured: IoU 0.9 for a duplicate, 2× for oversize, 10 px for an outline inside the box. They live in the recipe, and a flag only makes the survey look at its region closely.
  • ink.json is 1.17 MB. It is a committed oracle, regenerated byte for byte by its generator.
  • Merge order. Slice 10, the call runner (opening next), registers its pixel digest on the same line of DependencyInjection.cs. Whichever lands second needs a one-line rebase, which I'll do. I'll probe the two branches together once slice 10 is ready and post the result here.

🤖 Generated with Claude Code

This is slice 4 of Phase 5 in `PROJECT_PLAN.md`: the deterministic half of cleaning from ADR 0027, built on slice 3's raster layer. It covers each region's ink facts and box flags, and the glyph fill with its gate and guards. It also adds the grey rule and the untagged encoder for what goes to the edit model. Everything is a pure read: nothing here writes a page, and nothing calls these ports until the stage arrives (slices 7 and 8). ## What's in **UseCases ports**, beside the other pixel ports: - **`IRegionInkAnalyzer`:** - `AnalyzeAsync` returns each region's `InkFacts`: T (the box in page pixels, by the rounding every view uses), the lettering's own box, the box flags, a suggested box, and the closed balloon's paper and interior. - `FillAsync` returns the fill's would-be pixels over T + 6 as an untagged PNG, with a `FillReport` giving the gate's paper, flat std, ink left, residue and typed refusals. A refused fill is shown too, because the agent may accept one after looking. - **`ICleaningImages`:** the grey rule. - A page is grey when its mean chroma is below 1. - A grey page's window goes up as L (Pillow's luma after Lanczos to the canvas), unless its grown rects hold a colour area. That is the server's own `keep_grey` test: chroma above 40 on at least max(64 px, 0.2 %). - A grey page's raw becomes L except where its chroma is above 40. - Every image is an untagged 8-bit PNG, with no iCCP, sRGB, gAMA or cHRM chunk. - **`CleaningRecipe`** holds every constant and rides in every call, so the adapters only do arithmetic. **Infrastructure: `RasterInkAnalyzer` and `RasterCleaningImages`**, ports of the lab's `cleaner.py` on the managed raster layer, from the canonical decode. - **The box flags.** cleaner.py's flags keep its wording: ink past the box, ink touching the border, tiny ink, no ink found, grey ink, outline ring ignored. ADR 0027 adds four checks the rehearsal asked for: a duplicate box, a box over a neighbour's, an oversized bubble box, and an outline inside the box. - **The suggested box** stops at every neighbour's box. - **The fill's gate** is cleaner.py's, with its refusals: no glyph ink, a component spanning the box, blobs left in a closed balloon. ADR 0027 adds two departures: - the fill paints with the paper its gate measures, not the median of a ring outside T. This mends the rehearsal's tiny balloon; - an **undershoot guard** refuses a fill that leaves glyph ink within 8 px outside T, with other regions' T + 3 cut out. - **The raster layer** gains numpy's pairwise sum and std, Python's `round(x, digits)`, and the lab's box and mask helpers. The lab's gate rounds a grey std to one decimal before comparing it, so these are needed for parity. ## Tests 1,955 green and 1 skipped, against 1,676 on main. Integration has 873 (+279), and the skipped test is the opt-in corpus test below. Domain 132, UseCases 671 and BlazorAdapter 279 are unchanged. (1,953 at the first review; +2 in the review round.) Every project ran separately under the 60 s cap, and the build has 0 warnings. What they pin: - **Oracle parity.** `Cleaning/oracle/gen_cleaning_oracle.py` imports the lab's own `cleaner.py` and freezes its outputs on 80 drawn pages (`ink.json`), plus `grey.json` and `numbers.json`. The two departures are written beside the lab code in the generator. A rerun reproduces all three files byte for byte. - **Thresholds.** Thirty-six of the drawn pages sit exactly on one of the lab's limits, so moving a limit by a step changes the answer. The constants that survived mutation each gained a page here. - **Every recipe field is read.** Each field the adapters use is exercised through a non-default recipe, at every site that reads it. - **Drawn fill cases:** - the tiny balloon painted with its gate's paper; it fails under cleaner.py's ring paper; - a glyph piece just outside T, refused; - ink inside a neighbour's T + 3, ignored; - bars beside T on each side, which enclose nothing; - the fill's soft fringe; - a neighbour past the corner, through both the guard and the blob check. - **The suggested box:** each side held off a neighbour; and a neighbour off a corner over two growths, where the top or bottom is pulled back before the side. - **The grey rule:** the Pillow pipeline frozen in `grey.json`; the colour area at exactly its floor and share; rects beside the window. The encoder's chunk list is read back and compared with a tagged PNG. - **An opt-in corpus test**, skipped unless `ORIHON_CLEANLAB_E4` names an export from `Cleaning/oracle/export_e4_corpus.py`. No scan pixels are committed. Run on the lab's 150 e4 bubbles, with each page's other bubbles as neighbours: - 147 verdicts equal the lab's record. The other three flip from refused to passed because of the gate's paper, and the test names them: rj-p22 r2 and r3, and the rehearsal's sc-133705 r3; - the flat std and the paper match on all 150; - the ink left and the residue match wherever cleaner.py's ring paper equals the gate's paper. ## Browser-verified Nothing to verify in a browser: this slice has no UI, no seed change and no caller. ## Honest notes - **No caller yet.** Both ports are registered, and a test checks that they resolve. The stage that calls them arrives in slices 7 and 8. - **sc-133705 c001.** The plan asks for a unit test that freezes it. A scan can't be committed, so a drawn tiny balloon of the same shape stands in for it: 4 px of paper, a 2-px outline, then grey art. The real page runs in the opt-in corpus test, where sc-133705 r3 is one of the three flips. - **The four new flags' thresholds are not lab-measured:** IoU 0.9 for a duplicate, 2× for oversize, 10 px for an outline inside the box. They live in the recipe, and a flag only makes the survey look at its region closely. - **`ink.json` is 1.17 MB.** It is a committed oracle, regenerated byte for byte by its generator. - **Merge order.** Slice 10, the call runner (opening next), registers its pixel digest on the same line of `DependencyInjection.cs`. Whichever lands second needs a one-line rebase, which I'll do. I'll probe the two branches together once slice 10 is ready and post the result here. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The cleaning ports the lab's gate, which rounds a grey std to one decimal
before it compares it, so the layer gains numpy's pairwise sum (moved out of
the Gaussian kernel), its std, and Python's round to digits. PixelBox gains
the lab's grow, clip, inter, union and area; Mask gains box_mask and the
boolean operations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
IRegionInkAnalyzer, beside the other pixel ports, takes the stored page and
the regions' boxes and answers with UseCases DTOs; CleaningRecipe holds the
recipe's constants and rides in every call. RasterInkAnalyzer ports
cleaner.py on the managed raster layer, from the canonical decode:

- T is each region's box by the rounding every view uses;
- the lettering's box, the lab's flags and suggestion (derive_ink), and the
  closed balloon's paper and interior (balloon);
- the checks the rehearsal asked for: a box twice, a box over a neighbour's,
  an oversized bubble box, an outline inside a bubble's box; and a
  suggestion that stops at every neighbour's box;
- the glyph fill with its gate (flat paper, ink left, residue), the lab's
  refusals (no glyph, a component spanning the box, blobs left in a closed
  balloon), and its would-be pixels over T + 6 as an untagged PNG.

Two departures from cleaner.py: the fill paints with the paper its gate
measures, not the median of a ring outside T, which mends the rehearsal's
tiny balloon; and an undershoot guard refuses a fill that leaves glyph ink
within 8 px outside T, other regions' T + 3 cut out.

Cleaning/oracle/gen_cleaning_oracle.py imports the lab's cleaner.py and
freezes its outputs on 38 drawn pages, with the departures written beside
it; a rerun reproduces the files byte for byte.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ICleaningImages answers what cleaning trades with the edit model, every image
an untagged 8-bit PNG (no iCCP, sRGB, gAMA or cHRM chunk):

- a page is grey when its mean chroma is below 1, read once from the page;
- a grey page's window goes up as L (Pillow's luma after Lanczos to the
  canvas), unless its grown rects (each model rect + 20 px) hold a colour
  area, chroma above 40 on at least max(64 px, 0.2 %), the server's own
  keep_grey test; then it goes as RGB, as every colour page's does;
- a grey page's raw becomes L except where its chroma is above 40; a colour
  page's raw keeps its pixels.

The Pillow pipeline is frozen in the generator's grey.json; the encoder's
chunk list is read back in a test, beside a tagged PNG that shows the
reader finds a colour chunk where there is one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Cleaning/oracle/export_e4_corpus.py writes the lab's 150 e4 bubbles where
the test reads them: the pages as Pillow decoded them, the lab's derived T,
and the gate results e4 recorded. The scans are not committed; the test
runs only where ORIHON_CLEANLAB_E4 names the export.

Every verdict matches the record but three, which the gate's paper turns
from refused to passed: the bubbles whose ring outside T is art, among them
the rehearsal's sc-133705 r3. The flatness and the paper match on all 150,
and where cleaner.py's ring paper is the gate's paper, the ink left and the
residue match too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drawn pages carry no anti-aliasing, so a fringed page freezes the residue
the fill leaves when it takes the fringe along. A neighbour off the box's
corner holds off only the side it meets, and the outline flag fires at
exactly its pixel count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The oracle gains pages for a box one pixel off its lettering, a stroke half in
a larger neighbour's box, a speck and a blob just inside an outline, an
outline beside a glyph, a ring that spans a 20-px padded box, and sums whose
order matters at numpy's 128-element block. The paper tests pin the
dominant colour's limit and truncation, a closed component on each edge,
and the seed's middle choosing the component; the colour test, its chroma
limit and its share over the whole window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The stroke half in a neighbour's box now sits 9 px from the lettering, so
the rule that brings back a component continuing the text cannot hide the
share threshold. numpy's sum is frozen directly on values spanning sixteen
decades: a std barely moves with its mean's last bit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mask.Box sliced past the end of its bits for a box wholly right of the
raster that reached its last row, so the undershoot guard, the balloon's
blob check and the grey rule's colour test threw for an ordinary
neighbour lower and to the right. The opt-in corpus test now hands each
bubble its page's other bubbles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bubble's paper is the median of the pixels near the box's commonest
colour, which no pixel need be within the paper level of; the derivation
assumed one always was and threw. It now answers no ink found, as
cleaner.py does when it finds no paper component. Both paper-level sites
are pinned through a non-default recipe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A neighbour over T itself on each side the lettering spills past leaves
nothing to suggest; one above or below T beside a narrower suggestion
leaves its growth alone; boxes sharing exactly 0.9 are one box twice.
The box checks' summary says what they do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each side of the undershoot guard's enclosure test is pinned by a bar
that runs past T lengthwise but not across it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Thirty-six drawn pages, mostly on flat paper, sit each on one of the lab's
limits so that moving it by a step changes what cleaner.py and the port
answer: tiny ink by its short side alone, by its share alone and at both
edges; a balloon outline dropped as a ring only when sparse (a dense frame
and one exactly a quarter full stay), 2 px clear on every side and with
two others to enclose; floating strokes at grey 100 and 200, a 3-px poke
of 12 pixels; the foreign share at exactly a half and at exactly a fifth
past the bubble's own, and boxes of one size; faint lettering widening by
exactly 1.3, reaching exactly 4 and 5 px past the box, and pieces of 12
and 11 px; dark pieces of 4 and 3 px; the near band, the search's edge and
the core's erosion each at their step; a continuation at 8 px below and
right and none at 9; a glyph spanning exactly 0.9, a fill writing 9 and
10 pixels, residue 2 and 3 px off an outline, the paper ring just outside
the gate's region, a blob 4 px in, the balloon's seed and its cover at
exactly 98 %.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fill's pad (the padded box, the blob check's own exclusion, the
guard's erased band), the ink level at each of its eight sites (the gate's
paper, its flatness, the fill's glyphs, the ink left, the blobs, the
guard, the faint pass and its two lookups, the outline check), the text
level and its lookup, the blob check's exclusion pad, and the grey rule's
colour chroma, pixel floor and share, each on the step where the recipe's
value decides. The colour area's floor and share are pinned at exactly
their values, as is a blob of exactly five pixels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fix(raster): Python's rounding at no digits too, for the reason it holds
All checks were successful
CI / build (pull_request) Successful in 31s
CI / test (pull_request) Successful in 1m5s
4c5a23048d
.NET's fixed-point format rounds a double's exact value with exact ties to
even, as Python's round does, at no digits as at more; the comment and the
guard claimed otherwise. Only negative digits, which Python takes as tens,
are refused now, and the oracle freezes exact ties at 0, 1, 2 and 4
digits.

Co-Authored-By: Claude Opus 5.5 <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: df14dae · Generated: 2026-10-05 14:53:26 UTC · Revision: #2

Summary

Summary
Generated on: 10/05/2026 - 14:53:26
Coverage date: 10/05/2026 - 14:52:56 - 10/05/2026 - 14:53:22
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 608
Files: 285
Line coverage: 97.2% (24382 of 25073)
Covered lines: 24382
Uncovered lines: 691
Coverable lines: 25073
Total lines: 43494
Branch coverage: 86.4% (4687 of 5421)
Covered branches: 4687
Total branches: 5421
Method coverage: Feature is only available for sponsors

Coverage

Orihon.BlazorAdapter - 95.7%
Name Line Branch
Orihon.BlazorAdapter 95.7% 88.7%
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.5%
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.PageWorkspace.CreateRegionRequested 100%
Orihon.BlazorAdapter.PageWorkspace.DeletePageSummaryRequested 100%
Orihon.BlazorAdapter.PageWorkspace.DeleteRegionRequested 100%
Orihon.BlazorAdapter.PageWorkspace.LoadPageWorkspace 100%
Orihon.BlazorAdapter.PageWorkspace.PageStepsLoaded 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 93.6% 87.6%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceReducers 100% 64.2%
Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceState 100%
Orihon.BlazorAdapter.PageWorkspace.PageWriteFailed 100%
Orihon.BlazorAdapter.PageWorkspace.RegionColorsSampled 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.SampleRegionColorsRequested 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.6%
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% 94.6%
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.AgentRoutingPicked 100%
Orihon.BlazorAdapter.Settings.AgentRoutingSaved 100%
Orihon.BlazorAdapter.Settings.AgentRoutingSaveFailed 0%
Orihon.BlazorAdapter.Settings.AgentTranscriptsLoaded 100%
Orihon.BlazorAdapter.Settings.AgentTranscriptsLoadFailed 0%
Orihon.BlazorAdapter.Settings.CleaningServerChecked 100%
Orihon.BlazorAdapter.Settings.CleaningServerSaved 100%
Orihon.BlazorAdapter.Settings.CleaningServerSaveFailed 100%
Orihon.BlazorAdapter.Settings.EffortOption 100% 100%
Orihon.BlazorAdapter.Settings.FloatingPassToggled 100%
Orihon.BlazorAdapter.Settings.KeySaved 100%
Orihon.BlazorAdapter.Settings.KeySaveFailed 100%
Orihon.BlazorAdapter.Settings.ModelOptionsLoaded 100%
Orihon.BlazorAdapter.Settings.ModelOptionsUnavailable 100%
Orihon.BlazorAdapter.Settings.RoutingOption 100% 100%
Orihon.BlazorAdapter.Settings.RunConcurrencyPicked 100%
Orihon.BlazorAdapter.Settings.RunConcurrencySaveFailed 100%
Orihon.BlazorAdapter.Settings.SaveCleaningServerRequested 100%
Orihon.BlazorAdapter.Settings.SaveKeyRequested 100%
Orihon.BlazorAdapter.Settings.SettingsEffects 91.4% 81%
Orihon.BlazorAdapter.Settings.SettingsLoaded 100%
Orihon.BlazorAdapter.Settings.SettingsPage 97.5% 90.6%
Orihon.BlazorAdapter.Settings.SettingsReducers 95.7% 64.2%
Orihon.BlazorAdapter.Settings.SettingsState 100%
Orihon.BlazorAdapter.Settings.TranscriptFilterPicked 100%
Orihon.BlazorAdapter.Settings.TranscriptPagePicked 100%
Orihon.BlazorAdapter.Settings.TranscriptPicked 100%
Orihon.BlazorAdapter.Settings.TranscriptTextLoaded 100%
Orihon.BlazorAdapter.Settings.TranscriptTextLoadFailed 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.FloatingPassAnswered 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.7% 87.9%
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.RunFloatingPassRequested 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% 100%
Orihon.Domain.Translation.Chapter 100%
Orihon.Domain.Translation.InkColor 100% 100%
Orihon.Domain.Translation.Page 100%
Orihon.Domain.Translation.Region 100% 100%
Orihon.Domain.Translation.RegionInk 100% 100%
Orihon.Domain.Translation.RegionProfile 100%
Orihon.Infrastructure - 97.3%
Name Line Branch
Orihon.Infrastructure 97.3% 82.9%
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 95.6% 89%
Orihon.Infrastructure.Gateways.Cleaning.BoxChecks 100% 100%
Orihon.Infrastructure.Gateways.Cleaning.DerivedInk 100%
Orihon.Infrastructure.Gateways.Cleaning.FillResult 100%
Orihon.Infrastructure.Gateways.Cleaning.GateStats 100%
Orihon.Infrastructure.Gateways.Cleaning.GreyRule 100% 100%
Orihon.Infrastructure.Gateways.Cleaning.LabFill 100% 100%
Orihon.Infrastructure.Gateways.Cleaning.LabInk 100% 98.3%
Orihon.Infrastructure.Gateways.Cleaning.LabPaper 100% 97.3%
Orihon.Infrastructure.Gateways.Cleaning.PaperComponent 100%
Orihon.Infrastructure.Gateways.Cleaning.RasterCleaningImages 100% 100%
Orihon.Infrastructure.Gateways.Cleaning.RasterInkAnalyzer 100% 100%
Orihon.Infrastructure.Gateways.Cleaning.Rgb 100%
Orihon.Infrastructure.Gateways.FileSystemAgentTranscriptStore 85.2% 80.8%
Orihon.Infrastructure.Gateways.HttpWebPageFetcher 95.1% 83.3%
Orihon.Infrastructure.Gateways.LabelFont 100% 50%
Orihon.Infrastructure.Gateways.OpenRouterLlmGateway 90.2% 82.1%
Orihon.Infrastructure.Gateways.QwenImageServerGateway 95.1% 89.3%
Orihon.Infrastructure.Gateways.QwenImageServerJson 95.9% 72.3%
Orihon.Infrastructure.Gateways.Raster.FloatImage 66.6% 50%
Orihon.Infrastructure.Gateways.Raster.GrayImage 87.5% 75%
Orihon.Infrastructure.Gateways.Raster.Labels 100% 100%
Orihon.Infrastructure.Gateways.Raster.Mask 95.6% 92.6%
Orihon.Infrastructure.Gateways.Raster.NumpyMath 93.9% 93.4%
Orihon.Infrastructure.Gateways.Raster.PillowBlur 98.4% 89.4%
Orihon.Infrastructure.Gateways.Raster.PillowLanczos 100% 100%
Orihon.Infrastructure.Gateways.Raster.PixelBox 100% 100%
Orihon.Infrastructure.Gateways.Raster.RgbImage 96.4% 75%
Orihon.Infrastructure.Gateways.Raster.ScipyGaussian 100% 100%
Orihon.Infrastructure.Gateways.SkiaImages 97.2% 96.4%
Orihon.Infrastructure.Gateways.SkiaPageImageRenderer 97.4% 90.8%
Orihon.Infrastructure.Gateways.SkiaRegionColorSampler 100% 100%
Orihon.Infrastructure.Gateways.UntaggedPng 100% 100%
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.AddPagePassFacts 99%
Orihon.Infrastructure.Persistence.Migrations.AddProjectSourceLanguage 99.3%
Orihon.Infrastructure.Persistence.Migrations.AddRegionFitBoxDropFillHints 98.1%
Orihon.Infrastructure.Persistence.Migrations.AddRegionForm 99.4%
Orihon.Infrastructure.Persistence.Migrations.AddRegionInk 99.4%
Orihon.Infrastructure.Persistence.Migrations.AddRuns 99.1%
Orihon.Infrastructure.Persistence.Migrations.AddStoryOverview 99.5%
Orihon.Infrastructure.Persistence.Migrations.DropRegionContainer 99.1%
Orihon.Infrastructure.Persistence.Migrations.DropRegionType 99%
Orihon.Infrastructure.Persistence.Migrations.InitialTranslationDomain 97.3%
Orihon.Infrastructure.Persistence.Migrations.OrihonDbContextModelSnapshot 100%
Orihon.Infrastructure.Persistence.Migrations.RenameSourceTargetColumns 97.2%
Orihon.Infrastructure.Persistence.Migrations.ReplaceFitBoxWithContainerSeed 99.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.2% 75%
Orihon.Infrastructure.Settings.EfAppSettingsStore 100% 100%
Orihon.Infrastructure.Translation.EfChapterStore 100% 100%
Orihon.Infrastructure.Translation.EfPageStore 98.3% 93.7%
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 - 94.4%
Name Line Branch
Orihon.Server 94.4% 77.5%
Orihon.Server.Components.App 100%
Orihon.Server.Components.Layout.MainLayout 100%
Orihon.Server.Components.Pages.Gate 64.2% 66.6%
Orihon.Server.Diagnostics.FakeCleaningServer 94.3% 78.4%
Orihon.Server.RunEngineBootstrap 100%
Orihon.Server.Security.AccessGate 91.8% 41.6%
Orihon.Server.Security.AccessSecret 100% 50%
Orihon.Server.VolumeStartupValidator 100% 100%
Program 95.7% 85.7%
Orihon.UseCases - 97.6%
Name Line Branch
Orihon.UseCases 97.6% 89.5%
Orihon.UseCases.Agents.AgentAttemptPreparation 100%
Orihon.UseCases.Agents.AgentAttemptSupport 98.6% 98.3%
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.AddFloatingRegionParams 100%
Orihon.UseCases.Agents.Annotation.AddFloatingRegionTool 95.8% 75%
Orihon.UseCases.Agents.Annotation.AddRegionParams 100%
Orihon.UseCases.Agents.Annotation.AddRegionTool 95.4% 75%
Orihon.UseCases.Agents.Annotation.AnnotationBlueprints 100%
Orihon.UseCases.Agents.Annotation.AnnotationStage 100% 86.1%
Orihon.UseCases.Agents.Annotation.BboxCreationExecutor 90.4% 50%
Orihon.UseCases.Agents.Annotation.BboxRefinementExecutor 96.5% 90%
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 93.1% 80%
Orihon.UseCases.Agents.Annotation.BoundViewParams 100%
Orihon.UseCases.Agents.Annotation.ClassifyRegionParams 100%
Orihon.UseCases.Agents.Annotation.ClassifyRegionTool 100% 100%
Orihon.UseCases.Agents.Annotation.ColorReading 100% 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.FloatingCreationExecutor 86.9% 50%
Orihon.UseCases.Agents.Annotation.FloatingQaExecutor 91.8% 78.5%
Orihon.UseCases.Agents.Annotation.FloatingTranscriptionExecutor 95.4% 75%
Orihon.UseCases.Agents.Annotation.ListRegionsTool 93.7% 80.7%
Orihon.UseCases.Agents.Annotation.MoveResizeBoundTool 90.9% 50%
Orihon.UseCases.Agents.Annotation.MoveResizeRegionParams 100%
Orihon.UseCases.Agents.Annotation.MoveResizeRegionTool 95.8% 83.3%
Orihon.UseCases.Agents.Annotation.NoteRegionParams 100%
Orihon.UseCases.Agents.Annotation.NoteRegionTool 100% 100%
Orihon.UseCases.Agents.Annotation.PageQaExecutor 92.5% 79.1%
Orihon.UseCases.Agents.Annotation.QaReportSink 100% 100%
Orihon.UseCases.Agents.Annotation.RegionAuthoringAccess 89.4% 62.5%
Orihon.UseCases.Agents.Annotation.RegionBriefing 100% 96.1%
Orihon.UseCases.Agents.Annotation.RegionCropParams 100%
Orihon.UseCases.Agents.Annotation.RegionCropTool 100% 100%
Orihon.UseCases.Agents.Annotation.RegionProblemParams 100%
Orihon.UseCases.Agents.Annotation.RegionWindow 100% 100%
Orihon.UseCases.Agents.Annotation.RejectRegionParams 100%
Orihon.UseCases.Agents.Annotation.RejectRegionTool 100% 100%
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.8% 90%
Orihon.UseCases.Agents.Annotation.SampleColorsParams 100%
Orihon.UseCases.Agents.Annotation.SampleColorsTool 100% 100%
Orihon.UseCases.Agents.Annotation.SampleRegionColorsParams 100%
Orihon.UseCases.Agents.Annotation.SampleRegionColorsTool 100% 100%
Orihon.UseCases.Agents.Annotation.SetInkParams 100%
Orihon.UseCases.Agents.Annotation.SetInkTool 100% 100%
Orihon.UseCases.Agents.Annotation.SetPageMetaParams 100%
Orihon.UseCases.Agents.Annotation.SetPageMetaTool 100% 75%
Orihon.UseCases.Agents.Annotation.SetRegionInkParams 100%
Orihon.UseCases.Agents.Annotation.SetRegionInkTool 100% 100%
Orihon.UseCases.Agents.Annotation.SetTranscriptionParams 100%
Orihon.UseCases.Agents.Annotation.SetTranscriptionTool 100% 100%
Orihon.UseCases.Agents.Annotation.TranscriptionExecutor 97.7% 94.4%
Orihon.UseCases.Agents.AssistantSpoke 100%
Orihon.UseCases.Agents.BibleBuilding.BibleBuildingBlueprint 100%
Orihon.UseCases.Agents.BibleBuilding.BibleBuildingExecutor 96.9% 75%
Orihon.UseCases.Agents.BibleBuilding.GetRegionParams 100%
Orihon.UseCases.Agents.BibleBuilding.GetRegionTool 84.6% 70%
Orihon.UseCases.Agents.BibleBuilding.ListProjectRegionsTool 86.3% 83.3%
Orihon.UseCases.Agents.BibleBuilding.ListRegionsParams 100%
Orihon.UseCases.Agents.Inspection.PageImageAccess 95.2% 80.6%
Orihon.UseCases.Agents.Inspection.ViewAccount 100% 100%
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 87% 66.6%
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 95.8% 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.TranscriptLabel 100% 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.8% 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.Cleaning.CleaningRecipe 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.FakeCleaningServerAddress 100%
Orihon.UseCases.Diagnostics.SeedDevData 99.2% 82.1%
Orihon.UseCases.Gateways.BoxFlag 100%
Orihon.UseCases.Gateways.ClosedBalloon 100%
Orihon.UseCases.Gateways.ColorShare 100%
Orihon.UseCases.Gateways.EditBackendError 100%
Orihon.UseCases.Gateways.EditBackendIdentity 100%
Orihon.UseCases.Gateways.EditJob 100%
Orihon.UseCases.Gateways.EditJobAccepted 100%
Orihon.UseCases.Gateways.EditJobRejected 100%
Orihon.UseCases.Gateways.EditJobRequest 100%
Orihon.UseCases.Gateways.EditJobRun 100%
Orihon.UseCases.Gateways.EditModels 100%
Orihon.UseCases.Gateways.EditModelWeight 100%
Orihon.UseCases.Gateways.EditOutputImage 100%
Orihon.UseCases.Gateways.EditOutputWithheld 100%
Orihon.UseCases.Gateways.EditRect 100%
Orihon.UseCases.Gateways.EditRunOutput 100%
Orihon.UseCases.Gateways.EditServerAnswered`1 100%
Orihon.UseCases.Gateways.EditServerBuild 100%
Orihon.UseCases.Gateways.EditServerHealth 100%
Orihon.UseCases.Gateways.EditServerSilent`1 100%
Orihon.UseCases.Gateways.FillRefusal 100%
Orihon.UseCases.Gateways.FillReport 100%
Orihon.UseCases.Gateways.GlyphFill 100%
Orihon.UseCases.Gateways.GridAxis 100%
Orihon.UseCases.Gateways.GridSteps 100%
Orihon.UseCases.Gateways.InkFacts 100%
Orihon.UseCases.Gateways.InkRegion 100%
Orihon.UseCases.Gateways.LabeledBox 100%
Orihon.UseCases.Gateways.LlmKeyInfo 100%
Orihon.UseCases.Gateways.LlmModel 100%
Orihon.UseCases.Gateways.LlmReasoning 100% 100%
Orihon.UseCases.Gateways.PageTone 100%
Orihon.UseCases.Gateways.PaperColor 100%
Orihon.UseCases.Gateways.PixelMask 100%
Orihon.UseCases.Gateways.PixelRect 100%
Orihon.UseCases.Gateways.PixelWindow 100%
Orihon.UseCases.Gateways.RenderedView 100%
Orihon.UseCases.Gateways.StoredTranscript 100%
Orihon.UseCases.Gateways.StoredTranscriptPage 100%
Orihon.UseCases.Gateways.TranscriptHeader 97.3% 90.9%
Orihon.UseCases.Gateways.TranscriptListingFacets 100%
Orihon.UseCases.Gateways.TranscriptSummary 100%
Orihon.UseCases.Gateways.WindowUpload 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.GetPageSteps 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.MarkPagePasses 100% 50%
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.PageStepsDto 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.FloatingPassAnswer 100%
Orihon.UseCases.Projects.GetProject 100% 100%
Orihon.UseCases.Projects.ListProjects 100%
Orihon.UseCases.Projects.PageMention 100%
Orihon.UseCases.Projects.ProjectDto 96.1%
Orihon.UseCases.Projects.StartAnnotationRun 96.5% 92.8%
Orihon.UseCases.Projects.StartBibleRun 92.3% 83.3%
Orihon.UseCases.Projects.StartFloatingPassRun 100% 100%
Orihon.UseCases.Projects.StartSetupRun 100% 100%
Orihon.UseCases.Projects.StartTranslationRun 92.3% 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 96.8%
Orihon.UseCases.Regions.ReorderRegions 100%
Orihon.UseCases.Regions.SampleRegionColors 100% 50%
Orihon.UseCases.Regions.UpdateRegion 100% 100%
Orihon.UseCases.Runs.AnnotationPipeline 100% 100%
Orihon.UseCases.Runs.AttemptLedger 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.ExecutionSendBack 100%
Orihon.UseCases.Runs.PlannedExecution 100%
Orihon.UseCases.Runs.PulseTarget 100%
Orihon.UseCases.Runs.ReprocessPage 97% 95.8%
Orihon.UseCases.Runs.ReprocessTranslation 88.8% 83.3%
Orihon.UseCases.Runs.RunDto 93.3% 90%
Orihon.UseCases.Runs.RunEngine 95.8% 94%
Orihon.UseCases.Runs.RunEngineOptions 100% 100%
Orihon.UseCases.Runs.RunPhase 94.1% 100%
Orihon.UseCases.Runs.RunStart 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.CheckCleaningServer 87.5% 60%
Orihon.UseCases.Settings.CleaningServerSetting 100% 100%
Orihon.UseCases.Settings.CleaningServerStatusDto 100% 100%
Orihon.UseCases.Settings.ConcurrencySetting 100% 100%
Orihon.UseCases.Settings.EffortSetting 100% 100%
Orihon.UseCases.Settings.GetSettings 100% 100%
Orihon.UseCases.Settings.ListModelOptions 100% 100%
Orihon.UseCases.Settings.RoutingSetting 100% 100%
Orihon.UseCases.Settings.SaveAgentEffort 100% 100%
Orihon.UseCases.Settings.SaveAgentModel 100% 100%
Orihon.UseCases.Settings.SaveAgentRouting 100% 100%
Orihon.UseCases.Settings.SaveCleaningServer 95.2% 85.7%
Orihon.UseCases.Settings.SaveFloatingPass 100% 100%
Orihon.UseCases.Settings.SaveOpenRouterKey 100% 100%
Orihon.UseCases.Settings.SaveRunConcurrency 100% 100%
Orihon.UseCases.Settings.SettingKeys 100% 100%
Orihon.UseCases.Settings.SettingsDto 100% 100%
Orihon.UseCases.Transcripts.AgentTranscriptDto 100%
Orihon.UseCases.Transcripts.AgentTranscriptListDto 100%
Orihon.UseCases.Transcripts.AgentTranscriptPageDto 100%
Orihon.UseCases.Transcripts.AgentTranscriptTextDto 100%
Orihon.UseCases.Transcripts.ClearAgentTranscripts 100% 100%
Orihon.UseCases.Transcripts.ListAgentTranscripts 100% 100%
Orihon.UseCases.Transcripts.ReadAgentTranscript 100% 100%
<!-- coverage-comment --> > 🔄 **Auto-updating coverage report** — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip. > > **Commit:** `df14dae` · **Generated:** 2026-10-05 14:53:26 UTC · **Revision:** #2 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 10/05/2026 - 14:53:26 | | Coverage date: | 10/05/2026 - 14:52:56 - 10/05/2026 - 14:53:22 | | Parser: | MultiReport (4x Cobertura) | | Assemblies: | 6 | | Classes: | 608 | | Files: | 285 | | **Line coverage:** | 97.2% (24382 of 25073) | | Covered lines: | 24382 | | Uncovered lines: | 691 | | Coverable lines: | 25073 | | Total lines: | 43494 | | **Branch coverage:** | 86.4% (4687 of 5421) | | Covered branches: | 4687 | | Total branches: | 5421 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Orihon.BlazorAdapter - 95.7%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.BlazorAdapter**|**95.7%**|**88.7%**| |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.5%| |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.PageWorkspace.CreateRegionRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.DeletePageSummaryRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.DeleteRegionRequested|100%|| |Orihon.BlazorAdapter.PageWorkspace.LoadPageWorkspace|100%|| |Orihon.BlazorAdapter.PageWorkspace.PageStepsLoaded|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|93.6%|87.6%| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceReducers|100%|64.2%| |Orihon.BlazorAdapter.PageWorkspace.PageWorkspaceState|100%|| |Orihon.BlazorAdapter.PageWorkspace.PageWriteFailed|100%|| |Orihon.BlazorAdapter.PageWorkspace.RegionColorsSampled|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.SampleRegionColorsRequested|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.6%| |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%|94.6%| |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.AgentRoutingPicked|100%|| |Orihon.BlazorAdapter.Settings.AgentRoutingSaved|100%|| |Orihon.BlazorAdapter.Settings.AgentRoutingSaveFailed|0%|| |Orihon.BlazorAdapter.Settings.AgentTranscriptsLoaded|100%|| |Orihon.BlazorAdapter.Settings.AgentTranscriptsLoadFailed|0%|| |Orihon.BlazorAdapter.Settings.CleaningServerChecked|100%|| |Orihon.BlazorAdapter.Settings.CleaningServerSaved|100%|| |Orihon.BlazorAdapter.Settings.CleaningServerSaveFailed|100%|| |Orihon.BlazorAdapter.Settings.EffortOption|100%|100%| |Orihon.BlazorAdapter.Settings.FloatingPassToggled|100%|| |Orihon.BlazorAdapter.Settings.KeySaved|100%|| |Orihon.BlazorAdapter.Settings.KeySaveFailed|100%|| |Orihon.BlazorAdapter.Settings.ModelOptionsLoaded|100%|| |Orihon.BlazorAdapter.Settings.ModelOptionsUnavailable|100%|| |Orihon.BlazorAdapter.Settings.RoutingOption|100%|100%| |Orihon.BlazorAdapter.Settings.RunConcurrencyPicked|100%|| |Orihon.BlazorAdapter.Settings.RunConcurrencySaveFailed|100%|| |Orihon.BlazorAdapter.Settings.SaveCleaningServerRequested|100%|| |Orihon.BlazorAdapter.Settings.SaveKeyRequested|100%|| |Orihon.BlazorAdapter.Settings.SettingsEffects|91.4%|81%| |Orihon.BlazorAdapter.Settings.SettingsLoaded|100%|| |Orihon.BlazorAdapter.Settings.SettingsPage|97.5%|90.6%| |Orihon.BlazorAdapter.Settings.SettingsReducers|95.7%|64.2%| |Orihon.BlazorAdapter.Settings.SettingsState|100%|| |Orihon.BlazorAdapter.Settings.TranscriptFilterPicked|100%|| |Orihon.BlazorAdapter.Settings.TranscriptPagePicked|100%|| |Orihon.BlazorAdapter.Settings.TranscriptPicked|100%|| |Orihon.BlazorAdapter.Settings.TranscriptTextLoaded|100%|| |Orihon.BlazorAdapter.Settings.TranscriptTextLoadFailed|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.FloatingPassAnswered|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.7%|87.9%| |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.RunFloatingPassRequested|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%|100%| |Orihon.Domain.Translation.Chapter|100%|| |Orihon.Domain.Translation.InkColor|100%|100%| |Orihon.Domain.Translation.Page|100%|| |Orihon.Domain.Translation.Region|100%|100%| |Orihon.Domain.Translation.RegionInk|100%|100%| |Orihon.Domain.Translation.RegionProfile|100%|| </details> <details><summary>Orihon.Infrastructure - 97.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Infrastructure**|**97.3%**|**82.9%**| |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|95.6%|89%| |Orihon.Infrastructure.Gateways.Cleaning.BoxChecks|100%|100%| |Orihon.Infrastructure.Gateways.Cleaning.DerivedInk|100%|| |Orihon.Infrastructure.Gateways.Cleaning.FillResult|100%|| |Orihon.Infrastructure.Gateways.Cleaning.GateStats|100%|| |Orihon.Infrastructure.Gateways.Cleaning.GreyRule|100%|100%| |Orihon.Infrastructure.Gateways.Cleaning.LabFill|100%|100%| |Orihon.Infrastructure.Gateways.Cleaning.LabInk|100%|98.3%| |Orihon.Infrastructure.Gateways.Cleaning.LabPaper|100%|97.3%| |Orihon.Infrastructure.Gateways.Cleaning.PaperComponent|100%|| |Orihon.Infrastructure.Gateways.Cleaning.RasterCleaningImages|100%|100%| |Orihon.Infrastructure.Gateways.Cleaning.RasterInkAnalyzer|100%|100%| |Orihon.Infrastructure.Gateways.Cleaning.Rgb|100%|| |Orihon.Infrastructure.Gateways.FileSystemAgentTranscriptStore|85.2%|80.8%| |Orihon.Infrastructure.Gateways.HttpWebPageFetcher|95.1%|83.3%| |Orihon.Infrastructure.Gateways.LabelFont|100%|50%| |Orihon.Infrastructure.Gateways.OpenRouterLlmGateway|90.2%|82.1%| |Orihon.Infrastructure.Gateways.QwenImageServerGateway|95.1%|89.3%| |Orihon.Infrastructure.Gateways.QwenImageServerJson|95.9%|72.3%| |Orihon.Infrastructure.Gateways.Raster.FloatImage|66.6%|50%| |Orihon.Infrastructure.Gateways.Raster.GrayImage|87.5%|75%| |Orihon.Infrastructure.Gateways.Raster.Labels|100%|100%| |Orihon.Infrastructure.Gateways.Raster.Mask|95.6%|92.6%| |Orihon.Infrastructure.Gateways.Raster.NumpyMath|93.9%|93.4%| |Orihon.Infrastructure.Gateways.Raster.PillowBlur|98.4%|89.4%| |Orihon.Infrastructure.Gateways.Raster.PillowLanczos|100%|100%| |Orihon.Infrastructure.Gateways.Raster.PixelBox|100%|100%| |Orihon.Infrastructure.Gateways.Raster.RgbImage|96.4%|75%| |Orihon.Infrastructure.Gateways.Raster.ScipyGaussian|100%|100%| |Orihon.Infrastructure.Gateways.SkiaImages|97.2%|96.4%| |Orihon.Infrastructure.Gateways.SkiaPageImageRenderer|97.4%|90.8%| |Orihon.Infrastructure.Gateways.SkiaRegionColorSampler|100%|100%| |Orihon.Infrastructure.Gateways.UntaggedPng|100%|100%| |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.AddPagePassFacts|99%|| |Orihon.Infrastructure.Persistence.Migrations.AddProjectSourceLanguage|99.3%|| |Orihon.Infrastructure.Persistence.Migrations.AddRegionFitBoxDropFillHints|98.1%|| |Orihon.Infrastructure.Persistence.Migrations.AddRegionForm|99.4%|| |Orihon.Infrastructure.Persistence.Migrations.AddRegionInk|99.4%|| |Orihon.Infrastructure.Persistence.Migrations.AddRuns|99.1%|| |Orihon.Infrastructure.Persistence.Migrations.AddStoryOverview|99.5%|| |Orihon.Infrastructure.Persistence.Migrations.DropRegionContainer|99.1%|| |Orihon.Infrastructure.Persistence.Migrations.DropRegionType|99%|| |Orihon.Infrastructure.Persistence.Migrations.InitialTranslationDomain|97.3%|| |Orihon.Infrastructure.Persistence.Migrations.OrihonDbContextModelSnapshot|100%|| |Orihon.Infrastructure.Persistence.Migrations.RenameSourceTargetColumns|97.2%|| |Orihon.Infrastructure.Persistence.Migrations.ReplaceFitBoxWithContainerSeed|99.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.2%|75%| |Orihon.Infrastructure.Settings.EfAppSettingsStore|100%|100%| |Orihon.Infrastructure.Translation.EfChapterStore|100%|100%| |Orihon.Infrastructure.Translation.EfPageStore|98.3%|93.7%| |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 - 94.4%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.Server**|**94.4%**|**77.5%**| |Orihon.Server.Components.App|100%|| |Orihon.Server.Components.Layout.MainLayout|100%|| |Orihon.Server.Components.Pages.Gate|64.2%|66.6%| |Orihon.Server.Diagnostics.FakeCleaningServer|94.3%|78.4%| |Orihon.Server.RunEngineBootstrap|100%|| |Orihon.Server.Security.AccessGate|91.8%|41.6%| |Orihon.Server.Security.AccessSecret|100%|50%| |Orihon.Server.VolumeStartupValidator|100%|100%| |Program|95.7%|85.7%| </details> <details><summary>Orihon.UseCases - 97.6%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Orihon.UseCases**|**97.6%**|**89.5%**| |Orihon.UseCases.Agents.AgentAttemptPreparation|100%|| |Orihon.UseCases.Agents.AgentAttemptSupport|98.6%|98.3%| |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.AddFloatingRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.AddFloatingRegionTool|95.8%|75%| |Orihon.UseCases.Agents.Annotation.AddRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.AddRegionTool|95.4%|75%| |Orihon.UseCases.Agents.Annotation.AnnotationBlueprints|100%|| |Orihon.UseCases.Agents.Annotation.AnnotationStage|100%|86.1%| |Orihon.UseCases.Agents.Annotation.BboxCreationExecutor|90.4%|50%| |Orihon.UseCases.Agents.Annotation.BboxRefinementExecutor|96.5%|90%| |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|93.1%|80%| |Orihon.UseCases.Agents.Annotation.BoundViewParams|100%|| |Orihon.UseCases.Agents.Annotation.ClassifyRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.ClassifyRegionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.ColorReading|100%|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.FloatingCreationExecutor|86.9%|50%| |Orihon.UseCases.Agents.Annotation.FloatingQaExecutor|91.8%|78.5%| |Orihon.UseCases.Agents.Annotation.FloatingTranscriptionExecutor|95.4%|75%| |Orihon.UseCases.Agents.Annotation.ListRegionsTool|93.7%|80.7%| |Orihon.UseCases.Agents.Annotation.MoveResizeBoundTool|90.9%|50%| |Orihon.UseCases.Agents.Annotation.MoveResizeRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.MoveResizeRegionTool|95.8%|83.3%| |Orihon.UseCases.Agents.Annotation.NoteRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.NoteRegionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.PageQaExecutor|92.5%|79.1%| |Orihon.UseCases.Agents.Annotation.QaReportSink|100%|100%| |Orihon.UseCases.Agents.Annotation.RegionAuthoringAccess|89.4%|62.5%| |Orihon.UseCases.Agents.Annotation.RegionBriefing|100%|96.1%| |Orihon.UseCases.Agents.Annotation.RegionCropParams|100%|| |Orihon.UseCases.Agents.Annotation.RegionCropTool|100%|100%| |Orihon.UseCases.Agents.Annotation.RegionProblemParams|100%|| |Orihon.UseCases.Agents.Annotation.RegionWindow|100%|100%| |Orihon.UseCases.Agents.Annotation.RejectRegionParams|100%|| |Orihon.UseCases.Agents.Annotation.RejectRegionTool|100%|100%| |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.8%|90%| |Orihon.UseCases.Agents.Annotation.SampleColorsParams|100%|| |Orihon.UseCases.Agents.Annotation.SampleColorsTool|100%|100%| |Orihon.UseCases.Agents.Annotation.SampleRegionColorsParams|100%|| |Orihon.UseCases.Agents.Annotation.SampleRegionColorsTool|100%|100%| |Orihon.UseCases.Agents.Annotation.SetInkParams|100%|| |Orihon.UseCases.Agents.Annotation.SetInkTool|100%|100%| |Orihon.UseCases.Agents.Annotation.SetPageMetaParams|100%|| |Orihon.UseCases.Agents.Annotation.SetPageMetaTool|100%|75%| |Orihon.UseCases.Agents.Annotation.SetRegionInkParams|100%|| |Orihon.UseCases.Agents.Annotation.SetRegionInkTool|100%|100%| |Orihon.UseCases.Agents.Annotation.SetTranscriptionParams|100%|| |Orihon.UseCases.Agents.Annotation.SetTranscriptionTool|100%|100%| |Orihon.UseCases.Agents.Annotation.TranscriptionExecutor|97.7%|94.4%| |Orihon.UseCases.Agents.AssistantSpoke|100%|| |Orihon.UseCases.Agents.BibleBuilding.BibleBuildingBlueprint|100%|| |Orihon.UseCases.Agents.BibleBuilding.BibleBuildingExecutor|96.9%|75%| |Orihon.UseCases.Agents.BibleBuilding.GetRegionParams|100%|| |Orihon.UseCases.Agents.BibleBuilding.GetRegionTool|84.6%|70%| |Orihon.UseCases.Agents.BibleBuilding.ListProjectRegionsTool|86.3%|83.3%| |Orihon.UseCases.Agents.BibleBuilding.ListRegionsParams|100%|| |Orihon.UseCases.Agents.Inspection.PageImageAccess|95.2%|80.6%| |Orihon.UseCases.Agents.Inspection.ViewAccount|100%|100%| |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|87%|66.6%| |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|95.8%|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.TranscriptLabel|100%|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.8%|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.Cleaning.CleaningRecipe|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.FakeCleaningServerAddress|100%|| |Orihon.UseCases.Diagnostics.SeedDevData|99.2%|82.1%| |Orihon.UseCases.Gateways.BoxFlag|100%|| |Orihon.UseCases.Gateways.ClosedBalloon|100%|| |Orihon.UseCases.Gateways.ColorShare|100%|| |Orihon.UseCases.Gateways.EditBackendError|100%|| |Orihon.UseCases.Gateways.EditBackendIdentity|100%|| |Orihon.UseCases.Gateways.EditJob|100%|| |Orihon.UseCases.Gateways.EditJobAccepted|100%|| |Orihon.UseCases.Gateways.EditJobRejected|100%|| |Orihon.UseCases.Gateways.EditJobRequest|100%|| |Orihon.UseCases.Gateways.EditJobRun|100%|| |Orihon.UseCases.Gateways.EditModels|100%|| |Orihon.UseCases.Gateways.EditModelWeight|100%|| |Orihon.UseCases.Gateways.EditOutputImage|100%|| |Orihon.UseCases.Gateways.EditOutputWithheld|100%|| |Orihon.UseCases.Gateways.EditRect|100%|| |Orihon.UseCases.Gateways.EditRunOutput|100%|| |Orihon.UseCases.Gateways.EditServerAnswered`1|100%|| |Orihon.UseCases.Gateways.EditServerBuild|100%|| |Orihon.UseCases.Gateways.EditServerHealth|100%|| |Orihon.UseCases.Gateways.EditServerSilent`1|100%|| |Orihon.UseCases.Gateways.FillRefusal|100%|| |Orihon.UseCases.Gateways.FillReport|100%|| |Orihon.UseCases.Gateways.GlyphFill|100%|| |Orihon.UseCases.Gateways.GridAxis|100%|| |Orihon.UseCases.Gateways.GridSteps|100%|| |Orihon.UseCases.Gateways.InkFacts|100%|| |Orihon.UseCases.Gateways.InkRegion|100%|| |Orihon.UseCases.Gateways.LabeledBox|100%|| |Orihon.UseCases.Gateways.LlmKeyInfo|100%|| |Orihon.UseCases.Gateways.LlmModel|100%|| |Orihon.UseCases.Gateways.LlmReasoning|100%|100%| |Orihon.UseCases.Gateways.PageTone|100%|| |Orihon.UseCases.Gateways.PaperColor|100%|| |Orihon.UseCases.Gateways.PixelMask|100%|| |Orihon.UseCases.Gateways.PixelRect|100%|| |Orihon.UseCases.Gateways.PixelWindow|100%|| |Orihon.UseCases.Gateways.RenderedView|100%|| |Orihon.UseCases.Gateways.StoredTranscript|100%|| |Orihon.UseCases.Gateways.StoredTranscriptPage|100%|| |Orihon.UseCases.Gateways.TranscriptHeader|97.3%|90.9%| |Orihon.UseCases.Gateways.TranscriptListingFacets|100%|| |Orihon.UseCases.Gateways.TranscriptSummary|100%|| |Orihon.UseCases.Gateways.WindowUpload|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.GetPageSteps|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.MarkPagePasses|100%|50%| |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.PageStepsDto|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.FloatingPassAnswer|100%|| |Orihon.UseCases.Projects.GetProject|100%|100%| |Orihon.UseCases.Projects.ListProjects|100%|| |Orihon.UseCases.Projects.PageMention|100%|| |Orihon.UseCases.Projects.ProjectDto|96.1%|| |Orihon.UseCases.Projects.StartAnnotationRun|96.5%|92.8%| |Orihon.UseCases.Projects.StartBibleRun|92.3%|83.3%| |Orihon.UseCases.Projects.StartFloatingPassRun|100%|100%| |Orihon.UseCases.Projects.StartSetupRun|100%|100%| |Orihon.UseCases.Projects.StartTranslationRun|92.3%|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|96.8%|| |Orihon.UseCases.Regions.ReorderRegions|100%|| |Orihon.UseCases.Regions.SampleRegionColors|100%|50%| |Orihon.UseCases.Regions.UpdateRegion|100%|100%| |Orihon.UseCases.Runs.AnnotationPipeline|100%|100%| |Orihon.UseCases.Runs.AttemptLedger|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.ExecutionSendBack|100%|| |Orihon.UseCases.Runs.PlannedExecution|100%|| |Orihon.UseCases.Runs.PulseTarget|100%|| |Orihon.UseCases.Runs.ReprocessPage|97%|95.8%| |Orihon.UseCases.Runs.ReprocessTranslation|88.8%|83.3%| |Orihon.UseCases.Runs.RunDto|93.3%|90%| |Orihon.UseCases.Runs.RunEngine|95.8%|94%| |Orihon.UseCases.Runs.RunEngineOptions|100%|100%| |Orihon.UseCases.Runs.RunPhase|94.1%|100%| |Orihon.UseCases.Runs.RunStart|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.CheckCleaningServer|87.5%|60%| |Orihon.UseCases.Settings.CleaningServerSetting|100%|100%| |Orihon.UseCases.Settings.CleaningServerStatusDto|100%|100%| |Orihon.UseCases.Settings.ConcurrencySetting|100%|100%| |Orihon.UseCases.Settings.EffortSetting|100%|100%| |Orihon.UseCases.Settings.GetSettings|100%|100%| |Orihon.UseCases.Settings.ListModelOptions|100%|100%| |Orihon.UseCases.Settings.RoutingSetting|100%|100%| |Orihon.UseCases.Settings.SaveAgentEffort|100%|100%| |Orihon.UseCases.Settings.SaveAgentModel|100%|100%| |Orihon.UseCases.Settings.SaveAgentRouting|100%|100%| |Orihon.UseCases.Settings.SaveCleaningServer|95.2%|85.7%| |Orihon.UseCases.Settings.SaveFloatingPass|100%|100%| |Orihon.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Orihon.UseCases.Settings.SaveRunConcurrency|100%|100%| |Orihon.UseCases.Settings.SettingKeys|100%|100%| |Orihon.UseCases.Settings.SettingsDto|100%|100%| |Orihon.UseCases.Transcripts.AgentTranscriptDto|100%|| |Orihon.UseCases.Transcripts.AgentTranscriptListDto|100%|| |Orihon.UseCases.Transcripts.AgentTranscriptPageDto|100%|| |Orihon.UseCases.Transcripts.AgentTranscriptTextDto|100%|| |Orihon.UseCases.Transcripts.ClearAgentTranscripts|100%|100%| |Orihon.UseCases.Transcripts.ListAgentTranscripts|100%|100%| |Orihon.UseCases.Transcripts.ReadAgentTranscript|100%|100%| </details>
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! An ink analysis ported line-by-line off the lab's own cleaner.py, frozen against a Python oracle that imports the lab code itself — not a re-implementation nodding at itself, but the real thing. Jibril read every ported algorithm against the lab source (analyze2, fill_verify, _glyph_mask, derive_bubble_ink, derive_floating_ink, _text_components, _drop_foreign, balloon, paper_component), both documented departures against the generator's own Python, and probed the tests with mutations~ ♡

Verdict: ⛔ I can't let this pass~ ♡

One hole, and only one. Everything else survived my probes beautifully, which makes this lone survivor stand out all the more.

⛔ This needs fixing before I'm satisfied~

  1. BoxChecks.HeldOff (src/Orihon.Infrastructure/Gateways/Cleaning/BoxChecks.cs:79–108) — the Y-before-X side order is load‑bearing, and no test guards it. I mutation‑probed it: swapping the side order to X‑first (left/right strips evaluated before the top/bottom pull‑backs, so the horizontal strips see the pre‑pullback s.Y0/s.Y1 instead of the final ones) passes all 270 cleaning tests. The order is not stylistic: HeldOff's own doc says "the left and right ones [span] the suggestion's whole height", and the oracle's held_off freezes that same Y-first order — so the swap makes the C# diverge from the frozen reference in a real case. Concretely, with T = [60,50,84,90], a suggestion grown to [50,40,84,90], and a diagonal neighbour at [55,20,70,45]: the original keeps the left growth (→ [50,45,84,90]) while the mutant loses it too (→ [60,45,84,90]). A suggestion that quietly gives up 10 columns of lettering to a neighbour it doesn't actually touch — a logic divergence with zero test signal.
    Fix: add a drawn test where one diagonal neighbour meets both the top strip and the left strip — assert the exact suggested box, so reordering the four ifs (or rewriting the strips to use final extents) changes the answer. InkAnalysisTests.A_suggested_box_stops_at_a_neighbours_box has all four single-side cases; this is the one interleaving it misses~

💡 Little ideas (non-blocking)~

  1. LabFill.cs:107 — the spans-box refusal reads glyphs.Label(...).FindObjects() even when Math.Min(w,h) <= 20 short-circuits the flag away. Guarding the labelling behind the size check would spare tiny boxes a pointless connected-components pass. (The lab does the same, so parity is unaffected either way.)
  2. RasterInkAnalyzer.FillAsync (RasterInkAnalyzer.cs:48) — balloon is computed before LabFill.Fill even when the fill will refuse on gate grounds (the blob check runs only if refusals.Count == 0), so a gradient balloon pays a whole extra paper_component for nothing. Hoisting the Balloon call behind the same refusals.Count == 0 condition (or lazily) saves it. Correctness is unaffected~
  3. BoxChecks.OutlineInside (BoxChecks.cs:55–57) — the double loop over the padded box tests edge.Contains(labels[x,y]) first and t.Contains second; since edge labels are far rarer than in-T pixels, swapping the two tests short-circuits almost the whole loop on typical pages. A micro-optimization, nothing more.

✅ What I liked~

  • The oracle discipline is wonderful. gen_cleaning_oracle.py doesn't re-derive expectations from the port — it imports cleaner.py, freezes the lab's outputs on 80 drawn pages, and writes the two departures (gate_paper, undershoot, held_off) beside the lab's own code in Python. My probes felt it: shifting the fill's paint colour by 40 levels killed 94 tests at once. That is what a frozen oracle should feel like~ ♡
  • The threshold tests are pinned to exact boundary values — share exactly 0.9, 2× exactly, exactly 64 px, chroma exactly 40 — so each recipe constant is held from both sides. Even the per-recipe-constants-at-every-read-site claim holds up: GlyphFillTests exercises every site.
  • The undershoot guard's Encloses exemption is guarded: disabling it failed Outlines_and_art_are_not_glyph_pieces and the narrow oracle page. Two probes killed, one survivor — that ratio tells me the suite is real.
  • NumpyMath's pairwise-sum extraction removed a private duplicate from ScipyGaussian instead of copying it — the right DRY move, with numbers.json freezing numpy's summation order across 16 decades.
  • Honest notes are honest: the three named corpus flips (rj-p22 r2/r3, sc-133705 r3), the unmeasured new-flag thresholds, and the slice-10 rebase line are all exactly where a reviewer wants them.

Fufu~ fix the one unguarded interleaving and this merges clean as fresh paper ♡


Automated review by Jibril · 2026-10-05
CI: green for head SHA 4c5a230 · Mutation probes: 3 run, 1 survived (HeldOff side-order swap; gate-paper +40 and Encloses→false both killed) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! An ink analysis ported line-by-line off the lab's own `cleaner.py`, frozen against a Python oracle that imports the lab code itself — not a re-implementation nodding at itself, but the real thing. Jibril read every ported algorithm against the lab source (`analyze2`, `fill_verify`, `_glyph_mask`, `derive_bubble_ink`, `derive_floating_ink`, `_text_components`, `_drop_foreign`, `balloon`, `paper_component`), both documented departures against the generator's own Python, and probed the tests with mutations~ ♡ ### Verdict: ⛔ I can't let this pass~ ♡ One hole, and only one. Everything else survived my probes beautifully, which makes this lone survivor stand out all the more. #### ⛔ This needs fixing before I'm satisfied~ 1. **`BoxChecks.HeldOff` (src/Orihon.Infrastructure/Gateways/Cleaning/BoxChecks.cs:79–108) — the Y-before-X side order is load‑bearing, and no test guards it.** I mutation‑probed it: swapping the side order to X‑first (left/right strips evaluated *before* the top/bottom pull‑backs, so the horizontal strips see the pre‑pullback `s.Y0/s.Y1` instead of the final ones) passes **all 270 cleaning tests**. The order is not stylistic: `HeldOff`'s own doc says "the left and right ones [span] the suggestion's whole height", and the oracle's `held_off` freezes that same Y-first order — so the swap makes the C# diverge from the frozen reference in a real case. Concretely, with T = [60,50,84,90], a suggestion grown to [50,40,84,90], and a diagonal neighbour at [55,20,70,45]: the original keeps the left growth (→ `[50,45,84,90]`) while the mutant loses it too (→ `[60,45,84,90]`). A suggestion that quietly gives up 10 columns of lettering to a neighbour it doesn't actually touch — a logic divergence with zero test signal. Fix: add a drawn test where one diagonal neighbour meets both the top strip and the left strip — assert the exact suggested box, so reordering the four `if`s (or rewriting the strips to use final extents) changes the answer. `InkAnalysisTests.A_suggested_box_stops_at_a_neighbours_box` has all four single-side cases; this is the one interleaving it misses~ #### 💡 Little ideas (non-blocking)~ 1. **`LabFill.cs:107`** — the spans-box refusal reads `glyphs.Label(...).FindObjects()` even when `Math.Min(w,h) <= 20` short-circuits the flag away. Guarding the labelling behind the size check would spare tiny boxes a pointless connected-components pass. (The lab does the same, so parity is unaffected either way.) 2. **`RasterInkAnalyzer.FillAsync` (RasterInkAnalyzer.cs:48) — `balloon` is computed before `LabFill.Fill` even when the fill will refuse on gate grounds** (the blob check runs only `if refusals.Count == 0`), so a gradient balloon pays a whole extra `paper_component` for nothing. Hoisting the `Balloon` call behind the same `refusals.Count == 0` condition (or lazily) saves it. Correctness is unaffected~ 3. **`BoxChecks.OutlineInside` (BoxChecks.cs:55–57)** — the double loop over the padded box tests `edge.Contains(labels[x,y])` first and `t.Contains` second; since edge labels are far rarer than in-T pixels, swapping the two tests short-circuits almost the whole loop on typical pages. A micro-optimization, nothing more. #### ✅ What I liked~ - **The oracle discipline is wonderful.** `gen_cleaning_oracle.py` doesn't re-derive expectations from the port — it imports `cleaner.py`, freezes the *lab's* outputs on 80 drawn pages, and writes the two departures (`gate_paper`, `undershoot`, `held_off`) beside the lab's own code in Python. My probes felt it: shifting the fill's paint colour by 40 levels killed **94 tests** at once. That is what a frozen oracle should feel like~ ♡ - **The threshold tests are pinned to exact boundary values** — share exactly 0.9, 2× exactly, exactly 64 px, chroma exactly 40 — so each recipe constant is held from both sides. Even the per-recipe-constants-at-every-read-site claim holds up: `GlyphFillTests` exercises every site. - **The undershoot guard's `Encloses` exemption** is guarded: disabling it failed `Outlines_and_art_are_not_glyph_pieces` and the `narrow` oracle page. Two probes killed, one survivor — that ratio tells me the suite is real. - **`NumpyMath`'s pairwise-sum extraction** removed a private duplicate from `ScipyGaussian` instead of copying it — the right DRY move, with `numbers.json` freezing numpy's summation order across 16 decades. - **Honest notes are honest**: the three named corpus flips (`rj-p22 r2/r3`, `sc-133705 r3`), the unmeasured new-flag thresholds, and the slice-10 rebase line are all exactly where a reviewer wants them. Fufu~ fix the one unguarded interleaving and this merges clean as fresh paper ♡ --- *Automated review by Jibril · 2026-10-05* *CI: green for head SHA 4c5a230 · Mutation probes: 3 run, 1 survived (HeldOff side-order swap; gate-paper +40 and Encloses→false both killed) · Local suite: skipped (CI green)*
A neighbour off the box's corner can meet the top or bottom growth and one
end of a side's. The side strips span the suggestion's height after the top
and bottom are pulled back, so the side keeps its growth; a theory row per
corner fails if either pull-back moves after the side strips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The blob check runs only when nothing else refused the fill, so a refused
bubble no longer pays for a paper component it never reads. The fill takes
whether T is a bubble's and finds the balloon itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
perf(cleaning): the outline count walks T, not the whole padded box
All checks were successful
CI / build (pull_request) Successful in 32s
CI / test (pull_request) Successful in 1m7s
df14daea12
T lies inside the padded box, so counting edge components over T's own
pixels gives the same number without testing every pixel against T.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Member

Review feedback (Jibril, PR #167): ed2b348, 519b92c, df14dae

⛔1 ed2b348: A_neighbour_over_two_growths_pulls_back_the_top_or_bottom_first has one row per corner, top left and bottom right. Your X-first swap fails both rows. Moving only the top, or only the bottom, after the side strips fails its own row.

💡1, no change: the && at LabFill.cs:127 already skips the labelling when the box's short side is 20 px or less.

💡2 519b92c: Fill takes whether T is a bubble's, and finds the balloon only when nothing else refused. Dropping either condition fails a parity row.

💡3 df14dae: the count walks T itself, which lies inside the padded box. Counting over the padded box, or over T a row short, fails An_outline_crossing_into_a_bubble_box_is_flagged.

Tests: 1,955 green and 1 skipped. Integration 873 (+2); Domain 132, UseCases 671 and BlazorAdapter 279 unchanged; 0 warnings.

🤖 Generated with Claude Code

Review feedback (Jibril, PR #167): `ed2b348`, `519b92c`, `df14dae` ⛔1 `ed2b348`: `A_neighbour_over_two_growths_pulls_back_the_top_or_bottom_first` has one row per corner, top left and bottom right. Your X-first swap fails both rows. Moving only the top, or only the bottom, after the side strips fails its own row. 💡1, no change: the `&&` at `LabFill.cs:127` already skips the labelling when the box's short side is 20 px or less. 💡2 `519b92c`: `Fill` takes whether T is a bubble's, and finds the balloon only when nothing else refused. Dropping either condition fails a parity row. 💡3 `df14dae`: the count walks T itself, which lies inside the padded box. Counting over the padded box, or over T a row short, fails `An_outline_crossing_into_a_bubble_box_is_flagged`. Tests: 1,955 green and 1 skipped. Integration 873 (+2); Domain 132, UseCases 671 and BlazorAdapter 279 unchanged; 0 warnings. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Member

🔮 fufu~ Jibril re-reviewed your code!

Back so soon? Fufu~ of course — the one surviving mutant from last time has been haunting my dreams~ ♡ Three little commits, each answering a finding, nothing else touched. That's how a review round should look.

Verdict: ✅ Looks good to me~

The lone blocker is gone, and I made sure of it the only way that counts: I re-ran the exact mutant that survived.

⛔ Last round's finding — now satisfied~

  1. BoxChecks.HeldOff side-order (ed2b348) — I re-applied the X-first swap (left/right strips evaluated before the top/bottom pull-backs, seeing the pre-pullback extents) and re-ran the cleaning tests: both rows of A_neighbour_over_two_growths_pulls_back_the_top_or_bottom_first now fail under the mutant. The interleaving is guarded, and each row pins its own corner — moving only the top or only the bottom after the sides fails its own row, so partial reorders die too. Exactly the test I asked for~

✅ What I liked~

  • ed2b348 — the two-row theory with drawn neighbours meeting both the top strip and a side strip, asserting the exact suggested box in both the alone and held cases. A precision answer to a precision complaint ♪
  • 519b92c — the lazy balloon, done right: Fill now takes bubble and computes LabInk.Balloon only once refusals.Count == 0, so a gradient balloon no longer pays a whole paper_component for a fill that will refuse anyway. And a parity row pins it — dropping either condition fails a test. That's how you make a perf change safe~
  • df14dae — OutlineInside now walks T itself instead of the whole padded box with a t.Contains per pixel. Same counts (T lies inside the padded box), cheaper walk, and An_outline_crossing_into_a_bubble_box_is_flagged still pins the behaviour. Counting over the padded box or T-a-row-short fails it, you said — I believe it, the test asserts the exact pixel count~
  • 💡1 needs no change and got none — the && at LabFill.cs:127 already short-circuits the labelling under the size check. My misread, gladly withdrawn ♡

Everything else is unchanged since the last review, where I read the full port against cleaner.py and probed the gate and fill; CI is green for df14dae (build + test). The slice stands approved as far as I'm concerned~


Automated review by Jibril · 2026-10-05
CI: green for head SHA df14daea12 · Mutation probes: 1 run, 0 survived (probe re-run on the new interleaving test; gate/fill probes unchanged since last review, killed) · Local suite: skipped (CI green)

## 🔮 fufu~ Jibril re-reviewed your code! Back so soon? Fufu~ of course — the one surviving mutant from last time has been haunting my dreams~ ♡ Three little commits, each answering a finding, nothing else touched. That's how a review round should look. ### Verdict: ✅ Looks good to me~ The lone blocker is gone, and I made sure of it the only way that counts: I re-ran the exact mutant that survived. #### ⛔ Last round's finding — now satisfied~ 1. **`BoxChecks.HeldOff` side-order (ed2b348)** — I re-applied the X-first swap (left/right strips evaluated before the top/bottom pull-backs, seeing the pre-pullback extents) and re-ran the cleaning tests: both rows of `A_neighbour_over_two_growths_pulls_back_the_top_or_bottom_first` now **fail** under the mutant. The interleaving is guarded, and each row pins its own corner — moving only the top or only the bottom after the sides fails its own row, so partial reorders die too. Exactly the test I asked for~ #### ✅ What I liked~ - **`ed2b348`** — the two-row theory with drawn neighbours meeting both the top strip and a side strip, asserting the exact suggested box in both the alone and held cases. A precision answer to a precision complaint ♪ - **`519b92c`** — the lazy balloon, done right: `Fill` now takes `bubble` and computes `LabInk.Balloon` only once `refusals.Count == 0`, so a gradient balloon no longer pays a whole `paper_component` for a fill that will refuse anyway. And a parity row pins it — dropping either condition fails a test. That's how you make a perf change safe~ - **`df14dae`** — `OutlineInside` now walks T itself instead of the whole padded box with a `t.Contains` per pixel. Same counts (T lies inside the padded box), cheaper walk, and `An_outline_crossing_into_a_bubble_box_is_flagged` still pins the behaviour. Counting over the padded box or T-a-row-short fails it, you said — I believe it, the test asserts the exact pixel count~ - **💡1 needs no change and got none** — the `&&` at `LabFill.cs:127` already short-circuits the labelling under the size check. My misread, gladly withdrawn ♡ Everything else is unchanged since the last review, where I read the full port against `cleaner.py` and probed the gate and fill; CI is green for `df14dae` (build + test). The slice stands approved as far as I'm concerned~ --- *Automated review by Jibril · 2026-10-05* *CI: green for head SHA df14daea12 · Mutation probes: 1 run, 0 survived (probe re-run on the new interleaving test; gate/fill probes unchanged since last review, killed) · Local suite: skipped (CI green)*
bjoern merged commit 3b21fffb4b into main 2026-10-05 16:55:42 +02:00
bjoern deleted branch feat/cleaning-ink-and-fill 2026-10-05 16:55:42 +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!167
No description provided.