Протоколы замеров и приёмки¶
Назначение: сделать пользу RAGRAF измеримой числом, а не «стало удобнее». Каждая метрика имеет процедуру, инструмент снятия, артефакт и порог.
Основание: §2.3 плана, §7 ТЗ. Пилот: revoap.com. Второй корпус: z.batteryservice.ru (без git → часть метрик не снимается, см. §3).
1. Правила замеров¶
- Baseline снимается ДО внедрения индекса и сохраняется в
bench/baseline/. Замер, сделанный после, не является baseline. - Одинаковые задачи для baseline и для индекса: формулировка, файлы, критерий «сделано» — идентичны, различие только в доступных инструментах.
- Задачи фиксируются заранее списком
bench/tasks.yaml; задачи, придуманные после просмотра ответов индекса, в зачёт не идут. - Каждый замер — артефакт: JSON с числами и markdown с интерпретацией. Без артефакта замер не существует.
- Счёт токенов —
tiktoken; для сравнений фиксируется один и тот же токенизатор. - Никаких чужих процентов в качестве цели: ориентиры из литературы используются только как порядок величины, и это указывается рядом с числом.
- Замер воспроизводим: команда снятия записывается в артефакт.
2. Набор задач для замеров (черновик, уточняется с заказчиком)¶
| ID | Тип | Формулировка (сокращённо) | Что проверяет |
|---|---|---|---|
| T-01 | Навигация | «Найди обработчик настройки X и покажи, откуда приходят данные» | M1 |
| T-02 | Навигация | «Где формируется ответ API Y и какие поля он отдаёт» | M1 |
| T-03 | Связи | «Кто вызывает сервис Z и что будет, если изменить его сигнатуру» | M1, M3 |
| T-04 | Схема БД | «Какие колонки таблицы T реально читаются кодом и где» | M1, M6 |
| T-05 | Доработка | «Добавь фильтр по дате в список W» (реальная мелкая правка) | M2, M3 |
| T-06 | Доработка | «Добавь новый параметр в настройки S с сохранением в БД» | M2, M3 |
| T-07 | Доработка | «Вынеси повторяющийся блок в метод» (проверка slice_boundary) |
M2, M5 |
| T-08 | Impact | «Что затронет переименование метода M» | M2 |
| T-09 | Impact | «Что затронет добавление колонки C в таблицу T» | M2 |
| T-10 | Документация | «Что в документации сказано о модуле N» | M1, M6 |
Штатный размер набора — ≥ 20 задач, из них ≥ 8 — правки.
3. Матрица «метрика × корпус»¶
| Метрика | revoap.com (есть git) |
z.batteryservice.ru (нет git) |
|---|---|---|
| M1 навигация | да | да |
| M2 impact по истории | да (103 коммита) | нет → только синтетические задачи |
| M3 экономия контекста | да | да |
| M4 сжатие среза | да | да |
| M5 свежесть | да | да |
| M6 проверяемость | да | да |
| M7 стоимость обновления | да | да |
4. M1 — точность навигации¶
Вопрос: находит ли агент нужный файл и строку с первого запроса?
Процедура.
1. Для каждой задачи T-01…T-04, T-10 вручную фиксируется «эталонный ответ»: список path:line, которые обязаны быть в ответе (составлен по коду, а не по выдаче системы).
2. Baseline: агент получает задачу и работает только через rg и чтение файлов (индекс недоступен).
3. Опыт: агент получает ту же задачу, где первый шаг — операции фасада; rg разрешён только как fallback.
4. Фиксируется: число запросов до первого правильного path:line; полный/частичный/пустой ответ; число прочитанных файлов; число прочитанных строк.
Артефакт: bench/results/M1_<corpus>_<rev>.json + таблица.
| Показатель | Baseline | С индексом | Порог |
|---|---|---|---|
| Доля задач, решённых с первого запроса | замер | замер | улучшение обязательно |
| Среднее число прочитанных файлов на задачу | замер | замер | ≥ 2× снижение |
| Полнота эталонного ответа | замер | замер | ≥ 90% |
5. M2 — полнота impact-анализа (главная метрика)¶
Вопрос: можно ли по индексу предсказать, какие файлы реально затронет изменение?
Процедура (gold set из истории).
1. Из 103 коммитов пилота отбираются 20 коммитов-правок, где выполнено условие: изменено ≥ 2 файла, и хотя бы один — не тот, где лежит изменённый публичный метод (то есть простая «найти название» не работает).
2. Для каждого коммита берётся состояние до коммита, из него строится индекс.
3. Формулируется вопрос «что затронет изменение <символ>», без подсказки путей.
4. impact вызывается в трёх режимах: hard (только stated), full, и baseline — ручной поиск через rg.
5. Считаются precision / recall / F1 по файлам и по символам:
- precision = предсказанные и реально изменённые / предсказанные;
- recall = реально изменённые и предсказанные / реально изменённые.
Артефакт: bench/results/M2_<rev>.json, включая список коммитов и разбор ошибок (что пропустили и почему: динамический вызов, SQL-строка, include-обёртка, конфиг).
Ориентир: измеренный потолок в литературе — precision 69% / recall 79% / F1 55% (LCIP, arXiv:1512.07435, 17 574 изменений, Java, симуляция мутациями). Наш случай другой (реальные правки, PHP), поэтому сравнение — только ориентир порядка; рядом с числом это указывается.
| Показатель | Baseline (rg) |
hard |
full |
|---|---|---|---|
| precision по файлам | замер | замер | замер |
| recall по файлам | замер | замер | замер |
| F1 | замер | замер | замер |
Отдельный разбор ошибок обязателен: без него цифра бесполезна. Классификация пропусков: (а) динамический вызов; (б) SQL/строка; (в) include; (г) конфиг-зависимость; (д) не найдено вообще.
6. M3 — экономия контекста и стоимости задачи¶
Вопрос: сколько токенов и вызовов требует правка с индексом и без?
Процедура. Для задач T-05…T-07 (реальные мелкие правки):
1. Baseline: обычная работа агента (rg + чтение файлов).
2. Опыт: первый шаг — фасад, затем правка.
3. Фиксируется: токены входного контекста, число tool-вызовов, число прочитанных файлов/строк, результат (правка работает / не работает).
Артефакт: bench/results/M3_<corpus>_<rev>.json.
| Показатель | Baseline | С индексом |
|---|---|---|
| Медиана токенов на задачу | замер | замер |
| Медиана tool-вызовов | замер | замер |
| Доля задач, решённых без чтения файлов целиком | замер | замер |
Оговорка: прямое сравнение граф-индекса с «просто большим контекстом» в литературе не найдено, поэтому цель — собственная базовая линия, а не чужая цифра.
7. M4 — сжатие среза¶
Вопрос: сколько контекста экономит slice и укладывается ли repo_map в бюджет?
Процедура.
1. Для 20 символов пилота (разной величины: от 20 до 1000 строк) вычисляются токены: (а) тела всех связанных символов (окружение глубины 2), (б) slice, (в) repo_map с бюджетом.
2. Считается отношение tokens(slice) / tokens(окружение) и tokens(repo_map) / tokens(весь корпус выбранного модуля).
3. Отдельно проверяется ФТ-20: repo_map при budget_tokens = 2000 не превышает бюджет.
Артефакт: bench/results/M4_<rev>.json.
| Показатель | Значение |
|---|---|
| Медиана сжатия среза | замер |
| 10-й и 90-й процентиль | замер |
| Файлов с файлами > 1000 строк, где сжатие хуже всего | список |
Запрет: сравнивать полученное число с 68–70% / 90,93% из статьи — эти проценты первоисточником не подтверждены (см. 01_ARTICLE_COVERAGE.md). Допустимо только упоминание порядка величины.
8. M5 — свежесть и защита от неверных выводов¶
Вопрос: сколько раз агент опирался на устаревший факт, не зная об этом?
Процедура (сквозной сценарий).
1. Индексация пилота → rev-N.
2. Пачка из 5–10 правок агента, включая одну extract-method и одну миграцию БД.
3. После каждой правки — регистрация дельты (drift --scan), индекс не трогается.
4. Прогон 20 задач из набора: фиксируется, у скольких ответов были stale_warnings, и были ли случаи, где:
- ответ опирался на устаревший факт без пометки → инцидент (цель: 0);
- ответ содержал пометку и агент перешёл к live_read → корректное поведение;
- агент увидел пометку и всё равно использовал индекс → инцидент второго рода (цель: 0).
5. reindex --commit; проверяется, что: новая ревизия создана, ledger пуст, архив содержит разделы «изменения», «что устарело», «границы срезов».
Артефакт: bench/results/M5_<corpus>.json + копия архива drift/archive/*.md.
| Показатель | Значение | Порог |
|---|---|---|
| Инцидентов опоры на устаревшее без пометки | замер | 0 |
| Инцидентов второго рода | замер | 0 |
Доля ответов со stale_warnings при непустом ledger |
замер | 100% для затронутых путей |
Записей slice_boundary при extract-method |
замер | ≥ 1 |
Почему это собственная метрика: в литературе не найдено ни одной работы, измеряющей деградацию памяти агента во времени. Мы определяем и измеряем её сами — и этот факт указывается в отчёте.
9. M6 — проверяемость¶
Вопрос: можно ли автоматически подтвердить ссылки в ответах?
Процедура. Для 200 фактов из ответов всех операций:
1. существует ли файл evidence_path в рабочем дереве ревизии;
2. попадает ли evidence_line в диапазон узла;
3. совпадает ли index_rev факта с текущей ревизией (иначе — должен быть stale).
Артефакт: bench/results/M6_<rev>.json.
| Показатель | Порог |
|---|---|
| Доля фактов с существующим файлом | 100% |
| Доля фактов с попаданием строки в диапазон | ≥ 99% |
| Доля фактов с корректной ревизией | 100% |
Доля ссылок live_read, подтверждённых сравнением с файлом |
100% |
10. M7 — стоимость индексации и обновления¶
Процедура.
1. Полная индексация пилота: время по стадиям (AST, символы, CPG, БД, маршруты, текст, загрузка, эмбеддинги). Каждая стадия — отдельное число.
2. Переиндексация после правки 5 файлов: время и доля переиспользованных эмбеддингов.
3. Замер отклика операций: 100 запросов каждого вида, 95-й процентиль.
4. Проверка воспроизводимости: drop + index → сравнение метрик M1–M4 и идентификаторов (ФТ-13).
5. Проверка памяти: пиковое потребление процесса CPG.
Артефакт: bench/results/M7_<rev>.json.
| Показатель | Порог (НФТ) |
|---|---|
| Полная индексация пилота | ≤ 15 мин |
| Переиндексация после правки 5 файлов | ≤ 3 мин |
symbol/references/callers p95 |
≤ 200 мс |
impact (глубина 3) p95 |
≤ 1 с |
search p95 |
≤ 1 с |
slice p95 |
≤ 2 с |
| Пиковая память CPG | замер, лимит настраивается |
| Совпадение идентификаторов при пересборке | 100% |
11. Тесты (сводная карта)¶
| Тест | Что проверяет | Требования |
|---|---|---|
| M1-T1 | создание ревизии | ФТ-1 |
| M1-T2 | границы символов (100 символов против файла) | ФТ-2 |
| M1-T3 | отчёт покрытия, сумма файлов | ФТ-11 |
| M1-T4 | детерминированность (двойная сборка) | ФТ-13, НФТ-5 |
| M1-T5 | чтение и валидация конфига | ФТ-37 |
| M1-T6 | эффект исключений | ФТ-38 |
| M1-T7 | фиксация версий зависимостей | НФТ-7 |
| M2-T1 | символьные ссылки на 30 размеченных символах | ФТ-3 |
| M2-T2 | разделение calls / calls_heuristic |
ФТ-4 |
| M2-T3 | схема БД и источник | ФТ-5 |
| M2-T4 | SQL-литералы → таблицы, SELECT * |
ФТ-6 |
| M2-T5 | точки входа (15 размеченных) | ФТ-7 |
| M2-T6 | документация и documented_by |
ФТ-8 |
| M2-T7 | разделение текста и структуры | ФТ-9 |
| M2-T8 | провенанс у 1000 рёбер | ФТ-10 |
| M2-T9 | срез потока данных на 10 размеченных случаях | ФТ-41 |
| M2-T10 | flow на 10 парах узлов |
ФТ-43 |
| M3-T1 | деградация без CPG (и память) | ФТ-12, НФТ-8 |
| M3-T2 | секреты не в графе/векторе/логах | ФТ-39, ФТ-40 |
| M3-T3 | восстановление после прерывания сборки | НФТ-11 |
| M4-T1 | все 17 операций объёма релиза 1 (поставленный фасад реализует 38): валидный вход и пустой результат | ФТ-14 |
| M4-T2 | отказ на попытке передать язык запросов | ФТ-15 |
| M4-T3 | полнота конверта ответа | ФТ-16 |
| M4-T4 | разделение доказанных и эвристических связей в impact |
ФТ-18 |
| M4-T5 | slice без тел функций |
ФТ-19 |
| M4-T6 | честное «не найдено» + предложение live_read |
ФТ-21 |
| M4-T7 | совпадение MCP-инструментов и CLI | ФТ-22 |
| M5-T1 | индекс неизменен при чтении | ФТ-24 |
| M5-T2 | 5 способов обнаружения дельт | ФТ-25 |
| M5-T3 | append-only (нет удаления) | ФТ-26 |
| M5-T4 | дедупликация дельт | ФТ-27 |
| M5-T5 | slice_boundary при extract-method |
ФТ-29 |
| M5-T6 | schema_change при миграции |
ФТ-30 |
| M5-T7 | live_read выделяет отличия |
ФТ-31 |
| M5-T8 | reindex --commit: новая ревизия, чистый ledger, архив |
ФТ-32 |
| M5-T9 | содержание архива (3 обязательных раздела) | ФТ-33 |
| M5-T10 | ротация 3 из 5 при сохранении истории | ФТ-34 |
| M5-T11 | drift_ack не удаляет запись |
ФТ-36 |
| M6-T1 | линтер PowerShell и проверка BOM/CRLF | НФТ-9 |
| M6-T2 | изоляция артефактов в .ragraf/ |
НФТ-10 |
| M6-T3 | воспроизводимость ответа по ревизии и параметрам | НФТ-12 |
12. Итоговый отчёт приёмки¶
Форма отчёта (docs/03_implementation/ACCEPTANCE_REPORT.md):
- Сводная таблица К1–К9 с фактическим состоянием.
- Сводная таблица метрик M1–M7: baseline, результат, порог, вердикт.
- Разбор ошибок M2 по классам (динамика, SQL,
include, конфиг). - Список узких мест с числами (что именно медленно/неточно и насколько).
- Расхождения с ТЗ с письменным обоснованием (если требования изменены — с указанием, почему и с чьего согласия).
- Что не подтвердилось из ожиданий — прямой раздел, без сглаживания.
- Рекомендации для релиза 2 (языки, инструменты, узкие места).
Правило отчёта: любое утверждение «лучше» сопровождается числом и процедурой из этого документа.