Автоматическая проверка кода

Содержание

Обзор

Система автоматической проверки кода анализирует изменения (git diff, GitHub PR, GitLab MR) с использованием анализа графа свойств кода (CPG) для предоставления всесторонней обратной связи, включая:

  • Обнаружение уязвимостей безопасности
  • Анализ влияния на производительность
  • Оценку риска ошибок
  • Анализ влияния на архитектуру
  • Проверку соответствия критериям завершения (Definition of Done, DoD)
  • Фильтрацию с учётом области видимости и SARIF-вывод

Быстрый старт

Использование CLI

# Проверка изменений относительно базового коммита
python -m src.cli review --base-ref HEAD~3

# Проверка только проиндексированных изменений
python -m src.cli review --staged

# Проверка конкретных файлов
python -m src.cli review --files src/api/main.py src/api/auth.py

# Вывод в формате SARIF для CI-интеграции
python -m src.cli review --base-ref HEAD~5 --format sarif --output-file report.sarif

# JSON-вывод с отдельным SARIF-файлом
python -m src.cli review --base-ref HEAD~3 --format json --sarif-file findings.sarif

# Пропуск анализа безопасности
python -m src.cli review --base-ref HEAD~3 --no-security

# Указание базы данных
python -m src.cli review --db data/projects/postgres.duckdb --base-ref origin/main

Программное использование

import duckdb
from src.patch_review import ReviewWorkflow

# Подключение к базе данных CPG
from src.project_manager import ProjectManager
conn = duckdb.connect(ProjectManager.get_active_db_path())

# Настройка параметров DoD
dod_config = {
    'auto_generate': True,
    'interactive': False,
    'extraction': {
        'sources': ['pr_body', 'jira', 'commit_message'],
        'formats': ['checklist', 'yaml', 'markdown'],
    },
}

# Создание рабочего процесса
workflow = ReviewWorkflow(conn, dod_config=dod_config)

# Запуск проверки
verdict = workflow.run(
    patch_source='git_diff',
    patch_data={'diff': diff_content},
    pr_body=pr_description,
    task_description=task_desc,
    interactive_mode=False,
)

# Доступ к результатам
print(f"Оценка: {verdict.overall_score}/100")
print(f"Рекомендация: {verdict.recommendation.value}")

# Результаты проверки DoD
if verdict.dod_validation:
    print(f"Соответствие DoD: {verdict.dod_validation.compliance_score}%")

Архитектура

Трёхуровневая архитектура

Система проверки кода организована в три уровня, каждый из которых предназначен для различных сценариев:

┌─────────────────────────────────────────────────────────┐
│ Уровень 1: CLI Review Pipeline (src/review/)            │
│   ReviewPipeline → ReviewAggregator → ReviewReport      │
│   Точка входа: python -m src.cli review                 │
│   Фокус: CPG-качество + безопасность, SARIF, scope      │
├─────────────────────────────────────────────────────────┤
│ Уровень 2: Patch Review Workflow (src/patch_review/)     │
│   ReviewWorkflow (LangGraph) → Analyzers → Verdicts     │
│   Точка входа: ReviewWorkflow.run() / REST API / демо   │
│   Фокус: DoD, дельта CPG, интеграция с PR/MR            │
├─────────────────────────────────────────────────────────┤
│ Уровень 3: Workflow Scenario 9 (src/workflow/scenarios/) │
│   PRAnalyzer → ContextAggregator → ReviewReporter       │
│   Точка входа: MultiScenarioCopilot (code_review)       │
│   Фокус: LLM-проверка, оптимизация обработчиками        │
└─────────────────────────────────────────────────────────┘

Review Pipeline (Уровень 1)

CLI-ориентированный конвейер в src/review/pipeline.py. Выполняет CPG-запросы качества (мёртвый код, сложность, большие методы) и анализ безопасности. Выводит ReviewReport с поддержкой SARIF.

Patch Review Workflow (Уровень 2)

LangGraph-рабочий процесс в src/patch_review/. Парсит патчи из нескольких источников, генерирует дельта-CPG, запускает 4 анализатора воздействия, формирует 4 вердикта и проверяет DoD. Используется REST API и программным доступом.

Workflow Scenario 9 (Уровень 3)

LLM-усиленная проверка через src/workflow/scenarios/code_review.py. Трёхагентная архитектура с оптимизацией на основе обработчиков. Вызывается через MultiScenarioCopilot.

CLI-команда

Точка входа: src/cli/review_command.pyadd_review_commands()

python -m src.cli review [OPTIONS]

Аргументы

Аргумент Тип По умолчанию Описание
--db PATH автоопределение Путь к базе данных DuckDB CPG
--base-ref REF Базовый коммит для diff-проверки (например, HEAD~3, origin/main)
--staged флаг false Проверять только проиндексированные изменения
--files PATH… Проверять конкретные файлы (один или более)
--no-security флаг false Пропустить анализ безопасности
--format выбор markdown Формат вывода: markdown, json, sarif
--output-file PATH stdout Записать вывод в файл
--sarif-file PATH Записать SARIF-вывод в отдельный файл

Коды возврата

Код Значение
0 Критические и серьёзные проблемы не обнаружены
1 Обнаружены критические или серьёзные проблемы (или ошибка)

Review Pipeline

ReviewPipeline (src/review/pipeline.py) управляет полным конвейером CLI-проверки.

Шаги конвейера

pipeline = ReviewPipeline(
    db_path: Optional[str] = None,
    base_ref: Optional[str] = None,
    files: Optional[List[str]] = None,
    staged: bool = False,
    include_security: bool = True,
)
report = pipeline.run()  # -> ReviewReport

8 шагов конвейера:

  1. Resolve DB path — используется переданный db_path или ProjectManager.get_active_db_path()
  2. Check CPG status — сравнение cpg_git_state.commit_hash с git rev-list HEAD
  3. Load parse scope — чтение таблицы cpg_parse_scope для определения границ анализа
  4. Determine changed files — через git diff --name-only, фильтрация по расширениям
  5. Run quality analysisReviewAggregator.quality_findings_from_cpg(): мёртвый код (fan_in=0), высокая сложность (CC≥15), большие методы (LOC≥100)
  6. Run security analysisSecurityPRReview (если включён и указан base_ref)
  7. Aggregate and filter — фильтрация с учётом области видимости: подавление, понижение, пропуск
  8. Build reportReviewReport с находками, статусом CPG, метаданными, временем выполнения

ReviewReport

src/review/models.py — агрегированный отчёт проверки.

@dataclass
class ReviewReport:
    findings: List[ReviewFinding]          # Все отфильтрованные находки
    cpg_status: Optional[CPGStatus]        # Информация о свежести CPG
    parse_scope: Optional[ParseScope]      # Границы области анализа
    project_name: str                      # Название проекта
    base_ref: str                          # Базовый коммит
    duration_ms: float                     # Время выполнения конвейера
    suppressed_count: int                  # Подавленные находки (по scope)
    metadata: Dict[str, Any]              # Дополнительные данные

Методы: - severity_counts() -> Dict[str, int] — подсчёт находок по серьёзности - to_markdown() -> str — форматированный markdown-отчёт - to_dict() -> Dict[str, Any] — словарь для JSON-сериализации - to_sarif() -> Dict[str, Any] — вывод в формате SARIF 2.1.0

ReviewFinding

src/review/models.py — одна находка из анализа качества или безопасности.

@dataclass
class ReviewFinding:
    file: str                              # Путь к файлу
    line: Optional[int]                    # Номер строки
    type: str                              # Тип (dead_code, high_complexity и т.д.)
    severity: str                          # critical|high|medium|low|info
    message: str                           # Описание
    suggestion: Optional[str]              # Рекомендация по исправлению
    metric_value: Optional[float]          # Числовая метрика (CC, LOC, fan_in)
    scope_limited: bool                    # True при частичной области видимости
    source: str                            # "quality" или "security"

CPGStatus

src/review/models.py — статус свежести базы данных CPG.

@dataclass
class CPGStatus:
    available: bool         # True если БД существует и доступна
    fresh: bool             # True если commits_behind == 0
    commits_behind: int     # Количество коммитов после последнего обновления CPG
    commit_hash: str        # Записанный хеш коммита CPG
    db_path: str            # Путь к файлу базы данных

ParseScope

src/review/models.py — описывает границы CPG-анализа.

@dataclass
class ParseScope:
    source_path: str                       # Корневая директория исходного кода
    language: str                          # Основной язык
    include_tests: bool                    # Включены ли тесты в CPG
    include_paths: List[str]               # Пути для выборочного включения
    exclude_paths: List[str]               # Явные исключения
    default_excludes: List[str]            # Шаблоны исключений по умолчанию
    import_mode: str                       # "full" или "selective"

Свойства: - tests_in_scope: bool — включены ли тесты в CPG - is_partial: bool — есть ли исключения или выборочный режим - all_excludes: List[str] — объединённые явные + стандартные исключения - path_in_scope(path) -> bool — проверка, попадает ли файл в область анализа - scope_disclaimer() -> str — markdown-предупреждение для отчётов

SARIF-вывод

Review Pipeline поддерживает SARIF 2.1.0 (Static Analysis Results Interchange Format) для интеграции с CI/CD.

# Прямой SARIF-вывод
python -m src.cli review --base-ref HEAD~5 --format sarif --output-file report.sarif

# Markdown-вывод + отдельный SARIF-файл
python -m src.cli review --base-ref HEAD~5 --format markdown --sarif-file findings.sarif

ReviewReport.to_sarif() генерирует:

{
  "$schema": "https://json.schemastore.org/sarif-2.1.0.json",
  "version": "2.1.0",
  "runs": [{
    "tool": {
      "driver": {
        "name": "CodeGraph Review",
        "version": "1.0.0",
        "rules": [
          {"id": "dead_code", "shortDescription": {"text": "Dead Code"}},
          {"id": "high_complexity", "shortDescription": {"text": "High Complexity"}}
        ]
      }
    },
    "results": [
      {
        "ruleId": "high_complexity",
        "level": "warning",
        "message": {"text": "`MyClass.process` has cyclomatic complexity 25"},
        "locations": [{
          "physicalLocation": {
            "artifactLocation": {"uri": "src/service.py"},
            "region": {"startLine": 42}
          }
        }]
      }
    ]
  }]
}

Сопоставление серьёзности: critical/high → error, medium → warning, low/info → note.

Фильтрация с учётом области видимости

ReviewAggregator (src/review/aggregator.py) применяет фильтрацию на основе ParseScope:

Правило Условие Действие
Подавление missing_test tests_in_scope == false Находка удаляется
Понижение dead_code is_partial == true Серьёзность → info, scope_limited = true
Понижение blast_radius is_partial == true Серьёзность → info, scope_limited = true

Конфигурация (в config.yamlreview_pipeline):

review_pipeline:
  scope_aware_filtering: true
  suppress_tests_outside_scope: true
  demote_dead_code_partial_scope: true

При ограниченной области видимости markdown-отчёт содержит предупреждение:

> **Ограниченная область анализа**
>
> CPG построен с исключениями: `vendor/`, `generated/`
>
> Это означает:
> - Находки мёртвого кода могут быть ложноположительными
> - Радиус поражения занижен

Patch Review Workflow

ReviewWorkflow (src/patch_review/workflow/review_workflow.py) — LangGraph-рабочий процесс для глубокого анализа патчей с поддержкой DoD.

Конвейер рабочего процесса

parse_patch → extract_dod → [generate_dod] → [confirm_dod] → generate_delta_cpg
    ↓
run_analyzers → generate_verdicts → aggregate_verdict → validate_dod → format_output

Примечания: - [generate_dod] выполняется только если DoD не найден и auto_generate: true - [confirm_dod] выполняется только в интерактивном режиме (--interactive)

Узлы LangGraph (11): 1. parse_patch — PatchParser (git_diff, github_pr, gitlab_mr) 2. extract_dod — DoDExtractor (многоисточниковый) 3. generate_dod — DoDGenerator (на основе LLM) 4. confirm_dod — DoDConfirmer (интерактивный CLI) 5. generate_delta — DeltaCPGGenerator 6. run_analyzers — PatchCallGraphAnalyzer, PatchDataFlowAnalyzer, PatchControlFlowAnalyzer, PatchDependencyAnalyzer 7. generate_verdicts — SecurityVerdictGenerator, PerformanceVerdictGenerator, ErrorVerdictGenerator, ArchitectureVerdictGenerator 8. validate_dod — DoDValidator 9. aggregate_verdict — VerdictAggregator 10. format_output — JSONFormatter, MarkdownFormatter, PRCommentFormatter 11. handle_error — обработка ошибок

Компоненты

Компонент Описание
PatchParser Парсит git diff, GitHub PR, GitLab MR в PatchContext
DoDExtractor Извлекает DoD из тела PR, Jira, сообщения коммита
DoDGenerator Генерирует DoD с помощью LLM, если не найден
DoDConfirmer Интерактивное подтверждение DoD (просмотр, редактирование, пропуск)
DeltaCPGGenerator Создаёт дельта-CPG для изменений
PatchCallGraphAnalyzer Анализ воздействия на граф вызовов
PatchDataFlowAnalyzer Анализ потоков данных / путей распространения
PatchControlFlowAnalyzer Анализ потока управления / сложности
PatchDependencyAnalyzer Анализ зависимостей / связности
SecurityVerdictGenerator Вердикт безопасности по потокам данных
PerformanceVerdictGenerator Вердикт производительности по потоку управления + графу вызовов
ErrorVerdictGenerator Вердикт ошибок по потоку управления
ArchitectureVerdictGenerator Вердикт архитектуры по графу вызовов + зависимостям
DoDValidator Проверяет DoD по результатам анализа
VerdictAggregator Объединяет вердикты в итоговый ReviewVerdict

Определение готовности (DoD)

Источники DoD

Система извлекает DoD из нескольких источников (с настраиваемым приоритетом):

  1. Описание PR — Markdown-чек-лист в описании PR/MR
  2. Jira — пользовательское поле или описание из привязанного обращения
  3. Сообщение коммита — раздел DoD в первом коммите
  4. Ручной ввод — ввод через CLI или API
  5. Автогенерация — LLM генерирует на основе описания задачи

Форматы DoD

Поддерживаемые форматы извлечения DoD:

Markdown-чек-лист

## Definition of Done

- [ ] Функциональность работает, как ожидается
- [ ] Не внесено уязвимостей безопасности
- [ ] Добавлены модульные тесты
- [ ] Обновлена документация

Блок YAML

dod:
  - description: Функциональность работает, как ожидается
    type: functional
  - description: Модульные тесты проходят
    type: test

Блок JSON

{
  "dod": [
    {"description": "Функциональность работает", "type": "functional"},
    {"description": "Тесты проходят", "type": "test"}
  ]
}

Типы критериев

Тип Описание Проверка
functional Требования к функциональности Ручная проверка
security Отсутствие уязвимостей Оценка безопасности
test Наличие и прохождение тестов Рекомендации по ошибкам
documentation Обновление документации Ручная проверка
performance Отсутствие регрессии производительности Оценка производительности
code_quality Соответствие стилю кода Оценка архитектуры

Интерактивное подтверждение DoD

При запуске с флагом --interactive пользователь может просмотреть и изменить DoD перед началом проверки:

============================================================
ОПРЕДЕЛЕНИЕ ЗАВЕРШЁННОСТИ — ПОДТВЕРЖДЕНИЕ
============================================================

Текущее DoD (из pr_body):
----------------------------------------
  1. [FUNC] Функциональность работает, как ожидается
  2. [SECU] Не внесено уязвимостей безопасности
  3. [TEST] Добавлены модульные тесты для новой функциональности
  4. [PERF] Отсутствие регрессии производительности
  5. [CODE] Код соответствует стилю проекта
----------------------------------------
Всего: 5 пунктов

Опции:
  [c] Подтвердить и продолжить
  [e] Редактировать пункты
  [a] Добавить новый пункт
  [r] Удалить пункт
  [s] Пропустить проверку DoD
  [q] Отменить проверку

Опции: - Подтвердить (c) — принять текущее DoD и продолжить проверку - Редактировать (e) — изменить описания и типы пунктов - Добавить (a) — добавить новые пункты DoD с выбором типа - Удалить (r) — удалить пункты из списка - Пропустить (s) — пропустить проверку DoD полностью - Отмена (q) — отменить процесс проверки

Горячие клавиши для добавления/редактирования:

Клавиша Тип
f Функциональный
s Безопасность
t Тестирование
d Документация
p Производительность
q Качество кода

Проверка DoD

Каждый пункт DoD проверяется на соответствие результатам анализа:

  • Безопасность: по результатам вердикта безопасности (критические/серьёзные = провал)
  • Тесты: по количеству рекомендаций по тестам
  • Производительность: по оценке производительности
  • Качество кода: по оценке архитектуры
  • Функциональность/Документация: не могут быть проверены автоматически

REST API

src/api/routers/review.py предоставляет 7 эндпоинтов с префиксом /review.

Эндпоинты проверки

POST /review/patch

Проверка git diff/патча.

# Запрос: PatchReviewRequest
{
    "patch_content": "diff --git a/...",       # обязательное
    "task_description": "Добавить авторизацию", # опциональное
    "dod_items": ["Тесты проходят"],            # опциональное
    "output_format": "json"                     # json|markdown|yaml
}
# Заголовок: Authorization (JWT)

POST /review/pr

Проверка GitHub Pull Request.

# Запрос: GitHubPRReviewRequest
{
    "owner": "myorg",
    "repo": "myrepo",
    "pr_number": 123
}
# Заголовок: X-GitHub-Token (обязательный)

POST /review/mr

Проверка GitLab Merge Request.

# Запрос: GitLabMRReviewRequest
{
    "project_id": "group/project",
    "mr_iid": 456,
    "gitlab_url": "https://gitlab.com"
}
# Заголовок: X-GitLab-Token (обязательный)

POST /review/sourcecraft

Проверка SourceCraft Merge Request (Yandex Cloud).

# Запрос: SourceCraftMRReviewRequest
{
    "project_id": "project-id",
    "mr_iid": 789,
    "sourcecraft_url": "https://api.sourcecraft.yandex.cloud"
}
# Заголовок: X-SourceCraft-Token (обязательный)

POST /review/gitverse

Проверка GitVerse Pull Request (Sber).

# Запрос: GitVersePRReviewRequest
{
    "project_id": "owner/repo",
    "pr_number": 101,
    "gitverse_url": "https://gitverse.ru/api/v1"
}
# Заголовок: X-GitVerse-Token (обязательный)

Вспомогательные эндпоинты

POST /review/summary

Генерация структурированного резюме MR из diff.

# Запрос: SummaryRequest
{"diff_content": "...", "title": "...", "description": "..."}

# Ответ: SummaryResponse
{
    "summary": "Этот MR добавляет авторизацию...",
    "changed_files": ["src/auth.py"],
    "additions": 45,
    "deletions": 12,
    "changed_methods": ["authenticate", "reset_password"],
    "risk_areas": ["SQL-инъекция в auth.py"]
}

POST /review/commit-message

Генерация сообщения коммита из diff.

# Запрос: CommitMessageRequest
{"diff_content": "..."}

# Ответ: CommitMessageResponse
{"message": "feat(auth): add password reset flow", "type": "feat", "scope": "auth", "files_changed": 3}

Модель ответа

Все эндпоинты проверки возвращают ReviewResponse:

class ReviewResponse:
    recommendation: str      # APPROVE | REQUEST_CHANGES | COMMENT | BLOCK
    score: float             # 0-100
    findings: List[Finding]
    dod_validation: Optional[List[DODItem]]
    summary: str
    processing_time_ms: float
    request_id: str
    metadata: Dict[str, Any]

Workflow Scenario 9

src/workflow/scenarios/code_review.py — LLM-усиленная проверка кода через MultiScenarioCopilot.

Трёхагентная архитектура

Агент 1: PRAnalyzer — парсинг PR/diff

  • parse_pr_diff(diff_text, pr_metadata) -> Dict — парсинг unified diff
  • extract_changed_methods(pr_data) -> List[ChangedMethod] — извлечение методов
  • identify_affected_subsystems(changed_files) -> List[str] — определение подсистем

Агент 2: ContextAggregator — сбор CPG-контекста

  • Конструктор: ContextAggregator(cpg_service: CPGQueryService)
  • gather_method_context(method_id) -> MethodContext — вызывающие, вызываемые, сложность, тесты
  • find_impacted_methods(changed_methods) -> List[Dict] — радиус поражения
  • check_test_coverage(changed_methods) -> Dict — отчёт о тестовом покрытии

Агент 3: ReviewReporter — формирование отчёта

  • analyze_changes(pr_data, method_contexts, test_coverage) -> List[ReviewFinding]
  • calculate_review_score(findings) -> float — оценка 0-100
  • recommend_action(score, findings) -> ReviewAction — APPROVE | REQUEST_CHANGES | COMMENT
  • generate_review_report(pr_data, findings, method_contexts) -> ReviewReport

Обработчики Code Review

src/workflow/scenarios/code_review_handlers/ — оптимизация на основе обработчиков (Фаза 2), загружается динамически через integrate_handlers().

Обработчик Приоритет Описание
CallerAnalysisHandler 3 Анализ вызывающих методов
SignatureImpactHandler 5 Анализ влияния изменений сигнатуры
PRImpactHandler 10 Общий анализ воздействия PR
ChangeRiskHandler 20 Оценка рисков (степень риска, приоритет проверки)

Детектор намерений

CodeReviewIntentDetector сопоставляет запросы с типами обработчиков:

Тип намерения Приоритет Ключевые слова
pr_impact 10 PR impact, pull request, affected, blast radius
change_risk 20 risk, risky, dangerous, critical change
review_priority 30 review priority, what to review, focus review
dependency_impact 40 dependency, caller, callee, transitive

Конфигурация

config/code_review.yaml

# Конфигурация определения готовности (Definition of Done)
dod:
  sources:
    - pr_body
    - jira
    - commit_message
    - manual
  source_priority:
    - pr_body
    - jira
    - commit_message
  formats:
    - checklist
    - yaml
    - markdown
    - json
  auto_generate: true
  interactive_confirm: false

  # Интеграция с Jira
  jira:
    url: ${JIRA_URL}
    api_key: ${JIRA_API_KEY}
    dod_field: "customfield_10001"

  # Настройки генерации DoD (при auto_generate=true)
  generation:
    use_llm: true
    fallback_to_rules: true
    include_security: true
    include_performance: true
    require_tests: true

  # Настройки валидации
  validation:
    strict_mode: false
    blocking_severities:
      - critical
      - high

# Политика проверки
policy:
  block_on_critical_security: true
  block_on_high_security: false
  block_on_critical_errors: true
  block_on_breaking_changes: false
  min_score_to_approve: 70.0
  min_score_to_comment: 60.0
  max_critical_findings: 0
  max_high_findings: 5
  max_complexity_increase: 20
  require_dod_compliance: false
  min_dod_compliance_score: 60.0
  custom_rules: []

# Конфигурация анализаторов
analyzers:
  call_graph:
    enabled: true
    max_depth: 5
    include_indirect: true
  dataflow:
    enabled: true
    max_path_length: 10
    sanitization_threshold: 0.7
  control_flow:
    enabled: true
    complexity_threshold: 10
    max_nesting_depth: 5
  dependency:
    enabled: true
    check_circular: true
    max_coupling_increase: 0.2

# Веса вердиктов
verdicts:
  weights:
    security: 0.35
    performance: 0.20
    error: 0.25
    architecture: 0.20
  dod_compliance_weight: 0.10
  thresholds:
    block: 40
    request_changes: 60
    comment: 80
    approve: 80

# Конфигурация вывода
output:
  formats:
    - json
    - markdown
    - pr_comment
  include_dod: true
  include_findings: true
  include_snippets: true
  max_findings_per_category: 10
  pr_comment:
    max_length: 10000
    use_emoji: true
    collapsible_sections: true

Переменные окружения

Переменная Описание
JIRA_URL URL-адрес сервера Jira для извлечения DoD
JIRA_API_KEY Ключ аутентификации для API Jira
GITHUB_TOKEN Токен API GitHub для доступа к PR
GITLAB_TOKEN Токен API GitLab для доступа к MR

Справочник API

ReviewWorkflow

workflow = ReviewWorkflow(
    conn: duckdb.DuckDBPyConnection,
    config: Optional[AggregationConfig] = None,
    policy: Optional[ReviewPolicy] = None,
    dod_config: Optional[Dict[str, Any]] = None,
)

verdict = workflow.run(
    patch_source: str,          # 'git_diff', 'github_pr', 'gitlab_mr'
    patch_data: Dict[str, Any],
    session_id: Optional[str] = None,
    policy: Optional[ReviewPolicy] = None,
    task_description: Optional[str] = None,
    pr_body: Optional[str] = None,
    jira_ticket: Optional[str] = None,
    interactive_mode: bool = False,
)

ReviewVerdict

src/patch_review/models.py — итоговый агрегированный вердикт проверки.

@dataclass
class ReviewVerdict:
    # Основные
    patch_id: str
    overall_score: float                      # 0-100
    recommendation: Recommendation            # APPROVE, REQUEST_CHANGES, BLOCK, COMMENT
    security: SecurityVerdict
    performance: PerformanceVerdict
    error: ErrorVerdict
    architecture: ArchitectureVerdict

    # Агрегированные находки
    all_findings: List[Finding]
    critical_count: int
    high_count: int
    medium_count: int
    low_count: int

    # Метрики воздействия
    blast_radius_score: float                 # 0-100, выше = меньший радиус
    review_time_seconds: float
    summary: str
    reviewed_at: Optional[datetime]

    # DoD
    dod_validation: Optional[DoDValidationResult]
    dod_compliance_score: float               # 0-100, по умолчанию 100.0

    # Идентификация
    review_id: str                            # автогенерация REVIEW_xxxx
    session_id: str

DoDValidationResult

@dataclass
class DoDValidationResult:
    dod: DefinitionOfDone
    total_items: int
    satisfied_count: int
    failed_count: int
    pending_count: int
    compliance_score: float                   # 0-100
    blocking_failures: List[DoDItem]

    @property
    def is_compliant(self) -> bool:
        """Вычисляемое свойство: True если failed_count == 0 и pending_count == 0."""
        ...

Примечание: is_compliant — это @property, а не поле dataclass. Вычисляется из failed_count и pending_count.

ReviewPolicy

src/patch_review/models.py — настраиваемая политика проверки.

@dataclass
class ReviewPolicy:
    block_on_critical_security: bool = True
    block_on_high_security: bool = False
    block_on_critical_errors: bool = True
    block_on_breaking_changes: bool = False
    min_score_to_approve: float = 70.0
    min_score_to_comment: float = 60.0
    max_critical_findings: int = 0
    max_high_findings: int = 5
    max_complexity_increase: int = 20
    custom_rules: List[PolicyRule] = field(default_factory=list)

Поля PolicyRule: rule_id, name, condition, action ("block", "warn", "comment"), message.

Форматы вывода

Вывод в формате JSON

{
  "patch_id": "PATCH_abc123",
  "overall_score": 45.5,
  "recommendation": "REQUEST_CHANGES",
  "dod_compliance_score": 60.0,
  "findings": [...],
  "dod_validation": {
    "compliance_score": 60.0,
    "items": [
      {"description": "...", "satisfied": true, "evidence": "..."},
      {"description": "...", "satisfied": false, "evidence": "..."}
    ]
  }
}

Вывод в формате Markdown

## Резюме проверки изменений

**Общий балл:** 45/100
**Рекомендация:** REQUEST_CHANGES

### Критерии завершённости (Definition of Done)

**Уровень соответствия:** 60%

- [+] Функция работает, как ожидается
- [-] Не внесены уязвимости безопасности
  - Доказательство: Обнаружены проблемы: SQL-инъекция
- [?] Добавлены модульные тесты (ожидает ручной проверки)

### Результаты анализа безопасности

1. [HIGH] Уязвимость к SQL-инъекции
   - Расположение: src/auth/login.py:14
   - CWE-89

Устранение неполадок

«DoD не найден»

Если DoD не извлекается:

  1. Убедитесь, что тело PR содержит раздел DoD с правильным форматом
  2. Проверьте, что dod.sources включает ваш тип источника
  3. Убедитесь, что dod.formats включает ваш формат DoD
  4. Включите auto_generate: true, чтобы создавать DoD при его отсутствии

«Проверка DoD пропущена»

Для проверки DoD необходимо: - Успешное извлечение или создание DoD - Сформированный результат проверки - Отсутствие ошибок в рабочем процессе

«Извлечение данных из Jira не удалось»

  1. Убедитесь, что заданы переменные окружения JIRA_URL и JIRA_API_KEY
  2. Проверьте права доступа к Jira API
  3. Убедитесь, что параметр dod_field указывает на правильное пользовательское поле

«CPG отстаёт от HEAD на N коммитов»

База данных CPG устарела. Обновите:

gocpg parse --input=/path/to/source --output=project.duckdb

Примеры

Демо-скрипт

Демонстрационный скрипт доступен в examples/demo_patch_review.py:

python examples/demo_patch_review.py --db data/projects/postgres.duckdb
python examples/demo_patch_review.py --no-dod
python examples/demo_patch_review.py --auto-dod
python examples/demo_patch_review.py --interactive

Интеграция с GitHub PR

pr_data = {
    'number': 123,
    'title': 'Добавить аутентификацию',
    'body': pr_body_with_dod,
    'diff_url': 'https://api.github.com/repos/...',
}

verdict = workflow.run(
    patch_source='github_pr',
    patch_data=pr_data,
    pr_body=pr_data['body'],
)

Интеграция с GitLab MR

mr_data = {
    'iid': 456,
    'title': 'Добавить аутентификацию',
    'description': mr_description_with_dod,
}

verdict = workflow.run(
    patch_source='gitlab_mr',
    patch_data=mr_data,
    pr_body=mr_data['description'],
)

Ручное создание списка DoD

from src.patch_review.dod import DoDExtractor

extractor = DoDExtractor()
dod = extractor.create_manual_dod(
    items=[
        "Функция работает как ожидается",
        "Отсутствуют уязвимости безопасности",
        "Добавлены модульные тесты",
    ],
    types=["functional", "security", "test"],
)