Skip to content

Replace Cohere CoreML backend with pinned transcribe.cpp - #865

Open
dudemeister23 wants to merge 3 commits into
moona3k:mainfrom
dudemeister23:codex/cohere-transcribe-cpp-backend
Open

Replace Cohere CoreML backend with pinned transcribe.cpp#865
dudemeister23 wants to merge 3 commits into
moona3k:mainfrom
dudemeister23:codex/cohere-transcribe-cpp-backend

Conversation

@dudemeister23

@dudemeister23 dudemeister23 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

This replaces only Cohere Transcribe's FluidAudio/CoreML execution backend with a narrow transcribe.cpp adapter. Cohere remains the same opt-in local product engine, with the same persisted engine id, settings compatibility, CLI routes, scheduler admission, meeting leases, transcript persistence, telemetry identity, and STTResult contract.

Why this change is worthwhile

This is not runtime churn for its own sake. It turns Cohere from an accurate but operationally expensive option into a more practical local engine while reducing supply-chain and lifecycle risk:

  • Far lower resource cost. The historical FluidAudio/CoreML reference took about 73 seconds to its first transcript, ran about 11x realtime after loading, and peaked near 11.6 GB RSS. The pinned transcribe.cpp Q5_K_M path measured roughly 1.1 to 1.6 seconds for subsequent fresh-process transcripts, 20x to 38x realtime, and about 1.8 GB peak RSS. These are directional results from different Apple Silicon systems and fixture methodologies, not a controlled hardware shootout, but the magnitude is large enough to change Cohere's practicality on supported Macs.
  • No user migration or product fragmentation. Existing Cohere selections, settings, CLI commands, scheduler behavior, transcript records, and local-only privacy semantics continue to work. Users get the backend improvement without learning or selecting another engine.
  • Reproducible distribution. MacParakeet owns and verifies the exact source commit, arm64 XCFramework, artifact digest, wrapper version, model revision, and license notices. Production builds fail closed instead of silently consuming a floating dependency or mismatched binary.
  • Safer cancellation and model management. One actor owns native model and session objects, drains active work before teardown, destroys the session before the model, and coordinates deletion with scheduler leases. This removes the race-prone edges around cancellation, engine switching, and deleting a loaded model.
  • Automatic multilingual use without a language picker. The same model transcribes all fourteen supported languages without caller hints. MacParakeet adds local, best-effort transcript language metadata, while keeping audio and text on device.
  • Native-class performance is preserved. A follow-up local comparison against Handy 0.9.4 used byte-identical Q5 model files and the same normalized English, German, Japanese, and Chinese fixtures. Subsequent cold-process medians matched within 40 ms, every transcript matched, and MacParakeet used about 39 MiB less peak RSS. MacParakeet's end-to-end warm path was 4% to 43% slower depending on language, with the largest difference on CJK where it also performs local language classification.

Architecture:

  • CohereTranscribeEngine retains MacParakeet behavior: audio conversion, verified model resolution, bounded chunking, text stitching, error mapping, and result construction.
  • TranscribeCppCohereBackend is an actor-owned native boundary that serializes model/session access, forwards transcription cancellation, and drains work before deterministic session-then-model teardown.
  • The backend always transcribes without a caller language hint. Apple Natural Language classifies the returned text locally for best-effort language metadata because Cohere has no native language-identification head.
  • The Q5_K_M model uses revision-scoped Application Support storage, resumable partial downloads, exact size and SHA-256 verification, and verification markers tied to file metadata.
  • Audio above the native practical limit is split into bounded overlapping chunks and stitched without synthesizing word timings.

Parakeet, WhisperKit, Nemotron, meeting capture, transforms, and unrelated STT behavior remain unchanged.

Exact pins

  • Upstream: handy-computer/transcribe.cpp tag v0.1.3
  • Annotated tag object: d503d6a239e2a290a03ab72dbd3b40460d87acb0
  • Upstream commit: a94e021ef658dc7c788837341a13f6acea3baf3c
  • Swift wrapper: 0.1.3
  • Owned fork: DudeMeister23/transcribe.cpp
  • Owned implementation commit: 51aa23592167cc32f8f3c5d2155d9f9937324c8d
  • Immutable release: macparakeet-v0.1.3-arm64.1
  • Release: https://github.com/DudeMeister23/transcribe.cpp/releases/tag/macparakeet-v0.1.3-arm64.1
  • Artifact: TranscribeCpp-macOS-arm64-v0.1.3-macparakeet.1.xcframework.zip
  • Artifact SHA-256: caad2e1ce80801e5d0adb7e2bb9bcf8e7d1fd295657af281d8260d5dcc629350
  • Model repository: handy-computer/cohere-transcribe-03-2026-gguf
  • Model revision: dfa4adebb64f3076b7b6b90b721275cc069cb421
  • Model file: cohere-transcribe-03-2026-Q5_K_M.gguf
  • Model size: 1,770,270,208 bytes
  • Model SHA-256: 14d02f1ad6dd77b3a60f82639879012c3adb4fe25c50a5a47a2c4c661daf1558

GitHub reports the release as immutable. gh release verify validated the GitHub Sigstore release attestation binding the exact fork commit and artifact digest. A fresh release download matched the measured and pinned archive byte for byte.

Distribution and licenses

transcribe.cpp, its Swift wrapper, ggml, and miniz are MIT licensed. The Cohere GGUF model is Apache-2.0. The source notices and full Apache-2.0 text are retained under LICENSES. Production packaging copies the notices and THIRD_PARTY_LICENSES.md into the app Legal resources before signing.

The production verifier fails closed unless the package checkout, repository, commit, wrapper version, release metadata, artifact filename and SHA-256, materialized XCFramework contents, arm64-only binary, vendored ggml/miniz provenance, and retained notices all match the committed pins.

The owned fork and immutable XCFramework release prerequisite is complete. No GitHub fork or artifact publication remains outstanding for this PR.

Validation

  • Linked Cohere focused suite: 50 tests, 1 expected unavailable-runtime skip, 0 failures.

  • Unlinked Cohere focused suite: 49 tests, 0 failures.

  • Full Swift final gate, run once: 5,087 XCTest tests, 19 skipped, 0 failures; 17 Swift Testing tests passed.

  • Owned native real-model CTest: 2 of 2 passed.

  • Owned Swift wrapper suite: 56 tests executed, 41 unrelated-model skips, 0 failures.

  • Production release verifier passed against a fresh download of the immutable release.

  • Benchmark manifest validation and Python compilation passed.

  • Swift format lint passed for the Cohere adapter, engine, model pins, and focused tests.

  • git diff --check and the repository Unicode policy scan passed.

  • Review-fix focused suite: 214 tests, 1 expected unavailable-runtime skip, 0 failures.

  • Exact Swift 6 language-mode build passed.

  • Repository-only ASR benchmark verification passed, including scorer tests and committed multilingual/full-English rescoring.

  • GitHub CI run 30166261704 passed the release build, CLI smoke, release-bundle smoke, concurrency gate, Swift 6 build, and complete Swift suite on final head 1a38c0a.

  • Greptile and CodeRabbit passed on the final head; all review threads are resolved.

no-mistakes is not installed in this checkout. The hosted CI and repository review gates are complete.

Multilingual runtime evidence

Measured through the real macparakeet-cli without language hints on an Apple M1 Max with 64 GB, Metal compute. All cold and twelve repeated warm transcripts matched their fixture references.

Language Cold first transcript Warm transcription Realtime speed Peak RSS
English 1.291 s 0.392 s 28.05x 1,841.9 MiB
German 1.645 s 0.771 s 38.05x 1,865.9 MiB
Japanese 1.190 s 0.313 s 23.08x 1,835.2 MiB
Chinese 1.139 s 0.272 s 20.65x 1,832.4 MiB

The historical FluidAudio/CoreML reference was about 73 seconds cold, about 11x warm, and about 11.6 GB peak RSS on an Apple M4 Pro with 48 GB. That is a directional backend comparison only because the hardware and aggregate fixture methodology differ.

Known limitations

  • Cohere has no native language-identification head. Local transcript classification can return no language for short or ambiguous text, while preserving the transcript.
  • Cohere remains batch-only, with no live preview, word timings, or speaker labels.
  • Long-audio stitching is text based. Ambiguous overlap can retain or remove a short repeated phrase.
  • Native v0.1.3 model loading has no mid-load abort hook, and transcription cancellation is polled between decoder steps. Teardown waits for non-interruptible native work to finish.
  • The representative four-language runtime pass does not replace the historical full-corpus CoreML accuracy benchmark. A Q5_K_M full-corpus accuracy rerun remains future benchmark work.
  • The existing 16 GB admission gate remains conservative pending broader device-memory evidence.
  • One newly built release binary incurred a one-time 10.96-second Metal library initialization on its first invocation; subsequent fresh processes returned to roughly 1.1 to 1.7 seconds. A symmetric clean-install or post-reboot comparison with Handy remains outstanding.

Summary by cubic

Replaces Cohere’s CoreML backend with a pinned transcribe.cpp adapter while keeping the cohere engine id and product behavior. Adds automatic language detection, a smaller Q5_K_M model (~1.65 GB), and metal/cpu compute policies with reproducible, checksummed distribution.

  • Refactors

    • Added TranscribeCppCohereBackend actor with serialized model/session access, cancellation forwarding, and deterministic teardown.
    • Verified model lifecycle under ~/Library/Application Support/MacParakeet/models/stt/cohere/ with resumable downloads and exact size/SHA-256 checks; scheduler-gated destructive model delete.
    • Preserved batch-only behavior (no live preview or word timestamps); long audio is chunked and stitched; transcript language is classified locally from returned text.
    • Default compute policy is now metal; legacy ane/gpu values migrate; removed Cohere language picker; CLI still accepts --language and saved Cohere language values (normalized, e.g. hi-IN → hi, ru-RU → ru) for compatibility but ignores them.
    • Updated UI/CLI/docs copy (“Loading Cohere…”, model size), telemetry values (metal/cpu with legacy values accepted), and tests (stitching, lifecycle gates, scheduler deletion, Swift 6 isolation, bounded native waits).
    • Added multilingual speed benchmark harness and immutable release/attestation evidence and records.
  • Dependencies

    • Integrated optional local TranscribeCpp package gated by MACPARAKEET_TRANSCRIBE_CPP_PACKAGE_PATH; production bundles a checksum-pinned arm64 CTranscribe.framework and legal notices.
    • Pinned transcribe.cpp v0.1.3 (owned fork commit, wrapper version), and the GGUF model revision; verifier scripts fail closed on pin/provenance/architecture/artifact-tree drift; fail fast if UNIVERSAL=1 with the arm64-only artifact.
    • Updated build, signing, Homebrew packaging, and distribution docs to include the framework, verify pins/attestation, and install legal files.

Written for commit 1a38c0a. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Cohere transcription now runs on a local, checksum-verified transcribe.cpp backend with automatic multilingual language detection.
    • Added safe Cohere model deletion that won’t interrupt active transcription.
  • Changes
    • Removed the Cohere language picker/menu; saved or specified language values are kept only for compatibility and no longer affect decoding.
    • Cohere model download size is now ~1.65 GB.
    • Updated Cohere performance options to Metal and CPU (including related UI/CLI messaging).
  • Documentation
    • Refreshed CLI help, settings text, architecture docs, and benchmark/release documentation.

## What Changed
- Preserve the Cohere engine identity and product contracts while routing native execution through a small actor-owned transcribe.cpp adapter.
- Add revision-scoped Q5_K_M model download, exact size and SHA-256 verification, resumable recovery, bounded long-audio chunking, cancellation, and deterministic context teardown.
- Pin upstream v0.1.3, the owned fork commit, wrapper version, immutable arm64 XCFramework release and checksum, and compatible model revision. Release scripts fail closed on pin, architecture, provenance, artifact-tree, or notice drift.
- Keep automatic multilingual behavior local by invoking native transcription without a language hint and classifying returned text with Apple Natural Language for metadata.
- Extend focused scheduler, lifecycle, CLI, persistence, unavailable-runtime, and stitching tests, and record English, German, Japanese, and Chinese runtime evidence.
- Update ADR-029, the governing STT specifications, benchmark records, CLI documentation, distribution steps, and MIT and Apache-2.0 notices.

## Root Intent
Replace the old FluidAudio/CoreML Cohere implementation without introducing a new user-facing engine or disturbing the surrounding MacParakeet capture, persistence, scheduler, and CLI behavior. The shipping boundary must be reproducible, local-only, cancellation-safe, and owned by MacParakeet rather than a floating upstream binary.

## Seed Prompt
Replace only Cohere Transcribe execution with handy-computer/transcribe.cpp v0.1.3 through an owned, self-built macOS arm64 XCFramework. Preserve every existing Cohere product contract, verify a pinned Q5_K_M model, handle long audio safely, retain local-only privacy, and document exact source, artifact, model, license, benchmark, and distribution evidence. Do not broaden the change into unrelated STT cleanup.

## ADRs Applied
- ADR-016: centralized STT runtime, scheduler admission, and meeting leases.
- ADR-026: Cohere remains the narrow additional-runtime exception, not another engine family.
- ADR-029: transcribe.cpp adapter boundary, lifecycle, multilingual behavior, supply-chain pins, and release evidence.

## Author Notes
The native Cohere runtime transcribes all fourteen official languages without caller hints but has no language-identification head. Transcript language metadata is therefore best-effort local classification and can be absent for short or ambiguous text. No live preview or word timings are synthesized. The representative multilingual runtime pass is complete; full-corpus accuracy remains the historical CoreML baseline until separately rerun on Q5_K_M.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Cohere’s speech engine now uses a pinned transcribe.cpp backend with Metal/CPU execution, automatic language detection, verified GGUF model downloads, lifecycle-safe model deletion, updated CLI/UI behavior, expanded tests, benchmarks, and release documentation.

Changes

Cohere transcribe.cpp migration

Layer / File(s) Summary
Native backend and model lifecycle
Package.swift, Sources/MacParakeetCore/STT/*
Adds conditional transcribe.cpp integration, pinned model verification, native capability validation, Metal/CPU policies, cancellation-aware sessions, automatic language classification, and bounded chunking/stitching.
Lifecycle-safe model deletion
Sources/MacParakeetCore/STT/STTClient*, STTRuntime.swift, STTScheduler.swift, Sources/MacParakeetViewModels/EngineSettingsViewModel.swift
Adds coordinated Cohere model deletion that waits for scheduler/runtime quiescence, unloads native state, removes the model cache, and reports failures.
CLI, UI, and capability updates
Sources/CLI/..., Sources/MacParakeet/..., Sources/MacParakeetCore/...
Treats Cohere language values as compatibility metadata, removes the language submenu, updates Metal/CPU controls, changes capability metadata, and revises loading and download text.
Tests and benchmark evidence
Tests/..., benchmarks/asr/*
Adds native backend concurrency and capability tests, deletion lifecycle coverage, multilingual benchmark tooling, pinned-artifact manifests, and migration results.
Distribution and architecture documentation
LICENSES/*, THIRD_PARTY_LICENSES.md, docs/*, integrations/*, spec/*
Documents transcribe.cpp artifacts, model checksums, cache ownership, retained licenses, automatic language behavior, and ADR-029 architecture decisions.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • moona3k/macparakeet#65: Introduces the centralized STT runtime and scheduler ownership model used by the new Cohere deletion flow.
  • moona3k/macparakeet#167: Modifies shared speech-engine and language plumbing related to Cohere’s language handling.
  • moona3k/macparakeet#813: Adjusts Cohere language and menu routing behavior touched by this change.

Suggested reviewers: moona3k

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing Cohere's CoreML backend with a pinned transcribe.cpp backend.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dudemeister23
dudemeister23 marked this pull request as ready for review July 25, 2026 16:17
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown

Greptile Summary

Replaces Cohere’s CoreML implementation with a pinned, arm64-only transcribe.cpp backend.

  • Adds verified native framework and GGUF model distribution.
  • Preserves the existing Cohere engine identity and compatibility settings.
  • Adds serialized model lifecycle, cancellation, multilingual metadata, chunking, and scheduler-coordinated deletion.
  • Explicitly rejects universal distribution builds when the arm64-only package is enabled.

Confidence Score: 5/5

The PR appears safe to merge with respect to the previously reported universal-build issue.

No blocking failure remains in the reviewed fix.

Files Needing Attention: No files require additional attention.

T-Rex T-Rex Logs

What T-Rex did

  • Head validation exited 0 with manifest checks and four focused tests passing.
  • Pin consistency assertion exited 0 for repository, commit, release tag, artifact filename/SHA-256, and model repository details.
  • Paired parent capture confirms the focused validation file did not exist at HEAD^, while the head capture proves the newly added path executes successfully.
  • Native-gate probe logged Python 3.11.6, missing Swift/Xcode/lipo/ditto tools, and the verifier's expected missing-wrapper-input failure.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
Package.swift Conditionally integrates the local TranscribeCpp package and compile flag; the previously reported universal-build conflict is addressed by the distribution guards.
scripts/dist/build_app_bundle.sh Rejects universal builds using the arm64-only dependency and verifies, embeds, and validates the native framework for production bundles.
scripts/dist/verify_transcribe_cpp_release.sh Fails closed on mismatched source, artifact, architecture, provenance, and license pins.
Sources/MacParakeetCore/STT/CohereTranscribeCppBackend.swift Introduces the actor-owned native model and transcription-session boundary.
Sources/MacParakeetCore/STT/CohereTranscribeEngine.swift Migrates Cohere transcription to the verified native backend while retaining its existing product contract.

Reviews (2): Last reviewed commit: "Address Cohere backend review findings" | Re-trigger Greptile

Comment thread Package.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (2)
Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift (1)

846-856: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Bound the spin waiters with a deadline.

waitUntilLoadStarted/waitUntilTranscriptionStarted yield indefinitely. If a regression means the backend is never entered, these hang until the global XCTest timeout instead of failing fast with a useful message.

♻️ Deadline-bounded waiters
-    func waitUntilLoadStarted() async {
-        while !loadStarted {
-            await Task.yield()
-        }
-    }
-
-    func waitUntilTranscriptionStarted() async {
-        while !transcriptionStarted {
-            await Task.yield()
-        }
-    }
+    func waitUntilLoadStarted() async throws {
+        try await wait(until: { self.loadStarted })
+    }
+
+    func waitUntilTranscriptionStarted() async throws {
+        try await wait(until: { self.transcriptionStarted })
+    }
+
+    private func wait(
+        until condition: () -> Bool,
+        timeout: Duration = .seconds(2)
+    ) async throws {
+        let deadline = ContinuousClock().now.advanced(by: timeout)
+        while !condition() {
+            guard ContinuousClock().now < deadline else {
+                throw MockBackendError.timedOut
+            }
+            try await Task.sleep(for: .milliseconds(1))
+        }
+    }

Note this changes the call sites at Lines 479 and 507 to try await.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift` around lines
846 - 856, Update waitUntilLoadStarted and waitUntilTranscriptionStarted to use
deadline-bounded waiting that throws a clear failure when their flags are not
set in time, rather than yielding indefinitely. Mark both methods as throwing
and update their call sites around the affected tests to use try await,
preserving successful completion when the corresponding state is reached.
Package.swift (1)

8-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Trim the path used for the local package, not just the enable check.

enableTranscribeCpp is derived from the trimmed env var, but .package(path: transcribeCppPackagePath) uses the raw, untrimmed value. A trailing newline/whitespace in MACPARAKEET_TRANSCRIBE_CPP_PACKAGE_PATH (common with CI heredocs/exports) would pass the enable check yet resolve to an invalid path, producing an obscure SwiftPM resolution failure — precisely in the release-build path called out in the comment on line 34-35.

🔧 Proposed fix
 if let transcribeCppPackagePath, enableTranscribeCpp {
     // Release builds must point this at the verified package assembled from the
     // owned MacParakeet fork and its pinned arm64 XCFramework.
     packageDependencies.append(
-        .package(name: "transcribe-cpp", path: transcribeCppPackagePath)
+        .package(
+            name: "transcribe-cpp",
+            path: transcribeCppPackagePath.trimmingCharacters(in: .whitespacesAndNewlines)
+        )
     )
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Package.swift` around lines 8 - 39, Use the trimmed
MACPARAKEET_TRANSCRIBE_CPP_PACKAGE_PATH value when appending the local
transcribe-cpp dependency. Update the environment-value handling near
enableTranscribeCpp so the .package(path:) call receives the same
whitespace-trimmed path used for validation, while preserving the existing
disabled behavior for empty values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@benchmarks/asr/cohere_multilingual_speed.py`:
- Around line 213-225: Update the records serialization in the benchmark flow to
remove the absolute fixture path from each record. Replace the fixture field
with a stable fixture identifier and include the fixture digest, then redact or
migrate existing records so committed JSON contains no local paths.
- Around line 144-151: Update the transcript validation flow around the output
glob and count check to associate each fixture with its expected transcript and
content hash, then compare every generated transcript against the corresponding
shipped reference before publishing measurements. Reject mismatches as well as
missing or empty files, preserving fixture ordering and identifying which
fixture failed.
- Around line 161-176: Update the benchmark argument and provenance flow around
the runtime/model hash options and output generation to load immutable runtime
and model pins, release tag, immutability, and attestation metadata from the
checked-in release manifest instead of accepting caller-controlled values.
Verify the artifact digest and attestation against that manifest, reject any
mismatch before running or recording results, and emit the verified manifest
metadata in the evidence output.

In `@benchmarks/asr/run_macparakeet_fleurs.py`:
- Line 37: Update the benchmark logging near the Cohere engine handling so it
reports language=automatic instead of the unused hint value. Preserve hint
logging for engines that apply language hints, and use the existing Cohere
selection/configuration symbol to scope the change.

In `@Sources/CLI/Commands/ConfigCommand.swift`:
- Around line 119-124: Align the cohere-language CLI config spec and related
messaging to the same parsed language-code source used by parseCohereLanguage,
validation, override validation, and capability listing. Update
CLIConfigKeySpec’s valueSyntax and allowedValues, plus the corresponding
validation error and list/help output, so legacy-compatible values such as hi
and ru remain consistently accepted and advertised.

In `@spec/02-features.md`:
- Line 1896: Update the Cohere download size in the App size row to use the
consistent binary unit, changing the value to approximately 1.65 GiB while
leaving the other download-size estimates unchanged.

In `@spec/03-architecture.md`:
- Around line 519-524: Update the Markdown fences at spec/03-architecture.md
lines 519-524 and 768-775, and spec/06-stt-engine.md lines 101-105, to use the
text language identifier; preserve each fence’s existing content unchanged.
- Line 1056: Update the documented directory layout in spec/03-architecture.md
to include the models/stt/cohere/ leaf alongside stt/whisper/, and add the
revision-scoped-cache note for Cohere matching the documented file-location
table.

In `@spec/adr/001-parakeet-stt.md`:
- Line 15: Update the amendment in ADR-001 to state that the self-built owned
arm64 XCFramework prerequisite is satisfied, referencing the published
macparakeet-v0.1.3-arm64.1 release and checksum pin instead of saying release
remains blocked. Preserve the existing Cohere backend, scheduler, persistence,
and local classification descriptions.

---

Nitpick comments:
In `@Package.swift`:
- Around line 8-39: Use the trimmed MACPARAKEET_TRANSCRIBE_CPP_PACKAGE_PATH
value when appending the local transcribe-cpp dependency. Update the
environment-value handling near enableTranscribeCpp so the .package(path:) call
receives the same whitespace-trimmed path used for validation, while preserving
the existing disabled behavior for empty values.

In `@Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift`:
- Around line 846-856: Update waitUntilLoadStarted and
waitUntilTranscriptionStarted to use deadline-bounded waiting that throws a
clear failure when their flags are not set in time, rather than yielding
indefinitely. Mark both methods as throwing and update their call sites around
the affected tests to use try await, preserving successful completion when the
corresponding state is reached.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f439883-c888-48ad-ade8-41ad84897030

📥 Commits

Reviewing files that changed from the base of the PR and between 408d1bc and fb9f121.

⛔ Files ignored due to path filters (7)
  • scripts/dist/build_app_bundle.sh is excluded by !**/dist/**
  • scripts/dist/homebrew-tap-scaffold/HOWTO.md is excluded by !**/dist/**
  • scripts/dist/homebrew-tap-scaffold/README.md is excluded by !**/dist/**
  • scripts/dist/homebrew-tap-scaffold/macparakeet-cli.rb is excluded by !**/dist/**
  • scripts/dist/sign_notarize.sh is excluded by !**/dist/**
  • scripts/dist/transcribe_cpp_release_pins.sh is excluded by !**/dist/**
  • scripts/dist/verify_transcribe_cpp_release.sh is excluded by !**/dist/**
📒 Files selected for processing (69)
  • LICENSES/Apache-2.0.txt
  • LICENSES/transcribe.cpp-MIT.txt
  • LICENSES/transcribe.cpp-ggml-MIT.txt
  • LICENSES/transcribe.cpp-miniz-MIT.txt
  • Package.swift
  • Sources/CLI/CHANGELOG.md
  • Sources/CLI/Commands/ConfigCommand.swift
  • Sources/CLI/Commands/ModelsCommand.swift
  • Sources/CLI/Commands/RetranscribeCommand.swift
  • Sources/CLI/Commands/SpecCommand.swift
  • Sources/CLI/Commands/TranscribeCommand.swift
  • Sources/MacParakeet/App/DictationFlowCoordinator.swift
  • Sources/MacParakeet/App/MenuBarCoordinator.swift
  • Sources/MacParakeet/Views/Dictation/DictationOverlayController.swift
  • Sources/MacParakeet/Views/Dictation/LoadingCaptionView.swift
  • Sources/MacParakeet/Views/Settings/SettingsView.swift
  • Sources/MacParakeetCore/AppFeatures.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeBackend.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeCppBackend.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeEngine.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeModel.swift
  • Sources/MacParakeetCore/STT/README.md
  • Sources/MacParakeetCore/STT/STTClient.swift
  • Sources/MacParakeetCore/STT/STTClientProtocol.swift
  • Sources/MacParakeetCore/STT/STTRuntime.swift
  • Sources/MacParakeetCore/STT/STTScheduler.swift
  • Sources/MacParakeetCore/STT/SpeechEngineCapabilities.swift
  • Sources/MacParakeetCore/Services/AppPaths.swift
  • Sources/MacParakeetCore/Services/LLM/InProcessModelDownloader.swift
  • Sources/MacParakeetCore/Services/Telemetry/TelemetryEvent.swift
  • Sources/MacParakeetCore/SpeechEnginePreference.swift
  • Sources/MacParakeetViewModels/EngineSettingsViewModel.swift
  • Sources/MacParakeetViewModels/TranscriptionViewModel.swift
  • THIRD_PARTY_LICENSES.md
  • Tests/CLITests/ModelLifecycleCommandTests.swift
  • Tests/CLITests/SpecCommandTests.swift
  • Tests/CLITests/TranscribeCommandTests.swift
  • Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift
  • Tests/MacParakeetTests/STT/MockSTTClient.swift
  • Tests/MacParakeetTests/STT/STTSchedulerTests.swift
  • Tests/MacParakeetTests/STT/SpeechEngineCapabilitiesTests.swift
  • Tests/MacParakeetTests/Services/LLM/InProcessModelDownloaderTests.swift
  • Tests/MacParakeetTests/TelemetryServiceTests.swift
  • Tests/MacParakeetTests/ViewModels/EngineSettingsViewModelTests.swift
  • Tests/MacParakeetTests/ViewModels/TranscriptionViewModelTests.swift
  • benchmarks/asr/README.md
  • benchmarks/asr/cohere_multilingual_speed.py
  • benchmarks/asr/manifest.json
  • benchmarks/asr/results/cohere-transcribe-cpp-migration.md
  • benchmarks/asr/results/cohere-transcribe-cpp-multilingual.json
  • benchmarks/asr/run_macparakeet.py
  • benchmarks/asr/run_macparakeet_fleurs.py
  • benchmarks/asr/speed_bench.py
  • benchmarks/asr/test_manifest.py
  • docs/cli-testing.md
  • docs/distribution.md
  • integrations/README.md
  • integrations/hermes/README.md
  • integrations/openclaw/README.md
  • spec/00-vision.md
  • spec/02-features.md
  • spec/03-architecture.md
  • spec/04-ui-patterns.md
  • spec/06-stt-engine.md
  • spec/README.md
  • spec/adr/001-parakeet-stt.md
  • spec/adr/016-centralized-stt-runtime-scheduler.md
  • spec/adr/026-asr-engine-strategy.md
  • spec/adr/029-cohere-transcribe-cpp-backend.md
💤 Files with no reviewable changes (1)
  • Sources/MacParakeet/App/MenuBarCoordinator.swift
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift

📄 CodeRabbit inference engine (AGENTS.md)

**/*.swift: MacParakeetCore owns shared logic and must not own SwiftUI views; small AppKit-backed adapter services are allowed only when Foundation has no equivalent.
MacParakeetViewModels should contain @Observable view models that can be tested without the GUI.
New I/O should use async/await; avoid introducing new completion-handler or Combine patterns.
When ordering or result sequencing matters, make the API async and await it instead of using fire-and-forget Task.
Keep @MainActor work short; move long-running I/O, model, process, and audio work off the actor, then hop back for UI state.
Database access must use GRDB repositories, roughly one repository per table.
UI buttons should use .parakeetAction(...); do not tint whole hosting roots coral.

Files:

  • Sources/CLI/Commands/RetranscribeCommand.swift
  • Sources/CLI/Commands/ModelsCommand.swift
  • Sources/MacParakeetCore/Services/AppPaths.swift
  • Sources/MacParakeetCore/STT/STTClientProtocol.swift
  • Sources/MacParakeet/App/DictationFlowCoordinator.swift
  • Tests/CLITests/ModelLifecycleCommandTests.swift
  • Sources/MacParakeet/Views/Dictation/DictationOverlayController.swift
  • Sources/MacParakeetCore/AppFeatures.swift
  • Sources/MacParakeetCore/STT/SpeechEngineCapabilities.swift
  • Tests/CLITests/SpecCommandTests.swift
  • Sources/MacParakeet/Views/Dictation/LoadingCaptionView.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeModel.swift
  • Tests/MacParakeetTests/ViewModels/TranscriptionViewModelTests.swift
  • Sources/MacParakeetCore/Services/LLM/InProcessModelDownloader.swift
  • Sources/CLI/Commands/TranscribeCommand.swift
  • Tests/MacParakeetTests/Services/LLM/InProcessModelDownloaderTests.swift
  • Sources/CLI/Commands/SpecCommand.swift
  • Sources/MacParakeetCore/Services/Telemetry/TelemetryEvent.swift
  • Tests/MacParakeetTests/STT/SpeechEngineCapabilitiesTests.swift
  • Sources/MacParakeetViewModels/TranscriptionViewModel.swift
  • Tests/CLITests/TranscribeCommandTests.swift
  • Tests/MacParakeetTests/TelemetryServiceTests.swift
  • Sources/CLI/Commands/ConfigCommand.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeBackend.swift
  • Sources/MacParakeetCore/STT/STTClient.swift
  • Sources/MacParakeetCore/STT/STTScheduler.swift
  • Tests/MacParakeetTests/ViewModels/EngineSettingsViewModelTests.swift
  • Sources/MacParakeetCore/SpeechEnginePreference.swift
  • Package.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeCppBackend.swift
  • Tests/MacParakeetTests/STT/MockSTTClient.swift
  • Tests/MacParakeetTests/STT/STTSchedulerTests.swift
  • Sources/MacParakeetViewModels/EngineSettingsViewModel.swift
  • Sources/MacParakeetCore/STT/STTRuntime.swift
  • Sources/MacParakeet/Views/Settings/SettingsView.swift
  • Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeEngine.swift
🧠 Learnings (6)
📚 Learning: 2026-04-16T03:48:03.903Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 111
File: Sources/MacParakeet/Views/Transcription/PortalDropZone.swift:40-47
Timestamp: 2026-04-16T03:48:03.903Z
Learning: In SwiftUI, don’t flag `accessibilityReduceMotion` violations for *user-initiated, direct-response* feedback animations. If an animation is tied to a real-time user interaction (e.g., drag state changes like `isDragging`) and provides immediate state feedback (such as an opacity transition from ~0.7→0.9 while dragging), treat it as action feedback rather than automatic/decorative motion. Only expect `accessibilityReduceMotion` gating for automatic or non-essential animations; when the motion is driven by explicit user input, it’s acceptable to leave it ungated.

Applied to files:

  • Sources/CLI/Commands/RetranscribeCommand.swift
  • Sources/CLI/Commands/ModelsCommand.swift
  • Sources/MacParakeetCore/Services/AppPaths.swift
  • Sources/MacParakeetCore/STT/STTClientProtocol.swift
  • Sources/MacParakeet/App/DictationFlowCoordinator.swift
  • Sources/MacParakeet/Views/Dictation/DictationOverlayController.swift
  • Sources/MacParakeetCore/AppFeatures.swift
  • Sources/MacParakeetCore/STT/SpeechEngineCapabilities.swift
  • Sources/MacParakeet/Views/Dictation/LoadingCaptionView.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeModel.swift
  • Sources/MacParakeetCore/Services/LLM/InProcessModelDownloader.swift
  • Sources/CLI/Commands/TranscribeCommand.swift
  • Sources/CLI/Commands/SpecCommand.swift
  • Sources/MacParakeetCore/Services/Telemetry/TelemetryEvent.swift
  • Sources/MacParakeetViewModels/TranscriptionViewModel.swift
  • Sources/CLI/Commands/ConfigCommand.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeBackend.swift
  • Sources/MacParakeetCore/STT/STTClient.swift
  • Sources/MacParakeetCore/STT/STTScheduler.swift
  • Sources/MacParakeetCore/SpeechEnginePreference.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeCppBackend.swift
  • Sources/MacParakeetViewModels/EngineSettingsViewModel.swift
  • Sources/MacParakeetCore/STT/STTRuntime.swift
  • Sources/MacParakeet/Views/Settings/SettingsView.swift
  • Sources/MacParakeetCore/STT/CohereTranscribeEngine.swift
📚 Learning: 2026-04-07T04:06:36.832Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 76
File: Sources/MacParakeet/Views/MeetingRecording/MeetingRecordingPanelView.swift:134-142
Timestamp: 2026-04-07T04:06:36.832Z
Learning: In the moona3k/macparakeet codebase, treat an NSPasteboard usage sequence of `NSPasteboard.general.clearContents()` immediately followed by `NSPasteboard.general.setString(_, forType: .string)` as an intentional pattern. Do not flag the unchecked/ignored return value of `setString` in isolation when this `clearContents()`→`setString` sequence is used (as seen in ClipboardService and related views). If you believe this behavior is incorrect, changes should be validated and applied via a codebase-wide sweep rather than a single-file fix.

Applied to files:

  • Sources/MacParakeet/App/DictationFlowCoordinator.swift
  • Sources/MacParakeet/Views/Dictation/DictationOverlayController.swift
  • Sources/MacParakeet/Views/Dictation/LoadingCaptionView.swift
  • Sources/MacParakeet/Views/Settings/SettingsView.swift
📚 Learning: 2026-04-25T21:55:25.954Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 138
File: Tests/CLITests/PromptsCommandTests.swift:158-172
Timestamp: 2026-04-25T21:55:25.954Z
Learning: When reviewing Swift tests in this repo, remember that `DatabaseManager()` (the default test database initializer) seeds 6 built-in prompts during migration. As a result, code paths like `PromptRepository.fetchAll()` will not return an empty array, and positional assumptions/ordering-based assertions (e.g., checking `parsed?.first?[

Applied to files:

  • Tests/CLITests/ModelLifecycleCommandTests.swift
  • Tests/CLITests/SpecCommandTests.swift
  • Tests/MacParakeetTests/ViewModels/TranscriptionViewModelTests.swift
  • Tests/MacParakeetTests/Services/LLM/InProcessModelDownloaderTests.swift
  • Tests/MacParakeetTests/STT/SpeechEngineCapabilitiesTests.swift
  • Tests/CLITests/TranscribeCommandTests.swift
  • Tests/MacParakeetTests/TelemetryServiceTests.swift
  • Tests/MacParakeetTests/ViewModels/EngineSettingsViewModelTests.swift
  • Tests/MacParakeetTests/STT/MockSTTClient.swift
  • Tests/MacParakeetTests/STT/STTSchedulerTests.swift
  • Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift
📚 Learning: 2026-05-13T02:39:59.049Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 283
File: Tests/CLITests/TransformsCommandTests.swift:225-268
Timestamp: 2026-05-13T02:39:59.049Z
Learning: In CLI contract tests under Tests/CLITests (Swift), round-trip tests that exercise the `--database <path>` argument should use a file-backed `DatabaseManager(path:)` (on-disk SQLite) rather than an in-memory queue. Each CLI subcommand invocation independently reopens `DatabaseManager(path:)` from the provided path, so an in-memory `DatabaseQueue` cannot be shared across subcommand runs. Only repository-level history tests (outside the CLI `--database` contract tests) may use in-memory SQLite.

Applied to files:

  • Tests/CLITests/ModelLifecycleCommandTests.swift
  • Tests/CLITests/SpecCommandTests.swift
  • Tests/CLITests/TranscribeCommandTests.swift
📚 Learning: 2026-05-12T20:04:36.900Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 278
File: Sources/MacParakeet/Views/Transforms/TransformSpikeProgressPanelController.swift:15-18
Timestamp: 2026-05-12T20:04:36.900Z
Learning: In this codebase, non-activating overlay panels are implemented as private, per-controller NSPanel subclasses defined locally within each controller file. The subclass should override `canBecomeKey` and `canBecomeMain` to return `false`. During review, follow this existing pattern and avoid suggesting or introducing a shared/centralized `KeylessPanel` abstraction (e.g., don’t refactor these overlays to a common base type).

Applied to files:

  • Sources/MacParakeet/Views/Dictation/DictationOverlayController.swift
📚 Learning: 2026-04-09T02:00:51.656Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 93
File: Tests/MacParakeetTests/Audio/ObjCExceptionBridgeTests.swift:6-98
Timestamp: 2026-04-09T02:00:51.656Z
Learning: In this repo, unit tests that only exercise internal infrastructure/plumbing (e.g., exception trampolines, bridges, shims) should not require separate requirement IDs in `spec/kernel/traceability.md`. If a plumbing test exists only to make an existing production code path crash-safe or correct, treat it as covered by the existing product requirement that governs that code path (for example, dictation tests covered by `REQ-DICT-001`). Do not add new `REQ-CRASH-*` (or similar) traceability entries for pure infrastructure tests, as this is considered spec bloat per `spec/10-ai-coding-method.md`.

Applied to files:

  • Tests/MacParakeetTests/ViewModels/TranscriptionViewModelTests.swift
  • Tests/MacParakeetTests/Services/LLM/InProcessModelDownloaderTests.swift
  • Tests/MacParakeetTests/STT/SpeechEngineCapabilitiesTests.swift
  • Tests/MacParakeetTests/TelemetryServiceTests.swift
  • Tests/MacParakeetTests/ViewModels/EngineSettingsViewModelTests.swift
  • Tests/MacParakeetTests/STT/MockSTTClient.swift
  • Tests/MacParakeetTests/STT/STTSchedulerTests.swift
  • Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift
🪛 ast-grep (0.44.1)
benchmarks/asr/cohere_multilingual_speed.py

[info] 246-246: use jsonify instead of json.dumps for JSON output
Context: json.dumps(payload, ensure_ascii=False, indent=2)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[error] 42-47: Command coming from incoming request
Context: subprocess.run(
command,
text=True,
capture_output=True,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 72-77: Command coming from incoming request
Context: subprocess.run(
["/usr/bin/afinfo", "-b", str(path)],
text=True,
capture_output=True,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 124-130: Command coming from incoming request
Context: subprocess.run(
command,
text=True,
capture_output=True,
env=environment,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)


[error] 42-47: Use of unsanitized data to create processes
Context: subprocess.run(
command,
text=True,
capture_output=True,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 124-130: Use of unsanitized data to create processes
Context: subprocess.run(
command,
text=True,
capture_output=True,
env=environment,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)

🪛 LanguageTool
LICENSES/Apache-2.0.txt

[style] ~162-~162: ‘any and all’ might be wordy. Consider a shorter alternative.
Context: ...ge, computer failure or malfunction, or any and all other commercial damages or losse...

(EN_WORDINESS_PREMIUM_ANY_AND_ALL)

spec/adr/029-cohere-transcribe-cpp-backend.md

[grammar] ~102-~102: Use a hyphen to join words.
Context: ...timings, boundary stitching remains text based and may retain or remove a short r...

(QB_NEW_EN_HYPHEN)

docs/distribution.md

[style] ~26-~26: The double modal “required owned” is nonstandard (only accepted in certain dialects). Consider “to be owned”.
Context: ...package in source builds and a required owned artifact in production builds. A releas...

(NEEDS_FIXED)

🪛 markdownlint-cli2 (0.23.0)
spec/06-stt-engine.md

[warning] 101-101: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

spec/03-architecture.md

[warning] 519-519: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 768-768: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🪛 OpenGrep (1.25.0)
benchmarks/asr/results/cohere-transcribe-cpp-multilingual.json

[ERROR] 107-107: Possible credit card number (PAN) detected in source code. Credit card numbers should never be hardcoded or stored in source files. Use a secrets manager or tokenization service instead.

(coderabbit.pii.credit-card-number)

🪛 Ruff (0.15.21)
benchmarks/asr/cohere_multilingual_speed.py

[error] 43-43: subprocess call: check for execution of untrusted input

(S603)


[error] 73-73: subprocess call: check for execution of untrusted input

(S603)


[error] 125-125: subprocess call: check for execution of untrusted input

(S603)

🔇 Additional comments (76)
Sources/MacParakeetCore/STT/README.md (1)

69-89: LGTM!

Also applies to: 123-124

benchmarks/asr/manifest.json (1)

147-161: LGTM!

Also applies to: 450-451

benchmarks/asr/run_macparakeet.py (1)

17-17: LGTM!

Also applies to: 42-42

benchmarks/asr/speed_bench.py (1)

51-51: LGTM!

benchmarks/asr/test_manifest.py (1)

52-56: LGTM!

THIRD_PARTY_LICENSES.md (1)

49-84: LGTM!

Also applies to: 168-180

docs/cli-testing.md (1)

240-256: LGTM!

docs/distribution.md (1)

19-86: LGTM!

integrations/README.md (1)

19-20: LGTM!

Also applies to: 96-99, 323-325

integrations/hermes/README.md (1)

32-35: LGTM!

integrations/openclaw/README.md (1)

26-28: LGTM!

Also applies to: 39-41, 87-95

spec/adr/026-asr-engine-strategy.md (1)

7-9: LGTM!

Also applies to: 18-20, 63-69

spec/adr/029-cohere-transcribe-cpp-backend.md (1)

1-193: LGTM!

spec/00-vision.md (1)

477-477: LGTM!

spec/02-features.md (1)

727-727: LGTM!

Also applies to: 758-758, 771-771, 1916-1916

spec/03-architecture.md (1)

85-85: LGTM!

Also applies to: 104-104, 415-415, 483-483, 516-516, 755-766, 1090-1091, 1241-1241

spec/04-ui-patterns.md (1)

986-989: LGTM!

spec/06-stt-engine.md (1)

75-96: LGTM!

Also applies to: 97-100, 106-108

spec/README.md (1)

4-4: LGTM!

Also applies to: 53-53, 116-119, 284-286

spec/adr/001-parakeet-stt.md (1)

224-236: LGTM!

Also applies to: 276-277

spec/adr/016-centralized-stt-runtime-scheduler.md (1)

13-13: LGTM!

Also applies to: 55-55

LICENSES/Apache-2.0.txt (1)

1-203: LGTM!

LICENSES/transcribe.cpp-MIT.txt (1)

1-22: LGTM!

Sources/MacParakeetCore/STT/STTClient.swift (1)

10-10: LGTM!

Also applies to: 111-114

Sources/MacParakeetCore/STT/STTClientProtocol.swift (1)

152-157: LGTM!

Sources/MacParakeetCore/STT/STTScheduler.swift (2)

26-27: LGTM!


372-398: 🩺 Stability & Availability

No change needed. models delete cohere-transcribe already protects the currently selected Cohere engine, so this path does not bypass the delete guard unless --force is used.

Sources/MacParakeetViewModels/EngineSettingsViewModel.swift (1)

53-56: LGTM!

Also applies to: 113-116, 196-196, 281-283, 1410-1441, 1493-1493

Sources/CLI/CHANGELOG.md (1)

104-111: LGTM!

Tests/MacParakeetTests/STT/MockSTTClient.swift (1)

10-10: LGTM!

Also applies to: 32-32, 569-572

Tests/MacParakeetTests/STT/STTSchedulerTests.swift (1)

496-546: LGTM!

Also applies to: 1280-1294, 1494-1515, 1756-1766, 1932-1940

Tests/MacParakeetTests/ViewModels/EngineSettingsViewModelTests.swift (1)

95-95: LGTM!

Also applies to: 364-386, 793-815

Tests/MacParakeetTests/ViewModels/TranscriptionViewModelTests.swift (1)

3139-3142: LGTM!

LICENSES/transcribe.cpp-ggml-MIT.txt (1)

1-21: LGTM!

LICENSES/transcribe.cpp-miniz-MIT.txt (1)

1-22: LGTM!

Sources/MacParakeetCore/STT/CohereTranscribeModel.swift (3)

3-37: LGTM!


39-94: LGTM!


96-117: LGTM!

Sources/MacParakeetCore/STT/CohereTranscribeEngine.swift (6)

48-152: LGTM!


171-251: LGTM!


255-289: LGTM!


291-381: LGTM!


666-666: LGTM!

Also applies to: 711-774


785-811: LGTM!

Also applies to: 844-929

Sources/MacParakeetCore/STT/STTRuntime.swift (2)

41-41: LGTM!

Also applies to: 64-67


1563-1577: 🩺 Stability & Availability

No change needed.

STTScheduler.deleteCohereModel() holds speechEngineSwitchTask and disables job admission for the full operation, so new Cohere transcription jobs cannot be admitted while STTRuntime.deleteCohereModel() is suspended during unloadCohere().

Sources/MacParakeet/Views/Dictation/DictationOverlayController.swift (1)

210-212: LGTM!

Sources/MacParakeetCore/Services/LLM/InProcessModelDownloader.swift (1)

457-462: LGTM!

Sources/MacParakeetCore/SpeechEnginePreference.swift (1)

7-9: LGTM!

Also applies to: 27-29, 170-172, 186-203

Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift (4)

5-12: LGTM!

Also applies to: 258-334


343-438: LGTM!


463-646: LGTM!


664-845: LGTM!

Also applies to: 857-877

Tests/MacParakeetTests/Services/LLM/InProcessModelDownloaderTests.swift (1)

6-18: LGTM!

Tests/MacParakeetTests/TelemetryServiceTests.swift (1)

725-726: LGTM!

Package.swift (1)

54-82: LGTM!

Also applies to: 173-173, 186-186

Sources/MacParakeetCore/STT/CohereTranscribeBackend.swift (1)

1-156: LGTM!

Sources/MacParakeetCore/STT/CohereTranscribeCppBackend.swift (2)

28-35: 🩺 Stability & Availability

Confirm Transcribe.initBackends() is safe to call on every reload.

ensureCompatible()/initBackends() run again on every load(), including any reload after a prior unload() (e.g. re-selecting Cohere after switching engines away and back). Public transcribe.cpp docs describe per-Model run serialization but don't document whether repeated initBackends() calls across a process lifetime are idempotent/cheap or could reinitialize global GPU/backend state. Given the load path is exercised through the scheduler's lifecycle-safe unload/delete flow, a non-idempotent repeated init could surface only on the "unload → later reselect Cohere → load again" path, which may be under-covered by the current test surface.

Worth confirming directly against the pinned transcribe.cpp v0.1.3 Swift bindings/header docs, or adding a regression test that loads, unloads, and reloads TranscribeCppCohereBackend twice in the same process.
[medium]


41-69: LGTM!

Also applies to: 71-131, 133-167

Sources/CLI/Commands/ConfigCommand.swift (1)

42-42: LGTM!

Also applies to: 307-312, 603-610

Sources/CLI/Commands/ModelsCommand.swift (1)

562-562: LGTM!

Sources/CLI/Commands/SpecCommand.swift (1)

219-221: LGTM!

Also applies to: 275-277

Sources/CLI/Commands/TranscribeCommand.swift (1)

110-111: LGTM!

Also applies to: 297-312, 625-634

Sources/MacParakeet/App/DictationFlowCoordinator.swift (1)

838-846: LGTM!

Sources/MacParakeetCore/AppFeatures.swift (1)

72-79: LGTM!

Sources/MacParakeetCore/Services/AppPaths.swift (1)

123-126: LGTM!

Sources/CLI/Commands/RetranscribeCommand.swift (1)

147-147: LGTM!

Sources/MacParakeet/Views/Dictation/LoadingCaptionView.swift (1)

41-41: LGTM!

Also applies to: 52-52

Sources/MacParakeet/Views/Settings/SettingsView.swift (1)

567-567: LGTM!

Also applies to: 613-614, 2203-2206, 2572-2580, 2592-2593, 2873-2873, 2996-2996

Sources/MacParakeetCore/STT/SpeechEngineCapabilities.swift (1)

359-367: LGTM!

Sources/MacParakeetCore/Services/Telemetry/TelemetryEvent.swift (1)

1816-1820: LGTM!

Sources/MacParakeetViewModels/TranscriptionViewModel.swift (1)

809-810: LGTM!

Also applies to: 1451-1451

Tests/CLITests/ModelLifecycleCommandTests.swift (1)

152-152: LGTM!

Tests/CLITests/SpecCommandTests.swift (1)

357-357: LGTM!

Tests/CLITests/TranscribeCommandTests.swift (1)

279-280: LGTM!

Also applies to: 382-383

Tests/MacParakeetTests/STT/SpeechEngineCapabilitiesTests.swift (1)

111-116: LGTM!

Comment thread benchmarks/asr/cohere_multilingual_speed.py
Comment thread benchmarks/asr/cohere_multilingual_speed.py Outdated
Comment thread benchmarks/asr/cohere_multilingual_speed.py
Comment thread benchmarks/asr/run_macparakeet_fleurs.py
Comment thread Sources/CLI/Commands/ConfigCommand.swift
Comment thread spec/02-features.md Outdated
Comment thread spec/03-architecture.md Outdated
Comment thread spec/03-architecture.md
Comment thread spec/adr/001-parakeet-stt.md Outdated
Fail fast when the arm64-only transcribe.cpp package is combined with a universal build, preserve legacy Cohere CLI language values, and bound native lifecycle test waits.

Harden the multilingual benchmark with checked-in runtime, model, fixture, transcript, release, and attestation provenance, and correct the migration documentation.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
benchmarks/asr/test_cohere_multilingual_speed.py (1)

62-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider covering more validate_release_metadata failure branches.

Only the immutability-failure branch is exercised here. Given this function is the security-critical provenance gate, adding a couple more assertRaisesRegex cases (e.g., mismatched predicate.tag, mismatched asset digest, or missing commit-subject PURL) would catch regressions in the other checks at low cost.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@benchmarks/asr/test_cohere_multilingual_speed.py` around lines 62 - 120,
Extend test_release_metadata_requires_matching_immutable_attestation to cover
additional validate_release_metadata rejection branches, such as a mismatched
attestation predicate tag, mismatched asset digest, and missing commit-subject
PURL. For each mutation, use assertRaisesRegex with the expected validation
message, while preserving the existing valid case and immutability failure
check.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@benchmarks/asr/test_cohere_multilingual_speed.py`:
- Around line 62-120: Extend
test_release_metadata_requires_matching_immutable_attestation to cover
additional validate_release_metadata rejection branches, such as a mismatched
attestation predicate tag, mismatched asset digest, and missing commit-subject
PURL. For each mutation, use assertRaisesRegex with the expected validation
message, while preserving the existing valid case and immutability failure
check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 5454354f-108e-482c-8611-125b2137f0c0

📥 Commits

Reviewing files that changed from the base of the PR and between fb9f121 and 1a38c0a.

⛔ Files ignored due to path filters (2)
  • scripts/dist/build_app_bundle.sh is excluded by !**/dist/**
  • scripts/dist/verify_transcribe_cpp_release.sh is excluded by !**/dist/**
📒 Files selected for processing (20)
  • Package.swift
  • Sources/CLI/Commands/ConfigCommand.swift
  • Sources/CLI/Commands/TranscribeCommand.swift
  • Tests/CLITests/ConfigCommandTests.swift
  • Tests/CLITests/SpecCommandTests.swift
  • Tests/CLITests/TranscribeCommandTests.swift
  • Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift
  • benchmarks/asr/README.md
  • benchmarks/asr/cohere_multilingual_speed.py
  • benchmarks/asr/cohere_transcribe_cpp_release.json
  • benchmarks/asr/results/cohere-transcribe-cpp-migration.md
  • benchmarks/asr/results/cohere-transcribe-cpp-multilingual.json
  • benchmarks/asr/run_all.sh
  • benchmarks/asr/run_macparakeet_fleurs.py
  • benchmarks/asr/test_cohere_multilingual_speed.py
  • docs/distribution.md
  • spec/02-features.md
  • spec/03-architecture.md
  • spec/06-stt-engine.md
  • spec/adr/001-parakeet-stt.md
🚧 Files skipped from review as they are similar to previous changes (12)
  • Tests/CLITests/SpecCommandTests.swift
  • benchmarks/asr/run_macparakeet_fleurs.py
  • Sources/CLI/Commands/ConfigCommand.swift
  • benchmarks/asr/results/cohere-transcribe-cpp-migration.md
  • Tests/CLITests/TranscribeCommandTests.swift
  • docs/distribution.md
  • benchmarks/asr/results/cohere-transcribe-cpp-multilingual.json
  • Package.swift
  • spec/06-stt-engine.md
  • spec/03-architecture.md
  • Tests/MacParakeetTests/STT/CohereTranscribeEngineTests.swift
  • benchmarks/asr/README.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Greptile Review
  • GitHub Check: swift-test
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift

📄 CodeRabbit inference engine (AGENTS.md)

**/*.swift: MacParakeetCore owns shared logic and must not own SwiftUI views; small AppKit-backed adapter services are allowed only when Foundation has no equivalent.
MacParakeetViewModels should contain @Observable view models that can be tested without the GUI.
New I/O should use async/await; avoid introducing new completion-handler or Combine patterns.
When ordering or result sequencing matters, make the API async and await it instead of using fire-and-forget Task.
Keep @MainActor work short; move long-running I/O, model, process, and audio work off the actor, then hop back for UI state.
Database access must use GRDB repositories, roughly one repository per table.
UI buttons should use .parakeetAction(...); do not tint whole hosting roots coral.

Files:

  • Tests/CLITests/ConfigCommandTests.swift
  • Sources/CLI/Commands/TranscribeCommand.swift
🧠 Learnings (3)
📚 Learning: 2026-04-25T21:55:25.954Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 138
File: Tests/CLITests/PromptsCommandTests.swift:158-172
Timestamp: 2026-04-25T21:55:25.954Z
Learning: When reviewing Swift tests in this repo, remember that `DatabaseManager()` (the default test database initializer) seeds 6 built-in prompts during migration. As a result, code paths like `PromptRepository.fetchAll()` will not return an empty array, and positional assumptions/ordering-based assertions (e.g., checking `parsed?.first?[

Applied to files:

  • Tests/CLITests/ConfigCommandTests.swift
📚 Learning: 2026-05-13T02:39:59.049Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 283
File: Tests/CLITests/TransformsCommandTests.swift:225-268
Timestamp: 2026-05-13T02:39:59.049Z
Learning: In CLI contract tests under Tests/CLITests (Swift), round-trip tests that exercise the `--database <path>` argument should use a file-backed `DatabaseManager(path:)` (on-disk SQLite) rather than an in-memory queue. Each CLI subcommand invocation independently reopens `DatabaseManager(path:)` from the provided path, so an in-memory `DatabaseQueue` cannot be shared across subcommand runs. Only repository-level history tests (outside the CLI `--database` contract tests) may use in-memory SQLite.

Applied to files:

  • Tests/CLITests/ConfigCommandTests.swift
📚 Learning: 2026-04-16T03:48:03.903Z
Learnt from: moona3k
Repo: moona3k/macparakeet PR: 111
File: Sources/MacParakeet/Views/Transcription/PortalDropZone.swift:40-47
Timestamp: 2026-04-16T03:48:03.903Z
Learning: In SwiftUI, don’t flag `accessibilityReduceMotion` violations for *user-initiated, direct-response* feedback animations. If an animation is tied to a real-time user interaction (e.g., drag state changes like `isDragging`) and provides immediate state feedback (such as an opacity transition from ~0.7→0.9 while dragging), treat it as action feedback rather than automatic/decorative motion. Only expect `accessibilityReduceMotion` gating for automatic or non-essential animations; when the motion is driven by explicit user input, it’s acceptable to leave it ungated.

Applied to files:

  • Sources/CLI/Commands/TranscribeCommand.swift
🪛 ast-grep (0.44.1)
benchmarks/asr/test_cohere_multilingual_speed.py

[warning] 26-26: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.search(rf'^{name}="([^"]+)"$', pins, re.MULTILINE)
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

benchmarks/asr/cohere_multilingual_speed.py

[error] 97-102: Use of unsanitized data to create processes
Context: subprocess.run(
command,
text=True,
capture_output=True,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(os-system-unsanitized-data)


[error] 97-102: Command coming from incoming request
Context: subprocess.run(
command,
text=True,
capture_output=True,
check=False,
)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

🪛 Ruff (0.15.21)
benchmarks/asr/cohere_multilingual_speed.py

[error] 98-98: subprocess call: check for execution of untrusted input

(S603)

🔇 Additional comments (11)
Sources/CLI/Commands/TranscribeCommand.swift (1)

110-110: LGTM!

Also applies to: 302-308, 624-626

Tests/CLITests/ConfigCommandTests.swift (1)

551-560: LGTM!

benchmarks/asr/cohere_transcribe_cpp_release.json (2)

3-12: 🎯 Functional Correctness

Verify the custom attestation predicate type/schema against the fork's actual release workflow output.

attestation_predicate_type is pinned to "https://in-toto.io/attestation/release/v0.2", and validate_release_metadata in benchmarks/asr/cohere_multilingual_speed.py (lines 154-162) checks top-level predicate.repository/predicate.tag fields directly against this type. This doesn't match GitHub's standard build-provenance attestation format, whose default/well-known predicate type is https://slsa.dev/provenance/v1 with fields nested under predicate.buildDefinition.externalParameters.workflow.*, nor any predicate type in in-toto's official catalog (link, test-result, human-review, runtime-trace, SCAI, VSA). Custom predicate URIs are permitted by the in-toto spec, so this is plausible if the owned fork's release CI emits a bespoke attestation with exactly this shape — but if the fork's workflow instead uses the standard gh/SLSA provenance format, validate_release_metadata will always fail closed (safe, but blocks every benchmark/release-verification run).

Please confirm the owned fork's release workflow (DudeMeister23/transcribe.cpp at the pinned tag) actually emits an attestation with predicateType: "https://in-toto.io/attestation/release/v0.2" and this exact predicate.repository/predicate.tag/subject shape.


13-42: LGTM!

benchmarks/asr/cohere_multilingual_speed.py (3)

97-115: 🩺 Stability & Availability | ⚡ Quick win

Add a timeout to gh subprocess calls.

command_json() runs subprocess.run with no timeout, and it backs both gh release view and gh release verify in verify_release_provenance. If gh hangs (auth prompt, network stall), the benchmark run blocks indefinitely instead of failing fast.

🛡️ Proposed fix
 def command_json(command: list[str], description: str) -> dict:
     process = subprocess.run(
         command,
         text=True,
         capture_output=True,
         check=False,
+        timeout=60,
     )
The static-analysis "OS command injection"/"subprocess from request" hints on this block are false positives: `subprocess.run` is called with a list (no `shell=True`), and the command arguments (`runtime["release_tag"]`, `runtime["repository"]`) come from the checked-in, schema-validated release manifest, not from attacker-controlled/request input.

Source: Linters/SAST tools


36-95: LGTM! The fail-closed provenance verification, exact-match transcript validation, and stable fixture-ID/digest publishing (replacing absolute paths) all address the prior review feedback correctly.

Also applies to: 118-263


392-499: LGTM! Provenance verification happens before any fixture/model use, and the payload now records verified runtime/model provenance fields plus stable fixture identifiers instead of local paths.

benchmarks/asr/run_all.sh (1)

27-27: LGTM!

benchmarks/asr/test_cohere_multilingual_speed.py (1)

1-170: LGTM otherwise — good coverage of manifest/pin parity, fixture checksum mismatch, and transcript-mismatch fail-closed behavior, and the committed-result assertions correctly guard against reintroducing absolute paths.

spec/02-features.md (1)

727-727: LGTM! The unit for the Cohere download size was corrected to ~1.65 GiB (matches the pinned 1,770,270,208-byte model size in cohere_transcribe_cpp_release.json), addressing the prior review comment, and the language/local-execution wording is consistent with the new automatic-detection, transcribe.cpp-backed behavior.

Also applies to: 758-758, 771-771, 1896-1896, 1916-1916

spec/adr/001-parakeet-stt.md (1)

15-15: LGTM! The amendment now states the arm64 XCFramework prerequisite is satisfied via the pinned immutable release and SHA-256, resolving the prior contradiction with ADR-029's evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant