4.8 KiB
You are implementing Slice 1 (tracer bullet) of the Investor Flow project. You are an implementer agent operating with read/bash/edit/write tools. The orchestrator will review your diff afterward.
READ THESE FIRST (in this order)
.automaton/tasks/tracer-bullet-1-signup-cached-nvda-overview/SPEC.md— YOUR EXACT SCOPE. Build only what it lists.CONTEXT.md(repo root) — domain glossary + Primary Rule (Education, not investment advice).docs/adr/0001-local-first-multi-tenant.md,docs/adr/0004-shared-cache-vs-per-user-fetch.md,docs/adr/0007-education-not-investment-advice.md— the load-bearing ADRs for this slice..automaton/tasks/investor-flow-platform-design/DESIGN.md— read Section 1 (Typed Schema, Tier A + Tier D only), Section 2 (API Surface, tRPC + auth seam + market.snapshot), Section 3a (CacheRepository + SourceAdapter interfaces — match these EXACTLY), Section 7 (test-seam map, FakeSourceAdapter, Primary-Rule lint).
Do NOT read all of DESIGN.md — only the sections above. It is 1379 lines; the rest is for later slices.
WHAT TO BUILD (from slice SPEC — do not over-build)
A Bun + SQLite backend + a single-page Next.js panel where a user signs up (email+password, argon2/bcrypt, NO 2FA), logs in, and sees a cached NVDA overview hydrated by one yfinance adapter behind CacheRepository + AdapterQueue, served via tRPC.
Concretely, establish the skeleton that every later slice extends:
- SQLite schema:
users,sessions,symbol_meta,price_quotes,price_candles(daily, permanent, withadj_close),symbol_demand(refcount). Match DESIGN.md §1 Tier A + Tier D. - yfinance SourceAdapter: kinds
quote,price_history(daily),info/sector. Use theyfinancepython package via a thin subprocess/HTTP bridge OR a JS yfinance client — pick the simpler one that works. No options/holders/fundamentals. - CacheRepository:
get/set/stalewith staleness (quote 60s market-hours / 15m after-hours; price_history daily locked EOD; sector weekly). Stale-while-revalidate (return cached immediately, enqueue background refresh). - AdapterQueue: token-bucket 1 req/sec sustained burst 2/sec; dedupe same
source|kind|symbol|paramsHash; exponential backoff on 429 (2,4,8,16,60s, 5 attempts → FAILED). - tRPC:
auth.signup,auth.login,market.snapshot(symbol). - SPA shell (reuse existing
app/Next project, do NOT create a new one): single-page, active-symbol Zustand signal (NVDA hardcoded), M1 Symbol Overview panel (name + sector + complexity badge default beginner + price + day-change sparkline + one-line "why this matters" placeholder + ADR-0007 footer). - Test infra: FakeSourceAdapter, in-memory SQLite fixture, tRPC integration test, Playwright contract test.
- Primary-Rule lint test: grep curated UI strings for stoplist ["buy","sell","you should","add to your","rotate into","action needed"] outside approved noun phrases ("buy-zone estimate" allowed). FAIL on imperative trade directive.
SCOPE GUARDRAILS — DO NOT BUILD
2FA/OAuth (slice 2) · onboarding wizard (slice 3) · full period="max" backfill (slice 4 — only fetch latest quote + recent daily candles for the sparkline here) · any other panel M2–M20 · LLM Gateway/ornith (M1 "why this matters" is a placeholder STRING, not an LLM call) · Docker Compose (slice 26).
ENGINEERING DISCIPLINE (from installed skills — follow these)
tdd: vertical slices, red-green-refactor. One test → one impl → repeat. Do NOT write all tests then all impl.codebase-design: CacheRepository and SourceAdapter are DEEP MODULES — small interface (match DESIGN.md §3a exactly), large implementation hidden behind it. The interface IS the test surface; tests cross the same seam as callers.- Tests use FakeSourceAdapter + in-memory SQLite. NO network calls in tests.
PRIMARY RULE (ADR-0007) — non-negotiable
No user-facing string says "buy/sell/hold this." ADR-0007 footer on the page: "Educational analysis, not investment advice. Verify the underlying data; you are responsible for your own decisions." Primary-Rule lint test must pass.
HOW TO WORK
- Read the files above.
- Check the existing
app/structure (Next 16, React 19, Tailwind v4, Zustand already present). Reuse it. - Scaffold the Bun backend in a new
app/server/directory (orbackend/at repo root — pick one and be consistent). Install deps with bun. - Implement TDD: write the schema + a failing test, make it pass; write CacheRepository interface + failing test, pass; etc.
- Run the test suite. Make it green. The Primary-Rule lint test must pass.
- When acceptance criteria in the slice SPEC are all green, STOP. Do not start slice 2.
OUTPUT
Write the code to disk using your edit/write tools. When done, print a concise summary: files created/modified, test command + result, and which acceptance criteria are met. The orchestrator (me) will review the diff.