---
name: runtime-investigation
description: "Алгоритм рантайм-расследования багов в 1С BSL: граф вызовов + ключевые переменные → пробы → трасса → цикл гипотез. Используй, когда есть bug-report и нужно установить, что фактически происходит в коде, и сравнить с тем, как должно быть. Дебаггер — основной потребитель этого навыка."
---

# Runtime Investigation — расследование багов в рантайме

## 1. Когда применять

Цель навыка — ответить на три вопроса в строгом порядке:

1. **Что фактически происходит?** Вызывается ли процедура? С какими аргументами? Какие значения переменных? Какой путь по if/else? Что вернул запрос?
2. **Совпадает ли это с ожиданием?** (из спеки/дизайна/ассерта теста — `bug-report.expectation`)
3. **Где источник расхождения?**
   - **Код неверен** — поведение не соответствует требованию
   - **Код верен, данные не те** — контракт нарушен на стороне вызывающего/подготовки данных
   - **Код соответствует спеке, спека неверна/неполна**
   - **Тест/сценарий проверяет не то**

Без шага 1 шаги 2-3 невозможны.

**Триггер запуска:** оркестратор передал `bug-report.json` со статусом `open`.

---

## 2. Иерархия инструментов (от дешёвого к дорогому)

| Уровень | Инструмент | Когда |
|---|---|---|
| **L0** | Чтение исходников + спеки/дизайна (`code-navigation`) | Всегда первым |
| **L1** | `event-log-analysis` — ЖР через ClickHouse | Уже отработавший прогон, есть Error/Warning |
| **L2** | `platform-data-core` § Query Execution — запросы к БД | Проверить состояние данных независимо от кода |
| **L3** | `agent-debug` точки в коде | L0-L2 не дали ответа: факт вызова, путь if/else, значение/тип переменной |
| **L4** | Перепрогон сценария/теста после вставок | После L3 — собрать наблюдения |
| **L5** | `gui-control` + `screenshot` | Симптом в UI, неясно что на форме |
| **L6** | `syntax-checking` (`get_diagnostics` / `v8-runner syntax …`) | После любого изменения кода |
| **L7** | `tech-log-analysis` — техжурнал | **ТОЛЬКО с явного согласия пользователя.** Тяжёлый, медленный. Когда L0-L6 не дали ответа: блокировки, deadlock, скрытые исключения платформы, медленные SQL |

L0-L6 дебаггер использует автономно. Переход на L7 требует выйти к оркестратору с **структурированным запросом**:
- Какую гипотезу нельзя проверить через L0-L6 и почему
- Какие события техжурнала нужны (EXCP / DBMSSQL / TLOCK / TDEADLOCK / TTIMEOUT / CALL)
- Ориентировочное время сбора

Оркестратор переспрашивает пользователя. Без согласия — НЕ поднимать.

---

## 3. Полный алгоритм

```
ФАЗА 1. Подготовка
  1.1  Прочитать bug-report.json. Перевести status → in_investigation.
  1.2  Воспроизвести баг детерминированно (запустить указанный тест/сценарий).
       - Не воспроизводится → flaky, эскалация оркестратору.
  1.3  Прочитать код вокруг точки симптома + спеку/дизайн (L0).
  1.4  Построить ГРАФ ВЫЗОВОВ от точки входа сценария/теста до точки симптома (см. §4).
  1.5  Выделить КЛЮЧЕВЫЕ ПЕРЕМЕННЫЕ (см. §5).

ФАЗА 2. Первая проходка (БЕЗ гипотез)
  2.1  Расставить пробы H0 на каждом узле графа (префикс `AGENTDEBUG-<bug-id>-H0-NNN`):
       - маркер EXECUTED
       - снимок ключевых переменных (безопасная сериализация — §6)
  2.2  Прогнать сценарий/тест.
  2.3  Прочитать ЖР, собрать трассу: какие узлы прошли, состояние переменных.
       Сохранить в task_dir/.context/debug/<bug-id>/trace-run-1.md.
  2.4  Сравнить трассу с ожиданием. Локализовать первое расхождение «ожидание ≠ факт».
       Если трассы достаточно, чтобы сразу определить причину → переход к Фазе 4.

ФАЗА 3. Цикл гипотез (≤ 5 итераций; +3 расширение, max 8 — см. §7)
  Для гипотезы N (1..5, при расширении 6..8):

    3.N.1  Сформулировать наиболее вероятную гипотезу НА ОСНОВЕ ТЕКУЩЕЙ ТРАССЫ
           (не из головы). Записать в debug-report.md:
           - формулировка
           - evidence_from_trace (на каком факте из трассы основана)

    3.N.2  Выбрать способ проверки:
           (a) пробный фикс — узкое изменение в коде/тесте/сценарии,
               которое легко откатить;
           (b) дополнительные пробы (префикс `AGENTDEBUG-<bug-id>-H<N>-NNN`) —
               новые ключевые переменные, узлы между размеченными,
               состояние данных через platform-data-core § Query Execution.

    3.N.3  Применить, прогнать, прочитать трассу. Сохранить trace-run-<N+1>.md.

    3.N.4  Развилка:
           ✓ ПОДТВЕРЖДЕНА → переход к Фазе 4 (фикс по правилам)
           ✗ НЕ подтверждена:
               - откатить пробный фикс (если был)
               - снять пробы ИМЕННО ЭТОЙ гипотезы (grep H<N>); пробы H0 и
                 предыдущих опровергнутых гипотез ОСТАЮТСЯ
               - зафиксировать в debug-report.md: что проверял, результат,
                 почему опровергнута
               - переход к гипотезе N+1

  Между итерациями допустимо вернуться к Фазе 1 и расширить граф/ключевые
  переменные, добавив новые H0+ пробы (например, появились новые вызывающие
  места). Это не считается отдельной гипотезой.

  После 5 неподтверждённых:
    - если есть конкретная следующая гипотеза с высокой уверенностью →
      обратиться к оркестратору с запросом на расширение +3 (max 8 всего)
    - иначе → Фаза 5 (эскалация)

ФАЗА 4. Фикс (если гипотеза подтвердилась)
  4.1  Оценить масштаб по критерию «локальный vs возврат» (§8).
  4.2  Локальный → применить фикс, прогнать упавший тест/сценарий + смежные.
       - Должно стать зелёным
       - Если не стало — это была ошибочная гипотеза, вернуться в 3.N.4 с откатом
  4.3  Масштабный → возврат оркестратору с пояснением и рекомендацией
       (какому агенту передать).

ФАЗА 5. Эскалация (5/8 гипотез исчерпаны или масштаб слишком большой)
  5.1  Краткий структурированный отчёт оркестратору (см. §9).
  5.2  Оркестратор передаёт пользователю.

ФАЗА 6. Очистка (ВСЕГДА перед завершением — успехом или эскалацией)
  6.1  grep `//[AGENTDEBUG-` → ноль вхождений во ВСЕХ затронутых файлах.
  6.2  Если поднимали техжурнал — восстановить исходный конфиг.
  6.3  syntax-checking по затронутым модулям.
  6.4  Финальный debug-report.md с итоговым статусом и обновление
       bug-report.json (status: fixed_locally / returned_to_author / escalated_to_user).
```

---

## 4. Построение графа вызовов

Стартовая точка — место наблюдаемого симптома (упавший ассерт, исключение, неверное значение из `bug-report.symptom.fail_location`).

**Метод:** идти НАЗАД от симптома вверх по стеку:
- Какая процедура его вызвала?
- Кто вызвал её?
- … до точки входа сценария/теста.

**Инструменты:** `code-navigation` (навигация по символам), чтение модуля, поиск по `Вызвать` / `Выполнить` / обработчики событий формы / экспортные процедуры менеджера.

**Результат:** список узлов графа в виде:
```
[Тест.МойТест]
  → [Документ.РасходТовара.Объект.ОбработкаПроведения]
    → [ОбщийМодуль.РассчитатьСкидку]
      → [ОбщийМодуль.ПолучитьКатегориюКлиента]  ← точка симптома
```

Сохранить как `task_dir/.context/debug/<bug-id>/call-graph.md`.

---

## 5. Выделение ключевых переменных

**Определение:** ключевая переменная — та, которая влияет на:
1. Условие исполнения проблемной точки (входит в `Если/Иначе/Пока/Для` на пути к симптому), либо
2. Результат вычисления в проблемной точке (входит в формулу/запрос/возвращаемое значение), либо
3. Ветвление выше по стеку, ведущее к этой точке.

**Метод выделения — обратный обход:**

1. В точке симптома: какие переменные участвуют в ассерте/формуле? → ключевые.
2. По графу вверх: какие переменные участвуют в условиях, ведущих к этой точке? → ключевые.
3. Параметры процедур, передаваемые и трансформируемые по пути → ключевые.
4. Глобальные параметры сеанса (текущий пользователь, дата актуальности, активная организация) — **по умолчанию ключевые**, если не доказано обратное.

**НЕ ключевые:** локальные переменные, используемые только для расчёта без влияния на ветвление и не возвращаются.

Сохранить как `task_dir/.context/debug/<bug-id>/instrumentation-plan.md`: какие пробы куда ставит, какие ключевые переменные в каждой.

---

## 6. Безопасная сериализация при логировании

В пробах `agent-debug` фиксировать значения переменных. **НЕ дампить целиком:**

| Тип | Что НЕ логировать | Что логировать вместо |
|---|---|---|
| Документ/Справочник Объект | Весь объект | `ТипЗнч`, `Ссылка`, релевантные реквизиты по одному |
| ТаблицаЗначений | Все строки | `Количество()`, поля первой/проблемной строки |
| Структура | Сериализацию | `Количество()`, список ключей через запятую |
| Соответствие | Сериализацию | `Количество()`, ключ-цель если ищем конкретный |
| Объект формы | Целиком | Конкретные реквизиты формы по одному |
| Запрос | Текст полностью | Имя, ключевые параметры |
| Метаданные | `Метаданные.X.<всё>` | Только имя типа: `Метаданные(Ссылка).Имя` |
| Двоичные данные | Содержимое | `Размер()` |
| Пароли, токены, ПД | Никогда | Замаскировать или пропустить |

**Правило главное:** логируем только те поля объекта, которые код реально читает на пути к симптому (определяется по §5). Не дамп всего объекта.

**Параметр-объект как ключевая переменная:** если ключевая переменная — ссылка/объект, моделировать в эксперименте нужно **именно тем объектом, на котором баг воспроизводится**. Не подменять «похожим» из базы.

---

## 7. Лимит гипотез

**По умолчанию: 5 гипотез.** После 5-й неподтверждённой — эскалация.

**Расширение +3 (max 8 всего):** допустимо однократно, если:
- появилась конкретная следующая гипотеза с **высокой уверенностью** (есть прямые улики из трассы),
- запрос отправлен оркестратору с обоснованием,
- оркестратор согласовал.

Если уверенность низкая — НЕ просить расширение, эскалировать сразу.

**Качество > количество.** Каждая гипотеза в `debug-report.md` обязана иметь `evidence_from_trace` — на каком факте из собранной трассы она основана. Это блокирует «гипотезы наугад».

---

## 8. Критерий «локальный фикс vs возврат оркестратору»

**Дебаггер чинит сам, если выполнены ВСЕ условия:**
- Изменение в ≤ 2 файлах продкода ИЛИ ≤ 1 файл теста/сценария
- Не меняется публичный API (экспортные процедуры, их сигнатуры)
- Не меняется спека и technical-design
- Не затрагивает `protected_paths` из bug-report
- Фикс умещается в ~30 строк диффа

**Возврат оркестратору в любом из случаев:**
- Нужно менять спеку → Analyst
- Нужно менять технический дизайн или добавлять API → Architect
- Нужно переписывать > 2 файлов → Developer-Code
- Нужно менять `.feature` или step-library широко → Scenario-Author / Scenario-Coder
- Баг в данных, требует пересмотра подготовки тестового окружения → Developer-Tests или Scenario-Coder

После локального фикса — **обязательная верификация**:
1. Перепрогнать упавший тест/сценарий → должен быть зелёным.
2. Перепрогнать связанные unit-тесты модуля и Vanessa-сценарии с тем же тегом задачи.
3. Проверить, что не сломалось ничего смежного (узкая регрессия).
4. Если verification failed — это была ошибочная гипотеза, откатить фикс, вернуться в 3.N.4.

Локальный фикс ВСЕГДА проходит ревью (Reviewer scope=`debug` или соответствующий типу артефакта) — иначе минует контроль качества.

---

## 9. Шаблон `debug-report.md`

Сохраняется в `task_dir/.context/debug/<bug-id>/debug-report.md`.

```markdown
# Debug Report — <bug-id>

## Источник
- Bug-report: <ссылка на bug-report.json>
- Симптом: <symptom.what_ran> упал на <fail_location>
- Ожидание: <expectation.quote> (источник: <expectation.source>)

## Воспроизведение
- Команда: <symptom.command>
- Детерминизм: <yes/no>

## Граф вызовов
<ссылка на call-graph.md>

## Ключевые переменные
<ссылка на instrumentation-plan.md>

## Первая проходка (H0)
- Прогон: <ссылка на trace-run-1.md>
- Локализация расхождения: <узел графа + что не сошлось>

## Гипотезы

### H1: <формулировка>
- Evidence_from_trace: <на каком факте из трассы основана>
- Способ проверки: <фикс / доп.пробы>
- Прогон: <ссылка на trace-run-N.md>
- Результат: ПОДТВЕРЖДЕНА / ОПРОВЕРГНУТА
- Если опровергнута — почему: <...>

### H2: ...
...

## Вердикт
- Класс причины: код / данные / спека / тест/сценарий
- Корневая причина: <...>
- Затронутый слой источников правды (L1-L6): <см. source-of-truth-policy>

## Действие
- ВАРИАНТ A — Локальный фикс:
  - Файл(ы): <...>
  - Дифф: ≤ 30 строк
  - Верификация: упавший тест зелёный, смежные тесты зелёные
  - Подлежит ревью: scope=debug
- ВАРИАНТ B — Возврат оркестратору:
  - Кому передать: <agent>
  - Почему масштаб большой: <...>
  - Рекомендация по фиксу: <...>
- ВАРИАНТ C — Эскалация:
  - 5/8 гипотез не подтверждены
  - Что точно установлено: <...>
  - Что хотелось бы проверить, но не получилось: <...>
  - Рекомендация: к кому идти (Architect / Analyst / пользователь)

## Очистка
- [x] grep `//[AGENTDEBUG-` → 0 вхождений
- [x] техжурнал восстановлен (если поднимался)
- [x] syntax-checking пройден
```

---

## 10. Антипаттерны

| Антипаттерн | Последствие |
|---|---|
| Гипотеза без `evidence_from_trace` | Угадывание; ресурс расследования тратится впустую |
| Не снять пробы опровергнутой гипотезы перед следующей | Шум в трассе, путаница в интерпретации |
| Оставить пробный фикс при опровергнутой гипотезе | Накопление мусора в коде |
| Дамп всего объекта в `agent-debug` точке | Переполнение ЖР, утечка данных |
| Подмена тестового объекта «похожим» из базы | Баг не воспроизведётся, ложный отрицательный результат |
| Поднять техжурнал без согласия пользователя | Нарушение политики; тяжёлый процесс зря |
| 10+ проб H0 без чётких ключевых переменных | Широкое наблюдение, непонятный результат → разбить на гипотезы |
| Пропустить очистку перед завершением | Маркеры `AGENTDEBUG` уйдут в коммит |
| Пропустить верификацию после локального фикса | Ложный «починил», на самом деле сломали смежное |

---

depends_on:
  - framework/skills/tool-usage/diagnostics/bug-reporting/SKILL.md
  - framework/skills/tool-usage/diagnostics/agent-debug/SKILL.md
  - framework/skills/tool-usage/diagnostics/event-log-analysis/SKILL.md
  - framework/skills/tool-usage/diagnostics/tech-log-analysis/SKILL.md
  - framework/skills/tool-usage/platform-data/platform-data-core/SKILL.md
  - framework/skills/tool-usage/code-analysis/code-navigation/SKILL.md
  - framework/skills/tool-usage/code-analysis/syntax-checking/SKILL.md
  - framework/workflows/source-of-truth-policy.md
---
