Conversation
8d594f9 to
0f88105
Compare
kitlangton
left a comment
There was a problem hiding this comment.
Thanks for putting this together. On-demand rewriting is useful, and the existing ordered processor/output queue is the right place for it. I found two behavioral blockers before landing it:
- The output worker publishes
state.last_transcriptbeforefinish_outputpastes. A concurrent Rewrite Last can therefore accept text from a paste that later fails or is cancelled. Restoring the snapshot afterward cannot retract the already accepted rewrite. Please publish the shared last transcript only after successful output, and cover the in-flight paste failure/cancellation case. - Both shortcuts default to active on new installs and upgrades, including when OpenCode is absent. Please make these explicitly configured/opt-in so upgrading does not silently reserve two more global shortcuts.
Also, rewrite_generates_even_when_live_processing_is_disabled returns at the initial cancellation check, before profile selection or generation. It does not establish its named behavior; that needs a controlled generation boundary. The new in-process native layout test should use the existing subprocess layout harness rather than introducing process-global layout initialization into the parallel unit suite. Please add the affected feature map as well.
Add an Option-Shift-O shortcut that re-runs the last completed dictation through OpenCode and pastes the cleaned-up result at the cursor. Unlike live mode processing, the rewrite always generates with the matching mode's configured model even when automatic processing is off; failures paste nothing, the rewritten output never becomes the new last dictation, and the job flows through the existing processor queue so ordering, bounded admission, cancellation, and history capture are inherited. The shortcut is user-configurable from Settings with conflict validation, disables itself on load when it would shadow an existing binding, and shows the processing indicator through the standard Submitted -> Stage pipeline. Also fixes keyboard.rs layout-query concurrency (previous commit) that the new tests surfaced. AGENTS.md documents the invariant.
- Serialize HIToolbox keyboard-layout queries behind a lock: concurrent TISCopyCurrentKeyboardLayoutInputSource calls abort the process, which the new tests hit deterministically under parallel execution. - Drop the stored processor sender before joining processor workers so shutdown cannot block forever on a channel that never disconnects. - Publish Paste/Send text into the shared last-transcript mirror before the paste runs and restore it on failure, so a rewrite submitted while a paste is still in flight rewrites the transcript the user just heard. - Reject a second rewrite while one is already generating instead of queueing duplicate generations of the same text. - Report cancellation before the model gate, cover edit- and meeting-conflict cases in tests, and reword the normalized-settings log message.
- Surface user cancellation of a rewrite as a clean cancel instead of a failed rewrite (error tone) in the processor error path. - Fill the keyboard layout cache on cold misses so every key_code_for caller benefits from the serialized TIS scan. - Give rewrites their own DictationPhase::Rewritten so the activity feed no longer claims the dictation was merely pasted again. - Cover RewriteLast in the Voice Action takeover test.
Add a user-configurable Option-Shift-R shortcut that captures the selected text in the focused app (Accessibility, same as Voice Action), runs it through the on-demand OpenCode rewrite pipeline, and pastes the result over the selection. Requires a non-empty selection and OpenCode; failures paste nothing and never touch the last dictation. Also upgrades RewriteLast to cancel-and-replace: a second press cancels the in-flight rewrite and starts a fresh one instead of erroring.
Block Paste and Send behind a barrier, call rewrite_last while output is still running, then finish with success, error, or cancel-before-commit. Rewrite must enqueue only the previously published transcript in every case; shared state publishes the new text only after a successful paste.
Move the concurrent key_code_for stress case into keyboard_layout so process-global HIToolbox init stays out of the parallel unit suite.
Rewrite last/selection stay inactive until assigned. Ordinary Paste and Send publish the shared last transcript only after successful output. No migration flag: the feature never shipped, so missing fields default to None like a fresh install.
Configure runtime hotkeys before matching Option-Shift-O, assert None bindings are neither matched nor suppressed, and check PasteLast conflicts only when rewrite is actually saved.
Treat only a committed in-flight rewrite as blocking. Escape or cancel_latest already marks the job cancelled while OrderedOutputs may still hold that Cancelled event behind an earlier paste; a second press must start a fresh rewrite instead of reporting already in progress.
Disable sets the hotkey to None and persists; reassign is via capture, not a preserved inactive binding.
0f88105 to
1ae046c
Compare
|
Thanks for the careful review. Both blockers and the test findings are addressed on the branch, which is now rebased on current main. Publish after successful output. The output worker no longer writes Opt-in shortcuts. Both rewrite hotkeys now default to Generation boundary test. Added a Layout test. Moved into the existing subprocess harness in Feature map. Added the On-Demand Rewrites section in 481 tests pass locally; the only failure is the pre-existing personal_commands provisioning environment issue on this machine, unrelated to this PR. |
Document that Escape or cancel_latest leaves a cancelled rewrite buffered until OrderedOutputs drains, and a second press starts a fresh rewrite.
Closes #62
Summary
Two shortcuts built entirely on the existing OpenCode rewrite machinery, addressing the lost-flow-of-thought problem after accidental or messy captures (#62):
src/suppression.rs,src/parakeet.rs): re-submits the last completed transcript throughProfiles::rewrite_cancellable(existing processor queue: bounded admission, ordered output, Escape cancellation) and pastes the result at the cursor. Always generates with the matching mode's configured model, even when the automatic mode-processing toggle is off. Failures paste nothing. The rewritten output never becomes the new last dictation, so Option-Shift-V keeps returning the original. Duplicate presses cancel-and-replace the in-flight rewrite.src/keyboard.rs): concurrentTISCopyCurrentKeyboardLayoutInputSourcecalls abort the whole process (confirmed via a macOS crash report and reproduced by the new tests under parallel execution); TIS access is now serialized behind a lock and the cache is filled on cold misses.Both shortcuts are user-configurable in Settings with the standard capture UI, conflict validation, and load-time disable when they would shadow an existing binding. History records rewrite outputs under a new
Rewritekind; AGENTS.md gains the matching invariant bullets.Verification
cargo fmt --checkcargo test --locked --bin voice-control(one pre-existing unrelated failure:personal_commands::tests::clean_workspace_provisioning_preserves_user_config_on_refresh, fails on clean main in this environment)cargo clippy --locked --all-targets --all-features -- -D warningsgit diff --checkA note from me
I use HEX every single day and I am grateful for it, it genuinely changed how I work. I do not care about contributor credit at all; the feature is what matters to me. If you would rather design or land this yourselves, or if you would prefer I stop opening PRs on your repository, that is completely fine and there are no hard feelings. Happy to close this and keep using the app either way.