Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
5c59eb8
Run voice shell commands in dictation (opt-in list, never in transcri…
CakeRepository Sep 30, 2026
44f134a
Whisper.net (ggml) models in the new app for dictation and the workspace
CakeRepository Sep 30, 2026
36a4db3
One app: tray front door, header status, unified Settings
CakeRepository Sep 30, 2026
8d2ee00
Merge the unified tray, settings and voice shell commands
CakeRepository Sep 30, 2026
70b0c49
Ship the Avalonia app as PrimeDictate.exe in the installers (6.1.0)
CakeRepository Sep 30, 2026
14ad89e
Merge packaging, updater and 6.1.0 into the one-app branch
CakeRepository Sep 30, 2026
21368b2
Publish: keep only this runtime's Whisper.net natives
CakeRepository Sep 30, 2026
4d92049
Windows text delivery parity: focused-control insertion, direct injec…
CakeRepository Oct 1, 2026
8a9dd32
Add Dictation activity view: in-memory feed, sessions, copy buttons (…
CakeRepository Oct 1, 2026
7a61b32
Exclusive microphone access while dictating, delivery docs and releas…
CakeRepository Oct 1, 2026
75f0647
Merge Windows text delivery parity
CakeRepository Oct 1, 2026
1ea1a83
Port WPF shell parity: overlay controls and ripple, tray click and at…
CakeRepository Oct 1, 2026
908df4e
Settings and first-run parity with the WPF app
CakeRepository Oct 1, 2026
8212a71
Merge overlay, tray, history and settings parity; dark theme and hide…
CakeRepository Oct 1, 2026
803a291
Merge settings, first-run and Ollama parity; unknown theme falls back…
CakeRepository Oct 1, 2026
a8ef538
Port the Qualcomm QNN and NPU model paths into the new app
CakeRepository Oct 1, 2026
e38b781
Docs: Qualcomm NPU is in the new app
CakeRepository Oct 1, 2026
943fb43
Merge claude/prime-dictate-transcription-access-d2f2bc into the NPU port
CakeRepository Oct 1, 2026
c06378f
Parity: wake listener recovery, mic change restart, one-time model pr…
CakeRepository Oct 1, 2026
8709321
Fix parity audit findings: settings import, first-run, launch-at-logi…
CakeRepository Oct 1, 2026
71804ca
Merge branch 'worktree-agent-a7282f18e5a1c17fa' into claude/prime-dic…
CakeRepository Oct 1, 2026
de687a3
Release notes: transcription and meetings are a preview in 6.1.0; lea…
CakeRepository Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,10 @@ jobs:
-p:FileVersion=${{ steps.version.outputs.file_version }}
-p:InformationalVersion=${{ steps.version.outputs.informational_version }}

- name: Test
if: github.event_name != 'workflow_dispatch' || !inputs.submit_winget_only
run: dotnet test tests/PrimeDictate.Core.Tests -c Release

- name: Publish Windows payloads
if: github.event_name != 'workflow_dispatch' || !inputs.submit_winget_only
shell: pwsh
Expand Down
27 changes: 17 additions & 10 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file orients coding agents and future maintainers. It is not an end-user ma

## Purpose

**PrimeDictate** is a .NET 10 **Windows** app with a **WPF tray shell** and **first-run onboarding**. It is what the installers ship (6.0.0 and later). A cross-platform successor lives under `src/` (see the layout table) and is not packaged yet. The WPF app:
**PrimeDictate** is one .NET 10 app for hotkey dictation and for transcription and meetings. From 6.1.0 the installers ship the Avalonia app in `src/PrimeDictate.Desktop` as `PrimeDictate.exe`. The WPF app at the repository root (what 6.0.0 shipped) is legacy: it still builds, and it is not packaged. The Qualcomm QNN/AI Hub models are in both apps (the new app's code is under `src/PrimeDictate.Platforms/Speech/Qualcomm`; see `docs/architecture/qualcomm-npu.md`). The dictation behavior below is shared by both; the WPF file names in the Layout table are the legacy implementation. The behavior:

1. Listens for a **global** hotkey (`Ctrl+Shift+Space` / SharpHook) to start and stop capture.
2. Records from the **default** Windows input device using **WASAPI** (NAudio `WasapiCapture`), normalizing to **16 kHz, 16-bit, mono** PCM.
Expand All @@ -24,14 +24,14 @@ This file orients coding agents and future maintainers. It is not an end-user ma
| `WhisperTextInjectionPipeline.cs` | Transcription orchestration, logging, and final-only text injection. |
| `WindowsInputHelpers.cs` | Foreground-window guard for final injection and optional Windows Mouse Sonar pulse. |
| `TranscriptionOverlayWindow.xaml` | Non-activating live transcript overlay; placement is user-configurable. |
| `PrimeDictate.csproj` | The WPF app. Target `net10.0-windows` (SDK pinned in `global.json`); NAudio, SharpHook, sherpa-onnx; references `src/PrimeDictate.Core`. |
| `PrimeDictate.csproj` | The legacy WPF app (6.0.0; not packaged since 6.1.0). Target `net10.0-windows` (SDK pinned in `global.json`); NAudio, SharpHook, sherpa-onnx; references `src/PrimeDictate.Core`. |
| `Directory.Build.props` | Shared assembly/file `Version` (installers read this too). |
| `scripts/Publish-Windows.ps1` | Self-contained publish of the WPF app for one runtime (`win-x64` or `win-arm64`) to `artifacts/<rid>/publish`. |
| `scripts/Publish-Windows.ps1` | Self-contained publish of `src/PrimeDictate.Desktop` (PrimeDictate.exe) for one runtime (`win-x64` or `win-arm64`) to `artifacts/<rid>/publish`. |
| `scripts/Build-Installers.ps1` | Publishes then builds the online WiX `.wixproj` (NuGet `WixToolset.Sdk`) to x64 and ARM64 MSIs in `artifacts/installer`. |
| `installer/wix/` | WiX: `online/` is the shipped MSI (app payload only; models are downloaded in the app), with Start Menu and optional launch-at-login shortcuts; `offline/` is not built. `Branding.wxs` + `PrimeDictate.ico` for ARP/exe icon. |
| `src/PrimeDictate.Core` | Portable core used by both apps: transcript model, SQLite session store, pipeline, dictation controller, audio and provider contracts. |
| `src/PrimeDictate.Platforms` | Platform adapters: microphone capture (miniaudio; WASAPI loopback for system audio), speech providers (sherpa-onnx, Nemotron), hotkeys, typing, the meeting final pass. |
| `src/PrimeDictate.Desktop` | The cross-platform Avalonia app: transcription workspace, meetings, dictation. Not in the installers yet. |
| `src/PrimeDictate.Platforms` | Platform adapters: microphone capture (miniaudio; WASAPI loopback for system audio), speech providers (sherpa-onnx, Nemotron), hotkeys, typing, launch at login (`Startup/`), the GitHub updater (`Updates/`), the meeting final pass. |
| `src/PrimeDictate.Desktop` | The shipped app (6.1.0+), assembly name `PrimeDictate`: dictation, tray, overlay, transcription workspace and meetings, updater (`Updates/`). Avalonia; runs on Windows, macOS and Linux, installers are Windows only. |
| `tests/PrimeDictate.Core.Tests` | xUnit tests for Core and Platforms: `dotnet test tests/PrimeDictate.Core.Tests`. |
| `docs/architecture/` | Design notes and status per stage; `meeting-v1-acceptance.md` is the Meeting v1 test. |

Expand Down Expand Up @@ -61,9 +61,16 @@ This file orients coding agents and future maintainers. It is not an end-user ma
- **Whisper options**: Whisper uses sherpa-onnx `OfflineRecognizerConfig.ModelConfig.Whisper`; add provider/thread/language controls there when needed.
- **Non-Windows audio**: `DefaultMicrophoneRecorder` is Windows-centric (`WasapiCapture`); a cross-platform build would need an abstraction and platform-specific capture.

## Shipped shell + onboarding notes
## Shipped app (6.1.0+)

The tray/onboarding milestone is now implemented:
- **Output**: `src/PrimeDictate.Desktop` builds `PrimeDictate.exe` (AssemblyName `PrimeDictate`, RootNamespace stays `PrimeDictate.Desktop`). The version comes from `Directory.Build.props`.
- **Launch at login is one mechanism** (`Platforms/Startup/LaunchAtLogin.cs`): the MSI installs the all-users Startup shortcut `PrimeDictate.lnk` running `--background`, and the Settings checkbox turns that shortcut on or off per user through the Explorer StartupApproved switch. Only when the shortcut is absent (`LAUNCHATLOGIN=0`, portable copy) does it use the per-user Run value `PrimeDictate`. Never both. `--from-login` (the 6.0.0 shortcut argument) is treated as `--background`. The first start removes the 6.0.0 per-user shortcut and stale Run values.
- **Updater** (`Platforms/Updates`, `Desktop/Updates`): GitHub Releases, asset `PrimeDictate-Setup-vX.Y.Z-<x64|arm64>.msi` plus its `.sha256`, msiexec handoff after the clean exit path (`App.ExitAsync`). Windows only; installing is always user-initiated.
- **Single instance** keeps the name `PrimeDictate.Desktop.<user>`; it does not detect the legacy WPF app.

## Legacy WPF shell + onboarding notes (6.0.0)

The WPF tray/onboarding milestone (legacy, not packaged since 6.1.0):

1. **Host process**: WPF tray host (`App.xaml`) with notification icon, Settings/Exit menu, live transcript overlay, and Ready/Listening/Processing tooltip state.
2. **User settings**: Persisted under `%LocalAppData%\PrimeDictate\settings.json`; loaded at startup and applied to `GlobalHotkeyListener`.
Expand All @@ -73,15 +80,15 @@ The tray/onboarding milestone is now implemented:

## Build and test hints

- **Windows installers**: See [installer/README.md](installer/README.md). CI builds the online x64 and ARM64 MSIs; users download a model in the app's first-run setup or Settings.
- Run from the **repository root** so `./models/whisper/<model folder>` can be discovered during development when models are staged in the repo-local `models` tree.
- **Windows installers**: See [installer/README.md](installer/README.md). `scripts/Build-Installers.ps1` publishes `src/PrimeDictate.Desktop` and builds the MSIs locally (no signing inputs needed); CI builds the online x64 and ARM64 MSIs; users download a model in the app's first-run setup or Settings.
- The legacy WPF app (`PrimeDictate.csproj`) must keep building (`dotnet build PrimeDictate.sln`). Run from the **repository root** so `./models/whisper/<model folder>` can be discovered during development when models are staged in the repo-local `models` tree.
- A running `PrimeDictate.exe` from `dotnet run` can **lock the apphost**; stop the process if `MSB3021` / copy-to-output fails.
- Linter: project should build with **0 warnings** under default SDK analysis when possible; platform-specific API use should stay behind `OperatingSystem` checks or documented trade-offs.

## Releases

- Merging into `main` publishes nothing. A release is a "Release X.Y.Z" commit on `main` that bumps `Directory.Build.props` (`Version`, `AssemblyVersion`, `FileVersion`), then a pushed `vX.Y.Z` tag.
- The tag run of `.github/workflows/build.yml` builds and signs the WPF app, publishes the GitHub Release (x64 and ARM64 MSIs with checksums), pushes the Chocolatey package (then Chocolatey moderation) and opens a winget-pkgs PR (then winget validation and moderation). Details and fixes: [installer/README.md](installer/README.md).
- The tag run of `.github/workflows/build.yml` builds and signs `PrimeDictate.exe` (the Avalonia app), publishes the GitHub Release (x64 and ARM64 MSIs with checksums), pushes the Chocolatey package (then Chocolatey moderation) and opens a winget-pkgs PR (then winget validation and moderation). Details and fixes: [installer/README.md](installer/README.md).
- Never merge to `main`, tag a release or change signing without the owner's explicit go-ahead.

## Out of scope (unless explicitly requested)
Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<Project>
<PropertyGroup>
<!-- ONNX Runtime used by the Qualcomm QNN path (Microsoft.ML.OnnxRuntime.QNN). Keep it equal to the version inside the sherpa-onnx package. -->
<OnnxRuntimeVersion>1.24.4</OnnxRuntimeVersion>
<Version>6.0.0</Version>
<AssemblyVersion>6.0.0.0</AssemblyVersion>
<FileVersion>6.0.0.0</FileVersion>
Expand Down
11 changes: 7 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -281,16 +281,19 @@ PrimeDictate normalizes unsupported saved Whisper.net hardware settings at start
- GPU appears only when supported local Whisper.net GPU runtime support is present.
- NPU appears only for supported GGML models with the required sidecars.

### Experimental Qualcomm QNN path
### Experimental Qualcomm QNN path (native Windows ARM64; in the ARM64 installer)

The Qualcomm backend is experimental and intended for native Windows ARM64 builds on supported Snapdragon X devices.
The Qualcomm backend is experimental and intended for native Windows ARM64 builds on supported Snapdragon X devices. It is in the app that the installers ship (6.1.0 and later) as well as in the legacy WPF app. The models are offered in Settings and first-run setup only where they can run; on any other PC they are hidden, and a saved Qualcomm choice falls back to Whisper or Moonshine on the CPU.

It requires:

- Windows ARM64 process/runtime
- QNN runtime assets in the build output
- QNN runtime assets in the build output (the ARM64 installer carries them)
- Qualcomm AI Hub Whisper wrapper package files, including `encoder.onnx`, `decoder.onnx`, context binaries, metadata, and tokenizer files
- Successful EPContext session creation without CPU fallback when strict validation is requested
- For Moonshine on the NPU, the prepared `qnn` subfolder of the Moonshine model (see `scripts/qnn/quantize_moonshine_for_qnn.py`); such a model is then listed again as "(Qualcomm NPU)"

Developer validation commands (print a JSON report, optionally also write it to a file; they never start the app): `--qnn-aihub-whisper-transcribe <model-dir> <wav> [out]`, `--qnn-whisper-smoke <model-dir> <Cpu|Npu> [out]`, `--qnn-whisper-proof <model-dir> [true|false] [out]`, `--qnn-smoke <model-dir> <Cpu|Npu> [out]`, `--qnn-proof <model-dir> [true|false] [out]`.

Maintainer environment knobs:

Expand Down Expand Up @@ -345,7 +348,7 @@ For installer-specific details, see `installer/README.md`.

Tagged pushes that match `vX.Y.Z` build the app, produce release assets, and publish to GitHub Releases. Merging into `main` alone publishes nothing.

The release pipeline packages the Windows WPF app (`PrimeDictate.exe`). The cross-platform app under `src/` is in the repository but not in the installers yet.
From 6.1.0 the release pipeline packages the Avalonia app in `src/PrimeDictate.Desktop` as `PrimeDictate.exe`: one app for dictation and for transcription and meetings. The WPF app at the repository root is legacy: it still builds but is not packaged. The Qualcomm QNN path described above is in both apps.

In practice, the release pipeline keeps three public distribution channels aligned:

Expand Down
26 changes: 26 additions & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
# PrimeDictate 6.1.0

## Highlights

- Transcription and meetings are a **preview** in 6.1.0: they work, but have had far less real-world use than dictation. Dictation is the same daily-use feature set as 6.0.0.
- One app. The installers now ship the new PrimeDictate that does both jobs in one process: hotkey dictation from the tray, and the transcription and meeting workspace (recordings, speaker timeline, sessions). It is still `PrimeDictate.exe`, so shortcuts, winget, Chocolatey and the updater keep working, and 6.1.0 upgrades 6.0.0 in place.
- Your setup carries over. The new app reads the 6.0.0 settings and history once (it never rewrites them), keeps the same model folders under `%LocalAppData%\PrimeDictate\models`, and keeps the lifetime stats.
- Launch at login is one thing again. The installer's Startup shortcut now starts PrimeDictate in the tray (`--background`), and the app's "Start PrimeDictate when I sign in" checkbox turns that same shortcut on or off for you without administrator rights. `LAUNCHATLOGIN=0` still leaves it out; the checkbox then uses a per-user startup entry instead. The 6.0.0 per-user startup entries are cleaned up on first start.
- Record a meeting from the tray. "Record meeting" starts a microphone and system-audio recording in the workspace; the same item stops it. The main window shows dictation status and opens history, stats and Settings, and there is one Settings window for dictation and for transcription and meetings.
- Same models everywhere. Dictation and transcription pick from the same installed models, including Whisper.net (ggml) models on the GPU (CUDA or Vulkan); one loaded copy of a model is shared by both.
- NPU models carry over. On Snapdragon (Windows ARM64) PCs the ARM64 installer includes the Qualcomm QNN runtime, and Settings and first-run setup offer the Qualcomm AI Hub Whisper Small download and Moonshine on the NPU, with a saved 6.0.0 Qualcomm choice picked up as it was. On Intel PCs the Whisper.net device list now has the NPU (OpenVINO) choice, the large-v3 download fetches Intel's OpenVINO bundle, and "Auto" means the GPU, else the NPU when the model has its OpenVINO files, else the CPU. Choices the PC cannot run are not listed, and a saved choice that does not fit the PC falls back to what does.
- Voice shell commands run again in dictation (never in transcription). Commands from 6.0.0 keep their on/off state; new ones start off.
- Text delivery as in 6.0.0 on Windows: the final text goes straight into the focused edit control when there is one (keystrokes otherwise, never the clipboard), "return to the starting window" inserts into that window without bringing it forward unless coding-mode Enter is on, the Windows Mouse Sonar pulse marks start and stop, and "Request exclusive microphone access while dictating" is back (shared if the microphone refuses).
- Updates: "Check for updates..." in the tray menu, plus an automatic check at most once a day that you can turn off in Settings (the 6.0.0 choice and last-check time carry over). Nothing installs without your OK, the MSI is verified against its published SHA-256 first, and PrimeDictate closes the normal way (an active meeting recording is saved) before Windows Installer starts.
- The overlay has its 6.0.0 controls back: pin (keep it on screen), copy (the last transcript, only when you click it), settings, collapse and expand, the elapsed time, the "Local only" badge and the model in its header, and the compact microphone has its ripple animation and a Settings option keeps it on screen while idle, as 6.0.0 did (by default it shows only while dictating).
- The tray icon: single or double click (or neither) opens PrimeDictate, as chosen in Settings; it shows "needs attention" for 10 seconds after an error and when the wake word could not start, and its tooltip names the model and the wake phrase.
- Settings: start at sign-in for just you or for everyone on this PC (asks for administrator permission, as in 6.0.0; the `--enable-launch-at-login` and `--disable-launch-at-login` command-line switches work again), the typing speed that time saved is compared with (also in the stats window), a color scheme (dark by default, as in 6.0.0, or light, or follow the system), and the tray click choice.
- History window: filters for typed or not typed, app and window, "Clear filters", and "Copy details"; the stats window shows the achievements and daily word counts as before.
- The wake word listens with a small model of the same kind as your dictation model (Whisper.net tiny or base, Moonshine tiny or base, or a small Whisper), as in 6.0.0, and falls back to the dictation model.

## Not in 6.1.0 yet

Nothing from the 6.0.0 app is left out.

The old WPF app stays in the repository and still builds; it is just not shipped.

# PrimeDictate 6.0.0

## Highlights
Expand Down
39 changes: 0 additions & 39 deletions TranscriptionPreferencesSeed.cs

This file was deleted.

Loading
Loading