fix(review): remediate 3 P0s + P1s found by adversarial review of the reliability batches - #81
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c0066f681
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let _recording_mutation_guard = self | ||
| .recording_mutations | ||
| .lock() | ||
| .unwrap_or_else(|poisoned| poisoned.into_inner()); |
There was a problem hiding this comment.
Release the recording lock before retention cleanup
With the default retention settings (PreserveLimit, history limit 5), saving the sixth recording makes cleanup_old_entries() produce deletion candidates while this guard is still held. That cleanup path calls delete_entries_and_files(), which attempts to lock the same non-reentrant recording_mutations mutex again, so the save path deadlocks instead of completing the transcription history write. Drop the guard before running retention cleanup or use an inner deletion helper that does not reacquire it.
Useful? React with 👍 / 👎.
| if settings.adaptive_language_shortlist == snapshot.written_adaptive_language_shortlist { | ||
| settings.adaptive_language_shortlist = snapshot.previous_adaptive_language_shortlist; |
There was a problem hiding this comment.
Keep the language tuple atomic during rollback
If a user changes the selected language while load_model() is running, and that language is already present in the switch-written shortlist, change_selected_language_setting updates only selected_language/mode and leaves the shortlist equal to written_adaptive_language_shortlist. On load failure this branch restores the old shortlist while preserving the new selected language, which can leave Single mode pointing at a language absent from the shortlist and break the language picker/cycling invariants. Treat the language fields as one CAS tuple or revalidate after the partial rollback.
Useful? React with 👍 / 👎.
Batch 1 changed set_active_model to return ModelSwitchOutcome { reason }.
The Playwright mock still returned the pre-batch unit (null) shape, so
modelStore.selectModel's result.data.reason access threw during first-run
onboarding, stalling the model->shortcut step. Update the mock to the real
shape and null-guard the frontend read defensively.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Before Submitting This PR
Human Written Description
I had the reliability batches adversarially reviewed after they were already written and passing, and the review found three P0s that both the code review and my device testing had missed — all of them on failure paths rather than happy paths. That is the lesson here: everything worked when things went right. A password field whose role couldn't be classified on Linux got read anyway; deleting a recording whose file was locked reported success and orphaned the audio; and approving a recovered dictionary rule silently destroyed the very rule the migration had saved. This PR fixes those plus six related P1s.
P0s fixed
getRoleNameor returned a non-string, the password check was skipped and the protected text was read. Now a role that cannot be classified is a secure-check failure (fails closed), matching the Windows and macOS behavior.replacement_of = None. Promotion now merges the recovered rule into the retained entry, and re-records rather than drops it when two distinct rules conflict.Also fixed
x → umunder locked English). Dictionary output phrases are now protected from language-default filler removal; custom fillers stay authoritative.Single+auto,Multilingual+<2 languages) as current.en-US-u-ca-gregory).Testing
tsc, ESLint, Prettier, translations, settings-lock coverage, cargo-deny: all pass.approving_v3_recovered_rule_merges_into_retained_entryfail; restoring it passes.Still wants real-device verification (cannot be proven statically): Linux AT-SPI over-block behavior on real desktop apps, locked-file deletion against the real Windows filesystem, and model-switch rollback under genuine concurrency.
AI Assistance
If AI was used:
🤖 Generated with Claude Code