Commit Graph
78 Commits
Author SHA1 Message Date
vicrodh 21e81a4b42 fix(ci): reject early exits in packaged Qt startup smokes
Observe process survival through the full smoke window, isolate profiles and the session bus, restore hidden SDKs and reap private process groups. Reuse the Qt log gate and retain smoke evidence on failures. Add subprocess regressions to the test-crates gate.

cx
2026-09-06 19:24:15 -06:00
vicrodh 8f2050d703 fix(sacd): support images with 2064-byte physical sectors
Detect sector layout from Master TOC signatures and strip physical framing while preserving logical addressing, bounds and file mutation checks. Add reader and scanner regressions with synchronized CI presence guards.

Verified full decoding of 53 tracks across five real images, seek and previous-reader comparisons, isolated release UI opening and scanning, and disc, DSD, library and Qt tests.

cx
2026-09-06 17:29:06 -06:00
vicrodh 0ce4e1fa04 fix(local): publish ephemeral sessions before requesting navigation
Publish the open sequence after the active session and its document on the Qt thread. Keep boot restore and metadata updates from requesting navigation.

cx
2026-09-06 15:21:26 -06:00
vicrodh f9578d042c fix(navigation): include local library tabs in history
Record the outgoing tab state and scroll before switching, restore same-view history entries, and route sidebar tab requests through the same path without duplicating the initial landing. Add shared CI and local regressions for source filtering and tab transitions.

cx
2026-09-06 14:34:41 -06:00
vicrodh 9c9424bd30 fix(startup): keep Qt from retrying an unresponsive session bus
Carry transport failure into Qt startup with a process-local fail-fast bus address. Preserve a responsive bus when remote forwarding fails, and retry the original session on the next launch. Add the silent-bus xcb release regression to the shared CI/local runtime gate.

cx
2026-09-06 12:13:34 -06:00
vicrodh 9fd9978be2 fix(windows): bundle and audit app-local MSVC runtime
Deploy the official x64 redistributable DLLs into the shared MSI/ZIP payload and reject missing, debug, incompatible or shadowed CRT imports. Smoke both deployed products with isolated profiles and record loaded Qt/CRT paths.

Validate with 14 PE fixtures, PowerShell parsing, actionlint and shellcheck. Native clean-Windows acceptance remains pending.

cx
2026-09-06 04:54:40 -06:00
vicrodh 6794e15257 fix(build): invalidate native objects when the Qt SDK changes
Fingerprint Qt SDK headers for C++ cache inputs and share bounded debug/release startup gates between local tooling and CI.

cx
2026-09-06 03:53:05 -06:00
vicrodh 39ba3282f5 fix(ci): eliminate test-crates build warnings
Correct dead platform declarations, stale rustdoc and test warnings; validate complete gettext headers. Install LLD in the Qt job and explicitly validate committed shader packs without rebaking them. Keep the independent shader bake gate and add three build-policy tests.

The full local gate passed 2398 workspace tests and 715 Qt tests, QML audits, shader baking and the isolated offscreen smoke without compiler, rustdoc or gettext warnings.

cx
2026-09-05 20:31:05 -06:00
vicrodh 9b3b52cf9c fix(qconnect): preserve controller state across renderer handoffs
Keep queue reads from starving controls without weakening real queue-write serialization. Restore official proto3 zero defaults and next/previous loop, shuffle and autoplay semantics.

Project controls from the active peer state and target exact upcoming queue occurrences without optimistic cursor changes or local playback fallback. Cover takeover, seek, mute, wire decoding and manual skip regressions in the CI gate.

cx
2026-09-05 18:37:07 -06:00
vicrodh 4bb4982312 feat(sacd): support raw and DST-compressed ISO playback
Parse resilient SACD images, decode DST, scan ISO releases into the local library, and keep explicit opens ephemeral.

Ship decoder notices across distribution formats and align DSD album filtering and version selection.

cx
2026-09-05 10:00:24 -06:00
vicrodh 0d1cdb5e89 feat(packaging): complete Linux release assets
cx
2026-09-04 09:06:02 -06:00
vicrodh 56059e6814 feat(packaging): add complete AUR package set
cx
2026-09-04 08:27:17 -06:00
vicrodh f833a5a401 fix(tooling): audit the active Qt tree by default
cx
2026-09-03 09:34:31 -06:00
vicrodh e235cd3e23 test: require the account-migration and portable-blacklist suites in the gate
Same shape as the listen-log presence check: the workspace run already
executes them; the counts keep a renamed module or a dropped cfg from
shrinking coverage without a trace. The workflow calls the script, so the
mirror stays exact; its header names the new check.

cc
2026-09-02 08:25:09 -06:00
vicrodh 1cb988954e fix(qt): rename on-prefixed QML properties and gate the pattern
A property named `on<Upper>` is filed as a signal handler as soon as a
sibling member `<upper>` exists: its initializer never binds, it sits at
the type default, and nothing warns. `PurchasesView.qml` declared
`onAlbums` next to `albums`, so the Albums tab bound `[]` once and never
re-evaluated, which blanked Purchases for every account with real
purchases. Reproduced standalone with the `qml` runtime: the identical
expression under another name reads `true`.

Rename it to `albumsTab` and the four other `on<Upper>` properties
(`collectionsTab`, `surfaceTint`, `accentFloor`, `litColor`) so the rule
can be exact, and add `qml_on_prefixed_property_audit.py` to the four
QML audit sites (qt-run, cargo-test, test-crates, qt-gate-windows).

cc
2026-09-01 23:40:33 -06:00
vicrodh 860f1ad67f ci(linux): the AppDir check no longer expects .DirIcon (appimagetool writes it)
cc
2026-08-28 21:10:49 -06:00
vicrodh 8f35809df7 ci(release): desktop-entry icon gate; Icon Composer app icon on macOS
Linux: scripts/packaging/desktop_entry_check.sh asserts the MPRIS
DesktopEntry constant against the recipes (nfpm basename + Icon=,
StartupWMClass, reverse-DNS basenames) and against the built deb/rpm/
AppDir. The AppDir's desktop file now carries the reverse-DNS basename
so an integrated AppImage resolves the media-widget icon too. This
invariant regressed more than once; it is a gate now, not a rename.

macOS: compile packaging/icons/QBZ.icon (Icon Composer, issue #712) with
Xcode 26's actool into Assets.car + CFBundleIconName=QBZ; icon.icns stays
as CFBundleIconFile for older macOS. The Intel leg moves to macos-26-intel
so both legs carry actool.

cc
2026-08-28 20:45:55 -06:00
vicrodh c17f932d6c test: require the listen_log suite in the gate
cargo-test.sh and test-crates.yml assert qbz-app::listen_log lists at
least 25 tests and passes, so a refactor that drops the module's tests
fails loudly instead of shrinking coverage. Bounded: the binary is
already built by the workspace run.

cc
2026-08-28 20:30:43 -06:00
vicrodh bf710fb7eb ci(qml): share qmllint gate across Linux and Windows
cx
2026-08-28 09:44:25 -06:00
vicrodh bc4e8e6d7a fix(ci): make Windows preflight executable
Teach qmllint about statically registered native QML types and enforce metadata parity. Pin release builds to the MSVC 2022 runner and force Cargo to use the Visual Studio linker instead of Git for Windows link.exe.

cx
2026-08-28 09:44:25 -06:00
vicrodh a712284306 ci: shader gate bakes with qsb >= 6.9 and mirrors build.rs's -b rule
The GLSL 1.20 variant must stay in plasma/ambient's packs: Qt's OpenGL
RHI selects 120/130/140 on desktop GL <= 3.1 and the renderer tier does
not exclude that hardware, so dropping it (the previous attempt) was a
regression for old GL — caught in review. qsb 6.8 cannot lower those
shaders' uint hash constants for 1.20 while 6.9+ can, and the committed
.qsb were baked with 6.11: the bake toolchain is therefore pinned apart
from the 6.8 runtime floor (vars.QT_VERSION_SHADERTOOLS, default 6.9.3).
The gate also passes -b only to vertex shaders without the no-batch
marker, exactly like build.rs.

cc
2026-08-27 11:11:50 -06:00
vicrodh 811f6e978c ci: test-crates uses all cores (jobs=2 was a Slint-era memory tier)
Measured cold on the 4-vCPU CI VM: CARGO_BUILD_JOBS=4 finishes the
workspace test in 392 s against 589 s at jobs=2, with a 2.7 GB peak on
a 10 GB guest. The throttle protected a 30 GB rustc that no longer
exists in this graph. Leave the job count to cargo in the workflow and
in scripts/cargo-test.sh alike; --no-fail-fast and the 20-minute limit
stay.

cc
2026-08-26 20:22:17 -06:00
vicrodh f53543d1a4 ci: isolate the offscreen boot (private bus, private XDG dirs)
The single-instance lock is a D-Bus well-known name, so on a developer
box with QBZ open the debug binary presented the running instance and
exited with one log line, failing the gate for the wrong reason. The
smoke now runs under dbus-run-session with its own XDG dirs — never the
developer's config or session — in the script and the workflow alike.

cc
2026-08-26 20:14:23 -06:00
vicrodh ce57551a71 ci: test-crates as a living gate with cargo-test.sh as its exact mirror
Per the 2026-08-26 rule: the workflow's test job runs scripts/cargo-test.sh
(CARGO_BUILD_JOBS=2, --no-fail-fast, 20-minute limit), the script
documents what --workspace covers now that the Slint crates are gone,
and QT=1 runs the Qt gates locally in the same order as the shader-gate
and qt-gate jobs: audits, shader bake, Slint-free graph, cargo test
-p qbz-qt, offscreen boot.

cc
2026-08-26 19:11:58 -06:00
vicrodh af8d373d2c ci: shader bake gate; audits find Qt's qmltypes; builds never re-bake
qml_resolution_audit hard-coded /usr/lib64/qt6/qml, so on a runner it
saw zero Qt types and reported every Rectangle as unresolved; it now
takes QBZ_QT_QML_DIR (authoritative), then QT_ROOT_DIR, then the distro
layouts, and fails loudly when none has plugins.qmltypes. test-crates
runs the audits after the Qt install, pointed at it.

build.rs re-bakes a shader only when its .frag is newer than its .qsb,
which makes a fresh checkout nondeterministic whenever qsb is on PATH.
Release and test builds now install Qt without qtshadertools, so the
committed .qsb ship as-is, and a new shader-gate job bakes every shader
to a temp dir with the pinned qsb using build.rs's own target lists
(read from the file, so they cannot drift). It is red today at 6.8.3:
plasma.frag's uint literals do not bake for the GLSL 120 target with
qsb 6.8 (6.9+ accept them) — that is the finding, not a false positive.

cc
2026-08-26 19:11:01 -06:00
vicrodh dd6527043b ci: only test-crates runs from pre-release; drop the Slint excludes
The Slint crates are gone from the workspace, so cargo-test.sh's four
--exclude flags were stale; qbz-qt is the only exclusion now (it is the
one crate that needs Qt, and the sole consumer of wayland-sys — the
reason the workspace test fails on a runner without libwayland-dev).
Release workflows write their caches from main only: nothing but
test-crates.yml is meant to run from pre-release.

cc
2026-08-26 19:11:01 -06:00
vicrodh 7bd5cb1ec6 scripts: aarch64 build scripts for the Qt binary
build-aarch64-linux.sh builds -p qbz-qt natively with the distro's Qt
(gated at >= 6.8, the tree's floor; Debian 13 / Ubuntu 25.04 / Fedora
41 qualify), installs rustup when absent, forces one rustc at a time on
<= 4 GB boxes, and runs the same offscreen smoke as CI. Its CROSS mode
is retired honestly: cxx-qt runs the target Qt's qmake during the
build, which cross-rs's Ubuntu 20.04 images cannot do. The qbzd script
and Cross.toml keep cross-compiling the daemon, with the Qt-free dep
set.

cc
2026-08-26 19:11:01 -06:00
vicrodh 077e5fd97e ci: qt gate in test-crates; ship the QML audits in the repo
The five static QML audits move from the docs checkout to
scripts/qml-audits so CI runs the same gate as scripts/qt-run.sh
(which now defaults to the in-repo copy). New qt-gate job: audits,
Slint-free graph check, cargo test -p qbz-qt, and an offscreen boot of
the debug binary that fails on any QML complaint. cargo-test.sh excludes
qbz-qt (it needs Qt) so the no-UI job stays cheap.

cc
2026-08-26 19:11:01 -06:00
vicrodh ffc2d7d664 build(qt): gate on a fifth audit — every icon name must have a baked svg
`QbzIcon` does not draw an SVG by path: it picks a pre-baked, per-tint copy
out of `qml/assets/icons/<tint>/`. 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
2026-08-20 21:15:10 -06:00
vicrodh 3cfce8a769 feat(qt): the media-server settings panel, driven and verified in the window
ONE component instantiated twice, because it is one form twice. Every
difference between the protocols is a property set at the call site, so
they are visible in one place instead of drifting across two files:
"Test" proves the address for Jellyfin and only "a Subsonic server
answered" for Subsonic (which has no credential-free endpoint), the
password is discarded for Jellyfin and kept for Subsonic (no session,
md5(password+salt) per request), and the sync cost is stated up front —
45.8 s per 4924 tracks against 0.81 s per 6678 — so a long sweep does not
read as a hang. The credential never leaves Rust; the panel gets
`hasCredential`.

Assets: the colour marks for cards, the monochrome ones for rows. Both
mono files arrived as BLACK ink and are invisible on a dark theme
untinted, so they were normalised to the #ffffff master ink and joined
`icon_tint_qt::MASTERS` — the port's only shader-free way to recolour an
SVG per theme. The Jellyfin colour asset had a white rounded-rect plate
behind the mark; it was stripped, because every other brand mark here is
transparent and a white tile beside them reads as a rendering bug.
Rendered with Qt itself and looked at before any of it was wired.

CAVEAT, recorded in SourceIcon: the Subsonic mark is NAVIDROME's logo,
and `subsonic` covers Gonic, Airsonic, Astiga and Ampache too. `ping`
reports the server's own type and it is already persisted, so branching
later is cheap — a known wrongness, not an unnoticed one.

THREE BUGS THAT ONLY THE RUNNING WINDOW COULD SHOW, all found by
driving it under Xvfb rather than by reading the log:

1. `MediaServerSettings is not a type` — a .qml missing from build.rs is
   not in the QML module. It resolves fine on disk, compiles nothing,
   and blanks the WHOLE settings page at runtime. All three existing
   audits passed. `qml_module_registration_audit.py` is the missing
   check and is now in the gate.
2. The toggle would not move. The panel reads its state from the
   settings DOCUMENT, unlike Plex's toggle which reads a bridge
   property, so every mutation has to republish it — connect, enable,
   disconnect and the end of a sweep now do.
3. Every Jellyfin album in the grid drew the LOCAL HARD-DRIVE badge:
   `local_rows::badge_source` had never been taught the two words and
   folded them into `_ => local`. Not cosmetic — that string is what the
   source chips filter on.

`play_single_from_source` also grew the arm it needed: a media-server row
from the recently-played rail has no library.db row to mint a LocalTrack
from, so it resolves through `registry.tracks_of` instead.

END TO END, from the UI, against the real server: toggle on -> type the
address -> Connect -> "jellyfin sync: 500/4924 ... 4924 saved, 0 pruned,
4924 cached" -> Local Library shows 461 albums with their covers and the
Jellyfin badge. The cached quality distribution is identical to what the
server reported in the original protocol sweep.

428/428.

cc
2026-08-20 10:57:28 -06:00
vicrodh 931cb06d38 feat(qt): ease the visualizers on the pulse, and make Plasma react
TWO FINDINGS, both of which falsified something that was being assumed.

FLUIDITY IS NOT FRAME RATE. Driven at QBZ_PULSE_MS=10 the shell presented ~100
frames/s — qt-batches confirmed it, and the script now prints the pulse it ran
with so two logs cannot be confused — and the bars looked exactly as they had at
30. They would: every published frame was applied as a STEP, so the extra
presents repainted the same discrete values three times over. What the Slint
build does differently is not rate, it is `animate bar-h { 90ms }` — it moves
BETWEEN values.

So the interpolation is back, ON THE PULSE, and it costs nothing. The old
interpolator was expensive because of its private 16 ms Timer, not because it
interpolated: it presented at its own rate, unsynchronised with everything else.
Easing on the pulse presents exactly as often as stepping on the pulse did — one
repaint per period either way, only the value differs. Self-parking survives: a
converged ease writes nothing and schedules no repaint. The price is lag, and it
is the honest one — k = 0.45 is ~83% there in three pulses (~100 ms), matching
the reference's 90 ms, against 46 ms of FFT window and 77 ms of Rust smoothing
already in the chain.

The from/to/progress triple is gone with it, and its consumers moved to `cur`.
Note for the next reader: `SpectrumBand` drove all three of its modes from
`Connections` on those properties, and a Connections handler naming a property
that no longer exists is NOT a compile error — QML warns at runtime and simply
never fires. That is how the whole band went dead at once; grep for
`on<Name>Changed` when removing a property, not only for direct reads.

PLASMA WAS DRIVEN BY THE SLOWEST SIGNALS IN THE PIPELINE while the fast ones
travelled beside it unconnected. `transientAmp`, `bandsLo` and `bandsHi` were
published, parsed and stored, and never handed to the item — the shader declared
them and received zeros — so everything ran off the energy bands, which decay
x0.85 per frame (~473 ms) against the bars' x0.65 (~178 ms).

Worse, `beat` stops being a beat on dense material: it decays x0.88 per tick, so
above ~3 hits/s it never falls far enough to come back as a spike and settles
into a shallow ripple around 0.7. A splat multiplied by it becomes a steady
glow, and the busier the music the flatter the picture — the most frenetic input
produced the least motion. `beatAc` subtracts a slow density floor, so a hit
reads as a hit at any tempo.

The scene itself was rebuilt around the reference the owner filmed (Butterchurn
on a percussion-heavy track). Its recipe is three parts: one thin annulus
injected per frame that the feedback warp marches inward, so the concentric
rings ARE the last N frames of audio laid out in space; retention high enough
for that to stack (this held 0.85, where a trail died in ~15 frames and nothing
ever accumulated); and angular structure from reading the spectrum BY ANGLE.

But a CLOSED ring was wrong, and the owner named why: a perfect inner
circumference reads as a drawn shape, hard-edges the field, and at this
retention successive rings pack into one solid disc — which is what killed the
ambient feel. The annulus is gated by angle now, so a hit paints arcs the
conveyor carries inward, the circle never closes, and the gaps stay open for the
background. Noise bends, frays and thins those arcs so they are made of plasma
rather than of compass.

The worms are back at full strength with tighter cores and a contrast curve — a
raw gaussian is all shoulder and reads as haze — and their orbits now reach past
the arc band instead of being trapped inside it. Colour comes from ONE
album-derived triad, so everything used to be a shade of the same hue; a
Rodrigues hue turn splits it into worms, arcs and an ambient wash that sit apart
whatever album is playing. That wash is what stops the background being void for
the foreground to be a cut-out against. A soft limiter replaces the hard clamp:
at 0.945 retention a clamp pins the middle to white and the structure vanishes.

Release build clean, offscreen smoke green, 421/421.

cc
2026-08-19 13:53:57 -06:00
vicrodh a6b373cb5a build(qt): fail the build on a tab body that is built while hidden
The class the previous commit fixed leaves no trace a reader would
notice: the view renders correctly, cargo is happy, both existing
audits pass, and the only symptom is that entering the section takes
seconds. So it needs a static gate or it comes back.

qml_eager_tab_audit.py reports a per-tab body gated only on `visible:`,
and reports it only when it is genuinely heavy — it must instantiate a
Repeater/ListView/GridView AND that view's model must be data rather
than an inline literal. Without the second condition it flagged the
sort popups in LibraryToolbar, which are Repeaters over four fixed
options, and three false positives would have buried the one real
finding.

cc
2026-08-17 17:49:22 -06:00
vicrodh b136c9cf5d feat(qt): ambient background port, clip sweep and measurement tooling
Accumulated qt-frontend work from the 2026-08-11/12 sessions (cc),
uncommitted until now: the app-wide dynamic background in both modes
(AmbientField with GPU/Canvas arms, AppShell layering, ambient palette
pipeline), the wave-1 clip/batch sweep across the tree (alpha batches
449 -> 327, reproducible), the rounded-cover and icon-tint arms, and
scripts/qt-batches.sh (batches + presents/s sampler).

The GPU behaviour of these pieces was finalized in the follow-up pulse
commits; see qbz-nix-docs/qt-frontend/2026-08-11-scenegraph-batches/
GPU-COST-INVESTIGATION.md for the full campaign.

km
2026-08-13 13:01:32 -06:00
vicrodh ce7f29ff9c chore(qt): ship the binary as qbz, and log the first MPRIS metadata push
The artifact is now `target/<profile>/qbz` (owner, 2026-08-04). The package
stays `qbz-qt`, so `cargo build -p qbz-qt` is unchanged.

⚠ `crates/qbz` — the Slint binary — declares the SAME bin name and shares
this workspace's target dir, so both write `target/<profile>/qbz` and the
last build wins. Survivable only because the Slint binary is never built in
this worktree (the qbz-ui 20-30 GB wall); if it ever is, a smoke against
"the wrong qbz" is silent. Written into Cargo.toml beside the name.

The MPRIS line exists because "Plasma sees nothing" has two very different
causes — the player never registered, or it registered and no metadata was
ever pushed — and the log could not tell them apart. It settled that
question the same day: the owner's log shows `[mpris] metadata pushed:
Holy Diver — Dio (350s)`, so the port's half works and what remains is
desktop-side.

cc
2026-08-04 11:23:07 -06:00
vicrodh ec8588687b feat(qt): artist page parity - load more, section sort, discography
The release-section "Load more" fetched a page and appended it to a structure
no view ever re-read. The handler pushed IN PLACE into the object behind
`readonly property var artist: JSON.parse(QbzArtist.artistJson)`, and the
releaseSections projection returned that same array on the unfiltered arm, so
both Repeaters were re-handed the identical reference and nothing was dirty.
The tree's own rule, written in cards/PlaylistCollage.qml: rebind requires a
NEW object reference. A second bug sat on the same path - the artist document
republishes progressively (stories, then each MusicBrainz section as it
resolves) and every republish re-runs the parse, wiping anything appended, so
fixing only the first would have left a bug that looks random. Both
pre-existing; the in-flight placeholder added earlier is what made an
always-silent no-op visible.

Appended pages now live in an overlay keyed by release type. It survives a
republish, emits new arrays so the Repeaters rebuild, dedupes by album id,
carries the reference's 4-page cap per bucket (artist.rs:718-720, which hands
off to the discography page beyond it), and is guarded against a page
requested on one artist landing on another's grid - releaseSectionReady
carries no artist id and every artist has an "album" bucket.

"See discography" was a pointer-cursor MouseArea with no onClicked under a
POC-NOTE saying the page was out of scope. ArtistReleasesView.qml +
artist_releases_qt.rs port ArtistReleasesView.slint: infinite scroll rather
than a button, plus the loading, error-with-retry, empty and offline arms.
The album page's "More from <artist>" view-all is a second door to the same
page. Its paging offset counts what the SERVER returned rather than the
rendered row count the reference uses: blacklist filtering and id dedupe make
the rendered count smaller, so the reference re-requests seen rows and skips
the tail whenever the blacklist is non-empty.

The per-section sort was a dimmed Rectangle with no MouseArea, under a
comment asserting no seam existed. It is now a real QbzSelect with the
reference's five options and index mapping, persisted per release type in
artist_prefs. Choosing "Default" after a sort does not restore the server
order until the page reloads - that is the reference's behaviour
(album_map.rs:262 is a bare no-op arm and resort sorts the live model), kept
deliberately rather than diverged.

Also, two visual fixes from the same round that share these files: Popular
Tracks drew its cover at radius 8 where the shared rows/TrackRow.qml uses 4,
and the album page's rail mounts said `width: parent.width` inside a Column
with 32px padding - QML padding shifts children without narrowing
parent.width, so the rails hung 32px off the right and the right page chevron
landed outside the window.

Carries scripts/qt-diag.sh, which has been sitting untracked since the
rendering round: it answers "which backend is this actually running on" from
a real graphical session, refusing ssh and refusing offscreen because either
would answer the wrong question. That refusal is the point - the doctrine it
disproved ("shader effects render nothing on this port's software path") came
from an offscreen observation, and offscreen forces software by definition.

cc
2026-08-02 16:34:58 -06:00
vicrodh 0c159c141c feat(qt): For You gains Qobuz Mixes pages, Artist Spotlight and Radios
Ports the three sections the tab was missing, against the Slint
implementation rather than invented: the section rails, the cards, and the
mix landing page with its navigation seam so back/forward behave.

The mixes reuse the shared crates for their requests -- the Slint app
already makes them, so nothing new talks to Qobuz here.

Also carries the qt-run.sh portability work needed for the Mac mini:
`free`, `nproc`, `pgrep` and `timeout` all differ or are simply absent on
BSD/macOS. Two of those bit during the first Mac build. `pgrep` exits 1
when it matches nothing -- the normal case -- and under `pipefail` that
killed the script before a single line of output, which reads exactly like
a build that did nothing. And `timeout` does not exist on macOS at all, so
the smoke produced a one-line log over which the grep cheerfully reported
"0 QML complaints": a test that never ran, rendering as a pass. The smoke
now fails outright on a log that short.

cc
2026-07-29 16:26:11 -06:00
vicrodh 82b88ee8e0 chore(qt): add scripts/qt-run.sh
The Qt-track sibling of slint-run.sh, and deliberately not a copy of it.

No memory tiering and no cgroup cap: qbz-qt does not depend on qbz-ui, so
the 20-30 GB compilation unit never enters this graph. That is the point
of the track.

No RUSTFLAGS and no +nightly either. This worktree's target dir was built
on stable with rustflags=[], and RUSTFLAGS is a fingerprint input, so
exporting mold would buy a from-scratch rebuild of the workspace to save
seconds on a two-minute incremental. MOLD=1 opts in and warns first.

The two QML audits run before the build, because cargo check sees nothing
of the QML: a missing component or a bridge member that does not exist
compiles clean and throws when the view opens. They take a second.

SMOKE=1 runs the track's offscreen gate; a guard refuses to start while
another cargo/rustc is alive, since one Slint build in a sibling worktree
is enough to freeze the box.

cc
2026-07-29 10:31:05 -06:00
vicrodh f1eeaf9126 feat(steam-deck): game mode support (plan PR1-PR5)
- PR1: gamescope detection at boot — X11 backend, scale 1, kiosk
  fullscreen; tray + miniplayer suppressed (click-offset fix).
- PR2: full keyboard navigation for the kiosk (3 zones, focus ring,
  scroll-into-view; typing never navigates).
- PR3: native gamepad via gilrs — D-pad/stick/A/B to synthetic Slint
  keys with hysteresis, repeat and debounce; B suppresses Escape while
  a text field is focused (closes the Steam OSK).
- PR4: Steam OSK via the steam://open/keyboard deeplink on text focus.
- PR5: scripts/qbz-add-to-steam (stdlib-only, 19/19 unit tests) with
  artwork assets + pure-gamepad controller layout.

Spec: qbz-nix-docs/steam-deck/STEAM_DECK_GAME_MODE_PLAN.md

km
2026-07-25 12:04:58 -06:00
vicrodh e822c21c8b chore(scripts): add aarch64 qbzd cross-build script
Docker/cross build of the slint-free daemon for the Pi streamer
(~90 s incremental, dist/qbzd-aarch64-linux); native path included for
aarch64 hosts.

km
2026-07-22 09:04:23 -06:00
vicrodh be3319245e chore(scripts): visual build progress in slint-run (start/ETA/ticker/final)
Learned per-tier ETA from the last successful build, a live elapsed/ETA/percent ticker while codegen is silent, and start/finish banners. Safe under zsh/oh-my-zsh (runs under bash, newline-terminated, TTY-gated colors). NO_TICKER=1 silences it.

cc
2026-07-20 18:29:04 -06:00
vicrodh ece9b1ebc6 fix(qbzd): confirmed-kill escalation in acceptance script stop path
cc
2026-07-14 21:41:41 -06:00
vicrodh f48fc6ceb8 test(qbzd): P0 acceptance script for exit codes, status contract and roundtrip
cc
2026-07-14 21:31:19 -06:00
vicrodh af1ccce398 chore(scripts): add prune-incremental.sh for stale incremental caches
Keeps only the most-recently-modified incremental-compilation dir per crate under crates/target and prunes the rest (slint-run.sh's per-RAM-tier RUSTFLAGS spawn a new hash dir each time; Cargo never GCs them). Release builds do not use incremental, so unaffected.

cc
2026-07-13 21:01:48 -06:00
Victor RH 9352a498a7 Merge pull request #574 from afonsojramos/ci/test-crates
ci: add test-crates workflow for workspace unit tests
2026-07-12 19:39:44 -06:00
vicrodh a9949b8cf2 chore: fix stale packaging and monitor references to the deleted tree
cc
2026-07-10 01:05:47 -06:00
vicrodh 39204a41ff chore(cleanup): remove legacy Tauri/vite dev scripts and legacy-tree-notice workflow
cc
2026-07-10 01:00:06 -06:00
Afonso Jorge Ramos 54da577d56 ci(test-crates): align workflow with release CI conventions
Match naming, permissions, concurrency, mold linker, and cache save-if
policy (write only from pre-release) used by the Slint release jobs.
2026-07-10 01:02:37 +02:00
Afonso Jorge Ramos 7a600a60f4 ci: add workspace cargo test job (exclude Slint UI graph)
Run unit/doc tests for the shipping crates workspace on PRs without
compiling qbz-ui. Fix three green-blockers: local playlist schema for
tests, Track.work fixture, and a stale ListenBrainz doctest.
2026-07-10 00:52:05 +02:00
vicrodh 72a9f52d06 chore: untrack prune-incremental.sh (swept in by accident)
The file was an untracked local script predating this session; a
directory-level git add pulled it into the #549 commit unintentionally.
Back to untracked, file kept on disk.

cc
2026-07-05 14:18:01 -06:00
vicrodh 395e537b59 fix(build): drop compile-time x86 target-features — runtime AES dispatch
Users on CPUs without AES-NI (Nehalem i7-860, pre-2010 Intel Macs) or
without SSSE3 (AMD Phenom II) crashed at launch with SIGILL. The
global `-C target-feature=+aes,+ssse3` was kept after the #353/#343
x86-64-v3 incident on the belief that the aes crate's cpufeatures
runtime check would protect CPUs without AES-NI — but a compile-time
target feature makes cpufeatures compile its check to a constant, so
the AES-NI intrinsics ran unconditionally (credentials AES-GCM decrypt
at startup), and +ssse3 let LLVM autovectorize anywhere, breaking
Phenom II. Measured on the qbz-cmaf hot path (Ctr128BE<Aes128>
apply_keystream, 256 MB, release): 2145 MB/s compiled-in vs 2162 MB/s
runtime-dispatched, identical output — the flags bought nothing on
capable CPUs. Removed from .cargo/config.toml, all dev/build scripts
and the release/build workflows; old CPUs now get the software AES
fallback instead of a crash.

Fixes #549

cc
2026-07-05 14:17:46 -06:00