Files
pinball-duel/KNOWN_ISSUES.md
aevgarik 39056fdc74 Phase 3: Booster «Захват», cloud-save, 15 achievements
Реализует Phase 3 в sprint-mode согласно scope-lock + DoD alternative
для Ghost (без adaptation, balanced setup). Полный AI booster откладывается
в Phase 3.5/4 — см. KNOWN_ISSUES.md.

## Booster «Захват» (player-side, полная реализация)

- src/game/Booster.ts — FSM idle→armed→aiming→cooldown
  + charge tracking (100 BP=1 заряд, max 2)
  + lockout 30s от match start
  + slow-mo trigger через event callbacks
  + aim rotation ±10° per tap
  + auto-shoot через cradleDurationMs=1500ms ИЛИ повторный tap
- src/scenes/MatchScene.ts wiring:
  - charge добавляется при credited player hit (result.creditedTo='player')
  - tap BOOST zone / keyboard S → handleBoosterTap
  - handleFlipperHit при armed → attemptCradle на nearest player flipper
  - tickBooster каждый update: sticky-ball anchor, aim indicator, auto-shoot
  - slow-mo через matter.engine.timing.timeScale + time.timeScale + tweens
  - HUD: «BOOST locked/armed/aim L/R · TAP/N/2» + полоска прогресса заряда
  - L/R input в aiming-фазе перенаправляются в booster.rotateAim (не flipper)
- 18 unit-тестов src/game/Booster.test.ts:
  initial state, lockout, charge accumulation/cap, FSM transitions,
  rotateAim/shoot from non-aiming = noop, autoShoot timing, callbacks.

## SaveState v1 + cloud-save

- src/services/SaveStateService.ts:
  - defaultSaveState() — полная схема SaveState (settings, statistics,
    cosmetics, campaign, tournament, achievements={}, ghostProfile=null)
  - SaveStateService.load() / save() через PlatformAdapter.cloudLoad/Save
  - applyMatchResult() — immutable update: statistics totals + achievements
- src/main.ts: cloud-load на boot, registry.set('saveState', state) +
  'saveService'; isReturning telemetry flag из totalMatches > 0
- src/scenes/MatchScene.ts:
  - persistMatchAndUnlocks(matchResult) после endMatch
  - errors swallow'аются + telemetry save_failed (не блокер UX)

## 15 Achievements

- src/types/index.ts: AchievementId union (15 IDs), AchievementsState
- src/config/achievements.ts: 15 определений с title/description
  (first_win, defensive/aggressive/trickster/ghost_*_win, flawless_5_0,
  bumper_master_50, defender_20, cradle_first_use, cradle_goal,
  comeback_3_4, golden_goal_win, marathon_10)
- src/scoring/AchievementEvaluator.ts:
  - evaluateAchievements(ctx) — pure function, проверяет условия
  - applyAchievementUnlocks() — immutable state update
- 17 unit-тестов: basic wins, personality×difficulty, flawless,
  bumper milestones, comeback, cradle/golden goal, marathon,
  applyUnlocks idempotency
- MatchScene: после endMatch evaluate + platform.unlockAchievement(id) +
  telemetry achievement_unlocked

## Hard difficulty (config-level)

- AIDifficulty='hard' уже работает через config (80ms reaction / 20ms jitter)
- UI label fixed: "Профи — 80мс реакция, jitter ±20мс" (раньше "(cradle — Phase 3)")
- AI cradle activation — backlog, см. KNOWN_ISSUES.md

## Sprint-mode Ghost

- GhostProfile остаётся null per scope-lock alternative DoD
- GhostAI без profile-tracking; balanced setup сохранён из Phase 2

## Telemetry

- bumper_hit (Phase 2 v3.10) — уже работает
- achievement_unlocked — emit per ID
- cradle_first_use — emit раз за match
- cradle_goal — emit при scoring через cradle anchor
- save_failed — emit при cloud-save error

## Docs

- KNOWN_ISSUES.md: Phase 3 partial DoD coverage (AI booster wishlist,
  Ghost sprint-mode rationale, defender_20 proxy heuristic)
- README.md: phase plan updated (0-3 )

Tests: 85/85 (5 файлов: calculateScores 16 + flipperGeometry 13 +
MatchTracker 21 + Booster 18 + AchievementEvaluator 17). Build 387KB gzip.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-24 08:36:43 +03:00

5.7 KiB
Raw Permalink Blame History

Known Issues

Каталог известных проблем и плановых работ. Обновляется при каждом codex/external review.

Toolchain (build-time, dev-only — НЕ попадает в production bundle)

npm audit: 4 moderate vulnerabilities в цепочке vite@5.4.21

Дата фиксации: 2026-05-24 (codex review #3, HEAD bb9f720).

Затронуто: esbuild ≤ 0.24.2, транзитивно через vite@5.x и vitest@1.x.

CVE / advisories:

  • GHSA-67mh-4wv8-2f99 — esbuild dev-server CORS: встроенный esbuild dev-server отражает произвольный Origin, что позволяет cross-origin чтение source-кода во время разработки.

Impact analysis:

  • Production bundle: не затронут. Vite/Rollup собирают финальный бандл во время npm run build; esbuild-код не отгружается клиенту. На YG/RuStore/Play загружается только dist/ (см. vite.config.ts, build section).
  • Dev-server: уязвим только при запуске npm run dev И биндинге на доступный по сети адрес. Vite по умолчанию слушает 127.0.0.1.

Mitigation (текущий):

  • НЕ запускать dev-server с флагом --host 0.0.0.0 или --host в untrusted сетях. Команда npm run dev дефолтно safe.
  • В CI и production builds esbuild dev-server не запускается вовсе.

Resolution plan: Контролируемый апгрейд toolchain перед Phase 5 (YG SDK integration), когда build chain в любом случае пересматривается:

  • vite 5.x → 8.x — major upgrade, ломает API:
    • build.rollupOptions.output — изменён shape
    • Plugin lifecycle hooks (buildStart, transform) — сигнатуры
    • Возможны проблемы с base: './' на YG (требует проверки)
  • vitest 1.x → 3.x — major upgrade, ломает API:
    • Test runner v3 API (setupFiles, globals)
    • Coverage provider config (@vitest/coverage-v8 обязателен)

Текущий ETA: ~ конец июня 2026 (вместе с Phase 5 prep). Не блокирует Phase 3-4.


Phase 2 — game-side

AI personality distinguishability — codified, требует внешней валидации

Дата фиксации: 2026-05-24 (codex review #3).

Поведенческие отличия 4 личностей реализованы (PersonalityModifier в src/ai/AIPlayer.ts, специальные хуки в DefensiveAI/AggressiveAI/GhostAI/TricksterAI). Однако Phase 2 DoD #X — «тестер различает 4 личности после 5 матчей» — не доказуем code-only проверкой; требует blind playtest.

Resolution plan: Прогон по playtest-protocol.md с внешним тестером (не разработчик) до закрытия Phase 2. Pass-bar: ≥75% blind-attribution accuracy.


Phase 3 — partial DoD coverage (sprint-mode scope)

Дата фиксации: 2026-05-24 (post Phase 3 implementation).

AI booster (cradle) — wishlist Phase 3.5 / Phase 4

DoD definition-of-done.md:166-171 требует:

  • Defensive Hard — cradle при защите
  • Aggressive Hard — прицельный бустер в углы ворот игрока
  • Trickster Hard — прицел через bumper-кластер (3-5 отскоков)

В текущей реализации Hard difficulty работает на уровне reactionMs/jitterMs (80ms/20ms через config). Полноценный AI cradle (с ray-tracing solver, прицеливанием, shot direction) — не реализован. Hard subjectively сложнее Medium через быструю реакцию, но без cradle-aim solver не отличается тактически.

Resolution plan: Phase 3.5 polish или Phase 4 (вместе с Hard playtest tuning). Базовая инфраструктура (Booster class с reusable state machine) уже готова — нужен второй instance Booster для AI side + ray-tracing solver (~3 сек × 12 углов имитация траектории до flipper-зоны игрока).

Ghost adaptation — sprint-mode (без profile-tracking)

Per scope-lock.md и definition-of-done.md:395-419 sprint-mode alternative DoD активирован. GhostProfile остаётся null в SaveState; GhostAI использует balanced setup без EMA-updates. Это сознательное решение для MVP — full adaptation добавляется как live-ops feature через 4-8 недель после launch'а.

defender_20 achievement — proxy эвристика

DoD требует «20+ BP через свои setup-bumpers за матч». В Phase 3 у MatchResult нет отдельного breakdown по source (только total bumperPointsEarned). Используется proxy: total BP ≥ 20. Точный source-breakdown добавляется в Phase 4 через extension MatchResult (poля bumperPointsBySource: {fixed, setup}).


Cross-references

  • Phase roadmap: README.md#фазовый-план
  • Concept docs: ~/Knowledge/Projects/pinball-duel/
  • Audit history: ~/Knowledge/Projects/pinball-duel/index.md (10 раундов до dc53623, затем codex rounds #1-3 в git log с тегом Post-codex-review-*)