{% extends "base.html" %} {% block title %}Voxint — run {{ run.id.hex[:8] }}{% endblock %} {% block body %}

← runs

Run {{ run.id.hex[:8] }}

{% if sidecar_title %} {# The sidecar title (issue #104) is operator intent, shown as the run's display name; the raw path below stays visible as ground truth. #}

{{ sidecar_title }}

{% endif %}

{{ run.media_item.source_path }}

{% if provenance %} {# URL runs only: the acquisition source, shown as a bare host — never the raw source_url, whose query could carry a signed token. #}

Source: {{ provenance }}

{% endif %} {# Gate on the live status too: a bookmarked/refreshed ?enqueue=deferred URL must not keep asserting "is queued" after the sweep already republished it. #} {% if enqueue_deferred and run.status == "queued" %}

The initial enqueue was deferred because the task broker was unavailable. This run is queued and will start automatically once the broker recovers — no action needed.

{% endif %} {% if media_delete_result %}

Deleted {{ media_delete_result.files }} derived audio file{{ "" if media_delete_result.files == 1 else "s" }}{% if media_delete_result.missing %} ({{ media_delete_result.missing }} already gone){% endif %}{% if media_delete_result.failed %}, {{ media_delete_result.failed }} could not be removed and will be swept later{% endif %}. The original source recording was kept.

{% endif %} {% if run_archived %}

This run is archived — hidden from the runs list and the review queue. All its data is intact; un-archive to restore it.

{% endif %}
Status
{{ run.status }} {% if run_archived %}archived{% endif %}
Current stage
{{ run.current_stage or "—" }}
Revision
{{ run.revision }}
Created
{{ run.created_at.strftime("%Y-%m-%d %H:%M:%S") }}
Updated
{{ run.updated_at.strftime("%Y-%m-%d %H:%M:%S") }}
{% if run.error %}

{{ run.error }}

{% endif %} {% if run.status == "failed" %}
{# Carry the revision we rendered so a stale tab's requeue 409s (exact-revision CAS). #} Retries the failed stage ({{ run.current_stage or "—" }}).
{% if run.current_stage in ("transcribe", "diarize_embed") %} {# Static guidance only — no live probe on this page (a health check here would add model-service latency to every failed-run view and flap with service health; the setup wizard's SERVICES step owns live reachability). #}

This stage needs the model services (ASR / diarizer / embedder). If they aren't running, start a compute tier — docker compose -f compose.yaml -f compose.gpu.yaml up -d (NVIDIA GPU) or docker compose -f compose.yaml -f compose.cpu.yaml up -d (no GPU) — wait for them to come up, then requeue. The shipped models run offline; an HF_TOKEN is only needed if you overrode diarization to a gated pipeline.

{% endif %} {% endif %} {% if run.status in ("queued", "running", "awaiting_adjudication") %}
{# Carry the rendered revision so a stale tab's cancel 409s (exact-revision CAS). #} {% if run.status == "running" %} Stops the run. The stage now running ({{ run.current_stage or "—" }}) finishes first — cancel is cooperative, not an immediate kill — then no further stages start. Media and any partial results are left in place (delete is separate). {% else %} Stops the run; no further stages will run. Media is left in place (delete is separate). {% endif %}
{% endif %}

{% if audio_available %}Audio{% endif %} {% if transcript_available %}Transcript{% endif %} {% if run.status == "completed" %}Review{% endif %} Complete run archive (JSON) {% if transcript_available %}(transcript & subtitle exports are on the Transcript page){% endif %} {% if media_reclaimed_at %} Media reclaimed on {{ media_reclaimed_at.strftime("%Y-%m-%d") }} (transcript and decisions kept; re-run from source to restore audio). {% elif not audio_available and not transcript_available %} No audio or transcript yet. {% endif %}

{% if run_terminal %} {# Archive / un-archive + derived-media deletion (issue #5). Only terminal runs (completed / failed / cancelled) — a live run must be cancelled first. #}

Manage

{% if run_archived %}
Restores this run to the runs list and review queue.
{% else %}
Hides this run from the runs list and review queue. Keeps all its data; reversible.
{% endif %}
Frees disk by removing this run's preprocessed and chunked audio. Irreversible; the original source recording is kept.
{% endif %} {% if source_metadata %} {# Scraped acquisition context (issue #36) — write-once, shown apart from the operator's own notes so human and scraped input are never conflated. The URLs here are sanitized allowlist values (absolute http(s), no userinfo), unlike the raw source_url, which never reaches a template. #}

Source metadata

{% if source_metadata.title %}
Title
{{ source_metadata.title }}
{% endif %} {% if source_metadata.uploader or source_metadata.channel %}
Uploader
{{ source_metadata.uploader or source_metadata.channel }} {% if source_metadata.channel and source_metadata.uploader and source_metadata.channel != source_metadata.uploader %} · {{ source_metadata.channel }} {% endif %} {% if source_metadata.channel_url %} · channel {% endif %}
{% endif %} {% if source_metadata.upload_date %}
Uploaded
{{ source_metadata.upload_date.isoformat() }}
{% endif %} {% if source_metadata.duration_seconds %}
Claimed duration
{{ "%d:%02d" | format(source_metadata.duration_seconds // 60, source_metadata.duration_seconds % 60) }} (source-reported, not measured)
{% endif %} {% if source_metadata.tags %}
Tags
{{ source_metadata.tags | join(", ") }}
{% endif %} {% if source_metadata.canonical_url %}
Page
{{ source_metadata.canonical_url }}
{% endif %} {% if source_metadata.extractor %}
Extractor
{{ source_metadata.extractor }}{% if source_metadata.extractor_version %} (yt-dlp {{ source_metadata.extractor_version }}){% endif %}
{% endif %}
{% if source_metadata.description %}
Description

{{ source_metadata.description }}

{% endif %}
{% endif %}

Operator notes

{% include "fragments/run_assets.html" %}

Pipeline models

The model each stage saw just before it ran. This is observed immediately before the attempt, not read back from the output, so it records which model answered rather than proving the exact build.

{% for stage in model_provenance %}

{{ stage.label }}{% if stage.recorded and stage.attempt and stage.attempt > 1 %} (from attempt {{ stage.attempt }}){% endif %}

{% if not stage.recorded %}

Not recorded. This run finished before model provenance was added, no attempt of this stage completed, or the latest completed attempt did not record it.

{% else %}
{% for role in stage.roles %}
{{ role.label }}
{% if role.reachable %}
{% if role.model %}{{ role.model }}{% else %}no model name reported{% endif %} {% if role.engine %} engine {{ role.engine }}{% endif %} {% if role.revision %}
revision {{ role.revision }}{% endif %} {% if role.decode_config_hash %}
decode config {{ role.decode_config_hash[:12] }}{% endif %}
{% else %}
Not observed{% if role.detail %} ({{ role.detail }} when the stage ran){% endif %}.
{% endif %} {% endfor %}
{% endif %}
{% endfor %}
{# Glossary provenance (issue #123): the exact vocabulary hint whisper decoded this run with, the operator's glossary unioned with the pack's words. Read-only; NULL means the run had no vocabulary or predates this record. #}

Glossary applied

The vocabulary hint transcription saw for this run, the terms from your glossary and the run's domain pack. It records what the model was told to expect, not that every term was spelled this way.

{% if run.initial_prompt %}

{{ run.initial_prompt }}

{% else %}

Not recorded. This run has not been transcribed yet, had no vocabulary, or it finished before Voxint began recording the applied glossary.

{% endif %}
{# Detected language (issue #124): what whisper decided when it transcribed this run. The score is whisper's own detection probability, shown with honest framing: it is not a calibrated confidence and says nothing about a recording that switches languages mid-way. #}

Detected language

{% if run.detected_language %}

{{ language_label(run.detected_language) }}

{% if run.detected_language_probability is not none %}

Whisper language-detection score: {{ "%.2f" | format(run.detected_language_probability) }}. This is the model's own score for its language guess, not a measure of transcript accuracy. It reflects the whole recording as one language; a recording that mixes languages still gets a single detected language. Short or mostly silent recordings can produce low or arbitrary detections.

{% else %}

No detection score was recorded for this run.

{% endif %} {% else %}

Not recorded. This run has not been transcribed yet, or it finished before Voxint began recording the detected language.

{% endif %}

Stage ledger

{% if not stage_runs %}

No stage attempts recorded yet.

{% else %}
{% for s in stage_runs %} {% endfor %}
StageAttemptStatusWorker StartedFinishedLease expiresError
{{ s.stage }} {{ s.attempt }} {{ s.status }} {{ s.worker_id or "—" }} {{ s.started_at.strftime("%Y-%m-%d %H:%M:%S") if s.started_at else "—" }} {{ s.finished_at.strftime("%Y-%m-%d %H:%M:%S") if s.finished_at else "—" }} {{ s.lease_expires_at.strftime("%Y-%m-%d %H:%M:%S") if s.lease_expires_at else "—" }} {% if s.error %}{{ s.error }}{% else %}—{% endif %}
{% endif %}
{% endblock %}