69df2f8190
chore(quantik-game): полировка по финальному ревью + security-review
Финальное ревью: READY TO MERGE (0 блокеров). Security: SECURE (0 critical).
Применены дешёвые фиксы из ревью:
- validateSpec: блок game{} санитизируется ПОИМЁННО (chapter/subject →
sanitizeText, order/par_ms/unlockStars → проверка типа, неизвестные ключи
отбрасываются) — закрыт латентный хранимый XSS (раньше clean.game=spec.game).
- quantik.html: @media (prefers-reduced-motion) делает анимации мгновенными
(не выключает — иначе forwards-появление узлов оставило бы их скрытыми).
- progress-logic.js: фикс комментария isUnlocked (сумма звёзд по ВСЕМ уровням
с меньшим глобальным order, а не «той же главы»).
План: Ф6 (лидерборд/гонка) удалена (Amendment 1, решение пользователя);
финальные гейты отмечены; deferred-бэклог зафиксирован.
Затронутые тесты 45/45; lint:routes 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
108 lines
9.5 KiB
Markdown
108 lines
9.5 KiB
Markdown
# Feature: Квантик — Законы Мира (образовательная 2D-игра)
|
||
|
||
**Branch:** `feature/quantik-game`
|
||
**Base branch:** `feature/sim-builder` (движок P1–P3 и фазы sim-builder ещё не в master)
|
||
**Created:** 2026-06-13
|
||
**Status:** 🟡 In Progress
|
||
**Strategy:** Incremental
|
||
**Mode:** Automated
|
||
**Execution:** Orchestrator
|
||
|
||
## Summary
|
||
2D физика-головоломка-платформер поверх движка **SimForge** (`_sim_engine.js`). Герой —
|
||
**Квантик** (существующий питомец `PetSprite`): в уровне он светящаяся точка с glow и
|
||
кометной трассой (P2), на карте/в диалогах — SVG-блоб `PetSprite.render`. Игрок не рулит
|
||
героем напрямую, а **чинит «закон мира»**: задаёт скорость/угол/гравитацию (физ-уровни на
|
||
`SimPhysics`), собирает `f(x)` для движения по кривой (граф-уровни на `plot`/`SimExpr`),
|
||
открывает «ворота» уравниванием реакций/дробей. **Условие победы — булев блок `goal`
|
||
(SimExpr) в спеке** — это «атом», переиспользуемый всеми типами уровней.
|
||
|
||
Уровень = спека SimForge + блок `game/goal` → авторится в sim-builder, хранится в
|
||
`custom_sims`, открывается тем же конвейером, что и обычные симуляции. Всё новое —
|
||
**аддитивно и безопасно** (без `eval`/`Function`; нет блока `goal` → движок ведёт себя
|
||
как раньше).
|
||
|
||
Мета-слой: карта-созвездие, XP/скины Квантика, разблокировка по звёздам, класс-лидерборд
|
||
через classroom SSE. Квантовые способности: суперпозиция, коллапс/пауза, туннелирование
|
||
(энергия из быстрого SR-повторения флешкарт).
|
||
|
||
**MVP играбелен после Фазы 2.**
|
||
|
||
## Build & Test Commands
|
||
- **Build:** нет (vanilla JS, без бандлера; статика через Express)
|
||
- **Test:** `npm test` в `backend/` (`node --test tests/*.test.js`)
|
||
- **Lint:** `npm run lint:routes` в `backend/`
|
||
- ⚠️ После роутов/миграций: `npm run migrate` (живая БД `backend/data/learnspace.db`) + рестарт сервера.
|
||
- ⚠️ baseline: 3 pre-existing fail (`auth.test.js` — bcrypt/JWT в тест-окружении) + 5 page-тестов (`jsdom` не установлен). Хук толерантен.
|
||
|
||
## Project Constraints (соблюдают ВСЕ агенты)
|
||
- ⛔ Никаких эмодзи в коде — только inline SVG `.ic`.
|
||
- ⛔ Никакого `eval`/`new Function`. Выражения — ТОЛЬКО через `SimExpr` (безопасный парсер).
|
||
- Поиск по коду: `ast-index` (символы/usages/callers) + `vex` (semantic). НЕ Grep tool.
|
||
- БД — встроенный `node:sqlite` (`DatabaseSync`), НЕ better-sqlite3.
|
||
- Frontend — vanilla JS, `window.LS.*` (js/api.js), без бандлера.
|
||
- Стейджить файлы **поимённо** (НЕ `git add -A` — в репо много мусорных untracked + чужой WIP sim-builder).
|
||
- Аддитивность: новые блоки/типы в спеке не ломают существующие симуляции и каталог.
|
||
- Ассеты: база — in-house (PetSprite + canvas/SVG + встроенный FLUX `/api/imggen`).
|
||
Разрешены внешние **CC0/открытые** ассеты (звук/арт) с указанием источника/лицензии.
|
||
|
||
## Reuse Map (что переиспользуем)
|
||
- `frontend/js/labs/_sim_engine.js` — рантайм (SimPhysics, plot, glow/trails, zoom/pan, drag).
|
||
- `frontend/js/labs/_sim_expr.js` — `SimExpr.compile/evalSafe` для `goal`/`stars`.
|
||
- `frontend/js/pet-sprite.js` — `PetSprite.render(...)` Квантик + палитры → скины/нарратор.
|
||
- `custom_sims` + `customSimController.validateSpec` — хранение уровней + серверный гейт.
|
||
- `sim-builder.html`/`sim-builder.js` — авторинг уровней (Фаза 5).
|
||
- Флешкарты Tier-1 SR (мигр.074) — энергия туннелирования (Фаза 4).
|
||
- classroom SSE + мост `sim_state`/`apply_sim_state` (Ф7 sim-builder) — живая гонка (Фаза 6).
|
||
- Паттерн раздачи классу + `pushNotif` + `lab_sim_links` (Ф6 sim-builder).
|
||
|
||
## Phases
|
||
|
||
- [x] Phase 0: Слой целей в движке (goal/HUD/result) [domain: frontend] → [subplan](./phase-0-objective-layer.md)
|
||
- [x] Phase 1: Оболочка игры + 1 физ-уровень + прогресс [domain: fullstack] → [subplan](./phase-1-shell-first-level.md)
|
||
- [x] Phase 2: Карта-созвездие + мир физ-уровней + XP/скины [domain: fullstack] → [subplan](./phase-2-map-world-xp.md)
|
||
- [x] Phase 3: Граф-уровни (движение по f(x)) + зоны-препятствия [domain: fullstack] → [subplan](./phase-3-graph-levels.md)
|
||
- [x] Phase 4: Квантовые способности + SR-комнаты [domain: fullstack] → [subplan](./phase-4-quantum-abilities-sr.md)
|
||
- [x] Phase 5: Авторинг уровней в sim-builder + раздача классу [domain: fullstack] → [subplan](./phase-5-authoring-sharing.md)
|
||
- ~~Phase 6: Класс-лидерборд / живая гонка (classroom SSE)~~ — **REMOVED** (см. Amendment 1) → [subplan](./phase-6-leaderboard-live.md)
|
||
|
||
## Phase Progress Log
|
||
|
||
| Phase | Domain | Status | Review | Build | Committed |
|
||
|-------|--------|--------|--------|-------|-----------|
|
||
| Phase 0: Слой целей в движке | frontend | ✅ Done | ✅ | ✅ | ✅ |
|
||
| Phase 1: Оболочка + 1 уровень + прогресс | fullstack | ✅ Done | ✅ | ✅ | ✅ |
|
||
| Phase 2: Карта + мир + XP/скины | fullstack | ✅ Done | ✅ (1 🟡 fixed) | ✅ | ✅ |
|
||
| Phase 3: Граф-уровни + зоны | fullstack | ✅ Done | ✅ | ✅ | ✅ |
|
||
| Phase 4: Квантовые способности + SR | fullstack | ✅ Done | ✅ | ✅ | ✅ |
|
||
| Phase 5: Авторинг + раздача | fullstack | ✅ Done | ✅ | ✅ | ✅ |
|
||
| ~~Phase 6: Лидерборд / живая гонка~~ | fullstack | ❌ Removed (Amendment 1) | — | — | — |
|
||
|
||
## MVP boundary
|
||
После **Phase 2** игра играбельна и отгружаема: один полный мир физ-уровней с картой,
|
||
прогрессом, XP и скинами. Фазы 3–6 — расширение (новые типы уровней, способности,
|
||
авторинг, мультиплеер).
|
||
|
||
## Amendment Log
|
||
|
||
### Amendment 1 — 2026-06-14
|
||
**Type:** Removed phase
|
||
**What changed:** Phase 6 (Класс-лидерборд / живая гонка через classroom SSE) убрана из объёма по решению пользователя.
|
||
**Why:** Пользователь решил не реализовывать соревновательный слой; переходим к полировке и финальному ревью после Ф5.
|
||
**Impact on existing phases:** Нет. Фазы 0–5 самодостаточны и отгружаемы. `game_progress.level_id` (TEXT) уже готов под будущий лидерборд, если фичу вернут. Subplan `phase-6-leaderboard-live.md` сохранён как архив с пометкой REMOVED.
|
||
|
||
## Final Review
|
||
- [x] Comprehensive code review (final-reviewer) — ✅ READY TO MERGE, 0 блокеров (2026-06-14)
|
||
- [x] Security review (новые API/ввод) — ✅ SECURE, 0 critical (2026-06-14)
|
||
- [x] Polish-фиксы по ревью применены: game-блок санитизируется (был латентный XSS), prefers-reduced-motion guard, фикс комментария isUnlocked. Тесты 45/45 затронутых, lint 0.
|
||
- [x] `npm test` без новых регрессий (8 = baseline: 3 auth + 5 jsdom)
|
||
- [x] `npm run lint:routes` baseline 0
|
||
- [ ] Merged to `feature/sim-builder` (ожидает одобрения пользователя)
|
||
|
||
### Deferred / Backlog (не блокеры — из финального ревью)
|
||
- `QuantikLevels.ensureCustom` — N+1 `customSimGet` на загрузку /quantik; при росте числа авторённых уровней заменить на bulk-эндпоинт «список game-спек».
|
||
- Уровни 3/5/6 (отскок/орбита/манёвр): `fail` — только таймаут, «честная» механика не форсится. Точечно ужесточить `fail`-предикаты (контент-тюнинг).
|
||
- `graph-exp-11` капстоун узковат (~36–42/625) — при жалобах на сложность чуть расширить gate.
|
||
- Три похожих `starSvg`/`_starIcon` в разных модулях — консолидация не стоит связывания движка с игрой (оставлено).
|
||
- Клиентские очки прогресса фальсифицируемы (ожидаемо для single-player). ⚠️ Если когда-нибудь вернут Ф6-лидерборд — валидировать на сервере (replay/подписанные токены).
|