Хотя написание кода порой может даваться с трудом, вы вряд ли считали это главным узким местом своего рабочего дня. После того как вы запустили собственные тесты, подтвердили работоспособность, отправили изменения и терпеливо дождались мнения коллег о вашем коде, эээээх — сборка CI завершилась с ошибкой.
Но, как выясняется, это вовсе не ваш баг, а сбой, который никак не связан с вашими изменениями. Вам приходится откладывать свой патч, искать предыдущие прогоны CI, воспроизводить ошибку и решать, где кроется проблема: в базе данных, в самом тесте или в его окружении. Перезапуск джобы часто дает успешный результат. Первопричина остается на своем месте, и с ней сталкивается следующий контрибьютор.
Кто-то должен выполнять эту работу, и с марта 2026 года в кодовой базе ClickHouse этим «кем-то» все чаще оказывается не человек.
Мы создали GroeneAI для проведения таких расследований. Это полностью автономный инженерный AI-агент, который работает 24 часа в сутки, 7 дней в неделю. Он воспроизводит сбои, пишет и тестирует исправления, а также сопровождает свои пулл-реквесты через CI и ревью. Groene означает «зеленый» на нидерландском языке, что отражает изначальную цель: поддерживать CI зеленым.
Он открыл свой первый тикет в ClickHouse 25 марта, следом за ним — первый пулл-реквест спустя 72 минуты, и с тех пор не останавливается. Агент выполняет весь процесс разработки без участия человека. Он выбирает задачу, исследует причину, проектирует и реализует исправление, собирает ClickHouse, запускает тесты и открывает пулл-реквест. Ни один человек не выполняет эти шаги, и в большинстве случаев человек их даже не выбирает. GroeneAI находит львиную долю работы самостоятельно по результатам CI, данным фаззера и отчетам пользователей. Мэйнтейнер также может поручить ему баг одним комментарием. В остальном участие человека начинается со стадии ревью, где мэйнтейнер принимает решение: принять изменения или направить GroeneAI в нужное русло.
Последующая работа также выполняется автономно. GroeneAI следит за CI, отвечает на комментарии в ходе ревью, дорабатывает реализацию и выполняет ребейс изменений по мере развития репозитория. Задача может оставаться активной на протяжении множества сессий, сохраняя ход расследования и следующие шаги на каждом этапе.
Исследуя сбои, GroeneAI научился понимать устройство кодовой базы. Он сохраняет первопричины, не сработавшие подходы и отзывы ревьюеров в постоянную память, а затем использует эти уроки в последующих задачах. Этот цикл привел его к решению проблем корректности и производительности в SQL-движке, хранилище, планировщике запросов и сопутствующей тестовой инфраструктуре. Масштаб задач вышел далеко за рамки CI уже очень скоро.
К октябрю 2026 года GroeneAI внес более 3 000 объединенных пулл-реквестов в ClickHouse. За три месяца вплоть до 19 октября он занял второе место среди контрибьюторов ClickHouse по количеству созданных коммитов (исключая слияния), уступив лишь сооснователю и техническому директору ClickHouse Алексею Миловидову.
Месячная активность в ClickHouse/ClickHouse. Созданные, объединенные и закрытые пулл-реквесты учитываются в том месяце, когда произошло соответствующее событие. Октябрь включает данные только с 1 по 25 число.
Агент работает на Nerve, нашем агентском рантайме с открытым исходным кодом. Nerve обеспечивает постоянные сессии, память, инструменты и выполнение по расписанию. GroeneAI добавляет рабочий процесс разработки, созданный специально для ClickHouse. О том, как этот рабочий процесс пришел к своему текущему виду, лучше всего рассказать на примере одного бага.
Хотя мы гордимся каждым изменением, созданным нашим маленьким роботом, мы хотели бы выделить несколько конкретных месяцев, когда он проявил себя ярче всего:
3 июня GroeneAI следил за CI после внесения собственных изменений в DDL, когда другой, не связанный с ними тест 03047_on_fly_update_delete завершился с ошибкой при использовании распределенных планов запросов на хранилище S3. Ошибка выглядела как плавающая. Повторный пропуск теста дал бы успешный результат. Вместо этого GroeneAI воспроизвел ее, и именно в процессе воспроизведения баг стал очевиден.
Кэш условий запроса запоминает, какие диапазоны блока данных не содержат строк, соответствующих фильтру, поэтому последующий запрос с тем же условием может пропустить их. Запись заслуживает доверия только тогда, когда фильтр видел реальные данные. Если другая операция предварительно удалила или изменила строки, пустой результат говорит скорее о той операции, чем о том, что хранится в базе.
investigation отследил кажущуюся плавающую ошибку до рандомизированной гранулярности индексов. При более крупных гранулах одна уцелевшая совпадающая строка сохраняла диапазон доступным для чтения и скрывала баг. При одной строке на гранулу некорректное решение о пропуске воспроизводилось каждый раз. Отсутствующая проверка была старой. Она восходила к реализации оригинального кэша условий запроса, объединенной в марте предыдущего года, которая применяла мутации перед PREWHERE, но фиксировала получающиеся пустые диапазоны без проверки того, изменили ли эти мутации строки.
регрессионный тест наглядно демонстрирует это. Он создает 100 строк, где id и v принимают значения от 0 до 99. Он останавливает фоновые слияния и отправляет асинхронное обновление, которое устанавливает v в ноль для строк с id >= 50. Исходная часть остается доступной, поэтому запрос может решить, применять ли ожидающую мутацию по мере чтения. После включения и очистки кэша тест выполняет два чтения:
Первый запрос должен вернуть ноль, так как обновление изменяет каждое подходящее значение. Второй должен вернуть 50, так как он читает исходные значения. До исправления первый запрос записывал элемент в кэш, из-за чего второй пропускал совпадающие строки.
Записанные результаты для случая UPDATE в регрессионном фикстуре пулл-реквеста для одного реплицируемого узла при index_granularity = 1 и mutations_sync = 0.
Сторона чтения уже была осторожной: она избегала кэшированных результатов при активных мутациях. Отсутствующая защита находилась на стороне записи. защищает оба пути записи в кэш с помощью проверки шагов мутаций или частей патча перед PREWHERE. Когда эти преобразования активны, процессор чтения подавляет обновления кэша из PREWHERE и удерживает метаданные, которые позволили бы нижестоящему фильтру WHERE записать элемент. Для безопасности на уровне строк (row-level security) применяется такая же защита с помощью регрессионного теста для двух пользователей, который дает одному пользователю доступ к v < 50, а другому — политику «всегда истина». Запросы без этих трансформаций сохраняют оптимизацию.
В ветке пулл-реквеста показано, как GroeneAI работал в июне, еще до появления пайплайна из следующего раздела. Он открыл 11 июня с таблицей того, что он проверил. В тот же день поступили четыре замечания по результатам ревью: путь WHERE все еще не был защищен, политики для строк нуждались в такой же защите, для случая с частями патча не было теста, и этот тест был недетерминированным. GroeneAI исправил каждое замечание и повторно публиковал таблицу после каждого исправления — пять раз за двенадцать часов. Восемь дней спустя alesapin спросил, отключает ли это изменение PREWHERE при легких мутациях. GroeneAI ответил через 31 минуту: подавлялась только запись в кэш, а привязка кэша к состоянию мутаций была альтернативным вариантом, если он предпочитает его. Он одобрил изменения через 33 минуты после этого.
Изменение было объединено 19 июня. Его тесты охватывают обновления, удаления, части патчей, правила для строк и предикаты, явно сохраненные в WHERE. В каждом случае действует одно правило: фильтр может зафиксировать, что диапазон не содержит совпадающих строк, только тогда, когда он оценил данные, которые представляет запись в кэше.
Хорошая работа, робот.
Исправление кэша заняло шестнадцать дней от неудачного теста до слияния. Сборка, ночной прогон CI и возвращение рецензента спустя дни — все это входит в данный промежуток времени. Агент, который забывает всё между сессиями, вообще не может выполнить эту работу, а агент, который запоминает что-то не то, делает ее плохо. В июле, после июньского исправления, мы внедрили конвейер, который текущий рабочий процесс использует до сих пор, и мы продолжаем менять его проверки по мере того, как новые сбои выявляют упущения в кейсах.
Прием начинается с событий: сохранения уведомлений GitHub и отслеживания позиции каждого потребителя во входящих сообщениях. Затем обработчик входящих сообщений GroeneAI сопоставляет подлежащие обработке сообщения с задачами. Отдельное запланированное сканирование исследует сбои CI, включая те, которые никогда не появлялись в входящих уведомлениях аккаунта.
Полученная задача является долговечной, так как Nerve сохраняет ее Markdown-контент и индексирует его в SQLite. GroeneAI добавляет контрольную точку, в которой записываются фаза, ветка, коммит, идентификатор сборки, завершенные тесты, расположение свидетельств и следующее действие. Последующая сессия восстанавливает это состояние без необходимости поддерживать активность предыдущего разговора.
Nerve сохраняет задачу и планирует выполнение. Рабочий процесс GroeneAI управляет передачей фаз. Исправления возвращаются на этап реализации, в то время как отзывы CI и сопровождающих могут возобновить работу после публикации.
Исправление кэша показывает, почему это состояние имеет значение: возобновившему работу воркеру нужно знать, какой путь чтения уже был защищен, какой тест проверяет WHERE и ожидает ли тест части патча своего обновления. Контрольная точка указывает на соответствующие артефакты, что позволяет сохранить разницу между завершенным изменением и нерешенной тестовой проблемой.
Память переносит информацию между различными задачами. Короткие правила работы попадают в контекст сессии. Более длительные исследования хранятся в файлах, которые загружаются по мере необходимости, в то время как семантический поиск извлекает предыдущие выводы и процедуры. Навыки предоставляют многократно используемые инструкции для такой работы, как сборка ClickHouse или расследование сбоя CI.
Сохраненная информация также может устаревать, и рабочий процесс относится к ней соответствующим образом. Инструкции по сборке GroeneAI требуют проверки текущей конфигурации компилятора CI и кэша CMake, даже если в памяти уже содержится версия компилятора. Запомненный урок указывает воркеру на свидетельства, которые он должен проверить в текущей рабочей копии. Документация по задаче Nerve, документация по получению исходного кода и документация по памяти описывают эти примитивы среды выполнения.
Поверх этой среды выполнения рабочий процесс разделяет новый вклад на три фазы с разными задачами.
Планирующий воркер исследует отчет, проверяет исходный код и существующие исправления, а также пишет подход с процедурой воспроизведения. План проверяется отдельной моделью. На этом этапе работа может остановиться, если отчет является дубликатом, не может быть воспроизведен или требует решения сопровождающего.
Затем воркер реализации вносит изменение в рабочую копию задачи. Его инструкции требуют наличия свидетельств того, что регрессионный тест падает без патча и проходит с ним. Если предположения плана не подтверждаются, воркер записывает то, что он запускал, и возвращает задачу на этап планирования.
Свежая сессия ревью изучает код до того, как прочитает повествование валидации от реализатора. Она должна проинспектировать измененные функции, их вызывающий код и связанные реализации, а затем сравнить тесты с описанием предлагаемого пулл-реквеста. GroeneAI использует Claude для основных сессий воркеров и Codex для раздельных ревью подхода и полученного изменения. Рецензент строит собственное объяснение патча и сравнивает его с доказательствами реализации. Принятый существенный вывод становится исправлением для реализации. Оспоренный вывод требует доказательств в виде кода или тестов, объясняющих разногласия.
Рабочий процесс также проверяет, какая именно ревизия подверглась ревью. Обычный путь перед пушем требует завершенного ревью второй моделью, записанного для предполагаемого коммита, дерева или полного идентификатора патча. Выводы по-прежнему требуют рассмотрения, и ревью более ранней версии не должно молчаливо санкционировать более позднее изменение кода.
Два августовских изменения показывают этот процесс в действии, начиная по-настоящему сиять в автономном режиме. Первое — это оптимизация планировщика, которую GroeneAI должен был доказать как безопасную, прежде чем сопровождающий согласился бы ее объединить, а второе исправляет отчет CI, который инженеры читают при оценке чужих изменений.
Давайте посмотрим, как справился робот:
В PR #115173 GroeneAI заметил, что две эквивалентные формы запроса порождают разные конвейеры, и что более медленная форма — это именно то, что пишут люди. Его изменениенебольшое. То, что фиксирует пулл-реквест — это то, как GroeneAI аргументировал его. Перед слиянием он замерил противоположный случай, проход по плотности дубликатов и количеству потоков, обнаружил 16-поточный ввод, который стал на 22% медленнее, и наибольшее ухудшение при max_threads = 1, после чего добавил защитный механизм, сохраняющий старый план на одном потоке. Собственное ревью второй моделью отклонило первый регрессионный тест, поскольку отключение предварительного шага при сохранении метки его плана все равно прошло бы проверку утверждения (assertion), которая проверяла только наличие. Теперь тест явно утверждает наличие ровно двух предварительных шагов плана и трех DistinctTransforms, а целенаправленное переключение флага в любом из планировщиков приводит к его сбою.
Две формы представляли собой UNION DISTINCT, отправляющий все строки через один финальный шаг дедупликации, и внешний SELECT DISTINCT вокруг UNION ALL, который сначала удаляет дубликаты внутри каждой ветки параллельно. Патч добавляет предварительный шаг distinct для UNION DISTINCT, когда эффективное количество потоков превышает единицу, сдвигает его в ветки и сохраняет финальный шаг, так как разные ветки могут содержать одинаковые значения. Обе реализации планировщика были обновлены. INTERSECT и EXCEPT сохраняют свои существующие планы.
Дедупликация на уровне веток сокращает количество строк, поступающих на финальную стадию distinct. Финальная стадия по-прежнему удаляет дубликаты, общие для разных веток.
В пулл-реквесте сообщается об этом эксперименте на релизной сборке с двумя ветками по восемь миллионов строк в каждой, 2000 уникальных значений и самым быстрым из семи запусков:
Эта таблица отражает случай с большим количеством дубликатов, для которого и было создано изменение. Этот проход — причина, по которой существует защита при max_threads = 1, и почему таблица не заявляет об ускорении для каждого набора входных данных. Изменение было объединено 27 августа с регрессионным тестом, охватывающим результаты запросов и структуру плана выполнения.
Второе изменение касается инструмента, от которого зависит GroeneAI. В PR #114451 было уделено внимание отчету о сравнении производительности, чья общая сводка была успешной, в то время как детали содержали 22 красные строки. GroeneAI не трогал вердикт. Он построил регрессионные тесты на основе двух реальных артефактов отчета — успешного шарда с 11 нестабильными запросами и упавшего шарда, который должен был оставаться красным, и зафиксировал, что его исправление изменило только отображение.
В отчете каждому детальному ряду был присвоен жестко зашитый статус сбоя, а также отображались как исходная, так и кандидатская сторона каждого сравнения. Изменение result-builder переносит фактический вердикт запроса в отчет и отображает каждое сравнение один раз, отдавая предпочтение кандидатской стороне, при этом сохраняя строки, хранящиеся в базе данных CI, и их ссылки на историю. Регрессионные тесты regression tests утверждают, что проходящий шард выдает 11 нестабильных строк, а падающий шард сохраняет свой статус сбоя. Изменение было слияно 17 августа.
В сентябре внимание сместилось на безопасность. Пять пулл-реквестов, слиянных в том месяце, закрыли уязвимость SQL-инъекции, и каждый из них вел к следующему. Первый, PR #108469, был открыт с 25 июня. GroeneAI обнаружил, что протокол проводов PostgreSQL внедрял параметры подготовленных выражений в текст SQL как «сырые» строки, поэтому такое значение, как x' UNION ALL SELECT ... --, обходило свое литеральное экранирование. 2 сентября один из наших сопровождающих отправил два собственных коммита в ветку GroeneAI: квотирование для идентификаторов COPY и исправление CancelRequest. На следующее утро он попросил GroeneAI проверить их:
PR #108469: запрос сопровождающего от 3 сентября 2026 года и начало проверки его коммитов со стороны GroeneAI.
GroeneAI ответил через час. Он подтвердил оба исправления на отладочной сборке, затем перечислил три пробела, не назвав ни один из них блокирующим: новый ключ отмены поступал из некриптографического генератора, ни один тест не фиксировал ключ как учетные данные, а имя таблицы COPY FROM было единственным вектором инъекции без зонда. Антонио сам устранил первый пробел четырьмя дополнительными коммитами, включая ключ отмены, полученный из RAND_bytes, и вернул пулл-реквест. Через несколько часов GroeneAI закрыл остальные два пробела и самостоятельно нашел еще два дефекта: секрет отмены появлялся в идентификаторе запроса, а два слушателя могли выдать один и тот же идентификатор соединения. Изменение было слияно на следующее утро, через 71 день после открытия. Когда второй агент ClickHouse, ClickGap, на следующий день обнаружил регрессию в слиянном коде, у GroeneAI было the fix открыто в течение двух часов.
Слияние не положило конец этому классу проблем. Четыре дня спустя PR #111516 закрыл приемники строковых литералов в метаданных запросов PostgreSQL. На следующий день после этого ClickGap reported обнаружил, что приемники идентификаторов все еще открыты: имя удаленного сервера таблицы вида a"; CREATE TABLE t(x int); -- выполнялось на сервере PostgreSQL, поскольку код экранировал двойную кавычку обратным слэшем, а PostgreSQL уважает только "". GroeneAI открыл PR #119103 тем же вечером, зафиксировал остаточный эффект пути чтения в своем последнем абзаце и открыл PR #119216 для этого остатка на следующий день. PR #117421 применил тот же анализ к движку SQLite, где проверка обнаружила гонку данных в поставляемой библиотеке, и для исправления потребовалось сначала однострочное изменение во втором репозитории. Каждый пулл-реквест ссылается на предыдущий, и в каждом описании указано, что осталось открытым.
Самый старый элемент в списке не был связан с инъекциями. В марте 2022 года Алексей Миловидов подал issue #35504: clickhouse-client не проверял доменное имя в сертификате сервера. PR #116724 проследил это до одного литерала — значения по умолчанию false в SSLManager.cpp, из-за которого каждое исходящее TLS-соединение принимало любой подписанный CA сертификат для любого хоста. Исправление включает проверку для клиентов, сохраняет значение по умолчанию для сервера, исключает адреса loopback и документирует две настройки, восстанавливающие старое поведение. Алексей одобрил его 20 сентября, спустя четыре с половиной года после подачи, и оно было перенесено (бэкрортировано) в четыре релизные ветки.
Большая часть работы GroeneAI начинается с сигнала, который никто не вводил вручную: упавший тест, находка фаззера, отчет в трекере проблем. Иногда все начинается с человека. 28 сентября внешний пользователь сообщил, что словарь с локальным источником ClickHouse сохраняет роли, которые были у его пользователя на момент загрузки. Роль, предоставленная позже, никогда не вступала в силу, каждое обновление завершалось ошибкой ACCESS_ENIED, и словарь выдавал устаревшие данные до тех пор, пока кто-нибудь не перезагрузил его. Неделю спустя сопровождающий прочитал отчет и передал его дальше:
Проблема #122663: запрос сопровождающего и два ответа GroeneAI, все от 5 октября 2026 года.
Упоминание попало во входящие, как и любое другое уведомление, и превратилось в задачу. GroeneAI воспроизвел ошибку на выпущенном бинарнике 26.8.10.6, проследил ее до контекста, который хранил роли пользователя по умолчанию в виде фиксированного списка со времен изменений 2023 года, и открыл PR #124051 в течение семи часов. Исправление представляет собой 17 строк в двух исходных файлах. Тест состоит из 108 строк и падает на мастере при каждом запуске.
Эта цепочка демонстрирует уроки из предыдущих разделов в действии. GroeneAI оставил два комментария к пулл-реквесту, оба свернуты по умолчанию: рецензия по второй модели с нулевым количеством блокирующих замечаний и шлюз валидации. Здесь нет повторно опубликованной таблицы, поскольку конвейер выполнил эти проверки до публикации. Когда сопровождающий попросил его «просто проверить, нужно ли это где-то еще», GroeneAI оценил все остальные места, выполняющие запросы от имени пользователя ClickHouse — от источников удаленных словарей до представлений-определителей и HTTP-сессий, — и ответил таблицей менее чем за три часа. Он одобрил изменения 21 минуту спустя и выполнил слияние тем же днем, спустя три дня после своего первого предложения.
К 25 октября 2026 года GroeneAI открыл более 4400 пулл-реквестов в ClickHouse/ClickHouse. Из них более 3100 были слияны, около 750 остались открытыми и почти 500 закрыты без слияния. Среди пулл-реквестов с принятым решением 86,5% были слияны.
Ежемесячные слияния выросли почти со 100 в апреле почти до 700 в сентябре, а первые 25 дней октября добавили еще более 800. Эта работа включает более 1300 слиянных пулл-реквестов с меткой исправления ошибок (bug fixes), что почти равно количеству CI и тестов, и примерно 150 для улучшения производительности. Двадцать три имеют метку критического исправления ошибки.
Выбранные метки чейнджлога для слиянных пулл-реквестов по состоянию на 25 октября. Метки могут пересекаться, поэтому эти значения не следует складывать вместе.
Слиянные пулл-реквесты ссылаются более чем на 1000 различных проблем через ссылки GitHub на закрытие проблем. Они также включают работу, которая никогда не начиналась с проблемы: новое покрытие регрессионными тестами, более понятные отчеты CI и улучшения, обнаруженные при расследовании другого сбоя.
Медианный слиянный патч изменяет 67 строк в трех файлах. Приведенные выше примеры укладываются в эту схему. Исправить предположение о пути чтения, добавить недостающий шаг планировщика, исправить вводящий в заблуждение результат CI или привязать параметр как данные. Небольшой патч может защитить широко используемую операцию, особенно если он поставляется с тестом, который делает исходный сбой воспроизводимым.
Открытие пулл-реквеста оставляет незавершенную работу. Проверка может завершиться ошибкой, базовая ветка может сместиться, или сопровождающий может попросить использовать другой подход. GroeneAI сохраняет задачу и направляет эти события специалистам по сопровождению или реагированию человека.
Этот отзыв также меняет подход к решению следующей проблемы. В ходе расследования система сохраняет первопричины, шаги для воспроизведения, неудачные подходы и указания рецензентов в постоянной памяти. Новая задача открывается с вызовом соответствующей истории, что дает ей результаты, которых уже нет в текущей беседе.
Каждую неделю GroeneAI анализирует отзывы людей о запрашиваемых изменениях, отклоненных запросах на слияние (pull requests) и выбранных объединенных вливаниях. Система обобщает эти результаты в файле REVIEW-LESSONS.md, записывая исходный pull request, решение рецензента и урок, который необходимо применить. Инструкции по реализации, рецензированию и содержательным ответам — все они требуют чтения этого документа перед началом работы.
Один из сохраненных уроков имеет видимое происхождение. В PR #109738 исправление в ходе рецензирования было расширено за счет включения дополнительных случаев, в то время как описание по-прежнему содержало название только исходного бага. Замечание рецензента представляет собой максимально краткую формулировку проблемы:
Рецензия Avogar на PR #109738, 23 июля 2026 г.
Обе заметки стали уроками. Первая теперь является инструкцией о том, что описание должно отражать полное окончательное изменение, чтобы последующие рецензии сравнивали код и тесты с точным утверждением того, что обещает патч. Второй урок потребовал больше времени для усвоения. В июне GroeneAI пять раз повторно опубликовала свою таблицу валидации в одном pull request. В сентябре один из мейнтейнеров в PR #117727 начал свой комментарий со слов «если вы читаете это среди множества агентских комментариев». Ответ GroeneAI признавал этот факт:
Ответ GroeneAI на PR #117727, 2 сентября 2026 г.
Этот ответ стал постоянной директивой. С тех пор комментарии GroeneAI к pull request содержат примечание, которое ни один читатель не видит, пока не откроет исходный Markdown:
Постоянная директива REVIEW-LESSONS: два мейнтейнера назвали объем комментариев этого флота нагрузкой на рецензента (@rschu1ze #117727, @Algunenano #117619). Публикуется ТОЛЬКО этот свернутый комментарий; таблица валидации a-i намеренно НЕ публикуется. Источник: PR #120259, скрытый HTML-комментарий в исходном Markdown.
Постоянная директива REVIEW-LESSONS: два мейнтейнера назвали объем комментариев этого флота нагрузкой на рецензента (@rschu1ze #117727, @Algunenano #117619). Публикуется ТОЛЬКО этот свернутый комментарий; таблица валидации a-i намеренно НЕ публикуется. Источник: , скрытый HTML-комментарий в исходном Markdown.
GroeneAI также сопоставляет отклоненные ею автоматические находки с последовавшим за ними человеческим рецензированием. Когда мейнтейнер поднимает проблему, которую агент проигнорировал, он записывает как прежнее решение, так и последующую исправительную меру. Память сохраняет причину сбоя предыдущего решения, что делает исправление доступным за пределами того единственного pull request, где это произошло.
Для исправлений CI слияние не является концом. GroeneAI сохраняет состояние задачи проверки после слияния, а запланированный воркер запрашивает последующие сбои в ветке master. Ее инструкции требуют как минимум двух дней работы ветки master без зарегистрированного сбоя до закрытия задачи, а продолжающиеся сбои возвращаются на расследование. Решение о слиянии и последующая проверка сигнала об исходном сבое остаются раздельными шагами.
Вклад GroeneAI затрагивает несколько областей разработки баз данных. Исправления корректности защищают результаты запросов. Улучшения выполнения более эффективно используют параллелизм. Изменения в CI помогают контрибьюторам интерпретировать сбои, а регрессионные тесты сохраняют условия, которые изначально обнажили баг.










