Voxint v0.32.0
Voxint 0.32.0 ships the UX audit remediation epic (#369, seventeen slices), media library search and status filter (#380), a read-only viewer role (#363), the evidence pack and bundled quote export (#331, #281), and GPU resource awareness in the installer.
Images: ghcr.io/bengizmo/voxint:0.32.0 and the model-service images (CUDA, -cpu multi-arch, whisper -rocm), plus the optional voxint-llm and voxint-synthdetect images. Full changelog below.
Added
- Low-data rendering for project widgets (#385, UX audit S16). With the
one to ten recordings a new project actually has, the overview widgets
now pick a simpler shape instead of a near-empty chart: fewer than five
entities render as a ranked count list rather than same-length bars;
when there are fewer than three speakers or fewer than three
recordings, speaker coverage renders as a plain speaker list showing
each speaker's recording count and recording names; and recordings
that all fall on one day render a dated summary ("Trends appear once
recordings span more than one day") rather than a one-point trend
chart. The temporal payload carries a server-decideddisplay_mode,
so the page and the chart island share one threshold. The simpler
shapes hide nothing: every entity and speaker in them is listed and
linked, and truncated labels carry the full text as a tooltip. - Labelled navigation rail and one theme control (#384, UX audit S15).
The left rail now shows text labels next to its icons at desktop width
(wider than 1120px), collapses to the familiar icon-only rail with hover
tooltips between 800px and 1120px, and the narrow-screen disclosure
shows labels too instead of unlabelled icons. The theme switch
(System / Light / Dark) moves out of the top bar into the rail footer,
so it is in the same place on every page that has the rail, for
every user (the setup wizard has no rail, as before); the
Settings Appearance radios still mirror it. The Runs activity badge
stays attached to its icon at every width. - Media library search and status filter (#380). Server-side search
(case-insensitive substring over display name, source path, and folder
name) and a status filter (Needs review / Failed / Reviewed / All).
Search and filter compose with each other and with the existing sort
and view controls. An empty-result state with a Clear link replaces the
generic empty message when a filter is active. Row actions are now
state-dependent: Review (needs adjudication), Retry (failed), or Open
(everything else). The "File missing" chip is replaced with plain
language ("Original file not found") showing the expected path. - GPU resource awareness in the installer. VRAM-aware tier recommendation
with per-device compose targeting, interactive device selection,--gpu-check
diagnostics, and enhanced--hardware-dry-run. The installer now inventories
all NVIDIA and AMD GPUs, measures free VRAM, and recommends the compute tier
that fits. When a GPU is occupied (e.g. by a local LLM), the installer
explains why and defaults to CPU. - Runs canonical lifecycle surface (#381, part 1).
/runsbecomes the
canonical lifecycle view: four lifecycle tabs (Needs attention / Active /
Failed / All), title-first rows with the run ID demoted to a copyable
secondary, a collapsible filter bar (auto-opens when any filter is active,
power filters like transcript search and date range under "More filters"),
a one-line pipeline health summary linking to Settings Status, and
auxiliary jobs behind a closed disclosure. State-dependent row actions
(Review / Retry / View) and degraded-service banners carried over from
the Jobs page. - Grouped failures with bulk retry (#381, part 2). On the Failed tab,
runs with identical errors are grouped into a single row showing the
error label, count, and a "Retry all" button. The bulk retry endpoint
uses per-item CAS with savepoints for partial-failure safety, CSRF
protection, and a per-item result page. - Single-operator auto-claim (#374). When multi-user mode is off, the
editor and workbench auto-claim on mount, removing the manual "Claim for
editing" / "Claim for review" friction. The review queue hides the
"Claimed by" column. A non-rotatingrefreshendpoint replaces the
heartbeat's previous re-claim, so a stale tab receives 409 and drops to a
manual "Resume editing here" action with no two-tab heartbeat fight.
Visibility-aware: the heartbeat pauses while the tab is hidden and fires
an immediate refresh on re-visible. Multi-user behavior is unchanged. - Viewer role (#363). A new read-only
viewerrole: viewers can browse
transcripts, results, and exports but cannot submit media, adjudicate,
correct, annotate, or change any settings. Enforced server-side with a
blanket write gate on all mutation routes (console and API); the gate
allowlists only auth routes (login/logout). Template context exposes a
can_writeboolean for UI affordance hiding. CLIuser create --role
anduser set-roleacceptviewer. Migration 0057 widens the DB CHECK
constraint. Dark-shipped behind the existingconsole_users_enabledflag
(user management page only). - Evidence pack (#331, Phase 7 remainder). A printable page of a run's
highlights with their provenance (speakers, timing, tags, notes, source
text hash, clip references, pipeline model identity), linked from the
review transcript. Print or save it as a PDF from the browser; no PDF
library added. Stale highlights print with a visible warning instead of
blocking the document. - Bundled quote export (#281). One click downloads a highlight's Markdown
pull-quote, JSON provenance manifest, and audio clip (when one has been
extracted) as a single ZIP, per highlight or for every highlight matching
the current tag filter. The bundled files match the standalone exports
byte for byte (the manifest differs only in its export timestamp). No new
dependencies (stdlib zipfile). - Highlight tag rollup on Explore (#331, Phase 7 remainder). The Explore
page now shows how many highlights carry each tag, corpus-wide or narrowed
by the project filter. Computed live with one SQL query (no cache, no new
dependencies); archived tags and deleted highlights are excluded, and
highlights on runs still under review count from the moment they exist.
Changed
- Queue, speakers, explore polish (#383). Review queue rows show the
folder name instead of the raw file path. Confidence scores throughout
the review workbench are humanized to bands (likely / possible / low)
instead of raw decimals. Speakers page: unnamed voices are listed first
and expanded by default. Profile fields are editable inline (blank + Save
clears). Speaker insights poll automatically when computing (bounded,
with backoff). Explore empty state shows example searches and a
capability hint. /jobsnow redirects to the canonical/runssurface; old bookmarks and
links continue to work (#382)- Settings control model (#379). Every tri-state feature setting
(On / Off / Use installation setting) is now a toggle switch showing
the effective state. Overridden settings show a "Changed" badge and a
"Reset to default" affordance. Each settings tab has one Save button
instead of one per section. Feature dependencies are enforced by
disabling the dependent switch with an inline reason, not prose
notices. The LLM checkbox is restyled as a visual switch (no
inheritance; the underlying model is unchanged). The three persisted
states (on / off / inherit) are preserved on the wire; saving without
changes never converts an inherited flag to a pinned override (save
idempotency). - Settings IA: tabs (#378). The settings hub is split into tabbed
sub-pages: General (appearance, features, tutorial), Media (folders,
sources), and AI (LLM, translation, corrections, glossary, semantic
search). All five existing sub-pages (Status, Hardware, Database,
Plugins, Users) now share a single tab strip include instead of
duplicating it. Old fragment links like/settings#llmredirect to
the correct tab. All POST routes unchanged. The legacy flat page
(flag off) is unaffected. - Run detail restructure (#377). The run detail page (shared by
/runs
and/jobs) puts the summary card first (status, readable stage name,
error with recovery hint, and the primary action). The Manage card moves
up, right after notices. Technical details (source path, revision, pipeline
models, glossary, detected language, stage ledger) fold into a collapsed
section. Speaker timeline shows readable durations. "Restart from scratch"
becomes "Run again from the beginning". - Error normalization (#376). Raw pipeline error strings are replaced with
plain-language labels and recovery hints across all operator surfaces (home,
editor, run detail, jobs). The original error is preserved in a collapsible
details fold. The home Recent feed groups consecutive identical failures
into one row with a count. New patterns: GPU memory, GPU errors, deferred
stages, paused runs. - Editor content reorder (#375). The outline panel (topics and entities)
moves below the transcript and starts collapsed with a count badge, putting
the work surface first. Transcript rows show one speaker display name
instead of duplicating the raw diarization label and display name. The
export section collapses into a single "Download transcript" button with a
compact format picker (reviewed text default; other variants in a nested
disclosure). The breadcrumb shows run status instead of duplicating the
live progress counter. A new Run card shows status, error, and
Retry/Re-run actions directly on the editor page. - Type foundation (#373). Base font raised from 13px to 15px for reading
surfaces; grid-tables and HTML tables use a new dense token (13px) so they
keep their compact density.
Removed
CONSOLE_JOBS_ENABLEDdark-ship flag; the sidebar Jobs entry now always
points at/runs(#382)
Fixed
- Three review-console islands never hydrated (found by #385). The
speaker timeline on run detail, the temporal trends chart, and the
project quote board wrote theirdata-propsthrough a double-quoted
attribute with a quote-replacing filter, which autoescaping encoded a
second time; the browser handed the island literal"text and
JSON parsing failed silently behind the server-rendered fallback. All
three now use the single-quoted attribute the other islands use, and a
contract test pins the pattern. - Queue progress strikethrough (#372). The review queue's "N of M
resolved" label appeared struck-through because the progress column
(10rem) was too narrow for the track (min-width: 8rem) plus the
label text; the overflow caused the track to visually interfere with
adjacent text. Widened the column to 14rem. - Invisible "Set up" button on Status page (#372). The primary
action button next to "Your own AI endpoint" rendered as a solid teal
rectangle with no visible text. Cause:.component-row .cr-action a
(specificity 0,2,1) setcolor: var(--accent), overriding
.cb-btn-primary'scolor: var(--accent-contrast)(0,1,0). Fixed
with a:not(.cb-btn)guard on the action link rule. - Editor speaker-rail collapse (#370). The media-editor page nested the
island's.me-layoutgrid inside.lib-two-col, causing the speaker rail
to collapse to a sliver at desktop widths. Restructured: metadata cards
(media info, run chooser) now sit in a horizontal bar above the island,
and.me-layoutowns the full page width. The stacking breakpoint drops
from 72rem to 48rem since the grid is no longer width-constrained by an
outer grid. - Contradictory empty-state copy (#370). "No runs for this media file
yet." appeared alongside listed failed runs. Now reads "No completed runs
yet." when runs exist but none completed. - Copy and behavior bug batch (#371). Explore header now pluralizes
correctly ("1 hour" not "1 hours")./loginredirects to/with a 302
when multi-user mode is off (was a raw 404). Backups copy on the Database
settings page now mentions the native launcher's backup command alongside
pg_dump. Database largest-tables estimates suppress zero-row entries
(Postgres stats lag makes those misleading).