5.1 KiB
5.1 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: 5.2 (inventory/equipment services + routes — list, equip, unequip)
- Next step: 5.3 — stackable consumables: POST /api/inventory/use (health potion heals; energy tonic restores energy, capped)
- Updated: 2026-10-20
- 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–004 and 006 / "nothing to do" |
npm test |
111 passing, 0 failing (87 unit + 24 integration) |
3. What exists now (files that matter)
src/game/stats.js—calcDerived()is the ONLY derived-stat formula. Also re-exports xpToNext/checkLevelUp.src/game/combat.js—resolveCombat(hero, monster, rng); both sides attack each round, faster first.src/services/huntService.js—hunt(characterId, zoneId, {rng, now}); ONE transaction; test-injectable.src/services/zoneService.js—listZones(characterLevel)→ zones withunlockedflag.src/services/combatLogService.js—getCombatLog(characterId, limit)→ recent fights.src/services/characterService.js—createCharacter,getCharacterProfile,getCharacterIdForUser.- NEW:
src/services/inventoryService.js—listInventory,equipItem,unequipItem. Uses WeakMap stmt cache. Derived stats recalculated on list. - NEW:
src/routes/inventory.js—GET /api/inventory,POST /api/inventory/equip,POST /api/inventory/unequip. Zod-validated. src/utils/time.js—now()/setNow()/resetNow(); never callDate.now()in services.src/routes/zones.js—GET /api/zones.src/routes/combatLog.js—GET /api/combat-log.src/db/migrations/003_content.sql— also SEEDS zones/monsters/items/loot (INSERT OR IGNORE).src/db/migrations/004_inventory.sql— inventory table, FK constraints, partial unique index for equipped slots.tests/integration/inventory.test.js— 13 integration tests for inventory service.public/game.html— dashboard with stats panel, zone list, combat log, result panel.public/js/game.js— full hunt UI: load zones, hunt handler, result display, combat log replay, toast notifications, energy sync.public/css/main.css— zone cards, combat log entries, result panel, toast styles.
4. Half-finished / fragile things
- No consumable use endpoint yet (Phase 5 step 5.3).
- No UI for inventory/equipment (Phase 5 step 5.4).
- 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).
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.
6. Gotchas learned
npm testmust benode --testwith NO path/glob; files must be named*.test.js. A shell glob once skipped 17 tests.- 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. - Express query params are strings, not numbers — use
zod.coerce.number()for numeric query params. - SQL
SELECT idfrom inventory returns the auto-increment row id; rename withAS inventory_idwhen you also needitem_id. itemInSlotquery must aliasid AS inventory_idsoexisting.inventory_idworks in unequip logic.
7. Next-step briefing (5.3)
- Goal: Stackable consumables:
POST /api/inventory/use— health potion heals HP (capped at maxHp); energy tonic restores energy (capped at ENERGY_MAX). Only consumable type items can be used. Consumable is consumed (quantity -1, removed when 0). - Docs: DATABASE.md (§004_inventory), GAME_DESIGN.md §Items, BALANCE.md (effect format: 'heal:50', 'energy:25').
- Files to create/modify: extend
inventoryService.jswithuseConsumable(characterId, itemId), extendinventory.jsroute. - Key rules: parse
effectfield from items table ('heal:N' or 'energy:N'); validate character has the item in inventory (quantity >= 1); apply effect; decrement quantity; remove row when quantity reaches 0; return updated inventory listing. - Tests: happy-path heal, happy-path energy, use on non-consumable rejected, insufficient quantity, effect capped at maxHp/energyMax.
8. Open Known Issues
STATUS.md issues 1–6 (balance, dangling seed script, restart test, equipment-in-combat, HP regen, zone min_level balance).