feat(quantik-game): фаза 0 — слой целей в движке (goal/HUD/result)
Декларативный блок goal в спеке SimForge (булево SimExpr-условие победы),
вычисляемый каждый кадр: фиксация результата (победа/время/попытки/звёзды),
callback onGoal, HUD-оверлей (цель/звёзды/подсказка/баннер, inline SVG).
API инстанса: onGoal/getResult/resetResult. Серверный validateSpec
пропускает goal/game (длина выражений + escape текста, без исполнения).
Аддитивно: спека без goal ведёт себя как раньше. Смоук 40/40; npm test
238 pass/8 baseline; lint:routes 0. План фичи (7 фаз) + CONTEXT.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
LabMeasure (_measure.js): SVG-оверлей поверх сцены с pointer-events:none
(симуляция остаётся интерактивной), перетаскиваемые ручки. Линейка — длина
px + ≈ метры (PX_PER_M) + угол; угломер — угол при вершине с дугой.
Кнопка-тумблер в топбаре лаборатории. Самодостаточно, симуляции не трогает.
Этим Фаза 2 закрыта.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Поверх getState/applyState: в обычном режиме параметры активной симуляции
персистятся в localStorage (lab-sim-state-v1, дедуп, кап 8КБ, flush на pagehide)
и восстанавливаются при открытии. В embed/онлайн-уроке персист выключен —
состоянием управляет учитель. applyState обёрнут в try/catch (старые формы не ломают).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Удалён _util.js (SimUtil): 0 использований во всех симуляциях (проверено),
грузился впустую.
- LabPalette (_palette.js): единый источник цветов canvas + PX_PER_M вместо
хардкода в каждом файле; задел под светлую тему.
- SimBase (_simbase.js): опциональная база жизненного цикла (DPR-fit + RAF
play/pause/reset/destroy). Существующие симуляции не трогаются; «дробовик»
остаётся fallback. Адаптация — постепенно, по мере правок (нет фронт-тестов).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Превращает песочницы в учебные инструменты: задание → ответ числом с допуском →
проверка/подсказка/прогресс (по образцу race.js, но переиспользуемо).
- _tasks.js: LabTasks (панель, прогресс-точки, проверка с tol, KaTeX в условии).
- Интеграция в loadTheory (одна точка): панель «Задания» дописывается в теорию,
бейдж на кнопке теории когда задания есть.
- Данные на 5 симуляций: quadratic, trigcircle, normaldist, projectile, pendulum.
Проверка на клиенте (учебные, не оценочные). XP — отдельным инкрементом.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
План улучшения симуляций — plans/simulations-improvement/README.md.
- LabFX: reduced-motion/эконом-режим (prefers-reduced-motion + тумблер
localStorage labfx-economy). Тряска отключается, частицы ×0.25 — доступность
и экономия на слабых устройствах сразу для всех ~50 симуляций. Кнопка-тумблер
в lab.html рядом со звуком.
- lesson-editor: блок «Симуляция» — выпадающий список из /api/lab/sims
(сгруппирован по предметам) вместо сырого ввода simId; неизвестный id не
теряется, помечается «(не найдена)». Закрывает хрупкую вставку в урок.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- server: requireFeature('imggen') на /api/imggen (глобальный гейт).
- imggenController: enforcement через isFeatureEnabledForUser в status()/generate()
— учитывает глобальный флаг + оверлей класса + free_student (403 если выкл.).
- admin «games/features» + free-student: тумблер «Генерация картинок (ИИ)».
- classes.html: переключатель модуля imggen в настройках класса (per-class).
Дефолт — ON (opt-in disable), как у остальных фич. Проверено на features-движке.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Главный выключатель в разделе «Генерация картинок» (флаг on в конфиге,
независим от наличия токена). Выключено → /api/imggen отдаёт 503
«временно выключена». Админ-тест работает и при выключенном тумблере
(generateImage проверяет только наличие конфига). Бейдж различает
«Включена / Выключена / Не настроена».
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Новый админ-раздел: Account ID / токен (маскируется) / модель Cloudflare,
лимиты (пауза, дневной лимит) из БД, статистика, кнопка теста генерации.
imggenController: лимиты и модель теперь из конфига, поддержка JSON и
бинарного ответа CF, переиспользуемые generateImage() и stats().
Бэкенд GET/PUT /api/admin/imggen + POST /api/admin/imggen/test (admin-only).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Производный профиль (без LLM): слабые предметы, трудные темы экзамена,
цель/дата, серия — из test_sessions/exam_attempts/exam_user_plan. Подмешивается
в системный промпт → персональные ответы; такие не кэшируются глобально.
Заметки: таблица assistant_memory + фоновый LLM-экстрактор (дросселирован),
дедуп + лимит 15. Панель ученика «Что я о тебе помню» (профиль + заметки,
удаление). Админ-тумблер. API GET/DELETE /assistant/memory (/:id под
authMiddleware, владелец проверяется в хендлере).
Заодно: сверка стабильного baseline route-auth 56→66 (долг от branch-merge,
хук не идёт на merge) — новых незащищённых маршрутов не добавлено.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Цвета 6→11 (розовый/оранжевый/бирюза/лайм/индиго). Узоры 5→8
(сердечки/звёздочки/клетка). Аксессуары 11→18 + новая зона «В лапах»
(бини, нимб, монокль, медаль, серёжки, палочка, шарик). Разблокировка за
учёбу: нимб (8 достижений), медаль (30 тестов). Фоны 7→11
(класс/лаборатория/зима/радуга) с градиентами и частицами. Новая вкладка
«Образы» — 4 готовых набора (Учёный/Волшебник/Чемпион/Милашка) применяют
аксессуары+узор+цвет одним кликом.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Аксессуары больше не навешиваются авто по уровню — теперь разблокируются
и НАДЕВАЮТСЯ по выбору (один на слот). Новые: шапочка выпускника, наушники,
бабочка (бесплатные — доступны даже при 0 XP). Сохранены цилиндр/корона/очки/
звезда с прежними порогами; дефолт повторяет старый вид (без сюрпризов).
Бэкенд: миграция pet_equipped, каталог ACCESSORY_CATALOG + /api/pet/equip
(валидация разблокировки и слотов). Рендер аксессуаров строго по equipped —
в обеих копиях (pet.html и pet-sprite.js для дашборда). UI гардероба на /pet.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Лимит ответа был 420 токенов — длинное решение обрывалось внутри $$…$$,
незакрытый блок показывался сырым LaTeX. Теперь лимит по режиму
(ответ 1200, проверка 900, подсказка 320), а рендер отбрасывает
незакрытый хвост $$ (ставит «…») вместо сырого кода.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Новый GET /admin/assistant/models: тянет список моделей провайдера с лимитами
(OpenAI-совместимый /models: context_length+max_completion_tokens+pricing;
нативный Google generativelanguage: inputTokenLimit/outputTokenLimit) и кэширует
лимиты текущей модели на провайдере. Карточка показывает лимиты у ВСЕХ провайдеров
(не только Kilo), для отсутствующих — фоновая авто-подгрузка. В форме — кнопка
«Загрузить модели провайдера» с выбором модели и её лимитами. Так Gemini и любые
новые модели получают лимиты автоматически.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Рендер ответа: display-формулы KaTeX прокручиваются по горизонтали
(overflow-x:auto), пузырь ассистента во всю ширину, панель шире (380px) —
длинные выражения больше не режутся по правому краю.
Админка: к моделям Kilo добавлены ctx/out (из /models); на карточке Kilo
показывается «контекст N · ответ до M токенов · бесплатно».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Баннер «провайдеры недоступны» висел из старой записи assistant_failover.
Теперь успешный тест активного провайдера и смена активного снимают флаг,
плюс кнопка «Снять» на баннере (PUT /assistant {dismissFailover}).
Тест провайдера: system-инструкция + 64 токена + fallback на reasoning →
sample не показывает «мысли вслух» reasoning-моделей.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Раскрывается кнопкой «+ Добавить провайдера» (и автоматически при «Изм.»),
сворачивается после сохранения/отмены. Окно компактнее в обычном режиме.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Админ-раздел переделан: провайдеры — карточки (активный подсвечен, бейджи
ключ/активен, кнопки Сделать активным/Тест/Изменить/Удалить, hover-подъём).
Форма с лейблами и пресетами. Для Kilo — выпадающий список проверенных бесплатных
моделей (Nemotron 550B / Owl Alpha / Nemotron Nano 30B / Laguna XS) и инлайн-
переключатель модели прямо на карточке. Бэкенд: пресет Kilo + kiloModels в /admin/assistant.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
callLLMFailover пишет состояние в app_settings.assistant_failover: какой провайдер
исчерпан и каким подхвачено (или «все недоступны»); при успехе активного флаг
снимается. Админ-раздел показывает баннер «Провайдер X недоступен — работаю на Y».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Конфиг стал списком провайдеров (assistant_providers) + активный (assistant_active).
llmConfig берёт активного; providersOrdered — активный первым, затем остальные с
ключом; callLLMFailover перебирает их при 429/сетевой ошибке (второй ключ подхватывает
при исчерпании квоты). Legacy мигрируется в список. Админ-раздел: список провайдеров
(радио-активный, Тест/Изменить/Удалить) + форма с пресетами. Эндпоинты
POST/DELETE /admin/assistant/provider(/:id), POST /admin/assistant/active.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Баг «не помнит»: на самом деле free-лимит Gemini (429). callLLM теперь
возвращает ошибку; при 429 показываем «много запросов, подожди минутку —
память не потеряется» и НЕ ломаем историю (убираем неудачный вопрос); при
сбое — «не получилось, попробуй позже». Раньше показывалось «не нашёл ответ».
- В окне «Спроси» — пояснение, сколько помнит Квантик (≈6 реплик, рабочая память).
- Окна красивее: шире, аватар Квантика в шапке, мягкая анимация.
- Управление помощником вынесено в отдельный раздел админки «Помощник Квантик»
(системный вкл/выкл + модель/ключ/тест/RAG/кнопки экзамена/статистика/качество);
из раздела «Игры» конфиг убран.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Идентичность: вопросы про модель/нейросеть/провайдера/системный промпт
отбиваются шаблонно (META_RE, без вызова LLM) + запрет в системном промпте.
- Кнопки «Подсказка»/«Спросить Квантика» на карточках экзамена скрыты по
умолчанию; включаются тумблером в админке (assistant_exam_buttons →
examButtons в /context → класс html.asst-exam-on открывает кнопки).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Источники: RAG возвращает sources (slug/§/ref), под ответом ссылка «по учебнику
X, §N» на параграф (миграция 064: section_ref в textbook_chunks; headless-индексатор
его заполняет). Статический индексатор теперь не затирает headless-данные.
- Режим-наставник: переключатель Ответ/Подсказка/Проверить решение в «Спроси»
(mode в ask + промпт); на карточке экзамена кнопка «Подсказка» (mode hint).
- Оценка ответов: лайк/дизлайк под ответом (assistant_feedback) + сводка в админке.
- Утренний бриф на дашборде: «занимался N из 5 дн + план на сегодня».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- RAG: индексатор scripts/index-textbooks.js → textbook_chunks (миграция 063);
ask() подмешивает релевантные куски учебников (LIKE-скоринг). Покрывает
учебники со статическим текстом; JS-рендеримые — через контекст страницы.
Админка: тумблер RAG + кнопка «Переиндексировать» + число фрагментов.
- Кэш ответов (assistant_cache, 7 дней, только «чистые» вопросы без контекста/
истории) + суточный счётчик (assistant_usage: ИИ/кэш/FAQ) в админке.
- Режим учителя: роль в /context, системный промпт для учителей (задания,
план урока, учительские инструменты), подсказки-чипы для учителей.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Ответы модели рендерятся как markdown + формулы KaTeX (ленивая загрузка),
модель просим оформлять формулы в LaTeX $...$.
- «Объясни это»: ask принимает context; кнопки «Объяснить выделенное» (запоминаем
выделение) и «Объяснить/Конспект параграфа» на учебнике.
- Репетитор на экзамене: кнопка «Спросить Квантика» на карточке задания →
Assistant.ask с условием/ответом/решением как контекстом.
- Быстрые действия: «Флешкарты из параграфа» → POST /api/assistant/flashcards
(модель → JSON, починка обрезанного) → колода через существующий API флешкарт.
- Экспорт Assistant.ask(q,context) / explainSelection().
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ask() умеет вызывать OpenAI-совместимую модель: топ-FAQ как контекст, краткий
ответ на русском (source:'model'), таймаут 12с, при ошибке/без ключа — мягкий
откат на FAQ. Конфиг через ENV (ASSISTANT_LLM_URL/KEY/MODEL): дефолт — Groq
(бесплатный ключ), поддержан и локальный Ollama без ключа. Фронт показывает
ответ модели сверху, FAQ и поиск по платформе — ниже. .env.example дополнен.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Отдельный фича-флаг 'assistant' (вместо reuse 'pet'): админ может включать/
выключать помощника в Управление → фичи, независимо от питомца. Дефолт ON.
- FAQ расширен (~50 -> ~60): профиль/пароль, колоды/массовый импорт/SRS,
прогресс по предмету, поиск, экзамен9, питомец, «без класса», «о чём спросить».
- В «Спроси Квантика» — чипы с примерами вопросов (что можно спросить).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Контент: контекстные подсказки на ВСЕ разделы (PAGE_HINTS), «Совет дня» (ротация),
FAQ расширен ~10 -> ~50 записей по всем фичам. «Спроси Квантика» теперь ищет и по
платформе (LS.globalSearch) рядом с FAQ. Умный проактив: weakSubject (слабый предмет
по тестам, /api/assistant/context) -> «потренируемся» и daily-plan (план на сегодня из
квестов и карточек к повторению).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Подсказка тура уезжала за край на нижних пунктах сайдбара (Питомец), а оверлей
ловил клики → «ничего не сделать». Теперь: scrollIntoView ДО замера позиции,
подсказка жёстко клампится в пределах экрана (меряем реальный размер), и клик
по затемнённому фону закрывает тур (escape-hatch вдобавок к Esc).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Компаньон стоял на left:18px, поверх профиля внизу сайдбара (230/62px).
Теперь сдвигается правее сайдбара (.app-layout ~ .asst-root: 248px, collapsed
80px), на мобиле — к левому краю (шторка). Плавный transition при сворачивании.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ф2: коачмарк-тур новичка по разделам (сайдбар + сам помощник), офер на
дашборде пока не пройден/не закрыт, повтор из приветствия и Assistant.tour().
activeLesson: контекст-эндпоинт отдаёт начатый незавершённый урок (как
«продолжить чтение»), добавлено проактивное правило «Продолжи …» → /course.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Плавающий помощник на всех страницах (через sidebar.js + inject в учебник):
контекстные подсказки по странице, проактивные напоминания из реальных данных
(домашка с дедлайном, карточки к повторению, серия под угрозой, квест дня),
поздравления (левелап/серия) и панель «Спроси Квантика» (поиск по FAQ + точка
расширения под локальную модель). Консервативно: дневной лимит, кулдауны,
«не показывать», выключатель в профиле. Лицо — pet-sprite, данные — /api/pet.
Бэкенд: миграция 062 (assistant_enabled + assistant_seen, cross-device «видел»),
GET /api/assistant/context, POST seen/dismiss/ask, PATCH settings — гейт фичи 'pet'.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>