No description
- C# 88.8%
- HTML 9.2%
- CSS 1.8%
- Dockerfile 0.1%
bjoern sent a page where the fill takes "too much of everything, even at threshold 1". He was right, and the rule I shipped in #130 does not catch it. This replaces the tell. ## What the page actually does A balloon whose outline opens onto the page's left margin. Rendered with the real gateways at `LeastTolerance` — the tightest threshold there is: ``` p12r9 (a balloon): 1% of page, spread 1.23x accepted p12r4 (the margin): 11% of page, spread 10.05x refused ``` The margin fill runs the **full height of the sheet** and reaches back through the margin into **two further balloons** that touch the same panel edge. One seed, one connected white region. Tolerance cannot help: the margin and the balloon's inside are the *same white*, so there is no threshold that parts them. The fill is right about colour and wrong about what it is describing. ## Share is the wrong measure, in both directions **It misses this.** A strip the height of a page is 11% of its area — under `RunawayShare` (25), so #130 waves it through. **And it refuses real containers.** `jagged-shout-clipped` — a fixture in our own regression suite — is **37%** of its image. #130 would refuse it. The same balloon on a full page is 1%. A share depends on how much page surrounds the container, which is not a property of the container. ## The measure that works `spread` — the larger of the container's two dimensions over the region's own box. A container holds this text, so it is a small multiple of it, and that does not change with how much page there is. Measured across every container I have known-good numbers for — five regression fixtures and five balloons off two real pages: | container | share | spread | |---|---:|---:| | starburst-with-heart-glyphs | 2% | 0.29x | | round-balloons-on-art | 6% | 0.89x | | raw2 balloon | 1% | 1.23x | | raw balloon ×5 | 0–3% | 1.45–1.96x | | jagged-shout-clipped | **37%** | 1.49x | | white-boxes-on-white-page | 6% | 1.58x | | **the margin leak** | **11%** | **10.05x** | Widest good container **1.96x**; the leak **10x**. `LooseSpread = 4` sits between them with room on both sides — it leaves every known-good container alone by a factor of two and still catches the leak by a factor of two. The larger dimension rather than the area, because a leak is usually long in one direction only: this one is barely wider than it started and ten times taller, which an area would average away. ## What's in - **`ContainerFit.Spread`** — nullable, since a request without a `MustCover` box has nothing to be a multiple of. - **`LooksLikeRunaway`** uses spread where it exists, and falls back to share where it does not. Every production caller passes the region's box, so the fallback is for direct-gateway use. - **The refusal and the workspace hint now say what is wrong** — "came out 10 times the size of this region's own box" rather than a percentage — and name the case tolerance cannot fix, so an agent does not sit there lowering a number that will never help. - **ADR 0012** records why share was demoted, with the numbers. ## Tests — 1284/1284 green Domain 150, UseCases 575, Integration 280, BlazorAdapter 279. Build 0 warnings / 0 errors. New (+7), both directions on the fixture the suite already carries: - **`A_fill_that_reaches_the_page_margin_is_loose_however_small_its_share`** ×2 seeds — at `LeastTolerance`, asserting the fill *is* loose, spread > 10, **and that its share never reaches the old line**. That last assertion is the point: it fails if anyone reintroduces a share-based rule. - **`A_real_container_is_a_small_multiple_of_its_own_text`** ×5 — every seed the panel suite already trusts, asserting spread stays under *half* the limit. No new fixture: `whole-page-with-gutters.jpg` reproduces the leak exactly (spread 19.93x at its own margin), so the regression is pinned on an image already in the tree rather than another 848 KB. ## Notes - **This supersedes #130's share threshold in practice.** `RunawayShare` stays for the no-box case rather than being deleted, and the note in #130 about legitimately large containers being blocked is now moot — that was the `jagged-shout` false positive, and spread does not have it. - Unchanged: the editor's threshold control, both-ways guidance, and the floating rule from #130 all still apply. This only replaces *how a bad fill is recognised*. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: schattenan <schattenan@kagaku.eu> Reviewed-on: #131 Co-authored-by: scarlet <scarlet@kagaku.eu> Co-committed-by: scarlet <scarlet@kagaku.eu> |
||
|---|---|---|
| .claude/skills/pr-review-loop | ||
| .config | ||
| .github | ||
| deploy | ||
| docs | ||
| external | ||
| src | ||
| tests | ||
| .dockerignore | ||
| .gitattributes | ||
| .gitignore | ||
| .gitmodules | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| Directory.Build.props | ||
| Directory.Packages.props | ||
| Orihon.slnx | ||
| README.md | ||
Orihon
A single-user, self-hosted doujinshi translation harness — a Blazor Server app that drives translation through a heavy-handed, inspectable AI workflow graph.
Status: repository skeleton. Structure, submodules, central package management, CI and the container build are in place. The architecture (ADRs) and user stories are written next, before feature code.
Prerequisites
- .NET SDK 10.0+
- Access to the vendored submodules on
git.kagaku.eu(TeamAI org)
Getting started
# Clone WITH submodules (OpenRouter.Net, Kagaku.UI live under external/)
git clone --recurse-submodules <orihon-url>
# Already cloned without them?
git submodule update --init --recursive
dotnet build Orihon.slnx --configuration Release
dotnet test Orihon.slnx --configuration Release
dotnet run --project src/Orihon.Server # http://localhost:5000, /health
Layout
| Project | Responsibility |
|---|---|
src/Orihon.Kernel |
Technical primitives (Result<T>). References nothing. |
src/Orihon.Domain |
Entities and value objects. Pure — no I/O, no framework attributes. |
src/Orihon.UseCases |
Application layer: use cases and the ports they depend on. |
src/Orihon.Infrastructure |
Driven adapters. The only project that sees the vendored clients. |
src/Orihon.BlazorAdapter |
Primary UI adapter (Razor Class Library). |
src/Orihon.Server |
ASP.NET host + composition root. |
tests/* |
Unit, integration and component test projects. |
external/* |
Vendored libraries as git submodules (OpenRouter.Net, Kagaku.UI). |
Dependency direction: Kernel → Domain → UseCases → {Infrastructure, BlazorAdapter} → Server,
enforced by the project-reference graph.
Conventions
.slnxsolution format;Directory.Build.props+Directory.Packages.props(central package management).net10.0, nullable + implicit usings on, warnings-as-errors, deterministic, invariant globalization.- Versioning via MinVer (
v-prefixed tags). - CI on Forgejo Actions (
.github/workflows/); container image published togit.kagaku.eu/teamai/orihon.