Forced alignment is requested by Qwen word timing and by VibeVoice word timing. FireRed native word timing does not use this adapter. A successful processing run may preserve recognized text while abstaining from word timing; complete: true does not assert timing delivery.
alignment_unavailable retains the attempted source interval. New Qwen and VibeVoice results also include alignment with unit_id, segment_ids, code, and, when the rejection identifies one returned word, its zero-based word_index. The segment IDs refer to the same saved result. Qwen can produce several sentences from one unit, so segment_ids can identify several affected sentences. These are diagnostic associations; the interval is not a replacement for absent sentence or word timing. Historical results may omit alignment; do not infer a specific cause from that absence.
For out_of_unit_bounds, alignment.boundary records original_bounds, unit_bounds, start_overrun_ms, end_overrun_ms, and the effective max_overrun_ms. These values describe the returned estimate and the host's acceptance comparison, not an acoustic error measured against a reference. Other rejection causes and historical results do not acquire invented boundary measurements. Receipts expose alignment rejections and accepted corrections so the caller can inspect the next decision without deriving the host's limit from implementation code; the canonical result and retained raw response remain the detailed evidence.
alignment.code |
Observed normalization evidence |
|---|---|
provider_unavailable |
The stage explicitly returned words: null; inspect its response for any supplied exception. |
invalid_token |
A returned word is not an object with a nonempty lexical string token. |
invalid_bounds |
Bounds are missing, nonnumeric, nonfinite, or reversed, or the requested unit bounds are invalid. |
out_of_unit_bounds |
A returned word exceeds its input unit beyond the selected maximum overrun below. |
word_order |
A returned word starts before the previous word ends. |
text_mismatch |
VibeVoice's validated words do not reproduce its speech-segment text after punctuation and whitespace normalization. |
sentence_reconciliation |
Qwen's validated word stream cannot be partitioned into the recognized sentences without changing their text. |
The transport retains, for each finished JSON stage, the exact request.json and, if written, result.json beside its stdout.log and stderr.log in the announced private diagnostic directory. FluidAudio retains its structured result.json; it receives command-line arguments instead of a JSON request. Retention precedes JSON parsing and exit translation, so a malformed response or a provider failure remains inspectable. Missing responses stay absent. A retention error fails the command; it cannot silently discard evidence and declare successful delivery. These files contain recognized text and local paths and follow the same retention lifecycle as the existing raw logs. An interruption before the transport receives the completed process does not guarantee retention of structured files; already-written stdout/stderr follow the existing interruption contract.
Find the result's alignment.unit_id in the aligner's request.json and result.json, then inspect the returned word at word_index when present. The request gives the actual input interval/text; the response gives provider values and per-unit exceptions; the canonical alignment.code records the host's rejection. Lifecycle messages alone are not the structured response. Timed text/Markdown refusal identifies the affected canonical segment. If word timing already abstained, its remedy preserves untimed text and points to this evidence; it does not promise that replaying the same request will repair timing. Native VibeVoice segment timing can still support readable timestamps independently of word timing. SRT/VTT continue to refuse unbounded Qwen text even when its diagnostic segment link is known; the link does not authorize dropping recognized text.
The codes come from the alignment adapter, Qwen sentence reconciliation, and VibeVoice text reconciliation. The aligner stage writes per-unit provider exceptions to its structured response; the adapter does not infer them from a missing canonical word stream.
The alignment adapter keeps every accepted word inside its actual input unit, with finite, numeric, ordered bounds and a lexical token. The default maximum remains 0.501 ms, the existing serialization allowance for a start rounded just before the unit or an end rounded just after it. That allowance represents rounding to milliseconds, not model timestamp resolution. It does not grow with source duration, word length or backend grid spacing.
transcribe plan and transcribe run accept --alignment-max-overrun-ms as a finite number at least 0.501, only when the selected plan uses ForcedAligner. The executed value is recorded in provenance.plan.roles.aligner.config.max_overrun_ms. An explicit higher value authorizes clipping each returned endpoint to the unit boundary when its overrun is within that limit. It changes host acceptance, not model inference or the serialization allowance. Larger overruns still reject the unit's word stream and retain its recognized text. Invalid or reversed bounds, words wholly outside the unit, clipping that collapses a positive word, word order and text reconciliation remain separate checks; a larger boundary limit does not override them. A rejected stream is not published merely because some of its words fit the limit.
Accepted clips beyond the serialization allowance are recorded under provenance.observed.alignment_corrections. Each record links the unit, canonical segment and word to the original and applied bounds and selected limit. Read these records alongside the exact structured request/response and the recorded plan. A correction is an explicitly authorized host adjustment to a model estimate; it does not establish the correct acoustic endpoint. Absent word timing is never filled with a processing interval, and the host does not invent words or rewrite recognized text to obtain an export.
The caller may choose a higher limit or an alternative stack when the user's task authorizes that changed attempt. Re-plan the original source and required capabilities, retain every prior canonical result, and use fresh output and diagnostic destinations. The CLI never changes models automatically. In particular, Qwen and VibeVoice word timing share ForcedAligner, while FireRed supplies native words; a different recognizer alone is not evidence of a different timing mechanism. Observe the new result's outcomes, corrections and remaining abstentions before requesting native exports. Exit 1 remains a backend failure; an exit-0 capability abstention preserves a result but can still fail the requested delivery.
The recorded reproduction binds request SHA256 74639cc3d54d70933b9a2edb0a12a1f8b48d92cd6476baf297186e42da93f924 and response SHA256 9ae0ff981120072fff5f3e1825632f999562065fe93b1c9959543c02b794637f to the raw files retained under tests/artifacts/qwen-alignment-investigation-2026-09-06/. In that response, Qwen 1.7B unit turn_25 has text Like., input interval 96.570437–97.996625 seconds, and returned word Like at 96.570–98.010 seconds. Its start differs by 0.437 ms; its end exceeds the unit by 13.375 ms. The new diagnostic code for that unchanged response is out_of_unit_bounds, word index 0; its affected original segment is seg_27.
The pinned runner source recorded in that artifact, mlx_audio/stt/models/qwen3_asr/qwen3_forced_aligner.py lines 721–753, multiplies predicted classes by timestamp_segment_time. The recorded model config supplies 80 ms. This supports an inference that coarse model estimates explain the boundary integration problem; it supplies no acoustic reference proving that a clipped endpoint is accurate. Padding or expanding the alignment input would change inference and the ownership interval and requires separately measured original-source evidence. The configurable host limit neither changes that input nor introduces another model.
The historical response remains abstained under the default policy, and its saved timed Markdown refusal remains a failure record. The user subsequently chose explicit clipping with recorded corrections. A fresh recovery case may request a higher limit, such as the separately declared 20 ms case, while retaining the default attempt unchanged. Report its actual word-timing and native-export outcomes separately: successful delivery under that policy would not prove improved acoustic accuracy or erase the earlier failure. The original acceptance run lacked a structured response; the directly observed cause belongs to the later reproduction whose affected canonical fields match it.