Один репозиторий на GitHub вырос с 327 звёзд до 30 тысяч за четыре дня, а моя система мониторинга трендов этого вообще не заметила, потому что была заточена ловить только новое, а не следить за тем что уже однажды нашла. Я добавил velocity-трекинг: раз в два часа система обновляет звёзды у последних 150 репозиториев и кричит, когда у кого-то всплеск. И пока чинил, вскрылось ещё три беды подряд — мёртвый токен на проде, который четыре дня резал все запросы в 80 раз, спам одним и тем же репо каждые два часа и кривой порог срабатывания. Вся работа заняла часов пять, размазанных по неделе, и это как раз тот случай когда настоящая автоматизация — это не «написал и работает», а «написал, вскрылось, починил, вскрылось снова».
С чего всё началось
Утром не пришёл дайджест. У меня ORYON каждый день присылает в Telegram сводку по трендам, и вот в этот раз тишина, а параллельно я смотрю и спрашиваю — слушай, а почему мы вообще прохлопали mempalace, репозиторий который сейчас у всех на слуху и висит с 30 тысячами звёзд? Полезли в базу, и картина оказалась смешная и грустная одновременно: mempalace система действительно нашла, ещё четвёртого числа, только тогда у него было всего 327 звёзд, его аккуратно записали как «новый интересный репо» и больше к нему не возвращались.
А почему не возвращались, спросите вы? Да потому что коннектор по звёздам GitHub устроен ровно так, как устроены почти все подобные штуки: он ищет новое. Создан меньше недели назад, набирает звёзды — ага, кандидат, забираем. А дальше работает дедупликация по внешнему идентификатору, которая говорит «этот репо мы уже видели, второй раз не трогаем». Логично же, никто не хочет дублей. И вот в этой логике сидит дыра размером с тот самый mempalace: репозиторий, который ты однажды зацепил с 327 звёздами, может вырасти в сто раз, а ты этого не увидишь, потому что повторно его уже не смотришь. Скользящее окно ловит события в окне, а не рост того что в окно когда-то попало.
Это классическая слепая зона, и она универсальная, не только про GitHub. Любой мониторинг, который думает категориями «новое появилось», по умолчанию слеп к «старое внезапно взорвалось». А взрывается-то как раз чаще старое, потому что чтобы дорасти со 327 до 30000, нужно несколько дней, и всё это время оно лежит у тебя в базе помеченное как «уже обработано».
Что писали под капотом
Дальше я скинул задачу в Claude Code, и мы сели разбирать. Идея простая: раз в два часа берём топ-150 репозиториев из тех что уже собраны, дёргаем по каждому актуальное число звёзд, сравниваем с прошлым замером и если прирост заметный — шлём алерт. Посчитали лимиты: 150 репозиториев каждые два часа это 1800 запросов в день, около 15 процентов от часового лимита GitHub, с запасом. Заодно прикрутили дайджесту повтор, чтобы он не молчал когда Telegram отвалился по таймауту, а пробовал ещё раз.
Первый деплой упал сразу, и не из-за логики, а из-за докера — старый процесс планировщика не убился, новый не поднялся, гонка состояний. Перезапустили без пересборки, и всё поднялось. Первый прогон velocity прошёл по накопленным за две недели данным, и пошли первые всплески. Тогда же добавили обогащение: система тянет README репозитория и через LLM пишет короткое человеческое описание — что это вообще такое, почему взлетает, как сделать простой аналог и как посложнее. Это уже не «вот ссылка, разбирайся сам», а готовый бриф.
И вот тут я задал вопрос, который, как потом выяснилось, был правильным: а что если за прогон случилось 25 всплесков, а мы шлём только три? Двадцать два потеряем. Сели думать про лимит на алерты, и это оказалось не такое тривиальное решение как кажется.
Решение про лимит алертов
Вариантов было четыре: три, пять, семь или вообще без лимита. Без лимита отпало сразу, потому что Telegram не любит когда в один чат льют сообщения очередью, безопасный темп там примерно одно сообщение в секунду, и если высыпать 25 штук разом, часть просто не дойдёт или дойдёт с задержкой. Но и резать до трёх жалко, теряешь данные. Остановились на семи с сортировкой по абсолютному приросту звёзд, то есть сначала самое крупное. Семь алертов это семь секунд отправки, безопасно, а психологически больше человек уже и не читает, пролистывает. Так что тут ограничение в первую очередь не техническое, а про внимание читателя.
Грабля первая: мёртвый токен
Через пару дней лезу в логи, а там все 150 запросов velocity возвращают 429, Rate Limit. То есть фича написана, задеплоена, крутится — и ничего не делает, потому что упирается в потолок. Стали копать, и оказалось что токен GitHub на проде попросту не задан. По скриншоту из настроек GitHub видно: у токена статус «Never used». То есть его создали, но на сервер так и не положили, и он четыре дня пролежал девственно чистый, пока система ходила в GitHub анонимно.
А анонимно GitHub даёт 60 запросов в час. С токеном — 5000. Разница в 80 с лишним раз, и вся моя красивая velocity-логика просто захлёбывалась на первых же десятках репозиториев. Это вообще отдельный жанр граблей: код есть, логика верная, тесты что-то там показывают, а на проде переменная окружения не доехала до контейнера, и фича тихо мертва. У меня такое уже было с другой системой, и там тоже всё упиралось не в код, а в реальные правила окружения — я про это писал в истории про MAKO, где инфраструктура честно крутилась круглые сутки, но пока не наступишь на грабли, настоящих правил не узнаешь.
Заменили токен на свежий, перезапустили воркер, и следующий прогон показал догоняющий режим: проверено 150, обновлено 130, всплесков 28, отправлено 7. Сразу видно сколько накопилось за дни простоя.
Грабля вторая: кривой порог
Дальше я ловлю баг в самих алертах: приходит сообщение, что репо выросло, триггер сработал по приросту больше 500, а в тексте показано «плюс 35 за два часа». Где логика? А логика такая: порог считался по накопленному приросту с прошлого алерта, репозиторий за это время реально набрал свои +500, а вот за последние два часа было всего +35, и именно эти +35 и показывались. То есть триггер про одно, а показ про другое, и человек видит ерунду.
Claude сам нашёл этот баг и сам предложил фикс. Абсолютный порог в 500 звёзд это вообще плохая идея, потому что для репо с 30 тысячами звёзд 500 это шум, а для репо с двумя сотнями это космос, которого никогда не случится. Переписали на процент от числа звёзд на момент последнего алерта: порог равен 15 процентам, но не меньше 100 в абсолюте для совсем маленьких. Так репозиторий с 3462 звёздами получает порог в 520 и не дёргает на каждые +35, и при этом крошечный репо всё ещё может дать сигнал на сотне звёзд.
Грабля третья: спам
Последнее всплыло ещё через несколько дней: один репозиторий, пока растёт, шлёт алерт каждые два часа. Технически всё верно, он же реально растёт, порог реально пробивается. Но человеку это спам, он видит одно и то же название десять раз и перестаёт открывать вообще. Думали редактировать старое сообщение вместо нового, но кто полезет наверх по истории чата искать обновлённую цифру. В итоге сделали два механизма: в Telegram — кулдаун на 24 часа по конкретному репозиторию, чтобы он не мелькал чаще раза в сутки, а на сайте — обновление существующей записи вместо новой, чтобы там всегда лежала одна актуальная строчка по каждому репо, а не пять дублей.
Кстати про сайт. Когда я сказал что бот пишет в личку и друзья этих алертов не видят, первая оценка была «ну это дня два-три работы, эндпоинт, страница, навигация». Я настоял на упрощении, и в итоге это заняло час-полтора: появилась таблица всплесков, страница в интерфейсе и иконка в навигации. Часто оценка раздувается не потому что задача большая, а потому что заранее накручиваешь сложность.
Роль AI в этой истории
Я тут не писал код руками, и никогда этого не скрываю. Я заметил проблему («почему прохлопали?»), задавал вопросы про лимиты и про потерю данных, давал доступы и токены, настаивал на упрощении там где оценка раздувалась. А Claude Code сам предложил velocity-трекер, написал его, сам обнаружил что токена нет в окружении, сам нашёл собственный баг с порогом и починил его. Это и есть нормальная работа с ai агентом: человек держит рамку, направление и здравый смысл, а нейросеть выполняет и даже ловит свои же косяки — тем же манером я через Claude Code собрал целую цепочку агентов, которая превращает рабочие логи в контент. Когда мне говорят что это «не настоящая разработка» — ну, результат-то работает, и события класса mempalace система больше не пропускает. Вот и делайте выводы.
Цифры
- mempalace: 327 звёзд (7 апреля) → 30000 звёзд (11 апреля), без velocity невидимо
- GitHub без токена: 60 запросов в час; с токеном: 5000 запросов в час
- 150 репозиториев × каждые 2 часа = 1800 запросов в день = около 15% лимита
- Токен пролежал 4 дня со статусом «Never used», все запросы шли анонимно
- Прогон после фикса токена: проверено 150, обновлено 130, всплесков 28, отправлено 7
- Порог после фикса: репо с 3462 звёздами больше не спамит на +35, порог ≥15% = +520
- Кулдаун 24 часа на репозиторий + обновление одной записи в интерфейсе вместо дублей
Выводы
Если у вас есть любая система мониторинга, проверьте чем она по сути меряет: «появилось новое» или «изменилось существующее». Это разные вопросы, и почти всегда автоматизация умеет отвечать только на первый, а самое интересное прячется во втором. Скользящее окно по определению слепо к тому что выросло уже после того как попало в базу.
И второе, более приземлённое: автоматизация процессов через ии — это не разовый акт творения, после которого можно забыть. Это живой организм, который надо обслуживать, потому что реальные правила окружения вылезают только в бою. Мёртвый токен, который четыре дня тихо режет лимиты, кривой порог, который шлёт одно а показывает другое, спам по одному и тому же репо — ни одну из этих трёх вещей нельзя было предусмотреть на этапе «написали фичу». Их можно было только встретить, посмотреть в логи и починить, ровно как три «бесплатных» аккаунта Apify в том же ORYON, которые тихо жрали деньги, пока я не заглянул в счёт. Так оно и работает: написал, вскрылось, починил, вскрылось снова.