Dictate Transcription Plan
Date: 2026-07-05
Status: Active scoped authority for local transcription and release evidence.
This is the authoritative planning document only for Dictate local
transcription, recordings, model lanes, timestamping, and their release
evidence. Meetings and speaker labelling are shelved (P3, #140) and not part of
this plan. Dictate runs on the CPU only; GPU material below is history unless
it says otherwise. VISION.md is the
current cross-system authority; this plan is subordinate for account, cloud,
commerce, and Deck decisions. Older research/cost notes are archived under
docs/archive/.
Goal
Ship a clean local-first transcription stack where:
- Push-to-talk dictation and plain recordings use the same verbatim ASR path.
- Meeting capture is not in the app. It was removed on 2026-10-03 (#140) and
is kept on the
archive/meeting-2026-10-03branch and tag. - Parakeet on the CPU is the local ASR foundation. Dictate does not support GPUs: NVIDIA CUDA and AMD lanes were dropped on 2026-10-01 to focus on CPU latency on the machines people already have. Removing the remaining GPU code, the engine's device selection, is tracked in #111; GPU may return later as a separate decision.
- Whisper is gone: faster-whisper, WhisperX and whisper.cpp were removed on 2026-09-30. Parakeet v2 (English) and v3 (25 European languages) cover dictation.
- Latency from releasing the shortcut to text appearing, measured on everyday CPU machines, is the performance target.
Deployable Goal
Set this document as the active scoped deployment goal for local transcription and release evidence:
Implement
docs/TRANSCRIPTION_PLAN.mdend to end so Dictate is ready for human testing on everyday CPU machines, with a Windows build verified in the local VM lab.
This document is the source of truth only for the scoped transcription/model
deployment. Older goal, model-research, and cost-planning notes are archived or
reduced to pointers. If another document conflicts with this plan on local
transcription or release evidence, update that document to point here. For
product direction, follow VISION.md.
Planning Map
Use this file as the only active plan for transcription deployment. Other docs have narrower roles:
| File | Role |
|---|---|
../VISION.md |
Product direction: Dictate is local-only. |
docs/GOALS.md |
Compatibility pointer for older links. |
docs/archive/ |
Historical notes only; not current direction. |
benchmarks/README.md |
Benchmark command and artifact format referenced by this plan. |
docs/desktop-packaging.md |
Packaging runbook; not a separate deployment plan. |
Do not create a second planning landing page for this work. If implementation details outgrow this document, keep this plan as the goal and link to focused runbooks or specs from the relevant acceptance gate.
Deployment Snapshot
Current verified state:
- Linux source/local install is usable for human testing on this workstation.
- Fresh CPU English installs default to Parakeet v2 where the runtime is available.
- GPU lanes are no longer supported (2026-10-01). Last evidence, for the
record: Parakeet v2 int8 loaded on CUDA 13 (onnxruntime-gpu 1.30, RTX 4090 in
win11-gpuWSL2) on 2026-10-01, but only after working around a broken GPU install path (#109, closed), and with 742 CPU/GPU memcpy nodes, so int8 on CUDA was not a clear win. - The Windows
win11-devVM passes source install, update, uninstall, and desktop build smokes, including Store MSIX packaging. - The Windows human-test artifacts currently proven in the local VM are the
no-bundle executable plus
dictate-engine.exesidecar and a Store-style.msixpackage. MSI/NSIS direct-download installers are still not promoted. - Meeting capture, its speaker-attribution backends (pyannote, DiariZen, Sortformer), and the torch/pyannote runtime and model in the builds were removed on 2026-10-03 (#140). Meeting transcripts saved before then stay in history as notes.
Deployment blockers before calling this plan complete:
- Measure end-to-end dictation latency on CPU on the two daily machines (X Forge and the Framework laptop) and tune where the numbers point.
- Validate note timestamp quality. The engine, daemon, note store, expanded-note UI, search and Markdown export carry timestamped segments; their accuracy on real recordings is not yet measured.
- Decide the public Windows promotion path: current VM evidence proves the no-bundle executable and MSIX packaging paths; MSI/NSIS direct-download bundling is still not promoted.
- Staged update preparation is deferred out of the human-test release. The human-test release uses the tested immediate source update path plus the documented MSIX/manual package path.
Product Rules
| User Action | Internal Behavior |
|---|---|
| Push-to-talk dictation | Verbatim ASR, no speaker attribution. |
| Plain recording | Same ASR behavior as push-to-talk, no speaker attribution. |
The UI should expose product language such as Record. It should
not expose primary controls named diarization, ASR backend, CUDA, MIGraphX,
or similar engine terms.
Local ASR Lanes
| Lane | Target | Status | Decision |
|---|---|---|---|
| English CPU | Parakeet v2, nvidia/parakeet-tdt-0.6b-v2 |
Wired today through ONNX/onnx-asr CPU path | Default English local lane. |
| Multilingual CPU | Parakeet v3, nvidia/parakeet-tdt-0.6b-v3 |
Feasibility benchmark | Use only if CPU latency is acceptable. |
NVIDIA CUDA and AMD (ROCm/MIGraphX, DirectML) lanes were dropped on 2026-10-01. The engine's device selection is still present until #111 lands; treat it as unsupported, and do not add GPU evidence gates.
The faster-whisper/large-v3 bridge for this workstation was removed on
2026-09-30.
Implementation Status
GPU history: the CUDA and AMD lanes were dropped on 2026-10-01. Their benchmark, evidence and audit tooling was removed with #112 and the GPU install paths with #110; the engine's device selection goes with #111. Their last evidence is in this file's git history before 2026-10-01.
Parakeet v2 and v3 are wired through the ONNX/onnx-asr loader on the CPU.
- The Parakeet backend exposes a plain ASR
transcribe_segments(...)path viaonnx-asrtimestamp adapters when available. The engine and benchmark CLI consume this path for recordings so Parakeet dictation can carryTranscriptSegmenttiming metadata, not just plain text. - A repeatable local flite-smoke benchmark fixture generator exists at
scripts/generate-benchmark-fixtures.sh. These fixtures are for speed, JSON-shape, timestamp, and gate smoke evidence only; curated human speech recordings are still required for final WER promotion. - A repeatable longer flite benchmark fixture generator exists at
scripts/generate-long-benchmark-fixtures.sh. It writes a longer WAV plusmanifest.csvandmanifest-3x.csvso CPU speed runs can repeat the same synthetic audio with less startup-overhead distortion than the short smoke fixture.
Windows VM evidence on win11-dev:
scripts/windows-vm-smoke.sh --vm win11-dev --mode syntaxpasses.scripts/windows-vm-smoke.sh --vm win11-dev --mode installpasses, including clean guest app-data setup, install, Python compile, 314 focused Windows tests,dictate --version, default Parakeet doctor, and cleanup.scripts/windows-vm-smoke.sh --vm win11-dev --mode lifecyclepasses, including clean install, update, default Parakeet doctor, and uninstall.scripts/windows-vm-smoke.sh --vm win11-dev --mode build --keep-guest-workdirpasses for the no-bundle Windows desktop build. Verified guest artifacts:C:\Users\Public\dictate-vm-smoke\source\ui-shell\src-tauri\target\release\dictate-ui-shell.exeandC:\Users\Public\dictate-vm-smoke\source\ui-shell\src-tauri\target\release\engine\dictate-engine.exe.- Current dirty-tree no-bundle build verification after the preflighted lane
runner, stricter plan audit, refreshed install smoke, validated evidence
import, and segment-aware UI refresh:
scripts/windows-vm-smoke.sh --vm win11-dev --mode build --timeout 1800 --keep-guest-workdirpassed on 2026-07-05. The guest rebuilt the UI with Vite, froze and smoke-tested the Python engine sidecar, built the Tauri shell withDICTATE_BUNDLES=no-bundle, and verified the same no-bundle shell executable and engine sidecar artifact paths listed above. - Current dirty-tree MSIX verification after the preflighted lane runner,
stricter plan audit, refreshed install smoke, validated evidence import,
segment-aware UI refresh, and refreshed no-bundle build:
scripts/windows-vm-smoke.sh --vm win11-dev --mode msix --timeout 2400 --keep-guest-workdirpassed on 2026-07-05. The builder regenerated the UI with Vite, froze and smoke-tested the Python engine sidecar, built the Tauri shell, packed the MSIX with Windows SDKmakeappx.exe, unpacked it, and validated manifest identity plusdictate-ui-shell.exe, logo assets, andengine\dictate-engine.exe. Verified guest artifact:C:\Users\Public\dictate-vm-smoke\source\packaging\msix\out\ArcForgeDictate_2026.7.4.0_x64.msix. - Current dirty-tree Windows install verification after the evidence collector,
preflighted lane runner, stricter plan audit, Parakeet-first default,
Meeting readiness, and model-preparation changes:
scripts/windows-vm-smoke.sh --vm win11-dev --mode install --timeout 1800 --keep-guest-workdirpassed on 2026-07-05. The smoke resets the guest Dictate app-data directory, seeds a fresh config, compiles Python sources, runs 314 focused tests with 16 skips in the guest, verifiesdictate 2026.7.4, runsdictate doctor --quick --type-backend pynput, and reportsSTT backend: parakeetwithSTT model: parakeet-tdt-0.6b-v2before uninstalling cleanly. - Current dirty-tree Windows lifecycle verification after the preflighted lane
runner, stricter plan audit, refreshed install smoke, and current package
checks:
scripts/windows-vm-smoke.sh --vm win11-dev --mode lifecycle --timeout 2400 --keep-guest-workdirpassed on 2026-07-05. It performed the clean install path with 196 focused tests and 15 skips, ran update, then ran defaultdictate doctor --quick --type-backend pynputagain and reported the same Parakeet v2 default before uninstalling.
Windows MSI/NSIS installer bundling is not yet promoted. In the current win11-dev VM,
Tauri/WiX MSI bundling fails because candle.exe exits with -2146232576
(CLR/.NET runtime load failure), and NSIS bundling also fails inside Tauri. The
verified Windows human-test artifacts are currently the no-bundle executable
plus engine sidecar and the Store-style MSIX package, not MSI/NSIS installers.
Update scope decision: Staged update preparation is deferred out of the
human-test release. The human-test release uses the tested immediate source update path
(update-windows.ps1 through scripts/windows-vm-smoke.sh --mode lifecycle)
plus the documented MSIX/manual package path. The source lifecycle
smoke verifies install, update, post-update doctor, and uninstall on win11-dev;
the staged available -> preparing -> ready UX and persistent skipped-version
state are deferred until after human testing.
Benchmark evidence foundation:
dictate benchmarkruns plain ASR. Its speaker options (--diarize, DER and speaker-confusion gates) went with Meeting on 2026-10-03 (#140).- JSON output records backend/model/device, WER, RTF, RTFx, peak RSS when the platform exposes it, per-sample hypotheses, optional timed segments, segment-boundary mean absolute error, boundary-pair counts, and promotion gate results.
scripts/run-transcription-lane-benchmarks.shis the canonical local lane runner for writing the CPU, CPU multilingual, and curated-human CPU JSON artifacts consumed by this plan and the plan audit. Every lane runs on the CPU; its CUDA and AMD lanes were removed with #112 and its Meeting lanes with #140. Use--dry-runfirst on target machines to verify the exact commands without loading models.- The canonical lane runner preflights each selected lane with
dictate doctor --quickfor the exact backend/model before benchmark work starts. This fails fast when the Parakeet runtime is unavailable.--skip-preflightis reserved for intentionally collecting failed benchmark JSON artifacts. scripts/collect-transcription-evidence.shandscripts/collect-transcription-evidence.ps1package the plan, benchmark JSON artifacts, audit output, lane-runner dry-run output, per-lane doctor readiness output, and basic non-secret machine/CPU context into a timestamped archive underevidence-bundles/for CPU and Windows test-machine handoff. The plan audit requires that output directory to be ignored by Git.
AMD GPU Path (dropped)
AMD GPU lanes were dropped on 2026-10-01 with the rest of GPU support. There is
no AMD acceptance gate, and the readiness audit no longer requires the AMD
promotion artifacts (benchmark-results/parakeet-v2-amd-human-gated.json and
benchmark-results/parakeet-v3-amd-human-gated.json). The AMD benchmark
runners and the AMD audit gate were removed with #112, and the amd extra with
#110. The DirectML and ROCm/MIGraphX provider checks are still in the tree,
unsupported, until #111 removes them. Earlier revisions of this file hold the old
AMD runtime plan and gates.
Meetings (shelved)
Meeting capture, local speaker labelling (pyannote Community-1, DiariZen and
NVIDIA Sortformer lanes), the meeting and sortformer extras, the bundled
pyannote model and its Hugging Face token were removed from the app and every
build on 2026-10-03. The work is P3 and kept on the archive/meeting-2026-10-03
branch and tag; #140 records its state then (two speakers labelled in the frozen
Linux engine, never run on Windows, about 20 s added to the first engine state
request) and the bar for bringing it back. A saved meeting_stt_backend or
meeting_stt_model is removed from config.yaml on upgrade with one notice.
Meeting transcripts saved before then stay in history, readable, searchable and
exportable with their speaker labels.
UI And App Wiring
The desktop UI must stay product-level while the engine lanes mature. The app
surface should continue to expose Record, push-to-talk dictation and notes;
model/provider names remain advanced configuration and diagnostics.
Current UI/backend wiring that belongs to this deployment:
- Capture home, push-to-talk, and plain recording use the same Parakeet ASR path.
- Durable notes can carry structured transcript segments with optional timestamps. Speaker labels appear only on meeting transcripts saved before Meeting was removed.
- Expanded notes, list search, copy, and Markdown export understand structured segments while preserving the plain text path.
- The UI server exposes live state, history/notes, config, doctor, and update routes over the loopback API used by the Tauri shell.
- Mock/demo dictations are restricted to dev/test/browser preview mode or an
explicit
VITE_DICTATE_ENABLE_MOCK=1opt-in. A packaged shell with no live engine bridge must fail visibly instead of returning canned fixture text.
Remaining app-level gates:
- Validate segment rendering against real recordings, not only mock/dev output.
- A
.debupdate downloads and verifies while the app stays open. Install and restart are a second click. The Windows lifecycle smoke still covers its own installer path. - Persistent skipped update versions are deferred with the staged update UX.
The current UI-only
localStorageskip remains a non-authoritative preview behavior until staged updates are promoted. - Dictate is local-only (
VISION.md); there is no hosted provider lane to promote and no provider-key or switchable-backend UI.
Timestamping
All local systems should produce integrated timestamps. Parakeet v3 documents word and segment timestamp support. The implementation should also study WhisperX-style alignment/reconciliation patterns, but timestamping must be owned by Dictate rather than depending on WhisperX as the product stack.
Benchmark timestamp quality separately from WER:
- Segment start/end error.
- Word-level timing error where available.
- Stability on long recordings.
Benchmark Requirements
Before promoting a lane to default, benchmark:
- WER for transcript quality.
- RTFx and live latency.
- RAM use.
- First-run download size and install/package weight.
- Runtime failure rate and fallback behavior.
- Windows and Linux coverage where that lane is intended to ship.
The required artifact format is the dictate benchmark --json-output ...
report documented in benchmarks/README.md. Human-readable console output is
not enough for promotion because it cannot be compared reliably across hardware
lanes.
There is no GPU tier: GPU lanes were dropped on 2026-10-01. Lanes are benchmarked and promoted on the CPU of everyday machines.
Human-Test Acceptance Checklist
The deployment is ready for human testing only when these checks are true:
- CPU English: fresh install selects Parakeet v2, records real microphone speech, stores the note transcript, and does not repeat stale fixture text.
- Plain recording: pressing
Recorduses the same ASR behavior as push-to-talk and does not expose speaker-attribution engine terms. - Windows VM: install, lifecycle, no-bundle build, and MSIX package smokes
pass on
win11-dev; the tested artifact paths are documented for human testers. - Packaging: the public Windows path is either a tested Store/MSIX route or an explicitly approved temporary artifact; no stale MSI/NSIS assumption is presented as ready.
- Regression: focused Python tests for STT selection, model preparation, UI server state, tray helpers, Windows platform behavior, and settings migration pass locally.
These five items are exactly the items --readiness reports. The NVIDIA English,
NVIDIA multilingual, AMD English and AMD multilingual items were removed on
2026-10-01 when GPU lanes were dropped, and the Meeting item on 2026-10-03 when
Meeting was removed (#140).
Run python3 scripts/transcription_plan_audit.py before handing a build to a
tester. It summarizes which plan gates have local evidence and which are still
blocked. Use --strict in automation; it exits 2 while required promotion
evidence is missing.
Run python3 scripts/transcription_plan_audit.py --readiness for the
tester-facing checklist view. It maps the human-test acceptance items above to
the audit gates and reports five items: CPU English, Plain recording, Windows
VM, Packaging and Regression. All five are decided by files in the repository.
No GPU or Meeting item is reported. Use --readiness --json for a
machine-readable handoff report.
Use scripts/run-human-test-readiness.sh on Linux source installs, or
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts\run-human-test-readiness.ps1 on Windows source installs,
to print the readiness report, run a quick local Parakeet doctor, and show the
manual real-microphone checks that must be completed on each human-test
machine. These scripts intentionally print, rather than auto-pass, the
microphone checks because the acceptance condition is spoken human audio.
Latest full Python regression evidence: uv run pytest -q passed with
687 passed, 5 subtests passed on 2026-07-05 after the UI mock-mode guard,
benchmark fixture tooling, preflighted lane runner, evidence collector,
validated evidence importer, human-test readiness report and wrappers,
Windows MSIX, and segment-aware UI refresh (and the Meeting lanes, since
removed by #140).
uv run python -m py_compile src/dictate/__main__.py src/dictate/benchmark.py src/dictate/doctor.py src/dictate/stt/factory.py src/dictate/ui_server.py
also succeeded on the same worktree.
Latest readiness and plan-audit evidence: tests/test_transcription_plan_audit.py
runs python3 scripts/transcription_plan_audit.py --readiness on the checkout
in CI and requires all five items READY; the audit has a pass gate for the
canonical plan, benchmark fixture tooling, Windows VM package evidence, and the
staged-update deferral decision. The Meeting gate was removed with Meeting on
2026-10-03 (#140); before that, on 2026-10-01 (#112), it passed on the operator
workstation from local CPU curated-human artifacts. Benchmark JSON reports
record Python, platform, machine, and processor context only.
scripts/run-human-test-readiness.sh and
scripts/run-human-test-readiness.ps1 provide the source-install handoff
wrapper for that report plus the manual microphone checks; both run the CPU
doctor. Readiness and audit evidence from 2026-07-05, including the CUDA, AMD
and Meeting gates, is in earlier revisions of this file.
Latest Parakeet-first local default evidence: uv run pytest tests/test_default_local_model.py tests/test_main_stt_selection.py tests/test_stt_registry.py tests/test_parakeet_backend.py tests/test_ui_server.py tests/test_main_benchmark_dispatch.py tests/test_model_prepare.py -q passed
with 142 passed; uv run pytest tests/test_windows_platform.py tests/test_main_benchmark_dispatch.py tests/test_default_local_model.py tests/test_main_stt_selection.py tests/test_ui_server.py tests/test_stt_registry.py -q passed with 156 passed; uv run python -m py_compile src/dictate/stt/factory.py src/dictate/__main__.py src/dictate/doctor.py src/dictate/ui_server.py succeeded; and uv run dictate doctor --quick --type-backend pynput exited 0 with STT backend: parakeet and STT model: parakeet-tdt-0.6b-v2 on 2026-07-05. Fresh local startup defaults now choose
Parakeet v2 when the Parakeet runtime is importable;
faster-whisper was the fallback when Parakeet was unavailable until it was
removed on 2026-09-30; Parakeet is now a core dependency.
Latest Windows fresh-install Parakeet default evidence:
scripts/windows-vm-smoke.sh --vm win11-dev --mode install --timeout 1800 --keep-guest-workdir passed again on 2026-07-05 after the smoke expanded to
cover benchmark parser, benchmark dispatch, benchmark fixture-generator,
preflighted canonical lane-runner dry-run, evidence collector dry-run, and
stricter transcription-plan audit tests. The guest seeded
%APPDATA%\dictate\config.yaml, ran 314 focused Windows tests with
16 skipped, verified dictate 2026.7.4, and default
dictate doctor --quick --type-backend pynput reported STT backend: parakeet with STT model: parakeet-tdt-0.6b-v2.
scripts/windows-vm-smoke.sh --vm win11-dev --mode lifecycle --timeout 2400 --keep-guest-workdir also passed again on 2026-07-05 after the preflighted
lane runner, stricter plan audit, refreshed install smoke, and current package
checks: the install phase ran 196 focused
Windows tests with 15 skipped, default doctor reported Parakeet v2, update
completed, and post-update doctor again reported Parakeet v2 before uninstall.
Staged update preparation is deferred out of the human-test release. The
human-test release uses the tested immediate source update path verified by the
same lifecycle smoke; staged update preparation and persistent skipped-version
state are post-human-test work.
After adding tests.test_transcription_plan_audit to the Windows guest
selection, the local matching command uv run python -m unittest tests.test_update_status tests.test_windows_platform tests.test_ui_server tests.test_model_prepare tests.test_default_local_model tests.test_main_stt_selection tests.test_stt_registry tests.test_benchmark tests.test_main_benchmark_dispatch tests.test_benchmark_fixtures tests.test_transcription_plan_audit tests.test_config_commands tests.test_config_selection tests.test_daemon_history also passed with 314 tests.
Latest Windows package evidence: scripts/windows-vm-smoke.sh --vm win11-dev --mode build --timeout 1800 --keep-guest-workdir passed on 2026-07-05 after
the validated evidence import and segment-aware UI refresh. It rebuilt the
UI with Vite, froze and smoke-tested dictate-engine.exe, built
dictate-ui-shell.exe with DICTATE_BUNDLES=no-bundle, and verified both the
shell executable and engine\dictate-engine.exe sidecar. scripts/windows-vm-smoke.sh --vm win11-dev --mode msix --timeout 2400 --keep-guest-workdir then passed on
the same current worktree after the same UI refresh: it rebuilt the UI and
engine sidecar, built the Tauri shell, packed the MSIX with Windows SDK
makeappx.exe, unpacked it, and validated the manifest, shell executable, logo
assets, and engine sidecar payload. Verified MSIX guest artifact:
C:\Users\Public\dictate-vm-smoke\source\packaging\msix\out\ArcForgeDictate_2026.7.4.0_x64.msix.
Latest structured segment evidence: uv run pytest tests/test_engine_capabilities.py tests/test_note_store.py tests/test_daemon_history.py tests/test_parakeet_pyannote_backend.py -q
passed with 101 passed on 2026-07-05.
Latest benchmark evidence-format regression: uv run pytest tests/test_benchmark.py tests/test_main_benchmark_dispatch.py tests/test_windows_platform.py tests/test_stt_registry.py -q passed with
59 passed on 2026-07-05.
Latest UI evidence: npm test -- --run passed with 62 passed, and
npm run build completed successfully from ui/ on 2026-07-05.
Latest stale-fixture UI guard evidence: npm test -- --run src/test/ipc.test.js src/test/app.test.jsx passed with 48 passed from
ui/, and npm run build completed successfully on 2026-07-05. Coverage
verifies that a Tauri shell without an injected engine bridge is not mock mode,
does not seed demo history, and does not return the canned project-note
transcript.
Latest segment UI/export evidence: uv run pytest tests/test_ui_server.py tests/test_daemon_history.py tests/test_note_store.py -q passed with
123 passed, and npm test -- --run src/test/app.test.jsx src/test/ipc.test.js passed with 44 passed from ui/ on 2026-07-05.
Latest persisted segment rehydration evidence: uv run pytest tests/test_note_store.py tests/test_ui_server.py tests/test_daemon_history.py -q passed with 125 passed, and npm test -- --run src/test/app.test.jsx src/test/ipc.test.js && npm run build passed with 45 UI tests plus a
successful production build from ui/ on 2026-07-05.
Latest segment-aware notes search/export evidence: npm test -- --run passed
with 62 UI tests from ui/ on 2026-07-05. The suite now includes a
persisted Meeting note shaped like the curated Open Speech Repository fixture:
snake_case segment timestamps, speaker ids, speaker labels, and fractional
turn boundaries. Notes search can match segment-only text, the list preview
renders normalized speaker segment content instead of only a generic note
title, Markdown export preserves speaker labels and formatted timestamps, and
the expanded note renders the same real-fixture-style segment rows.
Latest non-meeting recording rule evidence: uv run pytest tests/test_daemon_history.py tests/test_provider_supervisor.py -q passed with
129 passed, and uv run python -m py_compile src/dictate/daemon.py
succeeded on 2026-07-05. Note/plain recordings now use the same non-speaker ASR
path as push-to-talk, including the long-recording remote retry path. Meeting,
the one mode that asked for speaker attribution, was removed with #140.
Latest timestamp/DER benchmark-gate evidence: uv run pytest tests/test_benchmark.py tests/test_main_benchmark_dispatch.py -q passed with
12 passed, and uv run python -m py_compile src/dictate/benchmark.py
succeeded on 2026-07-05. The
benchmark CLI now supports failing promotion gates for WER, RTF, DER, speaker
confusion, segment-boundary MAE, required timestamp metrics, and required DER
metrics. Runtime failures during benchmark transcription now write the requested
JSON artifact with a failed benchmark_runtime gate instead of producing only a
traceback. The DER and speaker-confusion gates were removed with Meeting (#140).
Latest Parakeet timestamp-segment evidence: uv run pytest tests/test_parakeet_backend.py tests/test_engine_capabilities.py tests/test_benchmark.py tests/test_main_benchmark_dispatch.py -q passed with
40 passed; uv run pytest tests/test_parakeet_backend.py tests/test_parakeet_pyannote_backend.py tests/test_engine_capabilities.py tests/test_benchmark.py tests/test_stt_registry.py -q passed with 66 passed;
and uv run python -m py_compile src/dictate/stt/parakeet_backend.py src/dictate/engine.py src/dictate/benchmark.py succeeded on 2026-07-05.
Latest evidence-import evidence: scripts/import-transcription-evidence.py imports returned Linux .tar.gz or
Windows .zip evidence bundles by copying benchmark-results/*.json into the
local repo and can rerun the audit with --audit, so returned promotion
artifacts can be validated without manual file copying. It now validates each
candidate artifact as benchmark JSON with config and summary objects before
copying, supports evidence directories plus .zip, .tar.gz, and .tgz
bundles, and ignores unsafe archive member paths. uv run pytest tests/test_benchmark_fixtures.py tests/test_transcription_plan_audit.py -q
passed with 27 passed on 2026-07-05 after adding zip dry-run, tar import,
no-overwrite, malformed-JSON rejection, and audit coverage.
Latest CPU Parakeet v2 long-fixture evidence:
scripts/generate-long-benchmark-fixtures.sh generated a longer synthetic
flite fixture under benchmark-fixtures/flite-long/ with a 47.81s WAV and a
three-row repeat manifest. uv run dictate benchmark --manifest benchmark-fixtures/flite-long/manifest-3x.csv --audio-root benchmark-fixtures/flite-long --stt-backend parakeet --model parakeet-tdt-0.6b-v2 --device cpu --language en --require-timestamp-metrics --max-mean-rtf 1.00 --max-mean-segment-boundary-mae-s 1.00 --json-output benchmark-results/parakeet-v2-cpu-flite-long-3x-gated.json --run-label local-cpu-flite-long-3x-gated passed through the preflighted canonical lane
runner on 2026-07-05 with mean_rtf=0.0345, mean_rtfx=28.98,
mean_wer=0.0976, and mean_segment_boundary_mae_s=0.3830. It remains
synthetic; curated human speech benchmarks are still required before final
product promotion.
Latest long fixture and lane-runner reproducibility evidence: bash -n scripts/generate-long-benchmark-fixtures.sh scripts/generate-benchmark-fixtures.sh scripts/generate-meeting-benchmark-fixtures.sh scripts/run-transcription-lane-benchmarks.sh scripts/collect-transcription-evidence.sh passed, and uv run pytest tests/test_benchmark_fixtures.py -q passed with 8 passed on 2026-07-05. The
lane runner dry-run lists the canonical CPU, multilingual CPU, and Meeting
smoke artifact names before loading models, and shows the preflight doctor
commands that will fail fast for a missing runtime or gated Meeting model
access (lane set reduced to CPU on 2026-10-01, #112). It also exposes explicit
cpu-human, cpu-human-v3, meeting-human,
meeting-diarizen-human, and meeting-sortformer-human lanes that require
curated manifests through DICTATE_HUMAN_MANIFEST or
DICTATE_MEETING_HUMAN_MANIFEST and write artifacts marked
fixture_class=curated-human. dictate benchmark --validate-manifest-only
now validates curated-human manifests before model loading, rejecting generated
benchmark-fixtures/ paths, flite sample IDs or filenames, missing audio
files, missing timestamp references, and missing timestamped speaker references
for Meeting/DER lanes. The Bash and PowerShell evidence collectors now include
human-lane-dry-run.txt with the exact curated-human CPU and Meeting
promotion commands plus promotion-status.txt showing whether each required
promotion artifact is present or missing. The collector dry-runs list the
handoff bundle contents without exposing token or environment-variable values
and include lane-readiness.txt with quick doctor output for CPU,
pyannote, DiariZen, and Sortformer lanes. The default evidence-bundles/
output path is ignored by Git.
scripts/windows-vm-smoke.sh --vm win11-dev --mode syntax --timeout 900 --keep-guest-workdir also passed again on 2026-07-05 after the collector
promotion-status changes and parsed scripts/collect-transcription-evidence.ps1
in the Windows guest. The Meeting lanes, the meeting fixture generators and their
collector entries were removed with #140.
Implementation Phases
-
Consolidate defaults
- Keep fresh CPU English installs on Parakeet v2.
- Keep recordings and push-to-talk on the same ASR path.
-
Parakeet on the CPU
- Benchmark Parakeet v3 CPU feasibility.
- Measure and tune release-to-text latency on everyday CPU machines.
- The CUDA and AMD runtime tasks that were here were dropped on 2026-10-01; their tooling and install paths went with #112 and #110, and the engine's device selection goes with #111.
-
Meeting speaker attribution — removed from the app on 2026-10-03 and shelved as P3 (#140); see "Meetings (shelved)" above.
-
Remove Whisper product dependency — done 2026-09-30, ahead of the Parakeet multilingual benchmark gate, by owner decision. The desktop UI already forced Parakeet, and faster-whisper pulled a GPL FFmpeg build (through PyAV) into the bundle. Benchmark comparison rows stay as historical evidence only.
Model Landscape Review (2026-09-20)
Periodic check of the open STT landscape against the lanes above. Numbers are from the Open ASR Leaderboard English short-form track (cleaned datasets, so they are not comparable to pre-2026 snapshots). RTFx is the leaderboard's GPU figure and only useful as a relative ordering.
| Model | WER | RTFx | Params | License | Relevance to Dictate |
|---|---|---|---|---|---|
| Qwen/Qwen3-ASR-1.7B | 4.31 | 820 | 1.7B | Apache-2.0 | 52 languages, LLM decoder. GPU-class accuracy option only. |
| nvidia/canary-qwen-2.5b | 4.43 | 867 | 2.5B | CC-BY-4.0 | GPU-class. |
| ibm-granite/granite-speech-4.1-2b | 4.62 | 546 | 2B | Apache-2.0 | -plus variant does speaker-attributed ASR with word timestamps; relevant only if Meetings return (#140). |
| CohereLabs/cohere-transcribe-03-2026 | 4.67 | 907 | 2B | Apache-2.0 | Open weights now; community ONNX exists. GPU-class. |
| nvidia/parakeet-tdt-0.6b-v2 (shipped default) | 4.70 | 6025 | 0.6B | CC-BY-4.0 | Best accuracy-per-speed of any open model. Keep. |
| nvidia/parakeet-tdt-0.6b-v3 (shipped multilingual) | 4.86 | 6076 | 0.6B | CC-BY-4.0 | Keep. |
| ibm-granite/granite-speech-5.0-470m-turboctc | 5.04 | 12946 | 0.47B | Apache-2.0 | Released 2026-08-25. 2x Parakeet throughput, English only, CTC with no timestamps, needs transformers>=5.16 or community ONNX. Watch. |
| nvidia/nemotron-speech-streaming-en-0.6b | 5.25 | 1167 | 0.6B | NVIDIA Open | Cache-aware streaming, 80 ms-1.1 s chunks. Streaming candidate. |
| distil-whisper/distil-large-v3.5 | 5.40 | 879 | 0.8B | MIT | Better than our faster-whisper turbo (6.36) at the same speed, English only. Was a selectable bridge model; removed with faster-whisper on 2026-09-30. |
openai/whisper-large-v3-turbo (faster-whisper turbo) |
6.36 | 797 | 0.8B | MIT | Former bridge lane; removed 2026-09-30. |
| nvidia/nemotron-3.5-asr-streaming-0.6b | 7.88 | 1345 | 0.6B | OpenMDW-1.1 | 40 locales, streaming. Multilingual streaming candidate; accuracy below v3. |
Parakeet Unified 0.6b evaluation
nvidia/parakeet-unified-en-0.6b (2026-04-07) is a FastConformer-RNNT that
runs offline and streaming (down to 160 ms) from one checkpoint. NVIDIA claims
it beats parakeet-tdt-0.6b-v2 offline. It was evaluated on 2026-09-20 on a
16-core CPU workstation, int8, as a possible v2 successor, using two community
ONNX exports (an onnx-asr layout and the k2/sherpa-onnx maintainer's export)
so the export was not the variable. Fixtures: 8 LibriSpeech test-clean clips
(216 reference words, 79 s) and the repo's open-speech-harvard fixture
(scripts/generate-curated-human-asr-fixture.sh, 80 words, peak level 0.34).
| Fixture | v2 int8 (onnx-asr) | unified int8 (onnx-asr) | unified int8 (sherpa-onnx) |
|---|---|---|---|
| LibriSpeech, 16 kHz, clean | 0.46% | 0.46% | 0.46% |
| LibriSpeech through an 8 kHz round-trip | 0.46% | 0.46% | - |
| LibriSpeech + white noise, 20 / 10 / 5 dB SNR | 0.46 / 0.46 / 0.46% | 0.93 / 1.39 / 1.39% | - |
| Harvard fixture, native level (peak 0.34) | 3.75% | 23.75% | 47.50% |
| Harvard fixture, peak-normalised to 0.90 | 5.00% | 8.75% | - |
| Harvard fixture, attenuated to peak 0.09 | 6.25% | 28.75% | - |
| CPU RTFx on LibriSpeech (same loaded machine) | 4.5 | 3.2 | 3.5 |
Findings:
- On clean, well-levelled audio unified matches v2 exactly.
- Unified is strongly input-level sensitive; v2 is not. Peak-normalising the
Harvard fixture takes unified from 23.75% to 8.75%, still more than twice
v2. Dictate's always-on AGC (
audio_preprocess.py, target -18 dBFS RMS) would narrow but not close that gap. - Unified degrades under additive noise where v2 does not.
- Unified is roughly 30% slower than v2 on CPU int8 with no accuracy gain.
- Streaming needs the sherpa-onnx runtime; onnx-asr has no streaming path.
Decision: parakeet-tdt-0.6b-v2 stays the English default. Unified is a
streaming-lane candidate only, to be revisited if live-text-while-holding-key
becomes a product goal, and then together with nemotron-speech-streaming and a
sherpa-onnx backend decision. Any such evaluation must include quiet-input and
noisy-input fixtures, not only clean read speech.
Runtime notes
onnx-asr0.12.0 (2026-07-15) adds convolution-based ONNX preprocessors for the GPU path.- ONNX Runtime is now pinned to
1.30.xfor both the CPU and CUDA lanes.onnxruntime-gpu1.27+ ships CUDA 13 runtime wheels (nvidia-cuda-runtime,nvidia-cudnn-cu13), which need NVIDIA driver 580 or newer; 1.26 was the last CUDA 12 build. The old<1.24pin existed for the external-data path check; Dictate stages Parakeet as flat real files, and an external-data model loads on 1.30 (verified 2026-09-20 on CPU). The CUDA lane was dropped on 2026-10-01 and is not re-validated. onnxruntime-directmlstopped at 1.24.4; theamdextra was capped at<1.25until #110 removed it. Microsoft has retired that wheel. The Windows AMD lane would have needed a replacement runtime; that question closed when GPU lanes were dropped on 2026-10-01.sherpa-onnx1.13.8 supports Parakeet Unified (offline and streaming), Nemotron streaming, Moonshine, Qwen3-ASR, and Cohere Transcribe. It is the runtime to evaluate if a streaming lane is opened.
Archived Notes
Archived notes are reference material only. They do not override this plan.
| Archived Note | Reason |
|---|---|
docs/archive/dictate-pro-subscription-architecture-2026-07-05.md |
Historical paid subscription and hosted-meeting architecture; the current model plan lives here; Meetings are shelved (#140). |
docs/archive/goals-2026-07-05.md |
Superseded as the planning landing page; retained for historical product/release notes. |
docs/archive/frontend-wiring-2026-07-05.md |
Superseded by the UI and app wiring section in this plan. |
docs/archive/meeting-transcription-research-2026-07-05.md |
Superseded; Meetings are shelved (#140). |
docs/archive/recent-dictation-history-spec-2026-07-05.md |
Historical implementation spec; local notes/history is now implementation context, not the active deployment goal. |
docs/archive/xai-diarization-cost-model-2026-07-05.md |
Cost-focused provider note; no longer the canonical model direction. |
Sources
- Open ASR Leaderboard paper/table: https://arxiv.org/html/2510.06961v4
- Parakeet v2 model card: https://huggingface.co/nvidia/parakeet-tdt-0.6b-v2
- Parakeet v3 model card: https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3
- Canary/Parakeet v3 technical report: https://arxiv.org/abs/2509.14128