Arc Forge Labs Docs v2026.10.2

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:

  1. Push-to-talk dictation and plain recordings use the same verbatim ASR path.
  2. Meeting capture is not in the app. It was removed on 2026-10-03 (#140) and is kept on the archive/meeting-2026-10-03 branch and tag.
  3. 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.
  4. 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.
  5. 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.md end 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:

  1. Linux source/local install is usable for human testing on this workstation.
  2. Fresh CPU English installs default to Parakeet v2 where the runtime is available.
  3. 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-gpu WSL2) 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.
  4. The Windows win11-dev VM passes source install, update, uninstall, and desktop build smokes, including Store MSIX packaging.
  5. The Windows human-test artifacts currently proven in the local VM are the no-bundle executable plus dictate-engine.exe sidecar and a Store-style .msix package. MSI/NSIS direct-download installers are still not promoted.
  6. 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:

  1. 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.
  2. 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.
  3. 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.
  4. 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.

  1. The Parakeet backend exposes a plain ASR transcribe_segments(...) path via onnx-asr timestamp adapters when available. The engine and benchmark CLI consume this path for recordings so Parakeet dictation can carry TranscriptSegment timing metadata, not just plain text.
  2. 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.
  3. A repeatable longer flite benchmark fixture generator exists at scripts/generate-long-benchmark-fixtures.sh. It writes a longer WAV plus manifest.csv and manifest-3x.csv so 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:

  1. scripts/windows-vm-smoke.sh --vm win11-dev --mode syntax passes.
  2. scripts/windows-vm-smoke.sh --vm win11-dev --mode install passes, including clean guest app-data setup, install, Python compile, 314 focused Windows tests, dictate --version, default Parakeet doctor, and cleanup.
  3. scripts/windows-vm-smoke.sh --vm win11-dev --mode lifecycle passes, including clean install, update, default Parakeet doctor, and uninstall.
  4. scripts/windows-vm-smoke.sh --vm win11-dev --mode build --keep-guest-workdir passes 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.exe and C:\Users\Public\dictate-vm-smoke\source\ui-shell\src-tauri\target\release\engine\dictate-engine.exe.
  5. 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-workdir passed on 2026-07-05. The guest rebuilt the UI with Vite, froze and smoke-tested the Python engine sidecar, built the Tauri shell with DICTATE_BUNDLES=no-bundle, and verified the same no-bundle shell executable and engine sidecar artifact paths listed above.
  6. 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-workdir passed 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 SDK makeappx.exe, unpacked it, and validated manifest identity plus dictate-ui-shell.exe, logo assets, and engine\dictate-engine.exe. Verified guest artifact: C:\Users\Public\dictate-vm-smoke\source\packaging\msix\out\ArcForgeDictate_2026.7.4.0_x64.msix.
  7. 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-workdir passed 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, verifies dictate 2026.7.4, runs dictate doctor --quick --type-backend pynput, and reports STT backend: parakeet with STT model: parakeet-tdt-0.6b-v2 before uninstalling cleanly.
  8. 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-workdir passed on 2026-07-05. It performed the clean install path with 196 focused tests and 15 skips, ran update, then ran default dictate doctor --quick --type-backend pynput again 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:

  1. dictate benchmark runs plain ASR. Its speaker options (--diarize, DER and speaker-confusion gates) went with Meeting on 2026-10-03 (#140).
  2. 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.
  3. scripts/run-transcription-lane-benchmarks.sh is 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-run first on target machines to verify the exact commands without loading models.
  4. The canonical lane runner preflights each selected lane with dictate doctor --quick for the exact backend/model before benchmark work starts. This fails fast when the Parakeet runtime is unavailable. --skip-preflight is reserved for intentionally collecting failed benchmark JSON artifacts.
  5. scripts/collect-transcription-evidence.sh and scripts/collect-transcription-evidence.ps1 package 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 under evidence-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:

  1. Capture home, push-to-talk, and plain recording use the same Parakeet ASR path.
  2. Durable notes can carry structured transcript segments with optional timestamps. Speaker labels appear only on meeting transcripts saved before Meeting was removed.
  3. Expanded notes, list search, copy, and Markdown export understand structured segments while preserving the plain text path.
  4. The UI server exposes live state, history/notes, config, doctor, and update routes over the loopback API used by the Tauri shell.
  5. Mock/demo dictations are restricted to dev/test/browser preview mode or an explicit VITE_DICTATE_ENABLE_MOCK=1 opt-in. A packaged shell with no live engine bridge must fail visibly instead of returning canned fixture text.

Remaining app-level gates:

  1. Validate segment rendering against real recordings, not only mock/dev output.
  2. A .deb update 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.
  3. Persistent skipped update versions are deferred with the staged update UX. The current UI-only localStorage skip remains a non-authoritative preview behavior until staged updates are promoted.
  4. 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:

  1. Segment start/end error.
  2. Word-level timing error where available.
  3. Stability on long recordings.

Benchmark Requirements

Before promoting a lane to default, benchmark:

  1. WER for transcript quality.
  2. RTFx and live latency.
  3. RAM use.
  4. First-run download size and install/package weight.
  5. Runtime failure rate and fallback behavior.
  6. 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:

  1. CPU English: fresh install selects Parakeet v2, records real microphone speech, stores the note transcript, and does not repeat stale fixture text.
  2. Plain recording: pressing Record uses the same ASR behavior as push-to-talk and does not expose speaker-attribution engine terms.
  3. Windows VM: install, lifecycle, no-bundle build, and MSIX package smokes pass on win11-dev; the tested artifact paths are documented for human testers.
  4. 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.
  5. 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

  1. Consolidate defaults

    • Keep fresh CPU English installs on Parakeet v2.
    • Keep recordings and push-to-talk on the same ASR path.
  2. 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.
  3. Meeting speaker attribution — removed from the app on 2026-10-03 and shelved as P3 (#140); see "Meetings (shelved)" above.

  4. 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:

  1. On clean, well-levelled audio unified matches v2 exactly.
  2. 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.
  3. Unified degrades under additive noise where v2 does not.
  4. Unified is roughly 30% slower than v2 on CPU int8 with no accuracy gain.
  5. 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

  1. onnx-asr 0.12.0 (2026-07-15) adds convolution-based ONNX preprocessors for the GPU path.
  2. ONNX Runtime is now pinned to 1.30.x for both the CPU and CUDA lanes. onnxruntime-gpu 1.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.24 pin 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.
  3. onnxruntime-directml stopped at 1.24.4; the amd extra was capped at <1.25 until #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.
  4. sherpa-onnx 1.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