- auto_detect_facts() scans chat turns for factual content (IPs, paths,
services, config changes, hardware refs) using pattern matching
- check_fact_conflicts() cross-references detected facts against stored
FTS5 memories — when a contradiction exists (same topic, diff value)
the system surfaces a rag_update_suggestion in the done SSE payload
- Frontend shows a floating notification banner comparing old vs new
fact with Update/Dismiss buttons
- confirm_fact_update() replaces the memory + re-embeds/re-indexes
the Qdraft entry on user confirmation
- Silent auto-ingest (memories + Qdrant) when no conflict exists
- Frontend: msg-toolbar opacity 0→0.35 for visibility
- request_model_swap() publishes cmd.swap_model on jc.admin, sets node status to swapping
- handle_model_ready() updates active_model from inventory, restores active status
- handle_model_failed() sets node status to error with failure detail
- select_node() made async with two-pass logic: find ready node or trigger swap
- inventory field stored in node records for swap target lookup
- Both handlers subscribed on jc.system via SUBSCRIBE_TABLE
- amqp.py: subscribe() creates exclusive queues bound to routing keys,
_rebind_subscriptions() recreates them after reconnect
- cluster.py: CLUSTER_NODES, CLUSTER_EVENTS (bounded 1000),
CLUSTER_COORDINATOR with auto-promotion, all 6 handlers
(register, deregister, pong, event, coordinator_query),
ping_node() with 5s timeout + auto-deregister on failure
- routers/cluster.py: GET /api/cluster
- Wired into app.py lifespan after amqp_connect()
- 13 tests covering all handlers, boundaries, and API shape
- No passive heartbeats — workers assumed present until ping
timeout at work-routing time
Developer-Architecture.md (§6):
- Broker-mediated design model as preferred architecture
- Coordinator vs Worker node type table with full service requirements
- Service distribution ASCII diagram
- Workers connect as AMQP clients only (no local broker needed)
- Contrasted with service-mesh alternative
docker.md (§9):
- New Worker Node Deployment Model section
- Worker requirements: llama-server binary + node_agent.py + aio-pika
- Explicit table of what workers do NOT run
- Architecture note: broker-mediated vs service-mesh
- Ref: AMQP-0-9-1 client-server protocol since 2006
Covers all six services (jarvisChat, SearXNG, Qdrant, RabbitMQ,
llama-server, Ollama) with images, ports, volumes, healthchecks,
env mapping, secrets management, setup wizard spec, and back-out
procedure. Includes pre-v1.0 gate checklist and open decisions.
Also add .env, secrets/, searxng/ to .gitignore (these are
generated by setup.sh and contain secrets).
- test_maybe_evict_all_pinned_breaks: above high water but only
pinned points → eviction breaks with 0 deleted, no EVICTION_LOG entry
- test_rag_stats_requires_admin: guest gets 403 on /api/rag/stats
- Move all eviction logic (evict_batch, maybe_evict, EVICTION_LOG,
get_collection_count/stats, get_rag_operational_stats) into eviction.py
- Move QDRANT_URL, RAG_COLLECTION into config.py to break circular dep
- rag.py re-exports eviction symbols for backward compatibility
- Router imports updated to use eviction module directly
- All 130 tests pass