И да и нет. Semble - это семантический поиск: он по эмбеддингам находит код, похожий по смыслу на запрос. У меня - структурный граф: реальные рёбра вызовов и типов. Это разные вопросы. "Найди код про аутентификацию" - это к semble. А "кто конкретно вызывает этот метод и что сломается, если я поменяю сигнатуру" - похожесть тут не поможет, нужна именно структура. Эмбеддинг не отличит реальный вызов функции от куска, который просто рядом по смыслу
Зависит от задачи: на рефакторинге и анализе ощутимо дешевле по токенам, на простых точечных запросах примерно схожие цифры с ним. Прямое сравнение с codegraph в части 2
Cодержание, замеры, выводы - мои, модель просто собрала всё в читаемый текст. Язык и структура - это редактура, а не авторство. "Честно" - это не самопохвала. За моими процентами 936 прогонов, открытые трейсы и стенд - иди да перепроверь. А за типичным "−40% токенов" строчка в README и всё. Критиковать подачу - это бесплатно. А сделать инструмент и прогнать тыщу замеров - нет.
По сути верно: строгий компилятор + плотные тесты — лучший оракул, что правка не сломала типы. Граф с этим не конкурирует.
Два момента, которые этот цикл не закрывает. Компилятор отвечает после правки и только про типовые поломки — а агенту надо понять, что и где менять, до (часто согласованно в N местах), и куча влияющих изменений компилируется чисто (смена семантики при той же сигнатуре, дефолты, сайд-эффекты). И жёсткие задачи в бенчмарке были на Python, где падающего билда на переименованный метод нет в принципе — там граф и выигрывал, потому что компилятора-оракула просто не существует.
Ну и граф ≠ «вместо компилятора». Find usages в вашей IDE — это и есть call-граф на LSP; вы ходите им по коду до правки, а не ломаете билд ради чтения ошибок. graphlens просто даёт агенту тот же find-usages, чтобы он не крутил build-fix-loop и не грепал.
Спасибо, что не просто потыкали, а реально полезли в код и в граничные кейсы — такой фидбэк ценнее всего.
Сначала про рамку, она тут ключевая. graphlens — это библиотека/движок, а не продукт «поставил и работает». Это не отговорка, это зафиксированная область применения: в доке есть отдельный раздел Scope & Non-goals, где прямо перечислено, чего он сознательно не делает — https://neko1313.github.io/graphlens/docs/#scope--non-goals. Его задача — отдать структурный IR, а слой «само запускается, подключается, трекает» — ровно то, что строится сверху. Так что бóльшая часть трения, которое вы словили (ручной запуск, ручной MCP, скил-обвязка), — это отсутствующий продуктовый слой, и претензия честная. Скил — правильное направление, его надо вылизывать, и это отдельная работа, которую я пока не сделал.
По конкретике:
— «на весь диск»: оно индексирует не диск, а путь, который вы дали (graphlens analyze ./repo). Но да — то, что это надо запускать руками на каждый проект и потом руками цеплять MCP, реальное неудобство, спорить не с чем.
— Go с vendor / replace / внешними либами: честно слабое место. Type-aware рёбра резолвит gopls, и на vendored-зависимостях с replace в go.mod он требует правильно настроенного окружения, иначе кросс-модульные ссылки разрешаются криво — что вы и увидели. Если не лень, киньте issue с минимальным репро (go.mod с replace + vendor) — это прям полезный кейс, чтобы пофиксить настройку резолвера.
— 52 ГБ репо: это сильно за пределами того, на что оно сейчас рассчитано — граф целиком держится в памяти (для superset это ~170 МБ, у вас был бы порядок гигабайтов), так что «легло намертво» ожидаемо. Отдельно: индексируется дерево исходников, а не история гита; если оно реально полезло в .git — это баг и тоже повод для issue.
— про векторные БД: вот тут поправлю, это частое недопонимание. В graphlens нет ни вектора, ни эмбеддингов, ни семантического поиска — это даже вынесено отдельным пунктом в тот же раздел Non-goals по ссылке выше («not a vector index»). Внутри только tree-sitter (парсинг в CST) и LSP-резолверы, которые дают точные рёбра по типам, а не «похожие по смыслу». Если соберёте пет-проект на Го/Расте с векторной БД — это будет другой инструмент, решающий другую задачу (семантический поиск). Здесь вектора нет принципиально, и не из-за языка.
А теперь главное — про «не буду использовать, jetbrains-mcp + греп хватает». Вы пришли ровно к тому выводу, который я измерял отдельным бенчмарком — https://github.com/Neko1313/agent-context-bench. Там я специально разделял результаты по типу задач: на простых («где определён», «от чего наследуется») все инструменты, включая греп, равны по точности, и удобство «из коробки» спокойно перекрывает пару процентов на поиске. Структурный граф окупается только на тяжёлых вопросах — радиус поражения, наборы переопределений, разрешение одноимённых методов; нет такой работы — родного тулинга правда достаточно. Так что это не «вы не оценили», а «вы независимо подтвердили числа». За это спасибо.
И раз код показался несложным — он таким и задуман: минимальное ядро это фича, а не недоработка, на нём проще строить. Контракт и IR под MIT, так что если дойдёт до пет-проекта на Расте — переиспользуйте без зазрения совести.
Тут скорее пока что базовые языки, которые чаще других встречаю в своем стеке, но в целом их можно расширить, проект модульный, также в целом я в статье писал, как можно написать свой диалект
Справедливое замечание. getattr/importlib — это known limitation любого статического call graph: без runtime информации такие вызовы в принципе не разрешимы полностью. В текущей реализации они либо не формируют CALLS-рёбра вообще, либо резолвятся в EXTERNAL_SYMBOL(unknown) — граф деградирует в этих местах, но не ломается (resolver_status всё равно будет ok, что технически не совсем честно для таких паттернов).
На ty-стороне пока не исследовал, насколько он это покрывает — он pre-1.0 и поведение нестабильно. Pyright теоретически чуть лучше с getattr(obj, name) где тип obj известен, но это: а) не универсально, б) существенно медленнее индексация. Скорее всего трекну это как известное ограничение и буду ждать ty 1.0, где type inference должен быть значительно зрелее.
Graphify — это Claude Code skill для конечного пользователя, graphlens — движок. По резолвингу: graphify делает name-based matching через AST + LLM-угадывание, сами помечают это как INFERRED. graphlens гоняет реальные тайп-чекеры (ty/gopls/rust-analyzer/tsc) — ребро CALLS указывает на конкретный объявленный узел, не на строку с именем. Это разные инструменты для разных задач, сравнение по звёздам бессмысленно.
Я считаю, что результатов, которых вы добились, более чем достаточно. Такая модель хорошо вписывается в концепцию мультиагентных систем, где одна модель выступает в роли оркестратора и распределяет задачи между более узкоспециализированными моделями.
Сейчас я в первую очередь хочу собрать обратную связь, чтобы понять, в каком направлении лучше дорабатывать библиотеку. При этом у меня уже есть идеи по её дальнейшему развитию: сделать текущий модуль частью более широкого решения, например общего casbin-decorator с extras для FastAPI, FastMCP, Flask и других фреймворков.
Продукт, который вы скинули, использует тот же принцип, что и codegraph, и скорее является его полным аналогом и имеет те же проблемы
А будет критика самого инструмента ?
И да и нет. Semble - это семантический поиск: он по эмбеддингам находит код, похожий по смыслу на запрос. У меня - структурный граф: реальные рёбра вызовов и типов. Это разные вопросы. "Найди код про аутентификацию" - это к semble. А "кто конкретно вызывает этот метод и что сломается, если я поменяю сигнатуру" - похожесть тут не поможет, нужна именно структура. Эмбеддинг не отличит реальный вызов функции от куска, который просто рядом по смыслу
Зависит от задачи: на рефакторинге и анализе ощутимо дешевле по токенам, на простых точечных запросах примерно схожие цифры с ним. Прямое сравнение с codegraph в части 2
Cодержание, замеры, выводы - мои, модель просто собрала всё в читаемый текст. Язык и структура - это редактура, а не авторство. "Честно" - это не самопохвала. За моими процентами 936 прогонов, открытые трейсы и стенд - иди да перепроверь. А за типичным "−40% токенов" строчка в README и всё. Критиковать подачу - это бесплатно. А сделать инструмент и прогнать тыщу замеров - нет.
По сути верно: строгий компилятор + плотные тесты — лучший оракул, что правка не сломала типы. Граф с этим не конкурирует.
Два момента, которые этот цикл не закрывает. Компилятор отвечает после правки и только про типовые поломки — а агенту надо понять, что и где менять, до (часто согласованно в N местах), и куча влияющих изменений компилируется чисто (смена семантики при той же сигнатуре, дефолты, сайд-эффекты). И жёсткие задачи в бенчмарке были на Python, где падающего билда на переименованный метод нет в принципе — там граф и выигрывал, потому что компилятора-оракула просто не существует.
Ну и граф ≠ «вместо компилятора». Find usages в вашей IDE — это и есть call-граф на LSP; вы ходите им по коду до правки, а не ломаете билд ради чтения ошибок. graphlens просто даёт агенту тот же find-usages, чтобы он не крутил build-fix-loop и не грепал.
Спасибо, что не просто потыкали, а реально полезли в код и в граничные кейсы — такой фидбэк ценнее всего.
Сначала про рамку, она тут ключевая. graphlens — это библиотека/движок, а не продукт «поставил и работает». Это не отговорка, это зафиксированная область применения: в доке есть отдельный раздел Scope & Non-goals, где прямо перечислено, чего он сознательно не делает — https://neko1313.github.io/graphlens/docs/#scope--non-goals. Его задача — отдать структурный IR, а слой «само запускается, подключается, трекает» — ровно то, что строится сверху. Так что бóльшая часть трения, которое вы словили (ручной запуск, ручной MCP, скил-обвязка), — это отсутствующий продуктовый слой, и претензия честная. Скил — правильное направление, его надо вылизывать, и это отдельная работа, которую я пока не сделал.
По конкретике:
— «на весь диск»: оно индексирует не диск, а путь, который вы дали (
graphlens analyze ./repo). Но да — то, что это надо запускать руками на каждый проект и потом руками цеплять MCP, реальное неудобство, спорить не с чем.— Go с vendor / replace / внешними либами: честно слабое место. Type-aware рёбра резолвит gopls, и на vendored-зависимостях с
replaceв go.mod он требует правильно настроенного окружения, иначе кросс-модульные ссылки разрешаются криво — что вы и увидели. Если не лень, киньте issue с минимальным репро (go.mod с replace + vendor) — это прям полезный кейс, чтобы пофиксить настройку резолвера.— 52 ГБ репо: это сильно за пределами того, на что оно сейчас рассчитано — граф целиком держится в памяти (для superset это ~170 МБ, у вас был бы порядок гигабайтов), так что «легло намертво» ожидаемо. Отдельно: индексируется дерево исходников, а не история гита; если оно реально полезло в
.git— это баг и тоже повод для issue.— про векторные БД: вот тут поправлю, это частое недопонимание. В graphlens нет ни вектора, ни эмбеддингов, ни семантического поиска — это даже вынесено отдельным пунктом в тот же раздел Non-goals по ссылке выше («not a vector index»). Внутри только tree-sitter (парсинг в CST) и LSP-резолверы, которые дают точные рёбра по типам, а не «похожие по смыслу». Если соберёте пет-проект на Го/Расте с векторной БД — это будет другой инструмент, решающий другую задачу (семантический поиск). Здесь вектора нет принципиально, и не из-за языка.
А теперь главное — про «не буду использовать, jetbrains-mcp + греп хватает». Вы пришли ровно к тому выводу, который я измерял отдельным бенчмарком — https://github.com/Neko1313/agent-context-bench. Там я специально разделял результаты по типу задач: на простых («где определён», «от чего наследуется») все инструменты, включая греп, равны по точности, и удобство «из коробки» спокойно перекрывает пару процентов на поиске. Структурный граф окупается только на тяжёлых вопросах — радиус поражения, наборы переопределений, разрешение одноимённых методов; нет такой работы — родного тулинга правда достаточно. Так что это не «вы не оценили», а «вы независимо подтвердили числа». За это спасибо.
И раз код показался несложным — он таким и задуман: минимальное ядро это фича, а не недоработка, на нём проще строить. Контракт и IR под MIT, так что если дойдёт до пет-проекта на Расте — переиспользуйте без зазрения совести.
Тут скорее пока что базовые языки, которые чаще других встречаю в своем стеке, но в целом их можно расширить, проект модульный, также в целом я в статье писал, как можно написать свой диалект
Справедливое замечание.
getattr/importlib— это known limitation любого статического call graph: без runtime информации такие вызовы в принципе не разрешимы полностью. В текущей реализации они либо не формируютCALLS-рёбра вообще, либо резолвятся вEXTERNAL_SYMBOL(unknown)— граф деградирует в этих местах, но не ломается (resolver_statusвсё равно будетok, что технически не совсем честно для таких паттернов).На
ty-стороне пока не исследовал, насколько он это покрывает — он pre-1.0 и поведение нестабильно. Pyright теоретически чуть лучше сgetattr(obj, name)где типobjизвестен, но это: а) не универсально, б) существенно медленнее индексация. Скорее всего трекну это как известное ограничение и буду ждатьty1.0, где type inference должен быть значительно зрелее.Graphify — это Claude Code skill для конечного пользователя, graphlens — движок. По резолвингу: graphify делает name-based matching через AST + LLM-угадывание, сами помечают это как INFERRED. graphlens гоняет реальные тайп-чекеры (ty/gopls/rust-analyzer/tsc) — ребро CALLS указывает на конкретный объявленный узел, не на строку с именем. Это разные инструменты для разных задач, сравнение по звёздам бессмысленно.
Я считаю, что результатов, которых вы добились, более чем достаточно. Такая модель хорошо вписывается в концепцию мультиагентных систем, где одна модель выступает в роли оркестратора и распределяет задачи между более узкоспециализированными моделями.
Добавил этот функционал в версии
1.1.0Сейчас я в первую очередь хочу собрать обратную связь, чтобы понять, в каком направлении лучше дорабатывать библиотеку. При этом у меня уже есть идеи по её дальнейшему развитию: сделать текущий модуль частью более широкого решения, например общего casbin-decorator с extras для FastAPI, FastMCP, Flask и других фреймворков.
Нет, но в целом можно добавить