f23d11dc64
* feat(web): add voice mode to task create dialog prompt Wires the existing VoiceInputButton (introduced in #1159 for the chat composer) into the task-create dialog's prompt toolbar so users can dictate the initial task description. - TaskFormInputs gains an internal insertAtCursor that splices the transcript at the textarea caret with a single leading space when it follows a non-whitespace character, matching the chat composer's behaviour. A pending-cursor ref + useLayoutEffect restores the caret position after React commits the new value. - An optional onVoiceAutoSend prop is threaded from TaskCreateDialog down through DialogPromptSection -> TaskFormInputs -> VoiceInputButton. The dialog points it at formRef.current?.requestSubmit() so dictation can create the task hands-free; every existing submit gate still applies via the disabled submit button. - Voice mode is gated globally on userSettings.voiceMode.enabled, so the button self-hides for users who turned it off in settings and self-greys on browsers without a usable engine. * fix(web): invoke submit handler directly for voice auto-send `HTMLFormElement.requestSubmit()` is missing on Safari < 16, so the previous wiring silently failed with a TypeError on browsers where voice mode itself works (Safari 14.5-15 supports Web Speech / Whisper Web). Drop the form ref and call `setup.guardedHandleSubmit` with a synthetic event instead. `guardedHandleSubmit` only reads `preventDefault` off the event, and every validation gate (`validateForCreate`, session-mode description/agent checks, edit-mode title check, `submitBlockedReason`) lives inside the submit handler — so dictation with incomplete fields still no-ops, identical to the prior requestSubmit-based behaviour. This also matches the chat composer's pattern of calling the same submit function the send button uses. independent-review: voice auto-send Safari < 16 compat * test(web): expand voice splice cases for task-create dialog Adds adversarial coverage for the at-cursor splice helper that backs voice-mode dictation in the task-create dialog: - multi-line description with caret on a line boundary - transcript with internal newlines preserved as-is - existing tabs / newlines before the caret treated as whitespace - session-mode renders the voice button Splits the test file into a rendering-and-wiring `describe` and a splice-behaviour `describe` so each arrow function stays under the 100-line `max-lines-per-function` lint cap. qa: adversarial voice splice cases + session-mode parity --------- Co-authored-by: Kandev Agent <agent@kandev.dev>