Skip to content

Changelog

Newest first. Short, intentionally incomplete — commits on main are the source of truth, this is the human-readable roll-up.

2026-04 — P5 (UI v2 + quality)

Frontend rewrite

  • React 18 + Vite 5 + Tailwind 3 replaces the original vanilla HTML SPA. Four-tab nav (Dashboard / Watchlist / Claw / Settings), TypeScript throughout, typed API client + adapter layer bridging backend Pydantic shapes to display types.
  • Signal card redesign matches the v1 format pixel-for-pixel: headline, per-ticker salience bars (tier-coloured red / gold / blue), bilingual EN/ZH columns, collapsible reasoning broken out per [AGENT] tag, Impact + Confidence score bars, collapsible agent breakdown, async-hydrated OG preview, compliance disclaimer.
  • UserMenu dropdown — click the avatar in the header for email, Settings shortcut, and Sign out (no more detour through Settings).
  • TelegramWizard — the link flow is now a three-step numbered guide with inline copy-to-clipboard instead of a paragraph of fine print.
  • Ask StockClaw page gives the chat transcript ≥55vh and moves Historical Search below so the chat card isn't squeezed by the RAG block.
  • OS-adaptive light palette — GitHub-style white cards on pale-grey page, tuned so text-gray-100 headlines render near-black (previously near-white on grey — invisible).
  • Extended-hours prices — watchlist rows now show a PRE / POST badge + extended price + % change directly beneath the regular price when yfinance reports marketState in an extended session. Alignment is CSS-grid so 836.92 and 856.33 line up digit-for-digit with the ticker symbol above.
  • Live status strip — "Last updated 8s ago" is now driven by the hook's real fetch timestamp and ticks every 15s; the gold "What's moving the market" ticker rotates through the top 12 real signal headlines instead of four hardcoded demo lines.

Signal quality

  • Urgency tiers unambiguous — FLASH / ALERT / NOTE / FYI now render as four distinct badges (red / orange / gold / grey) instead of collapsing FLASH + ALERT into a single overloaded "BREAKING" label. Status strip counts split too: "2 FLASH · 18 ALERT" rather than "20 BREAKING".
  • Duplicate signal fixRawItem.raw_id now inherits the content_hash (sha256 of source URL + title) so the DB-level dedup in run_user_pipeline_task actually fires. Previously raw_id was a fresh UUID4 on every crawl, making the existing dedup a no-op; users were seeing the same Yahoo Finance article pushed every ~20min beat cycle. Also reduces OpenRouter spend (each duplicate article was triggering a fresh 5-agent synthesis run).

Ask Claw (RAG) fixes

  • BM25 tokeniserwebsearch_to_tsquery was AND-matching every word in the user's question, which almost never hit. Replaced with a tokeniser that OR-joins content words ("Should I buy NVDA right now?""buy | nvda") after dropping English stopwords.
  • Retrieval diagnostics[rag] empty retrieval log line shows visible-signal count + per-retriever hits so RLS vs. query-logic failures are telegraphed clearly.

Deploy / ops

  • Vercel SPA fallback/:path*/ rewrite so /login, /watchlist, etc. serve index.html on direct hits. Without this, Google OAuth's post-sign-in redirect to /login?code=… 404'd.
  • Market quote cache cut from 60s → 30s TTL; pre/post-market prices now surface within ~30s instead of ~1min.

2026-04 — P4 complete

  • P4.4 Google OAuth with JWKS/ES256 verification (Supabase's current default); Sign in with Google wired end-to-end.
  • Web Push: VAPID-authenticated browser notifications with deep-link back to the triggering signal; FLASH gets sticky (requireInteraction) banners.
  • Telegram multi-user: deliver_batch reads per-user telegram_chat_id from user_settings instead of a global env var; users must link via Settings.
  • Per-user chat id + RLS fix: user_scope now SET LOCAL ROLE authenticated so RLS policies actually fire — earlier code silently ran as the Postgres superuser with BYPASSRLS.
  • Agent breakdown panel: each signal carries per-agent impact / confidence / latency / error in a collapsible table under the card.
  • Per-ticker relevance bars + Open Graph preview cards for every signal's source article.
  • Signal card redesign to match the Telegram delivery format — bilingual side-by-side summaries, signal id, signal_type pill, expandable reasoning block.
  • Email magic link via Supabase (no Google account required to sign up).
  • Real Claw chat backed by hybrid dense + BM25 retrieval over your own signals, with every query logged to rag_query_logs.
  • Embedding pipeline: each new signal is embedded into ChromaDB (paraphrase-multilingual-MiniLM-L12-v2) immediately after commit.
  • Claw rules CRUD with an LLM-based natural-language parser (stored only; triggering is future work).
  • OS-driven dark/light theme for the whole SPA.
  • Real market data endpoints (/market/quotes, /market/indices) via yfinance + 60 s Redis cache.
  • Watchlist auto-bootstrap so new users land on a usable empty list instead of a dead "+ Add ticker" button.
  • Logout UI (avatar dropdown in the top bar).
  • Legal pages (/privacy.html, /terms.html) and this documentation site.

2026-04 — P3

  • Write endpoints: POST /watchlists/{id}/tickers, DELETE .../{ticker}, PUT /settings, POST /integrations/telegram/link, POST /claw/chat (then still an echo stub).
  • user_settings table.
  • Adding a ticker fires an immediate crawl.

2026-04 — P2

  • Read-only FastAPI: GET /signals, GET /watchlists, GET /health, /ws/signals WebSocket.
  • JWT auth + row-level security scaffolding.
  • Frontend flipped off mock mode.

2026-04 — P1

  • Supabase Postgres + Redis via docker-compose.
  • Celery + Beat orchestration.
  • Signal persistence: pipeline writes each produced SignalCard to the DB.
  • SQLite → Supabase watchlist migration.

2026-04 — P0

  • 5-agent synthesis engine with Reflexion and Pydantic validation.
  • RSS / yfinance crawlers.
  • Watchlist SQLite DB.
  • Frontend SPA (dashboard / watchlist / claw / settings) with PWA manifest.
  • Telegram bot delivery (single-user).