# Phase 20: Offline Mode Hardening - Discussion Log

> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.

**Date:** 2026-04-10
**Phase:** 20-offline-mode-hardening
**Areas discussed:** Offline indicator UX, Edit queueing scope, Flush-then-sync ordering, Connectivity detection

---

## Offline Indicator UX

### Q1: Indicator prominence

| Option | Description | Selected |
|--------|-------------|----------|
| Status dot is enough (Recommended) | Existing red dot + "Disconnected" text in the status bar is sufficient | ✓ |
| Add a top banner | Persistent banner across the top of the dashboard | |
| Dim the refresh controls | Visually disable/dim refresh buttons with tooltip | |

**User's choice:** Status dot is enough
**Notes:** None

### Q2: Partial connectivity

| Option | Description | Selected |
|--------|-------------|----------|
| No, binary online/offline (Recommended) | Either both APIs are reachable or the app is "offline" | |
| Yes, show per-service status | Distinguish GitHub-down vs Shopify-down vs both-down | |

**User's choice:** Other (free text)
**Notes:** User described a broader offline-first architecture: "All app actions should happen offline, where the app's own database and local storage is its UI's source of truth. All changes modify the local stuff directly. Every change is also enqueued immediately, and a separate queue processor enacts the changes on the remote sources of truth. Syncs still only happen periodically." This reframed the entire phase from "handle disconnections" to "offline-first architecture."

---

## Edit Queueing Scope

### Q3: Which actions should write-local-then-queue

| Option | Description | Selected |
|--------|-------------|----------|
| Serial state transitions | Assigning/unassigning serial units, lifecycle transitions | |
| Item/product changes on cards | Adding/removing products from a card's item list | |
| All current write actions (Recommended) | Every action that currently writes to a remote API | ✓ |

**User's choice:** All current write actions
**Notes:** None — follows naturally from the offline-first model.

### Q4: Pending edit UI indicator

| Option | Description | Selected |
|--------|-------------|----------|
| No visible indicator (Recommended) | The user shouldn't care — edit is saved locally | |
| Pending count in status bar | Show "3 pending" next to the connection dot | |
| Per-card sync indicator | Cards with unflushed edits show a small sync icon | |

**User's choice:** Other (free text)
**Notes:** "While there are pending unflushed edits, make the green status indicator circle 'breathe' (gradual lighter->darker->lighter loop)." A specific animation request — subtle and glanceable.

---

## Flush-then-Sync Ordering

### Q5: Flush vs sync timing

| Option | Description | Selected |
|--------|-------------|----------|
| Flush first, then sync (Recommended) | Drain pending edit queue before pulling fresh data | |
| Independent timers | Flush and sync run on separate timers independently | |
| Flush is always running | Flusher runs continuously regardless of sync; sync skips fields with pending edits | ✓ |

**User's choice:** Flush is always running
**Notes:** Decoupled model — flusher and sync are independent.

### Q6: Conflict resolution

| Option | Description | Selected |
|--------|-------------|----------|
| Local pending edit wins (Recommended) | Sync skips any field that has a pending edit | ✓ |
| Merge with last-write-wins | Accept remote value but re-queue the local edit | |
| You decide | Claude picks the best approach | |

**User's choice:** Local pending edit wins
**Notes:** None

### Q7: Permanent flush failure

| Option | Description | Selected |
|--------|-------------|----------|
| Retry with backoff, then drop (Recommended) | Exponential backoff, drop after max retries, log warning | ✓ |
| Retry forever | Never drop a pending edit | |
| Notify user on repeated failure | Surface a warning after N retries | |

**User's choice:** Retry with backoff, then drop
**Notes:** None

---

## Connectivity Detection

### Q8: Detection speed

| Option | Description | Selected |
|--------|-------------|----------|
| Post-sync detection is fine (Recommended) | Status dot updates after each sync attempt | ✓ |
| Add a lightweight health ping | Ping endpoint every 30-60s | |
| OS-level network listener | Windows network change notifications | |

**User's choice:** Post-sync detection is fine
**Notes:** Since the app works identically online or offline, there is no urgency to detect disconnection quickly.

---

## Claude's Discretion

- Breathing animation timing (pulse frequency, easing curve)
- Max retry count before dropping a failed edit
- Flusher continuous interval
- Field-level conflict avoidance implementation approach

## Deferred Ideas

None — discussion stayed within phase scope.
