45 lines
4.8 KiB
Markdown
45 lines
4.8 KiB
Markdown
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)
|
|||
|
|
1. `.automaton/tasks/tracer-bullet-1-signup-cached-nvda-overview/SPEC.md` — YOUR EXACT SCOPE. Build only what it lists.
|
|||
|
|
2. `CONTEXT.md` (repo root) — domain glossary + Primary Rule (Education, not investment advice).
|
|||
|
|
3. `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.
|
|||
|
|
4. `.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, with `adj_close`), `symbol_demand` (refcount). Match DESIGN.md §1 Tier A + Tier D.
|
|||
|
|
- yfinance SourceAdapter: kinds `quote`, `price_history` (daily), `info/sector`. Use the `yfinance` python 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/stale` with 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
|
|||
|
|
1. Read the files above.
|
|||
|
|
2. Check the existing `app/` structure (Next 16, React 19, Tailwind v4, Zustand already present). Reuse it.
|
|||
|
|
3. Scaffold the Bun backend in a new `app/server/` directory (or `backend/` at repo root — pick one and be consistent). Install deps with bun.
|
|||
|
|
4. Implement TDD: write the schema + a failing test, make it pass; write CacheRepository interface + failing test, pass; etc.
|
|||
|
|
5. Run the test suite. Make it green. The Primary-Rule lint test must pass.
|
|||
|
|
6. 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.
|