Files
Learn_System/plans/lab-content-engine/CONTEXT.md
T
2026-05-30 15:04:08 +03:00

12 KiB
Raw Blame History

Feature Context: Контент-движок лаборатории

Current State

  • Лаборатория работает на захардкоженной регистрации (см. PLAN.md Summary).
  • Ветка feature/lab-content-engine создана от master.

Architecture map (как было ДО рефактора)

  • frontend/lab.html — sim-тела <div id="sim-xxx"> (inline HTML, ~3000 строк) + 58 <script> тегов (4800-4861) + three.js.
  • frontend/js/labs/lab-glue.js:
    • _catFilter, _disabledSimIds, _simModuleDisabled (вкл/выкл из админки)
    • filterSims(), renderSims() (карточки каталога)
    • preview-хелперы _grid/_axes/_svg + ~60 констант P_*
    • массив SIMS (821-866), window.SIMS/window.LAB_SIMS
  • frontend/js/labs/lab-init.js:
    • объявления переменных симуляций (gSim, pSim, …)
    • ALL_SIM_BODIES / ALL_CTRL_BARS (33-48)
    • _pauseAllSims() (54-91), openSim(id) if-цепочка (93-160), closeSim() (212-258)
    • _simShow(), _addTouchSupport() (touch-bridge + ResizeObserver)
    • объект THEORY + loadTheory() + _theoryToggle()
    • функции _openXxx() (603-756) — единый шаблон: _simShow('sim-xxx') + ленивое new XxxSim(...) + показ ctrl-xxx
  • frontend/js/admin/sections/sims.js — админ-секция (пока только вкл/выкл, _disabledSimIds).

Загрузочный порядок (КРИТИЧНО)

В lab.html: движки _fx_*, _phys_visuals, _graph_panel, _chem_visuals грузятся ПЕРЕД симуляциями. lab-init.js (4826) грузится ПЕРЕД lab-glue.js (4827). renderSims() вызывается в конце lab-glue. Некоторые sim-файлы (graph.js) грузятся РАНЬШЕ lab-glue.js → preview P_* ещё не определены на момент исполнения их тел. => В манифестах preview поддерживает функцию (ленивое вычисление в renderSims), не только строку.

Контракт LabRegistry (Фаза 0)

LabRegistry.register(manifest)  // manifest.id уникален; повторная регистрация перезаписывает
LabRegistry.get(id)             // по base-id (без ':arg')
LabRegistry.has(id)
LabRegistry.all()               // в порядке регистрации
LabRegistry.setActive(sim) / stopActive() / destroyActive()  // менеджер жизненного цикла

manifest: { id, cat, title, desc, preview(string|fn), theory?, bodyId?, mount?(host), open(ctx), stop?(), destroy?(), subject?, grade?, topics? }

Адаптер (Фаза 0): реестр в приоритете, иначе legacy

  • renderSims() — порядок берём из исходного SIMS; для id, который есть в реестре, используем манифест (resolve preview), иначе legacy-запись; в конце добавляем registry-only записи, которых нет в SIMS.
  • openSim(id)base = id.split(':')[0]; если LabRegistry.has(base)stopActive(); get(base).open({arg}); setActive; иначе старый if-путь.
  • loadTheory(id) — если get(base).theory есть → рендерим из него; иначе THEORY[base].
  • closeSim()/_pauseAllSims() — дополнительно LabRegistry.stopActive() / destroyActive().

RESUME STATE — Phase 3 done (2026-05-30, latest)

  • HEAD=70762be (Ф3). Ленивая загрузка кода: старт /lab ~530KB вместо ~2.9MB+600KB three.js (~6×).
  • Новые файлы: _loader.js, _sim_deps.js (генерированный манифест). Правки: _register-all.js, lab-init.js, lab.html (eager сокращён до каркаса).
  • Манифест SIM_DEPS: каждый sim → {open, files[], three}. Инвариант (проверен): файл, определяющий open-функцию, ВСЕГДА в files[] (кроме graph — он eager). Self-heal = страховка.
  • ⚠️ PUSH: на момент завершения Ф3 окружение глючило (пустой вывод команд); локально 2 коммита ahead (Ф2-docs + Ф3), 0 behind. НУЖНО допушить: git push origin feature/lab-content-engine (мог не пройти из-за транзиентного auth — повторить).
  • ⚠️ НЕ ПРОВЕРЕНО В БРАУЗЕРЕ (см. чеклист в phase-3-lazy-load.md handoff).
  • ГЕНЕРАТОР МАНИФЕСТА был временным (%TEMP%, удалён). Логика: framework-set + статический анализ provides/refs (комментарии вырезаются) + транзитивное замыкание по ленивым файлам; 3D-set хардкод {crystal,orbitals,stereo,periodic}; EXTRA_DEPS={periodic:[_periodic_data.js]}. При Ф4/5 положить в tools/gen-sim-deps.js.
  • СЛЕДУЮЩЕЕ: Ф4 (БД lab_sims + API + админка, backend — не трогает lab.html) или Ф5 (курикулум).

RESUME STATE — Phase 2 done (2026-05-30, ранее)

  • Ф2: 40 тел симуляций (~4420 строк) вынесены из lab.html (4880→484 строк) в frontend/labs-bodies.html. На месте региона — #sim-bodies-host + инлайн-скрипт с СИНХРОННЫМ XHR (open(...,false)), который во время парсинга грузит partial и insertAdjacentHTML('beforebegin') вставляет тела ДО хоста, затем удаляет хост. Тела присутствуют до DOMContentLoaded → обработчики geometry.js:3207 и порядок init сохранены.
  • ctrl-бары (#ctrl-*) и #theory-panel ОСТАЛИСЬ в lab.html (они в topbar, не в регионе).
  • partial раздаётся существующим express.static(frontendDir) (server.js:475) — новый роут не нужен.
  • ГАРАНТИИ (механические, не браузерные): реконструкция before+region+after == оригинал ПОБАЙТОВО; id-мультимножество (newLabhost)+partial == оригинал; 40 sim-body div; node --check OK.
  • ⚠️ НЕ ПРОВЕРЕНО В БРАУЗЕРЕ. РИСКИ к проверке вручную: (1) sync-XHR может блокироваться при file:// — но тут Express, ок; (2) консольное предупреждение о deprecated sync XHR — безвредно; (3) CSP на инлайн-скрипт — на странице уже есть инлайн-скрипты, должно быть ок; (4) кэш partial (?v=1) — при правках бампать версию.
  • ПРОВЕРИТЬ: открыть /lab, дождаться каталога, открыть несколько симуляций (graph, pendulum, geometry — у неё DOMContentLoaded-кнопки, stereo:cube, opticsbench), убедиться что canvas рисуется и кнопки работают.
  • ОТКАТ: git revert <commit Ф2> или вернуть регион из labs-bodies.html обратно.
  • СЛЕДУЮЩЕЕ: Фаза 3 (ленивая загрузка кода) ИЛИ Фаза 4 (БД+админка, backend — без конфликтов с lab.html). Параллельная сессия всё ещё может править lab.html.

RESUME STATE — Phase 1 done (2026-05-30, later)

  • Коммиты: 36c091b → 0888a70 (фикс Ф0) → ebb2a9b (Ф1). HEAD=ebb2a9b, ЗАПУШЕНО, remote синхронен.
  • Ф1: централизованный _register-all.js (data-driven из SIMS+THEORY+OPEN map 40 шт), if-цепочка openSim удалена, _pilots.js удалён, LAB_SIM_ALIASES добавлены. Ревью PASS, vm-harness ALL PASS.
  • SIMS/THEORY/_pauseAllSims/closeSim/ALL_SIM_BODIES/ALL_CTRL_BARS НАМЕРЕННО оставлены (источники данных + lifecycle-дробовик) — паритет без браузера. Их удаление = Фаза 2 (с ленивым mount).
  • БЛОКЕР-РИСК: параллельная сессия (biochem/opticsbench) активно правит lab.html и откатывала мои include-правки. Перед Фазой 2 (вынос ~3000 строк из lab.html) — СОГЛАСОВАТЬ, иначе конфликты/потеря работы.
  • СЛЕДУЮЩЕЕ: пользователю желательно открыть /lab в браузере и кликнуть несколько симуляций (особенно с :arg — стерео-фигуры, оптика-режимы) перед Фазой 2.

RESUME STATE (2026-05-30, ранее)

  • Ветка feature/lab-content-engine. Коммиты: 36c091b (Фаза 0, была неполной) → 8f72d68 (фикс 3 блокеров, ЗАПУШЕН).
  • Первое ревью Фазы 0 = FAIL (3 блокера: _registry.js не подключён, пилоты не зарегистрированы, loadTheory не адаптирован). ВСЕ ТРИ ИСПРАВЛЕНЫ в 8f72d68:
    • _registry.js подключён в lab.html:4799 (после three.js).
    • frontend/js/labs/_pilots.js — регистрирует graph/quadratic/pendulum; подключён в lab.html:4863 (defer, последним).
    • loadTheory (lab-glue.js:951) — реестр в приоритете.
  • СЛЕДУЮЩИЙ ШАГ: повторное независимое ревью Фазы 0 (агент). Если PASS → Фаза 1.
  • Фаза 1 решено вести ПО КАТЕГОРИЯМ с коммитами (math→phys→chem→bio→game), legacy удалять в конце.
  • НЕ ПРОВЕРЕНО в браузере (нет автоматизации). Паритет — статически + ревью.
  • ВАЖНО: open* функции глобальны (graph.js:506, quadratic.js:454, pendulum.js:1749). P* — top-level const в lab-glue.js (доступны cross-script). THEORY — const в lab-init.js. Манифест Фазы1 регистрировать в самом sim-файле, но следить за порядком (preview/theory как fn если файл грузится до lab-glue/lab-init).
  • УРОК: lab-glue.js/lab-init.js часто перенумеровываются линтером — перед Edit перечитывать. Делать правки ПО ОДНОЙ с проверкой (был сбой пакетного выполнения).

Temporary Workarounds

  • Пилоты (graph/quadratic/pendulum) оставлены в SIMS/THEORY для порядка карточек и единого источника теории; merge перекрывает по id. Удалить в Фазе 1.

Known follow-ups (из ревью Фазы 0)

  • При переключении на LEGACY-симуляцию LabRegistry._active не очищается → лишний destroyActive() на неактивной. Безвредно сейчас; очистить _active на legacy-open в Фазе 1.

Cross-Phase Dependencies

  • Фаза 1 опирается на ядро реестра из Фазы 0.
  • Фаза 3 (ленивая загрузка) опирается на манифесты с зависимостями движков (Фаза 1/2).
  • Фаза 4 (БД) мёржит код-манифесты Фазы 1 с оверрайдами.
  • Фаза 5 использует поля subject/grade/topics из манифестов.

openSim('stereo:figure'), ?stereofig=, обратная совместимость magnetic/coulomb→emfield, thinlens/mirrors/refraction→opticsbench.

Проектные правила (НЕ нарушать)

  • Иконки: только inline SVG .ic, НЕ эмоджи.
  • Поиск по коду: ast-index, НЕ Grep tool.
  • БД: встроенный node:sqlite DatabaseSync, НЕ better-sqlite3.
  • Git: коммитить только изменённые файлы.