"Abstract the one thing that varies. Leave everything else gloriously concrete."
The Inherited Rule
Firekeeper doesn't invent its architecture from scratch — it inherits a rule from the Pippa house: put the abstraction boundary in exactly one narrow place, and let everything specialize downstream of it. In the brain, that seam is the streaming-model API; above it, the whole app is written concretely, assuming one shape. In Firekeeper the same rule applies to two seams: the STT engine and the cleanup brain. Everywhere else, the code is direct and readable — no interfaces for the sake of interfaces.
Why Not Abstract Everything?
The tempting mistake is to make the whole app "provider-neutral" — abstract the audio layer, the insertion layer, the settings layer, all of it, just in case. That trades a real cost for an imaginary benefit. Every abstraction is a layer of indirection someone has to read through. You pay that tax in every file, forever, to enable a swap that happens in one place. The narrow-seam rule inverts it: pay the abstraction cost exactly where variation actually lives, and nowhere else.
Broad abstraction (avoid) Narrow seam (do this)
------------------------ ---------------------
every layer is an interface only STT + cleanup are interfaces
swap-ready everywhere swap-ready where swaps happen
indirection tax in every file concrete, readable everywhere else
flexibility you'll never use flexibility exactly where you need it
Cost Flows Downstream
The deeper principle: when a new variant needs something (a new STT engine, a new cleanup brain), it absorbs the cost of fitting the existing seam — the seam does not grow new abstractions to accommodate it. Concrete-first, specialize-on-demand. You never generalize in anticipation of a variant that might arrive; you specialize when it actually does. That's how the Pippa family stays small at the core while supporting many surfaces, and Firekeeper is one of those surfaces following the same discipline.