# Операции RAGRAF: выбор и границы

Справочник к навыку `ragraf-core`. Задача — выбирать операцию вместо чтения файлов
и знать, чего операция не показывает.

## 1. Полный набор

Фасад объявляет **79 операций** вида `op_*` (`src/ragraf/facade.py`). Поверхность
инструментов агента — **86 инструментов** с префиксом `ragraf_`
(`src/ragraf/mcp_server.py`). Разница не ошибка: инструментов больше, потому что
дополнительно выставлены приведение корпуса в актуальное состояние, выбор корпуса,
сводка телеметрии и состояние индекса, а одна операция фасада наружу не выставляется.

## 2. По типу вопроса

| Вопрос | Операция | Что показывает | Чего не показывает |
|---|---|---|---|
| Где определён символ | `symbol` | файл, строки, вид, подпись, разобранные параметры | тела функции |
| Где ещё используется | `references` | все места со ссылками | порядок выполнения |
| Кто вызывает | `callers` | вызывающие с доказательством | вызовы через строку или ссылку из данных |
| Что вызывает | `callees` | вызываемые | то же |
| Что затронет правка | `impact` | достижимые места по графу | конфликты веток и время выполнения |
| Структурный срез | `slice` | контекст без тел, только при полной сборке CPG | ничего при `capability=degraded` |
| Тело символа | `code` | точный текст | смысл вызывающих его мест |
| Карта репозитория | `repo_map` | файлы и объёмы в бюджете | связи между ними |
| Поиск по смыслу и словам | `search` | чанки с путями и строками | доказательство связи, это поиск, а не граф |
| Поиск по теме, а не по слову | `search` с `mode=docs` | уровень темы: сущности графа документов с адресами упоминаний, `match_kind=entity`; лексическая выдача не меняется | смысл найденного: адрес упоминания — факт, тема — совпадение имени |
| Только код, без документов | `search` с `mode=code` | материал кода и число скрытых хитов | ничего о документации |
| Оба уровня сразу, со связью между ними | `doc_search_levels` (`mode`: `local`, `global`, `both`; по умолчанию `both`) | локальные факты с адресами и глобальный уровень: сущности и связи документного графа, у каждого факта адрес цитаты; связь уровней названа (`via_entities` у хита, `via_chunk` у глобального факта). Локальный уровень не закрыт изданием, глобальному нужна `doc-graph` | смысла найденного; пустой слой назван кодом `layer_empty`, «связей нет» — `no_facts_in_chunks` |
| О чём корпус и какие в нём темы | `themes`, `global_overview` (издание pro) | `themes`: кластеры совместно встречающихся сущностей с адресом цитаты у каждого участника и сводкой по цитатам (или `summary=null` с причиной); `global_overview`: документы, сущности, связи, темы, сводки и топ-темы с адресами | смысловой категории: тема — совместная встречаемость в чанках, а не «относятся к одной области» |
| Несколько строк сразу; где копии и какая рабочая | `search_multi` | все вхождения по каждому запросу, кодировка файла, группировка по семействам, роль файла (точка входа / активный / копия) с ссылкой `path:line` | смысл найденного кода |
| Какие файлы — копии друг друга | `duplicates` | группы «одно имя с номерами» и байт-идентичные, главный файл и доказательство его активности | намерение автора: копия может быть веткой развития |
| Точки входа | `entrypoints` | роуты, HTTP-обработчики, CLI-скрипты, endpoint'ы разметки; с `path` — достижим ли файл | порядок выполнения внутри обработчика |
| Что не подключено | `dead_code` | файлы и подпрограммы без входящих ссылок И вне достижимости, с причиной и списком оправданных (`refuted`) | «удалять»: это находка, а не решение |
| Что в документе и где именно | `doc_search`, `doc_get` | адрес чанка (`path:12`, `path#anchor`, `path:page=3`, `path:sheet=Лист!A1:B2`), структура узла и провенанс разбора; сначала индекс, затем диск с названным источником | смысл текста: это адрес и текст, а не вывод |
| Какая редакция документа действовала на дату | `doc_asof` (издание pro) | редакция с интервалом `valid_from`/`valid_to`, `version_id`, признак замены `superseded_by`; документ без реквизитов возвращается с `validity=unknown`, а не выбрасывается | даты, которых нет в метаданных: интервал не угадывается по имени файла |
| Что пересчитать после изменения | `stale_cascade` (издание pro) | каскад по рёбрам факт → факт от изменённых входов до `depth`: адрес, расстояние, `cause_fact_id` и `input_fact_id`, `outside_cap` за глубиной; `apply` ставит пометки, `clear-marks` закрывает их после пересчёта | сам пересчёт: слой помечает и отдаёт список, повторный проход извлечения — решение человека |
| Что опиралось на утверждение | `dependents` (издание pro) | прямые и транзитивные зависимости по рёбрам деривации до `depth` (по умолчанию 3), расстояние, `outside_cap` за глубиной, действие: «пересчитать» для `derived` и «решение человека» для `stated` | автоматического пересчёта: операция помечает и отдаёт список, а не правит факты |
| Разобран ли документ | `doc_status`, `doc_validate` | состояние извлечения, частичные чанки, нарушения чанкинга | качество содержания документа |
| Кто рядом с сущностью в документах | `entity_neighbors` (издание pro) | соседи с видом связи, весом и адресом цитаты у КАЖДОГО; `depth` 1..3, вид `entity`/`theme` | связи, которых нет в слое: сущности извлекает модель |
| Какие документы связаны | `doc_relations` (издание pro) | пары документов через общие сущности с адресами упоминания с ОБЕИХ сторон | намерение автора: это общие имена, а не ссылка |
| Что в таблице | `schema` | колонки, типы, PK/UNIQUE/AUTO_INCREMENT и генерируемые колонки из миграций | фактическое состояние живой базы |
| Кто читает или пишет таблицу | `table_usage` | места чтения и записи, текст запроса и способ вызова (`prepared`/прямой) | права доступа базы данных |
| Можно ли так записать | `write_check` | сверка плана записи со схемой до выполнения | типы значений и ограничения |
| Кто и почему получает право | `policy_trace` | ветви решения, точки отказа | фактическую роль пользователя |
| Что в ЖИВОЙ базе | `db_schema` | базы, таблицы, колонки, типы, индексы | схему из миграций |
| Устройство одной таблицы | `db_table` | колонки, индексы, ключи, скрытые поля | связь `derived` как факт |
| Связи таблицы | `db_relations` | `stated` (факт) и `derived` (вывод) раздельно | считать вывод структурой |
| Как выглядят данные | `db_sample` | сборный пример, домены значений | текущее состояние данных |
| Что изменилось в структуре | `db_drift` | изменения между ревизиями И расхождения «миграции ↔ живая база» | изменение данных |
| Чего нет в базе из используемого кодом | `db_cross` | `used_missing` (с источником имени, видом доступа и доказательством `path:line`), `unused` (с размером и признаком «база используется кодом»), `write_paths`, `case_mismatch` и **слепые зоны** `dynamic_sql` | что удалять: это находка, а не решение |
| Что изменилось между ревизиями | `diff` | файлы, символы, рёбра, а также регрессии: `callers_lost` (символ потерял всех вызывающих) и `writes_lost` (таблица перестала заполняться) | смысл изменения: «исчезло» при `capability=degraded` может означать «не было разобрано» |
| Что мы уже знаем о проекте | `note` / `notes` | короткие заметки с автором, временем и задачей | проверку: заметка — знание агента, а не факт индекса (`source: note`) |
| Можно ли искать по файлам, а не по индексу | `gate` | решение `allow`/`ask`/`deny`, правило, причина и ответ в формате хука DSH (отказ — код 2) | что гейт перепишет команду: он только разрешает, спрашивает или отказывает |
| Чем подтверждена работа по задаче | `task_stats` | готовый отчёт: обращения, факты, заменённое чтение, ответы по устаревшей ревизии, решения гейта, заметки | смысл фактов: это сводка по журналу, а не проверка кода |
| Классы оформления | `class_usage` | описано правило или нет, где применён | итоговый вид в браузере, каскад |
| Маршруты и обработчики | `routes` | HTTP-маршруты и их обработчики | поведение за обработчиком |
| Актуальность индекса | `freshness` | расхождение сумм, при необходимости реиндексация | качество самих фактов |
| Состояние индекса | `index_status` | ревизия, полнота разбора, покрытие, стадии, журнал прогонов качества: число, предел, превышение | ничего сверх состояния |
| Чем именно падал кейс | `quality_trace` (издание pro) | `save` записывает сбой целиком: объявление кейса, шаги сеанса, решения гейта, ревизия; `list` показывает сохранённые; `replay` повторяет и называет вердикт `still_failing` / `fixed` / `other_rev` / `not_reproducible` | пройденный кейс не пишется; «исправлено» заявляется только на той же ревизии |
| Стало ли хуже после правки индекса | `quality_suite`, `quality_diff` (издание pro) | набор проверок индекса с записью прогона и разбор расхождений между прогонами; при разных ревизиях вердикт не выносится | конвенции проекта (это чекер) и качество ранжирования |
| Совпало ли ПОВЕДЕНИЕ, а не только вид | `contract_pin_sample` (издание enterprise) | проба вызывает операцию на фиксированном наборе аргументов и хеширует ответ без изменчивых полей (ревизия, свежесть, длительности, номера сеансов); `mode=take` пишет пробу, `mode=compare` сверяет с прошлой и называет расхождения | формы: правка, меняющая и форму, видна пину; всё, что нельзя вызвать без индекса, названо `not_sampled` с причиной, а не сочтено совпадением; пустая проба не доказательство |
| Кто и когда менял контракт | `contract_pin_history` (издание enterprise) | каждая смена описания отдельной строкой: имя, вид контракта, автор, отметка времени, возраст, `previous_hash`; сверху счётчик смен по авторам и объектам, срок хранения назван в ответе | качества работы: это счётчик смен, а одна смена может быть крупной правкой; пустая история называется отдельно |
| Журнал прогонов распух | `quality_prune` (издание pro) | перечень записей к удалению (по умолчанию сухой прогон), сколько записей выше предела, копия журнала до удаления, удаление только по явным номерам и только с подтверждением; сколько оставить — по умолчанию из предела журнала | удаление соседних таблиц журнала: история расхождений и ревизии не трогаются; размер файла может не уменьшиться без VACUUM |
| Журнал расхождений | `drift_report` | что изменилось после ревизии | тела изменений |
| Живое чтение | `live_read` | текущее содержимое файла с пометкой отличий | связи и граф |
| Статистика обращений | `usage` | вызовы, факты, экономия | смысл фактов |
| Реестр разработок | `catalog` | что заведено и с какими числами | содержимое индекса |
| Куда идти за ответом | `route` (CLI `route`, `ragraf_route`) | кандидаты, причина выбора, состояние локального индекса | содержимое файлов: маршрут не цитирует |
| Какие корни разрешены карте | CLI `sources list/add/remove/enable/disable/priority/secrets`; страница `/sources` | корни, правила, число файлов и секретных мест | содержимое; значения секретов не хранятся |
| Что в карте метаданных | CLI `map status/scan/find` | имена, размеры, даты, отпечаток | текст файлов |
| Отчёт о пользе и аналитика | CLI `feedback`, `analytics export/delete`; страница `/value` | агрегаты, оценки, копия перед удалением | пути и запросы: их нет в журнале |

## 3. Правила выбора

1. **Навигация — операция, содержание — чтение.** «Где» отвечает операция; «как
   именно работает» требует чтения того фрагмента, который операция указала.
2. **План записи — всегда `write_check`.** Это единственная проверка, которая
   ловит несуществующую колонку до запуска кода.
3. **Решения о правах — всегда `policy_trace`.** Читать большой набор ветвей глазами
   бесполезно: неизвестное действие, оставшееся разрешённым по умолчанию, видно
   только статически.
4. **Перед правкой разметки — `class_usage`.** Отсутствие правила в стилях не даёт
   ошибки: страница отрисуется оформлением браузера и будет работать.
5. **`slice` только при полной сборке.** Иначе операция откажет с кодом 3 —
   это ожидаемое поведение, а не поломка.
6. **`live_read` — когда файл точно изменился после ревизии.** В остальных случаях
   достаточно индекса, и это дешевле.

## 4. Готовые рецепты (десять типовых вопросов)

| Вопрос агента | Вызов | Что считается ответом |
|---|---|---|
| Где выводится эта строка | `search` / `search_multi` (несколько строк через `|`) | пути и строки; в `search_multi` — кодировка файла и роль копии |
| Все списки расширений в проекте | `search_multi` с массивом запросов | все вхождения сразу, сгруппированные по семействам |
| Кто пишет в таблицу | `table_usage --mode write` | места записи, текст запроса, `via` (prepared или прямой вызов) |
| Какие ключи перевода есть | `search` по ключу, затем `references("tpl:<ключ>")` | шаблон и код в одном узле графа |
| Что затронет правка кнопки/функции | `impact` | достижимые места с разделением факт/вывод |
| Какие файлы — копии | `duplicates` | группы, главный файл, чем доказана активность |
| Какие файлы не подключены | `entrypoints`, затем `dead_code` | список с причиной и опровергнутыми кандидатами |
| Генерируемые колонки таблицы | `schema` (миграции), `db_schema` (живая база), `write_check` до записи | `generated_columns`, `generated_kind`, `columns_marks` |
| Поиск в CP1251 | `search_multi` | поле `encoding` у каждого хита подтверждает, что файл прочитан верно |
| Что изменилось после правок | `diff` (код), `drift_report` (расхождения), `db_drift` (схема) | ревизии, что добавилось и исчезло, кто потерял вызывающих, какая таблица перестала заполняться |
| Ответ, а не сырые хиты | любая из `search`, `search_multi`, `symbol`, `callers`, `impact` с `answer=true` | готовая фраза и ссылки `файл:строка` (≤ 1–2 КБ) вместо структурного JSON |
| «Что мы уже знаем» | `notes` (по задаче или подстроке), запись — `note` | заметки агента с автором и временем; `source: note` отличает их от фактов |

## 5. Как читать ответ

Обязательные поля конверта: `op` (операция), `index_rev` (какая ревизия отвечала),
`capability` (`full` или `degraded`), `drift` (есть ли незакрытые расхождения),
`provenance` (откуда данные: индекс, живое чтение или смешанно), `limits`,
`result`, `stale_warnings`, `found`. Дополнительно бывают `error` и `freshness`.

- `found=false` при коде 0 — это «не найдено», а не сбой.
- Непустые `stale_warnings` означают, что факт мог быть затронут правками после
  ревизии; такой факт нельзя выдавать за актуальный без пометки.
- `provenance=live` означает, что данные получены чтением файла, а не из индекса:
  их доказательство — сам файл, а не ревизия.
- `provenance=none` означает, что данных не выдано (`found=false`): источник не
  объявляется. Правило живёт в одной точке — сборке конверта, поэтому оно
  действует для всех операций сразу. Замер 28.10.2026: отказ `code` (окно за
  концом файла) объявлял `live`, хотя текста не было ни символа.
- `found` означает «цель найдена» и НЕ означает «есть что читать». Где это важно,
  конверт называет отдельный счётчик: у `code` — `spans_with_text`, у `slice` и
  `impact` — `target_external` (цель вне корпуса, результат пуст по определению).
  Признак `found=true` без единого символа полезной нагрузки невозможен: такой
  ответ отказывает и называет причину числами.
- Пустой источник называется. `schema` при пустых миграциях отвечает отказом с
  числами (`migrations_tables`, `live_tables`, `live_table_names`,
  `live_databases`) и указывает `db_schema`/`db_table`; `table_usage` различает
  «миграций нет вовсе» (`schema_source=none`) и «таблицы нет в схеме».
- Колонки в `write_check` принимаются строкой через запятую или списком и
  разбираются одной функцией: посимвольный разбор (21 «неизвестная колонка»
  из `"No,Status"`) невозможен.
- Закрытые перечни значений проверяются: `code.style` (`compact`, `signatures`),
  `code.source` (`auto`, `index`, `disk`), `search.kinds` (`symbol`, `file`, `doc`,
  `db-structure`, `db-sample`), `impact.mode` (`full`, `hard`), `slice.direction`
  (`back`, `forward`), `repo_map.detail` (`normal`, `deep`), `table_usage.mode`
  (`all`, `read`, `write`), `class_usage.mode` (`all`, `missing`, `unused`).
  Неизвестное значение — отказ с перечнем; `None` и пустой список означают
  «все допустимые». Перечни живут в одной таблице `OP_CHOICES`.
- Параметра `context` у `live_read` нет: построчного сравнения с индексом не
  делается, отличие выражается признаком `changed_since_index` по sha256.
- Окно `start`/`end` у `code` и `live_read` — ФИЛЬТР ОТБОРА, а не только нарезка:
  у `code` спаны отбираются по пересечению с окном ДО применения `limit`;
  перевёрнутое окно и окно за границами файла — отказ с числами, а не пустой
  текст при `found=true` (замер 28.10.2026).

## 6. Чего в проекте нет

- Нет языка запросов к графу. Только фиксированные операции; текст, похожий на
  запрос к графу, отвергается с ошибкой вызова.
- Нет штатной команды проверки версий зависимостей, хотя `requirements.txt`
  её обещает.
- Нет единого раннера проверок: конфигурации pytest нет, файлы в каталоге `tests`
  запускаются по отдельности. Есть обёртка `python tools/check_all.py`
  (группа `core` — по умолчанию, `--list` показывает состав групп), но это запуск
  существующих скриптов, а не pytest.
- Маршрут (`route`) не цитирует содержимое: он отвечает «куда идти», а не «что
  написано». Для текста — `search` по рекомендованному корпусу.
- URL-коннекторы (`ssh://`, `s3://`, `webdav://`, `http://`) не реализованы:
  `sources add` отклоняет их с причиной. Сетевой корень — UNC или смонтированный
  путь, только с `--network`.
- Документы (PDF/DOCX/XLSX/PPTX/EML/ODT/RTF) читаются извлекателем; `path:line`
  для них — строка извлечённого текста с маркером страницы/листа/слайда. OCR есть
  только в издании pro (`doc_ocr`, локальный движок): на Community операция
  отвечает отказом с названием издания, а не притворяется, что распознавания нет.
  `.msg` без библиотеки `extract-msg` даёт `unavailable`, а не текст.
- Документного графа нет на Community: `entity_neighbors` и `doc_relations`
  объявлены возможностью `doc-graph` (издание pro) вместе с проходом извлечения.
