diff --git a/HANDOFF.md b/HANDOFF.md index 8179073..0d570aa 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -76,7 +76,23 @@ gives clean manual stepping. `T.press('Space')` = tap. Dismiss the intro overlay player in reach 8/8; constructed perfect corner (s=28, g×1.9) is a WINNER, medium center ball is returned (run scenarios ~12x — single runs are flaky due to 9% aiFlub). +## Tennis feel — CONFIRMED GOOD by Oliver (2026-07-11), don't regress +- Volleys: pre-bounce contact gets reach x1.4 / window x1.8 (VOLLEY in config.js). +- Half-volleys: a RISING ball is hittable at any height; only a dropping ball below + CONTACT.minY is "past you" (trySwing). This was the big one — the assist parks you on + the landing spot, so feet-bounces were unhittable before. +- Miss diagnostics: every tennis swing logs to T.G.missLog (ring of 50); last miss reason + flashes on the HUD (TUNE.missHud); TAPPING THE SCOREBOARD toggles an on-screen dump of + the last 9 entries — Oliver screenshots that from his phone to report live situations. +- Benchmarks that must keep holding: CPU returns 11/12 serves; 30 simulated points with + human-like tapping (tap when incoming ball d<2.2–3.2) = 50 hits 0 whiffs; feet-bounce + tap sweep ≈ 19/30 winning frames. + ## Gotchas learned the hard way +- Browser-pane verification: python http.server sends no cache headers, so edited ES + modules often load STALE even after location.reload(). Reliable fix: preview_stop + + preview_start (a new port = new origin = cold cache). Always sanity-check a just-added + field exists (e.g. `T.G.newField !== undefined`) before trusting test results. - Sprite pipeline: generate via generate-image skill (needs OPENROUTER_API_KEY in repo .env, gitignored) → magenta background → scratchpad slice.py (chroma-key, segment, strip ground lines/dividers, common-scale per sheet, IDLE_TARGET_H=112). Generator sometimes ignores