"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 keeps one core while supporting many surfaces, and Firekeeper is one of those surfaces following the same discipline.