From ffc2d7d66443be338ba7674d787c286e0fb1f694 Mon Sep 17 00:00:00 2001 From: vicrodh <103399283+vicrodh@users.noreply.github.com> Date: Thu, 20 Aug 2026 21:15:10 -0600 Subject: [PATCH] =?UTF-8?q?build(qt):=20gate=20on=20a=20fifth=20audit=20?= =?UTF-8?q?=E2=80=94=20every=20icon=20name=20must=20have=20a=20baked=20svg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `QbzIcon` does not draw an SVG by path: it picks a pre-baked, per-tint copy out of `qml/assets/icons//`. A name with no bake renders NOTHING. The row keeps its 15px slot, the label sits where it always did, and no test, audit or compiler says a word. That is how three rows of the new Refresh menu shipped iconless through a clean build, 434 green tests and four green audits: `"icon": "server"` looked obvious and has no bake. It was caught by driving the app and LOOKING. The audit checks literal `name:` / `"icon":` assignments against the union of the tint directories, and it is deliberately a floor, not a ceiling: an icon chosen by expression is out of reach for a static pass, and a first draft that also flagged names absent from SOME tints produced ~90 findings, all noise — amber/green/orange/favorite are status tints that hold a handful of glyphs by design. An audit that cries wolf gets ignored, and then it protects nothing. Proven in both directions before landing: with "server" reintroduced it fails and names the file; without it, 101 names across 288 files pass. The tool itself lives in qbz-nix-docs (planning/tooling stays out of the repo). cc --- scripts/qt-run.sh | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scripts/qt-run.sh b/scripts/qt-run.sh index c049860ec..207bdf9ce 100755 --- a/scripts/qt-run.sh +++ b/scripts/qt-run.sh @@ -29,7 +29,7 @@ # ─── THE QML AUDITS RUN FIRST, BY DESIGN ──────────────────────────────────── # `cargo check` sees NOTHING of the QML: a missing component or a call to a # bridge member that does not exist compiles clean and throws when the user -# opens that view. The two static audits are ~1s and catch exactly that, so they +# opens that view. The five static audits are ~1s and catch exactly that, so they # run BEFORE the build — failing in one second beats failing after two minutes, # or worse, at the owner's smoke. NO_AUDIT=1 skips them. # @@ -38,7 +38,7 @@ # NORUN=1 ./scripts/qt-run.sh # build only, don't exec # TEST=1 ./scripts/qt-run.sh # also run `cargo test -p qbz-qt` # SMOKE=1 ./scripts/qt-run.sh # offscreen gate instead of the GUI -# NO_AUDIT=1 ./scripts/qt-run.sh # skip the two QML audits +# NO_AUDIT=1 ./scripts/qt-run.sh # skip the five QML audits # JOBS=4 ./scripts/qt-run.sh # cargo build jobs (default: auto) # MOLD=1 ./scripts/qt-run.sh # link with mold (forces a full rebuild) # FORCE=1 ./scripts/qt-run.sh # build even if another cargo/rustc is up @@ -146,7 +146,11 @@ if [[ "${NO_AUDIT:-0}" != 1 ]]; then # missing from build.rs is not in the QML MODULE, so it resolves fine on # disk, compiles nothing, and blanks a whole page at runtime with # " is not a type" (2026-08-20, the media-server panel). - for a in qml_resolution_audit.py qml_singleton_xref.py qml_eager_tab_audit.py qml_module_registration_audit.py; do + # qml_icon_bake_audit.py joined on 2026-08-20: QbzIcon draws PRE-BAKED + # per-tint svgs, so an icon name with no bake renders NOTHING — no error, + # no failing test, no complaint from the other four. Three menu rows + # shipped iconless through a green build before anyone looked at the menu. + for a in qml_resolution_audit.py qml_singleton_xref.py qml_eager_tab_audit.py qml_module_registration_audit.py qml_icon_bake_audit.py; do [[ -r "${AUDIT_DIR}/${a}" ]] || { warn "audit ${a} not found — skipped"; continue; } if ! python3 "${AUDIT_DIR}/${a}" "${audit_abs}"; then die "${a} FAILED — fix it before burning a build (QML resolves lazily; this is what cargo cannot tell you)."