5.2 KiB
5.2 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.2 (Public profile:
GET /api/heroes/:name) — TICKED in STATUS.md - Next step: 8.3 — UI page for public hero profile.
- 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 |
167 passing, 0 failing (85 unit + 72 integration) |
3. What exists now (files that matter)
src/services/heroProfileService.js—getHeroProfile(heroName): case-insensitive lookup, returns name/class/level/xp/gold/str/agi/int/vit/kills/deaths/equipment (equipped item names by slot). Uses WeakMap stmt cache.src/routes/heroProfile.js—GET /api/heroes/:name(public, no auth). Returns 404 if hero not found.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.tests/integration/hero-profile.test.js— 5 integration tests.
4. Half-finished / fragile things
- No leaderboard UI yet (Phase 8).
- No public profile UI page (step 8.3 next).
- 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).
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.
7. Next-step briefing (8.3)
- Goal: Public profile UI page — a standalone HTML page showing the hero profile returned by
GET /api/heroes/:name. - Docs: GAME_DESIGN.md §Leaderboards, UI_GUIDE.
- Files to create:
public/profile.html,public/js/profile.js. - No new backend needed — the API endpoint already exists.
8. Open Known Issues
STATUS.md issues 1–6 (balance, dangling seed script, restart test, equipment-in-combat, HP regen, zone min_level balance).