Post-codex-review-3 docs: KNOWN_ISSUES + playtest protocol
- KNOWN_ISSUES.md: dev-only vite/esbuild moderate CVEs с impact analysis (production бандл не затронут), mitigation, плановый vite 5→8 + vitest 1→3 апгрейд перед Phase 5; AI distinguishability caveat с ссылкой на playtest. - playtest-protocol.md: 20-матчевая blind-attribution методика для закрытия Phase 2 DoD «тестер различает 4 личности»; рубрика per-match, expected tells (для оценщика, не тестера), randomization protocol, failure-mode follow-ups, report template, codex-automation roadmap. - README.md: новый раздел «Operational docs» с cross-ref на оба файла. Не код — операционная документация для closure Phase 2 и трекинга backlog. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
65
KNOWN_ISSUES.md
Normal file
65
KNOWN_ISSUES.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# 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.
|
||||
|
||||
---
|
||||
|
||||
## 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-*`)
|
||||
@@ -72,6 +72,11 @@ src/
|
||||
| **6** | YG polish + submission + soft launch |
|
||||
| **1.5** (post-MVP launch) | Capacitor: Google Play + RuStore mobile native |
|
||||
|
||||
## Operational docs (в репо)
|
||||
|
||||
- [`KNOWN_ISSUES.md`](./KNOWN_ISSUES.md) — toolchain vulnerabilities, плановые апгрейды, текущие game-side caveats
|
||||
- [`playtest-protocol.md`](./playtest-protocol.md) — спека blind-attribution тестирования AI-личностей для закрытия Phase 2 DoD
|
||||
|
||||
## Документация (концепт-пакет)
|
||||
|
||||
`~/Knowledge/Projects/pinball-duel/` — 19 файлов:
|
||||
|
||||
132
playtest-protocol.md
Normal file
132
playtest-protocol.md
Normal file
@@ -0,0 +1,132 @@
|
||||
# Playtest Protocol — Phase 2 AI Distinguishability
|
||||
|
||||
**Цель.** Закрыть Phase 2 DoD «тестер различает 4 AI-личности после 5 матчей»
|
||||
через blind attribution. Требуется внешний тестер (НЕ разработчик и НЕ автор AI кода).
|
||||
|
||||
**Pass-bar:** ≥ 75 % правильных attribution-ответов (≥ 15 / 20) ИЛИ ≥ 1 distinct tell
|
||||
per личность, названный тестером без подсказки.
|
||||
|
||||
---
|
||||
|
||||
## Подготовка
|
||||
|
||||
| Шаг | Команда / действие |
|
||||
|---|---|
|
||||
| Build | `npm run build && npm run preview` (production build на `localhost:4173`) |
|
||||
| Difficulty | **Medium** — Easy скрывает поведение за reaction-задержкой; Hard не реализован (Phase 3) |
|
||||
| Mode | Quick Match → выбор личности → Medium |
|
||||
| Device | Минимум 1 desktop + 1 mobile session (mobile важно — touch zones там единственный input) |
|
||||
| Telemetry | Mock adapter логирует `trackEvent` в консоль — оставить открытой DevTools для пост-анализа |
|
||||
|
||||
---
|
||||
|
||||
## Per-match observation rubric
|
||||
|
||||
После каждого матча тестер заполняет строку:
|
||||
|
||||
| Поле | Что фиксировать | Источник |
|
||||
|---|---|---|
|
||||
| `match_index` | 1..20 | manual |
|
||||
| `setup_pattern` | Какие bumper-типы AI поставил, где (углы / центр / далеко) | визуально, AI половина |
|
||||
| `reaction_distance` | «early / normal / late» — насколько близко мяч долетает до AI-флипперов | субъективно |
|
||||
| `miss_rate` | «низкий / средний / высокий» — как часто AI пропускает свой удар | визуально |
|
||||
| `special_behaviour` | Любой характерный приём (двойной свинг, странный угол отскока, агрессивная атака центром) | free-text |
|
||||
| `final_score` | Player : AI | HUD post-match |
|
||||
| `duration_sec` | Длина матча | HUD timer / `match_end` telemetry |
|
||||
| `personality_guess` | Бэтти / Турбо / Хитрый Хо / Эхо | blind по завершению ВСЕХ 20 матчей |
|
||||
|
||||
---
|
||||
|
||||
## Expected tells (для оценщика; тестеру НЕ показывать до конца сессии)
|
||||
|
||||
| Личность | Tells |
|
||||
|---|---|
|
||||
| **Defensive (Бэтти)** | Setup: 2 slingshot в углах ворот + 1 турбо центр + 1 curve + 1 пусто. Поведение: реакция надёжная (`reliabilityMul: 1.1`, capped 1.0 = почти 100 %), чуть быстрее (`reactionMul: 0.9`). AI пропускает редко; матчи длиннее обычного. |
|
||||
| **Aggressive (Турбо)** | Setup: 2 турбо в центре (фарм) + 1 slingshot угол + 1 curve + 1 standard. Поведение: реагирует с большего расстояния (`triggerDistBonus: +80px`), чаще промахивается (`reliabilityMul: 0.85`). Высокий счёт у обеих сторон, быстрые матчи. |
|
||||
| **Trickster (Хитрый Хо)** | Setup: 4 curve bumper'а (лабиринт) + 1 турбо центр. Поведение: 15 % случайный спайк jitter (×1.3) — реакция «дёргается». Непредсказуемый счёт; необычные траектории мяча. |
|
||||
| **Ghost (Эхо)** | Setup: balanced (2 slingshot + 1 турбо + 1 curve + 1 standard). Поведение: 15 % «echo double-swing» — обе стороны активируются одновременно, даже если мяч идёт только в одну. Медианный счёт; характерный двойной flip. |
|
||||
|
||||
---
|
||||
|
||||
## Процедура
|
||||
|
||||
1. **Randomize order.** Использовать random.org pick из `[defensive, aggressive, trickster, ghost]`,
|
||||
5 раз для каждой → 20 матчей. **Не группировать по личности** — рассыпать.
|
||||
Пример последовательности: `[T, D, G, A, T, A, D, G, T, A, D, G, A, T, D, G, A, D, G, T]`.
|
||||
|
||||
2. **Играть в выбранном порядке.** После каждого матча — заполнить строку рубрики.
|
||||
НЕ смотреть expected tells между матчами.
|
||||
|
||||
3. **Blind attribution.** По завершении всех 20 матчей — для каждой строки заполнить
|
||||
`personality_guess` без обращения к памяти о выборе перед матчем.
|
||||
|
||||
4. **Score.** Сравнить `personality_guess` с фактическим выбором. Подсчитать accuracy.
|
||||
|
||||
5. **Subjective rating.** Тестер ставит общую оценку «AI feels different» по 5-балльной
|
||||
шкале (≥ 4 = pass).
|
||||
|
||||
6. **Report.** Заполнить шаблон ниже, приложить к Phase 2 sign-off.
|
||||
|
||||
---
|
||||
|
||||
## Failure modes & follow-ups
|
||||
|
||||
| Результат | Что делать |
|
||||
|---|---|
|
||||
| Accuracy < 50 % | Модификаторы слишком слабые. Удвоить `triggerDistBonus`, опустить `reliabilityMul` ниже 0.7. |
|
||||
| Accuracy 50-74 % | Две личности путаются между собой. Развести их setup'ом сильнее (например, поменять Defensive curve → second slingshot для большего «защитного» паттерна). |
|
||||
| Accuracy ≥ 75 %, subjective < 4 | Поведение различимо, но не интересно. Это не блокер Phase 2, но завести задачу на «character polish» в Phase 4. |
|
||||
| Тестер жалуется «AI слишком сложный/лёгкий на Medium» | Тюнить `reactionMs` в `src/config/defaults.ts` — не personality-specific. |
|
||||
|
||||
---
|
||||
|
||||
## Codex automation (опционально)
|
||||
|
||||
`codex exec` потенциально может прогнать матчи через headless Phaser
|
||||
и replay-log; но для Phase 2 sign-off **достаточно ручного playtest'а**.
|
||||
Маппинг рубрики в telemetry events:
|
||||
|
||||
| Поле рубрики | Telemetry source |
|
||||
|---|---|
|
||||
| `setup_pattern` (AI) | `MatchResult.aiSetup.slots` |
|
||||
| `reaction_distance` | derivable: ball trajectory + `goal_scored.ballOwnershipBeforeGoal` |
|
||||
| `miss_rate` | `1 − (AI flipper hit count / ball-passes-through-AI-zone count)` (нужен новый event `flipper_hit` — не в Phase 2 scope) |
|
||||
| `final_score` | `match_end.goalsScored / goalsAgainst` |
|
||||
| `duration_sec` | `match_end.durationSeconds` |
|
||||
|
||||
Автоматизация — backlog Phase 5+.
|
||||
|
||||
---
|
||||
|
||||
## Report template
|
||||
|
||||
```markdown
|
||||
# Playtest Report — Phase 2 AI Distinguishability
|
||||
|
||||
**Tester:** <имя / handle>
|
||||
**Date:** <YYYY-MM-DD>
|
||||
**Build:** HEAD <git-sha>
|
||||
**Devices:** desktop=<browser/os>, mobile=<browser/os>
|
||||
|
||||
## Match log
|
||||
| # | Personality (actual) | Setup observed | Reaction | Miss rate | Special | Score | Duration | Guess | Match? |
|
||||
|---|---|---|---|---|---|---|---|---|---|
|
||||
| 1 | trickster | 4 curve + turbo | normal | medium | hectic angles | 5:3 | 4m12s | trickster | ✅ |
|
||||
| 2 | ... | | | | | | | | |
|
||||
|
||||
## Results
|
||||
- Accuracy: __ / 20 = __ %
|
||||
- Subjective rating: __ / 5
|
||||
- Per-personality breakdown:
|
||||
- Defensive: __ / 5
|
||||
- Aggressive: __ / 5
|
||||
- Trickster: __ / 5
|
||||
- Ghost: __ / 5
|
||||
|
||||
## Free-text observations
|
||||
<распознанные tells, неожиданные моменты, баги>
|
||||
|
||||
## Verdict
|
||||
- [ ] Phase 2 AI DoD PASS (≥75% accuracy + ≥4/5 subjective)
|
||||
- [ ] Phase 2 AI DoD FAIL — see follow-ups
|
||||
```
|
||||
Reference in New Issue
Block a user