From 9f8b492aae87c47706dce577fb461fdd9548c073 Mon Sep 17 00:00:00 2001 From: Bojie Li Date: Wed, 19 Aug 2026 22:44:32 +0800 Subject: [PATCH 1/5] docs(release): prepare the 0.2.0 changelog Date the accumulated release notes, leave a fresh Unreleased section, and replace the obsolete claim that the packaged Windows app has never been launched with the narrower hardware verification boundary. --- CHANGELOG.md | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43c9843..1a69bc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,16 @@ Notable changes, newest first. Behaviour changes that affect transcription quality carry the measurement that justified them; see [docs/EVALUATION.md](docs/EVALUATION.md). -Format loosely follows [Keep a Changelog](https://keepachangelog.com/). This project has not cut a -release yet, so everything below is unreleased. +Format loosely follows [Keep a Changelog](https://keepachangelog.com/). Release dates use the +repository's local calendar date. ## Unreleased +## 0.2.0 - 2026-08-19 + +Release preparation repaired the Android build after the AGP 9 migration and refreshed the +Windows app's locked transitive dependency graph after the ONNX Runtime update. + ### Added - **The connection test now sends a recording, so an endpoint that cannot take one fails the @@ -1216,8 +1221,10 @@ deliberate: writes the on-screen version number instead of the spoken one in roughly 36% of runs, against a 21% baseline error rate with no context at all. Numbers, method and failed mitigations are in [docs/EVALUATION.md](docs/EVALUATION.md). This is the central open problem. -- **The Windows app has never been run.** It compiles and its core tests pass, but every Win32 path - — keyboard hook, `waveIn` capture, `SendInput`, UI Automation, DPAPI — is unexercised. +- **Windows microphone capture and text injection still require a manual release check.** CI + launches the packaged app and exercises the packaged CLI on Windows, and the native boundaries + have unit coverage, but a hosted runner cannot speak into `waveIn` or verify `SendInput` in a + separately focused application. - **The near-miss suite is red, deliberately.** Adding real-speech cases took it from 0 regressions to 3, which is the honest state: two are the version-number substitution reproducing, and one is a case written as a positive control that failed in the opposite direction. It is not to be made From 065d925a3b9da482b6560f6aa4150f6be8053d0d Mon Sep 17 00:00:00 2001 From: Bojie Li Date: Wed, 19 Aug 2026 22:52:43 +0800 Subject: [PATCH 2/5] fix(eval): count empty silence transcripts as empty Speech-recognition clients surface a blank transcript as ProviderError.emptyOutput so real dictations cannot disappear silently. The silence harness exists specifically to expect that result and must classify it the same way ProviderProbe does, rather than reporting every correct recognizer response as an error. --- Sources/dnt-eval/Silence.swift | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Sources/dnt-eval/Silence.swift b/Sources/dnt-eval/Silence.swift index 3aeff1a..eeabb87 100644 --- a/Sources/dnt-eval/Silence.swift +++ b/Sources/dnt-eval/Silence.swift @@ -93,6 +93,15 @@ struct Silence: AsyncParsableCommand { Attempt( recording: name, run: run, transcript: text, isEmpty: text.isEmpty, error: nil)) + } catch ProviderError.emptyOutput { + // Provider clients reject a blank transcript on ordinary speech because losing + // a real dictation must be visible. In this command blank is the expected + // result: Deepgram and the other recognisers represent it with `emptyOutput`, + // just as ProviderProbe already accepts when its silent recording completes. + attempts.append( + Attempt( + recording: name, run: run, transcript: "", isEmpty: true, + error: nil)) } catch { // An error is not a hallucination. It is reported separately rather than // counted as a pass, because a backend that fails on silence has not From 2d00cdd238b5965173a4ba453a8d376df193a84c Mon Sep 17 00:00:00 2001 From: Bojie Li Date: Wed, 19 Aug 2026 22:59:36 +0800 Subject: [PATCH 3/5] fix(release): skip unavailable private attestations --- .github/workflows/release.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1b1a703..92fb8f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -152,6 +152,9 @@ jobs: (cd dist && shasum -a 256 DoNotType-macOS.zip | tee DoNotType-macOS.zip.sha256) - name: Attest build provenance + # GitHub does not support attestations for user-owned private repositories. Keep the + # release usable while private, and turn provenance on automatically if visibility changes. + if: github.event.repository.visibility == 'public' uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-path: dist/DoNotType-macOS.zip @@ -329,6 +332,7 @@ jobs: "$hash DoNotType-Windows-x64.zip`n") - name: Attest build provenance + if: github.event.repository.visibility == 'public' uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-path: dist/DoNotType-Windows-x64.zip @@ -445,6 +449,7 @@ jobs: (cd dist && sha256sum DoNotType-Android.apk | tee DoNotType-Android.apk.sha256) - name: Attest build provenance + if: github.event.repository.visibility == 'public' uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-path: dist/DoNotType-Android.apk From 211a0816a0ce2d1c3404ef5b2b07486fadeb7617 Mon Sep 17 00:00:00 2001 From: Bojie Li Date: Wed, 19 Aug 2026 23:07:19 +0800 Subject: [PATCH 4/5] fix(release): verify the Swift CLI version format --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 92fb8f1..af005fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -124,7 +124,8 @@ jobs: bundled_version=$(/usr/libexec/PlistBuddy \ -c 'Print :CFBundleShortVersionString' .build/DoNotType.app/Contents/Info.plist) test "$bundled_version" = "$VERSION" - .build/DoNotType.app/Contents/MacOS/dnt --version | grep -q "^dnt $VERSION (" + cli_version=$(.build/DoNotType.app/Contents/MacOS/dnt --version) + test "$cli_version" = "$VERSION" - name: Notarize if: env.NOTARY_KEY_ID != '' From 14e22f77663f81fab51af6c4b6d142152cad5d8f Mon Sep 17 00:00:00 2001 From: Bojie Li Date: Wed, 19 Aug 2026 23:22:55 +0800 Subject: [PATCH 5/5] fix(release): verify the macOS signing team --- .github/workflows/release.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index af005fe..259172c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -115,8 +115,12 @@ jobs: run: | codesign --verify --deep --strict --verbose=2 .build/DoNotType.app signature=$(codesign -dv --verbose=4 .build/DoNotType.app 2>&1) + printf '%s\n' "$signature" if [[ -n "$MACOS_CERTIFICATE" ]]; then - grep -q '^Authority=Developer ID Application:' <<< "$signature" + # `Authority` is omitted on some hosted runners even though the imported identity and + # signature are valid. The build only selects Developer ID Application identities; + # verify that the result belongs to this release team and has hardened runtime instead. + grep -q '^TeamIdentifier=5BR9M56H9W$' <<< "$signature" grep -q 'flags=.*runtime' <<< "$signature" else grep -q '^Signature=adhoc$' <<< "$signature"