Imported from matthewtmonk-dot/offshiftoptions (
AGENTS.md). Install upstream withnpx skills add matthewtmonk-dot/offshiftoptions. Copyright stays with the author.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ (resolved from this file's directory; in monorepos the next package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by next dev — verify at node_modules/next/dist/server/lib/generate-agent-files.js. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.
IMPORTANT — Project Continuity and Engineering Rules
Before doing meaningful work in this repository, read PROJECT_HANDOFF.md.
If Matt explicitly says "Read PROJECT_HANDOFF.md": read it in full, read this file, and verify enough repository context to understand the current state. If there are no critical blockers, respond with only Ready. — no summary, no recap, no next-steps list.
PROJECT_HANDOFF.md is the canonical current-state document (architecture, deployment, database/seed safety, environment variables, invariants, current roadmap, and known issues) — it is deliberately concise; read it first, in full, before reading anything else. It points to docs/PROJECT_HANDOFF_ARCHIVE.md and the other docs/*.md files for chronological history and subsystem depth — read those only when a task actually needs that detail, not by default. This AGENTS.md file covers general operating notes; PROJECT_HANDOFF.md is authoritative for project state.
After every meaningful project change, update PROJECT_HANDOFF.md automatically before considering the task complete. Matt should never need to ask. "Meaningful" includes changes to application behavior, architecture, database/schema, auth, deployment, environment variables, hosting/domain, external integrations, scanner, market-data behavior, Schwab status, security, PWA, chat, notifications, production status, known issues, technical debt, test status, or important decisions. Never put secrets into PROJECT_HANDOFF.md or any other tracked file.
Do not blindly implement a technically weaker approach just because Matt requested it. Evaluate significant technical requests for security, data safety, maintainability, production reliability, deployment compatibility, and standard best practices. When a clearly better solution exists, recommend and prefer it unless Matt explicitly says he understands the tradeoffs and wants the original approach anyway.
Off Shift Options Agent Notes
Off Shift Options (formerly "LST Buddy") is a private, fun, educational trading research and tracking PWA for Matt and Eric. It helps with conservative cash-secured-put research, manual/demo tracking, watchlists, recommendations, chat, notifications, and rule-following. The "My LST" scanner profile name refers to the underlying Low Stress Trading strategy, not the app's product name.
The product has four connected jobs - Scan (technical opportunity), Research (personal company judgment, private by default), Track (append-only campaign history), Performance (whether the strategy works over time) - see PROJECT_HANDOFF.md's Product Model section before touching any of them. A personal Research judgment must never change a Scan result's technical score. "Watchlist" was renamed to "Research" (2026-09, /watchlist now redirects to /research) - don't reintroduce a separate watchlist concept.
Absolute Product Rule
This application does not place trades. Do not add buy, sell, place order, submit order, replace order, cancel order, automated trading, or algorithmic execution methods. Schwab integration is read-only.
Schwab market data is shared application infrastructure, but brokerage account data is user-scoped. Never reuse Matt's OAuth/account authorization for Eric or let one user's balances, positions, transactions, imported records, campaigns, settings, performance, projections, or trading achievements populate or affect the other user's account.
Stack
- Next.js App Router
- strict TypeScript
- Prisma 7 with PostgreSQL
- Tailwind CSS
- server-side cookie/database sessions
- pnpm
- Vitest
- Docker Compose
Commands
pnpm devpnpm build(runsprisma generate && next build— this is also the exact Hostinger production build; it never seeds, bootstraps, or applies migrations, seedocs/ARCHITECTURE.mdDeployment)pnpm lintpnpm typecheckpnpm testRUN_DB_TESTS=1 DATABASE_URL=... pnpm test(opt-in database integration tests)pnpm test:e2e(Playwright smoke tests against a running app)pnpm db:migratepnpm db:seed(destructive, local development/reset data only — never run against production)pnpm db:resetpnpm bootstrap:production(safe, non-destructive, idempotent production user bootstrap — not part of routine deploys)docker compose up --build
Coding Expectations
- Keep financial calculations isolated in
src/domain/financeand covered by deterministic tests. - Account/trading performance must be derived from the append-only ledger (
AccountLedgerEntry), never fromcurrentBalance − startingBalance— a deposit or withdrawal must never be mistaken for trading profit or loss. SeePROJECT_HANDOFF.mdAccount Ledger section. - A scanner criterion's default
enabledstate must come fromSCANNER_RULE_DEFINITIONS[...].defaultEnabled, not left to the database column default — this bit us once inprisma/seed.ts(every rule silently defaulted to enabled). - Brokerage import/reconciliation: never use a filename or CSV row number as economic identity — use
BrokerRecord.fingerprint(the economic fact) andidentityKey(the same real-world slot, without financial fields) instead. A same-identity-different-fingerprint match is aCONFLICT, never a silent overwrite. CampaignEvents remain the sole trading-performance source of truth even for a Campaign created from reconciled broker evidence — a Realized Gain/Loss import may only verify a Campaign's result, never add to it. - Keep scanner logic in
src/domain/scannerwith PASS/FAIL/UNKNOWN per criterion. - Enforce privacy server-side with
src/lib/privacy.ts; never rely only on React hiding. - Treat Phase 1 financial values as DEMO or MANUAL.
- Use record-level
Visibilityfor shareable records. - Keep UI friendly with restrained green accents; the app now supports Dark (original look, default for existing users)/Light/System appearance — see
PROJECT_HANDOFF.mdAppearance System section. Use red/green mainly for fail/pass states, consistently in both themes. - Never use a Tailwind color-scale literal (e.g.
text-zinc-950) for something that must stay a fixed color regardless of theme, such as dark text on a permanently-bright accent button — the Light theme remaps that same scale variable, so a "fixed" use of it silently becomes illegible. Usetext-black/a dedicated non-remapped value instead. This bit us once (10 files fixed in the Appearance System slice). - When running Playwright against
next dev, usePLAYWRIGHT_BASE_URL=http://localhost:<port>, never127.0.0.1— Next's dev-mode cross-origin asset guard silently 403s JS chunks requested via the IP literal, breaking client hydration (and therefore everyonClick-driven assertion) with no visible test failure.playwright.config.ts's default already useslocalhost. - Playwright specs log in via the real email/password sign-in form, not a dev-only shortcut button — this is what lets the suite run against a genuine
next startproduction build, which is the authoritative pass/fail signal for this project (seePROJECT_HANDOFF.mdTesting section on the dev-only overlay artifact that otherwise makesnext devruns unreliable for anything involving Sign Out). - Never let a personal/preference field (Research status, exclusion, a future per-user setting) alter a Scan/Scanner result's technical score, status, or label. Compute them independently and join only for display — this is a load-bearing product invariant, not a style preference. See
PROJECT_HANDOFF.mdProduct Model and Research sections. - Don't blindly trust a claim about what a third-party API (e.g. Schwab's quote
fundamentalfield group) returns — verify the actual live response (field names, presence, units) before normalizing/displaying it. Guessing at units (e.g. Debt/Equity as0.42vs42%) is exactly the kind of silent-wrong-interpretation bug this project explicitly guards against. - Update
PROJECT_HANDOFF.mdautomatically after every meaningful change (see top of this file), keeping it concise — move chronological/historical detail todocs/PROJECT_HANDOFF_ARCHIVE.mdrather than letting it grow into a diary again.docs/HANDOFF.mdis an older, separate chronological session log (earliest project history, through the first production deploy) kept for detailed history.
Key Docs
Read PROJECT_HANDOFF.md first. These are subsystem/historical depth, read only when a task needs them:
docs/ARCHITECTURE.mddocs/DATA_MODEL.mddocs/DECISIONS.mddocs/PROJECT_HANDOFF_ARCHIVE.md— full chronological history superseded out of the root handoff (2026-09-20 cleanup)docs/HANDOFF.md— earliest project history (Phase 1 foundation)docs/SCHWAB_INTEGRATION.md