fix(coordinator): post-audit logic-review hotfixes#393
Merged
Conversation
Two real bugs surfaced by the 2026-05-10 end-to-end logic review of beta after the 8-PR audit-fix wave landed. 1. coordinator.rs:2313 — `acquire_recording_mute(inner, "qa");` was missing `.await`. PR #391 (`6171df61`) made the function `async fn` and updated the dictation call site at coordinator/dictation.rs:451, but the QA call site was missed. Effect: when a user has `mute_during_recording = true` and triggers QA via Right Option, the returned Future is dropped on the next line, `spawn_blocking` is never scheduled, holders never increments, and system audio is NOT muted (e.g. YouTube playback continues into the QA recording). Both the matching `release_recording_mute(inner, "qa")` calls become no-ops (early return at holders == 0). The compiler was emitting `unused_must_use` for this site (verified before this commit). Fix: add `.await`. 2. coordinator/dictation.rs:843-849 — PR #387 (`ce82fcd9`) was framed as "clear focus_target on cancel regardless of phase", but the only code path that gained the unconditional clear was `finish_cancel_session_state`. cancel_session deliberately skips that helper for Processing (so end_session can drive its own teardown), and end_session's "ASR-finished, cancelled" exit at dictation.rs:843-849 set phase=Idle but never touched focus_target. Result: cancel-during-Processing leaves a stale `usize` focus slot in state.focus_target until the next begin_session_state overwrites it. Today the leak is bounded (no documented reader between cancel and next begin), but it violates PR #387's stated contract and is a silent footgun for any future reader of focus_target on that interval. Fix: in the cancelled-after-ASR exit branch, take the state lock once and clear both phase and focus_target together. Source: docs/logic-review-2026-05-10.md (subagent end-to-end review). 185/185 lib tests pass; cargo check clean (unused_must_use gone). Manual verification checklist for both fixes in the review doc.
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
5 tasks
pull Bot
pushed a commit
to yimmy23/openless
that referenced
this pull request
May 10, 2026
10 PRs landed on beta this cycle: - Open-Less#377 paste shortcut configurable (issue Open-Less#360) - Open-Less#386 TS UserPreferences updateChannel alignment - Open-Less#387 focus_target leak on Processing-phase cancel - Open-Less#388 [严重] MacHotkeyAdapter::shutdown stops CFRunLoop + tap - Open-Less#389 emit_capsule window.show/hide off audio thread - Open-Less#390 QA / dictation hotkey routing race - Open-Less#391 audio-mute spawn_blocking (async hygiene) - Open-Less#392 hotkey supervisor + global dispatcher exit signal - Open-Less#393 post-audit logic-review hotfixes (QA mute .await + focus_target Processing branch) - Open-Less#394 in-process credentials cache (kills repeated Keychain prompts) Bump 4 files: package.json, tauri.conf.json, Cargo.toml, Cargo.lock.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
User description
Summary
Two real bugs surfaced by the 2026-05-10 end-to-end logic review of beta after the 8-PR audit-fix wave landed (full report at `docs/logic-review-2026-05-10.md`, kept local).
Bug 1: `coordinator.rs:2313` — QA path missing `.await`
PR #391 (`6171df61`) made `acquire_recording_mute` `async fn` and updated the dictation call site (`coordinator/dictation.rs:451`), but the QA call site was missed.
Effect: when `mute_during_recording = true` and the user triggers QA, the returned Future was dropped on the next line, `spawn_blocking` was never scheduled, `holders` never incremented, system audio was NOT muted (YouTube/etc. kept playing into the QA recording). Both matching `release_recording_mute(inner, "qa")` calls became no-ops (early return at `holders == 0`). The Rust compiler was emitting `unused_must_use` for this exact line.
Fix: `+ .await`. Compiler warning gone.
Bug 2: `coordinator/dictation.rs:843-849` — `focus_target` not cleared on cancel during Processing
PR #387 (`ce82fcd9`) was framed as "clear focus_target on cancel regardless of phase", but the unconditional clear only landed in `finish_cancel_session_state`. `cancel_session` deliberately skips that helper for the `Processing` branch (so `end_session` drives its own teardown), and `end_session`'s "ASR-finished, cancelled" exit set `phase = Idle` but never touched `focus_target`.
Effect: cancel-during-Processing leaves a stale `usize` focus slot in `state.focus_target` until the next `begin_session_state` overwrites it. Today bounded (no documented reader on that interval), but violates PR #387's stated contract and is a silent footgun for future readers.
Fix: in the cancelled-after-ASR exit branch, take `state.lock()` once and clear both `phase` and `focus_target` together.
Test plan
PR Type
Bug fix
Description
Add missing
.awaitonacquire_recording_mutein QA pathClear
focus_targeton Processing‑phase cancel inend_sessionDiagram Walkthrough
flowchart LR QA["begin_qa_session"] -- ".await" --> Mute["acquire_recording_mute('qa') (mute engages)"] Cancel["end_session (cancel after ASR)"] -- "clear focus_target" --> Focus["state.focus_target = None (no stale handle)"]File Walkthrough
coordinator.rs
Await QA audio mute callopenless-all/app/src-tauri/src/coordinator.rs
.awaittoacquire_recording_mute(inner, "qa")to prevent droppedfuture
dictation.rs
Clear focus_target on Processing cancelopenless-all/app/src-tauri/src/coordinator/dictation.rs
focus_targetwhen cancelling during Processing phase to preventstale handle