Правила работы — `AGENTS.md` в корне репозитория. Репозиторий: `https://github.com/ochenstarik-ui/kagent`, база — `main` Ветка: новая от свежего `main`, `wt/b5-measurability-ci` Выполняется **после** задачи `b4-drift-check-quality.md`. ## Предусловие Этапы 0.9.0 и 0.9.1 влиты в `main`, сборка зелёная. Скрипты `drift_check.py`, `roadmap_status.py` и `eval_suite.py` лежат в `main`, но ни один из них не вызывается из непрерывной интеграции. То есть вычисляемый статус пока остаётся декларацией, а сами скрипты — недостижимым кодом, ровно тем дефектом, который они созданы обнаруживать. **Начинать только после того, как задача b4 принята.** До неё `drift_check.py` даёт 21 находку при одной настоящей и пропускает три реальных мёртвых модуля. Подключение такой проверки как блокирующей остановит любой пуш по ложным поводам и пропустит настоящие. Если b4 не выполнена — останови работу и сообщи. Ослаблять проверку, чтобы подключить её раньше срока, запрещено. ## 1. Подключить к непрерывной интеграции В `.github/workflows/ci.yml`: - шаг `python scripts/drift_check.py` в существующий job `python`. Сборка падает при обнаружении расхождения. Набор проверок — из спецификации, раздел 41.5: заявленная возможность без проходящего доказательства; модуль в дереве, недостижимый ни из одной точки входа; задокументированный endpoint, отсутствующий в таблице маршрутов; задокументированная переменная окружения, которая нигде не читается; пользовательское изменение без записи в `CHANGELOG.md`; архитектурное изменение без ADR; - отдельный job `measurability`: выполняет `roadmap_status.py`, публикует полученный `ROADMAP.md` как артефакт сборки и падает, если сгенерированный файл отличается от закоммиченного. Это и есть механизм, запрещающий ручную правку статусов; - `eval_suite.py` запускать в режиме, не требующем поставщика моделей. Пока набор состоит из черновых случаев, job проверяет только разбор контрактов и целостность набора, а не прохождение случаев. ## 2. Первый прогон будет красным Ожидаемо и правильно. `drift_check.py` после b4 обязан находить четыре модуля, не подключённых ни к одной точке входа: ``` services/nats/src/events.py services/auth/src/totp.py services/control-plane/src/db.ts packages/contracts/src/reasoning.ts ``` Если к моменту выполнения задача c1 уже принята, `db.ts` из списка уйдёт — он будет подключён к маршрутам. Остальные три останутся. **Не чинить эти модули здесь и не ослаблять проверку ради зелёного.** Правильное действие: убедиться, что проверка их находит, зафиксировать список в отчёте, завести отдельную задачу на решение по каждому — подключить или удалить. Чтобы ветку можно было влить, добавь файл известных расхождений `docs/known-drift.json`. Запись содержит путь, причину, дату и задачу, в которой расхождение снимается. Запись без задачи или с истёкшим сроком роняет сборку. Список может только сокращаться — добавление записи в него требует отдельного обоснования в отчёте. ## 3. Проверить, что механизм работает Недостаточно, чтобы job был зелёным. Нужно показать, что он ловит то, ради чего создан: - вручную изменить статус в `ROADMAP.md`, показать красный прогон, откатить; - добавить в дерево модуль, не подключённый ни к одной точке входа, показать, что `drift_check.py` его находит, удалить; - внести пользовательское изменение без записи в `CHANGELOG.md`, показать, что проверка это ловит, откатить. Все три демонстрации привести в отчёте со ссылками на прогоны. ## Чего не делать - наполнение случаев оценки настоящими снимками репозиториев; - метрики автономности и гейт релиза по ним; - исправление найденных расхождений. ## Критерий приёмки - `drift_check.py` и `roadmap_status.py` вызываются из CI; - расхождение сгенерированного и закоммиченного `ROADMAP.md` роняет сборку — показано прогоном; - три демонстрации из пункта 3 выполнены; - прогон зелёный при списке известных расхождений, содержащем только зафиксированные модули, у каждого — причина и задача; - ссылки на прогоны приложены. ## Границы `.github/workflows/ci.yml`, `scripts/*`, `docs/capabilities.json`, `docs/known-drift.json`, `ROADMAP.md`. Ничего в сервисах не трогать.