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

Bidirectional Check · скрипт двусторонней проверки

Принцип четырёхсторонней выверки имеет силу, только если он проверяется автоматически. В репозиторий встроен scripts/bidirectional-check.py, собирающий три направления — «вопросы → курс», «программа → вопросы», «покрытие карточками» — в одну команду. Семантический уровень «курс объясняет неверно» по-прежнему остаётся за ручной выверкой (правила — в four-alignment.ru.md).


Terminal window
pnpm run check:alignment # из корня репозитория; по умолчанию сканирует examples/dev-intro/
pnpm run check:alignment -- examples/my-topic/ # просканировать указанную тему
# или напрямую через Python
python3 scripts/bidirectional-check.py examples/my-topic/

Коды выхода: 0 = всё зелёное (△ «упомянуто вскользь» — предупреждение, не блокирует); 1 = есть ✗ (не объяснено / не покрыто / не сходится сверка); 2 = каталог темы не существует. Можно напрямую вешать в CI / скрипты как порог.

Пример вывода (контрактный режим) — реальный вывод скрипта, оставлен на китайском без перевода:

扫描主题: examples/dev-intro
题数: 10 / 闪卡: 4 / 课程文件: ['git-basics.html', 'linux-basics.html']
考点排布表: 4 个考点(契约模式)
方向 1 · 题 → 课
✓ 暂存区: 课程 14 次命中
方向 2 · 大纲 → 题(排布表对账)
✓ EP-01 暂存区: single×3, multi×1, judge×1 共 5 题,day D1 一致
✓ 闪卡数对账: 表合计 = 实际 = 4 张
方向 3 · 闪卡覆盖
✓ 暂存区: 闪卡已覆盖
○ 相对路径: 排布表声明 0 卡(了解级不配卡),跳过
结论: 全绿(△ 为略提警告,不算失败)

Контрактный режим: таблица распределения пунктов экзамена

Заголовок раздела «Контрактный режим: таблица распределения пунктов экзамена»

Если в MISSION.md темы есть раздел «## 考点排布表» (таблица распределения пунктов экзамена), включается контрактный режим — пункты экзамена берутся из таблицы, а не из встроенных ключевых слов, поэтому для смены темы скрипт править не нужно:

## 考点排布表
| 考点id | 考点 | 深度 | 题型×题量 | day | 闪卡数 |
|--------|------|------|-----------|-----|--------|
| EP-01 | 暂存区 | 掌握 | single×3, multi×1, judge×1 | D1 | 1 |

Заголовки столбцов выше (考点id / 考点 / 深度 / 题型×题量 / day / 闪卡数, то есть «id пункта / пункт / глубина / тип×количество / день / число карточек») — часть контракта данных и остаются китайскими.

  • Столбец «考点» (пункт экзамена) содержит ключевые слова: направления 1/3 ищут их как подстроки (подсчёт вхождений в тексте курса без пробелов; совпадение с front/back/topic карточек), поэтому это должно быть слово, реально встречающееся в курсе и в формулировках вопросов.
  • «深度» (глубина): 掌握 (владение) / 理解 (понимание) / 了解 (знакомство) — справочно для человека, машиной не оценивается.
  • «闪卡数» (число карточек) = 0 означает, что программа не назначает карточек: направление 3 пропускает такой пункт (обычно для уровня «знакомство»); при этом сумма столбца карточек по всем строкам обязана равняться фактическому числу карточек в flashcards.json.

Правила контрактного режима:

  • Направление 1 (вопросы → курс): ключевое слово каждого пункта должно встречаться в HTML курса (без пробелов) ≥3 раз — тогда оно покрыто; 1–2 раза — △ упомянуто вскользь; 0 раз — ✗ нужно обязательно дополнить курс.
  • Направление 2 (программа → вопросы, сверка): если у вопроса в examPoint указан несуществующий id пункта — ✗; непомеченные вопросы получают лишь напоминание △ и в сверке не участвуют (само поле необязательное, но в контрактном режиме его рекомендуется ставить каждому вопросу). Фактическое число вопросов по каждому пункту и распределение по типам обязаны совпадать со столбцом «题型×题量» (тип×количество); day вопроса обязан совпадать со значением day в строке пункта; итог по карточкам сходится со таблицей. Любое расхождение — ✗.
  • Направление 3 (покрытие карточками): для пунктов, у которых заявлено ≥1 карточки, ключевое слово должно найтись в front / back / topic хотя бы одной карточки.

Темы, в чьём MISSION.md нет таблицы, откатываются на сканирование частотных слов: скрипт подсчитывает встроенные ключевые слова (слова пунктов git/Linux из dev-intro), встречающиеся ≥3 раз в формулировках и пояснениях, затем выполняет направления 1/3 и ставит предупреждение ⚠. Старые темы работают как раньше, но таблицу стоит добавить — в резервном режиме нет сверки направления 2, а набор слов-маркеров принадлежит dev-intro.


Обязательно после любого изменения артефактов (подробнее — в разделе «Когда запускать проверку» у four-alignment.ru.md):

  1. после генерации нового курса
  2. после изменения examPoint / day / числа вопросов
  3. после правки flashcards.json
  4. после прогона очередного глубокого разбора ошибок через grill CLI

Скрипт делает только грубое сканирование и не заменяет ручное рецензирование. Он ловит жёсткие пробелы вида «курс вообще не объясняет X» или «число вопросов не совпадает с программой», но не поймает «курс объясняет X, но неверно» и не отличит «вопрос и курс используют одно слово в разных смыслах». Считайте его первой линией обороны; сложная семантическая сверка остаётся на совести автора темы.

Чёрно-ящичные тесты контракта лежат в apps/quiz-app/scripts/lib/bidirectional-contract.test.mjs (три fixture-темы: корректная сверка с таблицей / откат без таблицы / блокировка при расхождении) и автоматически запускаются pnpm test.

Источник истины — scripts/bidirectional-check.py в репозитории.