студия автора
Собрать практику
FastAPI и SPA на localhost. Три шага подготовки, вызовы LLM,
эфемерный Postgres в контейнере на каждый прогон. Тот же CLI, если удобнее
из терминала.
машина автора · uv run gen
локально · пак в git · без общего сервера
Автор собирает практику в студии у себя на машине: предметная область, задания,
эталонные решения. Движок разворачивает десятки вариантов данных и прогоняет по
ним эталон. Студент решает в Docker и коммитит solutions/ —
CI преподавателя считает то же самое и тем же кодом.
Столько раз задание проверено до того, как студент его увидел.
из чего состоит
Общего сервера нет. Пак — это каталог в git и одновременно контракт: студия его
только пишет, раннер только читает. Обе стороны зависят от одной библиотеки
packcore, поэтому «у меня проверка проходит, а в CI нет» не бывает
по построению.
студия автора
FastAPI и SPA на localhost. Три шага подготовки, вызовы LLM,
эфемерный Postgres в контейнере на каждый прогон. Тот же CLI, если удобнее
из терминала.
машина автора · uv run gen
раннер студента
Docker-образ: FastAPI, SPA и Postgres. Живая база для экспериментов, отдельная
чистая — для проверок. Тот же образ с --mode=ci проверяет сдачу
в пайплайне.
машина студента · GitLab CI
пак практики
Каталог в git: описание базы, задания, эталоны, спеки данных, миграции вариантов, проверки, отчёт приёмки и оформление курса. Утверждения держатся на хэшах.
packs/<практика>/
путь практики
Первые три проходит автор, и каждый заканчивается утверждением: пока шаг не утверждён, следующий не начинается. Четвёртый идёт у студента и в CI.
шаг 1 · область
Описание базы, темы курса с квотами заданий, DDL. Утверждённая область получает хэш содержимого — задания привязаны именно к этой версии.
domain.json
шаг 2 · задания
Формулировки, темы, сложность, обязательные и запрещённые конструкции. Покрытие тем считается до утверждения, а не после жалоб студентов.
tasks.json
шаг 3 · данные
Эталонное решение, спека данных, варианты, набор проверок и негативные решения — заведомо неверные ответы, на которых проверки обязаны падать.
materializations/
<id>.json
шаг 4 · практика
Студент пишет запрос на живой базе, жмёт «Проверить решение» и получает прогон по всем вариантам. Результат ложится в файл и уезжает в CI.
solutions/<задание>.sql
ручной режим Ключ LLM не обязателен: студия печатает промпт, вы приносите ответ модели из чата и вставляете обратно. Шаги те же, гейты те же.
почему это воспроизводимо
LLM пишет спеку данных, строки генерирует движок по seed. Один seed — один и тот же набор строк на любой машине, в любой день.
Ожидаемый результат каждого варианта вычисляется прогоном эталонного решения, а не пересказывается моделью.
Перед сравнением результат канонизируется: регистр имён колонок, точность чисел, даты в ISO-8601 UTC, место NULL, порядок строк. 40 и 40.00 — одно значение.
Образ Postgres пришпилен по digest и записан в манифест, база создаётся с LC_COLLATE=C. Иначе сортировка текста разъедется между машинами.
когда не сошлось
Полоса прогона показывает не слово «зачёт», а объём проверки. Упавший скрытый вариант раскрывается — видно его данные, ожидаемый результат и ваш. До падения он закрыт, чтобы ответ нельзя было подогнать под данные.
студия автора · localhost:8765
Отчёт приёмки показывает каждый вариант данных, каждую проверку и каждое негативное решение. Оговорки к прогону пишутся прямо в отчёт: если однозначность эталона не проверялась, это будет написано, а не умолчано.
приложение студента · localhost:8766
docker compose up — и практика открыта в браузере. Слева задания, сверху
условие и редактор с подсветкой и автодополнением по схеме пака, снизу результат,
проверка, схема базы, примеры данных и история попыток.
solutions/.
что умеет
Задание набирает нужные ему проверки. Одни сравнивают результат, другие — состояние таблиц после записи, третьи — сам текст решения через AST, а не регулярками.
| Тип | Что сравнивает |
|---|---|
| schema | Набор и порядок колонок результата, имена псевдонимов. |
| cardinality | Сколько строк ожидается: ровно одна, много, допустим ли пустой ответ. |
| result_exact | Результат построчно — на открытых примерах данных. |
| result_hash | Хэш нормализованного результата — на скрытых вариантах. |
| table_state | Состояние таблиц после INSERT, UPDATE, DELETE. |
| db_schema | Структура схемы после CREATE и ALTER. |
| sql_constraints | Обязательные и запрещённые конструкции в решении — разбором AST. |
Систематические крайности — каждый класс строк пуст, каждый единственный — плюс случайные комбинации квот.
Типичные ошибки записаны как SQL. Если проверки их не ловят, задание не проходит приёмку.
Промпт наружу, ответ модели внутрь. Полный конвейер без ключа API и без трафика в чужой сервис.
gen domain, tasks, materialize, status, build — те же этапы из терминала.
Тот же образ раннера с --mode=ci читает solutions/ из merge request и считает то же самое.
Тема пака задаёт цвета, радиусы, логотип и свой CSS. Семь готовых тем в комплекте.
Поменяли формулировку — материализация помечается устаревшей до того, как пак уедет студентам.
Эталоны и скрытые варианты лежат зашифрованными: студент видит вариант только после падения на нём.
Строками — как в консоли; по записям — когда колонок больше, чем помещается в экран.
контракт
Пак читают студия, раннер и CI. Версия формата и версия движка данных лежат
в манифесте: несовместимый мажор раннер не откроет, а не откроет «как-нибудь».
Утверждения держатся на хэшах — content_hash области,
source_hash задания.
быстрый старт · 15 минут
Ключ LLM не нужен: оба сценария работают на заготовленных ответах модели.
Нужны Docker и uv; Node — только если собираете интерфейсы из исходников.
01 · зависимости
Один uv-воркспейс на весь монорепозиторий: ядро, генератор, раннер.
uv sync --all-packages
02 · автор
Ответы модели берутся из mock_llm/. На macOS сторож testcontainers отключается флагом.
# localhost:8765 TESTCONTAINERS_RYUK_DISABLED=true \ uv run gen studio \ --pack packs/spike --mock
03 · студент
Первый запуск собирает образ и накатывает схему пака, дальше старт занимает секунды.
# deploy/student · localhost:8766
docker compose up
оформление курса
Одна папка theme/ задаёт цвета, радиусы, логотип и, если нужно,
свой CSS — приложение студента открывается уже в фирменном виде. Семь готовых
тем в комплекте, включая полную брендовую пару.
дальше
В документации — руководства автора и студента, контракт темы, формат пака, справочник API и разбор частых ошибок.