feat: integrate Spark Intelligence into Timmy swarm system
Adds a self-evolving cognitive layer inspired by vibeship-spark-intelligence,
adapted for Timmy's agent architecture. Spark captures swarm events, runs
EIDOS prediction-evaluation loops, consolidates memories, and generates
advisory recommendations — all backed by SQLite consistent with existing
patterns.
New modules:
- spark/memory.py — event capture with importance scoring + memory consolidation
- spark/eidos.py — EIDOS cognitive loop (predict → observe → evaluate → learn)
- spark/advisor.py — ranked advisory generation from accumulated intelligence
- spark/engine.py — top-level API wiring all subsystems together
Dashboard:
- /spark/ui — full Spark Intelligence dashboard (3-column: status/advisories,
predictions/memories, event timeline) with HTMX auto-refresh
- /spark — JSON API for programmatic access
- SPARK link added to navigation header
Integration:
- Coordinator hooks emit Spark events on task post, bid, assign, complete, fail
- EIDOS predictions generated when tasks are posted, evaluated on completion
- Memory consolidation triggers when agents accumulate enough outcomes
- SPARK_ENABLED config toggle (default: true)
Tests: 47 new tests covering all Spark subsystems + dashboard routes.
Full suite: 538 tests passing.
https://claude.ai/code/session_01KJm6jQkNi3aA3yoQJn636c
2026-02-24 15:51:15 +00:00
{% extends "base.html" %}
{% block title %}Timmy Time — Spark Intelligence{% endblock %}
2026-03-11 09:52:57 -04:00
{% block extra_styles %}{% endblock %}
fix: comprehensive iPhone UI overhaul — glassmorphism, responsive layouts, theme unification
- base.html: add missing {% block extra_styles %}, mobile hamburger menu with
slide-out nav, interactive-widget viewport meta, -webkit-text-size-adjust
- style.css: define 15+ missing CSS variables (--bg-secondary, --text-muted,
--accent, --success, --danger, etc.), add missing utility classes (.grid,
.stat, .agent-card, .agent-avatar, .form-group), glassmorphism card effects,
iPhone breakpoints (768px, 390px), 44pt min touch targets, smooth animations
- mobile.html: rewrite with proper theme variables, glass cards, touch-friendly
quick actions grid, chat with proper message bubbles
- swarm_live.html: replace undefined CSS vars, use mc-panel theme cards
- marketplace.html: responsive agent cards that stack on iPhone, themed pricing
- voice_button.html & voice_enhanced.html: proper theme integration, touch-sized
buttons, themed result containers
- create_task.html: mobile-friendly forms with 16px font (prevents iOS zoom)
- tools.html & creative.html: themed headers, responsive column stacking
- spark.html: replace all hardcoded blue (#00d4ff) colors with theme purple/orange
- briefing.html: replace hardcoded bootstrap colors with theme variables
Fixes: header nav overflow on iPhone (7 links in single row), missing
extra_styles block silently dropping child template styles, undefined CSS
variables breaking mobile/swarm/marketplace/voice pages, sub-44pt touch
targets, missing -webkit-text-size-adjust, inconsistent color themes.
97 UI tests pass (91 UI-specific + 6 creative route).
https://claude.ai/code/session_01JiyhGyee2zoMN4p8xWYqEe
2026-02-24 22:25:04 +00:00
{% block content %}
< div class = "container-fluid spark-container py-3" >
<!-- Header -->
< div class = "spark-header" >
< div class = "spark-title" > SPARK INTELLIGENCE< / div >
< div class = "spark-subtitle" >
Self-evolving cognitive layer —
< span class = "spark-status-val" > {{ status.events_captured }}< / span > events captured,
< span class = "spark-status-val" > {{ status.memories_stored }}< / span > memories,
< span class = "spark-status-val" > {{ status.predictions.evaluated }}< / span > predictions evaluated
< / div >
< / div >
< div class = "row g-3" >
<!-- Left column: Status + Advisories -->
< div class = "col-12 col-lg-4 d-flex flex-column gap-3" >
< div class = "card mc-panel" >
< div class = "card-header mc-panel-header" > // EIDOS LOOP< / div >
< div class = "card-body p-3" >
< div class = "spark-stat-grid" >
< div class = "spark-stat" >
< span class = "spark-stat-label" > PREDICTIONS< / span >
< span class = "spark-stat-value" > {{ status.predictions.total_predictions }}< / span >
< / div >
< div class = "spark-stat" >
< span class = "spark-stat-label" > EVALUATED< / span >
< span class = "spark-stat-value" > {{ status.predictions.evaluated }}< / span >
< / div >
< div class = "spark-stat" >
< span class = "spark-stat-label" > PENDING< / span >
< span class = "spark-stat-value" > {{ status.predictions.pending }}< / span >
< / div >
< div class = "spark-stat" >
< span class = "spark-stat-label" > ACCURACY< / span >
< span class = "spark-stat-value {% if status.predictions.avg_accuracy >= 0.7 %}text-success{% elif status.predictions.avg_accuracy < 0.4 %}text-danger{% else %}text-warning{% endif %}" >
{{ "%.0f"|format(status.predictions.avg_accuracy * 100) }}%
< / span >
< / div >
< / div >
< / div >
< / div >
< div class = "card mc-panel" >
< div class = "card-header mc-panel-header" > // EVENT PIPELINE< / div >
< div class = "card-body p-3" >
{% for event_type, count in status.event_types.items() %}
< div class = "spark-event-row" >
< span class = "spark-event-type-badge spark-type-{{ event_type }}" > {{ event_type | replace("_", " ") | upper }}< / span >
< span class = "spark-event-count" > {{ count }}< / span >
< / div >
{% endfor %}
< / div >
< / div >
< div class = "card mc-panel"
hx-get="/spark/insights"
hx-trigger="load, every 30s"
hx-target="#spark-insights-body"
hx-swap="innerHTML">
< div class = "card-header mc-panel-header d-flex justify-content-between align-items-center" >
< span > // ADVISORIES< / span >
< span class = "badge badge-info" > {{ advisories | length }}< / span >
< / div >
< div class = "card-body p-3" id = "spark-insights-body" >
{% if advisories %}
{% for adv in advisories %}
< div class = "spark-advisory priority-{{ 'high' if adv.priority >= 0.7 else ('medium' if adv.priority >= 0.4 else 'low') }}" >
< div class = "spark-advisory-header" >
< span class = "spark-advisory-cat" > {{ adv.category | replace("_", " ") | upper }}< / span >
< span class = "spark-advisory-priority" > {{ "%.0f"|format(adv.priority * 100) }}%< / span >
< / div >
< div class = "spark-advisory-title" > {{ adv.title }}< / div >
< div class = "spark-advisory-detail" > {{ adv.detail }}< / div >
< div class = "spark-advisory-action" > {{ adv.suggested_action }}< / div >
< / div >
{% endfor %}
{% else %}
< div style = "text-align:center; color:var(--text-dim); padding:16px; font-size:0.85rem;" > No advisories yet. Run more tasks to build intelligence.< / div >
{% endif %}
< / div >
< / div >
< / div >
<!-- Middle column: Predictions -->
< div class = "col-12 col-lg-4 d-flex flex-column gap-3" >
< div class = "card mc-panel" >
< div class = "card-header mc-panel-header" > // EIDOS PREDICTIONS< / div >
< div class = "card-body p-3" >
{% if predictions %}
{% for pred in predictions %}
< div class = "spark-prediction {% if pred.evaluated_at %}evaluated{% else %}pending{% endif %}" >
< div class = "spark-pred-header" >
< span class = "spark-pred-task" > {{ pred.task_id[:8] }}...< / span >
{% if pred.accuracy is not none %}
< span class = "spark-pred-accuracy {% if pred.accuracy >= 0.7 %}text-success{% elif pred.accuracy < 0.4 %}text-danger{% else %}text-warning{% endif %}" >
{{ "%.0f"|format(pred.accuracy * 100) }}%
< / span >
{% else %}
< span class = "spark-pred-pending-badge" > PENDING< / span >
{% endif %}
< / div >
< div class = "spark-pred-detail" >
{% if pred.predicted %}
< div class = "spark-pred-item" >
< span class = "spark-pred-label" > Winner:< / span >
{{ (pred.predicted.likely_winner or "?")[:8] }}
< / div >
< div class = "spark-pred-item" >
< span class = "spark-pred-label" > Success:< / span >
{{ "%.0f"|format((pred.predicted.success_probability or 0) * 100) }}%
< / div >
< div class = "spark-pred-item" >
< span class = "spark-pred-label" > Bid range:< / span >
{{ pred.predicted.estimated_bid_range | join("– ") }} sats
< / div >
{% endif %}
{% if pred.actual %}
< div class = "spark-pred-actual" >
< span class = "spark-pred-label" > Actual:< / span >
{% if pred.actual.succeeded %}completed{% else %}failed{% endif %}
by {{ (pred.actual.winner or "?")[:8] }}
{% if pred.actual.winning_bid %} at {{ pred.actual.winning_bid }} sats{% endif %}
< / div >
{% endif %}
< / div >
< div class = "spark-pred-time" > {{ pred.created_at[:19] }}< / div >
< / div >
{% endfor %}
{% else %}
< div style = "text-align:center; color:var(--text-dim); padding:16px; font-size:0.85rem;" > No predictions yet. Post tasks to activate the EIDOS loop.< / div >
{% endif %}
< / div >
< / div >
< div class = "card mc-panel" >
< div class = "card-header mc-panel-header" > // MEMORIES< / div >
< div class = "card-body p-3" >
{% if memories %}
{% for mem in memories %}
< div class = "spark-memory-card mem-{{ mem.memory_type }}" >
< div class = "spark-mem-header" >
< span class = "spark-mem-type" > {{ mem.memory_type | upper }}< / span >
< span class = "spark-mem-confidence" > {{ "%.0f"|format(mem.confidence * 100) }}% conf< / span >
< / div >
< div class = "spark-mem-content" > {{ mem.content }}< / div >
< div class = "spark-mem-meta" >
{{ mem.source_events }} events • {{ mem.created_at[:10] }}
< / div >
< / div >
{% endfor %}
{% else %}
< div style = "text-align:center; color:var(--text-dim); padding:16px; font-size:0.85rem;" > Memories will form as patterns emerge.< / div >
{% endif %}
< / div >
< / div >
< / div >
<!-- Right column: Event Timeline -->
< div class = "col-12 col-lg-4 d-flex flex-column gap-3" >
< div class = "card mc-panel"
hx-get="/spark/timeline"
hx-trigger="load, every 15s"
hx-target="#spark-timeline-body"
hx-swap="innerHTML">
< div class = "card-header mc-panel-header d-flex justify-content-between align-items-center" >
< span > // EVENT TIMELINE< / span >
< span class = "badge badge-secondary" > {{ status.events_captured }} total< / span >
< / div >
< div class = "card-body p-3 spark-timeline-scroll" id = "spark-timeline-body" >
{% if timeline %}
{% for ev in timeline %}
< div class = "spark-event spark-type-{{ ev.event_type }}" >
< div class = "spark-event-header" >
< span class = "spark-event-type-badge" > {{ ev.event_type | replace("_", " ") | upper }}< / span >
< span class = "spark-event-importance" title = "Importance: {{ ev.importance }}" >
{% if ev.importance >= 0.8 %}● ● ● {% elif ev.importance >= 0.5 %}● ● {% else %}● {% endif %}
< / span >
< / div >
< div class = "spark-event-desc" > {{ ev.description }}< / div >
{% if ev.task_id %}
< div class = "spark-event-meta" > task: {{ ev.task_id[:8] }}{% if ev.agent_id %} • agent: {{ ev.agent_id[:8] }}{% endif %}< / div >
{% endif %}
< div class = "spark-event-time" > {{ ev.created_at[:19] }}< / div >
< / div >
{% endfor %}
{% else %}
< div style = "text-align:center; color:var(--text-dim); padding:16px; font-size:0.85rem;" > No events captured yet.< / div >
{% endif %}
< / div >
< / div >
< / div >
< / div >
< / div >
{% endblock %}