Skip to content

transcribe phase A: the normalized result schema, its serializer, and the generated sample #19

Description

@fyang0507

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.

{
  "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": {}}
}
  • 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.

  • A key exists iff its capability was requested, asserted over every cell of VOCABULARY
    §Resolution's derivation table, including both refusal codes.
  • "N/A" never appears as an attribution anywhere in a serialized document — walked over
    every mapping key, not only over segments, because turns carry speaker labels too.
  • A placeholder document contains no 0.0 bound and no plausible placeholder string.
  • languages and verbatim in the requested set add no key to the document.
  • Constructing a document with a key for an unrequested capability fails the suite, and so
    does one with 0.0 where null belongs. An invariant that cannot fail is inert — the
    punctuation floor spent four review passes proving that.
  • uv run --extra dev pytest green.

Depends on

#18 — the schema names complete and the abstention reason enum, which phase 0 adds to the documents.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions