Files
Emberfall/HANDOFF.md
T
2026-10-21 06:59:52 +11:00

5.9 KiB
Raw Blame History

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.2 (Expedition API: start, active, claim endpoints) — TICKED in STATUS.md
  • Next step: 7.3 — UI: start panel, progress bar, claim button. Acceptance: start → close browser → return after duration → claim → rewards granted exactly once.
  • 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 151 passing, 0 failing (85 unit + 66 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 — NEW: startExpedition, getActive, claimExpedition. Uses WeakMap stmt cache.
  • src/routes/expeditions.js — NEW: POST /api/expeditions/start, GET /api/expeditions/active, POST /api/expeditions/claim.
  • src/game/energy.js — Modified: computeEnergy now uses now() from utils/time (for test time override compatibility).
  • 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.
  • 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/expeditions.test.js — NEW: 11 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.
  • public/shop.html — dedicated shop page with buy/sell tabs.
  • public/game.html — dashboard with stats panel, tabbed action panel (Hunt/Inventory).
  • public/js/game.js — full hunt UI + inventory UI.

4. Half-finished / fragile things

  • No expedition UI yet (step 7.3).
  • 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 AppErrors 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 (7.3)

  • Goal: Expedition UI — start panel, progress bar, claim button.
  • Docs: GAME_DESIGN.md §Expeditions, UI_GUIDE.md.
  • Files to modify: public/game.html (add expedition tab/panel), public/js/game.js (expedition UI logic).
  • APIs to use: GET /api/expeditions/active (check for active expedition), POST /api/expeditions/start { defId } (start expedition), POST /api/expeditions/claim { expeditionId } (claim finished expedition).
  • UI elements: expedition definitions list with level gating, energy cost display, progress bar with countdown, claim button when finished.

8. Open Known Issues

STATUS.md issues 1–6 (balance, dangling seed script, restart test, equipment-in-combat, HP regen, zone min_level balance).