Repository navigation
hyperframes check: flag text drawn in a fallback face (VA-3327) - #7330
Closed
jerrai-bot-heygen wants to merge 2 commits into
Closed
jerrai-bot-heygen wants to merge 2 commits into
jerrai-bot-heygen wants to merge 2 commits into
Conversation
Adds a fonts section to hyperframes check. For each element with text, Chrome's CSS.getPlatformFontsForNode says which faces drew it; any face other than the declared first family is a text_in_fallback_face error. Jerrai
Contributor
Fallow audit reportQuality gate failed Found 2 findings. Dead code (2)
Generated by fallow.
|
Contributor
Edit accuracy: accurate 267 (base branch 267), smooth 119 of thoseThe gate passes. Quarantined, measured but not gated (8)
Unstable (1)
|
…bounds its cost Jerrai
SanHsien
added a commit
to SanHsien/hyperframes
that referenced
this pull request
Nov 6, 2026
…, record duplicate rule Review PR heygen-com#7304-heygen-com#7335: 10 merged already adopted or deferred; 10 open or draft PRs pinned (heygen-com#7304, heygen-com#7308, heygen-com#7311, heygen-com#7315, heygen-com#7321, heygen-com#7330-heygen-com#7334); open duplicates of pinned heygen-com#7281/heygen-com#7285/heygen-com#7286/heygen-com#7296 are tracked by those pins. strict exit 0; monitored 110 -> 120. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Co-Authored-By: Claude Opus 5.5 <[email protected]>
Contributor
Author
|
Closing for now; the branch stays. VA-3327 itself was fixed by the 32 MB install_font cap in EF #66451. This glyph-coverage check was the optional third item, its CI is red and Magi's review fixes are still open, and nobody will pick it up this week. It can come back as a new PR from this branch. — Jerrai |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A composition set Korean text in IBM Plex Mono, which has no Hangul. Chrome quietly drew it in a system fallback face, and
hyperframes checksaid nothing. VA-3327 asks for a check that flags any text drawn in a face other than the declared one, whatever the script or cause.Design
hyperframes checkgets afontssection beside layout, contrast and craft.CSS.getPlatformFontsForNode, on the same Puppeteer page the other sections use (page.createCDPSession()).font-family. System faces are matched by family name. Chrome reports a webfont by the file's internal name, which can be unrelated to the CSS name, so a custom face counts as the declared one when the declared family is a loaded@font-face.text_in_fallback_facefinding per element, graded by outcome: error when the declared face drew none of the run's characters (the whole run fell back, the VA-3327 case), warning for a partial fallback. A repeated element and cause across seeks merges, keeping the worse severity.sans-serif,monospace,system-ui,-apple-system,BlinkMacSystemFont, ...) as the first family name no face, so they are skipped.Extended_Pictographic,Emoji_Presentation,\p{S}, plus ZWJ, variation selectors and keycap), so "Launch day 🚀" in Inter is clean.OS_SUBSTITUTES): Liberation Sans for Arial/Helvetica, Liberation Serif for Times New Roman/Times, Liberation Mono for Courier New/Courier,.SF NSfor the SF names. Core OS substitutes only, no per-language entries.isDeclaredFacedocuments this).unicode-rangegap all show up the same way.times.Code:
packages/cli/src/utils/checkFonts.ts(new), wired throughcheckBrowser.ts(drivercollectFontFallback),checkPipeline.ts(auditFonts, report section, error count, finding crops),checkTypes.ts,checkFailureCodes.ts, and aFontsblock in the human report.Report shape
report.fontsis a normal section (ok,errorCount,warningCount,infoCount,findings). A finding:{ "code": "text_in_fallback_face", "severity": "error", "selector": "#caption", "text": "한국어", "declaredFamily": "IBM Plex Mono", "usedFamily": "Noto Sans CJK KR", "glyphCount": 3, "message": "Text in #caption is declared in \"IBM Plex Mono\" but 3 glyph(s) were drawn in \"Noto Sans CJK KR\".", "fixHint": "Load a face for \"IBM Plex Mono\" that covers these characters, or declare a family that does.", "sourceFile": "index.html", "bbox": { "x": 0, "y": 32, "width": 800, "height": 46 }, "time": 0.5, "times": [0.5, 1] }Cost
Measured with
collectFontFallbackon repo composition blocks in headless Chromium on this box, 3 consecutive seeks (ms each, text-bearing elements in brackets):A clean film costs tens of milliseconds for all 3 seeks. The cost is the per-character probe, paid only where a foreign face shows up, so the worst case is a film whose declared webfont is missing. Before the changes below that case took 2.4 s per seek (ui-3d-reveal, 118 flagged elements). Now: element-level reads are pipelined, per-character probes are batched per element and cached per computed font, and flagged elements are capped at 30 per seek, so the worst case is about 0.5 s per seek (about 1.5 s for the 3 seeks). A film with more than 30 affected elements reports the first 30, which already says the font is wrong.
Known limit
If the box has no fallback face for a script at all, Chrome draws the missing glyph as a notdef box in the declared face and reports the declared face. That case is not a fallback, so this check does not see it. The fixture therefore uses a
unicode-rangegap, which gives a real fallback on any machine.Tests
checkFonts.chromium.test.ts(real Chromium, 11 tests): a webfont declared for capitals only.ABC xyzis a partial fallback, a warning namingxyzand the fallback face.xyz xyzis a whole-run fallback, an error. An emoji-only run, and capitals with emoji and symbols, are not flagged. A-apple-system, BlinkMacSystemFontstack is not flagged. Fully covered text, a generic first family and hidden text are not flagged.isDeclaredFacetakes the OS substitutes and a later webfont in the stack, and rejects a wrong substitute.runAuditGridthroughcreatePageDriverfillsfontFindings.check.test.ts,checkPipeline*,checkBrowser.test.tssuites pass with the new section (fixtures gainfonts/fontFamily/ a stub CDP session).tsc --noEmitshows no errors in the touched files, andoxlint/oxfmtare clean on them.Follow-up outside this PR
The
hyperframes-cliskill line listing the--jsonenvelope sections (skills/hyperframes-cli/references/lint-validate-inspect.md) and its mirrors do not mentionfontsyet; left out to keep the mirror check untouched. Say if you want it here.On the experiment-framework side,
hf_check/pipeline.pypasses afontssection through unchanged (its stages read any member with afindingslist). One small EF follow-up is needed so the turn-end report path keeps it: add"fonts"toBROWSER_SECTIONSincutroom/agent/plugins/dsh/hf_check/turn.py.— Jerrai