🎯 Icarus Phase 5 — 'Real World' Sprint
Director: Matt (Veto Active: Path B, Hardware Procurement, SaaS Logic)
Sprint Goal: Prove utility in real household before scaling
Timeline: 2 weeks
Status: APPROVED — Execute Immediately
📋 Scope (Modified Path A)
| # | Component | Owner | Constraint |
|---|---|---|---|
| 1 | Data Abstraction | Socrates 🧠 | Single-tenant ONLY. No multi-family auth. |
| 2 | System State View | Daedalus 🎨 | Read-only. No onboarding/editor UI. |
| 3 | User Acceptance Testing | Matt (Director) | Live stress test with real documents. |
VETOED:
- ❌ Path B (multi-family, SaaS)
- ❌ M4 Mac mini procurement
- ❌ Multi-tenant authentication
- ❌ Onboarding UI
- ❌ Family self-service registration
Component 1: Data Abstraction (Socrates)
Deliverable: hoffmann.yaml + family_loader.py
File: icarus/config/families/hoffmann.yaml
# Icarus Family Configuration — Hoffmann Household
# Single-tenant: Hardcoded family_id="hoffmann"
family_id: "hoffmann"
version: "1.0.0"
last_updated: "2026-04-26"
members:
- id: "sully"
name: "Sullivan"
nickname: "Sully"
birthdate: "2019-05-15"
current_grade: 1
school: "St. John's Elementary"
teacher: "Mrs. Smith"
interests: ["dinosaurs", "space", "lego"]
calendar_color: "blue"
- id: "harper"
name: "Harper"
nickname: null
birthdate: "2021-03-22"
current_grade: "pre-K"
school: "St. John's Elementary"
teacher: "Ms. Johnson"
interests: ["unicorns", "dance", "art"]
calendar_color: "pink"
- id: "aundrea"
name: "Aundrea"
nickname: null
relationship: "parent"
workplace: "hospital"
is_parent: true
calendar_color: "purple"
- id: "matt"
name: "Matt"
nickname: null
relationship: "parent"
workplace: "software"
is_parent: true
calendar_color: "green"
inference_rules:
- id: "rule_001"
pattern: "first grade|1st grade|grade 1|Mrs\\. Smith"
assign_to: ["sully"]
confidence: 0.95
description: "Sully's grade level and teacher"
- id: "rule_002"
pattern: "pre-K|preschool|4 years old|Ms\\. Johnson"
assign_to: ["harper"]
confidence: 0.90
description: "Harper's grade level and teacher"
- id: "rule_003"
pattern: "parent-teacher|conference|both parents"
assign_to: ["aundrea", "matt"]
confidence: 0.80
description: "Events involving both parents"
- id: "rule_004"
pattern: "Sullivan|Sully"
assign_to: ["sully"]
confidence: 0.98
description: "Direct name mention"
- id: "rule_005"
pattern: "Harper"
assign_to: ["harper"]
confidence: 0.98
description: "Direct name mention"
# Confidence thresholds
telemetry:
log_assignments: true
log_confidence: true
fallback_threshold: 0.70
File: icarus/core/family_loader.py
"""Family configuration loader — Single-tenant only."""
import yaml
from pathlib import Path
from typing import Optional
from icarus.core.config.staging import DATA_DIR
# SINGLE-TENANT: Hardcoded family
DEFAULT_FAMILY_ID = "hoffmann"
FAMILY_CONFIG_PATH = Path(__file__).parent.parent / "config" / "families" / f"{DEFAULT_FAMILY_ID}.yaml"
class FamilyConfig:
"""Single-tenant family configuration."""
def __init__(self, family_id: str = DEFAULT_FAMILY_ID):
"""Load family configuration from YAML.
Args:
family_id: Must be "hoffmann". Single-tenant constraint.
"""
if family_id != DEFAULT_FAMILY_ID:
raise ValueError(f"Single-tenant only. Family must be '{DEFAULT_FAMILY_ID}'.")
self.family_id = family_id
self._config = self._load_config()
def _load_config(self) -> dict:
"""Load and parse YAML configuration."""
if not FAMILY_CONFIG_PATH.exists():
raise FileNotFoundError(f"Family config not found: {FAMILY_CONFIG_PATH}")
with open(FAMILY_CONFIG_PATH) as f:
return yaml.safe_load(f)
@property
def members(self) -> list[dict]:
"""Return all family members."""
return self._config.get("members", [])
@property
def inference_rules(self) -> list[dict]:
"""Return pattern matching rules."""
return self._config.get("inference_rules", [])
@property
def fallback_threshold(self) -> float:
"""Confidence threshold for asking user."""
return self._config.get("telemetry", {}).get("fallback_threshold", 0.70)
def get_member(self, member_id: str) -> Optional[dict]:
"""Get member by ID."""
for member in self.members:
if member.get("id") == member_id:
return member
return None
def build_context_prompt(self) -> str:
"""Build family context string for LLM prompts."""
lines = ["FAMILY MEMBERS:"]
for member in self.members:
if member.get("current_grade"): # Kids only for school docs
lines.append(f"- {member['name']} ({member.get('nickname', 'no nickname')}):")
lines.append(f" Grade: {member['current_grade']}")
lines.append(f" Teacher: {member.get('teacher', 'unknown')}")
lines.append(f" School: {member.get('school', 'unknown')}")
if member.get("interests"):
lines.append(f" Interests: {', '.join(member['interests'])}")
return "\n".join(lines)
# Singleton instance
_family_config: Optional[FamilyConfig] = None
def get_family_config() -> FamilyConfig:
"""Get singleton family configuration.
Single-tenant: Always returns Hoffmann family config.
"""
global _family_config
if _family_config is None:
_family_config = FamilyConfig()
return _family_config
Refactor: Update briefing/generator.py
Replace hardcoded FAMILY_CONTEXT with:
from icarus.core.family_loader import get_family_config
family_config = get_family_config()
FAMILY_CONTEXT = family_config.build_context_prompt()
Component 2: System State View (Daedalus)
Deliverable: Read-only Dashboard
Route: /system/state or /admin/insights
Display:
┌─────────────────────────────────────────┐
│ Icarus System State │
│ Family: Hoffmann │
├─────────────────────────────────────────┤
│ Active Rules (5) │
├─────────────────────────────────────────┤
│ Rule 001: first grade|1st grade... │
│ → Sully (95% confidence) │
│ Last triggered: 2026-04-25 14:30 │
│ │
│ Rule 002: pre-K|preschool... │
│ → Harper (90% confidence) │
│ Last triggered: 2026-04-25 09:15 │
├─────────────────────────────────────────┤
│ Recent Routing Decisions (10) │
├─────────────────────────────────────────┤
│ [✓] Pumpkin Patch → Sully (95%) │
│ [✓] Dentist → Sully (98%) │
│ [?] Community Event → Asked user │
│ [✓] Pre-K Graduation → Harper (92%) │
├─────────────────────────────────────────┤
│ Confidence Distribution │
│ ████████████ High (>90%): 45 │
│ ████ Medium (70-90%): 12 │
│ ██ Low (<70%): 3 (user asked) │
└─────────────────────────────────────────┘
Requirements:
- ❌ NO editor, NO forms, NO buttons
- ✅ Read-only visibility into system thinking
- ✅ Shows YAML rules + real routing decisions
- ✅ Confidence distribution histogram
Component 3: User Acceptance Testing (Matt)
Two-Week Trial Protocol
Daily:
1. Forward real family emails to @IcarusTestBot
2. Upload PDFs, screenshots of forms
3. Note routing accuracy, confidence levels
4. Report false positives/negatives
Metrics to Track:
| Metric | Target |
|--------|--------|
| Correct routing (auto) | >90% |
| Correct routing (user asked) | >95% |
| Briefing quality score | >4/5 |
| Time to briefing | <5 seconds |
Daily Log Format:
Date: 2026-04-26
Documents tested: 3
- Field trip PDF → Sully (95%) ✅
- Dentist reminder → Harper (asked, correct) ✅
- Newsletter → No action (correct) ✅
Issues: None
🚀 Execution Order
Week 1
| Day | Task | Owner |
|---|---|---|
| 1 | Create hoffmann.yaml, family_loader.py |
Socrates |
| 2 | Refactor briefing/generator.py to use loader |
Socrates |
| 3 | System State view UI mock | Daedalus |
| 4 | System State view implementation | Daedalus |
| 5 | Integration test, validation | Wadsworth |
| 6-7 | UAT begins (Matt starts daily testing) | Matt |
Week 2
| Day | Task | Owner |
|---|---|---|
| 8-10 | UAT continues, data collection | Matt |
| 11 | Mid-sprint review, adjust rules | All |
| 12-13 | Rule refinement if needed | Socrates |
| 14 | Sprint retrospective, Phase 6 planning | All |
✅ Success Criteria
- ✅
hoffmann.yamldrives all family inference - ✅ System State view shows rules + routing decisions
- ✅ UAT: >90% auto-routing accuracy
- ✅ Zero multi-tenant code (validated by Wadsworth audit)
- ✅ Real-world stress: 20+ documents processed
📚 Files Created/Modified
| File | Action | Owner |
|---|---|---|
config/families/hoffmann.yaml |
Create | Socrates |
core/family_loader.py |
Create | Socrates |
briefing/generator.py |
Refactor | Socrates |
admin/system_state.html |
Create | Daedalus |
memory/2026-04-26-icarus-uat.md |
Daily logs | Matt |
EXECUTE. Modified Path A. Prove utility before scale.
Questions: @mention Wadsworth in The Hoffmann Board