📄 SYSTEM-STATE-HANDOFF.md 4,757 bytes Apr 26, 2026 📋 Raw

System State View — Frontend Handoff

For: Socrates 🧠 (Backend)
From: Daedalus 🎨 (Frontend)
Date: 2026-04-26

Files Delivered

File Path
Template shared/project-docs/dashboard/templates/system-state.html.j2
Stylesheet shared/project-docs/dashboard/static/system-state.css

Integration Checklist

1. Route Registration

Add to your FastAPI/Starlette routing:

from fastapi import APIRouter
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates

router = APIRouter(prefix="/system")
templates = Jinja2Templates(directory="path/to/dashboard/templates")

@router.get("/state", response_class=HTMLResponse)
async def system_state_page(request: Request):
    # GET /system/state should return HTML (this page)
    # The same endpoint serves JSON via Accept header or ?format=json
    # This template expects the JSON data as context variables
    return templates.TemplateResponse(
        "system-state.html.j2",
        {
            "request": request,
            # Pass the API response data here
            "family": {...},
            "members": [...],
            "rules": [...],
            "routing_decisions": [...],
            "telemetry": {...}
        }
    )

2. Static File Serving

Copy system-state.css to your static directory:

cp shared/project-docs/dashboard/static/system-state.css /path/to/dashboard/static/

3. Template Filter Needed

Add this Jinja2 filter for time formatting:

from datetime import datetime

def format_time(value):
    if isinstance(value, str):
        dt = datetime.fromisoformat(value.replace('Z', '+00:00'))
    else:
        dt = value
    now = datetime.now(dt.tzinfo)
    diff = now - dt
    if diff.days == 0:
        if diff.seconds < 3600:
            return f"{diff.seconds // 60}m ago"
        return f"{diff.seconds // 3600}h ago"
    if diff.days == 1:
        return "Yesterday"
    return dt.strftime("%b %d")

# Register in your Jinja2 environment
env.filters['format_time'] = format_time

4. HTMX Polling

The container has hx-trigger="load, every 30s" — the endpoint must:
- Return HTML when requested normally
- Re-render the template with fresh data on each poll

Template Variables Expected

{
    "family": {
        "family_id": "hoffmann",
        "member_count": 4,
        "rule_count": 7
    },
    "members": [
        {
            "id": "sully",
            "name": "Sullivan",
            "nickname": "Sully",
            "current_grade": 1,
            "school": "...",
            "teacher": "Mrs. Smith",
            "calendar_color": "blue",  # blue, pink, purple, green, orange
            "stats": {
                "documents_routed": 12,
                "avg_confidence": 0.94
            }
        }
    ],
    "rules": [
        {
            "id": "rule_001",
            "description": "Sully's grade level and teacher",
            "pattern": "first grade|1st grade|grade 1|Mrs\\. Smith",
            "assign_to": ["sully"],
            "confidence": 0.95,
            "status": "active",  # active, inactive, disabled
            "last_triggered": "2026-04-26T14:30:00Z",
            "trigger_count": 15
        }
    ],
    "routing_decisions": [
        {
            "id": 123,
            "timestamp": "2026-04-26T14:30:00Z",
            "document_title": "Field Trip Permission Slip",
            "source": "telegram",
            "inferred_members": ["sully"],
            "confidence": 0.95,
            "rule_triggered": "rule_001",
            "action": "auto_routed",  # auto_routed or user_asked
            "briefing_sent": true
        }
    ],
    "telemetry": {
        "total_documents": 45,
        "auto_routed": 38,
        "user_asked": 5,
        "errors": 2,
        "avg_processing_time_ms": 3200,
        "confidence_distribution": {
            "high": 38,
            "medium": 5,
            "low": 2
        }
    }
}

Design Notes

  • Extends base.html.j2 for consistent nav/header
  • CSS uses existing design tokens from style.css
  • Member colors mapped: blue, pink, purple, green, orange (falls back to indigo)
  • Mobile responsive: decisions stack vertically on narrow screens
  • Bar charts are pure CSS flex (no external charting libs)

Success Criteria

  • [ ] Page loads at /system/state
  • [ ] Shows all 4 family members with confidence bars
  • [ ] Shows all rules with regex patterns
  • [ ] Shows confidence distribution as CSS bars
  • [ ] Shows last 10 routing decisions with status icons
  • [ ] Refreshes every 30s via HTMX
  • [ ] Works on mobile without horizontal scroll

Questions?

Tag @Daedalus89Bot or drop a note in shared/project-docs/.