dd-code-review · git:20261016.295b5a0 · 2026-10-16 · sha256 4d51669363ad8f68
dd-code-review git:20261016.295b5a0A
Immutable. This exact content never changes and is served at /api/v1/blob/4d51669363ad8f68.
--- name: dd-code-review description: Ревью локальных изменений, открытого PR/MR или diff ветки на баги, проблемы безопасности и нарушения гайдлайнов проекта и актуальных спецификаций (docs/specs/) — через набор ревью-линз инлайн (маленький diff) или параллельными агентами (большой diff). Стиль и то, что ловит линтер, — вне скоупа. Read-only: правки и комментарии в PR/MR только по явному одобрению пользователя. trigger_phrases: - "code review" - "код ревью" - "ревью изменений" - "ревью PR" - "проверь diff" - "проверь изменения" - "review PR" - "dd code review" related_skills: - dd-discovery - dd-delivery - git-commit --- # dd-code-review Анализ локальных git-изменений (или PR/MR) на соответствие гайдлайнам проекта и актуальным спецификациям через ревью-линзы из [Шага 4](#шаг-4-ревью-по-линзам) — инлайн на маленьком diff, параллельными агентами на большом. Вне скоупа: стиль, субъективные предпочтения и всё, что уже ловит линтер. Скилл — часть пакета DD-SDD: опирается на те же источники, что и треки. `docs/specs/` здесь первичный источник — тот, что читает `dd-discovery` перед постановкой задачи и обновляет `dd-delivery` по факту реализации: в спеках зафиксированы актуальное поведение системы и проектные нюансы логики и конвенций. Изменение, отходящее от спеки без её обновления, — находка ревью. Адаптировано из [optimus-claude/skills/code-review](https://github.com/oprogramadorreal/optimus-claude/tree/master/skills/code-review). Промпты агентов и общие ограничения — в `references/` рядом с этим файлом. Аргументы: `[--pr N | --branch | путь]` — всё остальное трактуется как естественно-языковой скоуп/фокус (пути, номера PR, рефы: «ревью src/auth», «ревью PR #42», «изменения против main»). ## Шаг 1: Разбор аргументов и пререквизиты - `--branch` → принудительно diff ветки в Шаге 2, без авто-маршрутизации на PR. Не действует, если есть локальные изменения или PR запрошен явно (`--pr N`, `#N`, URL PR). - **Multi-repo / вне git**: если `git rev-parse --is-inside-work-tree` не вернул `true`, проверь, не workspace ли это с несколькими репозиториями (например, мета-репозиторий с подпроектами в подкаталогах). Тогда git-команды Шага 2 выполняются внутри каждого дочернего репо, а для PR/MR-режима пользователь обязан назвать репозиторий. Корень репо — `git rev-parse --show-toplevel` (работает и в worktree, и в подкаталоге). - **Пререквизиты**: если в проекте нет `AGENTS.md`/`CLAUDE.md`, гайдлайнов (`docs/coding-guidelines.md`) или спецификаций (`docs/specs/`), предложи сначала сформировать их — в DD-SDD спеки заводятся треками `dd-discovery`/`dd-delivery`. Если пользователь решает продолжить — ревьюй против общих best practices для обнаруженного стека и отметь в отчёте, что находки общие, а не проектно-специфичные. ## Шаг 2: Определение скоупа ревью **Локальные изменения (по умолчанию)**: собери staged + unstaged + untracked через `git diff --cached`, `git diff` и `git status --short`. Если есть — ревьюим их. **Локальных изменений нет → авто-маршрутизация** (без вопросов пользователю): 1. Определи платформу по `git remote get-url origin`: содержит `github.com` → GitHub (`gh`); `gitlab` → GitLab (`glab`). Неизвестно — попробуй оба CLI, бери первый подтверждённый открытый PR/MR. 2. Проверь открытый PR/MR текущей ветки: GitHub — `gh pr view --json number,state,baseRefName` (учитывать только `state` = `"OPEN"`); GitLab — `glab mr view --output json` (только `state` = `"opened"`; падение команды = нет MR, если только это не похоже на ошибку авторизации/сети — тогда скажи пользователю до фолбэка). 3. База = target-ветка PR/MR; если PR/MR или CLI нет — определи default-ветку: `git symbolic-ref --quiet refs/remotes/origin/HEAD` (обрезать `refs/remotes/origin/`), фолбэк — `git rev-parse --verify origin/main`, затем `origin/master`. Не удалось — спроси у пользователя базовый реф, **никогда не угадывай**; если рефа нет — ревьюить нечего. 4. Выполни `git log --oneline origin/<base>..HEAD`; если коммиты есть, маршрутизируй: - `--branch` → diff ветки. - Открытый PR/MR найден И HEAD полностью запушен (`git rev-list origin/<current-branch>..HEAD` пуст) → PR-режим без переспрашивания. Одной строкой: *«Ревьюю PR #N — описание PR использую как контекст намерения автора. Передай `--branch`, чтобы ревьюить diff ветки.»* - PR/MR найден, НО HEAD не запушен полностью или статус пуша не определить → diff ветки. Одной строкой: *«Ревьюю diff ветки — PR #N существует, но HEAD запушен не полностью. Передай `--pr N`, чтобы ревьюить только запушенное состояние PR.»* - PR/MR нет (или CLI недоступен) → diff ветки. **Совсем ничего нет** → сообщи, что ревьюить нечего; предложи застейджить изменения или указать PR. ### PR-режим Вход по явному запросу или авто-маршрутом. | | GitHub | GitLab | |---|---|---| | Метаданные | `gh pr view <N> --json state,isDraft,title,body,baseRefName,headRefName,headRefOid` | `glab mr view <N> --output json` | | Поля `pr-description` | `title` + `body` | `title` + `description` | | Diff | `gh pr diff <N>` | `glab mr diff <N>` | | Head SHA | `headRefOid` | `sha` | | Checkout | `gh pr checkout <N>` | `glab mr checkout <N>` | - Сначала проверь CLI (`gh --version` / `glab --version`); недоступен → скажи, что для PR/MR-режима он нужен, и предложи diff ветки. - Сохрани title + body как `pr-description` для Шагов 4–5 (контекст намерения автора). - PR/MR закрыт или влит → предупреди и остановись. - **Расхождение head**: если head SHA отличается от `git rev-parse HEAD`, предложи checkout до продолжения — агенты Шага 4 и валидация Шага 5 читают локальное дерево, и при расхождении молча ревьюится не тот контент. При отказе — продолжай с предупреждением, что валидация идёт по локальному дереву, а не по head PR. **Режим ветки/рефа**: diff — `git diff <ref>...HEAD`; список файлов — `git diff --name-only <ref>...HEAD`. **Фильтр по пути**: при скоупе на путь фильтруй diff (`git diff -- <path>`, `git diff --cached -- <path>`). ### Сводка скоупа Перед продолжением покажи короткую `## Review Scope`: режим (локальные изменения / PR #N / diff ветки с `<ref>`), файлов изменено, строк +/-. В PR/MR-режиме, если `pr-description` пусто или в нём нет заполненной секции `## Intent` (Problem / Scope / Non-goals / Key decisions), добавь одну заметку, какой из случаев: проверки intent-vs-implementation пропускаются. Мягкое предупреждение — ревью продолжается в любом случае. **Предупреждение о большом diff**: больше 50 файлов или 3000 строк — предупреди и предложи сузить скоуп (путь, каталог). ## Шаг 3: Загрузка контекста проекта Загрузи документы-ограничения проекта — они определяют критерии ревью: - `docs/specs/*` — актуальные спецификации: зафиксированное поведение системы и проектные нюансы логики и конвенций. Первичный источник для проверки: изменение, противоречащее спеке, — находка, если только спека не обновляется в том же diff (это нормальный выход `dd-delivery`); - `AGENTS.md` / `CLAUDE.md` (карта кодбазы, правила); - `docs/coding-guidelines.md`, `docs/architecture.md`, `docs/testing.md` — что есть; - в монорепо/workspace — для каждого затронутого подпроекта свои документы, применяются к файлам только этого подпроекта; - исключи vendored/submodule-каталоги (`vendor/`, `node_modules/`, сабмодули) — их код не ревьюим. Каждая находка по гайдлайнам должна обосновываться тем, что установлено этими документами; внешние предпочтения не навязывать. Покажи короткую сводку контекста (какие доки загружены, каких нет и какой фолбэк, тип проекта) и сразу переходи к Шагу 4 — без ожидания подтверждения. ## Шаг 4: Ревью по линзам Таблица ниже — линзы, которые ревью обязано покрыть. В скольких контекстах их покрывать — решаешь по размеру diff. **На маленьком diff — примерно до 3 файлов и 150 изменённых строк — применяй линзы сам за один проход.** Пять сабагентов над пятистрочным изменением перечитают одни и те же доки и diff, чтобы выдать то, до чего ты дойдёшь напрямую; прочитай файлы промптов ради критериев и пройдись по ним. Разветвляйся, когда diff велик настолько, что один контекст не вмещает его вместе с доками, когда линзам нужны genuinely разные части дерева. При разветвлении запускай всех применимых агентов **одним сообщением** параллельно — разные сообщения сериализуют их без выгоды. Каждый агент покрывает линзу, которой нет у других; выкинуть агента = оставить категорию без ревью. Дождись завершения всех запущенных агентов до Шага 5. | Агент | Роль | Файл промпта | |-------|------|--------------| | 1 — Bug Detector | Null-доступ, off-by-one, гонки, утечки ресурсов, несовпадение типов | `references/bug-detector.md` | | 2 — Security & Logic | Инъекции, XSS, секреты, отсутствующая авторизация, security-релевантные нарушения API | `references/security-reviewer.md` | | 3 — Guideline Compliance | Явные нарушения документов проекта, каждое со ссылкой на правило | `references/guideline-reviewer.md` | | 4 — Architecture & Boundaries | Слоистость и направление зависимостей, ответственность модулей, дрейф структурных паттернов, размещение | `references/architecture-reviewer.md` | | 5 — Code Simplifier | Лишняя сложность, мёртвый код, упрощения только удалением | `references/code-simplifier.md` | | 6 — Test Guardian | Пробелы в покрытии тестами, структурные барьеры тестируемости | `references/test-guardian.md` | | 7 — Contracts Reviewer | Обратная совместимость, типобезопасность, версионирование, инкапсуляция | `references/contracts-reviewer.md` | Линзы 1–5 применяются всегда, инлайн или агентами. Линза 6 — когда обнаружена тестовая инфраструктура (`docs/testing.md`, каталог `tests/`, конфиг phpunit/jest/vitest/pest). Линза 7 — когда хоть один изменённый файл матчит контракт-паттерн: каталоги `api/`, `routes/`, `controllers/`, `endpoints/`, `handlers/`, `graphql/`, `proto/`, `grpc/`; файлы `*.dto.*`, `*.schema.*`, `*.contract.*`, `openapi.*`, `swagger.*`, `*.proto`, `*.graphql`, `*.gql`. Нет совпадения — пропускай целиком. **Сборка промпта**: прочитай файл промпта из `references/` + `references/shared-constraints.md` (общая планка качества и формат вывода; он же тянет `references/shared-agent-constraints.md`). Промпт агента = общие ограничения + файл линзы + список изменённых файлов + hunks diff'а. Для агента 3 замени строку `<!-- dispatcher: ... -->` в `guideline-reviewer.md` на конкретные пути документов, разрешённые в Шаге 3. Заверши каждый собранный промпт списком изменённых файлов (из Шага 2), за которым идут hunks diff'а — как минимум диапазоны изменённых строк по файлам, если diff целиком не влезает. У агентов нет санкционированного способа вычислить diff самим; никогда не отправляй одни только пути файлов. ### Инъекция PR/MR-контекста (только PR/MR-режим) Если `pr-description` из Шага 2 непустое, добавь в начало каждого промпта агента, прямо перед списком файлов, блок: ``` ## PR/MR Context Title: <title> Description: <body, обрезать до 2000 символов с пометкой об усечении> Это заявленное намерение автора. Источник правды — код и git-история: при противоречии доверяй коду, а не описанию. ``` ## Шаг 5: Валидация находок Прочитай `references/finding-validation.md` и примени к каждой находке. Дополнения code review: - **Перекрёстная корроборация** — два агента независимо флагают одно место → уверенность растёт, даже если категории разные. - **Санкционированные pre-existing находки** — проверка Pre-existing не отбрасывает security/bug-находки непосредственно рядом с изменёнными строками и consistency-находки по структурным соседям (`references/shared-constraints.md` разрешает оба); остальные проверки применяются. ### Описание PR/MR как сигнал намерения Если захвачено `pr-description`, используй его как дополнительный мягкий сигнал: явное объяснение *почему* сделано флагаемое изменение, подтверждённое git-историей → −1 уверенность; противоречит истории или не подтверждено ею → доверяй истории (код важнее заявлений); молчит о находке → без корректировки. Никогда не фильтруй находку жёстко только по описанию. **Уверенность после валидации**: High и Medium идут в Шаг 6; число отброшенных укажи в сводке отчёта. ## Шаг 6: Консолидация и отчёт - **Дедупликация**: тот же файл + диапазон строк + категория → оставь более детальную версию. Если два агента дошли независимо — слей в одну с пометкой «подтверждено независимым ревью». - **Противоречия**: находки на один регион с противоположными рекомендациями («добавь валидацию» vs «упрости валидацию») → оставь более высокую серьёзность; при ничьей — security/correctness-находку (требования безопасности оправдывают соразмерную сложность). - **Серьёзность**: **Critical** — баги, уязвимости, падения рантайма, Intent Mismatch в противоречии с заявленным non-goal. **Warning** — нарушения гайдлайнов, отсутствующая обработка ошибок, пробелы покрытия на критических путях, обратно-несовместимые изменения контрактов, Intent Mismatch по неподтверждённым scope-заявлениям. **Suggestion** — улучшения качества, мелкий дрейф, Intent Mismatch по частичным совпадениям. - **Лимит находок**: максимум **15 доменных находок**, по серьёзности, затем по уверенности. `Intent Mismatch` — сверх 15, до 5, дедуплицированные между агентами, после доменных. Если проблем больше — укажи число и предложи более узкий скоуп. ### Формат вывода ``` ## Code Review ### Summary - Scope: [локальные изменения / PR #N / diff ветки с X] - Files reviewed: [N] - Lines changed: +[A] / -[R] - Findings: [N] (Critical: [N], Warning: [N], Suggestion: [N]) - Unconfirmed findings dropped: [N] - Docs used: [список] - Agents: [список запущенных] - Verdict: CHANGES LOOK GOOD / ISSUES FOUND ### Change Summary [2–4 фактических предложения о том, что делают изменения] ### Findings **[N]. [Заголовок находки]** (Critical/Warning/Suggestion — [Category]) - **File:** `file:line` - **Category:** [категория по файлу промпта линзы] - **Guideline:** [правило проекта, "General: ...", или для Intent Mismatch литерально "Intent (see Intent claim)"] - **Intent claim:** [только Intent Mismatch — цитата из `## Intent`] - **Issue:** [конкретное описание] - **Current:** [сниппет — макс 5 строк] - **Suggested:** [фикс или рекомендация — макс 5 строк] [Порядок: Critical → Warning → Suggestion, внутри — по пути файла. Если находок нет: «Изменения соответствуют гайдлайнам проекта. Багов, проблем безопасности и нарушений не обнаружено.»] ``` В PR-режиме добавляй ссылки на код с полным SHA: - GitHub: `https://github.com/owner/repo/blob/[full-sha]/path#L[start]-L[end]` - GitLab: URL инстанса из `git remote get-url origin`, затем `https://[gitlab-host]/owner/repo/-/blob/[full-sha]/path#L[start]-L[end]` ## Шаг 7: Предложение действий Вердикт **CHANGES LOOK GOOD** → пропусти шаг целиком, сразу к финальной рекомендации. Вердикт **ISSUES FOUND** → спроси (вопрос «Как поступим с находками ревью?»): - **Исправить** — примени предложенные фиксы напрямую, затем прогони тесты и доложи результат; отмена фикса — только обратными правками, никогда не `git checkout`/`git restore`/`git stash` — они снесут незакоммиченные изменения, которые ревьюились. - **Комментарий в PR** (только PR/MR-режим) — запости сводку ревью комментарием. - **Пропустить** — оставить отчёт как справку. **Постинг комментария**: выполни `mktemp ./review-summary-XXXXXX` — относительный путь, не `/tmp` (на Windows Git Bash монт `/tmp` не разрешается нативными `gh.exe`/`glab.exe`, и комментарий молча уйдёт пустым). Запиши сводку в напечатанный путь и подставь его литерально вместо `<summary-file>` (shell-переменные между вызовами не живут). Всегда `rm -f <summary-file>` после попытки постинга, независимо от результата. - GitHub: `gh pr comment <N> --body-file <summary-file>` - GitLab: `glab api -X POST "projects/:id/merge_requests/<N>/notes" -F body=@<summary-file>` — избегает поломки на shell-метасимволах, которая ждёт `glab mr note --message "$(cat ...)"` со сниппетами кода в сводке ## Важно Скилл read-only: никогда не изменяй файлы, не коммить, не пушь и не пости комментарии без явного одобрения пользователя; одобренные фиксы остаются локальными изменениями, которые пользователь проверяет через `git diff` до коммита. В финале порекомендуй следующий шаг: находки исправлены → коммит (скилл `git-commit`); чисто или фиксы пропущены → оформление PR/MR (если ревьюился не сам PR). Оставайся в этом разговоре — контекст реализации здесь.