Aurelius β Implementation Roadmap
This document records the codebase review that preceded the current round of
work and the phased plan that follows from it. It is written against the
post-rebuild architecture (core/ + adapters/ + ingest/, source-agnostic
GraphNavigator, SQLite GraphStore).
Update β optional Gemini layer. An additive AI narration layer (
core/llm.py) was later added: plain-English path explanations, finance Compare analysis, discover "why these" narratives, entity summaries, and a news coverage summary + refined tone. It is off unlessGEMINI_API_KEYis set, is never in the search hot loop, and every AI endpoint degrades to a non-blocking notice (reason:"no_key"|"rate_limited"|"cooling_down") with the standard non-LLM result always shown. See CLAUDE.md β "Optional Gemini layer."
Part 1 β Review findings
Architecture (sound, keep)
- Adapter boundary holds. The engine (
core/navigator.py,core/discovery.py) speaks onlyNodeRef/Edgethrough theGraphSourceprotocol; Wikipedia, OpenAlex, GitHub are live adapters, Finance/News/Biomed answer from the store. Adding a domain is an adapter file plus (for ingested mode) an ingest script β no engine changes. This is exactly the property the Finance and News work below relies on, so it is reused as-is. - Search algorithm keeps its v1 lessons. Greedy best-first with the
depth tie-break, honest bidirectional meeting check (goal-zone d1/d2 with
bridge bookkeeping), the
_real_edges/_validate_pathregression fence, stagnation escape, andPRUNE_MIN_SURVIVORS. No algorithm change needed; "bidirectional A*" in product terms maps to this meeting-check design (true A* is impossible here β1 β cosineis not admissible β and path optimality is not the product goal; a meaningful, explainable path is). - Store schema already supports typed, weighted edges
(
edges(source, src, dst, type, weight)), so the richer finance graph and the news entity graph need zero schema migration for edges. Node kinds ride in the existingfeaturesJSON column.
Bugs / hygiene found in review (fixed in Phase 0)
_ip_hitsrate-limit dict grows without bound (server.py) β adefaultdict(deque)keyed by client IP is never pruned; empty deques for long-gone IPs accumulate for the life of the process. Fixed by sweeping stale entries during rate checks.- Search timeout is silent β when a WS search hits
MAX_SEARCH_SECONDS, tasks are cancelled but the client is never told; the UI would sit on the last status line forever. Fixed by emitting anot_foundtimeout message. - Superseded v1 modules still on disk (
search.py,wiki.py, rootembedding.py) β no longer imported by anything but easy to edit by mistake. Deleted (git history keeps them). data/*.db*not git-ignored β locally-generated SQLite (+ WAL/SHM) would land in commits. Added to.gitignore.- No edge evidence for ingested sources β
StoreBackedSourceinherited the no-opedge_display, so a finance path rendered with no indication of why consecutive nodes connect. Fixed with a typed, weighted display ("co-moves (corr 0.72)", "supplies", "holds") β this is the foundation of the "explainable paths" requirement. - Unused import (
randominserver.py) β removed.
UI review (drives Phase 2)
- Nodes/links in the 3D view are oversized (
nodeRelSize 4, sphere values up to 7) and the camera has no damping and no auto-fit, so a 100+ node search turns into one giant tangled ball you must fight to read. - Every streamed node stays visible forever β no filtering, no level-of-detail, no way to collapse the exploration cloud once a path is found.
- The graph is display-only: you cannot expand a node to keep exploring after the search finishes.
- About / first-run copy still describes the Wikipedia-only v1.
- The Discover panel shows scored results with zero explanation of what a "hidden connection" is or why a given candidate appears.
Part 2 β Phased plan
Phase 0 β Fixes & hygiene (no behavior change) β
Everything in "Bugs / hygiene" above, plus this document.
Phase 1 β Explorer backend β
GET /api/neighbors?source=&q=&limit=β resolve a query, return outbound edges withtype,weight, and humandisplay, powering click-to-expand.edge_displayfor all store-backed sources (typed evidence).
Phase 2 β 3D graph redesign β
- Smaller nodes (relSize ~2.2, tighter size ladder), thinner links, more inter-node spacing (weaker charge + longer link distance).
- Orbit controls with inertial damping; smooth
zoomToFitafter growth bursts; camera fly-to on focus (already present, retimed). - Clutter control: view filters (All / Explored / Path), label level-of-detail (labels only on structurally important nodes; sprite size down), post-found dimming of the exploration cloud.
- Progressive expansion: click a node after the search settles β fetch its
neighbors from
/api/neighborsβ animate them in (capped per expansion). - Edge tooltips show the relationship type + weight (evidence surfacing).
Phase 3 β Hidden Connections explainer + modals β
- Discover panel opens with a plain-language explanation of what hidden connections are (indirect links through shared neighbors, semantic similarity without a direct edge, co-movement, shared dependenciesβ¦), and each result carries a "why you're seeing this" line built from its actual bridges and similarity.
- About + first-run hero copy rewritten for the multi-domain engine.
Phase 4 β Finance graph, typed β
Ingest builds a heterogeneous graph (node kinds ride in features.kind):
- Companies (Yahoo chart API: real prices, names) β as before.
- Sectors as first-class nodes;
sector_memberreplaces the old O(nΒ²) pairwisesame_sectoredges. - ETFs (SPY, QQQ, DIA, sector SPDRs) with
holdsedges to constituents. - Executives (
led_by), countries (based_in) from a curated map. - Supply chain (
supplies) and competitors (competes_with) from a curated, sourced seed set β the classic pairs (TSMβAAPL/NVDA/AMD, VβMA, FβGMβTSLAβ¦). - Ownership (
owns_stake): Berkshire Hathaway's flagship stakes. - Macro indicators (10-y yield, WTI crude, dollar index, gold, S&P 500,
VIX) fetched like any ticker;
macro_correlatesedges are computed from return correlation, so the macro linkage is evidence, not assertion. co_movescorrelation kNN edges kept (the structural workhorse). Every edge type has a human display string β every path step is explainable. Deferred (documented, not blocking): timeline mode, live 13F ownership ingestion, event-propagation explorer (needs the news graph first β see Phase 5 wiring).
Phase 5 β News Intelligence subsystem β
A standalone package news_intel/, deliberately not finance-specific:
- Connectors (
connectors.py):NewsConnectorinterface; NewsAPI + GDELT implemented; RSS/Reddit/SEC/etc. are new connector classes, nothing else changes. - Store (
store.py): rawnews_articlestable (URL-hash dedup, re-fetch updates), entity link table, story tables β same SQLite file, own namespace. - Pipeline (
pipeline.py): Fetch β Clean(dedup) β Extract(entities) β Embed β Build relationships β Update graph β Index, each stage a function. - Stories (
stories.py): embedding + shared-entity clustering groups articles into evolving stories. - Ranking (
rank.py): relevance Γ freshness decay Γ source credibility Γ entity graph-degree. - Service (
service.py) + REST:/api/news/search,/api/news/stories,/api/news/entity,/api/news/status,/api/news/refreshβ any domain module (Finance, Biologyβ¦) consumes these; nothing in the package imports from a domain. - Optional scheduled refresh (env
NEWS_REFRESH_MINUTES, off by default). - Graph output lands in the existing
newssource (entities + article nodes +mentions/co_mentionededges), so navigator/discover/3D UI work on it with zero changes β the proof of loose coupling.
Phase 6 β Verify, document, ship β
End-to-end verification in the live preview; CLAUDE.md / README / AURELIUS_LEARNINGS updated; deploy steps for Hugging Face Spaces (backend) and Vercel (frontend).
Future (deliberately out of scope now)
- Postgres + pgvector swap (
GraphStoreinterface is already shaped for it). - GraphSAGE upgrade over node2vec; cross-source entity resolution (news "Nvidia" β finance NVDA β wikipedia "Nvidia").
- Timeline mode over story clusters; event-propagation explorer (news event β entities β finance exposure).
- LLM explanation layer (optional service, explicitly outside the core).