| # 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 unless `GEMINI_API_KEY` is |
| > 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 only `NodeRef`/`Edge` through the `GraphSource` |
| protocol; 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_path` regression fence, |
| stagnation escape, and `PRUNE_MIN_SURVIVORS`. No algorithm change needed; |
| "bidirectional A*" in product terms maps to this meeting-check design |
| (true A* is impossible here β `1 β cosine` is 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 existing `features` JSON column. |
| |
| ### Bugs / hygiene found in review (fixed in Phase 0) |
| 1. **`_ip_hits` rate-limit dict grows without bound** (`server.py`) β a |
| `defaultdict(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. |
| 2. **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 a |
| `not_found` timeout message. |
| 3. **Superseded v1 modules still on disk** (`search.py`, `wiki.py`, root |
| `embedding.py`) β no longer imported by anything but easy to edit by |
| mistake. Deleted (git history keeps them). |
| 4. **`data/*.db*` not git-ignored** β locally-generated SQLite (+ WAL/SHM) |
| would land in commits. Added to `.gitignore`. |
| 5. **No edge evidence for ingested sources** β `StoreBackedSource` inherited |
| the no-op `edge_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. |
| 6. **Unused import** (`random` in `server.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 with `type`, `weight`, and human `display`, powering click-to-expand. |
| - `edge_display` for 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 `zoomToFit` after 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_member` replaces the old |
| O(nΒ²) pairwise `same_sector` edges. |
| - **ETFs** (SPY, QQQ, DIA, sector SPDRs) with `holds` edges 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_correlates` edges are *computed* from |
| return correlation, so the macro linkage is evidence, not assertion. |
| - `co_moves` correlation 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`): `NewsConnector` interface; NewsAPI + |
| GDELT implemented; RSS/Reddit/SEC/etc. are new connector classes, nothing |
| else changes. |
| - **Store** (`store.py`): raw `news_articles` table (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 `news` source (entities + article |
| nodes + `mentions`/`co_mentioned` edges), 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 (`GraphStore` interface 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). |
| |