Files
pinball-duel/playtest-protocol.md
aevgarik a1b0ae9e96 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>
2026-05-24 04:10:04 +03:00

133 lines
7.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.
# 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
```