Skip to content

Voxint v0.32.0

Choose a tag to compare

@bengizmo bengizmo released this 02 Sep 05:55
· 30 commits to main since this release
555b9ed

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-decided display_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). /runs becomes 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-rotating refresh endpoint 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 viewer role: 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_write boolean for UI affordance hiding. CLI user create --role
    and user set-role accept viewer. Migration 0057 widens the DB CHECK
    constraint. Dark-shipped behind the existing console_users_enabled flag
    (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.
  • /jobs now redirects to the canonical /runs surface; 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#llm redirect 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_ENABLED dark-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 their data-props through 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) set color: var(--accent), overriding
    .cb-btn-primary's color: 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-layout grid 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-layout owns 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"). /login redirects 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).