# Journey 6: Graceful Degradation

**Persona**: All users
**Scenario**: Internet goes down, tunnel fails, engine crashes
**Principle**: The proxy ALWAYS starts. Everything else is progressive enhancement.

## Degradation Matrix

| Condition | Behavior |
|-----------|----------|
| **No internet** | Proxy still runs locally. All local inference works. |
| **No tunnel** | Device still registers via heartbeat when internet returns. Dashboard shows device status. |
| **No relay server** | Fallback to Tailscale/Cloudflare if installed. Otherwise local-only. |
| **No Ollama** | Auto-provisions Ollama + starter model on first run. If Ollama crashes mid-session, proxy returns clear error, doesn't crash itself. |
| **Port conflict** | Auto-finds next available port. Never fails to start. |
| **VRAM insufficient** | Suggests smaller model, pulls it automatically. |
| **Relay disconnected** | Local proxy continues. Auto-reconnect with exponential backoff. |
| **Token expired** | Auto-refresh via control stream. Transparent to user. |
| **Network change** | Re-connect on IP change (WiFi switch). |

## The Golden Rule

**The proxy ALWAYS starts.** No matter what subsystem fails — tunnel, auth, engine, internet — the local proxy boots and serves whatever it can. Everything else is progressive enhancement layered on top.

## Success Criteria

- [ ] Proxy starts with zero internet connectivity
- [ ] Proxy starts with no inference engine installed
- [ ] Proxy starts when default port is taken
- [ ] Proxy survives Ollama crash mid-session
- [ ] Relay reconnects within 5s (p95) after network interruption
- [ ] No user intervention required for any degradation scenario

## Features Exercised

- 5-phase pipeline resilience (`llmhosts/up.py`)
- Progressive enhancement architecture
- Automatic port scanning
- Engine provisioner fallback
- Relay reconnection with exponential backoff + jitter
- HTTP heartbeat fallback (when WebSocket unavailable)
