Visual-maker SVGs never execute script, so a browser added nothing but a
process. resvg rasterizes in-process now (white background and fitTo
width mirror the old Chrome-page semantics; svgViewport unchanged,
quirks included for parity). The old Chrome path stays verbatim as the
fallback for exotic-SVG parse failures - it was the only path before,
so nothing regresses.
The resvg binary (4MB per platform, one per build) rides the standalone
via the same tracing pattern. Gates 1519/1519; native path pinned
against real SVGs (intrinsic size, viewBox-only 900 default, opts
override, system-font text).
The browser was never the PDF engine - pdfjs always painted the pages;
Chrome only hosted the canvas tab. Now pdfjs-dist v6's own Node
integration (@napi-rs/canvas, its optionalDependency) hosts in-process:
same paint code, Skia canvas, zero browsers, zero temp files, no base64
hop. The whole pdf-reader runs browser-free - the Chrome gate on
pdf_render is gone.
The Skia binary (27MB per platform, exactly one per build - npm installs
only the building machine's) rides the standalone via the same
outputFileTracingIncludes pattern as pdfjs-dist. Verified: builds green
(1515), native render pinned against the real fixture (canonical
single-IDAT PNGs, dpi/72 arithmetic, page-range skipping), and the
canvas loads + paints from inside .next/standalone.
Stages 2-3 (resvg for SVG, the --browser-service demo helper) follow.
Live dispatch smoke against the Turbopack dev server (master's ask,
2026-09-19) caught two things unit tests cannot - they run unbundled:
- Bundling pdfjs-dist broke its node fake-worker: the chunk-relative
pdf.worker.mjs import 404s inside .next/dev/server/chunks. Fix:
serverExternalPackages + tracing includes for legacy/ + standard_fonts/
(next.config.ts - a clearly-marked seam, same precedent as bcdcd51; the
standalone output now ships the worker and font files, verified).
- Real-world PDFs warned about missing standardFontDataUrl (non-embedded
standard fonts silently fall back) and flooded the log with JBIG2
warnings on scanned files. Fix: standardFontsDir() + verbosity 0 in
both the node ops and the headless canvas shim.
Verified live end-to-end on GEB (802pp, text layer): teacher dispatch,
12-step read with vision renders, brief with accurate page citations,
wake turn folding the resolution (Chapter IX, pp. 268-270) into the
lesson. Scanned/DRM Polya correctly refuses to fabricate citations.
Learner source files, on the teacher's own terms (nothing auto-injects):
- read tool (src/agent/tools/read.ts): pi-read port — path/offset/limit,
2000-line/50KB truncation with use-offset continuation notices, image
files (jpg/png/gif/webp/bmp) returned as native image content parts
(new LhToolImageResult escape hatch in lh-tool.ts). Always-on in both
the prober and teacher registries (user-decided 2026-09).
- pdf-reader sub-agent (JobKind 'pdf', toggleable, ack-and-steer): triage
via pdf_info (pdfjs text layer: per-page text/image/math-density),
targeted pdf_extract, regex pdf_search (hits count as consultation),
and pdf_render — pages painted by pdfjs onto a canvas shim in headless
Chrome (the pdfium viewer doesn't paint headless), screenshot fed back
image-in-the-loop (visual-maker idiom, providerSafePng applied). The
unread-finish gate bounces a zero-consultation brief once. Teacher gets
a text brief with page citations only; renders never leave the loop.
- MODELS.pdfReader = qwen/qwen3.8-flash (user override 2026-09-19: the
look-at-renders workload wants the vision-proven model; catalog listed
glm-5.3-flash as image-capable but qwen is the known-good daily driver).
- UI: PdfCompleteBadge + PdfBriefCard (steer-card, job-card), dispatch
card + activity-dock kind entries (type-forced, flagged for UI review).
- Prompts: 'Learner source files' section in teacher/30-jobs.md; read
line in prober/10-probe-doctrine.md. Doctrine rides tool descriptions
per the self-contained-tools principle.