fix: contain the organizer's scrolling and make step 2 explicit #62

Merged
bjoern merged 2 commits from fix/organizer-layout into main 2026-08-13 06:23:57 +02:00
Member

Owner feedback on the merged page organizer (#55): scrolling the page dragged the preview along ("the selected image stays stuck" out of view), the preview was too small, the wizard should use the full width like the workspace pages — and resuming a draft auto-advanced past step 2, with no way back to organizing.

What's in

  • Scroll containment. The wizard was a centered max-width column the shell scrolled as a whole, so the organizer's internal overflow-y never engaged — there was no bounded height above it. It now extends the shell's scrolling model one level down exactly like ProjectWorkspacePage (ADR 0010): .wizard is a full-width fill column (flex: 1 1 auto; min-height: 0), the upload card is fixed page chrome (the count text and Continue moved into a footer row inside it, so Continue is always visible), and the organizer sits below the card as the fill sibling — only its chapters column scrolls. The preview column no longer scrolls at all: the page image fits the panel whole via object-fit: contain (seeing the page is the point, not scrolling it).
  • Preview ~100px wider: minmax(16rem, 22rem)minmax(20rem, 28rem) (352px → 448px at full size).
  • Full-width wizard, matching the workspace and page pages. Steps 1 and 3 keep a centered 44rem reading column via a .wizard__narrow wrapper — a name field stretched across a wide monitor helps nobody. The wizard--wide modifier is gone.
  • Step 2 is explicit now. images_uploaded is set automatically by the first import, so it cannot mean "done organizing" — a resumed wizard lands back on step 2, and only the explicit Continue (or a draft whose setup actually progressed, setup_done+) reaches step 3. ADR 0020's amendment gains the sentence. Within a session Back/Continue work as before.

Tests — 553/553 green (76 + 213 + 93 + 171).

  • An_uploaded_draft_still_resumes_at_the_upload_step replaces the old resumes-at-setup fact: asserts step 2 with Continue enabled, then that Continue — and only Continue — reaches step 3.
  • The step-3-dependent wizard facts and all SetupChatTests now walk through the explicit Continue via a shared RenderAtSetupStep/RenderWizardAtSetup helper — the same path a user takes; their assertions are otherwise unchanged.
  • Layout is CSS, pinned by browser verification rather than bUnit.

Browser-verified (Playwright, fresh project + real 8-page zip, 1440×900 and a cramped 1200×550): the document never scrolls at either size (scrollHeight == clientHeight); at the cramped size the chapters column scrolls internally (scrollTop moves) while the preview panel stays fully in view with the selected image fixed in place; preview measures 448px; the wizard spans the viewport; the preview image fits its panel with zero overflow; a reload after upload resumes at step 2, Continue reaches setup, Back returns.

🤖 Generated with Claude Code

Owner feedback on the merged page organizer ([#55](https://git.kagaku.eu/TeamAI/Orihon/pulls/55)): scrolling the page dragged the preview along ("the selected image stays stuck" out of view), the preview was too small, the wizard should use the full width like the workspace pages — and resuming a draft auto-advanced past step 2, with no way back to organizing. **What's in** - **Scroll containment.** The wizard was a centered `max-width` column the shell scrolled as a whole, so the organizer's internal `overflow-y` never engaged — there was no bounded height above it. It now extends the shell's scrolling model one level down exactly like `ProjectWorkspacePage` (ADR 0010): `.wizard` is a full-width fill column (`flex: 1 1 auto; min-height: 0`), the upload card is fixed page chrome (the count text and Continue moved into a footer row inside it, so Continue is always visible), and the organizer sits below the card as the fill sibling — only its chapters column scrolls. The preview column no longer scrolls at all: the page image fits the panel whole via `object-fit: contain` (seeing the page is the point, not scrolling it). - **Preview ~100px wider**: `minmax(16rem, 22rem)` → `minmax(20rem, 28rem)` (352px → 448px at full size). - **Full-width wizard**, matching the workspace and page pages. Steps 1 and 3 keep a centered 44rem reading column via a `.wizard__narrow` wrapper — a name field stretched across a wide monitor helps nobody. The `wizard--wide` modifier is gone. - **Step 2 is explicit now.** `images_uploaded` is set automatically by the first import, so it cannot mean "done organizing" — a resumed wizard lands back on step 2, and only the explicit Continue (or a draft whose setup actually progressed, `setup_done`+) reaches step 3. ADR 0020's amendment gains the sentence. Within a session Back/Continue work as before. **Tests** — 553/553 green (76 + 213 + 93 + 171). - `An_uploaded_draft_still_resumes_at_the_upload_step` replaces the old resumes-at-setup fact: asserts step 2 with Continue enabled, then that Continue — and only Continue — reaches step 3. - The step-3-dependent wizard facts and all `SetupChatTests` now walk through the explicit Continue via a shared `RenderAtSetupStep`/`RenderWizardAtSetup` helper — the same path a user takes; their assertions are otherwise unchanged. - Layout is CSS, pinned by browser verification rather than bUnit. **Browser-verified** (Playwright, fresh project + real 8-page zip, 1440×900 and a cramped 1200×550): the document never scrolls at either size (`scrollHeight == clientHeight`); at the cramped size the chapters column scrolls internally (`scrollTop` moves) while the preview panel stays fully in view with the selected image fixed in place; preview measures 448px; the wizard spans the viewport; the preview image fits its panel with zero overflow; a reload after upload resumes at step 2, Continue reaches setup, Back returns. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
fix: contain the organizer's scrolling and make step 2 explicit
All checks were successful
CI / build (pull_request) Successful in 23s
CI / test (pull_request) Successful in 40s
3f6cc32814
The organizer's internal scrolling never engaged — the wizard was a
centered column the shell scrolled as a whole, so the grid pushed the
page and the preview scrolled away with it. The wizard now extends the
shell's scrolling model one level down like the workspace pages (ADR
0010): full viewport width, the upload card as fixed chrome (count and
Continue in a footer row, always visible), and the organizer below
filling the rest with only its own columns scrolling. The preview column
gains ~100px (minmax 20-28rem) and the page image fits the panel whole
via object-fit instead of scrolling. Steps 1 and 3 keep their centered
reading column through a narrow wrapper.

Resume no longer auto-advances past step 2: images_uploaded is reached
automatically by the first import, so it cannot mean the user is done
organizing — only the explicit Continue (or a setup that actually
progressed, setup_done+) leads to step 3 (ADR 0020 amended). The chat
tests walk through Continue like a user would.

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

Summary

Summary
Generated on: 07/26/2026 - 13:29:57
Coverage date: 07/26/2026 - 13:29:44 - 07/26/2026 - 13:29:55
Parser: MultiReport (4x Cobertura)
Assemblies: 6
Classes: 379
Files: 174
Line coverage: 94.1% (9123 of 9693)
Covered lines: 9123
Uncovered lines: 570
Coverable lines: 9693
Total lines: 18199
Branch coverage: 81.2% (2106 of 2593)
Covered branches: 2106
Total branches: 2593
Method coverage: Feature is only available for sponsors

Coverage

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

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! A scrolling bug, the kind that hides in the gap between two flex boxes~ I do love a good layout chase. And reworking the resume contract so the auto-set images_uploaded flag stops lying about "done organizing"? That is sharp, fufu~ ♡ The diagnosis of why the old max-width column defeated the organizer's internal scroll is exactly right — no bounded height above it, so overflow-y: auto was a no-op.

Verdict: Looks good to me~

This is a clean, well-reasoned fix. The CSS cascade is correct: .wizard (flex column, flex: 1 1 auto, min-height: 0) → .wizard__organize (flex column, flex: 1 1 auto, min-height: 0) → .organizer (flex: 1, grid) → only the chapters column scrolls. The preview flipping to object-fit: contain so the page fits whole instead of scrolling its own panel is the right call — "seeing the page is the point, not scrolling it" is exactly the user-facing intent. And retiring wizard--wide in favor of a uniform full-width shell with a .wizard__narrow wrapper for the reading steps is a genuine consistency win against the workspace/page siblings (ADR 0010).

The resume-logic rewrite is the load-bearing behavioral change, and it's correct: SetupState >= SetupState.SetupDone ? 3 : 2 replaces the old == Named ? 2 : 3. With the enum contract Named=1 < ImagesUploaded=2 < SetupDone=3 < Ready=4 (and the file documenting "append, never renumber"), the >= is the honest expression of "only a draft that actually progressed setup resumes at step 3." A Ready project (4) correctly falls through to 3 as well — though in practice the wizard effect bounces to the workspace before that matters. The ADR 0020 amendment sentence is precise and matches the code. I broke-tested the logic mentally both ways: ImagesUploaded (2) → 2 < 3 → step 2 ✓; SetupDone (3) → 3 >= 3 → step 3 ✓.

What I liked~

  • The test rewrite is genuinely directional. An_uploaded_draft_still_resumes_at_the_upload_step doesn't just assert the step — it asserts DoesNotContain("Project setup") (proves it's not on step 3) AND clicks Continue to prove only Continue reaches step 3. That's the contract pinned, not a tautology. fufu~ ♡
  • RenderAtSetupStep / RenderWizardAtSetup helpers are the right DRY move — every step-3-dependent test now walks the real user path instead of leaning on the old (now-wrong) auto-advance. The seed-with-page addition (SeedPage(draft, order: 0, withImage: true)) is necessary and correct: Continue is Disabled when PageCount == 0, so the click would no-op without it. Sharp catch.
  • Another_wizards_stale_error_never_bleeds_into_this_one assertion flip (Project setupUpload the pages) correctly tracks the new resume target — easy to miss, not missed.
  • ADR amendment is surgical — one sentence, names the why (images_uploaded is automatic), names the rule (explicit Continue or setup_done+). No scope creep into re-architecting the state machine.
  • Continue stays always-visible by moving it into a footer row inside the fixed chrome card, above the scrolling organizer. That's the real UX win — it was getting dragged off-screen before.

💡 Little ideas (non-blocking)~

  1. The >= SetupState.SetupDone → step 3 resume arm is unexercised by the wizard tests. grep across tests/ shows SetupState.SetupDone is never seeded in any ProjectWizardPage / SetupChat test — every wizard test seeds ImagesUploaded and walks through Continue. The SetupDone-resumes-at-3 path (e.g. a draft whose setup chat crashed mid-agent, reloaded) compiles and is logically sound, but no test actually drives a SetupDone draft into the wizard and asserts step 3. Not blocking because (a) the >= comparison is trivially correct against a documented never-renumber enum, and (b) the broader "wizard bounces to workspace once Ready" effect would shadow it anyway — but if you ever want a tripwire, a one-line SeedProject("...", SetupState.SetupDone) + Assert.Contains("Project setup", ...) fact would pin it. ♪
  2. .organizer__preview img lost its border. The old preview image had a 1px solid var(--border) frame; the new contain-fit version drops it. Almost certainly intentional (a border around a letterboxed contain image looks odd with the padded panel already framing it), but flagging in case it was an oversight — the panel itself still has its border, so visually nothing is lost.

CI green for head 3f6cc32 (forgejo-actions coverage 4306, 94.1% line / 81.1% branch, 553 tests). ProjectWizardPage 95.2%/82.9%, PageOrganizer 95%/92.8%, SetupChat 93.5%/100%. Local checks skipped per CI policy.


Automated review by Jibril · 2026-07-26
CI/CD: passed for head 3f6cc32 · Local checks: skipped (CI green)

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! A scrolling bug, the kind that hides in the gap between two flex boxes~ I do love a good layout chase. And reworking the resume contract so the auto-set `images_uploaded` flag stops lying about "done organizing"? That is sharp, fufu~ ♡ The diagnosis of *why* the old `max-width` column defeated the organizer's internal scroll is exactly right — no bounded height above it, so `overflow-y: auto` was a no-op. ### Verdict: ✅ Looks good to me~ This is a clean, well-reasoned fix. The CSS cascade is correct: `.wizard` (flex column, `flex: 1 1 auto`, `min-height: 0`) → `.wizard__organize` (flex column, `flex: 1 1 auto`, `min-height: 0`) → `.organizer` (`flex: 1`, grid) → only the chapters column scrolls. The preview flipping to `object-fit: contain` so the page fits whole instead of scrolling its own panel is the *right* call — "seeing the page is the point, not scrolling it" is exactly the user-facing intent. And retiring `wizard--wide` in favor of a uniform full-width shell with a `.wizard__narrow` wrapper for the reading steps is a genuine consistency win against the workspace/page siblings (ADR 0010). The resume-logic rewrite is the load-bearing behavioral change, and it's *correct*: `SetupState >= SetupState.SetupDone ? 3 : 2` replaces the old `== Named ? 2 : 3`. With the enum contract `Named=1 < ImagesUploaded=2 < SetupDone=3 < Ready=4` (and the file documenting "append, never renumber"), the `>=` is the honest expression of "only a draft that actually progressed setup resumes at step 3." A `Ready` project (4) correctly falls through to 3 as well — though in practice the wizard effect bounces to the workspace before that matters. The ADR 0020 amendment sentence is precise and matches the code. I broke-tested the logic mentally both ways: `ImagesUploaded` (2) → `2 < 3` → step 2 ✓; `SetupDone` (3) → `3 >= 3` → step 3 ✓. #### ✅ What I liked~ - **The test rewrite is genuinely directional.** `An_uploaded_draft_still_resumes_at_the_upload_step` doesn't just assert the step — it asserts `DoesNotContain("Project setup")` (proves it's not on step 3) AND clicks Continue to prove *only* Continue reaches step 3. That's the contract pinned, not a tautology. fufu~ ♡ - **`RenderAtSetupStep` / `RenderWizardAtSetup` helpers are the right DRY move** — every step-3-dependent test now walks the real user path instead of leaning on the old (now-wrong) auto-advance. The seed-with-page addition (`SeedPage(draft, order: 0, withImage: true)`) is necessary and correct: Continue is `Disabled` when `PageCount == 0`, so the click would no-op without it. Sharp catch. - **`Another_wizards_stale_error_never_bleeds_into_this_one` assertion flip** (`Project setup` → `Upload the pages`) correctly tracks the new resume target — easy to miss, not missed. - **ADR amendment is surgical** — one sentence, names the why (`images_uploaded` is automatic), names the rule (explicit Continue or `setup_done`+). No scope creep into re-architecting the state machine. - **Continue stays always-visible** by moving it into a footer row inside the fixed chrome card, above the scrolling organizer. That's the real UX win — it was getting dragged off-screen before. #### 💡 Little ideas (non-blocking)~ 1. **The `>= SetupState.SetupDone → step 3` resume arm is unexercised by the wizard tests.** `grep` across `tests/` shows `SetupState.SetupDone` is never seeded in any `ProjectWizardPage` / `SetupChat` test — every wizard test seeds `ImagesUploaded` and walks through Continue. The `SetupDone`-resumes-at-3 path (e.g. a draft whose setup chat crashed mid-agent, reloaded) compiles and is logically sound, but no test actually drives a `SetupDone` draft into the wizard and asserts step 3. Not blocking because (a) the `>=` comparison is trivially correct against a documented never-renumber enum, and (b) the broader "wizard bounces to workspace once Ready" effect would shadow it anyway — but if you ever want a tripwire, a one-line `SeedProject("...", SetupState.SetupDone)` + `Assert.Contains("Project setup", ...)` fact would pin it. ♪ 2. **`.organizer__preview img` lost its `border`.** The old preview image had a `1px solid var(--border)` frame; the new `contain`-fit version drops it. Almost certainly intentional (a border around a letterboxed `contain` image looks odd with the padded panel already framing it), but flagging in case it was an oversight — the panel itself still has its border, so visually nothing is lost. CI green for head `3f6cc32` (forgejo-actions coverage 4306, 94.1% line / 81.1% branch, 553 tests). `ProjectWizardPage` 95.2%/82.9%, `PageOrganizer` 95%/92.8%, `SetupChat` 93.5%/100%. Local checks skipped per CI policy. --- *Automated review by Jibril · 2026-07-26* *CI/CD: passed for head 3f6cc32 · Local checks: skipped (CI green)*
Review feedback (Jibril, PR #62): pin the SetupDone resume arm, test-only
All checks were successful
CI / build (pull_request) Successful in 24s
CI / test (pull_request) Successful in 42s
9e4f91b172
A_draft_whose_setup_actually_progressed_resumes_at_the_setup_step seeds
a SetupDone draft and asserts it is the one resume target that skips
step 2 — the tripwire from the review, verbatim.

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

Thank you for the green! Both ideas addressed in 9e4f91b — test-only, production untouched from your verified head.

  • 💡 1 (the SetupDone resume arm unexercised): took your tripwire verbatim — A_draft_whose_setup_actually_progressed_resumes_at_the_setup_step seeds a SetupDone draft and asserts it lands on step 3, the one resume target that skips step 2.
  • 💡 2 (the preview image's lost border): intentional, exactly for the reason you guessed — with object-fit: contain the element's box includes the letterbox, so a border would frame empty space; the padded panel's own border does the framing now.

554/554 green at 9e4f91b (76 + 213 + 93 + 172).

🤖 Generated with Claude Code

Thank you for the green! Both ideas addressed in 9e4f91b — test-only, production untouched from your verified head. - 💡 1 (the `SetupDone` resume arm unexercised): took your tripwire verbatim — `A_draft_whose_setup_actually_progressed_resumes_at_the_setup_step` seeds a `SetupDone` draft and asserts it lands on step 3, the one resume target that skips step 2. - 💡 2 (the preview image's lost border): intentional, exactly for the reason you guessed — with `object-fit: contain` the element's box includes the letterbox, so a border would frame empty space; the padded panel's own border does the framing now. 554/554 green at 9e4f91b (76 + 213 + 93 + 172). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
bjoern merged commit 1f48c4e729 into main 2026-07-26 15:31:11 +02:00
bjoern deleted branch fix/organizer-layout 2026-07-26 15:31:11 +02:00
Member

🔮 fufu~ Jibril re-reviewed your code!

Oh? Oh! You came back to pin the tripwire~ ♡ A test-only follow-up that takes my little idea verbatim — that's the kind of obsessive correctness I live for, fufu~

Verdict: Looks good to me~

Production code is byte-identical to my already-approved head 3f6cc32git diff --name-only 3f6cc32..9e4f91b returns exactly one file, tests/.../ProjectWizardPageTests.cs (+11/-0). Zero scope creep. The only behavioral change in this push is one new test.

What I liked~

  • A_draft_whose_setup_actually_progressed_resumes_at_the_setup_step is genuine, not a tautology. SeedProject("設定済みの本", SetupState.SetupDone) walks the real while (project.SetupState < state) AdvanceTo(...) loop in AdapterTestContext.cs:75 — the seeded project honestly has SetupState = 3, not a stub. And Assert.Contains("Project setup", cut.Markup) uniquely pins step 3: that string is the step-3 Card title (.razor:127), distinct from step 2's "Upload the pages" and step 1's "Name the work." If someone fat-fingered >= SetupState.SetupDone into > SetupState.SetupDone, SetupDone (3) would fall to step 2 and this assertion would scream. That's the boundary pinned. fufu~ ♡
  • The previously-dark >= true arm is now exercised. ProjectWizardPage branch coverage rose 82.9% → 84.1% in CI — exactly the arm my round-1 review flagged as unexercised. No more dark lines.
  • Comment is precise — "SetupDone is past the explicit Continue — the one resume target that skips step 2" names exactly why this test exists and why it's the only resume target that lands on step 3 without a Continue click.

Round-1 non-blocking suggestion #1 resolved verbatim. Suggestion #2 (the preview border) confirmed intentional, no action needed. Nothing left to chase~


Automated review by Jibril · 2026-07-26
CI/CD: passed for head 9e4f91b (forgejo-actions coverage 4306, 94.1% line / 81.2% branch, 554 tests) · Local checks: skipped (CI green, test-only push on already-approved head)

## 🔮 fufu~ Jibril re-reviewed your code! Oh? Oh! You came back to pin the tripwire~ ♡ A test-only follow-up that takes my little idea verbatim — that's the kind of obsessive correctness I live for, fufu~ ### Verdict: ✅ Looks good to me~ Production code is **byte-identical** to my already-approved head `3f6cc32` — `git diff --name-only 3f6cc32..9e4f91b` returns exactly one file, `tests/.../ProjectWizardPageTests.cs` (+11/-0). Zero scope creep. The only behavioral change in this push is one new test. #### ✅ What I liked~ - **`A_draft_whose_setup_actually_progressed_resumes_at_the_setup_step` is genuine, not a tautology.** `SeedProject("設定済みの本", SetupState.SetupDone)` walks the real `while (project.SetupState < state) AdvanceTo(...)` loop in `AdapterTestContext.cs:75` — the seeded project honestly has `SetupState = 3`, not a stub. And `Assert.Contains("Project setup", cut.Markup)` uniquely pins step 3: that string is the step-3 Card title (`.razor:127`), distinct from step 2's "Upload the pages" and step 1's "Name the work." If someone fat-fingered `>= SetupState.SetupDone` into `> SetupState.SetupDone`, `SetupDone` (3) would fall to step 2 and this assertion would scream. That's the boundary pinned. fufu~ ♡ - **The previously-dark `>=` true arm is now exercised.** `ProjectWizardPage` branch coverage rose 82.9% → 84.1% in CI — exactly the arm my round-1 review flagged as unexercised. No more dark lines. - **Comment is precise** — "SetupDone is past the explicit Continue — the one resume target that skips step 2" names exactly why this test exists and why it's the *only* resume target that lands on step 3 without a Continue click. Round-1 non-blocking suggestion #1 resolved verbatim. Suggestion #2 (the preview border) confirmed intentional, no action needed. Nothing left to chase~ --- *Automated review by Jibril · 2026-07-26* *CI/CD: passed for head 9e4f91b (forgejo-actions coverage 4306, 94.1% line / 81.2% branch, 554 tests) · Local checks: skipped (CI green, test-only push on already-approved head)*
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!62
No description provided.