Тренажёр-по-темам и практика брали FROM exam_tasks без фильтра по варианту — в пул
попадали год-пачки (variant=год≥2011) и variant=0, которые ДУБЛИРУЮТ выверенные
варианты-пробники (51 дубль чистый↔пачка, 20 через variant=0). Ученик мог получить
одну задачу дважды.
Добавлен фильтр variant BETWEEN MV_LO..MV_HI (тот же [101;1999], что у пикера) во все
7 запросов выборки/счёта задач: practiceRandom, practiceUnsolved, topicTasksUnsolved,
topicTasksAny, listTopicsWithCounts (счётчик подтем), weakBatchTasks, pickRandomByDifficulty
(×2). Хелперы MV_LO/MV_HI (для math9 без диапазона — всё, кроме variant=0).
Результат: практика ctmath = только варианты 101–117 (496 задач, 0 дублей между собой),
год-пачки (714 задач) остаются в БД для возможного будущего, но не показываются.
Обратимо, без удаления данных. Рантайм-проверка: 5 эндпоинтов практики/тем → 200.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Пробник ЦТ по математике 2021, Вариант 1. Формат: 32 задания (А1–А18 + В1–В14), А12/А16 —
с несколькими верными (тип open, ответ цифрами), В2/В3 множ.выбор, В1 на соответствие.
Источник: чистый PDF ЦТ 2021.pdf. ВСЕ 32 ответа решены и сверены с официальной таблицей
(стр.45, столбец Вариант 1) — полное совпадение, включая B9=324, B11=960, B13=460 (пары чисел),
B14=1375 (описанный четырёхугольник, r=60/7). Фигурные A7/A17/B1/B4 реконструированы; B5: в скане
∛(-7) → на деле ∛(-343)=-7 (иначе нецелый), ответ -98. Без авторских ссылок.
VARIANT_LABEL 117 -> 'ЦТ-2021'. DRY-RUN 32/32, self-check и структурный KaTeX — зелёные.
Запись в БД — пользователь: node backend/scripts/seed_ctmath_ct2021_v1.js --apply
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Пробник ЦТ по математике 2020, Вариант 1. ⚠️ Новый формат: 32 задания (А1–А20 + В1–В12),
В1 на соответствие, В2 множ.выбор. Машинерия параметризована N_TASKS=32. Источник: чистый
PDF ЦТ 2020.pdf. ВСЕ 32 ответа решены и сверены с официальной таблицей (стр.44, столбец
Вариант 1) — полное совпадение, включая A20=37√13/3, B5=-335, B8=-320, B9=160, B10=577,
B11=-16, B12=336 (сфера через 4 точки куба). Фигурные A9/A11 реконструированы; без авторских
ссылок (политика «все учебники наши»). VARIANT_LABEL 116 -> 'ЦТ-2020'.
DRY-RUN 32/32, self-check и структурный KaTeX — зелёные.
Запись в БД — пользователь: node backend/scripts/seed_ctmath_ct2020_v1.js --apply
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Политика «все учебники наши»: нигде не упоминаются сторонние авторы.
- Миграции (15 файлов): колонка author → 'LearnSpace'; из описаний убран оборот
«по учебнику <автор>:»; авторские фамилии вычищены из комментариев. Покрыты
Арефьева/Пирютко, Казаков, Латотин/Чеботаревский/Горбунова/Цыбулько, Исаченкова,
Жилко/Маркович/Сокольский, Герасимов/Лобанов.
- HTML: physics_9_ch5 («по канве учебника Исаченковой» → «по учебной программе»),
physics_11_hub (hdr-sub с авторами → описание курса), mocks-redesign (карточки-авторы → LearnSpace).
- Генераторы gen_phys9_ch.js/gen_phys11_stubs.js — шаблоны без авторов.
- НОВОЕ: update_textbook_authors.js — идемпотентный апдейтер ЖИВОЙ БД (миграции уже
применены): author→'LearnSpace' у всех 107 учебников + чистка описаний. DRY-RUN по умолч.
⚠️ Живую БД правит ПОЛЬЗОВАТЕЛЬ: node backend/scripts/update_textbook_authors.js --apply
(в БД сейчас author пуст у всех, видимые упоминания были в описаниях «по учебнику …»).
review_geom10/11.js не тронуты — там фамилии как поисковые шаблоны детектора, не атрибуция.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Пробник ЦТ по математике 2019, Вариант 1 (А1–А18 + В1–В12; В1 на соответствие, В2 множ.выбор)
для трека exam-prep ctmath. Источник: чистый PDF ЦТ 2019.pdf. Все 30 решены и сверены: столбец
Вариант 1 в таблице (стр.45) затемнён, но читаемые ячейки совпали; методы B5/B6/B7/B11/B12
перекрёстно подтверждены на Варианте 10 (его задания на стр.43-44, ответы читаемы → 81/56/-1071/
624/540 ровно по таблице). Тяжёлые: B7=-264 (период+нечётность), B11=288, B12=110 (т.Гульдина).
Фигурные A1/A7/A9 разрешены по столбцу 1 (D/2√34/2,4); B1/B2 — данные текстом.
VARIANT_LABEL 115 -> 'ЦТ-2019'. DRY-RUN 30/30, self-check и структурный KaTeX — зелёные.
Запись в БД — пользователь: node backend/scripts/seed_ctmath_ct2019_v1.js --apply
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Пробник ЦТ по математике 2018, Вариант 1 (А1–А18 + В1–В12, В1 на соответствие) для трека
exam-prep ctmath. Источник: чистый PDF ЦТ 2018.pdf. ВСЕ 30 ответов решены и сверены с
официальной таблицей (стр.32, столбец Вариант 1) — полное совпадение, включая B8=-18,
B9=-130 (двугранный угол), B11=32, B12=45 (координатный метод, PT=5/2).
Фигурные/несогласованные (А3 точки, А9 графики→пути, А11 квадраты, В1/В2 функция по узлам,
В8 экв. показательное, В10 множитель (6-x)² по ответу) реконструированы/адаптированы.
VARIANT_LABEL 114 -> 'ЦТ-2018'. DRY-RUN 30/30, self-check и структурный KaTeX — зелёные.
Запись в БД — пользователь: node backend/scripts/seed_ctmath_ct2018_v1.js --apply
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Пробник ЦТ по математике 2016, Вариант 1 (А1–А18 + В1–В12) для трека exam-prep ctmath.
Источник: чистый PDF ЦТ 2016.pdf. ВСЕ 30 ответов решены и сверены с официальной таблицей
(стр.35, столбец Вариант 1) — полное совпадение, включая B5=-22, B9=712, B11=56, B12=724.
Фигурные задания (А2 угол через MN||BC, А3 числа на прямой, А6 таблица, А7 площадь по
координатам, А8 область значений, А11 круговая диаграмма) реконструированы/адаптированы
в самодостаточные авто-проверяемые формы. VARIANT_LABEL 113 -> 'ЦТ-2016'.
DRY-RUN 30/30, self-check и структурный KaTeX — зелёные.
Запись в БД — пользователь: node backend/scripts/seed_ctmath_ct2016_v1.js --apply
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Чинит 8 «baseline»-падений (теперь 330/330):
- auth (3): контроллер/фронт требуют пароль >=8, а схема роута (minLen:6) и тест
(7-симв. 'pass123') устарели → схема register/profile 6→8, тест-пароли → 8 симв.
(login/duplicate падали как следствие незарегистрированного юзера).
- page (5): jsdom не был установлен → добавлен в devDependencies.
- флакость jsdom-страниц при параллельном прогоне (фикс. wait под нагрузкой CPU) →
npm test с --test-concurrency=1 (детерминированно; в изоляции тесты и так проходят).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Актуальный формат экзамена: А1–А10 (8 mc + 2 open) + В1–В20 (1 long + 19 open).
Перенабор по PDF сборника РИКЗ; решений в источнике нет — решено вручную,
ВСЕ 30 ответов сверены с официальным ключом (стр.35, столбец Вариант 1).
Адаптации: А1 (точки на прямой) → равные промежутки в тексте; А6 (промежуток
на рисунке) → описан словами. Метка 111 (ЦЭ-2024) в VARIANT_LABEL.
Идемпотентный seed, --apply — пользователь.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Первый из ЦТ-годовых. Формат ЦТ: А1–А18 (18 mc) + В1–В12 (12 open) = 30.
Перенабор по PDF; решений в источнике НЕТ — решено вручную, ответы
сверены с официальным ключом (стр.34 сборника). Адаптации картинок:
А2 (симметричные фигуры, неразборчивы) → MC о симметрии точки; А6
(параллелограмм на сетке) → координаты вершин; А10/А15 — текстом.
Метка 110 (ЦТ-2014) в VARIANT_LABEL. Идемпотентный seed, --apply — пользователь.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
30 заданий (А1–А10 + В1–В20), перенабрано вручную в KaTeX по PDF РИКЗ
(РТ-1 23/24 В1). Геометрия закодирована текстом — чертежи не нужны.
Идемпотентный upsert, DRY-RUN по умолчанию, запись с --apply.
Верификация: node --check, валидация 30/30, KaTeX-рендер 413/413 сегментов.
+ метки вариантов 104–106 (РТ-2023/24 этап I/II/III) в routes/exam-prep.js.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Вместо «Вариант 101/102/103» (технические номера) показываем источник:
«РТ-2024/25 · этап I/II/III». examVariantLabel() в exam-prep.js — единый
источник подписи: listVariants (пикер/dropdown) + variant_label в ответе
mock/:id (строка прохождения и результата). Номера в БД остаются 101+
(нужны для фильтра-диапазона [101;1999] и провенанса). math9 — fallback
«Вариант N» (не затронут). Новые варианты (104+) — дописывать в VARIANT_LABEL.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- exam-prep.js: MOCK_VARIANT_RANGE — для ctmath показываем как пробники
только чистые 30-задачные варианты [101;1999]; год-пачки (variant=год
2011-2024 и 0, до 114 задач) остаются пулом для тренажёра по темам,
но скрыты из пикера/mock-start/просмотра вариантов. math9 (1..80) не затронут
(диапазон только для ctmath).
- mock.js: пикер «По варианту» — выпадающий список реальных вариантов
(через listVariants) вместо number-input 1..N; раньше для ctmath он
предлагал 1..18 и не доходил до 101 → пробник по варианту не запускался.
- cleanup_ctmath_bank.js: идемпотентный скрипт — ретайр битого id=1419
(mc с противоречивым ответом → long), variants_count → 3 (чистых вариантов).
- seed_*: variants_count считается по диапазону [101;1999] (консистентно с роутом).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
У Квантика не было фиче-флага — его нельзя было выключить, и он всегда висел
в сайдбаре (даже у учеников без класса). Добавлено по образцу остальных игр:
- adminController.updateFeatures: 'quantik' в whitelist (PATCH принимает флаг).
- games.js: пункт «Квантик: Законы Мира» в GAME_FEATURES и FS_FEATURES
(тумблер в админке → Игры; пишет feature_quantik_enabled).
- api.js hideDisabledFeatures: quantik -> ['/quantik','/quantik.html'] (скрытие
из сайдбара при выключении) + '/quantik' в classOnlyHrefs/classOnlyPaths
(скрыт у учеников без класса, как прочие игры).
Миграция не нужна: флаг «неявно включён», пока админ не выключит (features[key]
!== false => включено). Требует Ctrl+F5 (фронт).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Не было UI для управления exam_tracks.enabled (только флаг в БД, ставился
миграцией). Добавлена админ-секция «Экзамен-модули»:
- backend exam-prep.js: GET /admin/tracks (все треки, вкл. выключенные, + число
заданий) и PATCH /admin/track (exam_key, enabled), обе requireRole('admin').
Пути без :examKey, чтобы не задеть гейт content_access.
- frontend: секция sections/exams.js (список треков + переключатель enabled),
вкладка в admin.html (admin-only через ADMIN_ONLY_TABS, locked для не-админов),
регистрация в admin.js (ROUTE_TO_SECTION).
Выключенный трек скрыт у учеников и пропадает из каталога прав доступа (тот
берёт exam_tracks WHERE enabled=1). Доступ ученикам по-прежнему в «Доступ · контент».
Требует перезапуска бэкенда + Ctrl+F5.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1) exam-prep practice (strategy=random) возвращал около 0.6 от count: функция
distributeByDifficulty раскладывает count по 5 уровням сложности, а у трека
ctmath задания только уровней 1-3 (уровни 4-5 пустые) -> часть выборки терялась
(20 -> 12, 15 -> 10, 10 -> 6). В pickRandomByDifficulty добавлен добор до count
из доступных уровней. Трек math9 не затронут (там добор не требуется).
2) lesson.html: .lesson-nav-btn-title был inline-span, поэтому max-width и ellipsis
игнорировались и длинные заголовки вылезали за кнопку. Добавлен display:block.
Бэкенд-правка требует перезапуска сервера; фронт-правка видна после Ctrl+F5.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
feat(quantik-game): фаза 5 — авторинг игровых уровней в sim-builder + раздача
Учитель собирает игровой уровень без кода: новая (аддитивная, сворачиваемая)
панель в sim-builder задаёт блок goal (when/title/hint/hold/fail) + до 3
звёзд + game-мету (chapter/order/par_ms); выражения проверяются inline через
SimExpr.compile (без eval). buildSpec/loadFromSim — round-trip без потерь
(goal/game пишутся только при включённом слое; обычная sim не меняется).
Кнопка «Играть» монтирует черновик в SimEngine-модалке (HUD цели из Ф0).
QuantikLevels стал async: подмешивает custom_sims cat=game (свои+
published) в реестр (custom:<dbid>), offline-safe, строки без goal
отбрасываются; deep-link /quantik?level=custom:<id> с серверной проверкой
доступа (own|published → иначе 403/404), мимо геймплейного гейта unlockStars.
Раздача классу — реюз share Ф6 (game-aware ссылка + durable pushNotif).
Правки sim-builder строго аддитивны (параллельная сессия). npm test 259/8
baseline; quantik-authoring 6/6; lint:routes 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
feat(quantik-game): фаза 3 — граф-уровни (движение по f(x)) + зоны
Новый тип уровня: Квантик едет по кривой y=f(x), которую игрок собирает
слайдерами коэффициентов, проходя сквозь зоны-препятствия. Движок
(аддитивно): plot.runner → env-поля curve.runX/runY/runDone (f компилится
1 раз, питает И кривую, И бегунок-героя, без само-ссылки); type zone
(forbidden/target/collect) → булево env-поле zone.hit. Грамматика
выражений ЗАКРЫТА — никаких inzone()-предикатов, только именованные
env-поля (модель t/tries из Ф0), без eval. Глава-созвездие functions из
5 уровней (луч/синус/парабола/модуль/экспонента), разблокировка 9/11/13/
15/17 (цепочка проходима). validateSpec принимает zone+runner. Все 5
уровней независимо проверены на движке (2★ достижимы). npm test 253/8
baseline; custom-sims 26/26; lint:routes 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
feat(quantik-game): фаза 1 — оболочка игры + физ-уровень + прогресс (MVP)
Страница /quantik монтирует уровень-спеку в SimEngine (игровой режим: HUD из
Ф0 + слайдеры закона + play/reset), на победу шлёт результат и показывает
экран успеха (звёзды/время/попытки, inline SVG). Уровень phys-artillery-1
как данные (levels.js): гравитация + запуск тела из угла/скорости, портал,
бонус-звезда. Бэкенд: миграция 076 game_progress (UNIQUE user+level),
/api/game/progress (GET свой / POST upsert best time/stars, attempts++,
auth-only, валидация входа), клиент LS.gameProgress*, пункт сайдбара.
game.test.js 13/13; npm test 251 pass/8 baseline; lint:routes 0.
Уровень проверен на реальном интеграторе (311 выигрышных комбо, 31 на 3★).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@
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>
@
Учитель делится своей колодой с классом или конкретными учениками; карты общие
(одна копия), а прогресс у каждого свой — flashcard_reviews уже keyed по
user_id+card_id, поэтому ученик копит собственные интервалы на тех же картах.
- миграция 075: flashcard_deck_access (deck_id, type class|user, target_id) —
зеркало folder_access; индексы по target и deck.
- deckAccess(): владелец/админ (canEdit) либо назначенный напрямую/через класс
(canRead). listDecks отдаёт свои + назначенные (shared/can_edit/owner_name);
getCards/getStudySession/submitReview пускают по canRead (ученик учится и
ставит отзыв), правка карт/колоды — только владелец.
- share API (owner + роль teacher/admin): GET /shares, POST /share, DELETE
/share?type=&target_id=; цель валидируется (свой класс / свой ученик).
- фронт: общие колоды с бейджем учителя, открываются read-only (CSS .readonly
прячет ручки/удаление/правку, drag и inline-edit выключены), кнопка
«Поделиться» с модалкой (вкладки Классы/Ученики, тоггл = add/remove share).
- тест flashcards-share 13/13 (шаринг класс/ученик, видимость, изучение+отзыв,
правка 404, доступ 404, роль-гейт 403, чужой класс 403, снятие доступа).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tier-1 апгрейд интервального повторения:
- schedule() с состояниями learning/relearning/review вместо плоского sm2():
новая карта проходит шаги [1,10] мин, «Снова» возвращает на шаг 0 (минуты),
«Знаю» продвигает шаг → выпуск (1д), «Легко» выпускает сразу (4д); зрелая
«Снова» = lapse → relearning (ef−0.2, ×0.5).
- study-сессия: динамическая очередь — недоученная карта (graduated=false)
возвращается через 3 карты и показывается снова в той же сессии.
- лимит новых карт/день (decks.new_per_day, деф.20) в getStudySession и бейдже.
- превью кнопок fcPreview() показывает минуты/дни, зеркало серверной логики.
- миграция 074: state/learning_step/lapses/created_at + new_per_day + индексы.
- тесты SRS 9/9 (шаги, lapse, лимит новых).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Раньше на новой карте Снова/Трудно/Знаю/Легко все давали 1 день (чистый SM-2:
оценка влияла только на ease factor). Теперь интервал зависит от оценки:
новая карта Легко=4д (остальные 1д), на повторах Трудно ×1.2 / Знаю ×ef /
Легко ×ef×1.3 (easy-бонус). Серверный sm2() и клиентское превью fcNextInterval
синхронны — проверено 0 расхождений на 256 комбинациях.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- imggen: дневной счётчик генераций перенесён из in-memory Map в таблицу
imggen_usage (миграция 070) — переживает рестарт. Cooldown остаётся в памяти,
но добавлена периодическая чистка Map + старых строк imggen_usage (>7 дн).
- classroom-cleanup: ретеншн error_log (app_settings.error_log_retention_days,
по умолч. 30; 0 = выкл) в том же суточном джобе.
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>
- errorHandler: MulterError → 413 «слишком большой» / 400 (а не 500).
- server: process.on(unhandledRejection/uncaughtException) — глобальная страховка
с логированием, процесс не падает от единичной асинхронной ошибки.
- pet: атомарный CAS на кулдаунах petAction/starCatch/feedPet
(UPDATE ... WHERE last IS ?, начисление только при changes=1) — нет двойного
начисления при параллельных запросах. Проверено на семантике node:sqlite.
- assistant.flashcardsFromText: await callLLMFailover в try/catch → 502 вместо
необработанного отклонения промиса.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#5 rate-limit (byUser) на дорогих LLM-эндпоинтах: /assistant/ask (20/мин),
/assistant/flashcards (10/мин), /imggen (20/мин) — поверх cooldown/дневного
лимита. Защита от «сжигания» бюджета провайдера одним аккаунтом.
#6 SSE больше не таскает JWT в URL: добавлен authed /notifications/stream-ticket
(одноразовый тикет, TTL 30с), клиент берёт тикет заголовком и подключается
с ?ticket=. ?token= оставлен как временный фоллбэк для старых клиентов.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- games: дневной лимит начислений XP за hangman/crossword (DAILY_WIN_CAP=10,
счёт по xp_log.reason) — нельзя бесконечно фармить циклом complete.
- lessons.markComplete: XP/монеты только при ПЕРВОМ завершении урока
(повторные POST больше ничего не начисляют).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- courses: requireOwnership(created_by) на PUT/DELETE/duplicate/publish-all
и все мутации секций — учитель больше не может править/удалять чужой курс.
- lessonController.create: проверка владения курсом перед вставкой урока.
- assign/unassign курса классу: проверка владения классом (_ownsClass).
- materials.share по userId: получатель должен быть учеником учителя
(класс или teacher_students), иначе 403.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
#1 Студенческий поллинг: вместо полной перезагрузки доски каждые 2с —
лёгкая сигнатура страницы (?meta=1 → maxSeq+count). Если доска совпадает
с сервером (обычный случай при живом WS) — ничего не грузим. Полная
перезагрузка только при расхождении. Счёт подтверждённых штрихов — по
положительным id (без bookkeeping).
#2 Картинки-штрихи выносятся в файлы /uploads/classroom (вместо base64 в БД):
меньше БД и payload поллинга. Имя с префиксом sessionId.
#5 Ретеншн: classroom-cleanup удаляет штрихи+файлы завершённых сессий старше
N дней (app_settings.classroom_retention_days, по умолч. 30; 0 = выкл),
историю/чат/посещаемость не трогает. Планировщик в server.js.
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>
FLUX лучше понимает английский. Если в промпте есть кириллица — прогоняем
через тот же LLM-провайдер ассистента (callLLMFailover, с failover) и
отправляем перевод. При сбое перевода — исходный текст. callLLMFailover
теперь экспортируется из assistantController.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Питомец: кастомный фон (миграция 068 pet_bg_custom, POST /api/pet/bg/custom,
карточка «Свой фон (ИИ)» в гардеробной, применение картинкой).
Курсы: обложка-картинка (миграция 069 cover_image, генерация в модалке
редактирования, рендер вместо эмодзи).
Аватар: кнопка «Сгенерировать (ИИ)» в загрузке → кадрирование → модерация.
Доска (classroom): кнопка-инструмент «Сгенерировать картинку (ИИ)».
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Полная проверка всех бесплатных моделей Kilo на русском: openrouter/free
теперь роутит на reasoning-модель и выводит «мысли вслух» — убран. Надёжное
ядро (чисто, без утечки): Owl Alpha, Nemotron 120B/550B, Nex N2 Pro, Laguna XS.
kilo-auto/free и stepfun/step-3.7-flash тоже текут — в список не берём.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Сверка с живым /models: qwen/qwen3.7-plus:free удалена из шлюза (висела
мёртвой в списке). Заменена на nex-agi/nex-n2-pro:free (проверено: чистый
русский, 262K, ~3с). Остальные 7 моделей живы; активная owl-alpha — ОК.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GET /assistant/student-profile/:id (teacher/admin): производный профиль ученика
— слабые предметы, трудные темы экзамена, цель, серия. Сырые заметки НЕ
отдаются (приватны). Доступ: свой класс или «Мои ученики»; чужой → 403; админ
— любой (проверено). На /my-students — кнопка «Профиль» с поповером. Ученику в
панели памяти уже написано «учитель видит лишь общие слабые темы».
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>