AI-агент получает задачу отрефакторить класс UserService - выделить методы аутентификации в отдельный модуль. Модель генерирует чистый код, тесты проходят, PR уходит на ревью. Через час падает CI: сломаны 14 файлов, которые зависели от сигнатуры старого метода. Агент успешно решил локальную задачу, но разрушил системную целостность. Это не гипотетический сценарий - это воспроизводимый паттерн, который проявляется тем чаще, чем больше агентов одновременно работают с кодовой базой.
CodeSlicer - инструмент статического анализа, который строит проверяемый граф влияния проекта. Он проходит четыре этапа: inventory, extraction, precision resolution и impact query - и выдаёт верифицированную карту зависимостей без ложных срабатываний. Тесты на Python и TypeScript подтверждают: precision 100%, recall 99.7%, ноль false positives на выборке из 120 000 строк кода. Агент, вооружённый таким графом, перестаёт «забывать» о зависимостях и начинает работать с целостной картиной системы.
Этот подход напрямую связан с методологией Graph Engineering, которая в июле 2026 года оформилась в самостоятельное направление после реплики разработчика Питера Штайнбергера и статьи Анатоли Копадзе. Графовая инженерия проектирует работу агентов как исполняемый граф: узлы выполняют ограниченные задачи, рёбра передают данные и задают реальные зависимости. Главный риск такого подхода - принять внутреннее согласие агентов за истину. CodeSlicer даёт тот самый внешний якорь, без которого граф агентов остаётся красивой абстракцией, а не надёжным инструментом.
Почему AI-агенты теряют целостность кода
Корневая проблема не в интеллекте модели. Современные LLM отлично справляются с изолированными задачами: написать функцию, поправить баг, сгенерировать тесты. Проблема в том, что кодовая база - это граф с сотнями и тысячами рёбер, а агент видит только тот фрагмент, который помещается в контекстное окно. Даже при идеальном промпте модель не знает, что изменение сигнатуры метода в одном файле сломает вызовы в трёх других модулях, если эти модули не попали в контекст.
Результат предсказуем: агенты генерируют код, который проходит unit-тесты, но проваливает интеграционные проверки. Команда тратит время на отладку, ревьюеры выгорают на поиске скрытых конфликтов, а скорость разработки падает. Скорость набора строк становится фиктивным KPI, за которым скрывается лавина сгенерированного кода, разрушающая понимание кодовой базы.
Локальный успех, системный провал
Возьмём конкретный пример. В проекте на TypeScript есть класс DataExporter с методом exportToCSV(data: Dataset, options: ExportOptions). Агент получает задачу добавить поддержку формата Parquet. Модель меняет сигнатуру на exportData(data: Dataset, format: Format, options?: ExportOptions) и обновляет тело метода. Юнит-тесты для DataExporter проходят.
Однако в проекте 23 файла вызывают exportToCSV. Из них только 3 попали в контекст агента - модель обновила их. Остальные 20 остались со старой сигнатурой. TypeScript-компилятор ловит ошибки на этапе сборки, но в Python та же ситуация всплывёт только в рантайме. Агент не виноват - ему не дали карту зависимостей. Он действовал в пределах предоставленной информации.
Этот сценарий воспроизводится на любом языке и в любом фреймворке. Масштаб проблемы растёт нелинейно с размером кодовой базы: в проекте из 50 файлов агент может удержать в контексте почти всё, в проекте из 5000 файлов - гарантированно пропустит критическую зависимость. Отсюда парадокс: чем больше проект выигрывает от автоматизации, тем выше риск разрушения целостности.
Граф влияния как внешний якорь истины
Graph Engineering даёт чёткий принцип: агент не должен проверять сам себя. Каждый узел графа получает вход, выдаёт структурированный выход, а проверку выполняет независимый компонент. В кодовой базе этот принцип требует внешнего якоря - верифицированной карты всех связей между сущностями.
Граф влияния проекта делает именно это. Он фиксирует: функция A вызывает функцию B, класс C наследуется от D, модуль E импортирует F, сигнатура G используется в файлах H, I, J. Когда агент собирается изменить сигнатуру G, граф возвращает точный список затронутых файлов. Агент получает не свою догадку о зависимостях, а доказанный факт. Это устраняет главный риск графовой инженерии - подмену реальных связей внутренним согласием модели.
Главное преимущество такого подхода - явные контракты и видимые точки отказа. Если граф говорит, что изменение затронет 14 файлов, а агент обновил только 3, проблема локализована мгновенно. Никакой магии, только детерминированный анализ. Спецификации и явные контракты спасают разработку с AI-агентами, возвращая инженеру роль командира, а агенту - роль автопилота.
CodeSlicer: конвейер построения проверяемого графа влияния
CodeSlicer реализует четырёхэтапный конвейер. Каждый этап добавляет слой верификации, и только после полного прохода данные попадают в граф. Архитектура спроектирована так, чтобы исключить ложные срабатывания на каждом шаге, а не отфильтровывать их постфактум.
Inventory: полная инвентаризация кодовой базы
Первый этап - сбор всех сущностей проекта без пропусков. CodeSlicer сканирует файловую систему, парсит AST для каждого файла и извлекает: классы, функции, методы, переменные, интерфейсы, типы, перечисления. Для Python учитываются динамические конструкции - декораторы, метаклассы, __init__.py с реэкспортами. Для TypeScript - declaration files, ambient declarations, условные типы.
Важный момент: инвентаризация не полагается на соглашения об именовании или структуру директорий. Парсер работает с синтаксическим деревом напрямую, поэтому неважно, как организованы файлы и папки. Если сущность существует в коде, она попадёт в инвентарь. Пропуск на этом этапе означает каскадную потерю зависимостей на всех последующих шагах, поэтому CodeSlicer жертвует скоростью в пользу полноты: inventory занимает 60-70% общего времени конвейера.
Extraction: извлечение фактов о зависимостях
На втором этапе CodeSlicer анализирует отношения между сущностями и сохраняет их в виде триплетов: субъект, отношение, объект. Типы отношений включают: IMPORTS (модуль импортирует другой модуль), CALLS (функция вызывает функцию), INHERITS (класс наследует класс), USES_TYPE (функция использует тип), DECORATES (декоратор оборачивает функцию), REEXPORTS (модуль реэкспортирует символ).
Для каждого отношения фиксируется контекст: файл, строка, область видимости. Например, триплет «UserService.createUser CALLS Database.insert» дополняется информацией, что вызов происходит в файле services/user_service.py на строке 47 внутри метода createUser. Эта метаинформация критична для следующего этапа - без неё невозможно разрешить неоднозначности.
Precision Resolution: семантическое разрешение без ложных срабатываний
Это ключевой этап, который отличает CodeSlicer от простых grep-подобных анализаторов. На стадии extraction собраны тысячи триплетов, но многие из них содержат неоднозначности. Функция с именем process может быть определена в трёх разных модулях - какой из них реально вызывается в конкретном файле? Класс User может быть импортирован из auth.models или из billing.models - какой используется в этом контексте?
CodeSlicer разрешает эти неоднозначности через многоуровневый анализ:
- Разрешение импортов: отслеживание цепочек import ... from, реэкспортов через __init__.py и barrel-файлы.
- Анализ областей видимости: учёт локальных переменных, замыканий, nonlocal/global в Python.
- Вывод типов: для TypeScript используется информация компилятора о реальных типах переменных; для Python - аннотации типов и анализ присваиваний.
- Разрешение перегрузок: когда функция имеет несколько сигнатур, определяется, какая из них реально вызывается.
Результат этого этапа - очищенный набор триплетов, где каждый факт зависимости подтверждён семантическим анализом. Именно здесь достигается заявленный zero false positives: все неоднозначные связи либо разрешаются, либо помечаются как uncertain и исключаются из графа влияния.
Impact Query: оценка влияния изменений
Финальный этап - построение графа и API для запросов. Граф хранится в оптимизированном формате, который позволяет выполнять поиск в ширину и глубину за доли секунды даже для проектов с сотнями тысяч узлов. Разработчик или агент может задать вопрос: «Какие модули затронет изменение сигнатуры этой функции?» - и получить точный список зависимых файлов и символов.
Типичный запрос к impact query выглядит так: указать символ (функцию, класс, интерфейс) и направление поиска - вверх по зависимостям (кто зависит от этого символа) или вниз (от чего зависит этот символ). CodeSlicer возвращает дерево зависимостей с указанием файлов и строк. Это можно встроить в PR-ревью: перед мержем автоматически проверяется, что все затронутые файлы действительно изменены. Или в пайплайн агента: перед генерацией кода модель получает контекст влияния и учитывает его при планировании изменений.
Результаты тестов: Python и TypeScript без ложных срабатываний
CodeSlicer протестирован на наборе из 14 проектов суммарным объёмом 120 000 строк кода: 8 проектов на Python (Django, FastAPI, библиотеки) и 6 на TypeScript (Next.js, Express, утилиты). Для каждого проекта выполнена полная инвентаризация, извлечение фактов и precision resolution. Результаты верифицированы ручной проверкой случайной выборки из 500 связей на каждый проект.
Методология тестирования
Для оценки качества использовались стандартные метрики информационного поиска:
- Precision: доля найденных зависимостей, которые реально существуют. Целевое значение - 100%.
- Recall: доля реальных зависимостей, которые найдены инструментом. Целевое значение - выше 99%.
- False positive rate: доля ложных связей среди всех найденных. Целевое значение - 0%.
Ручная верификация проводилась двумя инженерами независимо, спорные случаи разрешались коллегиально. Для Python особое внимание уделялось динамическим паттернам: monkey-patching, runtime-инъекции зависимостей, вызовы через getattr. Для TypeScript - сложным generic-конструкциям, conditional types и mapped types.
Итоговые результаты: precision 100% на обоих языках, recall 99.7% для Python и 99.9% для TypeScript, false positive rate 0%. Единственные пропущенные зависимости в Python - случаи динамической генерации кода через exec/eval, которые статический анализ принципиально не может обнаружить. CodeSlicer честно маркирует такие файлы как содержащие динамический код и исключает их из гарантий полноты.
Практические примеры использования
Сценарий 1: AI-агент перед рефакторингом. Агент получает задачу изменить сигнатуру метода в проекте на 800 файлов. Перед генерацией кода он запрашивает impact query для целевого метода. CodeSlicer возвращает список из 34 файлов, которые используют эту сигнатуру. Агент включает их в контекст и генерирует изменения сразу для всех затронутых модулей. Результат: CI проходит с первой попытки, время ревью сокращается втрое.
Сценарий 2: Автоматическое PR-ревью. В CI-пайплайн встроена проверка: для каждого изменённого символа CodeSlicer вычисляет зону влияния и сравнивает со списком реально изменённых файлов. Если затронутый файл не изменён, PR блокируется с указанием конкретной зависимости. Это ловит ошибки, которые пропускают линтеры и тесты, потому что проблема не в синтаксисе, а в несогласованности изменений. Подобный подход с кросс-валидацией уже доказал эффективность в DevSecOps, где объединение сканеров превращает шум алертов в доказанные уязвимости.
Интеграция с AI-агентами и Graph Engineering
CodeSlicer не просто инструмент статического анализа - это компонент инфраструктуры для графовой инженерии агентов. Он реализует принцип внешнего якоря истины, без которого граф агентов рискует стать самосогласованной, но ошибочной системой.
От контрактов узлов к контрактам кода
В графе агентов каждый узел имеет чёткий контракт: вход определённой структуры, выход определённой структуры. Рёбра передают данные между узлами по этим контрактам. CodeSlicer выявляет аналогичные контракты в коде: сигнатура функции - это её контракт, импорт модуля - контракт зависимости, наследование класса - контракт интерфейса.
Когда агент работает с кодом, он должен соблюдать эти контракты. Граф влияния делает контракты явными и проверяемыми. Агент не может «забыть» обновить зависимый модуль, потому что граф предъявит ему список всех модулей, связанных контрактом с изменяемой сущностью. Это тот же принцип, что и в графах агентов: явные зависимости вместо неявных предположений.
Предотвращение коллапса контекста на fan-in
Паттерн diamond из Graph Engineering - fan-out, reduce, verify, synthesize - создаёт точку fan-in, где результаты параллельных агентов сходятся для финальной сборки. В кодовой базе аналогом fan-in служит модуль, от которого зависят десятки других модулей: утилитарные функции, базовые классы, общие типы.
Когда множество агентов одновременно модифицируют модули, сходящиеся к общему fan-in, легко потерять контекст и создать несовместимые изменения. CodeSlicer позволяет отследить все входящие зависимости для fan-in-модуля и проверить их совместимость до мержа. Это превращает потенциальный коллапс контекста в контролируемую точку синхронизации.
Кейс Bun с 64 агентами и экстремальным параллелизмом показал цену отсутствия такой проверки: агенты генерировали конфликтующие изменения, которые требовали ручного разрешения. С графом влияния каждый агент перед коммитом проверяет, не конфликтует ли его изменение с зависимостями, уже изменёнными другими агентами. Инструменты вроде Pre2Prod уже показывают, как двухролевая модель агентов с механизмом форка и перепроверки превращает прототип в production-ready MVP, и граф влияния - естественное развитие этой идеи для масштаба всей кодовой базы.
Когда CodeSlicer необходим, а когда можно обойтись без него
Граф влияния окупается не для любого проекта. Критерии, при которых CodeSlicer даёт максимальную отдачу:
- Кодовая база от 200 файлов и от 30 000 строк кода. На меньших объёмах агент способен удержать весь проект в контексте, и граф влияния избыточен.
- Активное использование AI-агентов для генерации кода. Если агенты пишут больше 20% нового кода, ручной контроль зависимостей перестаёт справляться.
- Частые рефакторинги, затрагивающие публичные API. Каждое изменение сигнатуры - потенциальный каскад ошибок в зависимых модулях.
- Многомодульная архитектура с глубокими деревьями зависимостей. Чем больше уровней импортов, тем выше вероятность, что агент пропустит транзитивную зависимость.
Ситуации, где выгода от CodeSlicer минимальна: изолированные микросервисы с жёсткими API-контрактами (зависимости ограничены одним модулем), скрипты и утилиты до 1000 строк, проекты, где агенты используются только для генерации тестов или документации. Это аналогично принципу из Graph Engineering: граф не нужен для любого промпта, он окупается при разделении задачи на независимые потоки с последующей сборкой.
Практический критерий внедрения: если ваша команда тратит больше часа в неделю на исправление ошибок, вызванных несогласованными изменениями агентов, CodeSlicer окупится в первый месяц. Если такие ошибки единичны - начните с инвентаризации кодовой базы, чтобы оценить реальную плотность зависимостей, и принимайте решение на основе данных, а не интуиции. Опыт внедрения контекстной инфраструктуры на tree-sitter подтверждает: инструмент, созданный для разработки, часто даёт максимальную ценность в смежных сценариях - аналитике, ревью, аудите зависимостей.