Чинит 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>
scripts/index-textbooks-headless.js: puppeteer-core + системный Chrome/Edge
рендерит каждый учебник через локальный сервер (служебный JWT в localStorage,
т.к. /textbook требует логина), кликает по параграфам и забирает рендерный
текст движков (математика/физика и т.п.) в textbook_chunks. Дополняет
статический индексатор. npm: index:textbooks / index:textbooks:full (headless).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
content/phys/ct-2024.yaml — 15 questions from ЦЭ,ЦТ 2024 across
6 topics (kinem, mol, emf, electro, magnet, optics) as proof of format.
backend/scripts/import-content.js — unified importer:
- Validates schema (subject, year, options, exactly-1-correct)
- Aliases (kinem, mol, ...) resolve to Russian topic names via get-or-create
- Deduplicates by first 80 chars of text (matches legacy seed_*.js behavior)
- Runs in a single transaction, idempotent re-runs
On fresh DB: 13 added (2 dedup collisions — same 80-char prefix, expected).
On prod DB: 0 added (all already exist from legacy seeds).
Second run on either: 0 added (dedup works).
Legacy seed_phys_ct2024.js kept as backup — see content/README.md
for migration guide.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Classroom performance:
- WebSocket server (ws-server.js) for low-latency cursor & stroke preview
Replaces HTTP POST per event → eliminates per-message auth overhead
Session member cache (30s TTL) avoids SQLite query per WS message
Fallback to HTTP POST when WS not connected
- Cursor throttle reduced 100ms → 33ms (~30fps)
- Stroke preview throttle reduced 50ms → 20ms
- whiteboard.js: render() is now rAF-gated (_doRender/_rafPending)
Multiple render() calls within one frame collapse into one repaint
document.hidden check — zero CPU when tab is in background
visibilitychange listener restores canvas on tab focus
Guest board:
- guestClassroom.js route: public token-based read-only access
- guest-board.html: name entry + read-only whiteboard + SSE
- SSE: addGuestClient/removeGuestClient/emitToGuests
Screen share picker:
- Discord-style modal with tab switching (screen/window/tab)
- Live video preview before confirming share
- useExistingScreenStream() in ClassroomRTC
Fullscreen exit overlay:
- #cr-fs-exit-overlay button inside cr-board-wrap
- Visible only via CSS :fullscreen selector (touchpad users)
File sharing from library:
- Teacher picks file from library, sends as styled card in chat
- crDownloadLibraryFile() fetches with Bearer auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>