Skip to content

feat(ci): упавший прогон называет тесты в самом PR - #1383

Merged
ArtVsMark merged 3 commits into
mainfrom
agent/ci-failures-in-pr-comment
Aug 27, 2026
Merged

feat(ci): упавший прогон называет тесты в самом PR#1383
ArtVsMark merged 3 commits into
mainfrom
agent/ci-failures-in-pr-comment

Conversation

@ArtVsMark

Copy link
Copy Markdown
Owner

Логи джоба и артефакты прогона живут в скоупе actions, на который прокси
облачной сессии отвечает 403. То есть junit-отчёт отвечает «какой тест упал»
только владельцу, у которого есть веб-интерфейс, а тому, кто чинит из
облака, достаётся одна строка — Process completed with exit code 1. Цена
измерена сегодня: причину красных macOS-джобов пришлось искать тремя полными
прогонами набора локально, подбирая условия.

Открытый канал ровно один — комментарий PR. Отдельный джоб report-failures
(не шаг в матрице: девять джобов гонялись бы за одним комментарием)
разбирает отчёты всех комбинаций и держит в PR ОДНУ сводку, обновляемую по
скрытому маркеру.

Границы, без которых это стало бы шумом: только на pull_request и только
при падении test; поимённо названы первые 25 упавших, остальные — числом
(молчаливая обрезка читалась бы как «это всё»); красный прогон без единого
упавшего теста получает отдельную формулировку — он означает смерть до тела
тестов.

Closes #1382

Работа сделана вместе: @ArtVsMark — постановка, решения и приёмка; Claude Code — реализация.

Логи джоба и артефакты прогона живут в скоупе `actions`, на который прокси
облачной сессии отвечает 403. То есть junit-отчёт отвечает «какой тест упал»
только владельцу, у которого есть веб-интерфейс, а тому, кто чинит из
облака, достаётся одна строка — `Process completed with exit code 1`. Цена
измерена сегодня: причину красных macOS-джобов пришлось искать тремя полными
прогонами набора локально, подбирая условия.

Открытый канал ровно один — комментарий PR. Отдельный джоб `report-failures`
(не шаг в матрице: девять джобов гонялись бы за одним комментарием)
разбирает отчёты всех комбинаций и держит в PR ОДНУ сводку, обновляемую по
скрытому маркеру.

Границы, без которых это стало бы шумом: только на `pull_request` и только
при падении `test`; поимённо названы первые 25 упавших, остальные — числом
(молчаливая обрезка читалась бы как «это всё»); красный прогон без единого
упавшего теста получает отдельную формулировку — он означает смерть до тела
тестов.

Closes #1382

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Artem Markitanov <86671904+ArtVsMark@users.noreply.github.com>
@ArtVsMark ArtVsMark added the merge-when-green Согласие смержить без автора: авто-мерж включится, как позеленеет label Aug 27, 2026
@ArtVsMark
ArtVsMark enabled auto-merge (squash) August 27, 2026 11:34
@claude claude Bot added area/ci CI/CD и скрипты (.github/, scripts/) enhancement New feature or request labels Aug 27, 2026
@ArtVsMark
ArtVsMark merged commit 98a5ec9 into main Aug 27, 2026
18 checks passed
@ArtVsMark
ArtVsMark deleted the agent/ci-failures-in-pr-comment branch August 27, 2026 13:40
ArtVsMark added a commit that referenced this pull request Aug 27, 2026
`.gitignore` игнорировал `.claude/*` целиком — исключение стояло только на
`settings.json`. Настройки честно объявляли `SessionStart`, а файла хука в
репозитории не было: он существовал в рабочей копии того окна, где его
написали. В чистом клоне и в CI механизма не существовало вовсе, то есть
второй рубеж не действовал ни у кого, кроме одного окна.

Поймано прогоном на всех девяти комбинациях матрицы: тест звал хук по пути и
получал код 2 — «файла нет». Диагноз пришёл сводкой упавших тестов прямо в
PR, той самой, что появилась в #1383: логи Actions облачной сессии
по-прежнему недоступны, а имя теста было названо через минуту после прогона.

Класс закрыт проверкой: `check_rules_digest.py` теперь смотрит не только, что
хук объявлен в настройках, но и что файл лежит в репозитории; отдельный тест
спрашивает git, отслеживается ли он.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Artem Markitanov <86671904+ArtVsMark@users.noreply.github.com>
ArtVsMark added a commit that referenced this pull request Aug 27, 2026
* feat(rules): второй рубеж — правила читаются окном на старте

Первый рубеж — механизм: гейт краснеет, и правило действует независимо от
памяти окна. Но механизмом покрыто 35 правил из 101 действующих; остальные
держатся тем, что окно про них знает, — а знать оно может лишь то, что
прочитало. `CLAUDE.md` формулирует немногие, указатель перечисляет заголовки
и следы, а сами утверждения живут в каталоге, куда в работе никто не заходит.

Дайджест закрывает зазор: утверждение каждого правила одной строкой,
`docs/agent/rules/DIGEST.md`. Хук `SessionStart` кладёт его в стартовый
контекст — то есть правила оказываются прочитанными раньше, чем окно успеет
что-нибудь нарушить. Порядок групп не алфавитный: сначала то, что не поймает
машина, потому что правило с гейтом окну помнить не обязательно; у группы с
гейтом утверждения нет вовсе — место в стартовом контексте не бесконечно.

Ответ каталогу заодно стал полным: нерассмотренных было 43 (30 записей плюс
13 правил без записи вовсе), стало ноль. Разбор шёл по фактам, а не по
памяти: каждый ответ проверен grep'ом по предмету, отсюда и рост гейтов с 9
до 35 — не новые механизмы, а увиденные наконец старые. «Ничем не
обеспечено» — 60, и это очередь на автоматизацию.

Указатель правил впервые за месяц пересобрался: он считал своими следы,
ведущие в каталог (правила 049, 140, 142 родились там и держатся его
файлами), падал на «след ведёт в никуда» и потому застрял на числах
месячной давности — 89 правил и 9 гейтов. Владельца следа теперь задаёт
абзац, а не файл целиком.

Механизмы: `check_rules_digest.py` (на каждый PR, без сети — дайджест не
разошёлся с `.rules/bindings.json`, хук объявлен) и
`generate_rules_digest.py --check` в ночном обходе, где есть клон каталога.

Часть #1384 — второй рубеж и полнота ответа; покрытие механизмами
непокрытых правил идёт отдельно.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Artem Markitanov <86671904+ArtVsMark@users.noreply.github.com>

* fix(rules): хуки харнесса живут в репозитории, а не в рабочей копии

`.gitignore` игнорировал `.claude/*` целиком — исключение стояло только на
`settings.json`. Настройки честно объявляли `SessionStart`, а файла хука в
репозитории не было: он существовал в рабочей копии того окна, где его
написали. В чистом клоне и в CI механизма не существовало вовсе, то есть
второй рубеж не действовал ни у кого, кроме одного окна.

Поймано прогоном на всех девяти комбинациях матрицы: тест звал хук по пути и
получал код 2 — «файла нет». Диагноз пришёл сводкой упавших тестов прямо в
PR, той самой, что появилась в #1383: логи Actions облачной сессии
по-прежнему недоступны, а имя теста было названо через минуту после прогона.

Класс закрыт проверкой: `check_rules_digest.py` теперь смотрит не только, что
хук объявлен в настройках, но и что файл лежит в репозитории; отдельный тест
спрашивает git, отслеживается ли он.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Artem Markitanov <86671904+ArtVsMark@users.noreply.github.com>

* fix(rules): стартовый хук печатает в любой консоли

Дайджест русский, а на Windows-раннере кодовая страница западноевропейская —
кириллицы в ней нет вовсе. `print` падал `UnicodeEncodeError`, хук возвращал
код 1, то есть старт сессии ронялся бы из-за кодировки вывода. На macOS и
Linux этого не видно: там UTF-8 по умолчанию.

Приём тот же, что у гейтов проекта (#1108): `reconfigure` обоих потоков в
UTF-8 раньше первой печати, собственной копией — хук обязан работать там, где
пакет не установлен.

Тест воспроизводит дефект `PYTHONIOENCODING=cp1252`, а не `cp1251`: в русской
консоли кириллица как раз кодируется, и cp1251 показал бы зелёное там, где
Windows красная. Проверено полу-откатом: без `_force_utf8_stdio` тест краснеет.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Artem Markitanov <86671904+ArtVsMark@users.noreply.github.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ci CI/CD и скрипты (.github/, scripts/) enhancement New feature or request merge-when-green Согласие смержить без автора: авто-мерж включится, как позеленеет

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ci): упавший джоб называет тесты там, где облачная сессия их видит

2 participants