Skip to content

Commit 992d045

Browse files
committed
Release OST 0.2.2
1 parent 68b9b2b commit 992d045

12 files changed

Lines changed: 155 additions & 113 deletions

File tree

.github/workflows/release.yml

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
- name: Checkout
1616
uses: actions/checkout@v4
1717

18-
- name: Verify 0.2.1 artifact
18+
- name: Verify 0.2.2 artifact
1919
run: |
2020
set -euo pipefail
21-
artifact="dist/OST-0.2.1-macos-arm64.zip"
21+
artifact="dist/OST-0.2.2-macos-arm64.zip"
2222
test -s "$artifact"
2323
sha256sum "$artifact"
2424
unzip -t "$artifact"
@@ -32,27 +32,26 @@ jobs:
3232
3333
plist = plistlib.loads(Path("/tmp/ost-release-check/OST.app/Contents/Info.plist").read_bytes())
3434
assert plist["CFBundleIdentifier"] == "com.reserve.OST"
35-
assert plist["CFBundleShortVersionString"] == "0.2.1"
36-
assert plist["CFBundleVersion"] == "3"
35+
assert plist["CFBundleShortVersionString"] == "0.2.2"
36+
assert plist["CFBundleVersion"] == "4"
3737
assert plist["LSUIElement"] is True
3838
PY
3939
4040
- name: Create GitHub release
4141
uses: softprops/action-gh-release@v2
4242
with:
43-
name: v0.2.1
43+
name: v0.2.2
4444
body: |
45-
## v0.2.1
45+
## v0.2.2
4646
47-
This release improves settings and overlay reliability for macOS 26+ on Apple Silicon.
47+
This release improves Apple SpeechAnalyzer transcription reliability for macOS 26+ on Apple Silicon.
4848
49-
- Settings now opens reliably in front as the active window
50-
- Start requests system audio permission before model preflight and repairs incompatible saved input settings
51-
- The overlay starts unlocked on a clean first launch while preserving saved choices
52-
- Overlay settings include a live preview
53-
- Improved localized UI copy and memory-pressure handling
54-
- Added automated verification that the main app opens no network sockets
49+
- Apple Speech is limited to English, Chinese, Japanese, and Korean, including both Simplified and Traditional Chinese
50+
- Stopping capture now finalizes the latest volatile SpeechAnalyzer result instead of discarding the final words
51+
- SpeechAnalyzer input preserves captured-audio timestamps through format conversion
52+
- Settings activation now retries until the window is visible and active
53+
- Added automated checks for supported languages and audio timestamps, plus manual stop-finalization QA
5554
5655
This asset is ad-hoc signed because no Developer ID certificate is available in the release environment. See the README installation note if macOS quarantine blocks first launch.
57-
files: dist/OST-0.2.1-macos-arm64.zip
56+
files: dist/OST-0.2.2-macos-arm64.zip
5857
fail_on_unmatched_files: true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ DerivedDataTests/
66
dist/*
77
!dist/OST-0.2.0-macos-arm64.zip
88
!dist/OST-0.2.1-macos-arm64.zip
9+
!dist/OST-0.2.2-macos-arm64.zip
910
*.xcuserstate
1011
xcuserdata/
1112
Models/

OST.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@
190190
/* Begin XCBuildConfiguration section */
191191
Q00100000000000000000001 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GCC_OPTIMIZATION_LEVEL = 0; MACOSX_DEPLOYMENT_TARGET = 26.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 6.0; }; name = Debug; };
192192
Q00100000000000000000002 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ENABLE_MODULES = YES; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_C_LANGUAGE_STANDARD = gnu17; MACOSX_DEPLOYMENT_TARGET = 26.0; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_VERSION = 6.0; }; name = Release; };
193-
Q00100000000000000000003 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {CODE_SIGN_ENTITLEMENTS = Xcode/OSTApp/OSTApp.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/OSTApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MARKETING_VERSION = 0.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST; PRODUCT_NAME = OST; SKIP_INSTALL = NO; SUPPORTED_PLATFORMS = macosx; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_STRICT_CONCURRENCY = complete; }; name = Debug; };
194-
Q00100000000000000000004 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {CODE_SIGN_ENTITLEMENTS = Xcode/OSTApp/OSTApp.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/OSTApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MARKETING_VERSION = 0.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST; PRODUCT_NAME = OST; SKIP_INSTALL = NO; SUPPORTED_PLATFORMS = macosx; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_STRICT_CONCURRENCY = complete; }; name = Release; };
195-
Q00100000000000000000005 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = Xcode/ModelDownloaderXPC/ModelDownloaderXPC.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/ModelDownloaderXPC/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MARKETING_VERSION = 0.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST.ModelDownloader; PRODUCT_NAME = OSTModelDownloaderXPC; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = macosx; SWIFT_STRICT_CONCURRENCY = complete; }; name = Debug; };
196-
Q00100000000000000000006 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = Xcode/ModelDownloaderXPC/ModelDownloaderXPC.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/ModelDownloaderXPC/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MARKETING_VERSION = 0.2.1; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST.ModelDownloader; PRODUCT_NAME = OSTModelDownloaderXPC; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = macosx; SWIFT_STRICT_CONCURRENCY = complete; }; name = Release; };
193+
Q00100000000000000000003 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {CODE_SIGN_ENTITLEMENTS = Xcode/OSTApp/OSTApp.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/OSTApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MARKETING_VERSION = 0.2.2; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST; PRODUCT_NAME = OST; SKIP_INSTALL = NO; SUPPORTED_PLATFORMS = macosx; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_STRICT_CONCURRENCY = complete; }; name = Debug; };
194+
Q00100000000000000000004 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {CODE_SIGN_ENTITLEMENTS = Xcode/OSTApp/OSTApp.entitlements; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/OSTApp/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; MARKETING_VERSION = 0.2.2; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST; PRODUCT_NAME = OST; SKIP_INSTALL = NO; SUPPORTED_PLATFORMS = macosx; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_STRICT_CONCURRENCY = complete; }; name = Release; };
195+
Q00100000000000000000005 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = Xcode/ModelDownloaderXPC/ModelDownloaderXPC.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/ModelDownloaderXPC/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MARKETING_VERSION = 0.2.2; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST.ModelDownloader; PRODUCT_NAME = OSTModelDownloaderXPC; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = macosx; SWIFT_STRICT_CONCURRENCY = complete; }; name = Debug; };
196+
Q00100000000000000000006 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = Xcode/ModelDownloaderXPC/ModelDownloaderXPC.entitlements; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 4; DEVELOPMENT_TEAM = ""; ENABLE_APP_SANDBOX = YES; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = Xcode/ModelDownloaderXPC/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; MARKETING_VERSION = 0.2.2; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OST.ModelDownloader; PRODUCT_NAME = OSTModelDownloaderXPC; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = macosx; SWIFT_STRICT_CONCURRENCY = complete; }; name = Release; };
197197
Q00100000000000000000007 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OSTTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_STRICT_CONCURRENCY = complete; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OST.app/Contents/MacOS/OST"; }; name = Debug; };
198198
Q00100000000000000000008 /* Release */ = {isa = XCBuildConfiguration; buildSettings = {BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OSTTests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_STRICT_CONCURRENCY = complete; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/OST.app/Contents/MacOS/OST"; }; name = Release; };
199199
Q00100000000000000000009 /* Debug */ = {isa = XCBuildConfiguration; buildSettings = {CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; GENERATE_INFOPLIST_FILE = YES; PRODUCT_BUNDLE_IDENTIFIER = com.reserve.OSTUITests; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_STRICT_CONCURRENCY = complete; TEST_TARGET_NAME = OST; }; name = Debug; };

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ OST is a menu bar app for macOS 26+ that transcribes system audio and shows on-d
77
## Highlights
88

99
- Apple Speech and Apple Translation are the default on-device providers.
10+
- Apple Speech supports English, Chinese (Simplified and Traditional), Japanese, and Korean when the corresponding system locale is available.
1011
- Optional Qwen3 ASR and translation models run locally with MLX.
1112
- Confirmed transcript and translation history stay visible while two separate lines are reserved for the current preview.
1213
- Each transcript and translation area supports 2–10 confirmed lines; the window resizes when this value changes.
@@ -27,9 +28,9 @@ Internet access is used only when the user chooses to download an MLX model. The
2728
- macOS 26.0 or later
2829
- Apple Silicon
2930

30-
## Install 0.2.1
31+
## Install 0.2.2
3132

32-
Download `OST-0.2.1-macos-arm64.zip` from the [v0.2.1 release](https://github.com/9bow/OST/releases/tag/v0.2.1), extract it, and move `OST.app` to Applications.
33+
Download `OST-0.2.2-macos-arm64.zip` from the [v0.2.2 release](https://github.com/9bow/OST/releases/tag/v0.2.2), extract it, and move `OST.app` to Applications.
3334

3435
The current binary is ad-hoc signed because a Developer ID certificate was not available in the release environment. If macOS quarantine reports that the app cannot be verified or is damaged, remove the quarantine attribute after confirming that you downloaded it from this repository:
3536

@@ -40,7 +41,7 @@ xattr -dr com.apple.quarantine /Applications/OST.app
4041
The release ZIP SHA-256 is published by the release workflow and can be compared with:
4142

4243
```bash
43-
shasum -a 256 OST-0.2.1-macos-arm64.zip
44+
shasum -a 256 OST-0.2.2-macos-arm64.zip
4445
```
4546

4647
## Start transcribing

Sources/OSTApp/AppModel.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,9 +159,10 @@ final class AppModel: ObservableObject {
159159
} catch {
160160
captureState = .stopping
161161
}
162-
transcriptionTask?.cancel()
163-
transcriptionTask = nil
162+
let finalizingTranscriptionTask = transcriptionTask
164163
await activeTranscriptionProvider?.stop()
164+
await finalizingTranscriptionTask?.value
165+
transcriptionTask = nil
165166
activeTranscriptionProvider = nil
166167
await translationScheduler.cancelAll()
167168
await appleTranslation.cancelAll()

Sources/OSTApp/OSTApp.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@ enum SettingsWindowPresenter {
6060
private static let settingsWindowIdentifier = "com_apple_SwiftUI_Settings_window"
6161

6262
static func bringForward() async {
63-
NSApp.activate(ignoringOtherApps: true)
6463
for attempt in 0..<20 {
64+
NSApp.activate(ignoringOtherApps: true)
6565
if let window = NSApp.windows.first(where: {
6666
$0.identifier?.rawValue == settingsWindowIdentifier
6767
}) {
6868
window.makeKeyAndOrderFront(nil)
6969
window.orderFrontRegardless()
70-
return
70+
if window.isVisible, window.isKeyWindow {
71+
return
72+
}
7173
}
7274
if attempt < 19 {
7375
try? await Task.sleep(for: .milliseconds(50))

0 commit comments

Comments
 (0)