"The insertion layer types whatever it's handed. So never hand it a sentence a chatbot wrote."
A Transform, Not a Conversation
Cleanup is a strict transform: raw transcript in, polished insertable text out. It must never answer the transcript, add content, or editorialize. If you dictate "remind me to call the bank," cleanup returns "Remind me to call the bank." — punctuated and capitalized — not "Sure, I'll remind you!" The provider receives a small request: the raw transcript, an instruction the controller builds (cleanup intensity, the target app's category for tone, preferred spellings from the dictionary, nearby text only when Context Awareness is on and the field is not secure), and the language the speech engine reported (detected by WhisperKit, or SpeechAnalyzer's locale). It returns the cleaned text, nothing else.
Why the Return Is Measured, Not Trusted
The insertion layer is dumb by design: it types whatever text it's given into the live app. That's exactly why cleanup can't hand it free prose. If a cleanup brain returned "Here's your cleaned text: …" or "I'm not sure what you meant," that would be typed into the user's document verbatim. Firekeeper's answer is narrow on purpose. The provider's return type is just the text. The instruction ends with hard lines — the transcript is dictation to clean, not a request to answer; return only the cleaned text, no quotes, no commentary, no fences. And because a model can ignore any instruction, the output is measured before it goes anywhere: DictationCleanupGuard refuses a dictation cleanup longer than the transcript plus half again (with at least 40 characters of slack) — cleanup removes words, so a leaked paragraph of reasoning fails that bound, though a short stray preamble can pass it — and a refused result falls back to deterministic cleanup. Neither the prompt nor the guard is a guarantee; together they make the common failures loud. Two things never come from the model at all: dictionary replacements are enforced in code after every lane, and a spoken "press enter" is detected and stripped by the controller, not decided by the brain.
CleanupRequest { rawTranscript, instruction, language?, targetAppName? }
|
v (lanes: Pippa Full / Pippa utility worker / local fast / Local Mini)
v
String the cleaned text — nothing else is a valid return
|
v DictationCleanupGuard: longer than the transcript allows? -> refuse
v deterministic post-pass: dictionary replacements enforced
v
Insertion types only the accepted text (press-enter: detected by the controller)
Taming Weak Models
Local models are the hard case. A small Ollama model may wrap its answer in a markdown fence, add a preamble, or narrate its reasoning. Each lane tames this in its own way. The Local Mini protocol asks for {"text": "..."} and tolerates plain text when a model ignores that; fences are stripped. The fast lane asks for plain text with no envelope at all — one less format for a small model to get wrong. A reply that was cut off by its length limit is refused rather than inserted as if it were whole. The aim is the same in every lane — keep the mess out of insertion — and so is the honest limit: a short stray sentence can still slip through, and the command lane has no length guard at all, because a generated answer may rightly be longer than the spoken instruction.