← Сводный отчёт этапа

gigachat-3-ultra · run-01

Тег GigaChat-3-Ultra · рассуждение max · окно 102.4K · начало 2026-10-21 02:37

Прогон и окружение

Агент-кандидат работает в изолированном pi на временной копии скелета задания; проверяющие ярусы подключаются после выполнения и каждый работает на своей копии решения.

2 из 11обязательные сценарии
0 из 2бонусные сценарии
1 из 4код и архитектура
1 из 4процесс и коммуникация
2 из 4слепое ревью
44 миндлительность прогона
7.8Mтокенов, кэш 0%
1464строк
30файлов в решении (без vendor)

Как запускался агент

PI_CODING_AGENT_DIR=<tmp>/pi-home PI_OFFLINE=1 \
pi -p --session-dir <прогон>/pi-session \
    --model GigaChat-3-Ultra --thinking max \
    "Прочитай TASK.md в корне репозитория и выполни задание."

Что дано кандидату

Скелет skeleton/ — рабочий Symfony-каркас (PHP >=8.4, Doctrine, bcmath) с TASK.md и AGENTS.md. Инструменты самопроверки в require-dev: phpunit/phpunit ^11.5, squizlabs/php_codesniffer ^3.13, vimeo/psalm ^6.0 — только это кандидату доступно; phpstan и phpmd в скелет не кладём (phpmd слишком жёсток для самопроверки, phpstan дублирует psalm) — меряем ими только внешние ярусы. Само задание — TASK.md; агенту оно передаётся одной фразой-промптом (в блоке выше), без уточнений и наводок.

Артефакты: run.json

Выполнение · сессия pi

Ход работы агента-кандидата: рост контекста по вызовам API, автокомпакты, чем самопроверялся.

674вызовов API
7.8Mтокенов всего (вход 7.7M, выход 49.2K, кэш-чтение 0 — 0%)
61.7Kпик контекста из 102.4K
0автокомпактов и правок истории (компактов 0, правок 0)
674tool-вызовов (650 bash)
22 минчистой генерации

Tool-вызовы по инструментам

Обращения агента к инструментам pi: чтение файлов, правки, запись, шелл.

674tool-вызовов
bash65096%
read101%
write91%
edit51%

Утилиты в bash

Запуски программ внутри 650 вызовов инструмента bash: один вызов — обычно цепочка команд через ; / && / |, считаются первые слова каждого сегмента.

650вызовов
console64098%
ls71%
composer20%
make10%

Наложены периоды работы tool-вызовов — прямоугольник от вызова до результата, ширина = длительность, цвет = инструмент: ■ bash, ■ read, ■ write, ■ edit.

026.6K53.2K79.9K10м20м30м40млимит 102.4Kвремя от начала сессии (674 вызовов API)контекст, токены

Контекст — полный промпт вызова (вход + кэш-чтение + кэш-запись). Резкое падение линии — автокомпакт или правка истории. ◆ — кэш-промах: контекст цел, но перезалит в кэш целиком (TTL кэша истёк за долгой генерацией). У GigaChat падения без компакций — артефакт учёта провайдера: usage отдаёт только некэшированную часть промпта, кэшированный префикс не показывает.

Самопроверка моделью

Сколько раз за прогон агент сам проверял свою работу, по инструментам. Кандидату в require-dev даны тесты phpunit, phpcs и psalm (пустой бар — не запускал); phpstan и phpmd — только внешние ярусы.

приёмка (bin/console app:*)
6
сборка (composer)
2
тесты (phpunit / make test)
0
стиль (phpcs / phpcbf)
0
psalm
0

Косяки и переделки

99%команд bash прошли с первого раза (без ошибок в выводе)
4вызовов завершились ошибкой (Fatal error, SQLSTATE, not found…)
4раз после ошибки агент правил и перезапускал команду
0 из 0падений тестов доведены до прохода (агент правил код, тесты потом прошли)

Показатель качества: чем меньше ошибок и переделок, тем ближе прогон к «ваншоту» и тем быстрее получен результат. Перекликается с показателем галлюцинаций из интервью.

Вызовов печатной отладки (var_dump / dump / dd) в финальном коде: 0. Уникальных файлов создано или отредактировано: 9.

Артефакты: pi-session · pi-run.log · diff.patch · session-profile.md · summary.md

Аудит безопасности

Наблюдение за поведением агента: детектор помечает обращение к сети и пути вне рабочего каталога прогона. Сигнал — не вердикт: каждый разбирает судья-аудитор (изолированная pi-сессия glm-5.3-flash, checker/judge_audit.py). Полный список сигналов — security.json, построчный разбор — audit-verdict.md рядом с отчётом.

Сеть не использовалась, за пределы рабочего каталога агент не выходил.

Вердикт аудитора: чисто — сигналов нет — аудитор не вызывался

Артефакты: security.json · audit-verdict.md · audit.json

Ярус 1 · чекер: обязательных 2 из 11, бонусных 0 из 2

Отвечает «сделано и работает по контракту», но не «хорошо сделано»: каждый сценарий запускает решение и сверяет результат с эталоном — счётчики импорта, дедупликация, отчёт байт-в-байт. Качество кода чекер не оценивает. Работает на своей временной копии решения: артефакты кандидата не трогаются, vendor поднимается composer install (при рассинхроне с lock — update).

СценарийСтатусДетали
artifacts_presentfailотсутствуют/пусты: COMMIT_MESSAGE.md, PR_DESCRIPTION.md
db_createpassCreated database "chk_47739" for connection named default
import_duplicatesfailПровайдер не найден: prism (строка 1)
migratepassmethod=migrations
prices_importfailМодель не найдена: prism/lumen-8
rate_after_duplicatesfailstdout: 'Ошибка тарификации: An exception occurred while executing a query: SQLSTATE[42703]: Undefined column: 7 ERROR: column t'
rate_countsfailв stdout нет 'RATED= UNRATED=': 'Ошибка тарификации: An exception occurred while executing a query: SQLSTATE[42703]: Undefined column: 7 ERROR: column t'
report_basefailкод 7: es not exist
LINE 1: ...u0_.provider_request_id AS provider_request_id_1, u0_.user A...
^


app:billing:report [--from FROM] [--to TO]
report_duplicatesfailкод 7: es not exist
LINE 1: ...u0_.provider_request_id AS provider_request_id_1, u0_.user A...
^


app:billing:report [--from FROM] [--to TO]
report_retroskipкоманды app:billing:reprice нет (бонус не выполнялся)
reprice_outputskipкоманды app:billing:reprice нет (бонус не выполнялся)
skeleton_changespassизменены: composer.json, composer.lock
unrated_stderrfailожидались ['UNRATED prism/h13 2026-07-31T23:00:00Z no_price'], получено []
usage_importfailПровайдер не найден: prism (строка 1)

Артефакты: check.json

Ярус 2 · метрики кода

Насколько хорошо написан код: предупреждения статанализа (phpstan, psalm, phpcs) и структурные метрики (сложность, связность). Числа не про поведение — его проверил чекер, и не про смысл решения — его оценивают судьи ярусов 3–4.

phpcs PSR12
21
среднее других прогонов модели: 21
psalm L1
191
среднее других прогонов модели: 191
phpstan L8
33
среднее других прогонов модели: 33
phpmd (наблюдение)
24
среднее других прогонов модели: 24

Синяя полоса — этот прогон; красная риска — среднее того же показателя по другим прогонам этой же модели (меньше — лучше). phpmd — наблюдение: в оценку решений не входит. Сравнение показывает постоянство решений модели от прогона к прогону; другие модели — в сводном отчёте этапа.

Код в цифрах и нарушения в деталях

scc — объём кода

779строк кода
70строк комментариев — 9% от строк кода
9файлов
файлов
9
среднее: 9
строк кода
779
среднее: 779
комментариев
70
среднее: 70
пустых строк
155
среднее: 155
суммарная сложность
42
среднее: 42

phpcs (стиль, PSR-12) — топ сообщений

разсообщение
4×[x] Expected 1 newline at end of file; 0 found
3×[ ] Line exceeds 120 characters; contains 123 characters
2×Line exceeds 120 characters; contains 128 characters
2×Line exceeds 120 characters; contains 127 characters
2×Line exceeds 120 characters; contains 131 characters
1×Line exceeds 120 characters; contains 130 characters

psalm (уровень 1) — топ типов проблем

разтиппример
55×MixedArrayAccesssrc/Command/BillingReportCommand.php:74
33×MixedMethodCallsrc/Command/BillingRateCommand.php:98
30×MixedArgumentsrc/Command/BillingRateCommand.php:121
27×MixedAssignmentsrc/Command/BillingRateCommand.php:86
23×MixedOperandsrc/Command/BillingReportCommand.php:53
7×MissingOverrideAttributesrc/Command/BillingRateCommand.php:29
4×PossiblyFalseArgumentsrc/Command/BillingReportCommand.php:81
3×PropertyNotSetInConstructorsrc/Entity/Model.php:17

phpstan — топ сообщений

разсообщениепример
7×Call to method add() on an unknown class BCMath.src/Command/BillingRateCommand.php:103
6×Call to method mul() on an unknown class BCMath.src/Command/BillingRateCommand.php:116
5×Call to method div() on an unknown class BCMath.src/Command/BillingRateCommand.php:104
3×Parameter #1 $stream of function fputcsv expects resource, resource|false given.src/Command/BillingReportCommand.php:104
2×Call to an undefined method App\Entity\Price::setProvider().src/Entity/Provider.php:132
1×Property App\Command\BillingRateCommand::$conn is never read, only written.src/Command/BillingRateCommand.php:24

phpmd — правила (наблюдение, в оценку не входит)

разправило
10×ShortVariable
5×MissingImport
3×ElseExpression
3×ExcessiveMethodLength
2×UnusedFormalParameter
1×UnusedLocalVariable

Классы: размер и связность

Каждая точка — один класс решения. Горизонталь — LOC, строк кода. Вертикаль — LCOM4: сколько у класса несвязанных «зон ответственности» (1 — класс про одно; 2+ — делает несколько дел сразу, кандидат на разнос). Размер точки — WMC: суммарная сложность всех методов класса. Цвет — CC самого сложного метода (цикломатическая сложность: сколько в нём путей исполнения, грубо — ветвлений if/for/case): синий ≤5 — спокойно, оранжевый 6–10 — тяжеловато, красный >10 — метод-спагетти.

0246810023466992115138App\Command\BillingRateCommandLOC 132 · LCOM4 4 · WMC 23 · cc_max 6BillingRateCommandApp\Entity\ProviderLOC 125 · LCOM4 7 · WMC 20 · cc_max 2ProviderApp\Command\PricesImportCommandLOC 119 · LCOM4 2 · WMC 17 · cc_max 15PricesImportCommandApp\Entity\UsageEventLOC 124 · LCOM4 11 · WMC 13 · cc_max 1UsageEventApp\Command\UsageImportCommandLOC 98 · LCOM4 2 · WMC 12 · cc_max 10UsageImportCommandApp\Entity\PriceLOC 121 · LCOM4 11 · WMC 12 · cc_max 1PriceApp\Command\BillingReportCommandLOC 103 · LCOM4 2 · WMC 10 · cc_max 8App\Entity\ModelLOC 48 · LCOM4 3 · WMC 6 · cc_max 1App\KernelLOC 23 · LCOM4 1 · WMC 5 · cc_max 3LOC классакомпоненты LCOM4

Размер точки — WMC класса, цвет — максимальная CC метода: ● ≤5, ● 6–10, ● >10. Наведите на точку — полная сводка.

Матрица зависимостей классов

BillingRateCommandBillingRateCommandBillingReportCommandBillingReportCommandPricesImportCommandPricesImportCommandUsageImportCommandUsageImportCommandModelModelPricePriceProviderProviderUsageEventUsageEventKernelKernelBillingRateCommand → Price · 1BillingRateCommand → UsageEvent · 1BillingReportCommand → UsageEvent · 1PricesImportCommand → Model · 1PricesImportCommand → Price · 1PricesImportCommand → Provider · 1UsageImportCommand → Model · 1UsageImportCommand → Provider · 1UsageImportCommand → UsageEvent · 1Model → Provider · 1Price → Model · 1Price → Provider · 1Provider → Model · 1Provider → Price · 1UsageEvent → Model · 1UsageEvent → Provider · 1BillingRateCommand → BCMath ×1, Connection ×1, EntityManagerInt…BillingReportCommand → DateTimeImmutable ×1, EntityManagerInter…PricesImportCommand → DateTimeImmutable ×1, EntityManagerInterf…UsageImportCommand → DateTimeImmutable ×1, EntityManagerInterfa…Model → Column ×1, Entity ×1, GeneratedValue ×1, …Price → DateTimeImmutable ×1, Column ×1, Entity ×1, …Provider → ArrayCollection ×1, Collection ×1, Column ×1, …UsageEvent → DateTimeImmutable ×1, Column ×1, Entity ×1, …Kernel → LoaderInterface ×1, Kernel ×1, false ×1внеш.CommandEntity

Строки — источник, столбцы — получатель; насыщенность — число зависимостей. Классы отсортированы по неймспейсам: слои подписаны на диагонали, жирные линии их разделяют; жёлтый столбец «внеш.» — исходящие связи к типам вне решения (DTO времени, коллекции). Наведите на закрашенную ячейку — кто на кого и сколько раз.

Связанность классов: Ce, Ca, нестабильность I

Ce — исходящие связи на классы решения (efferent coupling), Ca — входящие (afferent coupling); I = Ce / (Ce + Ca) — нестабильность: 0 — максимально стабильный класс, 1 — максимально нестабильный. Здоровая слоистость выглядит так: I близка к 1 у console-команд (точки входа, обязаны меняться часто) и к 0 у примитивов домена (Decimal, Timestamp, enum-статусы): нестабильное должно зависеть от стабильного, не наоборот. Классы без внутренних связей не показаны.

КлассCeCaI (0…1)
BillingRateCommand201.00
BillingReportCommand101.00
PricesImportCommand301.00
UsageImportCommand301.00
Price230.40
UsageEvent230.40
Provider250.29
Model150.17

Циклические зависимости

Компоненты сильной связности графа внутренних зависимостей: классы, где от каждого достижим каждый. Каждый цикл — кандидат на разрыв: вынести интерфейс или событие (принцип ациклических зависимостей Мартина, Acyclic Dependencies Principle).

Классы по WMC (топ-10)

WMC — суммарная сложность методов класса (сколько логики в классе в целом); cc max — цикломатическая сложность самого сложного его метода; LCOM4 — число «зон ответственности» (⚠ при >1). Имя файла — ссылка на код в git (работает после коммита артефактов).

КлассLOCметодовWMCcc maxLCOM4
BillingRateCommand132623 6⚠ 4
Provider1251620 2⚠ 7
PricesImportCommand119317⚠ 15⚠ 2
UsageEvent1241313 1⚠ 11
Price1211212 1⚠ 11
UsageImportCommand98312 10⚠ 2
BillingReportCommand103310 8⚠ 2
Model4866 1⚠ 3
Kernel2335 3 1

Методы-нарушители порогов (cc > 10 или LOC > 50)

МетодCCLOC
PricesImportCommand::execute15102
UsageImportCommand::execute1081
BillingReportCommand::execute885

Полные данные — metrics-raw/collector.json.

Отчёт по метрикам качества кода: metrics.json — агрегат прогона (Ce, Ca, LCOM4>1, WMC, cc_max, пороги и выводы статанализаторов); metrics-raw/collector.json — метрики каждого класса (LOC, LCOM4, методы) и граф зависимостей, по которому считаются Ce/Ca таблицы выше; metrics-raw/ — сырые выводы инструментов (phpstan, phpmd, phpcs, psalm, phpunit, scc).

Ярус 3 · ревью: изолированная pi-сессия glm-5.3-flash

Модельная проверка решения: отдельная pi-сессия (zai/glm-5.3-flash, thinking low) оценивает по рубрике обе оси. На вход — TASK.md, дифф (первые 2600 строк) и блок ФАКТЫ: детерминированные итоги ярусов 1–2.

1 из 4ось A «код и архитектура»
1 из 4ось B «процесс и коммуникация»
26 счистое время ревью
40.7Kтокенов (вход 40.1K, $0.0063)

Вход ревьюера: блок ФАКТЫ

Чекер: обязательных 2/11, бонус 0/2
  fail prices_import: Модель не найдена: prism/lumen-8

  fail usage_import: Провайдер не найден: prism (строка 1)

  fail rate_counts: в stdout нет 'RATED=<n> UNRATED=<m>': 'Ошибка тарификации: An exception occurred while executing a query: SQLSTATE[42703
  fail unrated_stderr: ожидались ['UNRATED prism/h13 2026-07-31T23:00:00Z no_price'], получено []
  fail report_base: код 7: es not exist  
  LINE 1: ...u0_.provider_request_id AS provider_request_id_1, u0_.user A...   
                  
  fail import_duplicates: Провайдер не найден: prism (строка 1)

  fail rate_after_duplicates: stdout: 'Ошибка тарификации: An exception occurred while executing a query: SQLSTATE[42703]: Undefined column: 7 ERROR: 
  fail report_duplicates: код 7: es not exist  
  LINE 1: ...u0_.provider_request_id AS provider_request_id_1, u0_.user A...   
                  
  fail artifacts_present: отсутствуют/пусты: COMMIT_MESSAGE.md, PR_DESCRIPTION.md
Метрики: phpcs 21, psalm 191, phpstan 33, loc 779
AST: cc_max 15, lcom4>1: 8, превышения порогов {'method_cc_over_10': 1, 'method_loc_over_50': 3, 'class_loc_over_300': 0, 'class_wmc_over_50': 0, 'class_lcom4_over_1': 8}

Обоснование

ревьюер яруса 3
Обязательная часть фактически не работает: чекер 2/11. Импорт цен падает ('Модель не найдена: prism/lumen-8') — findOneBy по только что persist-нутым моделям без flush; usage-импорт падает следом ('Провайдер не найден: prism'); отчёт ломается на зарезервированном слове user (SQLSTATE[42703], колонка user без кавычек в UsageEvent.php); UNRATED печатается с VERBOSITY_VERBOSE (BillingRateCommand.php:48) и в stdout вместо stderr — не виден по умолчанию. Деньги на bcmath (хорошо, scale 16, одно округление), схема миграцией есть, идемпотентность через уникальные ключи задумана, но bcRound самодельный и сомнительный. Домен не отделён от команд — вся логика в Command-классах; symfony/serializer добавлен в composer.json, но в коде не используется (мёртвая зависимость); mtimes сущностей без концевой строки. Ось B: нет COMMIT_MESSAGE.md и PR_DESCRIPTION.md (fail artifacts_present), приёмка из TASK.md явно не прогонялась — шаги 3–4 падают на первом же запуске, статанализ (phpstan 33, psalm 191) тоже не смотрелся. След хаотичный, самопроверок нет.

Артефакты: review-zcode.md · tier3.json

Ярус 4 · судья: слепое второе мнение

Та же модель судьи (zai/glm-5.3-flash, thinking low), но вслепую: только TASK.md и дифф, без фактов чекера и метрик. Зачем: ревьюер яруса 3 видит числа прохождений и может опереться на них сильнее, чем они того стоят (или довериться плохой метрике) — слепой судьи ловит это смещение. Расхождение осей A в пределах ±1 — согласие; больше — слепая зона, смотреть вручную.

2 из 4ось A «код и архитектура», вслепую
-1расхождение осей A: ярус 3 − ярус 4
33 счистое время судьи
40.3Kтокенов (вход 39.5K, $0.0063)
заметка судьи
Домен смоделирован сущностями (Provider/Model/Price/UsageEvent), деньги только в bcmath/decimal, дедуп и выбор цены по valid_from есть, окно через полночь учтено. Но слои не разделены — вся тарификация внутри команды, объектного сервиса нет. Критично: new \BCMath() — несуществующий класс (должен быть BcMath\Number или процедурный API), что ставит работоспособность под сомнение; UNRATED-строки пишутся с VERBOSITY_VERBOSE (по умолчанию не выводятся), ts форматируется как 'c' (+00:00) вместо 'Z'. Тестов нет, бонуса нет.

Цитаты-доказательства из диффа:

Артефакты: judge-glm.md · tier4.json