Все записи
8 мин

AGPL-лицензия съела два дня работы — и мы написали свой астрономический движок

Building in Publicclaude codeai-агенты

Короче, история такая. Я два дня гонял полный процесс принятия решения по астрологической фиче для Картары: консилиум из восьми экспертов, двойной стресс-тест, два раунда дебатов между Claude и GPT, зафиксировал ценообразование, и только на первом же шаге кода всплыло, что библиотека, на которой всё это держалось, лежит под AGPL-3.0. А для коммерческого закрытого приложения с платежами это значит обязанность раскрыть весь исходный код любому, кто дёрнет твой API. Обходить не стали. Вместо одной готовой библиотеки под управлением Claude Code написали собственный астрономический движок с нуля за два дня, и расхождение по Солнцу, Асценденту и MC с эталонным astro.com получилось меньше 0.05 градуса.

Дальше расскажу подробно, потому что это та история, которую ни в одном туториале по вайбкодингу вы не встретите. Там учат как развернуть библиотеку, как подключить API, как задеплоить, а вот про юридический слой, который может убить два дня работы за одну строчку в classifier на PyPI, молчат все.

С чего всё началось

Задача была понятная: добавить в Картару (это мой Telegram Mini App с AI-персонажем) расчёт натальной карты. Юзер вводит дату, время и место рождения, мы считаем положения планет, домов и аспектов, а дальше отдаём это нейросети на интерпретацию. Классическая фича, ничего экзотического. Готовое решение для математики тоже было, библиотека Kerykeion, она как раз про натальные карты, активно используется, документация есть.

И вот я честно прошёл по всему своему процессу, как и положено для решения, где цена ошибки высокая. Сначала спека с шестью открытыми вопросами. Потом запустил консилиум, это когда восемь экспертов параллельно (четыре Claude и четыре GPT через Codex) разбирают решение каждый со своей колокольни: архитектор, прагматик, скептик, адвокат пользователя. Если интересно как этот метод устроен, я про него отдельно писал в SCD: собрал новый метод принятия решений из двух существующих, а про сам формат спора в AI-дебаты: два AI спорят, я выбираю победителя.

Оба скептика, и клодовский, и гэпэтэшный, жёстко встали на честность точности: мол, если юзер не знает точное время рождения, нельзя подсовывать ему полдень и бейдж «примерно», потому что это продажа ложной точности. Хороший заход, я его принял. Прошёл два раунда дебатов, выбрал модель ценообразования (дешёвый вход на 15 токенов с follow-up вместо премиума на 20 одним выстрелом), закрыл все шесть вопросов. Восемь экспертов отработали, спека обновлена, можно кодить. Всё по красоте.

Где всё сломалось

Шаг первый по коду: установить зависимости, собрать Dockerfile, прогреть кэш. И тут Docker build падает, а Codex-ревьюер, который у меня крутится параллельно с Claude, всплывает с диагнозом. pyswisseph лежит под AGPL-3.0 и тянется транзитивно как зависимость самой Kerykeion. То есть сама-то библиотека для карт лицензию явно не выпячивает, а вот её фундамент да.

Claude тогда написал ровно то, что я и сам подумал: «это прошло мимо консилиума и ресёрча, никто не проверил лицензию». Восемь экспертов по архитектуре и UX, шестнадцать мнений на круг, два раунда споров, и ни один не залез в classifier пакета на PyPI. Потому что все думали про то, как считать дома и аспекты, про ценообразование, про честность точности, а юридический слой просто выпал из поля зрения у всех сразу.

А что такое AGPL в коммерческом закрытом проекте, давайте проговорю простыми словами. GPL обязывает раскрыть код тем, кому вы программу раздаёте. AGPL идёт дальше и закрывает лазейку с сервером: если пользователь просто работает с вашим софтом по сети, через API, он уже имеет право потребовать весь исходник. То есть для платного приложения с пользователями это значит «откройте всю кодовую базу любому желающему». Для бизнеса это не вариант, тут даже думать нечего.

Почему не стали обходить

Костылей напрашивалось четыре, и мы их по очереди отсекли. Вынести библиотеку в отдельный open-source сервис-сайдкар — юридически серая зона, AGPL и так заразен через сеть, фокус сомнительный. Купить коммерческую лицензию у авторов — бюджет на это ноль, я на LLM-то трачу копейки, не то что на лицензии. Использовать бесплатный сторонний API для расчётов в проде — плацебо, ты просто переносишь зависимость и риск на чужой дядин сервер. Отложить астрологию вообще — это выкинуть в мусорку два дня консилиума и дебатов.

Остался пятый вариант, который сначала казался безумным: написать свой астрономический движок. И вот почему он выиграл, хотя звучит как «давайте изобретём велосипед». Это не часть одной фичи, это переиспользуемая инфраструктура. Натальная карта сегодня, а завтра транзиты, синастрия, прогрессии, и всё это сядет на тот же движок. То есть я не закрываю дыру в одной фиче, я строю фундамент, который понадобится ещё не раз — ровно так у меня уже было с одним модулем шаринга на семь продуктов. Поэтому астрономический движок поехал отдельной спекой, не вложенной в астрологию.

И тут случился момент, который я хочу зафиксировать отдельно, потому что он про меня и про то, как я работаю с ИИ. Claude начал прикидывать сроки в духе «2-3 дня на одно, 1-2 недели на другое», и сам же себя поймал: «про дни херня. Уже сохранил себе фидбэк про необоснованные оценки, и всё равно наступил. Реальная единица измерения — итерация ИИ, а не дни». Это второй раз за неделю, когда он сам признал, что оценки в человеческих днях для агентского кодинга не работают. Когда код пишет нейросеть, время меряется не календарём, а числом проходов, и это совсем другая математика.

Что собрали вместо библиотеки

Запустил новый консилиум уже под движок, те же восемь экспертов. И вот тут клодовский скептик закрыл свой же blind spot из первого раунда: «pyswisseph под AGPL подтверждён, проверил classifier на PyPI и репозиторий на GitHub, движок обоснован». Заодно проверили Flatlib, которую кто-то мог бы предложить как замену, и оказалось, что это MIT-обёртка над тем же AGPL-ядром, в рантайме всё равно тянет pyswisseph. Отпала.

Дальше под управлением Claude Code (это была версия Opus 4.6 с миллионным контекстом, плюс Codex-ревьюер в параллель) с нуля собрался весь пакет: загрузчик эфемерид, бэкенд на Skyfield, расчёт знаков, аспектов, углов, домов по системе Whole Sign, проверка стабильности Луны, деривация и эвалюация на десяти adversarial-профилях. В основе JPL reference ephemeris DE440s, тот самый эталон, по которому считают реальные миссии. Математику Асцендента и MC брали по Меесу, классическому справочнику по астрономическим вычислениям.

Отдельно скажу про честность разделения труда, потому что я её не скрываю: весь код движка написала нейросеть. Я код руками не пишу и никогда не писал, я стал разработчиком только через ИИ и агентский кодинг. Моя роль тут была другая. Я решал ценообразование, я ловил Claude на необоснованных оценках в днях, я требовал полный чеклист из четырёх ревьюеров на каждом шаге («а где блять ревью и верифай?»), я координировал две спеки и их синхронизацию, и я руками сверял результат с внешним эталоном. Вот это и есть оркестрация: ты не печатаешь код, ты держишь рамку, ловишь косяки и проверяешь итог.

Цифры, чтобы история была проверяемой

Без конкретики любой build-log это просто красивый рассказ, поэтому вот что получилось измеримого:

  • 8 экспертов × 2 консилиума = 16 мнений на два решения (ценообразование плюс архитектура движка)
  • 2 дня (с 14 по 16 апреля) на 10 шагов процесса с полным чеклистом ревью на каждом
  • 260 тестов зелёные, 29 в skip (это численные снапшоты на полярных зонах, там отдельная логика)
  • точность против astro.com на профиле Стива Джобса: Солнце разошлось на 0.002°, Асцендент на 0.05°, MC на 0.04°, Луна на 0.93°
  • 31 МБ эфемерид DE440s вместо 114 МБ полной DE440 — урезанная версия покрывает 1849–2150 годы, для живущих людей с запасом, экономия 83 МБ в каждом образе
  • 12 коммитов в main за два дня

Про Луну с её 0.93° отдельно, чтобы не выглядело как косяк. Это не баг, это выбранная модель наблюдателя. Я считаю Луну топоцентрически, то есть из конкретной точки на поверхности Земли, а astro.com геоцентрически, из центра планеты. Параллакс между ними доходит до градуса, и для допусков я заложил 0.5° на всё обычное и 1.5° на Луну именно по этой причине. Сверку профиля Стива Джобса я делал руками через astrotheme.com, чтобы убедиться, что движок не врёт.

Что я из этого вынес

Первое и главное: юридический слой надо проверять до консилиума, а не во время первого Docker build. Восемь умных экспертов могут идеально разобрать архитектуру и UX и всем составом проморгать одну строчку лицензии. AGPL-ловушка релевантна вообще любому коммерческому проекту на Python, и она тихая, ведь транзитивная зависимость не машет вам флагом, её надо искать самому. Теперь проверка лицензий всех зависимостей у меня уезжает в ресёрч до того, как эксперты начнут спорить.

Второе: оценки в днях для агентского кодинга это самообман, и даже сам Claude уже дважды на этом себя ловил. Единица измерения тут итерация ИИ, а не сутки. Я могу за вечер прогнать столько проходов, сколько живой команде хватило бы на неделю, а могу и наоборот застрять на одной тупой штуке там, где казалось «полчаса».

И третье, более общее. Когда что-то ломается, у вас всегда есть выбор: обойти по-быстрому или переписать честно. Обойти AGPL сайдкаром или плацебо-API было бы быстрее, но это технический долг и юридический риск, который однажды прилетит обратно. А переписать свою версию это два дня и движок, который теперь мой, чистый по лицензии и переиспользуемый под будущие фичи. Я выбрал второе и не жалею. Вы видите готовое приложение, фасад, а как оно сделано внутри и через сколько граблей нет. Вот эту изнанку я и показываю. Кстати, как я вообще заставил AI-агента работать по процессу с обязательными ревью, а не лепить как попало, я разбирал в STC + Guardian MCP, и без этого процесса AGPL всплыл бы не на первом шаге, а уже в проде.