Files
Emberfall/HANDOFF.md
T
2026-10-21 07:16:18 +11:00

81 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:** 7.3 (Expedition UI: start panel, progress bar, claim button) — TICKED in STATUS.md
- **Next step:** 8.1 — Leaderboard: `GET /api/leaderboard?type=level|gold|kills` top 50, with pagination param.
- **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` | **153 passing, 0 failing** (85 unit + 68 integration) |
## 3. What exists now (files that matter)
- `src/db/migrations/005_expeditions.sql` — `expedition_defs` + `expeditions` tables, unique active-expedition index, 3 seed definitions.
- `src/services/expeditionService.js` — `startExpedition`, `getActive`, `claimExpedition`, `listDefinitions`. Uses WeakMap stmt cache.
- `src/routes/expeditions.js` — `POST /api/expeditions/start`, `GET /api/expeditions/active`, `POST /api/expeditions/claim`, `GET /api/expeditions/defs`.
- `src/game/energy.js` — `computeEnergy` now uses `now()` from utils/time.
- `src/services/characterService.js` — `createCharacter`, `getCharacterProfile`, `getCharacterIdForUser`.
- `src/services/huntService.js` — `hunt(characterId, zoneId, {rng, now})`; ONE transaction; test-injectable.
- `src/services/inventoryService.js` — `listInventory`, `equipItem`, `unequipItem`, `useConsumable`. Uses WeakMap stmt cache.
- `src/services/shopService.js` — `getStock`, `buyItem`, `sellItem`. Uses WeakMap stmt cache.
- `src/game/combat.js` — `resolveCombat(hero, monster, rng)`; both sides attack each round, faster first.
- `src/game/stats.js` — `calcDerived()` is the ONLY derived-stat formula. Also re-exports xpToNext/checkLevelUp.
- `src/utils/time.js` — `now()/setNow()/resetNow()`; never call `Date.now()` in services.
- `src/routes/zones.js` — `GET /api/zones`.
- `src/routes/combatLog.js` — `GET /api/combat-log`.
- `public/game.html` — dashboard with stats panel, tabbed action panel (Hunt/Inventory/Expedition).
- `public/js/game.js` — full hunt UI + inventory UI + expedition UI (start panel, progress bar, claim button, auto-refresh).
- `public/css/main.css` — expedition UI styles (cards, progress bar, buttons).
- `public/shop.html` — dedicated shop page with buy/sell tabs.
- `tests/integration/expeditions.test.js` — 13 integration tests.
- `tests/integration/shop.test.js` — 16 integration tests.
- `tests/integration/shop-page.test.js` — 5 integration tests.
- `tests/integration/inventory.test.js` — 20 integration tests.
## 4. Half-finished / fragile things
- No leaderboard UI yet (Phase 8).
- HP never regenerates naturally; only level-up restores it.
- No restart-persistence test for sessions.
- `npm run seed` script in package.json points to nonexistent `scripts/seed.js`.
- Equipment bonuses not yet passed into combat (Issue #5 in STATUS.md).
- No shop link in game.html top-bar navigation.
## 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) and `inventoryId` (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:** `sellItem` checks equipped_slot before material type.
- **D-010:** `startExpedition` checks active-expedition before energy (so 409 ACTIVE_EXPEDITION takes priority over 422 INSUFFICIENT_ENERGY).
- **D-011:** `computeEnergy` uses `now()` from utils/time instead of `Date.now()` directly, so test time overrides work.
## 6. Gotchas learned
- `npm test` must be `node --test` with 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 `fetch` doesn't persist cookies across calls — extract `Set-Cookie` header and pass manually in integration tests.
- SQL `SELECT id` from inventory returns the auto-increment row id; rename with `AS inventory_id` when you also need `item_id`.
- Transaction callback args must match the call order exactly.
- Error responses from route-level `AppError`s do NOT include `data` field.
- `setNow` affects ALL `now()` calls including those in service logic — for tests that need to verify time-based behavior, manipulate the DB directly instead.
## 7. Next-step briefing (8.1)
- **Goal:** Leaderboard endpoint — `GET /api/leaderboard?type=level|gold|kills` top 50, with `?page=N` pagination.
- **Docs:** GAME_DESIGN.md §Leaderboards, DATABASE.
- **Files to create:** `src/services/leaderboardService.js`, `src/routes/leaderboard.js`.
- **Files to modify:** `src/app.js` (register route).
- **API:** `GET /api/leaderboard?type=level|gold|kills&page=1` — returns ranked list of heroes (name, level/gold/kills) with pagination metadata.
## 8. Open Known Issues
STATUS.md issues 1–6 (balance, dangling `seed` script, restart test, equipment-in-combat, HP regen, zone min_level balance).