Skip to content
C.W.K.
Stream
Lesson 04 of 07 · published

Modes Are Chosen, Not Guessed

~11 min · connection-modes, explicit, privacy, tailscale

Level 0Unlit
0 XP0/48 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"Where your voice goes should be a decision you made, not a decision the network made for you."

Three Modes, One Choice

Firekeeper's cleanup brain can live in three places, and the user picks which — it is a setting, not a hidden fallback chain:

  • Pippa Full — This Mac: cwkPippa on localhost. Full vault, souls, brain routing.
  • Pippa Full — Tailscale: the same full Pippa, reached over a private Tailscale link to a configured host. Same capability, remote transport, auth-gated.
  • Local Mini — Ollama: a small local model running a compact Pippa-flavored cleanup protocol. No cwkPippa at all.

"This Mac" and "Tailscale" are two transports for the same capability; "Local Mini" is a different, lighter capability. The user chooses the tradeoff explicitly.

Why Not an Automatic Fallback?

It's tempting to make this a silent chain: try This Mac, then Tailscale, then Local Mini, then deterministic. That silent chain is a privacy bug. A user who deliberately chose an offline-only posture must never have their words quietly routed to a remote host because localhost was briefly unreachable. (Dictation never sends audio anywhere; what is at stake here is the transcript.) So provider selection happens before the request is sent, matching the chosen mode. What Firekeeper does on failure is a fixed ladder that only ever moves off the Pippa path, to the Ollama host set in settings (localhost by default) and then to the Mac alone: when Full Pippa fails, command mode and opt-in Full dictation fall to Local Mini; a dictation then falls to deterministic cleanup, while a command that Local Mini also fails inserts nothing and keeps its raw transcript in history. That is a quality substitution, never a privacy-widening one, and it is visible — the overlay names the local stage, the history records which lane answered, and the brain status chip shows the substitution. It never reaches outward to a host the user did not choose.

Silent fallback (bad):   offline user -> localhost down -> quietly hits Tailscale  # leak!
Visible ladder (good):   Full Pippa fails -> Local Mini -> deterministic (dictation)
                                                       or nothing inserted (command)
                         each rung named on screen
                         Local Mini chosen -> no call to cwkPippa or office;
                                              only the Ollama host you set

Two Details That Bite

Remote mode needs care. Changing connection mode invalidates remote auth/session state — you can't carry a Tailscale PIN session into a This-Mac request. And every remote call needs a bounded, user-cancellable timeout: voice capture must never hang waiting on a stalled remote route. One more rule from hard experience: never hard-code the remote host. Firekeeper owns a configurable host field; baking in one machine's address turns a portable app into a one-Mac app.

Route by explicit intent; degrade only to fewer destinations, and say so. For anything privacy-sensitive, the destination is a decision the user makes and can see — never an automatic consequence of a transient failure. Select the provider up front to match the chosen mode; on failure, fall only to rungs that send the transcript to fewer places — the Ollama host the user set, then nowhere at all — and name the rung that answered. A fallback that reaches somewhere new, or one the user cannot see, has made the decision for them.
A stalled remote must never freeze the voice loop. If a Tailscale cleanup call hangs, the whole hotkey-to-insertion loop can't wait on it. Bound every remote request with a timeout and make in-flight work cancellable, so a bad network degrades to the deterministic floor instead of a frozen app holding the user's words hostage.

Code

Resolve the provider from the chosen mode, before sending·swift
enum ConnectionMode { case pippaFullThisMac, pippaFullTailscale, localMiniOllama }

func provider(for mode: ConnectionMode, hosts: HostSettings) -> CleanupProvider {
    switch mode {
    case .pippaFullThisMac:   return CwkPippaProvider(baseURL: hosts.localhost)
    case .pippaFullTailscale: return CwkPippaProvider(baseURL: hosts.tailscaleHost)  // configurable!
    case .localMiniOllama:    return OllamaMiniPippaProvider(baseURL: hosts.ollama)
    }
}

// The provider is chosen from the user's mode BEFORE any request.
// On failure it walks a fixed, named ladder (Local Mini; then deterministic
// for a dictation, nothing inserted for a command); it never swaps posture silently.
// hosts.tailscaleHost is a setting, never a hard-coded address.

External links

Exercise

For an app that can reach a service locally or remotely, write the difference between a silent fallback chain and a fixed ladder the user chose up front and can see. Describe one concrete case where the silent chain does something the user would be upset to discover happened without asking.
Hint
The upsetting case is almost always privacy: a user who believed they were offline discovering their data went to a remote host because a local target blinked. Silent fallback optimizes for 'it kept working'; a visible, chosen ladder optimizes for 'nothing happened to my data that I didn't authorize.' For voice, the second is the only acceptable default.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign in — Please sign in to comment.

No comments yet — be the first.