Developer Reference
Architecture
End-to-end system flow — from a user triggering an analysis to database writes and alert delivery.
System Overview
User action (manual or scheduled trigger)
│
▼
runAnalysis(token) src/server/debate/runAnalysis.ts
│
├─▶ runDebate(token) src/server/personas/index.ts
│ │
│ ├─▶ Bull parallel ──┐
│ ├─▶ Bear parallel │ MixRoute gpt-4o-mini
│ ├─▶ Quant parallel │ + Ryo MCP tools
│ ├─▶ Macro-Regime parallel │
│ ├─▶ Narrative parallel ──┘
│ └─▶ Contrarian sequential (after all 5)
│
├─▶ generateConsensus() src/server/consensus/engine.ts
│ └─▶ agreement level, conviction score, final_call
│
├─▶ detectDivergence() src/server/divergence/detector.ts
│ └─▶ DivergenceEvent if flip / agreement drop
│
└─▶ scoreVerdicts() src/server/backtest/scorer.ts
└─▶ updateReputation() per resolved positionBackground Jobs (Inngest)
alerts/trigger.scheduled
│
▼
alertTriggerCheck src/server/inngest/functions.ts
│ step.sleep(gapMinutes)
│ claim optimistic lock
│ runAnalysis(token)
│ evaluateConditions()
│
├─▶ notifyInApp → TriggerEvent record
├─▶ notifyEmail → sendAlertEmail() (1h cooldown)
└─▶ re-queue next check (infinite loop until disabled)
recheck/schedule.created
│
▼
scheduledRecheck src/server/inngest/functions.ts
│ step.sleep(gapMinutes)
│ claim lock
│ runAnalysis(token)
└─▶ advance nextRunAt, re-queueKey Files
| File | Purpose |
|---|---|
src/server/debate/runAnalysis.ts | Main orchestrator — runs debate, consensus, divergence, scoring |
src/server/personas/index.ts | runDebate() — parallel persona execution |
src/server/consensus/engine.ts | generateConsensus() — aggregates verdicts into a Consensus |
src/server/divergence/detector.ts | detectDivergence() — compares two consecutive snapshots |
src/server/backtest/scorer.ts | scoreVerdictsForToken() — resolves positions against price |
src/server/backtest/reputation.ts | updateReputation() — upserts Reputation records |
src/server/inngest/functions.ts | scheduledRecheck + alertTriggerCheck Inngest functions |
src/server/triggers/conditions.ts | evaluateConditions() — checks alert conditions |
src/server/email/mailer.ts | sendAlertEmail() — Nodemailer SMTP dispatch |
src/server/mcp/tools.ts | Ryo MCP API wrappers with 1 req/s rate limiter |
src/lib/llm.ts | askPersona() — MixRoute API call returning parsed Verdict JSON |
Data Flow
- Persona → Verdict — Each agent calls
askPersona(prompt)which hits MixRoute. The LLM uses the injected Ryo MCP tool results and returns a structuredVerdictJSON object. - Verdict → Consensus —
generateConsensus()groups verdicts by stance, computes weighted conviction (1.5× for majority), and determines thefinal_call. - Consensus → DivergenceEvent —
detectDivergence()compares the new consensus with the previous one for that token. Stores aDivergenceEventif a meaningful shift occurred. - Consensus → Reputation —
scoreVerdictsForToken()resolves any unresolved positions from prior debates using the new consensus's entry refs as a proxy price. Resolved positions update the relevantReputationrecord.