Embed the selector engine in the standalone report viewer - #243
Merged
Conversation
The viewer shell shipped every line of UI Inspector code and no engine to run it, so "Inspect UI" opened a panel that could never show a selector suggestion. An exported report gets the engine from the Kotlin generator path; the shell is built by bun alone and had no equivalent step. A build-time macro now embeds the bundle through the same transport the report uses. build-viewer-shell.sh builds it on demand and takes --require-engine, which the docs deploy passes so a published viewer can't silently lose the feature.
This workflow publishes: it holds `pages: write` + `id-token: write` and deploys what it builds to the live site. A restored dependency cache in a publishing workflow is the cache-poisoning vector zizmor flags, and it would land on the very payload the JDK step exists to produce — the selector engine bundle embedded in the published viewer. build-desktop.yml and release.yml already take this posture; this was the only `cache:` left in any workflow. Cost is a cold compile of one small Kotlin/JS module per deploy.
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.
The UI Inspector's selector suggestions were unavailable in the standalone report viewer — the one the docs site publishes and anyone can self-host. The shell embeds every line of Inspector code (
Inspect UI,selectorSuggestion*, the#tb-selector-enginereader) but nothing ever embedded the engine for it to run, soloadSelectorEngineFromChunkreturned null and the panel opened with no suggestions. Silently: a null engine is a designed degrade path.Exported reports were never affected. There the Kotlin side supplies it —
RunReportGeneratorstages the JAR resource,run-report-cli.tspacks it into the chunk. The shell is built by bun alone, with no run baked in, and had no equivalent step.Verified on today's
docs-report-clockartifact — the exported report carries the payload and the published viewer does not:report-interactive.htmlThe fix
A bun macro reads the Kotlin/JS bundle at transpile time and
buildViewerShellHtmlembeds it as the same#tb-selector-enginechunk a report uses. The macro importspackSelectorEnginerather than re-implementing the transport, so the two homes can't drift.The shell embeds it unconditionally, unlike a report, which embeds it only when a session carries an analyzable hierarchy: the shell has no session at build time, any archive dropped later may need it, and an offline single-file viewer gets no second chance to fetch one.
Size: 416,116 → 531,155 bytes (+115 KB — gzip+base64 of the ~320 KB bundle, which always lands on the gz side of the threshold). The macro is replaced by its value at transpile time, so no driver code enters the bundle; the delta is the payload and its wrapper, nothing else.
Delivery.
build-viewer-shell.shbuilds the bundle on demand when./gradlewis present, so the default path produces a complete viewer. A JDK stays optional: without one you get today's viewer plus a warning naming the gradle task.--require-engineturns that warning into a failure, and the Pages deploy passes it — a missing engine is invisible in a rendered page, so this is the one payload worth failing a deploy over. That step needs a JVM, so the deploy gainssetup-java(JDK 17, gradle cache) used for nothing else.Test plan
TrailblazeSelectorEngineexposingresolveTapTarget/resolveSelector/computeSelectorAnalysis) and suggestions rendered:textRegex: ALARMmarked UNIQUE/BEST, plus the structural content-free suggestion--require-enginewith the bundle absent exits 1; without the flag exits 0 and emits a shell byte-identical to today's (416,116 bytes), so the degrade path is unchangedtsc --noEmitclean;bun test440 pass / 0 failpackSelectorEngine,readSelectorEngineSource,anyAnalyzableHierarchyall absent from the output)