Context
Decomposes #12, phase A of
TRANSCRIBE_IMPLEMENTATION_PLAN.md.
The schema is where fabrication becomes possible, so it comes first and its anti-fabrication
assertions are built with it rather than after. Everything downstream is shaped by it: a plan's
sample_output is this schema serialized from a placeholder, so plan cannot ship before it.
Scope
src/audio_cli/transcribe/result.py and sample.py.
- One serializer.
sample_output is a placeholder result through the same code path run
uses. A second rendering path is the specific mistake to avoid: four stacks against nine
capability names is ~2,048 combinations, and a hand-maintained example set would both rot and
be infeasible.
- The gating rule is bidirectional. A key exists iff its capability was requested. Two
capabilities license no key at all — languages and verbatim assert an interface and change
no output shape — so their outcome is always produced and the key-set test must encode that
they contribute nothing.
- Placeholder values. Timing and text are
null, never 0.0 or a plausible string; 0.0 is
a legal timestamp and would violate the no-synthesized-bounds floor the moment a consumer read
it as measured. Enum fields show one legal member so a consumer can see the field is
categorical. Real metadata the plan genuinely has — duration, path — is populated.
coverage is over the source timeline: missing_intervals are the extents of units that
did not run, covered_intervals their complement, covered_fraction covered over source
duration, and covered_through_seconds the start of the first missing interval. That watermark
is genuinely early when duration-bucketed ordering leaves the longest turns unprocessed
(model_tests/benchmark/run_turn_attributed_mlx_asr.py:636), which is why the explicit
interval lists sit beside it rather than instead of it.
observed.total_wall_seconds is the sum of the stage walls, so the arithmetic
tests/test_spec_docs.py already asserts stays checkable. A caller timing the command sees
more, because interpreter startup and artifact writes are outside every stage — the same
distinction model_tests/benchmark/run_interview_pipeline.py:201-206 draws.
peak_rss_bytes is the maximum of the per-stage peaks, never their sum, and the per-stage
numbers are kept so the claim is checkable rather than asserted.
Out of scope
The stack table, the planner, and any command surface — those are the next phase. No transport,
no adapters, no backend.
Acceptance
Assertions that must exist and must be shown to fail when violated.
Depends on
#18 — the schema names complete and the abstention reason enum, which phase 0 adds to the documents.
Context
Decomposes #12, phase A of
TRANSCRIBE_IMPLEMENTATION_PLAN.md.
The schema is where fabrication becomes possible, so it comes first and its anti-fabrication
assertions are built with it rather than after. Everything downstream is shaped by it: a plan's
sample_outputis this schema serialized from a placeholder, soplancannot ship before it.Scope
src/audio_cli/transcribe/result.pyandsample.py.{ "schema_version": 1, "complete": true, "source": {"path": "...", "duration_seconds": 0.0, "timebase": "seconds"}, "segments": [{"segment_id": "seg_0", "text": "...", "speaker": "...", // iff diarization "start": 0.0, "end": 0.0, // iff segment_timestamps "words": [{"word_id": "w_0", "text": "...", "start": 0.0, "end": 0.0}]}], "turns": [], // iff diarization "vad_regions": [], // iff vad "lid_regions": [], // iff lid "overlapped_speech": [], // iff overlapped_speech "abstentions": [], // floor artifact, always present "coverage": {}, // iff complete is false "provenance": {"stack": "...", "outcomes": {}, "observed": {}, "plan": {}} }sample_outputis a placeholder result through the same code pathrunuses. A second rendering path is the specific mistake to avoid: four stacks against nine
capability names is ~2,048 combinations, and a hand-maintained example set would both rot and
be infeasible.
capabilities license no key at all —
languagesandverbatimassert an interface and changeno output shape — so their
outcomeis alwaysproducedand the key-set test must encode thatthey contribute nothing.
null, never0.0or a plausible string;0.0isa legal timestamp and would violate the no-synthesized-bounds floor the moment a consumer read
it as measured. Enum fields show one legal member so a consumer can see the field is
categorical. Real metadata the plan genuinely has — duration, path — is populated.
coverageis over the source timeline:missing_intervalsare the extents of units thatdid not run,
covered_intervalstheir complement,covered_fractioncovered over sourceduration, and
covered_through_secondsthe start of the first missing interval. That watermarkis genuinely early when duration-bucketed ordering leaves the longest turns unprocessed
(
model_tests/benchmark/run_turn_attributed_mlx_asr.py:636), which is why the explicitinterval lists sit beside it rather than instead of it.
observed.total_wall_secondsis the sum of the stage walls, so the arithmetictests/test_spec_docs.pyalready asserts stays checkable. A caller timing the command seesmore, because interpreter startup and artifact writes are outside every stage — the same
distinction
model_tests/benchmark/run_interview_pipeline.py:201-206draws.peak_rss_bytesis the maximum of the per-stage peaks, never their sum, and the per-stagenumbers are kept so the claim is checkable rather than asserted.
Out of scope
The stack table, the planner, and any command surface — those are the next phase. No transport,
no adapters, no backend.
Acceptance
Assertions that must exist and must be shown to fail when violated.
§Resolution's derivation table, including both refusal codes.
"N/A"never appears as an attribution anywhere in a serialized document — walked overevery mapping key, not only over segments, because turns carry speaker labels too.
0.0bound and no plausible placeholder string.languagesandverbatimin the requested set add no key to the document.does one with
0.0wherenullbelongs. An invariant that cannot fail is inert — thepunctuation floor spent four review passes proving that.
uv run --extra dev pytestgreen.Depends on
#18 — the schema names
completeand the abstention reason enum, which phase 0 adds to the documents.