# RAGRAF

**Графово-векторная база знаний о коде для LLM-агентов.**

[**Сайт**](https://ragraf.ru) · [**Вики**](https://github.com/paulmann/RAGRAF/wiki) · [**Документация (Pages)**](https://paulmann.github.io/RAGRAF/) · [**Релизы**](https://github.com/paulmann/RAGRAF/releases) · [**Обсуждения**](https://github.com/paulmann/RAGRAF/discussions)

![RAGRAF — графово-векторная база знаний о коде для LLM-агентов: 40 инструментов MCP, проверяемые факты со ссылкой файл:строка, полностью локально](assets/social-preview.png)

Ассистент, который отвечает на вопросы агента о кодовой базе — *где это лежит, кто это вызывает, что сломается при правке, как сделано похожее рядом* — проверяемыми фактами (`файл:строка`) вместо слепого `rg` и чтения файлов целиком. Python 3.13+, SQLite (граф + FTS5 + векторы в одном файле), tree-sitter, локальные эмбеддинги без torch. **Всё работает на машине, где лежит код**: сервис поднимать не нужно, индекс в облако не уходит — локальный RAG-индекс по вашему репозиторию. Необязательный слой графа свойств кода (Java + Joern) открывает срезы; без него продукт работает и честно об этом говорит.

---

## Содержание

- [Что это и зачем](#что-это-и-зачем)
- [Сценарии](#сценарии)
- [Возможности](#возможности)
- [Проект в числах](#проект-в-числах)
- [Как это устроено](#как-это-устроено)
- [Установка](#установка)
- [Первые шаги](#первые-шаги)
- [Требования и ограничения](#требования-и-ограничения)
- [Документация](#документация)
- [Разработка](#разработка)
- [Участие](#участие)
- [Лицензия](#лицензия)

---

## Что это и зачем

Агент, работающий над доработкой кода, тратит основную часть контекста на **поиск места**: где определена функция, кто её вызывает, как сделано похожее рядом. Привычный путь — `rg` плюс чтение файлов целиком.

RAGRAF заменяет этот путь индексом. Агент задаёт вопрос фиксированной операцией и получает факт со ссылкой `файл:строка`, а не десять кандидатов на просмотр.

Замерено на реальном проекте (PHP-портал, 14 задач навигации; прогон сделан на машине автора — см. «что именно лежит в артефактах» ниже):

| Показатель | Без индекса | С индексом |
|---|---|---|
| Вызовов инструментов на 14 задач | 28 (реалистично 43) | **14** |
| Среднее на задачу | 2,0 / 3,1 | **1,0** |
| Кандидатов к просмотру | до 34 файлов | 1–5 точных |
| Читается файлов целиком | 14 (минимум) | **0** |
| Попадание в файл-цель с первого запроса | — | **92%** (12 из 13) |
| Проверяемость (факты со ссылкой `файл:строка`) | — | **100%** |

Числа вызовов, попадания и проверяемости — **измерения** того прогона; его сырые артефакты в публикуемое дерево не входят (пункт `R-REL-1` в [`ROADMAP.md`](ROADMAP.md)). Зато в поставке есть артефакт графовой метрики: [`bench/results/M2_rev-0012.json`](bench/results/M2_rev-0012.json) и [`M2_rev-0025.json`](bench/results/M2_rev-0025.json) измеряют **полноту impact-анализа** на том же портале — доходит ли граф до файлов, которые действительно менялись вместе. Средний recall **0,771 → 0,917** на 20 и 8 коммитах при глубине 3, медианный recall **1,0**, precision 0,072 → 0,020 (низкий намеренно: метрика считает связность, а не предсказание) при наивном baseline **0,0**.

«Реалистично 43» — модельная поправка (агент просматривает до 5 кандидатов вместо одного), и она записана в самом артефакте.

Важная оговорка, которую обычно опускают: **выигрыш в 2–3 раза относится к задачам локализации** («где определено», «кто вызывает»). В цикле правки «прочитал → изменил → проверил» экономии по числу вызовов почти нет — там выигрыш в другом: правки не ломают индекс, а спорный SQL проверяется до запуска.

---

## Сценарии

| Что вы делаете | Что спросить у RAGRAF | Что придёт в ответ |
|---|---|---|
| Вводите агента в незнакомый репозиторий на 200 тысяч строк | `repo_map`, затем `search` / `symbol` | один факт на вопрос, со ссылкой `файл:строка`, вместо стены кандидатов |
| Рефакторите функцию, которую вызывают из десятка мест | `callers`, `impact`, `slice` при доступном CPG | доказанные связи отдельно от эвристик; срез, который говорит, что именно покрывает |
| Переименовываете или удаляете колонку БД | `write_check` **до** запуска SQL, затем `table_usage` | отсутствующие колонки с ближайшими именами; кто читает и кто пишет таблицу |
| Разбираете чужой диф | `diff`, `drift_report`, `live_read` | изменившиеся символы и рёбра, включая регрессии, и текущий файл с отметкой расхождений |
| Ищете копии (`Files.php` … `Files7.php`) | `duplicates` | какие файлы — копии и какая копия **доказанно** рабочая |
| «Как это сделано в других местах кода?» | `search` (BM25 + векторы, гибридно) | ранжированные фрагменты корпуса; для самих ответов модель эмбеддингов не нужна |
| Подключаете индекс к агенту | **40 инструментов MCP** `ragraf_*` или CLI | те же операции по stdio — см. [`docs/ru/03_implementation/INTEGRATION.md`](docs/ru/03_implementation/INTEGRATION.md) |

---

## Возможности

**38 операций** над репозиторием — фиксированный набор, без языка запросов к графу:

| Операция | Отвечает на вопрос |
|---|---|
| `search` | где об этом написано (гибридно: лексика BM25 + вектор) |
| `search_multi` | где встречается сразу несколько строк; копии файлов и какой из них рабочий |
| `duplicates` | какие файлы — копии друг друга и чем доказана активность главного |
| `entrypoints` | точки входа: маршруты, HTTP-обработчики, CLI, endpoint'ы разметки |
| `dead_code` | файлы и подпрограммы без ссылок и вне достижимости |
| `symbol` | где определён символ: вид, файл, строки, сигнатура |
| `references` | где ещё используется |
| `callers` / `callees` | кто вызывает / кого вызывает |
| `impact` | что затронет изменение (доказанные и эвристические связи раздельно) |
| `slice` | структурный срез: узлы, рёбра, строки — без тел функций |
| `code` | тела символов (только по явному запросу) |
| `repo_map` | карта репозитория в заданном бюджете символов |
| `schema` / `table_usage` | что в таблице БД и кто её читает или пишет |
| `routes` | маршруты и точки входа |
| `policy_trace` | кто и по какому условию получает право |
| `class_usage` | класс оформления: где определён, где использован, что расходится |
| `write_check` | можно ли так записать (сверка плана записи со схемой до запуска) |
| `live_read` | актуальный файл с выделением отличий от индекса |
| `freshness` | актуален ли индекс (сверка контрольной суммы) |
| `index_status` | ревизия, покрытие, деградация, размер журнала |
| `drift_report` / `drift_ack` | журнал расхождений между индексом и кодом |
| `catalog` | реестр корпусов: что проиндексировано и с какими суммами |
| `calibrate` | калибровка порогов |
| `usage` | телеметрия обращений и оценка эффекта |
| `diff` | что изменилось между ревизиями: файлы, символы, рёбра, регрессии (P2-1) |
| `task_stats` | отчёт по задаче: обращения к индексу, решения гейта (§3.4) |
| `gate` | решение гейта по вызову инструмента: `allow` / `ask` / `deny` (§3.2) |
| `note` / `notes` | записать и прочитать заметку о решении — знание между сессиями (P2-3) |

Ещё два режима — не операции, а форма ответа: **`answer=true`** отдаёт
сформулированный ответ со ссылками вместо структурного результата (P2-2), а
`brief=true` — краткую оболочку ответа. `usage` показывает метрики эффекта
(`saved_calls`, `hit_rate`, `avg_ms`, `misses`, `stale_served`).

Те же операции доступны как **40 инструментов MCP** (`ragraf_*`) — для подключения к агенту как сервер, и через CLI. Отдельная группа инструментов — живой слой баз данных: `ragraf_db_schema`, `ragraf_db_table`, `ragraf_db_relations`, `ragraf_db_sample`, `ragraf_db_drift`, `ragraf_db_cross`.
Двадцать четвёртый — `use_project`: выбор корпуса, когда один сервер обслуживает несколько проектов. `context` отвечает, какой корпус выбран и на каком основании: без него ответы о чужом проекте было неотличимы от ответов о своём.

**Шестнадцать языков** разбираются деревом (узлы и рёбра графа): PHP, Python, JavaScript, TypeScript, Java, C#, C, C++, Ruby, Lua, Go, Perl, bash, PowerShell, CSS, HTML — тринадцать общих профилей плюс отдельные извлекатели PHP, CSS и HTML. Ещё одиннадцать подключаются текстом — файлы находятся поиском, но узлов не дают: Markdown, SQL, YAML, JSON, TOML, INI, XML, RST, Rust, batch, обычный текст. Всего сопоставлено 55 расширений.

---

## Проект в числах

Все числа ниже измерены по публикуемому дереву **16.10.2026** — не переписаны из прежних текстов. Два главных из них сторожит `Test-DocumentedNumbers` в [`tools/Invoke-ProjectDoctrine.ps1`](tools/Invoke-ProjectDoctrine.ps1): он сверяет документы с кодом.

| Поверхность | Сколько | Откуда измерено |
|---|---|---|
| Операции фасада | **38** | `def op_*` в `src/ragraf/facade.py` |
| Инструменты MCP | **40** — из них 6 — живой слой баз | имена `ragraf_*` в `src/ragraf/mcp_server.py` |
| Ресурсы / подсказки MCP | 3 + 1 шаблон URI / 2 | `ragraf://status`, `ragraf://catalog`, `ragraf://corpus/{name}/map`; подсказки `ragraf-check`, `ragraf-repair` |
| Подкоманд CLI / операций `query` | 14 / **39** | `add_parser(…)` и `OPS` в `src/ragraf/cli.py` |
| Языков разбирается деревом | **16** | `TREE_LANGS` в `src/ragraf/config.py` |
| Языков подключается текстом | **11** | остальные значения `LANG_BY_EXT` |
| Расширений сопоставлено | 55 | `LANG_BY_EXT` |
| Маршрутов API админ-панели | 32 | `src/ragraf/admin_server.py` |
| Зависимостей времени выполнения | 7 (+1 необязательный набор `tls`) | `pyproject.toml` |
| Python в `src/` | 50 файлов · 37 592 строки | публикуемое дерево |
| PowerShell — установщик, обёртки, чекер | 5 файлов · 3 423 строки | публикуемое дерево |
| Markdown | 28 файлов (20 в `docs/`, из них 9 русских) + 15 страниц вики | публикуемое дерево и вики |
| Переносимых наборов тестов | 6 наборов · **164 проверки, 0 провалов** | каждый набор запущен отдельно |
| Реестр дефектов | 61 находка | [`docs/DEFECTS.md`](docs/DEFECTS.md); в сводке аудита по важности учтены 43 из них |
| Публикуемое дерево | 136 файлов · 3,5 МБ | публикуемое дерево |

Для масштаба: RAGRAF индексирует собственное рабочее дерево (648 файлов, 140 741 строка — больше этого публикуемого подмножества) в 3 620 символов, 46 296 рёбер и 3 417 чанков за **74 с**, из которых 63 с — необязательная стадия Joern/CPG (`rev-0156`, замер 16.10.2026; `capability=full`, 0 файлов с ошибкой). Подробный разбор — в [вики → Benchmarks and Limits](https://github.com/paulmann/RAGRAF/wiki/11-Benchmarks-and-Limits).

**Измеренный полигон, обезличенно.** В реестре **28 корпусов, 25 проиндексированы** — 10 со слоем CPG, 15 в режиме `degraded`. У 16 из них запись ревизии прочитана 16.10.2026: **7 527 файлов, 94 528 символов, 791 871 ребро, 86 790 чанков**. Названия проектов, пути и домены скрыты намеренно: метки упорядочены по размеру, а разрешает их только приватная карта автора.

| Корпус | Тип | Файлов | Символов | Рёбер | Режим |
|---|---|---|---|---|---|
| C-02 | веб-приложение на PHP | 2 722 | 32 761 | 355 192 | degraded |
| C-04 | служба / десктоп на C# | 1 274 | 20 331 | 98 605 | degraded |
| C-05 | веб-приложение на PHP | 928 | 17 381 | 99 029 | full |
| C-18 | набор автоматизации на PowerShell | 81 | 324 | 4 214 | degraded |
| C-24 | Markdown + bash (самый малый) | 18 | 184 | 1 515 | degraded |

Полная таблица на 16 строк, правила обезличивания и одна оговорка к подсчёту — в [вики → Benchmarks and Limits](https://github.com/paulmann/RAGRAF/wiki/11-Benchmarks-and-Limits). Оговорка важна при цитировании чисел: реестр корпусов и запись ревизии дают **разные** итоги для одной и той же ревизии (замерено на одном корпусе: 8 721 против 4 498 символов, 41 201 против 56 106 рёбер), поэтому все числа выше взяты из **записи ревизии** — той, которую отдаёт конверт ответа.

---

## Как это устроено

**Три хранилища SQLite** на корпус, в каталоге `.ragraf/` **внутри индексируемого проекта**:

| Хранилище | Что внутри |
|---|---|
| `graph.sqlite` | узлы (класс, функция, метод), рёбра (вызовы, наследование, импорты), схема БД |
| `lexvec.sqlite` | лексика FTS5 (BM25) и векторы в одном файле; сырой текст чанков для выдачи фрагментов |
| `control.sqlite` | ревизии, журнал расхождений, телеметрия обращений |

**Поток индексации:** `scan` (обход и контрольные суммы) → `ast` (tree-sitter: символы, вызовы, SQL) → `load` → `resolve` (имена) → `schema` (таблицы из миграций) → `cpg` (межпроцедурные вызовы через Joern) → `lexvec` (FTS5 + векторы).

**Три решения, определяющие поведение** — каждое выведено из измеренного дефекта:

1. **Неизменяемый индекс и журнал различий вместо «обновления по ходу».** Внутри ревизии индекс не меняется; правки кода копятся в журнале, а затронутые факты помечаются `stale`. Иначе факты разных моментов времени смешивались бы в одном ответе без различия — именно так и рождаются неверные выводы.
2. **Агенту не даётся язык запросов к графу.** Только фиксированные операции. Основание: в LLMxCPG (USENIX Security '25) базовые модели дают 132/1278 и 19/1278 валидных CPGQL-запросов против 1278/1278 у обученной — то есть свободный язык превращается в генератор ошибок.
3. **Каждый факт несёт доказательство.** `path:line`, `provenance` (`stated` — доказано, `derived` — эвристика), `index_rev`, `confidence`. Ребро без доказательства выглядит достоверно только потому, что пришло «из базы».

**Деградация вместо падения.** Отсутствие графа свойств кода даёт `capability=degraded` и понятный отказ операции `slice` с указанием фактического режима; остальные операции работают. Нет модели эмбеддингов — работает лексический поиск. Нет свободного порта — сервер сообщает причину. Молчаливой деградации не бывает.

---

## Установка

Требуется **Python 3.13 или новее**. Права администратора не нужны.

### Быстрая установка одной командой

Установщик скачивает пакет с GitHub и разворачивает его в диалоге:

```powershell
iwr -OutFile install.ps1 https://raw.githubusercontent.com/paulmann/RAGRAF/main/install.ps1
pwsh -NoLogo -NoProfile -File .\install.ps1
```

Он спросит каталог установки (по умолчанию `C:\RAGRAF`), создаст виртуальное окружение и поставит зависимости через `scripts/install.ps1`, предложит найти AutoClaw и DeepSeek Harness и настроить подключение, а в конце напечатает инструкцию по запуску панели управления и предупреждение о доступе к ней.

О том, чего он не делает, установщик говорит прямо: **значения для AutoClaw он показывает, но не записывает** — AutoClaw принимает MCP-серверы только через свой интерфейс, а его хранилище принадлежит продукту. Для **Harness** установщик умеет записать блок профиля: с резервной копией и последующей проверкой разбора. Найденная установка не перезаписывается молча, а репетиция без зависимостей доступна ключом `-SkipDeps`.

### Windows (PowerShell 7.6+)

```powershell
git clone https://github.com/paulmann/RAGRAF.git
cd RAGRAF
pwsh -NoLogo -NoProfile -File scripts/install.ps1
```

Скрипт создаст виртуальное окружение в `~/.ragraf/venv`, поставит зависимости и **проверит, что получилось работоспособное окружение** — шаг за шагом, с итоговой таблицей. Он не «делает вид, что установил»: каждый шаг заканчивается проверкой.

Полезные варианты:

```powershell
# установить и сразу подготовить корпус для своего проекта
pwsh -File scripts/install.ps1 -Project C:\work\myproject

# то же плюс полная индексация (скачает модель эмбеддингов ~240 МБ)
pwsh -File scripts/install.ps1 -Project C:\work\myproject -Index

# индексация без векторов: модель не скачивается, лексический поиск работает
pwsh -File scripts/install.ps1 -Project C:\work\myproject -Index -NoVectors

# в сети с TLS-инспекцией (корпоративный прокси)
pwsh -File scripts/install.ps1 -WithTruststore
```

### Другие платформы

Один общий путь, работает везде, где есть Python 3.13+:

```bash
git clone https://github.com/paulmann/RAGRAF.git
cd RAGRAF
python -m venv .venv
. .venv/bin/activate            # Windows: .venv\Scripts\Activate.ps1
pip install -e .                # или: pip install -r requirements.txt
ragraf --version
```

Без установки пакета продукт тоже работает — через обёртку, которая сама добавляет `src/` в путь:

```bash
python tools/ragraf.py --version
```

> `scripts/install.ps1` проверен на Windows (PowerShell 7.6, Python 3.14.7). Общий путь через `pip` на Linux и macOS **не проверялся** — продукт разрабатывался и замерялся на Windows.

### Внешний слой: Java и Joern (необязательно)

Для межпроцедурного графа (операция `slice`) нужны JDK 21 и Joern. Без них продукт работает: индекс строится, поиск и структура доступны, `slice` отказывает с причиной.

```powershell
pwsh -File scripts/install-joern.ps1
```

Архив кладётся в `.tools/downloads/` — скрипт идемпотентен. Распакованный комплект занимает около 5 ГБ.

---

## Первые шаги

```bash
# 1. Подготовить корпус: найти, досоздать, пересобрать отставший индекс.
#    Корпус для незнакомого каталога создаётся этой же командой.
ragraf ensure C:\work\myproject

# 2. Проверить окружение (отчёт по 11 компонентам).
#    ВНИМАНИЕ: команда ВСЕГДА возвращает код 0 — это не гейт, читайте отчёт.
ragraf -p <конфиг> selftest

# 3. Спросить
ragraf -p <конфиг> query search "задержка переиндексации"
ragraf -p <конфиг> query symbol --name corpus_hash
ragraf -p <конфиг> query code --name corpus_hash
ragraf -p <конфиг> query callers --name dedupe
ragraf -p <конфиг> query impact --target Facade --depth 2

# 4. Свежесть: изменился ли код после индексации
ragraf -p <конфиг> check
```

Полный список команд — `ragraf --help`. Важно: **глобальные ключи `--project/-p` и `--json` ставятся ДО подкоманды** (`ragraf -p cfg query search ...`), а собственные ключи подкоманды — после неё.

### Управление корпусом

```bash
ragraf init C:\work\myproject         # создать конфигурацию корпуса и показать путь к ней
ragraf -p <конфиг> register           # зарегистрировать разработку в реестре
ragraf -p <конфиг> index              # полная индексация
ragraf -p <конфиг> reindex            # переиндексация + архивация журнала расхождений
ragraf -p <конфиг> drift --scan       # зарегистрировать различия, НЕ меняя индекс
ragraf -p <конфиг> status             # состояние: ревизия, покрытие, размер журнала
ragraf -p <конфиг> usage              # телеметрия: обращения, факты, оценка эффекта
```

### Подключение к агенту как MCP-сервер

```json
{
  "mcpServers": {
    "ragraf": {
      "command": "python",
      "args": [
        "/path/to/RAGRAF/tools/ragraf-mcp.py",
        "--project", "/path/to/RAGRAF/examples/mycorpus.yaml",
        "--agent", "my-agent",
        "--agent-kind", "external"
      ]
    }
  }
}
```

`--project` обязателен. `--agent` и `--agent-kind` нужны только для раздельной статистики обращений: без них вызовы попадут в журнал как `unknown`.

### Панель настроек

```bash
python tools/ragraf-admin.py --no-browser
```

Открывается на `127.0.0.1:8777`, слушает только этот адрес. Показывает корпуса и состояние их индексов, размеры хранилищ, качество индекса, статистику обращений. Изменяющие запросы требуют токен доступа, который печатается при запуске.

---

## Требования и ограничения

| Что | Значение |
|---|---|
| Python | **3.13+** (объявлено `requires-python`; проверено на 3.14) |
| Платформа | Windows + PowerShell 7.6 — проверено; другие ОС — **не проверялись** |
| Права | не требуются: всё работает из пользовательского каталога |
| Диск | индекс корпуса `.ragraf/` — примерно 1 МБ на 1–2 файла исходников; внешний слой Java/Joern — ~5 ГБ |
| Интернет | нужен дважды: при установке (PyPI) и при **первой индексации с векторами** — скачивается модель эмбеддингов ~240 МБ в `~/.ragraf/models` |
| Java + Joern | необязательны; без них `capability=degraded` и `slice` недоступна |
| Видеокарта | необязательна; ускоряет только кодирование векторов и включается по порогу окупаемости |

**Про интернет и сертификаты.** В сети с TLS-инспекцией (корпоративный прокси) загрузка модели падает на проверке сертификата. Лечится установкой `truststore`:

```bash
pip install truststore      # или: install.ps1 -WithTruststore
```

В домашней сети пакет не нужен. Измерено: без него — отказ `certificate verify failed`, с ним — 240 МБ скачиваются за 9,2 с.

**Про cache модели.** Каталог кэша переопределяется переменной `RAGRAF_MODEL_CACHE`. Операции чтения модель не скачивают никогда — только индексация с векторами.

---

## Документация

| Документ | Что внутри |
|---|---|
| [ragraf.ru](https://ragraf.ru) | публичный сайт: возможности, измеренные бенчмарки, эмулятор админ-панели |
| [Вики](https://github.com/paulmann/RAGRAF/wiki) | 15 страниц: начало работы, справочник операций, CLI, MCP, слой CPG, диагностика, FAQ |
| [Документация (Pages)](https://paulmann.github.io/RAGRAF/) | этот набор документации с поиском — собирается и публикуется конвейером `pages.yml` |
| [`docs/ru/02_architecture/ARCHITECTURE.md`](docs/ru/02_architecture/ARCHITECTURE.md) | принципы, компоненты, схема хранилищ, контракт операций |
| [`docs/ru/02_architecture/TZ.md`](docs/ru/02_architecture/TZ.md) | функциональные и нефункциональные требования, критерии приёмки |
| [`docs/ru/03_implementation/INTEGRATION.md`](docs/ru/03_implementation/INTEGRATION.md) | подключение к агенту: MCP, правила работы, регламент |
| [`docs/ru/03_implementation/CPG_INTEGRATION.md`](docs/ru/03_implementation/CPG_INTEGRATION.md) | граф свойств кода: Joern, JDK, режимы деградации |
| [`docs/ru/skills/ragraf-core/SKILL.md`](docs/ru/skills/ragraf-core/SKILL.md) | навык работы с индексом: выбор операции, восстановление |
| [`docs/ru/05_article/RAGRAF_ARTICLE.md`](docs/ru/05_article/RAGRAF_ARTICLE.md) | обзорная статья: стек, архитектура, замеры |
| [`docs/DEFECTS.md`](docs/DEFECTS.md) | реестр найденных дефектов, у каждой находки — доказательство `файл:строка` |
| [`ROADMAP.md`](ROADMAP.md) | планируемые улучшения со стабильными идентификаторами (`R-*`) |

---

## Разработка

```bash
# тесты запускаются отдельными скриптами — единого раннера нет
python tests/test_lang_routing.py
python tests/test_watch.py

# чекер конвенций проекта (14 проверок)
pwsh -NoLogo -NoProfile -File tools/Invoke-ProjectDoctrine.ps1

# актуализация индекса самого RAGRAF
python tools/ragraf.py ensure .
```

В поставке — только те проверки, которые работают на **синтетических
фикстурах** и переносимы. Остальные замеряют поведение на реальных корпусах
автора (PHP-портал, C#-служба, конфигурации их проектов) и на другом коде
смысла не имеют.

Что проходит сразу после установки:

| Тест | Проверок |
|---|---|
| `test_lang_routing.py` | 56 |
| `test_watch.py` | 31 |
| `test_script_extract.py` | 25 |
| `test_threshold.py` | 23 |
| `test_ensure.py` | 17 |
| `test_csharp_records.py` | 12 |

Три проверки требуют того, чего нет в базовой установке, и это **не дефект
поставки**, а характер проверки:

* `test_joern_server.py` — нужен внешний слой Java + Joern (`scripts/install-joern.ps1`);
* `test_graph_algo.py` — нужен `torch` (около 2,5 ГБ), которого нет ни в `pyproject.toml`,
  ни в `requirements.txt`: графовые алгоритмы на видеокарте — необязательная ветка,
  и без `torch` она честно деградирует на процессор;
* `test_cpg_call_names.py` — нужен конфиг корпуса (каталог `config/` не публикуется);
  тест можно запустить, скопировав `examples/ragraf.example.yaml` в `config/` и
  указав в нём свой корень; без конфига он отказывается запускаться, а не «проходит» молча.

Десятый файл, `test_capability_consistency.py`, отвечает «неприменимо», пока нет конфига корпуса:
он проверяет, что заявленный `capability` соответствует содержимому графа. `test_graph_algo.py`
без `torch` всё равно прогоняет **7 проверок** и называет **17 свойств, которые проверить не смог**,
вместо зелёной строки над непроверенным кодом.

Чекер проекта так же честен про это публикуемое подмножество: из **14 проверок** здесь проходят
11, а 3 сообщают о файлах, которых в публичном дереве нет намеренно (конфиг корпуса,
`tests/test_dedupe.py`, `tests/test_text_from_index.py`) — это пункт `R-REL-1` в
[`ROADMAP.md`](ROADMAP.md).

`selftest` — **не гейт**: он печатает отчёт по 11 компонентам и всегда
возвращает код 0. Ненулевого кода у него не предусмотрено, поэтому «зелёный
selftest» сам по себе ничего не доказывает.

---

## Участие

Полезные сообщения: воспроизводимый дефект с командой и выводом; расхождение документа с кодом; случай деградации, которую продукт не назвал. Приветствуется одно: факт со ссылкой на файл и строку. См. [CONTRIBUTING.md](CONTRIBUTING.md); вопросы, идеи и замеры на своём корпусе — в [Обсуждениях](https://github.com/paulmann/RAGRAF/discussions). Участие регулируется [Кодексом поведения](CODE_OF_CONDUCT.md).

Проект разрабатывается под конкретные задачи, поэтому предложения по архитектуре обсуждаются охотнее, чем большие патчи без предварительного разговора. О проблемах безопасности сообщают приватно, не публичным issue — см. [SECURITY.md](SECURITY.md).

Если это сэкономило вам окно контекста — звезда помогает следующему агенту найти проект.

---

## Лицензия

**[PolyForm Noncommercial License 1.0.0](LICENSE)** — свободно для любой некоммерческой цели: личные проекты, учёба, исследования, эксперименты и тесты, а также использование благотворительными, образовательными, публично-исследовательскими, природоохранными организациями и организациями здравоохранения и общественной безопасности. Для коммерческого использования нужна отдельная лицензия от правообладателя: все права, явно не предоставленные, за ним сохранены. Переход с MIT 15.10.2026 записан в [CHANGELOG.md](CHANGELOG.md).

> Значок лицензии на GitHub у этого репозитория показывает «Other»: PolyForm отсутствует в каталоге, который GitHub умеет распознавать, поэтому значку здесь верить нельзя. Источники истины — файл `LICENSE` и `pyproject.toml` (`license = "PolyForm-Noncommercial-1.0.0"`).

Внешние зависимости сохраняют свои лицензии: `tree-sitter` (MIT), `sqlite-vec` (MIT/Apache-2.0), `fastembed` (Apache-2.0), `PyYAML` (MIT), `tiktoken` (MIT), `ijson` (BSD). Java и Joern, устанавливаемые отдельно, распространяются под Apache-2.0 и в поставку не входят.
