## Codex review on 6bb1c81
### #1 Critical (corrected): visible ball not syncing
Codex заявил что ball.syncSprite() нигде не вызывается. Это неверно —
syncSprite вызывается каждый update tick на MatchScene.ts:216 (grep
подтверждает). Но описанный симптом (ball визуально не двигается) —
реальная проблема и требует hardening.
Hardening:
- Ball.setPosition() теперь immediate-sync sprite вместе с physics body.
Раньше при teleport (stuck nudge, hard respawn) sprite оставался на
старой позиции до следующего update tick — теоретическая 1-frame
рассинхронизация устранена.
- Ball sprite получил setDepth(30) — выше fixed/setup bumper'ов чтобы
не быть случайно перекрытым в render order.
### #2 High: double-centering canvas
Корень: #game-container использовал display:flex justify-content:center,
И Phaser Scale.CENTER_BOTH добавлял margin-left на canvas. Оба
центрирования складывались → canvas сдвинут вправо.
Fix: убрал flex из #game-container, оставил только Phaser CENTER_BOTH
(он надёжно центрирует через computed margin'ы).
### #3 Medium: physics fix не тестируется
Extract Bumper outward-force logic в pure helper src/game/bumperPhysics.ts
(computeOutwardForce). Возвращает new velocity или null если apply не
нужен.
src/game/bumperPhysics.test.ts — 10 unit-тестов:
- happy paths: fast outward, fast diagonal outward → null
- force apply: slow outward (still apply min speed), fast inward,
zero velocity, fast tangential (radial<threshold)
- direction correctness: ball over bumper → outward up; ball diagonal
→ outward по диагонали 45°
- degenerate: ball точно в центре bumper → fallback вверх
- REAL stuck regression: low speed + radial nearly zero → force outward
Bumper.handleBallHit рефактор: вызывает computeOutwardForce, applies
если non-null.
117/117 tests (было 107). typecheck/lint/build ✅.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Mobile match controls (codex #1 High): 3 touch zones внизу MatchScene
(L / BOOST / R). Visible semi-transparent overlay'и; работает и на mouse,
и на touch. Keyboard input теперь optional (this.keys?), не падает на
headless mobile.
- Turbo first-hit bug (codex #2): guard на lastHitTime > 0 — иначе первый
удар по turbo в первую секунду давал 0 очков (now < 0 + 1000).
- AI behavior diff (codex #3): добавлен PersonalityModifier (triggerDistBonus,
reliabilityMul, reactionMul). Defensive: +reliability, -reaction.
Aggressive: +trigger distance, -reliability. Ghost: 15% «эхо-double-swing»
(обе стороны одновременно). Trickster уже имел jitter modifier.
Поведенческие отличия теперь должны быть различимы за 5 матчей.
- Favicon 404 (codex #4 Low): inline SVG favicon в index.html, no more
console noise.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>