5.3 KiB
5.3 KiB
HANDOFF.md — Session Handoff (OVERWRITE at the end of every phase or when context is getting long)
Read order for a new session:
NOTES.md→STATUS.md→ this file → then work. If this file disagrees with the code, trust the code and fix this file.
1. Where we are
- Last completed step: 8.3 (Public profile UI page) — TICKED in STATUS.md
- Next step: Phase 9 — Hardening & Polish (9.1 first)
- Updated: 2026-10-21
- Was the last session cut off mid-task? No
2. Verified state (run these first)
| Command | Expected |
|---|---|
npm install |
succeeds |
npm run migrate |
applies 001–006 / "nothing to do" |
npm test |
172 passing, 0 failing (85 unit + 87 integration) |
3. What exists now (files that matter)
public/profile.html— Public hero profile page (reads ?name=, displays stats/equipment).public/js/profile.js— Fetches GET /api/heroes/:name, renders profile, handles 404.src/services/heroProfileService.js—getHeroProfile(heroName): case-insensitive lookup, returns name/class/level/xp/gold/str/agi/int/vit/kills/deaths/equipment.src/routes/heroProfile.js—GET /api/heroes/:name(public, no auth).src/services/leaderboardService.js—getLeaderboard(type, page, limit).src/routes/leaderboard.js—GET /api/leaderboard?type=level|gold|kills&page=1.src/services/expeditionService.js— start, getActive, claim, listDefinitions.src/routes/expeditions.js— 4 expedition endpoints.src/services/shopService.js— getStock, buyItem, sellItem.src/routes/shop.js— GET/POST shop endpoints.src/services/inventoryService.js— listInventory, equipItem, unequipItem, useConsumable.src/services/huntService.js— hunt (one transaction).src/services/characterService.js— createCharacter, getCharacterProfile, getCharacterIdForUser.src/services/authService.js— register, verifyLogin.src/game/combat.js— resolveCombat.src/game/stats.js— calcDerived, xpToNext, checkLevelUp.src/game/energy.js— computeEnergy.src/utils/time.js— now()/setNow()/resetNow().public/game.html— dashboard with stats panel, tabbed action panel (Hunt/Inventory/Expedition).public/js/game.js— hunt UI + inventory UI + expedition UI.public/shop.html— dedicated shop page.public/login.html,public/register.html,public/create-hero.html— auth & hero creation.tests/integration/profile.test.js— 5 integration tests.
4. Half-finished / fragile things
- No leaderboard UI yet (Phase 8, but 8.1/8.2 API done — could add UI if desired).
- HP never regenerates naturally; only level-up restores it.
- No restart-persistence test for sessions.
npm run seedscript in package.json points to nonexistentscripts/seed.js.- Equipment bonuses not yet passed into combat (Issue #5 in STATUS.md).
- Starter gear (GAME_DESIGN.md §Items) documented but not auto-created on character creation.
GET /api/zonesdocumented in API.md but not implemented (Issue #2).- Phase 9 (hardening) not started.
5. Decisions & deviations from the docs
- D-004..D-007 in
docs/DECISIONS.md(combat rounds, equipment counted once, session store, clock). - Zod query param parsing uses
zod.coerce.number()because Express query params are strings. - Inventory response uses
itemId(item.id) andinventoryId(inventory row id) to avoid confusion. - Consumable effect parsing: regex
^(heal|energy):(\d+)$on items.effect field. - Qty decrement avoids CHECK constraint violation: delete directly when qty==1, decrement when qty>1.
- D-008: Shop materials with buy_price=0 sell at
floor(default_rate * character_level / item_min_level). - D-009:
sellItemchecks equipped_slot before material type. - D-010:
startExpeditionchecks active-expedition before energy. - D-011:
computeEnergyusesnow()from utils/time.
6. Gotchas learned
npm testmust benode --testwith NO path/glob; files must be named*.test.js.- better-sqlite3-session-store ignores
clear:false; that's why the timer is unref'd. - Statement caches are per-DB-handle (WeakMap) in huntService; copy that pattern for new services.
- Verify test COUNT, not just "all passing".
- Node.js
fetchdoesn't persist cookies across calls — extractSet-Cookieheader and pass manually in integration tests. - SQL
SELECT idfrom inventory returns the auto-increment row id; rename withAS inventory_idwhen you also needitem_id. - Transaction callback args must match the call order exactly.
- Error responses from route-level
AppErrors do NOT includedatafield. setNowaffects ALLnow()calls including those in service logic.- Shop API returns
{ ok: true, data: { stock: [...], character: {...} } }— field isstock, notstocks. - Shop stock items have flat fields (
itemId,buyPrice), not nested (item.id). - New characters have NO inventory items (starter gear not auto-created yet).
- Hero profile endpoint is PUBLIC — no
requireAuthmiddleware. - Profile page is public: no auth.js guard needed; uses ?name= query param for lookup.
7. Next-step briefing (9.1)
- Goal: Walk the SECURITY.md checklist; fix gaps.
- Docs: SECURITY.md, CODING_STANDARDS.
- Phase 9 is hardening & polish — review security, add error pages, loading states, mobile responsive pass, final playable run.