Mission Control (MC) is Luci's web dashboard and operational hub. It manages tickets, workers, sessions, and provides a real-time conversation interface.
~/workspace/mission-control/app.py (Flask)luci-dashboard.service (systemd)mc.db (SQLite, WAL mode)| Page | Route | Purpose |
|---|---|---|
| Overview | / |
Health, stats, task status |
| Board | /board |
Kanban-style ticket board (30 cards, load more) |
| Ticket | /ticket/<id> |
Individual ticket conversation + actions |
| Activity | /activity |
Activity feed |
| Life Manager | /life-manager |
WhatsApp/email scan results |
| Tasks | /tasks |
Scheduled task list and run history |
| Skills | /skills |
Installed skills browser |
| Reports | /reports |
HTML research reports served from ~/workspace/reports/ |
| Radio | /spotify |
Spotify Radio dashboard with mood controls |
| F1 | /f1 |
F1 Predictor season dashboard |
| Team | /team |
Agent team overview |
| Apps | /apps |
External dashboards (Smart Money, Price Watch) |
| Logs | /logs |
Scheduler and heartbeat logs |
Gunicorn runs with -w 2 -k gthread --threads 16 → 16 handler threads per worker process. Caps are PER-WORKER (counters are module-level globals), so the sum of caps must fit one worker's thread budget with headroom for normal HTTP requests:
SSE_MAX_TOTAL_CLIENTS = 8 — global broadcast (/api/v1/stream) + per-ticket (/api/v1/tickets/<id>/stream) share this bucket.SSE_MAX_TAIL_CLIENTS = 4 — worker log tail (/api/v1/tickets/<id>/tail?follow=1) has its own bucket so a noisy tail page can't starve the broadcast bucket or all page renders. Over-cap returns 503 with a retry: 30000 SSE hint.max_lifetime ≤ 300s and heartbeats ≤ 30s so dead clients release threads quickly; browsers reconnect via the SSE retry hint.Thread starvation symptom: listener accepts connections but every request hangs / times out, ss shows many CLOSE-WAIT sockets on the worker PIDs. Restart restores capacity; the caps prevent recurrence.
tickets — the core ticket table (id, identifier, title, status, priority, assigned_to, etc.)ticket_comments — conversation history per ticketticket_messages — raw message stream (thinking, tool_use, assistant, user)ticket_events — granular stream-json events for live activity panel (MC-747). Columns: ticket_id TEXT, seq INT, event_type TEXT, payload_json TEXT, ts TEXT. Populated by workers as they run; replayed on page load for any ticket.ticket_tags — ticket categorization tags (auto-assigned on creation: bug, feature, infra, refactor, research, review)ticket_relationships — ticket-to-ticket links with validated relationship types: blocks, duplicate_of, caused_by, child_of, relates_to, related_toticket_context — ticket↔vault bridge (MC-462). Links tickets to vault.db files that were consulted, updated, or created during work. Auto-populated by vault_mcp.py during worker sessions, also supports manual linking via API.sessions — registered Claude sessionssessions_index / sessions_fts — indexed session transcripts (FTS5). Canonical store for all sessions (both Luci and Lucienne).queued_messages — messages waiting for worker pickup. Managed by queue_reaper.py which expires stuck messages (>30 min), retries failed ones, and sends Telegram alerts.task_runs — scheduler execution logheartbeats — health check historyvk_sync — Vibe Kanban external board sync mapping| File | Purpose |
|---|---|
| app.py | Flask routes, API endpoints, SSE/WS handlers |
| models.py | Database queries, ticket/comment CRUD |
| auth.py | Token-based auth (env vars or hardcoded fallbacks) |
| mc_interactive.py | WebSocket interactive session manager |
| static/chat.js | Client-side conversation UI |
| static/app.js | Board, search, general UI logic |
| static/style.css | All styles |
| Method | Route | Purpose |
|---|---|---|
| GET | /api/v1/tickets/<id>/context |
List vault files linked to a ticket |
| POST | /api/v1/tickets/<id>/context |
Link a vault file to a ticket (manual or auto) |
| DELETE | /api/v1/tickets/<id>/context/<ctx_id> |
Remove a ticket↔vault link |
| Method | Route | Purpose |
|---|---|---|
| POST | /api/v1/tickets/<identifier>/events |
Persist a stream-json event; broadcast via SSE |
| GET | /api/v1/tickets/<identifier>/events?after=<seq> |
Replay ticket_events in seq order |
Workers call POST to persist events during execution. The ticket detail page calls GET on load to replay history, then subscribes to the ticket SSE stream for ticket_event messages while the worker is live.
Mission Control is the board for your delegated work: requests come in, Luci coordinates the next step, and evidence stays visible for review.
Luci is your always-on assistant for routing, status updates, and follow-through. Operators can still open deeper evidence when needed.