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

100 lines
5.7 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.
# 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](https://github.com/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`](./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#фазовый-план`](./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-*`)