16 KiB
Investor Flow — DECOMPOSITION (vertical tracer-bullet slices)
Per the to-issues skill: each slice is a thin vertical path through ALL layers (schema, adapter, cache repo, API, UI, tests) — narrow but COMPLETE end-to-end, demoable on its own, fresh-context per slice. Slice #1 is the approved tracer bullet. Slices are listed in dependency order (blockers first).
The shared tRPC integration seam (Section 7.2) and Primary-Rule lint (ADR-0007) are established in slice #1 and extended by every slice. Cache-only testability (fakes at the seam) is required; nothing reaches the network in tests.
Slice 1 — tracer-bullet-1: signup + cached NVDA overview [APPROVED]
What to build: User can sign up (email+password, no 2FA yet) + log in, and see a cached NVDA overview panel hydrated by one yfinance quote + price_history+info/sector adapter behind CacheRepository + AdapterQueue + a tRPC market.snapshot endpoint. Establishes: SQLite schema (Tier A price_quotes/price_candles/symbol_meta; Tier D users/sessions), one SourceAdapter (yfinance), CacheRepository staleness (quote 60s, sector weekly), single-page shell with active-symbol signal (NVDA hardcoded first), the tRPC seam, FakeLLM/FakeSourceAdapter test infra, and the Primary-Rule stub (landing page carries ADR-0007 footer).
Acceptance criteria:
- Signup → login → session cookie; users/sessions rows Tier D.
market.snapshot(symbol=NVDA)returns from cache; UI renders price + sparkline + one-line sector.- Stale-while-revalidate: UI renders cached immediately; background AdapterQueue job refreshes.
- AdapterQueue dedupe collapses two concurrent NVDA snapshot calls into one yfinance fetch.
- Playwright + Playwright-contract: shell single-page, active-symbol rehydration works, ADR-0007 footer present, no imperative-trade-verb in any string.
- Primary-Rule lint test runs and passes (stoplist). Blocked by: None.
Slice 2 — auth-2fa-and-social-oauth
What to build: Add TOTP 2FA + social OAuth (GitHub/Google) to slice 1; session includes complexity default beginner; refresh-token flow. Adds two_factor table + oauth_identities.
Acceptance criteria:
- 2FA enrollment + login works; backup codes generated.
- Social OAuth sign-in / link existing account.
- Session carries complexity; UI reflects beginner defaults. Blocked by: Slice 1.
Slice 3 — onboarding-wizard
What to build: First-login wizard: complexity pick, risk tolerance, drawdown-tolerance plain-English Q (gentle-halt explained), starter watchlist (IREN, CIFR, ASST, SLNH, BKKT, NUAI, NVDA, BTC, SATA) with one-line reasons + ticker-kind, optional portfolio CSV/manual. Writes Tier C watchlist + portfolio. Explicit ADR-0007 statement during onboarding. Acceptance criteria:
- Wizard completes → user has complexity, risk tolerance, first watchlist (default set with ticker-kind).
- Crypto symbols flagged "limited research module"; SEC-derived rows gated.
- Onboarding explicitly states "educational tool, not financial advice". Blocked by: Slice 2.
Slice 4 — yfinance-backfill-permanent-ohlcv
What to build: On first symbol-track (Slice 3 starter watchlist) trigger history(period="max"); write permanent daily OHLCV with adj_close + price_adjustments for splits/dividends; this enables backtests. Extend yfinance SourceAdapter kinds; staleness = daily locked end-of-day.
Acceptance criteria:
- First track of NVDA backfills years of daily candles; rerun is a no-op (stale only checks for NEW).
adj_closecorrect; split/dividend inprice_adjustments; raw toggle available.- Storage only Tier A shared; refcount in
symbol_demandprotects while user tracks. Blocked by: Slice 3.
Slice 5 — chart-lab-panel (M2)
What to build: M2 panel — multi-timeframe candles + volume + indicator toggles (EMA 9/21/50/200, RSI, relative volume) reading permanent OHLCV from cache. Per-indicator one-line lesson tooltip (P7 G2). No trade signals; every chart string passes Primary-Rule lint. Acceptance criteria:
- 1D/1W read from cache; intraday opt-in.
- EMA200 tooltip gloss present; no buy/sell arrows; relative-volume "above/below typical" not "bullish/bearish".
- P7 + Primary-Rule lint pass. Blocked by: Slice 4.
Slice 6 — sec-edgar-adapter-and-filings-panel (M6)
What to build: SEC EDGAR SourceAdapter (filings_index, full_text_search, primary_doc, company_facts, 13f_holdings, form4_tx, 13d/13g, filer_cik_meta SIC). M6 filings panel with summaries + materiality 8-K heuristics. ETAG/If-Modified-Since; immutable cache forever. LLM filing_summary via FakeLLM fixture in tests.
Acceptance criteria:
- Fetch a 10-K + 8-K with UA + 8 req/sec; 304 re-check is a no-op.
- Filter by form type/date; "Summarize" renders cached summary; materiality tags present.
- Filer CIK/SIC fetched once, cached; class-inference ready for next slice. Blocked by: Slice 1 (schema seam).
Slice 7 — institution-flow-engine (M4 view) + insider-stream (M5)
What to build: InstitutionFlowEngine deep module behind M4 per-symbol view (5 holder classes via CIK/SIC; 13F diff; buy-zone estimate stamped "estimated"). Form 4 adapter paths for M5 Insider Activity Stream (Informed Buy/Sell/Routine via 10b5-1). Plotted on quarterly price strip with citation chips. Acceptance criteria:
- Each owner class has one-line plain-English meaning; buy-zone estimate always stamped "estimated".
- Form 4 informed events distinct from routine; Routine hidden by default for beginners.
- Class via CIK SIC metadata, not name heuristics. Blocked by: Slice 6.
Slice 8 — institutional-dashboard-rollup (M4 dashboard)
What to build: M4 dashboard rollup across watchlist + portfolio; compact grid (Symbol / Net Active Conviction Δ / insider recency / class-roll flag / alert); sortable + filterable; one-paragraph LLM dashboard_rollup summary (always on, ADR-0005 voice, ADR-0007 footer).
Acceptance criteria:
- Rollup reads across owned watchlists+portfolio; grid sortable; LLM rollup summary present + cited.
- Summary passes Primary-Rule lint (no "follow this flow"). Blocked by: Slice 7.
Slice 9 — sector-rotation (M7)
What to build: RotationDetector deep module: RS-breadth thrust + cross-sectional rank; incipient signal detection daily; γ two-stage resolution (price ~4wk + institutional at quarter-end); rotation phase labels + confidence; retention of signal history with real/false labeling. Acceptance criteria:
- Heatmap (RS-ratio + rel-volume) + phase labels; signal-history table shows resolution timestamps; false-alarm rate visible per signal type.
- γ resolution labels real vs false; educational framing "capital appears to be moving". Blocked by: Slice 4 (price history), Slice 7 (institutional).
Slice 10 — watchlist-portfolio-shell-panels (M9 + M10 minimal)
What to build: M9 multiple watchlists (add/import/drag-reorder) with compact mini-overviews. M10 minimal portfolio (holdings, P/L) + journal entry collects Two-Axis Model: fundamental thesis WHY + invalidation criteria + technical entry WHEN + Confluence Rack (SlotLibrary default 4-slot beginner Rack).ApiKey: no TradePlan accepted without stop + risk% + thesis + invalidation criteria (server-side block). A_STAR/Strategy authoring disabled (not unlocked yet). Acceptance criteria:
- Watchlists CRUD + ticker-kind gating; portfolio CRUD.
- Journal TradePlan requires stop + risk + thesis-invalidation; server rejects otherwise with helpful error.
- Confluence Rack default 4-slot beginner; redundancy-awareness tags duplicate signals. Blocked by: Slice 3 (onboarding), Slice 4.
Slice 11 — sizing-engine-and-conviction-unlock (deep module behind M10/M16)
What to build: SizingEngine 4-layer sizing (stop / ATR / conviction-tier / correlation-cluster + macro gate); Conviction Tier unlock gate (20B→A, 10A→A_STAR) reading per-tier win-rate from journal; Two-Axis matrix enforced pre-create in UI AND server-side (High conviction × Bad entry = WAIT; override-with-written-reason). sizing_explain LLM feature. SizingEngine pure/cache-deterministic.
Acceptance criteria:
- Sizing computed from plan + account + portfolio + regime; A_STAR blocked until unlock met.
- Override-with-written-reason recorded; matrix enforced both sides.
- LLM "if your plan is X, the math implies ~Y shares" framing (Primary-Rule). Blocked by: Slice 10.
Slice 12 — strategy-lab-and-backtest (M16)
What to build: Author + parameterize Strategy bundles {Regime gate, Setup, Risk Policy, Exit Strategy}; BacktestEngine.run/evaluateLatest against permanent OHLCV. Symbol-locked at base unless Conviction Tier unlocks Strategy authoring (slice 11). Exit reasons: TA-stop/thesis-broken/target-hit. Sample-size caveat in UI. Acceptance criteria:
- Strategy author gated by unlock; backtest runs cache-only; exit-reasons labeled.
- Equity curve annotated with reasons; no "155% return!" hype highlight (P7).
- "this Strategy would have behaved" framing (Primary-Rule). Blocked by: Slice 11.
Slice 13 — universe-evaluator + filter-screener (M15a) + strategy-screener (M15b)
What to build: UniverseEvaluator deep module (one engine, two predicates: compiled filter expression OR Strategy entry conditions). M15a filter screener over tiered universe (watchlist → broader by sector). M15b strategy screener delegates to BacktestEngine.evaluateLatest. One-tap "open in workbench". Saved filter sets per-user (Tier C). Acceptance criteria:
- Filter screener runs instantly on watchlist universe; broader-scan gated with cost/time note.
- Strategy screener outputs conviction-strength + conditions-fired; one-tap loads M1.
- "discovery for learning" framing + ADR-0007 footer. Blocked by: Slice 12.
Slice 14 — sector-confirmation-via-screener cross-link
What to build: Wire screener + rotation: "show symbols in the rotated-into sector matching my Strategy". Educational framing only — NOT a ready-made buy list. Blocked by: Slice 9, 13.
Slice 15 — options-adapters-and-options-dd-panel (M3)
What to build: yfinance options_chain kind; M3 read-only Options Due Diligence panel — IV rank/percentile, greeks, OI walls, max-pain; defined-risk stamp; undefined-risk shaded with "advanced only". Feeds M17 in slice 19; never directional options. Acceptance criteria:
- Options data cached 15min; IV-rank bar teaches the mechanic (not hype gauge).
- Default no directional options; no "buy this call". Blocked by: Slice 1 (adapter queue).
Slice 16 — x-cookie-adapter-and-sentiment-feed (M8)
What to build: X cookie SourceAdapter (cashtag_search + trusted-account timeline) at 1 req/3s; cookie-expiry → FAILED + source-degraded UI. Reddit PRAW adapter. M8 sentiment feed with per-user trusted accounts + post_summary LLM. Attribution preserved; "crowds aren't edge" caveat. Acceptance criteria:
- X + Reddit threads cached 7d rolling; trusted accounts per-user.
- Cookie expiry alerts operator; UI shows cached-only.
- "Crowd sentiment is not edge" caveat visible; no "buy because Twitter is bullish". Blocked by: Slice 1.
Slice 17 — alerts-v1 (AlertEngine hybrid)
What to build: AlertEngine hybrid (event-driven for cheap Form4/13DA/quote-stale; poll for thesis-monitor). Alert types: informed_buy/sell, new_13da, rotation_incipient, regime_shift, conviction_unlock, thesis_broken/weakening, cluster_breach, drawdown_halt, asymmetry_warning. SSE push. Dedupe per filing. Acceptance criteria:
- Informed-buy fires once per filing (not every tick).
- Alert text "something changed" not "action needed" (Primary-Rule). Blocked by: Slice 7, 11, 9, 16.
Slice 18 — risk-engine-and-risk-posture (M20 + halt circuit breaker)
What to build: RiskEngine aggregator → RiskPosture + recommendedActions (reworded considerations per ADR-0007). Gentle halt circuit breaker: MaxDrawdownTolerance breach → halt_new_entries 24h + consider_reducing_position consideration; existing positions continue; HaltedError on journal.trade.create during cooldown. M20 posture surface; prominence on M19 (S20 read-only mobile from same API).
Acceptance criteria:
- Gentle halt blocks new entries 24h; existing continue; consideration reworded (ADR-0007).
- Asymmetry < 1 → warning; cluster > cap → consider_rebalancing_cluster.
- Every recommended-action has "trade-off to think through" frame + ADR-0007 footer. Blocked by: Slice 11.
Slice 19 — options-convexity-sleeve (M17)
What to build: M17 5-state unlock (Off → Covered Income → Cash-Secured Entry → Insurance Sleeve → LEAPS Conviction), defined-risk-only; naked永远 blocked; IV-Regime Gate; requires core position or articulated thesis; default OFF. Payoff diagrams teach the convex mechanic (P7 G1/G4). Reads M3 (slice 15). Acceptance criteria:
- 5-state unlock with demonstrated-understanding step before each elevation.
- Max-loss/breakeven/convex-shape labeled; no P&L celebration.
- "insurance / cheaper entry / defined leverage" frame only; ADR-0007 footer. Blocked by: Slice 15, 18.
Slice 20 — macro-module (M18)
What to build: FRED adapter + economic-calendar adapter (Ethercalc fixed safely); M18a calendar, M18b regime classifier, M18c Portfolio-Impact Commentary (LLM Druckenmiller lens, 2-horizon: short-term reaction risk with sample-size + disclaimer; long-term structural), M18d regime history. Never a macro-trade recommendation (Alfred caution). Acceptance criteria:
- Regime history lane teaches regime-shift mechanic; commentary samples disclosed.
- No macro-trade recommendations (Primary-Rule). Blocked by: Slice 18 (portfolio link + regime).
Slice 21 — thesis-monitoring-l1 (timeline + cover alerts wired)
What to build: L1 thesis monitor via local-only LLM (ADR-0006) cross-refs stated invalidation criteria against events (filing/insider/sentiment) → intact/weakening/broken; wiring into AlertEngine (thesis_broken/weakening). Feeds "consider exiting if thesis broken" — never silent hold (RiskEngine rule). Blocked by: Slice 17, 18.
Slice 22 — reports-research-note (M11 HTML v1)
What to build: ReportRunner HTML research-note v1 (inline SVG charts, P7, Analyst Voice, ADR-0007 footer). Scopes: symbol/watchlist/portfolio/rotation/sizing_year/risk_posture (cache-only reconstruction). Markdown + CSV/JSON deferred. Acceptance criteria:
- HTML report self-contained, opens in browser; browser print → PDF works.
- recommendedActions rendered as considerations+questions; ADR-0007 footer present.
- Cross-owner download → NotOwnerError; deterministic given cache. Blocked by: Slice 18.
Slice 23 — derisking-strategy-library (behind M10)
What to build: Derisking Library 6 (scale-out at targets / stop-trail-up EMA21-50 / thesis-based partial / option-protected collar / regime-cut / correlation-driven). derisk_suggestion LLM (Alfred framing — winners have flexibility; losers only cut, never average down). Options-protected hold depends on slice 19.
Blocked by: Slice 19, 21.
Slice 24 — mobile-companion (M19)
What to build: Thin responsive Next route (not RN in v1) reading same backend — alerts, P/L glance, condensed symbol story, thesis monitoring L1/L2/L3 in priority order. Read-mostly; limited authoring (add watchlist, ack alert, save post). No backtests/screens/strategy authoring; no P&L celebration animations. Acceptance criteria:
- Shares all backend work (refcounted shared cache — second client, not second product).
- ADR-0007 footer on every card; no trade-act buttons. Blocked by: Slice 17, 18, 22.
Slice 25 — admin-tooling (M13)
What to build: Operator CLI/hidden route: list users, reset pw, GDPR export, adapter queue health, rate-limit backoff reset, ownership labels on exports. Blocked by: Slice 1.
Slice 26 — docker-compose-deployment
What to build: Docker Compose target: Bun backend + SQLite volume + SPA build + secrets file (X cookies, LLM provider URL). Operator self-hostable. Acceptance criteria:
docker compose upboots the stack; secrets file mounted; SQLite volume persists.- ADM ADR-0007 footer present on deployed pages. Blocked by: Slice 22 (most features) — deployable earlier with subset.