---
name: codex-code-review-fix
description: "Независимое cross-model ревью кода. Отправляет изменённые файлы на проверку через codex в headless-режиме, получает структурированные замечания, верифицирует их по кодовой базе, исправляет через агента 1c-code-writer и итеративно повторяет до одобрения."
disable-model-invocation: true
---

# Codex Code Review Fix

Независимое ревью кода через Codex: изменения отправляются на проверку, Codex исследует кодовую базу и возвращает структурированные замечания, ты верифицируешь их, CONFIRMED замечания исправляет агент `1c-code-writer`, и цикл повторяется до одобрения или лимита итераций.

## Формат вызова

```
/codex-code-review-fix <scope> [N итераций] [план <путь> | <описание доработки>]
```

`scope` — что ревьюировать:
- `незакомиченные` / `unstaged` → все незакомиченные изменения (`git diff HEAD`)
- `последний коммит` / `last-commit` → последний коммит (`git show HEAD`)
- `последние 2` / `последние N` → N последних коммитов (`HEAD~N..HEAD`)
- `HEAD~3` или `HEAD~3..HEAD` → диапазон коммитов
- `abc123..def456` → конкретный диапазон
- `abc123` → конкретный коммит по хешу
- `abc123 def456 ...` → несколько конкретных коммитов (объединение файлов)
- `path/to/file.bsl` или несколько путей через пробел → конкретные файлы

Если scope не указан — спроси у пользователя.
Если N итераций не указано — по умолчанию 5.

Контекст доработки (опционально) — всё что идёт после scope и итераций:
- `план <путь>` / `plan <путь>` → путь к файлу плана
- любой другой текст → текстовое описание доработки

## Алгоритм

### 1. Подготовка

1. Распарси аргументы: извлеки число + «итераций» в конце как max iterations, затем `план <путь>` или `plan <путь>` как контекст-план, иначе остаток текста после scope и итераций — как текстовый контекст доработки; остальное — scope
2. Получи список файлов и определи `DIFF_COMMAND` в зависимости от scope:

   **Список файлов** (для преобразования в абсолютные пути):
   - `незакомиченные` / `unstaged` → `git diff HEAD --name-only`
   - `последний коммит` / `last-commit` → `git show HEAD --name-only --format=""`
   - `последние N` / `HEAD~N..HEAD` / `HEAD~N` → `git diff HEAD~N --name-only`
   - `X..Y` (явный диапазон с разными хешами) → `git diff X --name-only` (Y намеренно игнорируется — по той же причине что и в DIFF_COMMAND: Codex должен видеть правки агента)
   - `abc123` (одиночный хеш) → `git show abc123 --name-only --format=""`
   - несколько хешей → для каждого `git show <hash> --name-only --format=""`, объединить (дубликаты убрать)
   - конкретные файлы → использовать напрямую, проверить что существуют

   **`DIFF_COMMAND`** — команда, которую Codex выполнит сам для получения диффа:
   - `незакомиченные` / `unstaged` → `git diff HEAD`
   - `последний коммит` → `git diff HEAD^`
   - `последние N` / `HEAD~N..HEAD` → `git diff HEAD~N`
   - `X..Y` → `git diff X` (X — базовая точка, диапазон начинается после X)
   - `abc123` (одиночный хеш) → `git diff abc123^`
   - несколько хешей → `git diff <самый ранний хеш>^`
   - конкретные файлы → `git diff HEAD -- <файл1> <файл2> ...`

   `DIFF_COMMAND` намеренно без `..конец` — так Codex видит исходные изменения + незакоммиченные правки агента в последующих итерациях.
3. Если список файлов пуст — сообщи пользователю и завершись
4. Преобразуй пути файлов в абсолютные (относительно корня git-репозитория)
5. Создай папку `.codex-code-review/` в корне проекта — в неё пишутся промпты, лог и run.log
6. Если передан контекст доработки — сохрани его в `.codex-code-review/context.md`:
   - если `план <путь>`: прочитай файл плана и запиши его содержимое
   - если текстовое описание: запиши как есть
7. Инициализируй лог: `.codex-code-review/review-log.md`
8. Собери `RULES_CONTEXT` (подробности в разделе «Сборка контекста правил»)

### 2. Сборка контекста правил

Codex не читает `.claude/rules/` и `CLAUDE.md` автоматически — контекст нужно передать явно в промпте.

1. Прочитай все файлы из `~/.claude/rules/*.md` (глобальные правила пользователя)
2. Прочитай `~/.claude/CLAUDE.md` (глобальный CLAUDE.md, если существует)
3. Найди и прочитай `.claude/rules/*.md` в корне текущего проекта (если каталог существует)
4. Найди и прочитай `CLAUDE.md` в корне текущего проекта (если существует). Также проверь `CLAUDE.md` в текущем рабочем каталоге, если он отличается от корня проекта
5. Прочитай `references/review-system-prompt.md` относительно этого скилла — используй абсолютный путь
6. Объедини правила (без system prompt) в `RULES_CONTEXT`:

```
--- Файл: имя_файла_правил.md ---
содержимое файла

--- Файл: ~/.claude/CLAUDE.md ---
содержимое глобального CLAUDE.md

--- Файл: CLAUDE.md ---
содержимое проектного CLAUDE.md
```

Если файлы не найдены — пропусти без ошибки.

### 3. Цикл ревью

Повторяй пока Codex не вернёт `"status": "approved"` или не исчерпан лимит итераций:

**a) Собери промпт для Codex:**

```
<system_instructions>
СОДЕРЖИМОЕ_REVIEW_SYSTEM_PROMPT_MD
</system_instructions>

<project_rules>
RULES_CONTEXT
</project_rules>

ПРОМПТ_ИТЕРАЦИИ
```

Если `context.md` создан на шаге подготовки — добавь в конец любого промпта строку: `Перед ревью прочитай контекст доработки: АБСОЛЮТНЫЙ_ПУТЬ/.codex-code-review/context.md`

**Промпт первой итерации:**
```
Проведи ревью кода. Выполни `DIFF_COMMAND` чтобы увидеть изменения. Для чтения полного контекста доступны файлы:
АБСОЛЮТНЫЙ_ПУТЬ_1
АБСОЛЮТНЫЙ_ПУТЬ_2
...
```

**Промпт последующих итераций:**
```
Проведи ревью кода. Выполни `DIFF_COMMAND` чтобы увидеть изменения (включает исходные коммиты и незакоммиченные правки агента). Для чтения полного контекста доступны файлы:
АБСОЛЮТНЫЙ_ПУТЬ_1
АБСОЛЮТНЫЙ_ПУТЬ_2
...

Следующие замечания приняты и исправлены — не повторяй их:
<accepted_issues>
НАКОПЛЕННЫЙ_СПИСОК_ПРИНЯТЫХ_ЗАМЕЧАНИЙ
</accepted_issues>

<rejected_issues>
Следующие замечания были отклонены. Прочитай аргументы — если они убедительны, не повторяй замечание. Если аргументы ошибочны, объясни почему проблема всё ещё существует.

НАКОПЛЕННЫЙ_СПИСОК_ОТКЛОНЁННЫХ_ЗАМЕЧАНИЙ_С_АРГУМЕНТАМИ
</rejected_issues>

Сосредоточься на новых проблемах. Если считаешь что отклонённое замечание всё же валидно — аргументируй, почему приведённые аргументы ошибочны.
```

`НАКОПЛЕННЫЙ_СПИСОК_ПРИНЯТЫХ_ЗАМЕЧАНИЙ` — компактный список всех CONFIRMED замечаний за все итерации, по одной строке: `[файл, "ИмяМетода > фрагмент"]: суть в 5-7 словах`. Например:
```
[МодульМенеджера.bsl, "ОбработатьДокументы > Запрос = Новый Запрос"]: запрос внутри цикла
[ФормаСписка.bsl, "ПриОткрытии > Контрагент.ИНН"]: получение реквизита через точку
[ОбщийМодуль.bsl, "ПроверитьДанные > Сообщить(ТекстОшибки)"]: Сообщить() вместо ОбщегоНазначения.СообщитьПользователю()
```

Якорь состоит из имени метода и ключевого фрагмента кода — он устойчив к сдвигу строк. Codex прочитает файл и по нему поймёт, исправлена ли проблема.

`НАКОПЛЕННЫЙ_СПИСОК_ОТКЛОНЁННЫХ_ЗАМЕЧАНИЙ_С_АРГУМЕНТАМИ` — для каждого FALSE POSITIVE: суть + развёрнутый аргумент (2-3 предложения с указанием конкретных мест в коде). Формат:
```
[файл, "ИмяМетода > фрагмент"]: суть замечания
Аргумент: Полное объяснение почему отклонено. Ссылки на конкретный код, логическое обоснование.

[файл, "ИмяМетода > фрагмент"]: суть замечания
Аргумент: Полное объяснение почему отклонено.
```

Аргумент должен быть убедительным для Codex — это диалог между моделями. Codex прочитает его и решит: принять отклонение или настоять с новыми доказательствами.

Если отклонённых замечаний нет — блок `<rejected_issues>` можно опустить.

**b) Запусти codex:**

Запиши промпт в `.codex-code-review/prompt-iter<N>.txt` через Write, затем передай через stdin:

```bash
RESULT=$(codex exec \
  -s read-only \
  -c model_reasoning_effort=xhigh \
  -c stream_idle_timeout_ms=1800000 \
  - < ".codex-code-review/prompt-iter<N>.txt" \
  2>".codex-code-review/run.log") \
  || (echo "codex failed:"; cat ".codex-code-review/run.log")
echo "$RESULT"
```

- Передача через файл+stdin надёжнее прямого аргумента: промпт содержит теги, кавычки и спецсимволы
- stderr (лог сессии) идёт в `.codex-code-review/run.log` — не засоряет контекст
- Финальный ответ Codex пишет в stdout — читай из `$RESULT`
- Таймаут Bash-вызова: 1800000 мс (30 минут)

**c) Распарси ответ:**

JSON читай из `$RESULT`. Если обёрнут в markdown-блок (` ```json ... ``` `), извлеки содержимое между маркерами.

Структура ответа Codex:
```json
{
  "status": "approved" | "has_issues",
  "issues": [
    {
      "severity": "critical" | "important",
      "confidence": 80,
      "file": "путь/к/файлу",
      "line": "45" или "45-52",
      "problem": "Описание проблемы",
      "impact": "Как это повлияет: баг, нарушение правил, производительность и т.п.",
      "suggestion": "Предложение по исправлению",
      "evidence": "Подтверждение из кода или логическое обоснование"
    }
  ],
  "summary": "Общая оценка"
}
```

**d) Если `status == "approved"` или `issues` пуст — выйди из цикла.**

**e) Stalemate detection:** если замечания текущей итерации по сути повторяют предыдущие (те же файлы, те же проблемы) — прерви цикл и сообщи пользователю о расхождении мнений. Без этой проверки цикл тратит итерации впустую, когда Codex и Claude не сходятся во мнении.

**f) Если есть новые замечания:**
1. Верифицируй каждое замечание — прочитай упомянутый код, проверь факты. Используй свои знания и контекст проекта, не копируй слепо предложения Codex. Классифицируй: CONFIRMED / FALSE POSITIVE. При верификации — извлеки **якорь**: имя метода (процедуры/функции), в котором находится проблема, и 4-7 ключевых слов из проблемного места (уникальная часть выражения). Формат якоря: `"ИмяМетода > фрагмент кода"`, например `"ОбработатьДокументы > Запрос = Новый Запрос"`. Якорь устойчив к сдвигу строк после правок — используй его вместо номера строки для идентификации. Если проблема вне метода (например, в области объявления переменных) — используй только фрагмент кода
2. По CONFIRMED замечаниям вызови агент для исправления (подробности в разделе «Вызов агента»)
3. Добавь в `accepted_issues` только успешно исправленные замечания — после верификации результата агента (подробности в разделе «Вызов агента»)
4. Добавь FALSE POSITIVE в `rejected_issues` с развёрнутым аргументом:
   ```
   [файл, "ИмяМетода > фрагмент"]: суть замечания
   Аргумент: Почему отклонено — 2-3 предложения со ссылками на конкретный код.
   ```
5. Допиши итерацию в лог
6. Перейди к следующей итерации

Между итерациями не показывай промежуточные результаты — работай молча до завершения.

### 4. Вызов агента

После верификации — для каждого CONFIRMED замечания вызови агент `1c-code-writer`.

**Группировка:** если несколько CONFIRMED замечаний относятся к одному файлу — передай их одним вызовом агента.

**Промпт агенту** (для одного файла):
```
Исправь ТОЛЬКО следующие проблемы в файле <абсолютный_путь>. Не трогай ничего за пределами указанных мест — никаких попутных улучшений, рефакторинга или стилевых правок.

1. Метод «<ИмяМетода>», строка ~<line> (найди «<фрагмент кода>»): <problem>
   Влияние: <impact>
   Предложение: <suggestion>
   Обоснование: <evidence>

2. Метод «<ИмяМетода>», строка ~<line> (найди «<фрагмент кода>»): <problem>
   Влияние: <impact>
   Предложение: <suggestion>
   Обоснование: <evidence>

В ответе перечисли ТОЛЬКО: что исправлено (одна строка на пункт) и что не удалось исправить с краткой причиной. Без объяснений, рассуждений и показа кода.
```

**Если агент не может исправить без дополнительного контекста** — он сообщит об этом:
- Если у тебя достаточно контекста — ответь агенту самостоятельно
- Если требуется мнение или контекст пользователя — прерви молчаливый режим, спроси пользователя, затем передай ответ агенту

**Верификация результата агента:**

После ответа агента прочитай файл и проверь по якорю:
1. Найди фрагмент `"ИмяМетода > фрагмент"` в файле — убедись что код вокруг него соответствует `suggestion`
2. Убедись что соседний код не пострадал

Если исправление корректно — добавь замечание в `accepted_issues`.

Если исправление некорректно или частично:
- сформулируй что именно агент сделал не так (что нашёл по якорю vs что ожидалось)
- вызови агента повторно с уточнённым промптом: укажи что исправление было некорректным и почему
- если после второй попытки всё ещё неверно — не добавляй в `accepted_issues`; Codex увидит проблему на следующей итерации

### 5. Итоговый отчёт

После завершения цикла выведи пользователю:

```
## Результат ревью (Codex)

- Итераций: N из M (максимум)
- Найдено проблем: X (критических: Y, важных: Z)
- Исправлено: K, отклонено: L
- Статус: код одобрен / лимит итераций достигнут / stalemate
- Лог ревью: .codex-code-review/review-log.md
```

Если лимит достигнут:
- Все CONFIRMED замечания исправлены → написать «лимит достигнут, все найденные проблемы исправлены»
- Есть неисправленные (FALSE POSITIVE или stalemate) → показать что осталось и спросить пользователя что делать дальше

## Формат лога

Файл `.codex-code-review/review-log.md`:

```markdown
# Лог ревью (Codex): <scope>
Дата: <дата>
Файлы: <список файлов>
Максимум итераций: N

## Итерация 1

### Замечания Codex
- [critical, 95] файл:строка — Проблема → Предложение
- [important, 80] файл:строка — Проблема → Предложение

### Верификация
- CONFIRMED: [МодульМенеджера.bsl, "ОбработатьДокументы > Запрос = Новый Запрос"] — запрос в цикле → исправлено агентом
- FALSE POSITIVE: [ФормаСписка.bsl, "ПриОткрытии > Контрагент.ИНН"] — описание → причина отклонения

### Принято / Отклонено
- ПРИНЯТО: [МодульМенеджера.bsl, "ОбработатьДокументы > Запрос = Новый Запрос"]: запрос внутри цикла
- ОТКЛОНЕНО: [ФормаСписка.bsl, "ПриОткрытии > Контрагент.ИНН"]: получение реквизита через точку — причина

## Итерация 2
...

## Итог
- Всего итераций: N
- Всего найдено проблем: M (подтверждено: K, отклонено: L)
- Статус: одобрен / лимит достигнут / stalemate
```

## Обработка ошибок

- **`$RESULT` пустой или не валидный JSON**: повтори вызов один раз. Если снова ошибка — покажи `.codex-code-review/run.log` пользователю
- **Scope не определён**: спроси пользователя
- **Список файлов пуст**: сообщи пользователю — нет изменений для ревью
- **Файл плана не найден** (`план <путь>`): сообщи пользователю и спроси как поступить — продолжить без контекста или указать другой путь
- **codex не найден в PATH**: сообщи пользователю, что команда `codex` не найдена
