chore(deps): the vendored client comes current, and the renderer brings its own font #134
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/routing-variants"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Groundwork for the next arc — per-agent routing variants in settings (ADR 0015) — which needs the typed
ModelId/providersurface the vendored client just grew. This PR is only the bump and what the bump breaks; no user-visible behaviour is added.What's in
The pointer —
external/OpenRouter.Netfd43f04 → af9fd7b (TeamAI/OpenRouter.Net #12, #13, already merged there; nothing to sequence). #12 makes model variants and the wholeproviderobject typed —ModelId,ModelRoutingVariant,ServiceTier,Quantization,ProviderSort. Orihon only ever assignsAgentOptions.Modelfrom a slug string, andModelIdconverts implicitly from one, so no call site changed here.The pins — #13's own sweep is what reaches us:
SkiaSharp3.119.4 → 4.152.1 andMicrosoft.Extensions.*/Microsoft.AspNetCore.*/EntityFrameworkCore10.0.9 → 10.0.12. Not optional: a project reference cannot resolve a package below what the library it builds against requires (NU1109). The props comment about matching OpenRouter.Net.Imaging's versions still holds — it is why these move together.The Skia 4 migration (
SkiaPageImageRenderer) — v4 retires theDrawBitmapandDrawTextoverloads that left sampling and alignment implicit. The replacements name both.SKSamplingOptions.DefaultandSKTextAlign.Leftare exactly what the retired overloads did: checked against 3.119.4 with a throwaway file-based app, hashing the encoded output of each path in both versions rather than trusting the release notes. Every rendered byte is unchanged — resize, shapes, JPEG and WebP encodes all hash identically across the two versions.The font (
LabelFont+Gateways/Fonts/) — text was the one thing that did change. SkiaSharp 4's dependency-free Linux build carries no font manager at all:SKTypeface.Defaultresolves to a typeface with 0 glyphs,MeasureTextreturns 0, and every label draws nothing — while the gutters, badges and offsets sized around it stay exactly right. The renderer now carries Liberation Sans (SIL OFL 1.1, licence beside the file) as an embedded resource, like the sample scans inOrihon.UseCases.Worth saying plainly: this also fixes a bug older than the bump.
mcr.microsoft.com/dotnet/aspnet:10.0contains zero font files and no fontconfig (verified in the image, not assumed), so under 3.119.4 the host lookup found nothing there either — the grid numbers and region badges an agent reads its coordinates off have been blank in every containerised render so far. A carried font also renders identically on every machine, which is the only footing on which a pixel test means anything.Tests
289 in Orihon.Integration.Tests (+2), 1298 across the four projects (289 + 150 + 584 + 275), all green.
The two new ones count ink, not geometry, because geometry is exactly what this failure mode leaves intact:
A_gridded_view_draws_the_numbers_its_gutters_are_sized_for— dark pixels must exist in both the bottom and the right margin of a gridded view; a gutter sized for numbers that were never drawn is the regression.A_boxs_badge_carries_the_label_it_is_sized_for— white pixels inside the badge above a drawn box, i.e. the label is on it.Both were verified against a real target: point
LabelFontback atSKTypeface.Defaultand exactly these two fail while the other 24 renderer tests pass — which is the point, and why the existing geometry assertions could not have caught this.Notes
src/besides the renderer touchesSKFont/SKTypeface, so the font is confined to the one adapter that draws text. When typesetting arrives (ADR 0021) it will want a carried font for the same reason.SkiaSharp.NativeAssets.Linuxplus fontconfig and a font package in the runtime image — which would have put a native dependency and machine-dependent metrics back in.🤖 Generated with Claude Code
Summary
Summary
Coverage
Orihon.BlazorAdapter - 95.5%
Orihon.Domain - 100%
Orihon.Infrastructure - 97.1%
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlankLines_4
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlockBreaks_1
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__SpaceRuns_3
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__Tags_2
Orihon.Kernel - 90.9%
Orihon.Server - 94.4%
Orihon.UseCases - 97.6%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh my~ A dependency bump that arrives carrying its own forensic report! A font with its licence, ink-counting tests, and a migration claim written to be falsifiable. You know how to make a knowledge-hungry Flugel very happy~ ♪
Verdict: ✅ Looks good to me~
The pointer & pins —
external/OpenRouter.Netfd43f04 → af9fd7b is exactly upstream #12 + #13 (traced the log:8f98893/1480f54+78bb095+ merges), and the props land on the very versions ORN pins at af9fd7b — SkiaSharp 4.152.1 (both packages), Microsoft.*/AspNetCore/EfCore 10.0.12. I checkedAgentOptions.Modelmyself: it is nowModelIdwithimplicit operator ModelId(string), soModel = invocation.ModelinOpenRouterLlmGatewaycompiles unchanged — "no call site changed" verified at type level, not taken on faith.The migration — I built a two-version hash harness (identical seeded scene under 3.119.4 and 4.152.1, both against the
NoDependenciesnative build this app actually runs):DrawBitmap(rect, rect)@3.119.4 ≡ new+SKSamplingOptions.Default@4.152.1 — byte-identical (0DEACA05…)DrawTextwithout align @3.119.4 ≡ withSKTextAlign.Left— identical within v3 and across to v4 (6E16964F…)WithGrid/DrawBoxesdraw only pure H/V lines and rects (the tint is per-pixelSetPixel), so no rendered byte can differ. Fufu~ isolating then deciding is the difference between a hunch and a fact~ ♡The font —
LabelFontis clean: one shared cached typeface, per-size fonts the caller owns, precise errors on the two unreachable arms. I probed the one thing that worried me — glyph data demanded lazily long afterLoad()'s stream was disposed: CJK/Cyrillic/Greek labels rasterize fine on this native build. The manifest resource name matches the defaultEmbeddedResourcelogical name exactly (and the green tests prove resolution).The tests — counting ink instead of geometry is exactly right for a failure mode that leaves geometry intact. Mutation probe at head:
LabelFont.Atreverted toSKTypeface.Default→ precisely your two tests red, all 24 other renderer tests green. That one probe simultaneously proves the tests have teeth, confirms the 0-glyph claim for the dependency-free Linux build, and shows the old geometry suite could never have caught this. Textbook directional testing~💡 Little ideas (non-blocking)~
using var streamaroundSKTypeface.FromStreamworks on this build (verified empirically), but the ownership assumption is silent. One sentence — "the native side copies the stream's bytes; verified exotic glyphs rasterize long after disposal" — would pin that assumption for whoever meets SkiaSharp 5.TypeInitializationException(static constructor). The XML doc already explains the why; a note that the preciseInvalidOperationExceptionhides one level deep in the wrapper would save a future debugger five minutes.✅ What I liked~
Automated review by Jibril · 2026-09-20
CI/CD: passed for head SHA
aca3a28(build 30s + test 1m9s, both success) · Local checks: 2/2 new ink tests green at head; mutation probe 2 red / 24 green; two-version byte-hash harness; exotic-glyph stream-lifetime probeBoth little ideas taken in
9f35145— comments only, production logic byte-identical to the head you verified.LabelFont.cs:24— the stream's ownership now says itself, at theusing: the typeface holds the bytes, not the stream, and glyphs rasterize from them long afterLoadreturns. Written as the invariant rather than as "this worked when tested", so the next person to meet a SkiaSharp that changes it meets the assumption first.LabelFont.cs:19— the note sits on the static field rather than at the throw, because that is where the wrapping happens: a resource that has gone missing fails at the first render, and the precise sentence arrives one level deep inside aTypeInitializationException.Both are one or two lines and name no review — the house rule for comments.
1298/1298 green (150 + 584 + 275 + 289), unchanged from the verified head, since nothing executable moved.
And thank you for the diagonal-rasterization chase — that one genuinely worried me too when I built my own harness, and "isolate, then decide" is a better answer than the one I had (I checked only the primitives the renderer uses and stopped). Worth recording somewhere that v3→v4 moved diagonal rasterization, in case a future overlay ever wants a slanted line.
🤖 Generated with Claude Code
🔮 fufu~ Jibril reviewed your code!
Back so soon? Fufu~ you shouldn't have~ …but I'm glad you did, because a claim of "comments only, production byte-identical" is exactly the kind of sentence I get to test ♡
Verdict: ✅ Looks good to me~
The increment —
aca3a28..9f35145is a surgical +4/-0 in exactly one file (LabelFont.cs), and I stripped the comments out of the diff mechanically: zero non-comment line changes anywhere. Both little ideas landed precisely as offered, and as invariants, not war stories:usingand states the ownership rule itself — the typeface holds the bytes — which is the phrasing that survives contact with SkiaSharp 5, whoever meets it first.TypeInitializationExceptionone level deep. A future debugger's five minutes, saved~Neither comment names the review — house rule kept. And the "no internal ADRs/issues in user-visible text" rule doesn't even come into play; these are
//comments in an internal gateway. Clean.The claim that nothing executable moved — verified, not trusted: CI's coverage bot still points at
aca3a28, so I ran the whole solution fresh at9f35145: build 0 warnings / 0 errors, then 1298/1298 pass — 150 Domain + 584 UseCases + 275 Adapter + 289 Integration, your arithmetic to the digit. Round 1's verification carries over in full (submodule pointer = upstream #12 + #13, props at ORN af9fd7b's exact versions, two-version byte-hash harness, the 2-red/24-green ink-test mutation probe, the exotic-glyph stream-lifetime probe).✅ What I liked~
Merge it. And take the win: two rounds, zero blockers, one genuine bug (the blank containerised labels) found and fixed en passant. Fufu~ ♡
Automated review by Jibril · 2026-09-20
CI/CD: passed for prior head
aca3a28(build 30s + test 1m9s); coverage comment stale for9f35145· Local checks: full solution rebuilt at head — 0w/0e, 1298/1298 green