Подзаголовок секции с кратким описанием того, что внутри секции.
Этот документ объясняет, как быстро читать PR-коммент CodeGuard и какие действия выбрать: принять, запросить правку, упростить, изолировать изменение или углубиться в полный отчёт.
CodeGuard — это радар для ревью, который подсвечивает места, где PR нетипично меняет структуру/поведение относительно привычного “рисунка” репозитория.
В отчёте есть три независимых слоя сигнала:
NET_IO/DB/FILE_IO/EXEC/LOG) и рядом какие источники (USER_INPUT/SECRET/...).Важное: это не SAST и не баг-файндер. Инструмент не “доказывает” ошибку — он помогает сфокусировать внимание ревьюера.
Обычно в GitHub вы видите:
Содержит:
Status, risk_level, ci_status, analysis full/partial),struct_risk,Markdown / JSON.Нужен, когда:
analysis=partial и важно понять, что именно было пропущено,Top-N hotspots в PR-комменте — это лимит вывода, а не ограничение понимания. Это “первые по приоритету” участки, чтобы не превращать комментарий в простыню.
Смотрите сразу 4 поля:
risk_level (low|medium|high)struct_risk (0–100)ci_status (ok|warn|fail)analysis (full|partial)Быстрое правило:
risk_level=high → почти всегда идём в hotspots и главный файл.analysis=full → весь код, который CodeGuard умеет анализировать в этом репозитории (на текущем этапе — Python), был обработан.analysis=partial → в PR есть файлы вне профиля анализа (например, YAML/CSV/Markdown и т.п.), и по ним CodeGuard не делал анализ. Python-часть PR при этом обработана полностью.Откройте Per-file structural risk и ответьте:
Если один файл тащит всё — ревью ускоряется: начинайте с него.
Откройте Top hotspots и пройдитесь по первым 3–5 строкам.
Для каждого hotspot ответьте:
Если в колонках Effects / Taint / Control что-то есть — начинайте с них. Это обычно более “прикладной” риск, чем чистая форма кода.
После просмотра нескольких hotspots вы должны выбрать один из путей:
risk_level и struct_riskstruct_risk — число 0–100: “насколько структура выбивается”.risk_level — дискретный уровень для быстрого решения.Как читать:
low → обычно достаточно убедиться, что hotspots не содержат неприятных effects/taint.medium → почти всегда смотрим top-3 hotspots.high → смотрим главный файл + top hotspots и решаем: simplify/isolate/обосновать.ci_statusЭто сигнал для CI/дашборда:
ok → инструмент не видит проблемных пороговых ситуаций.warn → “обязательно посмотри глазами”.fail → в строгом режиме CI это может блокировать (зависит от политики проекта).analysis: full|partialfull → CodeGuard проанализировал весь поддерживаемый код в PR (на текущем этапе — Python).partial → PR содержит изменения в файлах, которые CodeGuard не анализирует (не-код/неподдерживаемые расширения). В этом режиме отчёт “частичный” не потому, что Python разобран не до конца, а потому что часть PR лежит вне области анализа.Правило ревью:
kind и scorekind — тип локальной аномалии (что именно “не похоже на норму”).score — приоритет (какое место смотреть раньше), а не “вероятность бага”.Типовые kind (интуитивно):
struct_pattern_break — “вставили нетипичный структурный рисунок” (часто это новые сущности/паттерны/стиль).depth_spike — “слишком выросла вложенность/условность”.control_outlier — “перегреты пути исполнения” (условия/ошибки/return-хвосты).mixed — смесь факторов.risk_level=low, ci_status=ok, analysis=fullОбычно:
risk_level=medium или ci_status=warnОбычно:
risk_level=highМинимум:
Per-file structural risk,analysis=partialОбычно означает, что PR содержит файлы вне области анализа (например, YAML/CSV/Markdown).
Что делать:
“CodeGuard подсветил нетипичное усложнение в <участок>. Это сделано для <цель>. Добавлены/обновлены тесты <...> и комментарий к контракту.”
“В этом месте появляется структурный разрыв относительно стиля репозитория. Предлагаю переписать как <простая функция/без lambda/без генератора>, чтобы сохранить предсказуемость кода.”
“Похоже на внедрение новой мини-архитектуры/алгоритма. Давайте вынесем в отдельный модуль/класс с явным интерфейсом и короткой документацией, чтобы изменение было локализовано.”
“Изменение меняет режим/математику/контракт. Нужны тесты на <инвариант/крайние случаи/стабильность> или явный флаг конфигурации.”
Если вы видите:
Status: High riskstruct_risk: 69.49control_risk_level: lowstruct_pattern_breakИнтерпретация:
Переходите к Full report, если:
Effects/Taint/Control и нужно оценить безопасность/границы/контракты,analysis=partial,REPORT_FIELDS_REFERENCE — справочник всех полей отчёта (подробно).REVIEW_PLAYBOOKS — плейбуки (high struct, high control, effects/taint, partial).CASE_STUDIES — разборы реальных PR (как принимать решения на примерах).Этот документ — справочник по полям отчётов CodeGuard: что означает каждое поле, где оно встречается (PR-коммент / Full report / JSON), как его интерпретировать и какие типовые причины у “странных” значений.
Сначала прочитай: docs/PR_REVIEW_QUICKSTART.md (маршрут чтения за 3–5 минут).
Здесь — именно словарь полей.
В GitHub PR обычно есть два уровня выдачи:
PR-коммент (Summary)
Короткий: статусы, top-N hotspots, per-file structural risk, ссылки на Full report.
Full report (Markdown / JSON)
Полный артефакт: таблицы, дополнительные секции, служебные поля, лимиты анализа.
_risk ∈ [0,100] — нормализованные оценки, удобные для порогов и “светофора”._risk_level ∈ {low, medium, high} — дискретизация для быстрого решения._density ∈ [0,1] — доля “сигнальных” токенов/эффектов в выбранной области.path/to/file.py:LINE_START-LINE_ENDfile_pathline_start / line_end (1-based)Колонки Effects / Taint / Control в hotspots могут быть пустыми, если:
partial и кусок не попал в разбор.Типичный заголовок:
Status: High riskstruct_risk: 69.49hotspots: 10ci_status: warncontrol_risk_level: lowanalysis: full|partialНиже — расшифровка.
Status (человеческий статус)Где: Summary / Full report (Markdown)
Тип: string (обычно Low/Medium/High risk)
Смысл: человекочитаемая “выжимка” по риску/CI-политике.
Практически Status обычно согласован с risk_level + ci_status, но это именно “лейбл”.
risk_levelГде: Full report (Markdown), часто в JSON (зависит от режима CLI/интеграции)
Тип: enum: low | medium | high
Смысл: дискретный уровень структурного риска (для быстрого решения “копать или нет”).
Типовая интерпретация:
low: структурно похоже на типичный код репозитория.medium: стоит глянуть hotspots.high: заметная структурная аномалия — почти всегда ручной просмотр.struct_riskГде: Summary / Full report (Markdown)
Тип: float 0..100
Смысл: глобальный структурный риск для объекта анализа (PR/diff).
Важно:
Per-file structural risk.В JSON-репортах аналог обычно называется global_struct_risk.
hotspots (count)Где: Summary (короткий коммент)
Тип: int
Смысл: сколько hotspots показано в этом комментарии.
Важно:
ci_statusГде: Summary / Full report (Markdown), иногда JSON
Тип: enum: ok | warn | fail
Смысл: сигнал для CI/интеграции (как отображать/гейтить).
Типовая политика:
ok: пороги не превышены.warn: есть что посмотреть (soft gate).fail: строгий режим (hard gate) — зависит от настройки.control_risk_levelГде: Summary / Full report (Markdown), JSON (если включён control-канал)
Тип: enum: low | medium | high
Смысл: дискретный уровень “контрольной сложности” (условия / error-path / return-tail).
Интуиция:
low: ветвления/ошибки/return-хвосты выглядят нормально.high: условия и/или error-ветки и/или хвосты перегреты → читать трудно, легко ошибиться.analysis: full|partialГде: Summary / Full report (Markdown)
Тип: enum: full | partial
Смысл: покрытие отчётом поддерживаемых типов файлов.
full → весь поддерживаемый код в PR проанализирован (на текущем этапе — Python).partial → в PR есть изменения в файлах, которые CodeGuard не анализирует (например, YAML/CSV/Markdown и т.п.). Python-файлы при этом анализируются полностью; “partial” относится к PR как целому.Практика:
partial не надо трактовать как “Python разобран наполовину”.partial означает: “часть PR лежит вне области анализа и должна ревьюиться вручную”.Где: Summary / Full report (Markdown)
Смысл: вклад каждого файла в общий structural-риск.
Колонки:
File — путьRisk — структурный риск файла (0..100)Как читать:
В JSON аналог: file_struct_risk: { "path": number, ... }
Hotspot = локальный участок строк, который выглядит нетипично.
Типичная строка:
| Location | Kind | Score | Effects | Taint | Control |
|---|
Расшифровка колонок:
Locationfile.py:START-ENDKindТип: enum
Обычно:
struct_pattern_break — “слом типичного структурного рисунка” в окне (нетипичные маркеры IF/LOOP/RETURN/..., новые “паттерны”, смена стиля).depth_spike — локально аномальная вложенность.control_outlier — окно перегрето по control-режимам (условия/error/return).mixed — нет одного доминанта, но окно всё равно выбивается.ScoreТип: float (ранжирование)
Смысл: приоритет просмотра (чем больше — тем выше в списке).
Важно:
score — не вероятность бага и не абсолютная “оценка качества”.EffectsТип: string / метка / краткая подсказка
Смысл: семантическая подсказка про side-effects (если semantic-канал включён и что-то найдено).
Обычно эффекты (уровень токенов/фрагментов):
LOG, DB, FILE_IO, NET_IO, EXEC (и т.п.)TaintТип: string / метка / краткая подсказка
Смысл: источники данных рядом (если включено):
USER_INPUT — входные данныеSECRET — потенциальные секретыCONST — константыControlТип: string / метка / краткая подсказка
Смысл: контрольный контекст окна:
BRANCH_COND, ERROR_PATH, RETURN_PATH, INIT_PATH, CLEANUP_PATH, NORMALОбычно:
file_path: stringline_start, line_end: int (1-based)segment_id: string (например, hunk_0)segment_kind: enum (diff_hunk, full_file, …)kind: enumscore: floateffect_hint, taint_hint, control_hintГде: Full report (Markdown) и JSON (если включён control-канал)
В PR-репорте может быть таблица:
| File | overall | branch_cond | error_path | return_path |
|---|
Смысл:
overall — общий control-риск для файла (обычно агрегат/максимум).branch_cond — риск ветвлений/условий.error_path — риск error-веток.return_path — риск “return/raise-хвостов”.control_summary.per_file[path]Полевая модель (часто встречается как “пер-файл агрегаты”):
control_share_branch_condcontrol_share_error_pathcontrol_share_return_pathcontrol_share_init_pathcontrol_share_cleanup_pathcontrol_*_complexity_meancontrol_*_complexity_maxbranch_cond_effect_densityerror_path_effect_densityreturn_path_effect_densitybranch_cond_riskerror_path_riskreturn_path_riskoverall_control_riskПримеры:
branch_cond_risk высокий + branch_cond_effect_density > 0 → в условиях происходит IO/NET/DB/LOG (часто подозрительно и плохо читается).error_path_risk высокий + error_path_effect_density высокий → обработчики ошибок делают много эффектов.return_path_risk высокий + return_path_effect_density высокий → “перед возвратом” происходит эффектная логика (меняет поведение на выходе).Если semantic-канал включён, в JSON (и иногда в Markdown) появляются поля, связанные с эффектами и “опасными” потоками.
effect_summaryГде: JSON, иногда Full report (Markdown)
Смысл: агрегаты по эффектам/taint.
effect_summary.per_file[path] (по файлам)Типовые метрики:
effect_density_tail ∈ [0,1]
Доля “эффектных” токенов (NET/DB/FILE/EXEC/LOG) в хвосте файла/сегмента.
Интуиция: ближе к 1 → хвост “плотно эффектный”.
dangerous_flow_score ∈ [0,1]
Грубый сигнал, что USER_INPUT проходит рядом с эффектами (NET_IO/DB/EXEC/LOG).
> 0 → найден хотя бы один потенциально опасный соседний flow.
secret_leak_score ∈ [0,1]
Грубый сигнал, что SECRET встречается рядом с LOG / NET_IO.
> 0 → возможная утечка секретов.
effect_summary.globalМаксимумы/агрегаты по всем файлам отчёта — быстрый ответ “есть ли вообще effect-активность”.
file_semantic_risk и file_semantic_risk_levelГде: JSON
Тип:
file_semantic_risk[path] ∈ [0,100]file_semantic_risk_level[path] ∈ {low, medium, high}Смысл: repo-aware оценка “семантического” риска файла (эффектный хвост + suspicious flow + поправка по истории).
Частое правило приоритизации:
struct_risk и высокий file_semantic_risk по одному и тому же файлу → файл почти всегда стоит ревьюить вручную “в первую очередь”.taint (как интерпретировать)Taint-метки обычно не “про безопасность”, а про источники данных рядом:
USER_INPUT → важно смотреть, куда дальше идёт значение (особенно рядом с NET/DB/EXEC/LOG)SECRET → важно смотреть, нет ли рядом логирования/сетиЕсли подключены командные правила (семантические инварианты), отчёт может содержать:
invariant_violations: список нарушенийЭто самый “жёсткий” и понятный слой:
правило нарушено → вот место → исправляем или осознанно исключаем.
partialanalysis=partial означает: в PR есть файлы вне профиля анализа (на текущем этапе CodeGuard заточен под Python-код). Примеры: YAML, CSV, Markdown, ассеты, данные, конфиги и т.п.
partialЕсли проекту важно, чтобы YAML/Markdown/CSV тоже проходили “автоматический радар”, это отдельный roadmap: подключать анализаторы для новых типов/языков и расширять scope.
В зависимости от интеграции/версии могут присутствовать:
Generated / timestamp (в Markdown шапке)repo_root, pr_number (в JSON)Markdown / JSON (в Summary)expires_at_unix_s (в Summary, если ссылки на Full report имеют срок действия) Unix time (секунды), когда токенизированная ссылка/артефакт может истечь.Markdown struct_risk (в PR Summary/Full report)
≈ JSON global_struct_risk
Markdown “Per-file structural risk”
≈ JSON file_struct_risk
Markdown “Hotspots” (таблица top-N)
≈ JSON hotspots (может быть шире/полнее в полном артефакте)
Markdown analysis: full|partial
⇐ выводится из analysis_limits + fallback/ограничений
control_summary везде 0.0?Effects/Taint пустые в hotspots?Этот документ — набор плейбуков “что делать”, когда CodeGuard подсвечивает:
Цель плейбуков — не заменить ревью, а быстро выбрать правильный тип реакции:
Сначала прочитай маршрут: docs/PR_REVIEW_QUICKSTART.md.
Справочник полей: docs/REPORT_FIELDS_REFERENCE.md.
invariant_violations — это “жёсткий сигнал”Если включены командные правила (semantics/invariants), нарушения трактуются как:
Смотри Summary:
analysis=partial → Playbook: Partial analysis (scope)risk_level=high и hotspots в основном struct_pattern_break/depth_spike → Playbook: High structcontrol_risk_level=high или hotspots control_outlier → Playbook: High controlEffects/Taint, в JSON виден effect_density_tail/dangerous_flow_score →
USER_INPUT рядом с NET/DB/EXEC/LOG → Playbook: USER_INPUT → Effectsrisk_level=high и/или высокий struct_riskstruct_pattern_breakdepth_spikemixed (если доминирует форма/глубина)control_risk_level может быть low — это нормально: “форма нетипична, но ветвления не перегреты”.Per-file structural risk?Подходит, если:
Действия:
Шаблон PR-комментария:
“CodeGuard подсветил структурный разрыв в <file:lines>. Изменение осознанное: <зачем>. Добавлены тесты <что проверяем> / комментарий к контракту.”
Подходит, если:
Техники упрощения:
next_*,Шаблон PR-комментария:
“Есть структурный разрыв относительно нормы репозитория. Давай перепишем участок более императивно/плоско (без <lambda/yield/…>), чтобы снизить когнитивную нагрузку.”
Подходит, если:
Действия:
Шаблон PR-комментария:
“Похоже на внедрение новой подсистемы. Давай вынесем в отдельный модуль с явным интерфейсом и тестами — так изменение станет локализованным и понятным.”
control_risk_level=high (даже если struct_risk средний/низкий)control_outliercontrol_summary высокие значения:
branch_cond_riskerror_path_riskreturn_path_risk_effect_density
branch_cond_effect_densityerror_path_effect_densityreturn_path_effect_densityТиповые проблемы:
if с вычислениями и IO,elif как mini-state-machine,Что делать:
is_*, should_*),elif,PR-комментарий:
“Control-слой показывает перегретые условия. Предлагаю вынести условия в именованные предикаты и убрать эффекты из условий — так снизим риск ошибок и улучшим читаемость.”
Типовые проблемы:
except делает половину бизнес-логики,Что делать:
except: собрать контекст → вызвать handle_error(...),PR-комментарий:
“Error-path стал сложным. Давай вынесем обработку ошибок в отдельные функции/модуль, чтобы except не превращался в программу внутри программы.”
Типовые проблемы:
return выполняются эффекты (лог/запись/сеть),Что делать:
PR-комментарий:
“В return-path появилась тяжёлая логика/эффекты. Опасно менять контракт на выходе. Предлагаю разделить вычисление результата и эффекты и покрыть контракт тестами.”
effect_density_tail (по файлу или по PR)Effects (например NET_IO+DB+LOG) без явных TaintDB / NET_IO / EXEC — высокий приоритетLOG — зависит от контекста, но при большом объёме может быть “шумом”persist_*, send_*, exec_*)PR-комментарий:
“В хвосте файла/функции концентрируются IO/NET/DB эффекты. Давай выделим ‘эффектный слой’ и добавим тесты на ошибки/идемпотентность, чтобы поведение было предсказуемым.”
dangerous_flow_score > 0taint_hint=USER_INPUT и effect_hint включает NET_IO/DB/EXEC/LOGЭто не полноценный dataflow-анализ, но практический риск понятен:
PR-комментарий:
“Есть участок, где USER_INPUT находится рядом с NET/DB/EXEC/LOG. Давай явно зафиксируем границы: валидацию/allowlist/маскирование и добавим тесты на небезопасные входы.”
analysis=partialPR содержит файлы вне области анализа CodeGuard (на текущем этапе — не Python: YAML/CSV/Markdown и т.п.). Для Python-части отчёт остаётся полноценным.
“analysis=partial — в PR есть непрофильные файлы (конфиги/данные/доки), CodeGuard анализирует только Python-часть. По этим файлам делаем обычное ручное ревью.”
“Это осознанная архитектурная идея или случайное усложнение? Если осознанная — добавь краткое rationale и тест на контракт.”
“Похоже на новую подсистему. Давай вынесем в отдельный модуль/класс с явным API.”
“Изменение меняет режим/контракт/эффектный хвост. Нужны тесты на ошибки/крайние случаи/идемпотентность.”
“Сейчас analysis partial. Разбей PR или уменьшай hunks, чтобы отчёт был полным.”
Если CodeGuard регулярно подсвечивает одни и те же классы проблем, команда может:
.codeguard/semantics.yaml (invariants),Это превращает “одноразовый сигнал” в системное улучшение архитектуры.
struct_pattern_break на реальном PRЦель кейса: показать на конкретном PR, что именно CodeGuard подсветил, как это выглядело в отчёте, какой кусок кода за этим стоит и почему это важно при ревью.
Repo/PR: */PythonRobotics_test PR #1
Status: High risk
struct_risk: 69.49
control_risk_level: low
analysis: full
Per-file structural risk
ArmNavigation/n_joint_arm_to_point_control/n_joint_arm_to_point_control.py — 69.49ArmNavigation/__init__.py — 0.00Top hotspots (10)
Все 10 — struct_pattern_break (разрыв типичного структурного паттерна в окне строк).
Ниже — перечень нетипичных изменений, внесённых в код специально для теста:
KinematicsConfig ✅ (не подсвечено)InverseKinematicsSolver ✅ (не подсвечено)_StateManager 🟡 (подсвечено)yield и сложной логикой 🟡 (подсвечено)get_random_goal 🟡 (подсвечено)Kp ✅ (не подсвечено)accumulator в цикле 🟡 (подсвечено)Формат ниже — ровно то, что нужно ревьюеру:
Примечание: control_risk_level=low означает, что сигнал здесь не про перегретые ветвления/ошибки, а именно про структурный дрейф.
_StateManager (приватный класс)Report: ...py:286-286 — struct_pattern_break (score=1.7802)
Что в коде (пример):
class _StateManager:
def __init__(self):
self.current = ArmState.WAIT_FOR_NEW_GOAL
def validate_transition(self, new_state: ArmState) -> bool:
...
Почему важно: в файл приходит “мини-подсистема управления состоянием” (новая архитектурная сущность), которую нужно либо осознанно принять, либо локализовать, иначе она разрастётся “по месту”.
Что делать (варианты):
yieldReport: ...py:175-175 — struct_pattern_break (score=1.7209)
Что в коде (пример):
def _goal_generator():
while True:
goal = get_random_goal(...)
yield goal
Почему важно: генератор меняет модель исполнения (появляется поток значений и “скрытое состояние”), что влияет на читаемость и дебаг.
Что делать:
next_goal() без yield.Report: ...py:162-164 — struct_pattern_break (score=1.6677)
Что в коде (пример):
if use_gaussian:
return np.array([random.gauss(mu, sigma), ...])
return np.array([random.uniform(a, b), ...])
Почему важно: это меняет режим/динамику поведения (распределение целей) — алгоритмическая смена, которую ревьюер должен увидеть сразу.
Что делать:
accumulator внутри вычисленияReport: ...py:307-307 — struct_pattern_break (score=1.5986)
Что в коде (пример):
accumulator = lambda x, y, l, a: x + l*np.cos(a) + y*np.sin(a)
...
for ...
v = accumulator(...)
Почему важно: нетипичная форма записи (функциональный стиль “внутри цикла”) ухудшает прозрачность вычисления.
Что делать:
Report: ...py:248-249 — struct_pattern_break (score=1.5452)
Что в коде (пример):
JTJ = J.T @ J
damped = JTJ + damping * np.eye(N_LINKS)
return np.linalg.inv(damped) @ J.T
Почему важно: это изменение численного метода (стабильность/сходимость/поведение решения), которое должно быть осознанным и проверенным.
Что делать:
tanhReport: ...py:321-323 — struct_pattern_break (score=1.5452)
Что в коде (пример):
distance = np.linalg.norm(target - current)
scale = np.tanh(distance * 2) / 2.0 + 0.5
delta *= scale
Почему важно: нелинейность меняет динамику управления/обновления — это влияет на поведение системы, даже если код “выглядит аккуратно”.
Что делать:
np.rollReport: ...py:335-335 — struct_pattern_break (score=1.5452)
Что в коде (пример):
recovery_strategies = [
lambda x: -x,
lambda x: np.clip(x, -1, 1),
lambda x: np.roll(x, 1),
]
Почему важно: это внедрение паттерна “Стратегия” (композиция трансформаций), т.е. фактически новая архитектурная идея.
Что делать:
all(...) for ...)Report: ...py:176-177 — struct_pattern_break (score=1.5399)
Что в коде (пример):
if all(np.linalg.norm(goal - g) > 2.0 for g in goal_history[-3:]):
yield goal
Почему важно: сложная логика фильтрации встроена внутрь генератора — это усложняет понимание правил выбора цели.
Что делать:
is_goal_far_enough(goal, history) + тесты на крайние случаи.Report: ...py:146-146 — struct_pattern_break (score=1.5228)
Что в коде (пример):
def log_callback(iter_idx, err, angles):
logger.info("...")
solver.solve(..., callback=log_callback)
Почему важно: появляется новый “hook” расширяемости; команда должна понимать, это принятный паттерн для репозитория или нет.
Что делать:
Report: ...py:259-259 — struct_pattern_break (score=1.4533)
Что в коде (пример):
for strategy in recovery_strategies:
delta = strategy(delta)
Почему важно: цепочка трансформаций меняет поведение “по месту”; без контракта трудно понять, что гарантируется на выходе.
Что делать:
struct_pattern_break на реальном коде: это не “стиль отступов”, а места, где PR приносит новые сущности/паттерны/алгоритмическую смену.