Перейти к основному содержимому

Формат пака

Пак — контракт между генератором и раннером. Оба зависят только от packcore, поэтому формат меняется в одном месте, а не в двух приложениях.

packs/<практика>/
brief.json разбор лекции, если им пользовались (шаг 0)
domain.json
tasks.json
materializations/<task_id>.json
migrations/
common/ создание схемы
tasks/<id>/ INSERT-ы вариантов данных
report/index.md
theme/ оформление; ставится из каталога на шаге 4
student-template/ правки файлов комплекта
release.json файлы комплекта, которые не кладутся в архив
dist/ собранные комплекты
state.json
mock_llm/ заготовленные ответы модели для --mock

В pack.enc уходит не всё: brief.json, report/, state.json, mock_llm/, student-template/, release.json и dist/ остаются у автора.

brief.json​

Артефакт необязательного шага 0: что автор дал на вход и что предложила модель. В комплект студента не попадает — на раннер и на проверки не влияет.

ПолеЧто содержит
lectureтекст лекции, до 60 000 знаков
wishesпожелания автора свободным текстом
proposalпредложение модели: topic, preset_id или domain_text, objectives, total, wishes, rationale, warnings
appliedперенесено ли предложение в форму шага 1

Идентификаторы тем в proposal.objectives совпадают с каталогом студии, если тема из него, и начинаются на custom-, если модель предложила свою.

domain.json​

ПолеЧто содержит
descriptionописание базы для студента
ddlSQL создания схемы
objectivesтемы курса: id, title, count: [min, max], required
totalсколько всего заданий: [min, max]
notesпожелания автора к данным и покрытию, уходят в промт
table_docsпояснения к таблицам и колонкам для студента

content_hash считается по всей области, кроме table_docs: тексты для студента можно править, не пересобирая практику.

tasks.json​

ПолеЧто содержит
id, titleидентификатор и короткое имя
kindselect, dml или ddl
business_statementформулировка для студента в Markdown, без имён таблиц, но со всем нужным для решения
statementточная формулировка в Markdown; по ней строятся проверки
objectivesидентификаторы тем курса
difficulty1–3
resultожидаемая форма результата для select
state_tablesтаблицы, состояние которых сравнивается, для dml
require_constructs, forbid_constructsограничения на текст решения

source_hash считается по всему заданию, кроме business_statement.

materializations/<task_id>.json​

ПолеЧто содержит
task_id, source_hashк какой версии задания это относится
solution_sqlэталонное решение
variantsописания вариантов данных: id, kind, seed, quotas
checksсписок проверок: type, section, params
expectedожидаемый исход эталона на каждом варианте
negativesнамеренно неверные решения: label, sql

Элемент expected содержит своё для каждого типа задания: result_hash и result_rows для select, table_state_hashes и table_state_rows для dml, schema_snapshot для ddl.

Проверки​

typeЧто сравнивает
schemaнабор и порядок колонок
cardinalityчисло строк: одна, много, допустимо ноль
result_exactрезультат построчно
result_hashхэш нормализованного результата
table_stateсостояние таблиц после dml
db_schemaструктуру схемы после ddl
sql_constraintsобязательные и запрещённые конструкции

Поле section делит проверки на public и sealed. Открытые студент видит по именам, скрытые существуют только на бэкенде.

state.json​

{
"domain_approved": "9d6654cf…",
"tasks_approved": "39bc8483…",
"tasks_domain_hash": "9d6654cf…"
}

Три хэша, из которых складывается вся логика «устарело»: что утверждено как область, что утверждено как набор заданий и к какой версии области этот набор собран. Материализация сверяет свой source_hash с текущим заданием сама.

Нормализация результата​

Перед сравнением результат канонизируется:

  • порядок строк приводится к каноническому, если задание не требует конкретного;
  • числа округляются до объявленной точности — 40 и 40.00 равны;
  • имена колонок сравниваются без учёта регистра;
  • NULL отличается от пустой строки и от нуля.

Одна и та же функция нормализации используется и при записи ожидаемых результатов, и при проверке решения студента, и при построчном сравнении в интерфейсе.

Совместимость​

Версия движка данных записана в манифесте пака. Несовместимость по мажорной версии — отказ раннера запускать пак, а не молчаливое расхождение результатов. Имена токенов темы — отдельный контракт со своей версией в theme.json.