C.W.K.
Stream
Lesson 04 of 04 · published

Modes Are Chosen, Not Guessed

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

Level 0Unlit
0 XP0/36 lessons0/12 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 audio quietly routed to a remote host because localhost was briefly unreachable. A user expecting full-Pippa quality must never silently get a weak local result. So provider selection happens before the request is sent, matching the chosen mode — and when the chosen target fails, the app offers alternatives (retry, switch to the other Full target, drop to Local Mini, insert raw) rather than picking one behind the user's back.

Silent fallback (bad):   offline user -> localhost down -> quietly hits Tailscale  # leak!
Explicit choice (good):  offline user -> localhost down -> "retry? / Local Mini? / raw?"

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, offer alternatives on failure. 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, surface choices rather than silently substituting a different privacy or quality posture.
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 'offer raw insert' 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 the app offers choices; it never silently swaps posture.
// 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 an explicit-choice-with-offered-alternatives. 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'; explicit choice 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 inPlease sign in to comment.

No comments yet — be the first.