Руководство по самоанализу: анализ коммитов на базе CPG¶
CodeGraph анализирует собственную кодовую базу через граф свойств кода (CPG) после каждого коммита, создавая цикл обратной связи Планирование-Действие-Проверка. Claude Code получает метрики качества, данные о зоне поражения и сравнение до/после как контекст сразу после коммита.
Содержание¶
- Как это работает
- Сценарии использования
- Сценарий 1: Автоматическая обратная связь после коммита
- Сценарий 2: Поиск и исправление проблем качества
- Сценарий 3: Валидация влияния рефакторинга
- Сценарий 4: Анализ по запросу
- Архитектура конвейера
- Поток данных
- Бюджет ограничений по времени
- Актуальность CPG и полный перепарсинг
- Дедупликация методов
- Дельта-отчёт
- Установка
- CLI-команды
- Конфигурация
- Формат отчёта
- Масштабирование на другие проекты
- Устранение неполадок
Как это работает¶
Конвейер самоанализа связывает три системы:
-
GoCPG строит и поддерживает граф свойств кода (CPG) в DuckDB с предвычисленными метриками для каждого метода: цикломатическая сложность, входящая/исходящая связность, флаги TODO/FIXME, отладочный код, устаревшие вызовы.
-
Git-хуки запускают обновление CPG после каждого коммита, поддерживая базу данных в синхронизации с кодом.
-
Хуки Claude Code срабатывают после команд
git commit, запрашивают CPG по изменённым методам, вычисляют метрики качества и зону поражения, затем внедряют отчёт обратно в диалог как дополнительный контекст.
Результат: каждый коммит мгновенно получает оценку качества без выхода из IDE и запуска отдельных инструментов.
Сценарии использования¶
Сценарий 1: Автоматическая обратная связь после коммита¶
Основной сценарий. Вы работаете в Claude Code, вносите изменения, коммитите:
Вы: "Закоммить эти изменения"
Claude: git add src/intent/classifier.py && git commit -m "refactor: extract pattern table"
Хук PostToolUse срабатывает автоматически и внедряет отчёт:
## Commit Analysis Report
**Summary:** 1 files, 45 methods, 2 high-CC, 3 TODO/FIXME, 128 affected callers
**CPG status:** fresh
**Impact of changes:**
- `_get_fallback_domain`: CC 29->8 (-21), FanOut 18->5 (-13)
**High complexity methods:**
- `classify` (CC: 17)
- `_score_domain` (CC: 16)
**Blast radius:** 128 callers affected
- `classify` called by: `run_intent_classifier`, `IntentBenchmark._evaluate_single` +126 more
Claude видит этот контекст и может отреагировать: “Рефакторинг снизил сложность _get_fallback_domain с 29 до 8. Два метода всё ещё имеют CC>10: classify и _score_domain.”
Что запускает хук: Любая команда git commit, выполненная через инструмент Bash. Хук обнаруживает "git commit" в строке команды. Другие Bash-команды (git status, ls) игнорируются.
Что НЕ запускает хук: Прямые коммиты из терминала вне Claude Code, git commit --amend, коммиты через другие инструменты.
Сценарий 2: Поиск и исправление проблем качества¶
Используйте CPG-запросы для поиска целей по улучшению качества, затем исправляйте их с обратной связью от конвейера:
Вы: "Запроси CPG для методов с CC > 15 и флагами TODO/FIXME в src/workflow/"
Claude: [выполняет запрос к DuckDB]
Найдено: _get_fallback_domain (CC=29, TODO), PolicyViolationsHandler.handle (CC=68, TODO)
Вы: "Отрефактори _get_fallback_domain для снижения сложности"
Claude: [извлекает шаблоны в таблицу данных, заменяет цепочку if/else на цикл]
Вы: "Закоммить"
Claude: git commit -m "refactor: extract fallback patterns to class-level table"
-> Хук срабатывает, отчёт показывает: CC 29->8 (-21)
Это полный цикл Планирование-Действие-Проверка: 1. Планирование: CPG-запрос выявляет проблему 2. Действие: Рефакторинг снижает сложность 3. Проверка: Хук подтверждает улучшение конкретными метриками
Сценарий 3: Валидация влияния рефакторинга¶
Перед крупным рефакторингом проверьте зону поражения:
Вы: "Какова зона поражения при изменении HierarchicalIntentClassifier.classify?"
Claude: [запрашивает call_containment]
213 прямых вызывающих методов в рабочем коде и тестах
Вы: "Продолжай рефакторинг"
Claude: [вносит изменения, коммитит]
-> Хук показывает: 213 затронутых вызывающих, CC без изменений, регрессий нет
Отчёт о зоне поражения помогает оценить риск изменений до их применения.
Сценарий 4: Анализ по запросу¶
Запуск анализа без коммита:
# Анализ последнего коммита
python -m src.cli.import_commands dogfood analyze --base-ref HEAD~1
# Анализ изменений между ветками
python -m src.cli.import_commands dogfood analyze --base-ref origin/main
# Генерация полного отчёта о качестве
python -m src.cli.import_commands dogfood report --format markdown
Архитектура конвейера¶
Поток данных¶
git commit (через инструмент Bash в Claude Code)
|
v
Хук PostToolUse срабатывает (.claude/hooks/commit_analysis.py, время ожидания 60с)
|
+-- Фаза 1: Проверка актуальности CPG
| Запрос cpg_git_state.commit_hash, сравнение с git rev-parse HEAD
|
+-- Фаза 1.5: Захват метрик до обновления (для дельта-отчёта)
| Запрос nodes_method для изменённых файлов ДО обновления CPG
| Сохранение {full_name: {cc, fan_out, ...}} для последующего сравнения
|
+-- Фаза 2: Обновление CPG (--force для точных метрик)
| gocpg update --force --input=<source> --output=<db>
| Полный перепарсинг гарантирует вычисление CC/fan_in/fan_out через MethodMetricsPass
|
+-- Фаза 3: Анализ качества + зона поражения
| Запрос nodes_method для изменённых файлов (после обновления)
| Дедупликация методов (нормализация слешей, выбор наибольшего CC)
| Сводка качества: high-CC, high-fan_out, TODO, debug, deprecated
| Запрос call_containment для вызывающих изменённых методов
|
+-- Фаза 4: Вычисление дельты
| Сравнение метрик до и после обновления
| Генерация отчёта до->после: "CC 29->8 (-21)"
|
+-- Вывод: {"additionalContext": "## Commit Analysis Report\n..."}
Внедряется обратно в диалог Claude Code
Бюджет ограничений по времени¶
Хук имеет общее ограничение по времени 60 секунд с внутренними фазами:
| Фаза | Бюджет | Действие |
|---|---|---|
| Проверка актуальности | 2с | Сравнение cpg_git_state.commit_hash с git rev-parse HEAD |
| Метрики до обновления | ~1с | Запрос текущих метрик для изменённых файлов (для дельта-отчёта) |
| Обновление CPG (–force) | 40с | Запуск gocpg update --force для полного перепарсинга с метриками |
| Анализ качества | 8с | Запрос nodes_method для CC, TODO, debug, deprecated |
| Зона поражения | 8с | Запрос call_containment для прямых вызывающих |
Если какая-либо фаза превышает бюджет, хук корректно снижает функциональность: выдаёт имеющиеся данные или возвращает пустой {}.
Актуальность CPG и полный перепарсинг¶
Хук использует флаг --force при запуске gocpg update. Это запускает полный перепарсинг вместо инкрементального обновления. Причина:
-
Инкрементальное обновление (
gocpg updateбез--force): Создаёт новые записи методов, но пропускаетMethodMetricsPass. Новые записи имеютcyclomatic_complexity=0,fan_in=0,fan_out=0. Быстро, но метрики неполные. -
Полный перепарсинг (
gocpg update --force): Запускает полный конвейер парсинга включаяMethodMetricsPass. Все метрики вычисляются корректно. Медленнее, но точно.
Для самоанализа точность важнее скорости. Бюджет в 40 секунд достаточен для полного перепарсинга проектов до нескольких сотен исходных файлов.
Дедупликация методов¶
GoCPG может хранить один и тот же метод с разными форматами имени файла (прямой слеш src/file.py vs обратный src\file.py). Анализатор дедуплицирует путём нормализации слешей в full_name и сохранения записи с наибольшим значением CC:
# До дедупликации: 2 записи для одного метода
src\intent\classifier.py:Classifier.classify CC=17
src/intent/classifier.py:Classifier.classify CC=0 (из инкрементального обновления)
# После дедупликации: 1 запись, наибольший CC побеждает
src\intent\classifier.py:Classifier.classify CC=17
Дельта-отчёт¶
Когда CPG устарел (требует обновления), хук захватывает метрики до обновления перед запуском gocpg update --force, затем сравнивает с метриками после обновления. Это создаёт дельту, показывающую реальное влияние изменений:
**Impact of changes:**
- `_get_fallback_domain`: CC 29->8 (-21), FanOut 18->5 (-13)
- `_build_quality_summary`: CC 5->3 (-2)
Методы без изменений метрик пропускаются. Это помогает разработчикам сразу увидеть, улучшил или ухудшил рефакторинг качество кода.
Установка¶
Установка одной командой¶
python -m src.cli.import_commands dogfood setup --repo . --db data/projects/codegraph.duckdb
Это устанавливает git-хуки (через gocpg) и проверяет конфигурацию хуков Claude Code.
Ручная установка¶
-
Установка git-хуков (фоновое обновление CPG при коммите):
bash gocpg/gocpg.exe hooks install --repo=. --db=data/projects/codegraph.duckdb -
Настройка хуков Claude Code в
.claude/settings.json:json { "hooks": { "PostToolUse": [{ "matcher": "Bash", "hooks": [{ "type": "command", "command": "python .claude/hooks/commit_analysis.py", "timeout": 60000 }] }] } }
Примечание: Поле matcher должно быть строкой (регулярное выражение), а не объектом. "Bash" соответствует конкретно инструменту Bash.
Проверка установки¶
python -m src.cli.import_commands dogfood status
Ожидаемый вывод показывает актуальность CPG, статус хуков и путь к базе данных.
CLI-команды¶
# Полная установка (git-хуки + хуки Claude Code)
python -m src.cli.import_commands dogfood setup [--repo PATH] [--db PATH] [--language LANG]
# Проверка актуальности CPG и статуса хуков
python -m src.cli.import_commands dogfood status [--db PATH]
# Запуск анализа коммита по запросу
python -m src.cli.import_commands dogfood analyze [--base-ref HEAD~1] [--db PATH]
# Генерация отчёта о качестве (markdown или JSON)
python -m src.cli.import_commands dogfood report [--format markdown|json] [--db PATH]
Конфигурация¶
В config.yaml:
dogfooding:
enabled: true
auto_update_cpg: true # Запускать gocpg update если CPG устарел
cpg_update_timeout: 40 # Секунды на обновление CPG
analysis_timeout: 16 # Секунды на анализ качества + зону поражения
cc_threshold: 10 # Отмечать методы с CC выше этого значения
fan_out_threshold: 30 # Отмечать методы с fan_out выше этого значения
blast_radius_depth: 2 # Максимальная глубина обхода вызывающих
max_files_per_commit: 15 # Максимум файлов для анализа за коммит
report_format: markdown # markdown или json
Формат отчёта¶
Хук возвращает markdown-отчёт как additionalContext в JSON:
{"additionalContext": "## Commit Analysis Report\n**Summary:** ..."}
Полная структура отчёта:
## Commit Analysis Report
**Summary:** 3 files, 45 methods, 2 high-CC, 1 TODO/FIXME, 128 affected callers
**CPG status:** fresh
**Impact of changes:**
- `_get_fallback_domain`: CC 29->8 (-21), FanOut 18->5 (-13)
**High complexity methods:**
- `classify` (CC: 17)
- `_score_domain` (CC: 16)
**High fan-out methods:**
- `classify` (fan_out: 39)
**Blast radius:** 128 callers affected
- `classify` called by: `run_intent_classifier`, `IntentBenchmark._evaluate_single` +126 more
- `_classify_domain` called by: `classify`, `get_morph` +4 more
*Analysis completed in 95ms*
Секции пропускаются если пустые (нет high-CC методов = нет секции “High complexity”).
Масштабирование на другие проекты¶
Конвейер самоанализа не привязан к конкретному проекту. Для настройки на любой проект:
-
Импортируйте проект для создания базы данных CPG:
bash python -m src.cli import /path/to/project --language python -
Зарегистрируйте проект в
config.yaml:yaml projects: active: my_project registry: my_project: db_path: data/projects/my_project.duckdb source_path: /path/to/project language: python domain: python_generic -
Запустите установку:
bash python -m src.cli.import_commands dogfood setup --repo /path/to/project --db data/projects/my_project.duckdb
Хук читает активный проект из config.yaml и автоматически определяет правильный путь к базе данных.
Устранение неполадок¶
Хук возвращает пустой {}:
- Проверьте, что файл базы данных существует по настроенному db_path
- Убедитесь, что активный проект в config.yaml имеет валидный db_path
- Запустите python -m src.cli.import_commands dogfood status для проверки актуальности
- Убедитесь, что коммит изменил файлы с кодом (.py, .go, .c и т.д.), а не только документацию или конфигурации
CPG всегда показывает устаревший статус:
- Убедитесь, что бинарник gocpg существует по пути gocpg/gocpg.exe (или настроенному GOCPG_PATH)
- Проверьте, что git-хуки установлены: ищите .git/hooks/post-commit
- Попробуйте ручное обновление: gocpg/gocpg.exe update --force --input=. --output=<db>
Значения CC равны 0 после инкрементального обновления:
- Это происходит когда gocpg update запускается без --force. Инкрементальное обновление пропускает MethodMetricsPass.
- Хук использует --force по умолчанию. Если вы видите CC=0, полный перепарсинг мог превысить ограничение по времени. Проверьте бюджет в 40 с.
Ошибка блокировки DuckDB (“file is being used by another process”):
- Другой процесс gocpg.exe запущен (например, от gocpg watch или параллельного вызова хука).
- Хук использует соединения в режиме только для чтения и обрабатывает ошибки блокировки, переключаясь на запросы через подпроцесс.
Дельта-отчёт не появляется:
- Дельта-отчёт появляется только когда CPG был устаревшим до обновления (были захвачены метрики до обновления).
- Если CPG уже актуален (например, gocpg watch обновил его), метрики до обновления отсутствуют для сравнения.
Превышение времени ожидания:
- Бюджет в 60 с достаточен для большинства коммитов. Для очень больших проектов gocpg update --force может превысить бюджет фазы в 40 с.
- Уменьшите max_files_per_commit в конфигурации или рассмотрите использование инкрементального обновления (уберите force=True в commit_analysis.py).
- Убедитесь, что индексы GoCPG актуальны: gocpg/gocpg.exe index --db=<db>