haiodo.blog
Минус 57% длинных комментариев. Мой хук тут почти ни при чём

Минус 57% длинных комментариев. Мой хук тут почти ни при чём

Неделю назад я нашёл, что правила про комментарии не доходят до субагентов, и починил это. Перемерил по 11 тысячам правок из транскриптов Claude: падение на 57% дала смена модели, правила на старте не изменили почти ничего. Работает другой хук - тот, что показывает находку сразу после правки.

Что такое hum1izer


hum1izer - CLI на Go. Ищет канцелярит, штампы и следы нейросети в прозе, комментариях к коду и сообщениях коммитов. Считает только то, что берётся грепом и арифметикой: правила лежат в YAML, плюс ритм, номинальность и балл чистоты от 0 до 100. Текст он не пишет. Он показывает находку с номером строки и говорит, что с ней делать, а решает человек.

Это третий пост про слоп. В первом, “Длинное тире не выдаёт нейросеть. Я проверил на корпусе”, я мерил признаки машинного текста на корпусе и выяснил, что инструмент ловит канцелярит, а не авторство. Во втором, “В погоне за нейрослопным кодом”, искал слоп в самом коде: детектора не нашёл, нашёл одну устойчивую величину - глубину вложенности. Теперь вопрос практический: помогает ли hum1izer агенту писать чище, если встроить его прямо в работу агента.

hum1izer post.md              # проза: отчёт с рекомендациями
hum1izer --code ./src         # комментарии в коде
hum1izer --code .             # то же плюс последние 20 коммитов
hum1izer tui ./src            # разобрать находки руками, три панели

Код у меня сейчас пишут Claude и его субагенты, а комментарии они пишут по-своему: три-пять строк пересказа того, что делает функция, история правок прямо в коде, баннеры из =====, тег ponytail: от плагина в начале строки.

Для этого есть одна команда:

hum1izer install --claude --hooks

Она ставит скилл и прописывает в ~/.claude/settings.json три хука:

СобытиеЧто делает
SessionStartкладёт в контекст свод правил: комментарий 1-2 строки, отвечает “почему”, а не “что”, без баннеров и тегов инструментов
SubagentStartто же самое каждому субагенту
PostToolUse на Edit и Writeпроверяет изменённые строки файла и возвращает находки агенту

Последний срабатывает сразу после правки. Если находок нет, он молчит. Если есть, агент получает такое:

hum1izer found the following in .../Session.swift. Address the findings:
fix the block or mark `fix --block <id> --keep` if the rule fired for nothing.

## .../Session.swift:190-192
block 5185d5332088 | `swift` | comment | weight 4

- **Tool tag in a comment** (hard, line 192) - Drop the prefix, keep the thought
- **Long comment** (line 190) - Fit in 2 lines: keep the reasoning, move the description to docs

// Тот же стенд и то же пространство - продолжаем прошлую сессию: вход
// заново стирает последний чат, и восстановление экрана не проверить.
// ponytail: аккаунт не сверяем, в прогоне он один.

Дальше агент либо переписывает блок, либо помечает его --keep, если правило сработало зря.


Откуда задача

Хуки стоят у меня с 17 сентября. 29 сентября я решил проверить, помогают ли они, и прошёлся по транскриптам ~/.claude/projects. Вышло 9937 правок кода. Метрика простая: сколько блоков с находками приходится на 100 добавленных строк комментариев. Все группы прогоняются одной версией hum1izer.

ГруппаСтрок комментариевДлинных на 100 строк
основная сессия, до хуков18333.82
основная сессия, с хуками6251.76
субагенты, до хуков69089.25
субагенты, с хуками137827.89

На субагентов приходилось 95% правок. Длинные комментарии они писали в 2.5-4.5 раза чаще основной сессии, а хуки сократили это всего на 15%.

Причин нашлось две.

SessionStart для субагентов не срабатывает. Это есть в документации Claude Code, в разделе про хуки субагентов. Правила нашлись в транскрипте одного субагента из 1020. Остальные узнавали о правиле только из находки, то есть уже после того, как его нарушили.

Кеш показанных блоков вёлся по session_id. Хук не повторяет блок, который уже показывал, иначе контекст растёт на каждой правке. Но субагент приходит с session_id родителя и отдельным agent_id. Блок, который увидел родитель, субагенту молча не показывался.

Инженер с планшетом за дверью, правила висят снаружи, роботы работают внутри

Починил так: добавил SubagentStart, который отдаёт те же правила, а ключом кеша сделал session_id плюс agent_id. Стоит это около 1.5 KB контекста на каждого субагента.

Критерий я записал заранее, в задаче: через неделю перемерить. Если у субагентов длинных комментариев станет меньше не больше чем на 15%, правила на старте не помогли, и надо искать другой путь.


Неделя спустя: минус 57%

Тот же скрипт, та же версия hum1izer для всех групп. За неделю правила получили 505 субагентов, они сделали 1073 правки и добавили 4739 строк комментариев.

СубагентыСтрок комментариевДлинных на 100 строк
до хуков69089.25
только проверка после правки138997.94
плюс правила на старте47393.40

Минус 57% к прошлой неделе. Критерий выполнен с запасом, можно закрывать задачу.


Только модель тоже сменилась

В ту же неделю субагенты в одном проекте, дальше проект А, переехали с sonnet-5 на opus-5-5 и sonnet-5-5. В другом, проекте Б, остался sonnet-5. Если группы различаются не одним хуком, сравнивать их целиком нельзя. Разбил по модели:

СубагентыМодельСтрокДлинных на 100 строк
только проверка после правкиsonnet-5137457.99
плюс правила на стартеsonnet-513877.43
плюс правила на стартеopus-5-531151.67

На одной и той же модели правила на старте дали минус 7%. Это ниже моего же порога. В проекте Б на sonnet-5 стало даже хуже: было 6.31, стало 7.04.

В проекте А, где сменилась модель, было 10.23, стало 1.69. Вот откуда минус 57%.

Старый и новый робот за чертёжными столами: у старого длинный свиток, у нового короткая записка

Правила в начале сессии первый вариант комментария почти не меняют. Модель меняет. Не разбей я данные по модели, записал бы чужой результат себе в победы.


Где хук всё-таки работает

Первый замер смотрит на черновик - комментарий в момент правки, до того как агент увидел находку. Но проверка после правки для того и стоит, чтобы черновик исправить. Поэтому я посчитал второе: что агент сделал с блоком после находки в том же транскрипте. Каждый блок учитывается один раз.

Субагенты, sonnet-5БлоковИсправилПометил --keepНе тронул
до 28 сентября233642%2%54%
неделя после18993%0%5%

Модель та же, а исправляет больше чем вдвое чаще. Это не смена состава проектов: внутри проекта Б было 35%, стало 91%, внутри проекта А было 50%, стало 95%.

Чей это вклад, сказать не могу. Между двумя замерами вышли три правки сразу: хук стал отдавать только новые находки, а не весь файл (90-й перцентиль вывода упал с 6745 до 3469 символов), субагенты стали получать правила, у каждого субагента появился свой кеш. По этим данным их не разделить.

С новыми моделями моя эвристика “исправил” не справляется: она ищет правку, в которой старый текст содержит первую строку блока. По ней opus-5-5 исправил 27% блоков, sonnet-5-5 - 6%. Тогда я прогнал hum1izer по файлам в их нынешнем виде. Из 322 блоков, показанных субагентам за неделю, 285 сейчас чистые, 22 всё ещё с находкой, у 15 файла уже нет. У opus-5-5 чистые все 79 из оставшихся. Кто их почистил - сам субагент, основная сессия или я руками - транскрипт не говорит.


Что дошло до git

Транскрипт показывает черновик, git показывает то, что я закоммитил. Взял только свои коммиты: в проекте А за неделю половина коммитов от коллеги, а его сессий у меня нет. Прогнал добавленные строки.

ПроектПериодСтрок комментариевДлинных на 100Прочих на 100
А17-28 сентября30590.920.39
А28 сентября - 5 октября53980.520.52
Б17-28 сентября26992.561.19
Б28 сентября - 5 октября15062.462.46

В коде, который дошёл до коммита, длинных комментариев в 3-11 раз меньше, чем в черновиках. Между правкой и коммитом их кто-то убирает: хук, основная сессия или я сам. Git этого не различает.

Но столбец “прочих” вырос. В проекте Б вдвое. Я посмотрел, за счёт чего.

Робот-клерк растягивает лист вширь, чтобы он влез между двумя полосами скотча

Long comment line - строка комментария длиннее 100 символов. В проекте Б за прошлую неделю таких было 3, за эту 21. В проекте А 26 из 28 “прочих” находок - это они. Агент получил правило “не больше двух строк” и выполняет его буквально: три строки по 80 символов становятся двумя по 120. Мысль та же, длина та же, проверка зелёная.

Это уже было. В первом посте агент склеил три строки в одну на 140 символов, и я добавил предел длины строки. Предел работает: такие строки он ловит. Но агент с этого начинает, а не заканчивает, и каждую такую строку приходится ловить уже после правки.

В посте про форму кода я писал, что порог, который нарушают слишком часто, агент научится игнорировать. Здесь он не игнорирует, а обходит: выполняет букву правила и не трогает то, ради чего оно написано.

На это есть своё правило, и хук его показывает. Но в черновиках opus-5-5 длинных строк 0.77 на 100 строк комментариев против 0.36 у sonnet-5 неделей раньше: блоков длиннее двух строк у него меньше, зато строки шире.


Итог

Метрика “находки hum1izer” оценивает сам hum1izer. Следующий шаг в задаче - слепая выборка: 30-50 комментариев из каждой группы, которые оцениваю я, не зная, откуда они.