Aurelius / ROADMAP.md
murtaza-2007
Add optional Gemini AI layer (additive, fallback-first)
19c6bad
|
Raw
History Blame Contribute Delete
8.93 kB
# 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).