# Family Assistant v1.5 — Scope Document **Wadsworth Review Copy with Comments for Daedalus** **Status:** Draft **Date:** 2026-04-21 **Owner:** Socrates (Backend) + Daedalus (Frontend) **Approver:** Matt (pending) **Target Release:** Post v1.0 stabilization **Reviewed by:** Wadsworth šŸ“‹ **Review Date:** 2026-04-21 22:06 UTC --- ## Executive Summary Family Assistant v1.0 is feature-frozen and operational. v1.5 addresses **trust and reliability gaps** identified in the April 2026 audit — human error recovery, persistent state management, and graceful degradation. This document follows contract-first protocol: API specs are binding on backend; UI/UX requirements are binding on frontend. --- ## Goals | Priority | Goal | Success Metric | |----------|------|----------------| | P0 | Eliminate silent data loss scenarios | User can undo any calendar mutation within 5 minutes | | P0 | Make conflicts actionable | Conflicts don't disappear after first alert; nag until resolved | | P1 | Ensure Family Brain availability when Gaming PC sleeps | Degrade to keyword search; no hard failures | | P1 | Give Aundrea phone-less calendar access | Web dashboard with read-only family calendar view | | P2 | Improve newsletter signal-to-noise | Formatted digest, not raw item dumps | | P2 | Proactive travel notifications | "Leave in 15min" alerts based on cached travel times | --- ## Features ### 1. Undo Stack (P0) **Problem:** Intent engine mutations (move, cancel, rename) are destructive and irreversible. Aundrea has no "oops" path. **Solution:** Persist last 5 operations with reversible snapshots. #### API Contract (Socrates) ```yaml # POST /api/v1/undo # Authorization: Bearer token (same auth as webhook) # Request: { "action": "list" | "undo" | "redo", "operation_id": "uuid" # required for undo/redo } # Response (list): { "operations": [ { "id": "uuid", "type": "move" | "cancel" | "rename" | "add", "summary": "Sullivan Soccer", "executed_at": "2026-04-21T14:30:00-05:00", "reversible_until": "2026-04-21T14:35:00-05:00", # 5 min TTL "can_undo": true, "snapshot": { "event_id": "caldav-uuid", "previous_state": { ... }, # full iCal VEVENT snapshot "new_state": { ... } } } ] } # Response (undo): { "status": "undone" | "expired" | "not_found", "restored_event": { ... }, "message": "Sullivan Soccer restored to original time" } ``` **Storage:** `~/.family_assistant/undo_stack.jsonl` — append-only, capped at 5 entries, 5-min TTL per entry. **Security:** Operations reversible only by same Telegram user who initiated (check `sender_id`). #### Daedalus Requirements - **Telegram Integration:** Add "ā†©ļø Undo" button to Hermes confirmation messages for 5-minute window - **Visual State:** Show "Recently modified" list in dashboard with undo affordance - **UX Pattern:** Toast notification style: "Moved Sullivan Soccer to Wednesday [Undo]" > **šŸ’¬ Wadsworth Comment for Daedalus:** > Consider "household-level" undo permission. Aundrea may ask Matt to undo her accidental mutation. Current spec restricts to `sender_id` only — discuss with Socrates if household admin override is needed. --- ### 2. Persistent Conflict Registry (P0) **Problem:** Conflict alerts fire once and disappear. No persistent "outstanding conflicts" list. **Solution:** SQLite-backed conflict registry with nag escalation. #### API Contract (Socrates) ```yaml # GET /api/v1/conflicts { "outstanding": [ { "id": "uuid", "detected_at": "2026-04-21T08:00:00-05:00", "event1": { "summary": "Sullivan Soccer", "start": "...", "end": "..." }, "event2": { "summary": "Harper Dance", "start": "...", "end": "..." }, "overlap_minutes": 30, "status": "unacknowledged" | "acknowledged" | "resolved", "nag_count": 2, # incremented on each heartbeat if unacknowledged "resolution": null | { "action": "split", "choice": 1, "executed_at": "..." } } ] } # POST /api/v1/conflicts/{id}/acknowledge { "status": "acknowledged" } # Stops nagging, keeps in registry # POST /api/v1/conflicts/{id}/resolve { "resolution_action": "split" | "reassign" | "reschedule", "choice_index": 0, # which option was selected "executed": true | false # whether calendar was actually modified } ``` **Storage:** SQLite at `~/.family_assistant/conflicts.db` — single table, indexed on `status` and `detected_at`. **Nag Logic:** - Heartbeat:check runs every 30m - If `unacknowledged` and `nag_count < 3`: send alert to family group - If `nag_count >= 3`: escalate to DM with "āš ļø UNRESOLVED CONFLICT" urgency #### Daedalus Requirements - **Conflict Badge:** Dashboard shows conflict count in header - **Conflict Detail View:** Side-by-side event comparison with resolution options - **Mobile Optimization:** Swipe-to-acknowledge, tap-to-resolve pattern - **Visual Priority:** Red accent for unacknowledged, yellow for acknowledged, green for resolved > **šŸ’¬ Wadsworth Comment for Daedalus:** > "Swipe-to-acknowledge" is good mobile UX, but ensure web dashboard has equivalent click/tap affordance. Also consider: family group visibility is important for shared accountability — DM escalation removes visibility. Discuss with Matt whether "escalate to DM" should be " louder family group message" instead. --- ### 3. Brain Offline Fallback (P1) **Problem:** If Gaming PC sleeps or Tailscale is down, `nomic-embed-text` fails. Family Brain throws exception. **Solution:** Try embeddings → if fail, fall back to keyword search against raw email chunks. #### API Contract (Socrates) ```yaml # POST /api/v1/brain/query { "question": "What do the kids need for the field trip?", "force_keyword": false # optional: bypass embeddings entirely } # Response: { "answer": "...", "mode": "semantic" | "keyword_fallback", # transparency to user "sources": [...], "confidence": "high" | "medium" | "low", "embeddings_available": true | false } ``` **Fallback Logic:** 1. Try `nomic-embed-text` on Gaming PC (timeout: 5s) 2. If timeout/error: search ChromaDB metadata (subject, sender, date) with keyword matching 3. If still no results: search raw email body text (cached in `~/.family_assistant/email_cache/`) **Health Check:** Add `embeddings_reachable` to `/health` endpoint. #### Daedalus Requirements - **Mode Indicator:** Show subtle "offline mode" badge when using keyword fallback - **Confidence Display:** Lower confidence → suggest rephrasing question - **No User Action Required:** Should be transparent, but honesty about quality is important > **šŸ’¬ Wadsworth Comment for Daedalus:** > "Subtle offline mode badge" is good — avoid alarmist UI. Consider: "keyword mode" badge with tooltip "Semantic search unavailable. Results may be less precise." This sets correct expectations without causing concern. --- ### 4. Family Dashboard — Read-Only Calendar View (P1) **Problem:** Aundrea doesn't want to install CalDAV clients. Needs phone-less access to family calendar. **Solution:** Web dashboard served from hoffdesk-api, read-only CalDAV view. #### API Contract (Socrates) ```yaml # GET /api/v1/calendar/events # Query params: # start=2026-04-01T00:00:00-05:00 # end=2026-04-30T23:59:59-05:00 # include_travel=true # enrich with travel time from location cache { "events": [ { "id": "caldav-uuid", "summary": "Sullivan Soccer", "start": "2026-04-21T15:00:00-05:00", "end": "2026-04-21T16:00:00-05:00", "location": "Golrusk Pet Center", "travel_time_minutes": 12, "travel_from_home": true, "status": "confirmed", "who": ["Sullivan"], "color": "#3b82f6" # auto-assigned per-person } ], "conflicts": [ // include outstanding conflicts in same response { "id": "...", "event1_id": "...", "event2_id": "...", "overlap_minutes": 30 } ] } # GET /api/v1/calendar/today # Shortcut for today's events # GET /api/v1/calendar/week # Query param: week_offset=0 (current), -1, +1, etc. ``` **Caching:** 5-minute cache on Radicale reads to reduce load. **Auth:** Same `TELEGRAM_BOT_TOKEN` validation as webhook (token in header, IP allowlist optional). #### Daedalus Requirements - **Calendar Views:** Day, week, month (month optional for MVP) - **Week View Default:** Family planning happens at weekly granularity - **Person Colors:** Sullivan = blue, Harper = pink, Family = green, etc. (see design-tokens/) - **Conflict Highlighting:** Red stripe on conflicting events - **Travel Time:** Small text under location: "12 min from home" - **Mobile-First:** Touch-friendly, swipe between days/weeks - **No Login Required:** Shareable URL with token (time-limited, revokeable) > **šŸ”“ Wadsworth Concern for Daedalus:** > **This is the largest scope item in v1.5.** Week/month calendar views + touch gestures + person colors + conflict overlay + travel markers is substantial frontend work. > > **Recommended refinement:** > - **MVP P1:** Day view only, simple list/timeline, no swipe gestures > - **P1.5:** Week view (grid), swipe gestures > - **P2:** Month view > > **Sizing request:** Please estimate effort before final P1 commit. If this exceeds ~3-4 days of focused work, recommend MVP scope reduction. --- ### 5. Newsletter Digest v2 (P2) **Problem:** Info items dump raw text to Telegram. Low signal-to-noise. **Solution:** LLM-summarized digest with categories. #### API Contract (Socrates) ```yaml # POST /api/v1/digest/generate (internal, called by pipeline) { "items": [...], // raw items from newsletter parser "style": "brief" | "detailed" // brief for daily, detailed for weekly } # Response: { "sections": [ { "category": "School", "icon": "šŸŽ’", "items": [ { "summary": "Field trip permission due Friday", "who": ["Sullivan"], "action_required": true, "deadline": "2026-04-25" } ] }, { "category": "Sports", "icon": "⚽", "items": [...] } ], "markdown": "šŸŽ’ **School**\n• Field trip...\n\n⚽ **Sports**..." // formatted for Telegram } ``` **Categories:** School, Sports, Medical, Community, Other (configurable in `family.yaml`) **Prompt:** Single LLM call with category definitions, returns structured JSON. #### Daedalus Requirements - **Digest View:** Dashboard card with collapsible sections - **Category Icons:** Consistent emoji/icon mapping (design-tokens/) - **Action Badges:** "Needs action" indicator on items with deadlines - **Mark Done:** Inline button to dismiss (triggers intent engine) > **šŸ’¬ Wadsworth Comment for Daedalus:** > Good candidate for HTMX progressive enhancement: collapsible sections that work without JS, enhanced with smooth animation when JS available. "Mark Done" button should have immediate visual feedback (strike-through or fade) before backend confirmation. --- ### 6. Proactive Travel Notifications (P2) **Problem:** Location cache has travel times but doesn't alert when to leave. **Solution:** Heartbeat-driven "leave by" notifications. #### API Contract (Socrates) ```yaml # GET /api/v1/notifications/leave-by // Called by heartbeat 30 min before event start { "upcoming": [ { "event_id": "...", "summary": "Sullivan Soccer", "start_time": "2026-04-21T15:00:00-05:00", "leave_by": "2026-04-21T14:43:00-05:00", // start - travel_time - 5min buffer "travel_time_minutes": 12, "location": "Golrusk Pet Center", "notified": false } ] } # POST /api/v1/notifications/mark-sent // Mark as notified to prevent duplicate alerts ``` **Trigger Logic:** - Heartbeat:check scans next 2 hours of events - If `event.start - travel_time - 5min_buffer <= now + 30min` and not notified: send alert - Only notify once per event **Hermes Message:** ``` šŸš— Leave soon for Sullivan Soccer Leave by: 2:43 PM (12 min drive) Location: Golrusk Pet Center ``` #### Daedalus Requirements - **Notification Preferences:** Per-user toggle (Aundrea wants these, Matt might not) - **Visual Timeline:** Dashboard shows "leave by" time as separate marker before event - **Snooze:** "Remind me in 5 minutes" button > **šŸ’¬ Wadsworth Comment for Daedalus:** > Snooze UX pattern: after snooze, show "Reminding at 2:38 PM" with cancel option. Consider: travel notifications may need tighter cadence than 30min heartbeat — discuss with Socrates if dedicated travel-alert cron (5-min) is feasible. --- ## Daedalus Deliverables Summary ### UI Components Required 1. **Undo Toast** — Floating notification with countdown timer 2. **Conflict Badge** — Header indicator with count 3. **Conflict Detail Panel** — Side-by-side event comparison 4. **Calendar Week View** — Grid layout with person colors 5. **Calendar Day View** — Timeline with travel markers 6. **Digest Card** — Collapsible category sections 7. **Offline Badge** — Subtle mode indicator ### Design Token Requirements | Token | Value | Usage | |-------|-------|-------| | `--color-person-sullivan` | `#3b82f6` (blue-500) | Sullivan events | | `--color-person-harper` | `#ec4899` (pink-500) | Harper events | | `--color-person-family` | `#22c55e` (green-500) | Family events | | `--color-conflict-unack` | `#ef4444` (red-500) | Unacknowledged conflicts | | `--color-conflict-ack` | `#eab308` (yellow-500) | Acknowledged conflicts | | `--color-travel-marker` | `#6b7280` (gray-500) | Leave-by indicators | | `--undo-toast-ttl` | `300s` | Undo button visibility duration | ### Shared Assets Place in `shared/design-tokens/family-assistant/`: - `colors.json` — Person assignments, conflict states - `icons.json` — Category icons for digest - `spacing.json` — Calendar grid dimensions > **šŸ”“ Wadsworth Action Required:** > Daedalus to provide effort estimate for dashboard (Feature 4) before final scope approval. Recommend day-view MVP if estimate exceeds 3-4 days. --- ## Wadsworth Review Summary ### Strengths of v1.5 Scope - Addresses real pain points (undo, persistent conflicts) - Contract-first approach with clear API specs - Well-prioritized (P0/P1/P2) - Graceful degradation mindset (brain fallback) ### Concerns | Feature | Concern | Severity | |---------|---------|----------| | Undo | Household-level permissions | Low | | Conflicts | DM escalation reduces visibility | Low | | Dashboard | Scope risk — week/month views are large | **Medium** | | Travel | 30min heartbeat may be too coarse | Low | ### Recommendations 1. āœ… Approve scope with dashboard MVP caveat (day-view only for P1) 2. šŸ“‹ Request Daedalus sizing estimate before final commit 3. šŸ“‹ Discuss undo permissions and conflict escalation with Matt ### Routing - **Socrates:** Backend implementation ready to proceed - **Daedalus:** Frontend scope needs sizing confirmation - **Wadsworth:** Coordination, approval tracking, scope refinement --- *Reviewed by: Wadsworth šŸ“‹* *Review Date: 2026-04-21 22:06 UTC* *Original document:* `shared/project-docs/family-assistant/v1.5/SCOPE.md` *This review copy:* `shared/project-docs/family-assistant/v1.5/SCOPE-wadsworth-review.md`