Forge

docs/ / design-rationale.md · branch main

Зачем гибридный индекс и почему он устроен именно так

Это текст для человека, который открывает репозиторий MCP: зачем слой между агентом и кодовой базой и почему выбраны конкретные компромиссы. Формальное архитектурное решение с нумерацией ADR относится к CascadeIDE — см. ADR 0105 (Accepted · Implemented). Интеграция продукта в IDE — ADR 0106.


Какую проблему решаем

Агенту и человеку в IDE нужно быстро сузить область поиска: куда смотреть, какие файлы открыть, какие символы потом проверять Roslyn’ом. «Перечитать полрепозитория» или десятки вызовов навигации — слишком дорого по шагам и по контексту модели.

При этом для C# у нас уже есть единственный надёжный источник для опасных операций (переименование, usages, семантический impact) — это Roslyn. Индекс не должен создавать иллюзию «ещё один компилятор».


Почему два слоя: Roslyn и «слой B»

  • Roslyn даёт истину по символам там, где есть семантическая модель.
  • Часть артефактов Roslyn не индексирует как символы (или не индексирует вообще): Razor/Blazor разметка, AXAML, markdown, конфиги, пайплайны, CSS/HTML. Там нужен хотя бы полнотекст и эвристики, чтобы не грепать всё дерево вслепую.
  • *.cs в FTS опционально и осознанно «как текст»: это помощь для ориентации и поиска по строкам/идентификаторам, не замена поиску символов. Иначе агент перепутает «попало в топ» с «семантически это то же».

Отсюда же требование явной метки типа попадания (hit_kind и связанные поля в ответах): человек или оркестратор должен понимать, перед ним текстовое совпадение или путь к следующему вызову Roslyn.


Почему SQLite FTS5 (+ опционально вектора в том же мире)

  • Нужен один локальный артефакт на workspace/решение без обязательного Docker и без обязательного отдельного сервера в baseline установки.
  • FTS5 — зрелый keyword-слой с предсказуемой стоимостью и маленьким operational footprint для Windows/Linux/macOS.
  • Векторный канал (semantic) — включение по желанию: отдельные провайдеры эмбеддингов, отдельные настройки; keyword остаётся основой «всегда работает».

Тяжёлые альтернативы класса «всегда включённый граф + Qdrant + контейнеры» откладываем: они хороши для исследований, но плохо совпадают с целью «поднять и искать локально».


Почему отдельный процесс MCP, а не только библиотека внутри IDE

  • Те же tool id и JSON-контракты можно вызывать из Cursor/другого хоста MCP без запуска Avalonia и без общей памяти с IDE.
  • Индекс, watcher и SQLite обновления изолированы: сбои и перезапуск не привязаны жёстко к UI-процессу CascadeIDE.

IDE может позже использовать то же ядро in-process или тот же бинарник как дочерний процесс — контракт остаётся общим.


Почему эвристики Razor / AXAML в виде «заголовков» к чанку (__hci_*)

Полный парсер Razor/XAML давал бы точность ценой сложности и зависимостей. На первом слое нужно ускорить поиск ключевых слов: директивы (@page, @inject, …), обработчики, ресурсы, пары файл–code-behind. Эти строки добавляются в начало текстового содержимого артефакта при индексации так, чтобы FTS нашёл их по запросу, не притворяясь синтаксическим деревом.

Это сознательно подсказка для ориентации, а не замена редактору форм или анализатору AXAML/CDS в IDE.


Что сознательно не делаем в этом MCP

  • Не заменяем Roslyn для рефакторингов по C#.
  • Не строим канонический semantic graph приложения как у карты намерений в CascadeIDE (0106): индекс — вход для orientation, не источник графа управления UI.
  • Не тащим в baseline обязательный Docker/облако — только опции.

Куда смотреть дальше

Документ Содержание
ADR 0105 в CascadeIDE Решение, слои, глоссарий, план внедрения, эскизы чанкинга и фьюжна
MCP-TOOLS Описание инструментов MCP (генерируется из кода)
README Установка, settings.toml, быстрый старт
View only · write via MCP/CIDE