Слепое сравнение · два раунда · один промпт

Claude Code, Codex и Cursor: что видно, когда ТЗ становится по-настоящему трудным

Первый раунд задание почти не сопротивлялось: 30, 29,8 и 28,3 из 30. Второй раунд написан так, чтобы полный балл был недостижим за 15 минут — с блоком требований по безопасности, мутационной проверкой тестов и ловушками, где буквальное прочтение приводит к абсурду. Ни один агент не взял 100 %.

21 августа 2026 Задача: модуль расчёта корзины, PHP 8.2 6 прогонов агентов · 6 независимых приёмок

01Итог второго раунда

Баллы — среднее трёх независимых оценок по рубрике на 50 пунктов: ручная приёмка оператора и две слепые оценки судьями. Все три оценщика выстроили агентов в одном порядке.

1 место
Codex
GPT-5.6 Sol · 387 с
94,3 %
46,0 · 47,0 · 48,5 из 50
покрытие 91,4 % · MSI 77,2 % тестов: 20 / 72 проверки доделок до мержа: 2–3
2 место
Cursor
Composer 2.5 · 268 с
89,0 %
43,5 · 45,0 · 45,0 из 50
покрытие 90,6 % · MSI 73,6 % тестов: 48 / 106 проверок доделок до мержа: 2–7
3 место
Claude Code
Opus 5 · 900 с, таймаут
84,0 %
40,5 · 42,0 · 43,5 из 50
покрытие 84,0 % · MSI 75,4 % тестов: 59 / 192 проверки доделок до мержа: 4–5
Главное

Расчётную часть — все двенадцать ловушек, включая поштучное округление, три разные базы порога доставки, построчный НДС и распределение фиксированной скидки методом наибольших остатков — взяли все трое, копейка в копейку. Разошлись они на трёх вещах: успел ли агент написать документацию, честен ли его финальный отчёт и выдерживает ли код враждебный вход на границах.

02Модели и версии

Перед вторым раундом проверено, что везде стоит последнее. Одно обновление потребовалось.

АгентРаунд 1Раунд 2Статус
Claude Code
CLI 2.1.238
claude-opus-5 claude-opus-5 уже последняя
Opus 5 вышел 24.07.2026 — позже Fable 5 (09.06.2026) и лидирует на агентных кодинг-бенчмарках, поэтому взят он, а не Fable
Codex
CLI 0.142.5 → 0.149.0
gpt-5.5 gpt-5.6-sol было устаревшее
CLI отставал на семь версий и физически не мог запустить GPT-5.6: сервер отвечал «требуется более новая версия Codex». Обновлён, перезапущен на флагмане
Cursor
CLI 2026.08.11
composer-2.5 composer-2.5 уже последняя
в списке моделей помечена как current; собственная модель Cursor, как и требовалось

03Методика

Что фиксировалиКак именно
Стартовое состояниеТри пустых каталога, в каждом только пустой git-репозиторий.
ПромптОдин файл, подставлялся всем троим дословно и ровно один раз, через stdin. Никаких уточнений и повторных отправок.
ТаймерЖёсткий timeout -k 15s 900s. Что не успел — не успел.
ВмешательствоНулевое. Уточняющих вопросов не задал никто.
ИзоляцияОтдельные CLAUDE_CONFIG_DIR и CODEX_HOME только с авторизацией: без хуков, плагинов, MCP, пользовательских настроек и памяти.
ПорядокПоследовательно, по одному — никто не делил CPU во время своих 15 минут.
Автор заданияВторое ТЗ написал Codex на GPT-5.6 Sol с высоким reasoning: ему дали первое задание, рубрику и результаты первого раунда и поручили усложнить так, чтобы 100 % стало недостижимо. Он же выдал карту из двенадцати ловушек с числовыми эталонами — которые затем пересчитаны вручную перед использованием.
Приёмка19 расчётных кейсов и 17 враждебных входов через CLI, покрытие через pcov, мутационное тестирование через Infection, прогон под faketime 2027 и в трёх часовых поясах — всё руками, а не со слов агентов.

Как задание стало труднее

Текст остался прозой без нумерации — требования по-прежнему нужно извлекать чтением. Изменилась не длина, а плотность взаимодействий: правила передают друг другу базу и округлённые копейки, поэтому ошибка в начале каскадом меняет доставку, НДС и итог.

Раунд 1Раунд 2
Скидка 10 % от суммы позиции10 % округляются на единице товара, потом умножаются на количество, а 15 % промокода — одним округлением от всей позиции
Скидки не складываютсяSUMMER26 не складывается, а WELCOME складывается с категорийной — вопреки привычной практике
Один порог бесплатной доставкиПорог считается от трёх разных баз: до WELCOME, но после SUMMER26
НДС выделяется от итогаНДС округляется построчно и отдельно для доставки, затем складывается
Фикс-скидка на корзинуРаспределяется методом наибольших остатков, ничья разрешается по возрастанию sku
Блок безопасности: лимит stdin до декодирования, глубина JSON, число позиций, UTF-8, точные типы чисел, защита каждой операции от переполнения, санитарные ошибки без трасс и путей
Требование детерминизма вывода при перестановке строк входа и сортировки позиций по байтам sku

04Расчётная часть: взяли всё

19 кейсов с эталонными числами, посчитанными вручную по тексту задания до открытия кода. Все суммы в копейках.

КейсэталонClaudeCodexCursor
Поштучное округление
аксессуар 5 коп × 3 шт: 10 % от единицы = 0,5 → 1
скидка 3
итог 35 012
НДС 5 835
3 / 35 012 / 5 8353 / 35 012 / 5 8353 / 35 012 / 5 835
SUMMER26 против категории
порог ровно 500 000 до скидок
75 000
460 000
76 667
75 000 / 460 000 / 76 66775 000 / 460 000 / 76 66775 000 / 460 000 / 76 667
Ничья скидок
обе дают 1 коп — побеждает категорийная
category_10 category_10category_10category_10
Распределение WELCOME
наибольшие остатки, ничья по sku
18 889 / 16 667 / 16 666
нетто 3 333 / 3 333 / 3 334
НДС 7 501
совпалосовпалосовпало
Нулевая «Электроника»
буквально активирует WELCOME
applied
итог 45 000
applied / 45 000applied / 45 000applied / 45 000
Три базы порога доставки 0 и 35 000 0 / 35 0000 / 35 0000 / 35 000
Построчный НДС
одно округление дало бы 5 834
5 833 5 8335 8335 833
Большие числа без переполнения
gross 1018, произведение на 15 не помещается в int
150 000 000 000 000 000
НДС 141 666 666 666 666 667
совпалосовпалосовпало
Граница SUMMER26
23:59:59,756 по Москве — последняя секунда
applied appliedapplied expired ✗

Итог по разделу: 19 из 19 кейсов у Claude и Codex, 18 из 19 у Cursor.

Единственное расхождение в расчёте — и его не поймал ни один тест агента

Cursor сравнивает текущий момент с дедлайном как $now > $deadline, где дедлайн — 23:59:59.000000. Любой момент внутри последней секунды (например, 23:59:59,756) оказывается больше — и промокод объявляется просроченным, хотя задание требует «включительно». У Cursor есть тест с говорящим именем testSummer26ValidOnDeadlineInclusive, и он зелёный: тест подаёт ровную секунду без микросекунд, то есть проверяет реализацию, а не требование. Claude и Codex на том же входе отвечают applied.

05Безопасность

Задание объявляет вход недоверенным. 17 враждебных входов поданы каждому решению вручную; проверялись код возврата, пустота stdout и отсутствие утечки внутренностей в stderr.

ПроверкаClaudeCodexCursor
stdin больше 1 МиБ отвергается до декодированиякод 2код 2код 2
Глубина JSON больше 32код 2код 2код 2
Больше 1 000 позиций до схлопываниякод 2код 2код 2
Лишние поля в корне и в позициикод 2код 2код 2
Ложные типы чисел: 1e3, 1.0, "1000", true, за пределом int5 из 55 из 55 из 5
Некорректный UTF-8, 257 байт, управляющий символ3 из 33 из 33 из 3
Переполнение суммы при валидных позицияхкод 2код 2код 2
Санитарные ошибки: только code и message, без трасс и путейчисточисточисто
Нет eval, unserialize, exec, shell_exec, proc_openчисточисточисто
sku вне разрешённого алфавита
задание допускает только A–Z, 0–9, точку, дефис, подчёркивание
код 2код 2принимает phone1, код 0
Валидный большой вход с WELCOME
две строки по 1018 — ответ помещается в int
посчиталпосчиталкод 2 на валидном входе

Первые девять проверок прошли все трое — это заметный шаг вперёд относительно первого раунда, где переполнение int роняло Codex и Cursor в PHP Fatal. Два последних пункта развели участников: у Cursor валидация sku пропускает строчные буквы, а защита от переполнения неполна — остаток при распределении WELCOME считается через опасное произведение, из-за чего математически корректный вход отвергается как некорректный. Обе находки сделал сначала один из судей, затем они воспроизведены вручную.

06Тесты: достаточность, сила, избыточность

Количество тестов ничего не говорит о том, ловят ли они дефекты. Поэтому кроме покрытия строк замерялась мутационная устойчивость: Infection вносит в код изменения и смотрит, падают ли тесты.

МетрикаClaudeCodexCursor
Тест-методов / тестов PHPUnit48 / 5920 / 2948 / 48
Проверок (assertions)19272106
Покрытие строк83,97 %91,45 %90,62 %
Мутантов сгенерировано337276280
Убито / выжило253 / 83211 / 63205 / 74
MSI (мутационное покрытие)75,4 %77,2 %73,6 %
Слабых ассертов (assertTrue, assertNotNull)021
Тестов прицельно по безопасности3719
Обязательных по ТЗ сценариев не покрыто5 из 143 из 141 из 14

Что из этого следует

Отдача на один тест

Codex
3,86 %/тест
Cursor
1,53 %/тест
Claude
1,57 %/тест

MSI, делённый на число тест-методов. Показывает, сколько мутационной устойчивости приносит один написанный тест: у Codex каждый тест «работает» примерно в 2,5 раза плотнее.

07Оценка тремя судьями

Результаты обезличены: скопированы в subject-1/2/3 в перемешанном порядке, git-история удалена, пути и упоминания авторства вычищены и проверены грепом. Каждый судья получил одинаковую рубрику на 50 пунктов, приложенный infection.phar и работал в своей копии материалов.

СудьяCodexCursorClaudeПорядок
Ручная приёмка (оператор)46,043,540,5Codex → Cursor → Claude
Судья Claude Code (Opus 5)47,045,042,0Codex → Cursor → Claude
Судья Codex (GPT-5.6 Sol)48,545,043,5Codex → Cursor → Claude
Среднее из 5047,17 94,3 %44,5 89,0 %42,0 84,0 %полное совпадение
Ручных доделок до мержа2–32–74–5

Максимальная оценка за весь раунд — 97 % от одного судьи. Ни один агент не набрал 100 % ни у одного оценщика: цель усложнения достигнута. Судья Codex, не зная авторства, поставил работе собственного CLI первое место — но и оба других оценщика пришли к тому же выводу независимо.

Что судьи нашли сверх ручной приёмки

08Разбор по агентам

Codex — 94,3 %

GPT-5.6 Sol · 387 с · 408 тыс. токенов · 4 класса, 476 строк · 2–3 доделки
Сильные стороны
Слабые стороны

Cursor — 89,0 %

Composer 2.5 · 268 с · 1,05 млн токенов · 7 классов, 755 строк · 2–7 доделок
Сильные стороны
Слабые стороны

Claude Code — 84,0 %

Opus 5 · 900 с, оборван таймером · 19 классов, 1 402 строки · 4–5 доделок
Сильные стороны
Слабые стороны

Затраты

МетрикаClaudeCodexCursor
Время900 с таймаут387 с268 с
Всего токенов2 010 431408 1721 047 298
Из них чтение кэша1 919 143354 304962 528
Выходные токенынет данных18 83746 375
Классов / строк кода19 / 1 4024 / 4767 / 755
Документация (строк)0133254

У Claude выходные токены недоступны: прогон оборван таймером, и финальное событие с итоговым usage не пришло. Приведённая сумма собрана по промежуточным сообщениям и занижена.

09Раунд 1 для сравнения

То же задание, но простое: 30 баллов, без блока безопасности. Показывает, насколько мало различимы агенты, когда ТЗ им не сопротивляется.

МетрикаClaudeCodexCursor
Модельopus-5gpt-5.5composer-2.5
Время891 с212 с155 с
Токенов2 236 372276 750409 750
Тестов / проверок129 / 40217 / 5849 / 96
Покрытие строк90,28 %96,95 %83,61 %
MSI71,52 %74,55 %72,09 %
Балл (среднее трёх оценок)30,0 / 3028,3 / 3029,8 / 30

В первом раунде две работы из трёх получили полный балл, и различить их можно было только по глубине проработки. Единственной ловушкой, которая тогда развела агентов, было противоречие про порог бесплатной доставки: Claude вынес его в конфигурируемый параметр с тестами на обе трактовки, Cursor завёл раздел «Неоднозначности ТЗ», Codex снял противоречие молча.

Показательно, что порядок мест между раундами изменился на противоположный. Это не шум: в первом раунде побеждала обстоятельность, во втором — способность уложить всё главное в отведённое время. Один и тот же агент может быть первым и последним в зависимости от того, чего требует задача.

10Выводы

Если выбирать под задачу

КогдаКого братьПочему
Жёсткий срок, объёмное ТЗ, нужен готовый результат целикомCodex (GPT-5.6 Sol) Единственный, кто уложил и код, и безопасность, и документацию в 6,5 минут при лучшем покрытии и MSI.
Нужен максимально аккуратный production-код, срок вториченClaude Code (Opus 5) Лучшая архитектура и самая точная работа с границами; но закладывайте время с запасом — в 15 минут он не уложился.
Быстрый черновик с хорошей документацией, есть кому проверитьCursor (Composer 2.5) Быстрее всех и лучше всех документирует, но именно у него нашлись все три реальных дефекта раунда.
Что стоит добавить в следующий прогон

Мутационное тестирование оказалось самым информативным инструментом приёмки: оно единственное показывает разрыв между «тесты зелёные» и «тесты что-то проверяют». В следующий раз имеет смысл вынести MSI в само задание как измеримое требование — и посмотреть, изменит ли это то, какие тесты агенты пишут.