Files
investor-flow/.scratch/parent-decomposition-backup.md

196 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_close` correct; split/dividend in `price_adjustments`; raw toggle available.
- [ ] Storage only Tier A shared; refcount in `symbol_demand` protects 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 up` boots 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.