# NOTES.md — Project Brief (READ FIRST) ## 1. What you are building **Emberfall**: a fantasy persistent browser-based game (PBBG). Players register an account, create a hero, and spend regenerating **Energy** on actions. The world keeps moving while they are offline (energy regenerates, expeditions finish). All state lives in a database on the server. You are the only developer. A human will play-test the result. Working, simple, and correct beats ambitious and broken. ## 2. Hard constraints (do not violate) 1. **Stack is fixed:** Node.js (>= 20), Express, SQLite via `better-sqlite3`, `bcryptjs` for password hashing, `express-session` + `better-sqlite3-session-store` (or `connect-sqlite3`) for sessions, `helmet`, `express-rate-limit`, `zod` for input validation. Tests with the built-in `node:test` runner. 2. **Frontend is vanilla HTML/CSS/JS.** No React, no build step, no bundler. Static files in `public/`, talking to the JSON API with `fetch`. 3. **No new dependencies** without logging the reason in `docs/DECISIONS.md`. 4. **The server is the only source of truth.** The client never sends results, damage, gold, XP, or timestamps. It only sends *intent* ("hunt in zone 2"). 5. **No real-time ticks / cron loops for game logic.** Use *lazy evaluation*: compute energy regen and finished timers when the player next makes a request (see `docs/GAME_DESIGN.md` §Time). 6. **All SQL uses prepared statements with bound parameters.** Never build SQL with string concatenation. 7. **Keep files small** (aim < 200 lines). Split by responsibility. 8. **Game rules live in `src/game/` as pure functions** (no DB, no Express). They take data in and return data out, so they can be unit tested. 9. **Never store plaintext passwords.** Never log passwords or session secrets. 10. **Don't touch what isn't in the current step.** No drive-by refactors. ## 3. How to work (summary — details in docs/WORKFLOW.md) 1. Open `STATUS.md`. Find the first unchecked step in the lowest-numbered phase. 2. Read ONLY the docs that step references. 3. Implement the step in small pieces. Run the app / tests after each piece. 4. When the step's acceptance criteria pass, tick the box in `STATUS.md`, add a Session Log line, and record any new Known Issues. 5. Stop and re-read `STATUS.md` before starting the next step. If a doc is ambiguous or contradicts another doc, pick the simplest option, and write it down in `docs/DECISIONS.md`. Do not stall. ## 4. Priority order when things conflict Correctness & security > persistence works > game is playable > code tidy > fun extras. ## 5. Glossary - **Hero / Character:** the player's in-game avatar. One per account (v1). - **Energy:** action currency. Max 100. Regenerates over real time. - **Gold:** soft currency. Earned from combat/expeditions, spent in shops. - **Expedition:** a timed activity; started now, claimed later. - **Zone:** an area with monsters, level range, and loot. - **Lazy regen:** computing regen from `energy_updated_at` when needed. ## 6. Out of scope for v1 Real-money payments, email verification, password reset by email, websockets, mobile apps, 3rd-party OAuth, admin web UI. (Stretch goals are in STATUS.md.) ## 7. Definition of "game is playable" (v1 target) A new visitor can: register → log in → create a hero → see stats/energy → hunt monsters → gain XP/gold/loot → level up → equip items → buy/sell in the shop → start and claim an expedition → see the leaderboard → log out → log back in and find everything exactly as left (plus offline energy regen). ## 8. Automated loop mode This project may be driven by `scripts/run-agent-loop.sh`, which starts a fresh agent session per step. In that mode: do exactly the one target step named in the prompt, never run commands that block forever, never run `git commit`/`git reset` (the loop commits after it verifies `npm test`, and rolls back on failure), and never delete or weaken tests (the loop rejects runs where the passing-test count drops).