| 1 | # ADR 0105: Hybrid Codebase Index (ядро + MCP) for C# stacks with Roslyn Truth |
| 2 | |
| 3 | **Статус:** Accepted · Implemented |
| 4 | **Дата:** 2026-05-06 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR | Роль | |
| 9 | |-----|------| |
| 10 | | [0039](0039-workspace-navigation-affordances.md) | Навигация по workspace — несколько представлений и «текущий файл + связанные» | |
| 11 | | [0040](0040-lsp-launch-line-settings-toml-presets-and-environment.md) | LSP (C# / Markdown) — командная строка в `settings.toml`: пресеты, опциональные ключи, переопределение через окружение | |
| 12 | | [0052](0052-agent-contract-cli-and-snapshot-tests.md) | CLI для контракта агента (паритет с MCP) и снапшот-тесты | |
| 13 | | [0053](0053-semantic-map-control-flow-pfd.md) | Карта намерений и поток управления на PFD (control flow) | |
| 14 | | [0056](0056-semantic-map-pipeline-adoption.md) | Semantic Map adoption of Skia composition pipeline | |
| 15 | | [0067](0067-graph-backed-surfaces-contract.md) | Graph-backed surfaces — общий контракт для семейства графовых экранов | |
| 16 | | [0069](0069-markdown-preview-tool-surface-and-renderer-decoupling.md) | Markdown Preview — инструмент MFD, renderer-first decoupling и отказ от inline preview в документе | |
| 17 | | [0079](0079-ide-display-system-ids-overlay-pipeline.md) | IDS vs CDS; AXAML индекс — не IDS | |
| 18 | | [0095](0095-workspace-solution-ide-health-stratification.md) | Три уровня Health — Workspace, Solution, IDE (таксономия каналов) | |
| 19 | | [0097](0097-cockpit-compute-units-transport-to-channel-dto.md) | Вычислительные блоки кабины (CCU; аналог LRU *Unit*) — слой между транспортом, смыслом и каналом | |
| 20 | | [0098](0098-semantic-first-document-as-projection.md) | Семантика первична; документ и репозиторий — проекции (Semantic-First) | |
| 21 | | [0099](0099-ide-databus-typed-events-and-projections.md) | IDE DataBus — типизированные события и проекции состояния | |
| 22 | | [0100](0100-project-constitution.md) | Конституция проекта | |
| 23 | | [0101](0101-licensing-and-commercialization-strategy.md) | Лицензирование и стратегия коммерциализации | |
| 24 | | [0102](0102-data-acquisition-layer-boundary-and-contract.md) | Data Acquisition Layer — граница внешних интерфейсов и адаптеров | |
| 25 | | [0106](0106-hybrid-codebase-index-cascadeide-integration-and-semantic-map.md) | Hybrid Codebase Index — интеграция в CascadeIDE, свежесть и Semantic Map | |
| 26 | ## Резюме |
| 27 | |
| 28 | - **Hybrid codebase index:** переносимое ядро + MCP; **Roslyn — истина для C#**. |
| 29 | - SQLite **FTS5** (keyword) + опциональный **vec** (semantic); fusion α/β. |
| 30 | - Scope: C#, Razor, AXAML, web-стеки в одном workspace; ADR 0106 — интеграция в CIDE. |
| 31 | |
| 32 | |
| 33 | --- |
| 34 | |
| 35 | <a id="adr0105-glossary"></a> |
| 36 | |
| 37 | ## Термины и сокращения |
| 38 | |
| 39 | Рабочие определения **в рамках этого ADR**; детали алгоритмов — по документации SQLite / выбранного провайдера эмбеддингов. |
| 40 | |
| 41 | | Термин | Смысл здесь | |
| 42 | | --- | --- | |
| 43 | | **FTS** (*full-text search*) | Полнотекстовый поиск: индекс и запросы по **токенам/словам** внутри текстов документов (файл или чанк), а не только «точное совпадение поля» или поиск по имени файла. | |
| 44 | | **FTS5** | Пятый модуль полнотекстового поиска **SQLite**: виртуальные таблицы FTS5, инвертированный индекс «термин → вхождения в документах», запросы с учётом релевантности. В этом ADR — основной **keyword**-backend слоя B. | |
| 45 | | **Инвертированный индекс** | Структура «слово/термин → список документов (и позиций)», на которой строится быстрый FTS; не путать с **графом символов** Roslyn. | |
| 46 | | **BM25** (*Best Matching 25*, семейство Okapi BM25) | Класс статистических **функций ранжирования** полнотекстовых попаданий: баланс «термин часто в этом документе» vs «термин редок в корпусе». В SQLite FTS5 релевантность задаётся через вспомогательные функции ранга (в т.ч. **`bm25()`**); в тексте ADR «keyword / BM25» означает **полнотекст с таким ранжированием**, а не отдельный движок вне SQLite. | |
| 47 | | **Keyword-поиск** | Поиск по **совпадению слов/фраз** (через FTS), без обязательного «понимания смысла» запроса разными формулировками. | |
| 48 | | **Эмбеддинг (embedding)** | Вектор фиксированной размерности, полученный моделью из текста (фрагмент кода, абзац, запрос). Похожие по смыслу тексты в идеале получают **близкие** векторы в выбранной метрике. | |
| 49 | | **Semantic / векторный поиск** | Отбор фрагментов по **близости эмбеддингов** запроса и чанков (косинусная близость и т.п.), а не по совпадению ключевых слов. В ADR обозначается также как **vec** (vector channel). | |
| 50 | | **Vector store** | Хранилище векторов и метаданных (идентификатор чанка, путь, диапазон строк), с операциями ближайших соседей (ANN / полный перебор на малых объёмах). | |
| 51 | | **sqlite-vec** | Расширение **SQLite** для хранения и запроса векторов; в этом ADR — опциональный локальный vector store **рядом** с FTS, не заменяя keyword-слой. | |
| 52 | | **Фьюжн (fusion)** | Объединение списков попаданий из **двух каналов** (здесь FTS и vec): нормализация скоров, взвешенная сумма или эквивалент, итоговый top‑N. См. [§ эскиз фьюжна](#adr0105-impl-sketch-fusion). | |
| 53 | | **Чанк (chunk)** | Непрерывный фрагмент файла, индексируемый как одна единица FTS/vec (строковое окно, логический блок и т.д.); см. [§ чанкинг](#adr0105-impl-sketch-chunking). | |
| 54 | | **MCP** | *Model Context Protocol* — транспорт и контракт tools для агентов/IDE; отдельный MCP-сервис индекса описан в [§ развёртывание](#adr0105-deployment). | |
| 55 | | **DAL** | *Data Acquisition Layer* — слой получения данных из workspace и внешнего мира по [0102](0102-data-acquisition-layer-boundary-and-contract.md). | |
| 56 | | **CCU** | *Cockpit Compute Unit(s)* — упаковка вычислительных результатов в стабильные DTO для каналов по [0097](0097-cockpit-compute-units-transport-to-channel-dto.md). | |
| 57 | |
| 58 | --- |
| 59 | |
| 60 | <a id="adr0105-context"></a> |
| 61 | |
| 62 | --- |
| 63 | ## Контекст |
| 64 | |
| 65 | CascadeIDE — MCP-first IDE: агенту нужно быстро ориентироваться в кодовой базе и собирать контекст в малом окне модели (или при ограниченном бюджете шагов/вызовов). |
| 66 | |
| 67 | Для **любых** .NET/C# решений у нас уже есть “источник истины” для точных семантических операций: |
| 68 | |
| 69 | - Roslyn (через roslyn-mcp и IDE wiring) для: diagnostics, go-to-definition, find-usages, rename, symbol-level navigation. |
| 70 | |
| 71 | Но Roslyn не решает полностью задачу: |
| 72 | |
| 73 | - быстрый “обзор по смыслу” и “первую карту” решения без чтения десятков файлов; |
| 74 | - полнотекст и ориентация по **Markdown**, конфигам, `.csproj` / `.sln` / `.slnx`, YAML/TOML, **веб-слою** (**Razor/Blazor `.razor`**, HTML/CSS), разметке **Avalonia (`.axaml`)** и другим артефактам **без** семантической модели Roslyn для этих форматов; |
| 75 | - для **обычного** C#‑проекта (включая сам **CascadeIDE**) тот же гибридный слой даёт быстрый keyword/опц. semantic по **репозиторию целиком** — в том числе по **тексту `.cs`** ([слой B](#adr0105-layer-b): только FTS, не символы), пока переименование/impact остаются на Roslyn; |
| 76 | - устойчивость между сессиями: “карта” должна жить рядом с проектом/профилем IDE и не требовать каждый раз переобучения агента. |
| 77 | |
| 78 | Есть внешние решения (например SocratiCode) с hybrid search + graph + impact, но они добавляют инфраструктурную нагрузку (Docker/Qdrant/Ollama), а также риск лицензий (AGPL) для интеграции в продукт. |
| 79 | |
| 80 | Дополнительно: CascadeIDE кроссплатформенный (Avalonia). Мы не хотим делать критичный слой навигации завязанным на Windows-only/драйверы/Docker, но на Linux можем разрешать более “тяжёлые” backend-опции. |
| 81 | |
| 82 | --- |
| 83 | |
| 84 | <a id="adr0105-decision-summary"></a> |
| 85 | |
| 86 | ## Решение в одном предложении |
| 87 | |
| 88 | Ввести **двухслойную модель навигации**: **Roslyn — источник истины для C# семантики**, а рядом — **лёгкий гибридный индекс** по **контуру решения**: веб‑артефакты (`.razor`, MD, HTML/CSS), **Avalonia `.axaml`** (и при необходимости эвристика пары с code-behind `.cs`), конфигурация и сопровождение (**в т.ч. опционально полнотекст по `.cs` как тексту**, без подмены symbol-level операций); keyword + опциональная семантика; минимальная ops‑цена и кроссплатформенность. |
| 89 | |
| 90 | --- |
| 91 | |
| 92 | <a id="adr0105-goals"></a> |
| 93 | |
| 94 | ## Цели |
| 95 | |
| 96 | 1. **Снизить число шагов агента**: 1–2 вызова → достаточно релевантного контекста для решения. |
| 97 | 2. Дать “первую карту” без “прочитать 20 файлов”: топ-файлы/узлы/потоки, входные точки — для **Blazor/Web**, для **Avalonia (AXAML + привязки/имена контролов)** и для **обычного C#**, в том числе при **разработке самого CascadeIDE** на том же стеке инструментов. |
| 98 | 3. Сохранить **семантическую корректность**: refactor-impact по C# не эвристический, а Roslyn-based. |
| 99 | 4. Работать **без обязательного Docker** (особенно на Windows), с предсказуемой локальной установкой/обновлением. |
| 100 | 5. Быть кроссплатформенным (Windows/Linux/macOS), с optional backend-ускорителями на Linux. |
| 101 | |
| 102 | --- |
| 103 | |
| 104 | <a id="adr0105-non-goals"></a> |
| 105 | |
| 106 | ## Не-цели (на первом этапе) |
| 107 | |
| 108 | - Полный “polyglot dependency graph” по 18+ языкам. |
| 109 | - Замена Roslyn MCP: Roslyn остаётся истиным слоем для C#. |
| 110 | - Обязательная векторная БД/контейнеры для базовых сценариев. |
| 111 | - “Один граф, который всегда прав”: граф/impact вне C# допускает эвристику и требует верификации. |
| 112 | |
| 113 | --- |
| 114 | |
| 115 | <a id="adr0105-architecture"></a> |
| 116 | |
| 117 | ## Архитектура (в терминах слоёв) |
| 118 | |
| 119 | <a id="adr0105-layer-a"></a> |
| 120 | |
| 121 | ### Слой A: Roslyn Truth (C#) |
| 122 | |
| 123 | Использовать Roslyn для: |
| 124 | |
| 125 | - diagnostics / code actions; |
| 126 | - find usages / rename; |
| 127 | - symbol navigation; |
| 128 | - (по возможности) call graph / entrypoints в пределах C# проекта. |
| 129 | |
| 130 | Этот слой — **точный**, но “дорогой” по workflow: агенту всё равно нужно знать, *что искать*. |
| 131 | |
| 132 | <a id="adr0105-layer-b"></a> |
| 133 | |
| 134 | ### Слой B: Hybrid Index (артефакты вокруг C#, веб-слой, Avalonia AXAML, опционально текст `.cs`) |
| 135 | |
| 136 | Индекс для файлов и фрагментов **вне** Roslyn-символики или **как текст** (не как граф типов): |
| 137 | |
| 138 | - `.razor`, `.razor.cs` (включая связь partial / file pairing); |
| 139 | - `.md` / `.mdx`; |
| 140 | - `.html`, `.css`, `.scss` (включая `@import`, классы/селекторы); |
| 141 | - базовые конфиги (`appsettings*.json`, `.editorconfig`, `*.props`, `*.targets`, `*.csproj`, `*.slnx`, pipeline YAML, `*.yml`, `*.toml` и т.п.); |
| 142 | - **`.axaml`** (и типичный code-behind `*.axaml.cs`, если есть): разметка и атрибуты — **как текст для FTS** и лёгких эвристик (`x:Name`, `{Binding …}`, `Classes=`, пути `avares:`); **не** подмена XAML-Avalonia-парсера, **не** семантика CDS/IDS (см. [0079 — CDS vs IDS](0079-ide-display-system-ids-overlay-pipeline.md#adr0079-cds-vs-ids)); |
| 143 | - **`*.cs` (опция индекса):** только **полнотекст/keyword** (идентификаторы и строки встречаются как совпадения в тексте файла); **rename/find-usages/impact** по-прежнему только Roslyn. В ответах инструмента явно помечать hits по `.cs` как **text-ranked**, чтобы не смешать с символьной истиной. |
| 144 | |
| 145 | Индекс предоставляет: |
| 146 | |
| 147 | - **keyword / BM25**: строки конфигов, CSS, маршруты Razor, фрагменты `.cs`/`.axaml`/доков; |
| 148 | - **опционально semantic**: поиск “по смыслу” (через embeddings), но без обязательного Docker. |
| 149 | |
| 150 | Данные индекса: |
| 151 | |
| 152 | - хранятся локально (профиль IDE или рядом с проектом); |
| 153 | - обновляются инкрементально (watcher + hash); |
| 154 | - имеют явную версионность формата (чтобы migration не ломала UX). |
| 155 | |
| 156 | <a id="adr0105-storage"></a> |
| 157 | |
| 158 | #### Storage / backend (baseline) |
| 159 | |
| 160 | Рекомендуемая конфигурация по умолчанию (без Docker, кроссплатформенно): |
| 161 | |
| 162 | - **Keyword/BM25**: SQLite **FTS5** (локальная БД на диске) как быстрый полнотекстовый индекс. |
| 163 | - **Semantic vectors (optional)**: SQLite + **`sqlite-vec`** как локальный vector store (включается только при включённой семантике). |
| 164 | |
| 165 | Движок здесь — **классический SQLite** (например `Microsoft.Data.Sqlite` или другой провайдер к той же библиотеке SQLite), **не** [WitDatabase](https://github.com/dmitrat/WitDatabase) (`*.witdb`): Wit остаётся для данных приложения CascadeIDE; файл индекса — отдельный SQLite на диске. |
| 166 | |
| 167 | Важно: hybrid = **FTS (keyword)** + **vec (semantic)** как два независимых подиндекса, объединяемых на уровне сервиса (ранжирование/фьюжн), а не “магия одной БД”. |
| 168 | |
| 169 | <a id="adr0105-layer-c"></a> |
| 170 | |
| 171 | ### Слой C: Composition (агентский workflow, переносимо) |
| 172 | |
| 173 | Дефолтный сценарий агента (вне конкретной IDE): |
| 174 | |
| 175 | 1. Hybrid search (быстро, дешево) → топ-N фрагментов и карта. |
| 176 | 2. Roslyn navigation для точной проверки/рефакторинга в C#. |
| 177 | 3. Точечное чтение файлов/фрагментов только после поиска. |
| 178 | |
| 179 | **Встраивание этого сценария в CascadeIDE** (кнопки, каналы, debounce reindex, CCU/DataBus, Semantic Map) — **[ADR 0106](0106-hybrid-codebase-index-cascadeide-integration-and-semantic-map.md)**. |
| 180 | |
| 181 | <a id="adr0105-deployment"></a> |
| 182 | |
| 183 | ### Развёртывание: библиотека + отдельный MCP |
| 184 | |
| 185 | Индекс оформлять как **общую библиотеку** (ядро: индексация, SQLite, форматы запроса/ответа) и **отдельный MCP-сервер** (тонкий слой stdio + регистрация tools), чтобы: |
| 186 | |
| 187 | - использовать поиск **вне контура CascadeIDE** (другие IDE/агенты с MCP, CLI, автоматизация); |
| 188 | - изолировать тяжёлый процесс (watcher, файлы SQLite, опционально embeddings): перезапуск и обновления не смешиваются с Avalonia/UI. |
| 189 | |
| 190 | CascadeIDE может подключать **то же ядро in-proc** или поднимать **тот же бинарник MCP** как дочерний процесс — **идентификаторы и контракт tools** сохраняются общими для обоих сценариев (детали размещения по слоям кабины — [0106](0106-hybrid-codebase-index-cascadeide-integration-and-semantic-map.md)). |
| 191 | |
| 192 | --- |
| 193 | |
| 194 | <a id="adr0105-config-ux"></a> |
| 195 | |
| 196 | ## Конфигурация и UX-инварианты |
| 197 | |
| 198 | - **Off-by-default по инфраструктуре**: если semantic embeddings требуют внешнего провайдера, это должно быть opt-in. |
| 199 | - **Кроссплатформенность**: одинаковые tool ids/контракты в MCP, разница только в backend-провайдере. |
| 200 | - **Работа в малом окне**: ответы инструментов должны быть “компактными по умолчанию” (top-N, с указанием пути/диапазона/score), с отдельной командой для расширения. |
| 201 | |
| 202 | --- |
| 203 | |
| 204 | <a id="adr0105-impl-watchouts"></a> |
| 205 | |
| 206 | ## На что смотреть при внедрении |
| 207 | |
| 208 | Операционные моменты, без которых dogfood и продакшен быстро разочаруют: |
| 209 | |
| 210 | <a id="adr0105-impl-watchouts-volume"></a> |
| 211 | |
| 212 | 1. **Объём и шум.** FTS по всем `*.cs` раздувает индекс и может **засорять топ-N** сырьевыми строковыми попаданиями. Нужны явные **умолчания и фильтры** в `settings.toml` (или эквивалент): игноры/`gitignore`-согласование, маски путей, **ранжирование** (например приоритет документов/конфигов перед «сырым» `.cs`, или наоборот — режим «сначала код»), возможность временно исключить `*.cs` из FTS без отключения остального индекса. |
| 213 | |
| 214 | <a id="adr0105-impl-watchouts-freshness"></a> |
| 215 | |
| 216 | 2. **Свежесть (freshness)** при сохранениях из **CascadeIDE**. Дёшевый инкремент и UX без лагов — **[ADR 0106](0106-hybrid-codebase-index-cascadeide-integration-and-semantic-map.md)**. В MCP/ядре возможен watcher и инкрементальный reindex; продуктовая связка с сессией редактора — в IDE. |
| 217 | |
| 218 | <a id="adr0105-impl-watchouts-hit-kind"></a> |
| 219 | |
| 220 | 3. **Контракт MCP с первого прототипа.** В структуре ответа поиска — **стабильное поле типа попадания** (например `hit_kind`: `text_fts` / `text_vector` / `symbol_followup_roslyn` или эквивалент), чтобы агент и человек не гадали по свободному тексту. Менять семантику поля позже дороже, чем заложить его в v0. |
| 221 | |
| 222 | --- |
| 223 | |
| 224 | <a id="adr0105-alternatives"></a> |
| 225 | |
| 226 | ## Альтернативы и почему нет (сейчас) |
| 227 | |
| 228 | <a id="adr0105-alt-roslyn-grep"></a> |
| 229 | |
| 230 | ### A) “Только Roslyn + grep” |
| 231 | |
| 232 | Плюсы: минимальная инфраструктура, высокая точность для C#. |
| 233 | Минусы: слишком много шагов и чтения файлов для агентных сценариев; плохо покрывает docs/config/web и **глобальный** “где упомянуто” по репозиторию, если не считать тяжёлый только-Roslyn обход. |
| 234 | |
| 235 | <a id="adr0105-alt-socraticode"></a> |
| 236 | |
| 237 | ### B) Встроить SocratiCode целиком |
| 238 | |
| 239 | Плюсы: готовый hybrid+graph+impact слой, быстрое “orientation” по большому репо. |
| 240 | Минусы: |
| 241 | - ops: Docker/Qdrant/Ollama в baseline; |
| 242 | - корректность графа вне C# зависит от эвристик; |
| 243 | - **лицензия AGPL** — нежелательна для встраивания в продукт (см. [0101](0101-licensing-and-commercialization-strategy.md)). |
| 244 | |
| 245 | <a id="adr0105-alt-lsp-all"></a> |
| 246 | |
| 247 | ### C) LSP для всего (полный polyglot) |
| 248 | |
| 249 | Плюсы: потенциальная семантическая точность по языкам. |
| 250 | Минусы: слишком большая операционная и интеграционная цена; не решает проблему “малое окно/мало вызовов” без отдельного индекса/ранжирования. |
| 251 | |
| 252 | --- |
| 253 | |
| 254 | <a id="adr0105-consequences"></a> |
| 255 | |
| 256 | ## Последствия |
| 257 | |
| 258 | <a id="adr0105-consequences-positive"></a> |
| 259 | |
| 260 | ### Положительные |
| 261 | |
| 262 | - Агент получает быстрый “первый проход” по решению **и** может **dogfood’ить** тот же индекс при разработке **самого CascadeIDE** и других C#‑репо без ограничения сценарием «только Blazor». |
| 263 | - Roslyn остаётся “истиной” для опасных операций (rename/impact/diagnostics). |
| 264 | - Docker становится optional: Windows-friendly baseline, Linux может получать расширенные режимы. |
| 265 | |
| 266 | <a id="adr0105-consequences-risks"></a> |
| 267 | |
| 268 | ### Негативные / риски |
| 269 | |
| 270 | - Появляется новый слой данных (индекс) → нужны версии, миграции, наблюдаемость. |
| 271 | - Есть риск ложных связей в `.razor`/CSS/HTML эвристиках → нужен “confidence” и явная маркировка, что это подсказка. |
| 272 | - Индекс по `.cs`/`.axaml` как текст может **случайно выглядеть** как «семантический find» → см. [§ на что смотреть при внедрении](#adr0105-impl-watchouts) ([`hit_kind`](#adr0105-impl-watchouts-hit-kind), [ранжирование](#adr0105-impl-watchouts-volume)). |
| 273 | - Нужно удерживать инструменты компактными, иначе hybrid-индекс может “спамить” контекстом и ухудшить UX. |
| 274 | |
| 275 | --- |
| 276 | |
| 277 | <a id="adr0105-rollout-plan"></a> |
| 278 | |
| 279 | ## План внедрения (переносимое ядро + MCP): статус |
| 280 | |
| 281 | | Шаг | Содержание | Контур ADR 0105 (реализовано) | |
| 282 | | --- | --- | --- | |
| 283 | | 1 | MCP-контракты (`search`, `status`, `reindex`, `explain-result`, версия/`hit_kind`); ядро в библиотеке | ✅ репозиторий **`hybrid-codebase-index`** | |
| 284 | | 2 | Keyword index, инкремент, игноры; FTS по `*.cs` опционально; watcher tool | ✅ | |
| 285 | | 3 | Razor / AXAML: пары `.razor`↔`.razor.cs`, `.axaml`↔`.axaml.cs`; заголовки эвристик `__hci_*` (директивы, ресурсы, привязки, теги) | ✅ (`HybridCodebaseIndex.Core` augment) | |
| 286 | | 4 | Embeddings opt-in (`settings.toml`), sqlite-vec optional | ✅ | |
| 287 | | 5 | IDE workflow + свежесть при сохранениях | → **[ADR 0106](0106-hybrid-codebase-index-cascadeide-integration-and-semantic-map.md)** | |
| 288 | | 6 | Умолчания области, чанкинг FTS, фьюжн FTS+vec | ✅ `settings.toml` + hybrid search | |
| 289 | |
| 290 | --- |
| 291 | |
| 292 | <a id="adr0105-impl-sketch-scope-chunk-fusion"></a> |
| 293 | |
| 294 | ## Эскиз: область индекса, чанки, фьюжн (FTS + vec) |
| 295 | |
| 296 | Дополнение к [плану внедрения](#adr0105-rollout-plan): разумные умолчания на спайке, без смены верхнеуровневой архитектуры ([слой B](#adr0105-layer-b), [storage](#adr0105-storage)). |
| 297 | |
| 298 | <a id="adr0105-impl-sketch-scope"></a> |
| 299 | |
| 300 | ### Область индекса |
| 301 | |
| 302 | - **Первичный якорь:** активный `.sln` / главный `.csproj` профиля CascadeIDE — тот же workspace-контур, что и Roslyn-сессия. |
| 303 | - **Расширение по умолчанию:** пути под **корнем workspace**, за вычетом согласованного **`.gitignore`** (при необходимости — `.cursorignore` против агентского шума) и **жёсткого denylist**: `bin/`, `obj/`, `node_modules/`, `.git/`, типовые каталоги кэшей тулов. |
| 304 | - **Монорепо:** одна БД индекса на пару **(workspace_root, solution_path)**; другое решение того же дерева — отдельный контур индекса (переключение профилем). Поле **`extra_include_roots`** в `settings.toml` для соседних каталогов (доки, внешний KB и т.п.) — **opt-in**. |
| 305 | |
| 306 | <a id="adr0105-impl-sketch-chunking"></a> |
| 307 | |
| 308 | ### Чанкинг для FTS |
| 309 | |
| 310 | | Тип | Стратегия | |
| 311 | | --- | --- | |
| 312 | | Компактные конфиги, небольшие `.md`, `.razor` в пределах лимита | Один FTS-документ на файл; верхний лимит размера документа (например 256–512 KiB) — конфигурируемо. | |
| 313 | | Длинные `.md`, `.cs`, `.axaml` | Скользящие **окна по строкам** (ориентир: 80–120 строк, overlap 10–15); стабильный `chunk_id`: путь + диапазон (`start_line` / offset). | |
| 314 | | `.razor` | По возможности **логические границы** (`@code`, крупные разметочные блоки); если не вышло дёшево — те же строковые окна. | |
| 315 | |
| 316 | **Свежесть:** при правке пересобирать только затронутые чанки; для маленьких файлов допускается пересборка целого документа. В ответе инструмента всегда указывать **путь и диапазон строк** (или offset), чтобы агент и человек открывали точку без угадываний. |
| 317 | |
| 318 | <a id="adr0105-impl-sketch-fusion"></a> |
| 319 | |
| 320 | ### Фьюжн keyword (FTS) и semantic (vec), v0 |
| 321 | |
| 322 | 1. Независимо получить **топ‑K** из FTS и из vec (внутренний K, ориентир 20–40; наружу после слияния — компактный top‑N). |
| 323 | 2. **Нормализовать** скоры внутри каждого канала (min-max или rank-based, например `1/(rank+R)`). |
| 324 | 3. Объединить множество уникальных чанков: итоговый score **`S = α·S_fts + β·S_vec`**; если чанка нет в канале — вклад этого канала **0**. |
| 325 | 4. **Дефолт при включённом vec:** `α ≈ 0.65`, `β ≈ 0.35`; при выключенном vec — только FTS. |
| 326 | 5. **Короткий запрос (1–2 токена)** или низкий max `S_vec`: усилить вклад FTS или не смешивать vec (keyword-доминирующий режим). |
| 327 | |
| 328 | В DTO по возможности сохранять **оба вклада** (`fts_score`, `vec_score` при наличии) вместе с `hit_kind` и итоговым рангом — чтобы объяснимость («почему в топе») не терялась. Пороги и веса выносить в `settings.toml` без ломки формата ответа на следующих итерациях. |
| 329 | |
| 330 | |