You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
TRANSCRIBE_HAPPY_PATH.md is the diff target for every phase after
this one, and tests/test_spec_docs.py, tests/test_environments.py, and tests/test_shipped_commands_match_the_document.py enforce it. An evidence pass over the
runners and recorded artifacts found six things in the specs that the artifacts refute. They
land first, because implementing against a wrong target produces code that matches the wrong
number.
Corrections
Each is a value or a claim an artifact or a pinned source refutes.
bytes: 2463307541 → 2467859030, five occurrences (CONTRACT §1.1 and §1.2,
HAPPY_PATH §1.2). manifest.json carries the measured figure read from the Hub at the pinned
revision, and tests/test_environments.py:205 retires this exact number as one of the
illustrative ones the specs used.
HAPPY_PATH §1.1 word_timestamps note says the aligner is "in the torch environment,
so this request spans three". It moved to mlx beside the ASR and adds no runtime — see ENVIRONMENTS.md and CONTRACT §1.4, which already say so.
HAPPY_PATH §2.1 execution.note says "both model stages share the torch environment"
one line below environments_spanned: ["mlx", "torch-vibevoice"].
HAPPY_PATH §3.1 residency and peaks.run_firered.py:395-426 loads VAD, LID, ASR and
Punc, assembles them onto one system object (:435), then calls system.process once
(:463) — so residency: "one_model_stage_at_a_time" and "four model stages in one
environment, none resident together" are false on the only stack with four stages. Measured on
the same 139.284 s clip: 9.16 GiB peak RSS with LID off, 12.26 GiB with LID on; the
30-minute channel is 9.12 GiB with LID off, so the peak is dominated by weights rather than
duration. §3.1 publishes a LID-on run at 6.43 GiB, below the measured LID-off floor,
because it was built as a maximum of isolated per-stage peaks. Correct residency to the
granularity that holds — no two environments resident at once, FireRed's models co-resident
inside torch-firered — and replace the illustrative peaks with the measured pair.
Artifacts: firered_lidoff_batch4_multispeaker_codeswitch_20260815.json, firered_lidon_batch4_multispeaker_codeswitch_20260815.json, firered_lidoff_batch4_spice30m_participant.json.
unit_count_known_at_plan_time is described in CONTRACT §1.1 prose and emitted
nowhere, and VOCABULARY's "unit" entry says the count is "reported absent" where the payload
prints null. Ruling: null in a fixed-shape structural block, because a processing block
whose key set varies by stack is worse than a null with a note saying why. VOCABULARY's
sentence changes.
Attribute the diarization figures to the configuration that produced them. The
95.42 % participant-interval F1 and the 33.56 % MER both trace to a diarization run with --num-speakers 2 and --overlapping-segments, and that run shaped the turn set the MER was
scored against (589 raw segments → 195 accepted turns, 9 overlap abstentions, 33 short turns,
54 raw-fragment-only spans). The shipped configuration supplies neither flag by default, so
the diarization and overlapped_speech notes say which configuration the figures describe
and that the shipped one is unmeasured.
Additions
Names and rows the implementation needs that no document carries yet.
abstentions[].reason: overlap (more than one speaker active), short_turn (an
accepted turn below the minimum), raw_fragment (a span whose only activity was a sub-250 ms
diarizer fragment). Three causes the recorded runner distinguishes; the budget-unprocessed
turns it files beside them are coverage, not abstention — nothing was declined, the work
was not reached.
The three turn-threshold values VOCABULARY names without publishing: raw_fragment_min_ms 250, accepted_turn_min_ms 500, same_label_merge_max_ms 300
(model_tests/benchmark/run_turn_attributed_mlx_asr.py:78-84).
failure_recovery.partial_results gains prefix_only; none is retired to VOCABULARY's
retired words. vibevoice was its only holder and a truncation leaves a usable prefix, so none becomes a member nothing reaches — the satisfaction: unavailable mistake. The
mechanism is in the vibevoice phase issue.
complete in a result document, always present, with coverage only when it is false. The one absence that would be dangerous rather than meaningful: a saved document
outlives its exit code and export branches on it when merging.
One error code, option_value_unsupported (exit 2; field, provided, allowed, did_you_mean when a near value exists, fix) — a stack that takes the option but not that
value. option_unsupported_on_stack keeps its exact field list for a stack that takes no such
option. Amending one row to carry conditional fields was considered and rejected: the
three-way capability split exists so two different failures are not rendered alike.
The 30 accepted --language names, cited to config.json:support_languages at both
pinned Qwen revisions, and FireRedLID's 115-label vocabulary cited to its dict.txt.
roles.aligner.config.language_rule, and the Cantonese trap as its stated reason: qwen3_forced_aligner.py:256-266 branches on japanese, korean, chinese, and everything
else to tokenize_space_lang, while its checkpoint declares Cantonese as supported. Passing Cantonese through would space-split CJK into one word per segment.
Code
A backend→(package, role) map in manifest.json. environments.packages_for() keys roles.values() on package ids
(src/audio_cli/environments/__init__.py:141), so firered-vad, firered-lid, firered-asr2-aed, and firered-punc — four backends of the single firered-asr2s package —
raise ManifestError. That is package data and belongs beside the rest of it.
Acceptance
uv run --extra dev pytest green with every edit in place.
packages_for("firered", {…four backends…}) returns [firered-asr2s], and still raises
on a backend that does not fill the role it is mapped to.
No document states a residency claim the recorded runs contradict, and no spec figure
equals a value tests/test_environments.py retires.
Context
Decomposes #12, phase 0 of
TRANSCRIBE_IMPLEMENTATION_PLAN.md.
TRANSCRIBE_HAPPY_PATH.md is the diff target for every phase after
this one, and
tests/test_spec_docs.py,tests/test_environments.py, andtests/test_shipped_commands_match_the_document.pyenforce it. An evidence pass over therunners and recorded artifacts found six things in the specs that the artifacts refute. They
land first, because implementing against a wrong target produces code that matches the wrong
number.
Corrections
Each is a value or a claim an artifact or a pinned source refutes.
bytes: 2463307541→2467859030, five occurrences (CONTRACT §1.1 and §1.2,HAPPY_PATH §1.2).
manifest.jsoncarries the measured figure read from the Hub at the pinnedrevision, and
tests/test_environments.py:205retires this exact number as one of theillustrative ones the specs used.
word_timestampsnote says the aligner is "in the torch environment,so this request spans three". It moved to
mlxbeside the ASR and adds no runtime — seeENVIRONMENTS.md and CONTRACT §1.4, which already say so.
execution.notesays "both model stages share the torch environment"one line below
environments_spanned: ["mlx", "torch-vibevoice"].run_firered.py:395-426loads VAD, LID, ASR andPunc, assembles them onto one system object (
:435), then callssystem.processonce(
:463) — soresidency: "one_model_stage_at_a_time"and "four model stages in oneenvironment, none resident together" are false on the only stack with four stages. Measured on
the same 139.284 s clip: 9.16 GiB peak RSS with LID off, 12.26 GiB with LID on; the
30-minute channel is 9.12 GiB with LID off, so the peak is dominated by weights rather than
duration. §3.1 publishes a LID-on run at 6.43 GiB, below the measured LID-off floor,
because it was built as a maximum of isolated per-stage peaks. Correct residency to the
granularity that holds — no two environments resident at once, FireRed's models co-resident
inside
torch-firered— and replace the illustrative peaks with the measured pair.Artifacts:
firered_lidoff_batch4_multispeaker_codeswitch_20260815.json,firered_lidon_batch4_multispeaker_codeswitch_20260815.json,firered_lidoff_batch4_spice30m_participant.json.unit_count_known_at_plan_timeis described in CONTRACT §1.1 prose and emittednowhere, and VOCABULARY's "unit" entry says the count is "reported absent" where the payload
prints
null. Ruling:nullin a fixed-shape structural block, because aprocessingblockwhose key set varies by stack is worse than a null with a note saying why. VOCABULARY's
sentence changes.
95.42 % participant-interval F1 and the 33.56 % MER both trace to a diarization run with
--num-speakers 2and--overlapping-segments, and that run shaped the turn set the MER wasscored against (589 raw segments → 195 accepted turns, 9 overlap abstentions, 33 short turns,
54 raw-fragment-only spans). The shipped configuration supplies neither flag by default, so
the
diarizationandoverlapped_speechnotes say which configuration the figures describeand that the shipped one is unmeasured.
Additions
Names and rows the implementation needs that no document carries yet.
abstentions[].reason:overlap(more than one speaker active),short_turn(anaccepted turn below the minimum),
raw_fragment(a span whose only activity was a sub-250 msdiarizer fragment). Three causes the recorded runner distinguishes; the budget-unprocessed
turns it files beside them are coverage, not abstention — nothing was declined, the work
was not reached.
raw_fragment_min_ms250,accepted_turn_min_ms500,same_label_merge_max_ms300(
model_tests/benchmark/run_turn_attributed_mlx_asr.py:78-84).failure_recovery.partial_resultsgainsprefix_only;noneis retired to VOCABULARY'sretired words.
vibevoicewas its only holder and a truncation leaves a usable prefix, sononebecomes a member nothing reaches — thesatisfaction: unavailablemistake. Themechanism is in the
vibevoicephase issue.completein a result document, always present, withcoverageonly when it isfalse. The one absence that would be dangerous rather than meaningful: a saved documentoutlives its exit code and
exportbranches on it when merging.option_value_unsupported(exit 2;field,provided,allowed,did_you_meanwhen a near value exists,fix) — a stack that takes the option but not thatvalue.
option_unsupported_on_stackkeeps its exact field list for a stack that takes no suchoption. Amending one row to carry conditional fields was considered and rejected: the
three-way capability split exists so two different failures are not rendered alike.
--languagenames, cited toconfig.json:support_languagesat bothpinned Qwen revisions, and FireRedLID's 115-label vocabulary cited to its
dict.txt.roles.aligner.config.language_rule, and the Cantonese trap as its stated reason:qwen3_forced_aligner.py:256-266branches onjapanese,korean,chinese, and everythingelse to
tokenize_space_lang, while its checkpoint declaresCantoneseas supported. PassingCantonesethrough would space-split CJK into one word per segment.Code
manifest.json.environments.packages_for()keysroles.values()on package ids(
src/audio_cli/environments/__init__.py:141), sofirered-vad,firered-lid,firered-asr2-aed, andfirered-punc— four backends of the singlefirered-asr2spackage —raise
ManifestError. That is package data and belongs beside the rest of it.Acceptance
uv run --extra dev pytestgreen with every edit in place.packages_for("firered", {…four backends…})returns[firered-asr2s], and still raiseson a backend that does not fill the role it is mapped to.
equals a value
tests/test_environments.pyretires.