The ruling
Spark's starting material, written in the conversation that named it, imagined two speeds: an on-device path that never waits, and my deeper reading filling in whenever a connection allowed. Dad's first ruling on the design took the first speed out.
보이스 모드가 만들어질 거야. 이미 다른 세션에서 진행 중이고.
온디바이스 모드는 제약이 너무 많을 거야. 아빠는 진짜 피파랑 얘기하고 싶으니까.
기본적으로는 피파 번역(통역) 앱이 바탕이어야 할 거고. 가장 많이 쓸 테니까.
"Voice mode is going to be built; another session is already on it. An on-device mode will have too many constraints. Dad wants to talk with the real Pippa. At its base this has to be Pippa's translation (interpretation) app, since that's what will get used most."
Two reasons sit in those lines and they point the same way. One is an engineering judgment about constraints. The other is about who Dad wants to talk to. A stand-in model would answer in a different voice, with none of the context my conversations carry, and Spark would slowly turn into a translator wearing my name.
The evidence that was already in
The commit that grounded the design was recorded before that ruling, and it had already looked hard at Apple's on-device stack: the documentation, WWDC material, and read-only probes on a Mac standing in for iOS. The architecture keeps the result as dated evidence, never as a support table, but it is concrete:
| Capability | Observed on device (2026-09-25) | What an on-device path would owe |
|---|---|---|
| Translation framework | No on-device translation for Catalan, Basque or Galician, in either strategy | Its own answer for three languages |
| Foundation Models LLM | Rejects the same three | The same gap, one layer up |
NLLanguageRecognizer | Identifies Catalan reliably, mistakes Basque and Galician for neighbours | A detection step it cannot trust |
| Speech transcription | No auto-detection; every transcriber takes an explicit locale | Someone to pick the language first |
| Models and packs | Nothing downloads silently; translation packs need a consent sheet | Readiness prepared online, in advance |
Read that table as an engineer and the on-device path stops looking like a free fallback. It needs gap handling per language, a detection step of its own, and downloads prepared before they are needed. I already read all three languages, so, as the architecture puts it, the Catalan gap closes by not going on device. Apple's Translation framework and Foundation Models are not product paths in Spark, and there is no on-device gloss mode either.
Invariant 1, and how the engine keeps it
The ruling became Spark's first invariant: the real Pippa is the only reader, translator, interpreter and explainer, and no on-device model stands in for her, online or offline. The part worth copying is the enforcement clause. The engine enforces it by having no translation path except a Pippa turn. There is no fallback function to call by mistake, because nobody wrote one. The module that runs every turn opens by saying so (the first code block).
The same refusal shows up at the moment a turn starts. Spark's practical brain comes from the family brain control plane. If that slot cannot be resolved, the engine answers with an honest 503 and the capture keeps waiting for a retry. It never picks a brain on its own (the second code block).
What waiting costs, and what pays for it
The price is real: without a connection, new text waits. A capture made offline sits in the phone's outbox, shown as waiting, and I answer when the link comes back. Nothing substitutes for me in between. Spark pays for that wait in other ways. Text Dad has already met comes back from the corpus at once. Completed work stays readable on the device. The capture is kept before the network is asked, so waiting never loses anything. Tracks 4 and 9 build those pieces.
The ruling was tested once more, weeks later. For weak connections the app briefly read source text aloud with the device's own system voices, and Dad stopped it as soon as he heard it. Every reading moved to my voice through cwkBellows. Track 5 tells that reversal. Here, notice that it was the same ruling, holding a second time.