docs(assistant): дизайн-документ «Квантик-ассистент» (правиловый, без кода)
План сквозного ассистента поверх существующего питомца: контекстные подсказки, проактивные напоминания из реальных данных, поздравления, онбординг-тур. Архитектура (assistant.js через sidebar.js, правиловый движок, анти-назойливость), каталог правил, фазы Ф0–Ф4, открытые вопросы. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
# Квантик-ассистент — дизайн-документ
|
||||
|
||||
> Статус: **дизайн** (код не пишем). Движок подсказок: **правиловый/эвристический** (без LLM).
|
||||
> Цель: превратить существующего питомца «Квантик» в сквозного ассистента, который
|
||||
> помогает работать в системе, подсказывает и проактивно напоминает.
|
||||
|
||||
---
|
||||
|
||||
## 1. Цель и принципы
|
||||
|
||||
Маленький плавающий компаньон (тот же Квантик) присутствует на всех страницах и:
|
||||
1. **Подсказывает по контексту страницы** — что тут можно, неочевидные фичи.
|
||||
2. **Проактивно напоминает** — из реальных данных (домашка, карточки, урок, серия, квесты).
|
||||
3. **Радуется успехам** — левелап, ачивка, серия, тест на 100%.
|
||||
4. **Ведёт новичка** — короткий тур по разделам при первом входе.
|
||||
5. **Отвечает «как сделать X»** — поиск по справке/FAQ (LLM — за рамками, точка расширения).
|
||||
|
||||
Принципы:
|
||||
- **Единая личность** — имя/цвет/настроение из `/api/pet`, лицо — `pet-sprite.js`. Никакого второго персонажа.
|
||||
- **Не назойливый** — один пузырь за раз, дневной лимит, кулдауны, «понял / не показывать», тихий режим, выключаемость.
|
||||
- **Детерминированный** — правила и шаблоны на реальных данных, предсказуемо и офлайн.
|
||||
- **Без эмоджи в коде** — только inline SVG `.ic` (правило проекта). Тексты подсказок — тоже без эмоджи.
|
||||
- **Лёгкий** — не грузит страницы, ленивая инициализация, минимум сетевых запросов.
|
||||
|
||||
Не-цели (сейчас): свободный диалог/LLM; голос; геймификация поверх (ачивки за общение — позже, Ф4).
|
||||
|
||||
---
|
||||
|
||||
## 2. Что уже есть (фундамент)
|
||||
|
||||
- **Питомец «Квантик»**: 8 уровней по XP, настроение (`_mood` от серии/дней без входа), аксессуары
|
||||
(`_accessories`: hat/glasses/crown/star), монеты, поглаживание/кормёжка, **дневные квесты** (`_quests`),
|
||||
недельный XP, лента активности, прогноз настроения (`_moodForecast`), цвета, магазин фонов.
|
||||
- **`GET /api/pet`** (`petController.getPet`) уже отдаёт: `petName, petLevel, petColor, mood,
|
||||
daysSinceLogin, accessories, xp, level, streakCurrent, streakBest, coins, quests[], moodForecast,
|
||||
recentActivity[], weeklyXP[], xpForNextLevel`. → почти весь контекст для подсказок берётся отсюда.
|
||||
- **`pet-sprite.js`** — `window.PetSprite.render(level, mood, accessories, colorKey, streak)` → SVG.
|
||||
Переиспользуем как «лицо» ассистента (мини-версия в пузыре).
|
||||
- Показ: страница `/pet` + виджет на `/dashboard`.
|
||||
- **Онбординга/туров/подсказок в системе нет** — строим с нуля, конфликтов не будет.
|
||||
- **Точка инъекции:** глобальные скрипты подключаются на каждой app-странице
|
||||
(`api.js`, `sidebar.js`, `search.js`, `notifications.js`, `mobile.js`). `sidebar.js` есть везде →
|
||||
он догружает `assistant.js` одной строкой, HTML страниц не трогаем.
|
||||
- Питомец — фича за `requireFeature('pet')` (см. `server.js`).
|
||||
|
||||
---
|
||||
|
||||
## 3. Архитектура
|
||||
|
||||
```
|
||||
sidebar.js (на каждой странице)
|
||||
└─ догружает /js/assistant.js (если фича включена и не отключено юзером)
|
||||
├─ Assistant.boot()
|
||||
│ ├─ собирает ctx (page + данные)
|
||||
│ ├─ прогоняет реестр правил → выбирает 1 подсказку по приоритету/кулдауну
|
||||
│ └─ рисует компаньона + пузырь (лицо = PetSprite.render)
|
||||
├─ assistant-rules.js — реестр правил (данные, не логика)
|
||||
└─ состояние/капы — localStorage (+ опц. сервер в Ф1+)
|
||||
```
|
||||
|
||||
### 3.1. Компоненты (файлы — создаём в фазах, не сейчас)
|
||||
- `frontend/js/assistant.js` — движок + UI (стили инжектит сам, как `board-clip.js`).
|
||||
- `frontend/js/assistant-rules.js` — каталог правил (отдельно, чтобы правила правились без движка).
|
||||
- `js/sidebar.js` — +строка ленивой загрузки ассистента.
|
||||
- `frontend/profile.html` — настройки (вкл/выкл, частота, сброс подсказок).
|
||||
- (Ф1) `backend/src/routes/assistant.js` + `controllers/assistantController.js` — `GET /api/assistant/context`.
|
||||
- (Ф1, опц.) миграция: серверная отметка «видел подсказку» для кросс-девайс (иначе только localStorage).
|
||||
|
||||
### 3.2. Движок: контекст и правила
|
||||
|
||||
**Контекст `ctx`** (собирается при загрузке страницы):
|
||||
```js
|
||||
{
|
||||
path, page, // page — нормализованный id ('textbook','classroom','exam-prep',...)
|
||||
role, // student | teacher | admin
|
||||
isFirstVisit, // нет ни одной отметки о показе
|
||||
pet, // кэш /api/pet (мин. TTL, чтобы не дёргать на каждой странице)
|
||||
data: { // лениво/из /api/assistant/context (Ф1)
|
||||
homeworkDue: [{title, deadline, status}],
|
||||
dueCards: <int>, // карточек к повторению
|
||||
activeLesson: {courseId, title, pct} | null,
|
||||
weakTopics: [...],
|
||||
quests: [...] // из /api/pet
|
||||
},
|
||||
events: [...], // свежие левелап/ачивка (детект по дельте)
|
||||
now
|
||||
}
|
||||
```
|
||||
|
||||
**Форма правила:**
|
||||
```js
|
||||
{
|
||||
id: 'textbook-clip',
|
||||
scope: 'page' | 'proactive' | 'celebration',
|
||||
when: (ctx) => boolean, // условие показа
|
||||
priority: 50, // больше = важнее (celebration > proactive > page)
|
||||
cooldownDays: 7, // не чаще раза в N дней
|
||||
maxShows: 3, // пожизненный лимит показов
|
||||
suppressOn: ['exam-run','board-draw'], // не мешать в фокусных режимах
|
||||
text: (ctx) => 'Можно вырезать кусок страницы в «Мои материалы».',
|
||||
action: (ctx) => ({ label: 'Показать', url: null, run: fn }) | null,
|
||||
petMood: 'happy' // настроение лица (опц.)
|
||||
}
|
||||
```
|
||||
|
||||
**Алгоритм выбора:** отфильтровать `when && !suppressed && подходит по кулдауну/лимиту`,
|
||||
отсортировать по `scope`-весу + `priority`, взять **одно**. Показ — по триггеру (см. 3.3).
|
||||
|
||||
### 3.3. Анти-назойливость (критично)
|
||||
- **1 пузырь** на экране за раз.
|
||||
- Триггеры показа: page-подсказка — через 6–8 с на странице **или** по наведению на компаньона;
|
||||
proactive — раз в сессию на категорию; celebration — сразу по событию.
|
||||
- **Дневной лимит** проактивных подсказок (по умолчанию 3).
|
||||
- **Кулдаун** на правило + **пожизненный maxShows**.
|
||||
- Кнопки в пузыре: «Понятно» (скрыть), «Не показывать» (навсегда для этого правила).
|
||||
- **Тихий режим** и глобальный выключатель в профиле.
|
||||
- **Не мешать в фокусе:** скрывать на странице запущенного теста, во время рисования на доске,
|
||||
на онлайн-уроке (`suppressOn`).
|
||||
- `prefers-reduced-motion` — без анимаций/конфетти.
|
||||
|
||||
### 3.4. Хранение состояния
|
||||
- localStorage: `asst_off` (вкл/выкл), `asst_freq`, `asst_seen:{ruleId}={count,lastTs}`,
|
||||
`asst_mute_until`, `asst_pet_level`/`asst_ach_seen` (для детекта событий).
|
||||
- (Опц., Ф1) сервер: таблица `assistant_seen(user_id, rule_id, count, last_at)` для кросс-девайс —
|
||||
иначе подсказки повторятся на другом устройстве. Решить в Открытых вопросах.
|
||||
|
||||
---
|
||||
|
||||
## 4. Каталог правил (черновик)
|
||||
|
||||
### 4.1. Контекстные (scope: page) — «что тут можно»
|
||||
| id | страница | текст (суть) | действие |
|
||||
|----|----------|--------------|----------|
|
||||
| textbook-clip | /textbook | Вырежи кусок страницы картинкой в «Мои материалы» | подсветить кнопку «Вырезать область» |
|
||||
| textbook-deeplink | /textbook | Можно делиться ссылкой прямо на параграф | — |
|
||||
| board-tools | /classroom, /board | Лассо, фигуры, формулы KaTeX, линейка — попробуй панель | — |
|
||||
| exam-modes | /exam-prep | Режимы: экзамен / тренировка / случайный | — |
|
||||
| lab-sims | /lab | Симуляции запускаются прямо тут, без установки | — |
|
||||
| flashcards-katex | /flashcards | Формулы вводятся через KaTeX-палитру | — |
|
||||
| materials-folders | /my-materials | Раскладывай материалы по папкам и аннотируй фото | — |
|
||||
| dashboard-widgets | /dashboard | Виджеты дашборда можно настроить под себя | — |
|
||||
|
||||
### 4.2. Проактивные (scope: proactive) — из реальных данных
|
||||
| id | условие | текст | действие |
|
||||
|----|---------|-------|----------|
|
||||
| hw-due-soon | есть домашка с дедлайном < 24ч и не сдана | Домашка «X» — дедлайн скоро | → /homework |
|
||||
| hw-overdue | есть просроченная несданная | Просрочена домашка «X» | → /homework |
|
||||
| cards-due | dueCards > 0 | К повторению N карточек | → /flashcards |
|
||||
| lesson-continue | есть незаконченный урок | Продолжи «X» (N%) | → /course?id=... |
|
||||
| streak-risk | streakCurrent ≥ 1 и сегодня нет активности (вечер) | Серия N дней под угрозой — закрепи | → /exam-prep |
|
||||
| quest-nudge | есть незакрытый дневной квест | Добей квест: «X» | → соответствующий раздел |
|
||||
| weak-topic | низкий средний по теме | Подтяни тему «X» | → тест/учебник по теме |
|
||||
|
||||
### 4.3. Поздравления (scope: celebration) — по событию
|
||||
| id | триггер | реакция |
|
||||
|----|---------|---------|
|
||||
| levelup | pet.level вырос с прошлой проверки | Квантик ecstatic + «Уровень N!» |
|
||||
| achievement | новая ачивка | поздравление + название |
|
||||
| streak-milestone | серия достигла 3/7/14/30 | поздравление + аксессуар-намёк |
|
||||
| test-perfect | тест на 100% (из recentActivity) | поздравление |
|
||||
|
||||
> Эмоджи в существующих квестах (`⭐📝🔥` в `petController._quests`) заменить на inline SVG `.ic`
|
||||
> при интеграции — для соответствия правилу проекта.
|
||||
|
||||
---
|
||||
|
||||
## 5. Источники данных (всё уже в системе)
|
||||
|
||||
| Нужно | Откуда |
|
||||
|-------|--------|
|
||||
| настроение/серия/квесты/прогноз/уровень | `GET /api/pet` |
|
||||
| домашка + дедлайны | assignments (как на дашборде: `asgn-row urgent/over`) |
|
||||
| карточки к повторению | flashcards SRS (`LS.fc*`) |
|
||||
| незаконченный урок | `/api/courses` (`doneCount/lessonCount`) / `lesson_progress` |
|
||||
| слабые темы | analytics по `test_sessions` |
|
||||
| левелап/ачивки | дельта `/api/pet` (level, xp) + список ачивок |
|
||||
|
||||
**Рекомендация (Ф1):** один эндпоинт `GET /api/assistant/context` собирает компактный бандл
|
||||
(`homeworkDue, dueCards, activeLesson, weakTopics`), чтобы не дёргать 4 API с клиента.
|
||||
|
||||
---
|
||||
|
||||
## 6. UI / UX
|
||||
|
||||
- **Компаньон:** мини-Квантик (≈48–56px) в правом-нижнем углу (на мобиле — выше `mob-bar`, не перекрывая).
|
||||
Лёгкое «дыхание»; при наличии подсказки — мягкий пульс/бейдж.
|
||||
- **Пузырь:** speech-bubble над компаньоном: текст (1–2 строки) + опц. кнопка действия +
|
||||
«Понятно» + «Не показывать». Закрытие: кнопка, клик вне, Esc.
|
||||
- **Состояния:** idle / has-hint / bubble-open / celebrating (конфетти + ecstatic) / hidden.
|
||||
- **Стиль:** дизайн-система `ls.css` (переменные `--violet/--text/--text-3`), inline SVG `.ic`,
|
||||
тёмная тема, без эмоджи. Тон: дружелюбный, на «ты», кратко.
|
||||
- **A11y:** `aria-live="polite"` на пузыре, фокус/Esc, уважение `prefers-reduced-motion`.
|
||||
- **Перетаскивание/сворачивание** компаньона (запоминать позицию) — опц., Ф2.
|
||||
|
||||
---
|
||||
|
||||
## 7. Настройки и приватность
|
||||
- Профиль: переключатель «Ассистент Квантик», частота (обычная/низкая), «Сбросить подсказки».
|
||||
- Фича-флаг: reuse `pet` **или** новый `assistant` (решить — см. Открытые вопросы).
|
||||
- Роли: ученики — основной сценарий; учителям — отдельный набор подсказок (Ф4); по умолчанию для
|
||||
admin, возможно, выключен.
|
||||
- Никакой персональной телеметрии наружу; состояние — локально (+опц. своя таблица).
|
||||
|
||||
---
|
||||
|
||||
## 8. Фазы
|
||||
|
||||
- **Ф0 — каркас:** `assistant.js` + `assistant-rules.js`, плавающий Квантик (лицо из `pet-sprite`),
|
||||
пузырь, dismissal/кулдауны/лимиты, вкл/выкл, инъекция через `sidebar.js`, 5–6 правил §4.1.
|
||||
- **Ф1 — проактив:** `GET /api/assistant/context` + правила §4.2 + поздравления §4.3 (детект событий).
|
||||
- **Ф2 — онбординг-тур** новичка по разделам + все контекстные подсказки + «не показывать снова» +
|
||||
(опц.) перетаскивание/сворачивание.
|
||||
- **Ф3 — «Спроси Квантика»:** окно с поиском по справке/FAQ (использует `search.js`).
|
||||
Точка расширения под LLM — **за рамками этого плана**.
|
||||
- **Ф4 — персонализация:** частота/тон, режим для учителей, ачивки за взаимодействие, на страницах
|
||||
учебника (серверный inject) тоже.
|
||||
|
||||
---
|
||||
|
||||
## 9. Затрагиваемые файлы (при будущей реализации)
|
||||
- + `frontend/js/assistant.js`, `frontend/js/assistant-rules.js`
|
||||
- ~ `js/sidebar.js` (одна строка-загрузчик)
|
||||
- ~ `frontend/profile.html` (настройки)
|
||||
- (Ф1) + `backend/src/routes/assistant.js`, `backend/src/controllers/assistantController.js`,
|
||||
mount в `server.js` (+ возможный фича-флаг `assistant`)
|
||||
- (Ф1, опц.) + миграция `assistant_seen`
|
||||
- ~ `petController._quests` — заменить эмоджи на `.ic` при интеграции
|
||||
|
||||
---
|
||||
|
||||
## 10. Открытые вопросы (обсудить перед Ф0)
|
||||
1. **Фича-флаг:** переиспользуем `pet` или заводим отдельный `assistant`? (ассистент шире питомца).
|
||||
2. **Кому по умолчанию вкл:** всем ученикам? учителям? admin — выкл?
|
||||
3. **Кросс-девайс «видел»:** localStorage достаточно, или нужна серверная таблица `assistant_seen`?
|
||||
4. **Учебник (серверный рендер):** включать ассистента и там (через inject) сразу или в Ф4?
|
||||
5. **Тон/частота по умолчанию:** насколько активно напоминать (консервативно vs заметно)?
|
||||
6. **«Спроси Квантика» (Ф3):** только справка/FAQ, или сразу закладываем место под локальную модель?
|
||||
|
||||
---
|
||||
|
||||
## 11. Риски
|
||||
- **Назойливость** — главный риск; смягчается лимитами/кулдаунами/тихим режимом (§3.3).
|
||||
- **Перекрытие UI** (особенно мобайл, существующие FAB вроде «Вырезать область», `flashcard-fab.js`) —
|
||||
согласовать z-index и позиции, не накладываться.
|
||||
- **Лишние запросы** — кэш `/api/pet`, один бандл-эндпоинт, ленивая инициализация.
|
||||
- **Рассинхрон личности** — всегда брать имя/цвет/настроение из одного источника (`/api/pet`).
|
||||
Reference in New Issue
Block a user