Подключение ИИ-агента к разработке 1С: по шагам
Обработку «Почему не закрывается месяц» я выложил на Инфостарт 30 октября. Её код от первой до последней строки написал ИИ-агент. Сейчас у меня для этого целый конвейер, но его основа простая: одна папка, одна копия базы и несколько скриптов. В статье я разбираю её по шагам: зачем нужен каждый, команда или фрагмент и где легко споткнуться. В конце коротко о том, что выросло поверх, на каких ошибках я это понял и сколько вышло по деньгам и времени.
Обработка работает в пяти типовых конфигурациях: Управление торговлей (УТ 11), Комплексная автоматизация (КА 2), ERP 2 («1С:ERP Управление предприятием»), Бухгалтерия предприятия (БП 3.0) и Управление нашей фирмой (УНФ 3.0). Эти сокращения дальше без расшифровки.

Что будет в итоге: агент правит исходники, одной командой собирает их в копию базы, прогоняет проверки кода, тесты и сценарии форм и по результату сам понимает, что сломал. Вам понадобятся: Windows с платформой 1С, файловая копия тестовой базы (не рабочей), подписка или ключ API. Про деньги: что считать расходом и как его мерить — в прошлой статье.
Я работаю в Claude Code, но шаги будут похожи в любой агентской системе и на любой модели.
Шаг 1. Поставьте агента: Claude Code или любой другой
Зачем. Чат-бот пишет код в окно, а вы переносите его в конфигуратор. Агент работает в папке с файлами: читает исходники, правит их и запускает команды. Поэтому остальные шаги нужны, чтобы у агента были файлы, которые можно читать, и команды, которыми можно проверять.
Что сделать. Установите агента по инструкции разработчика, создайте пустую папку проекта (у меня на каждую обработку своя), откройте в ней терминал и запустите агента. В Claude Code это команда claude.
Где легко споткнуться.
- Запускайте агента в папке проекта, а не в корне диска и не в папке с рабочими базами: всё, что лежит ниже, он может прочитать и изменить.
- Расход считается по токенам, и самый большой его кусок — перечитывание накопленного контекста. Поэтому длинную задачу лучше делить на короткие сессии, чем вести одну на целый день.
Шаг 2. Выгрузка в файлы
Зачем. Агент не умеет читать конфигурацию внутри базы, зато хорошо читает текст. Выгрузка в файлы превращает конфигурацию или обработку в дерево папок с модулями .bsl и XML: по ним агент ищет, читает и правит.
Конфигуратор выгружает без окон, итог пишет в файл журнала. Для внешней обработки:
& "$env:V8_EXE" DESIGNER /F "D:\bases\demo-copy" /N "$env:V8_USER" /DisableStartupDialogs /DisableStartupMessages `
/DumpExternalDataProcessorOrReportToFiles "D:\work\src\Обработка.xml" "D:\work\Обработка.epf" `
/Out "D:\work\dump.log" | Out-Null
"Код выгрузки: $LASTEXITCODE"; Get-Content "D:\work\dump.log"
Для конфигурации или расширения вместо этой строки ключ /DumpConfigToFiles "D:\work\src" (для расширения добавьте -Extension <имя>). V8_EXE — путь к 1cv8.exe нужной платформы, V8_USER — пользователь базы (если у него есть пароль, добавьте /P).
Сразу после выгрузки сделайте в папке git init и первый коммит (для коммита в git должны быть заданы user.name и user.email): тогда каждая правка агента видна в git diff, а плохую правку можно откатить одной командой.
Где легко споткнуться.
1cv8.exe— оконное приложение, и оператор&его не ждёт. Без| Out-Nullв конце строки PowerShell идёт дальше через доли секунды: журнала ещё нет, а$LASTEXITCODEпустой. С| Out-Nullкоманда ждёт конфигуратор, и код возврата честный: 0 при успехе, 1 при ошибке.- Пользователь базы. В демобазах есть пользователи, и без
/Nконфигуратор пишет в журнал «Пользователь ИБ не идентифицирован» и ничего не выгружает. - Первый аргумент — путь к корневому файлу, а не каталог. С путём
src\Обработка.xmlвыгрузка ложится предсказуемо:src\Обработка.xmlи папка рядом с ним, каталог создаётся сам. Если указать каталог, которого ещё нет, конфигуратор примет его имя за имя корневого файла: рядом ляжетsrc.xml, а вsrcокажутся только формы и модули, без корневого файла. Формат по умолчанию иерархический, ключ-Formatне нужен. - Формат выгрузки привязан к платформе. У меня платформы 8.3.20, 8.3.24 и 8.3.27 пишут и читают форматы 2.13, 2.17 и 2.20. Эталон УТ 11.5, выгруженный на 8.3.27, платформа 8.3.24 не прочитала: проверка на этой базе упала. Выгружайте и собирайте одной версией, а если баз несколько, начинайте с самой старой.
- Типовая конфигурация — это тысячи модулей по несколько тысяч строк. Если разрешить агенту читать их большими кусками, контекст забивается за минуты. Положите выгрузку эталона отдельно, только для чтения, и ограничьте чтение (шаг 3).
- Не выгружайте и не отдавайте агенту рабочую базу с данными заказчика: для работы нужна конфигурация, данные в ней не нужны.
Шаг 3. Файл правил агента
Зачем. Агент ничего не помнит между сессиями. Файл CLAUDE.md (в других системах он называется иначе, например AGENTS.md) читается при каждом запуске, поэтому в нём стоит то, что вы иначе повторяли бы в каждом чате: чем проверять, чего не делать, когда остановиться.
Вот сжатая версия моих рабочих правил (полный набор я не публикую):
# Правила для агента
Пиши по-русски. Работай только в этой папке.
## Инструменты
- Сборка — `.\build.ps1`, статика — `.\lint.ps1`, тесты — `.\test.ps1`.
Конфигуратор напрямую не запускай.
- Платформу сверяй по справке (MCP `1c-syntax`), не по памяти.
- Каталог `reference\` только читай, кусками не больше 200 строк.
- Работай в копии базы. Эталонную базу не меняй.
## Порядок
1. Правка кода в `src\`.
2. `.\lint.ps1`: замечания исправь до нуля.
3. `.\build.ps1`, затем `.\test.ps1`. Красный тест — причину бери из вывода.
## Нельзя
- Удалять файлы.
- Утверждать про платформу то, чего не проверил запуском или справкой.
- Одна и та же ошибка дважды — остановись и напиши, что решить человеку.
Где легко споткнуться.
- Правило «одна и та же ошибка дважды — остановись» нужно с первого дня. Без него агент может много раз пробовать одно и то же, и вы платите за каждую попытку.
- Правила работают, пока агент их читает. На длинной сессии он может их «забыть»: если видите, что он обходит скрипт и лезет в конфигуратор напрямую, напомните или начните новую сессию.
- Запреты я проверяю не словами, а хуком: так называется скрипт, который запускается перед каждой командой агента и может её отклонить. Так у меня закрыты удаление файлов и чтение больших кусков эталона. Но для первого вечера хватит строк в правилах.
Шаг 4. Проверка кода до запуска базы
Зачем. Это самые дешёвые проверки: они идут секунды, не требуют запуска 1С и не меняют данных. Агент получает обратную связь раньше, чем соберёт обработку и потратит минуты на прогон. У меня три слоя.
BSL Language Server. BSL Language Server (BSL LS) — анализатор кода на встроенном языке 1С BSL. Он находит неиспользуемые переменные, нарушения стандартов, подозрительные конструкции. Запуск (lint.ps1):
$env:JAVA_TOOL_OPTIONS = "-Dfile.encoding=UTF-8"
New-Item -ItemType Directory -Force lint | Out-Null
& "$env:BSLLS_EXE" analyze -s src -o lint -r json -c bsl-ls.json -q
$r = Get-Content lint\bsl-json.json -Raw | ConvertFrom-Json
"Замечаний: " + ($r.fileinfos.diagnostics | Measure-Object).Count
$r.fileinfos | ForEach-Object { $p = $_.path; $_.diagnostics | ForEach-Object {
"$p`:$($_.range.start.line + 1) $($_.code): $($_.message)" } }
Файл настроек bsl-ls.json может быть совсем коротким: { "language": "ru", "diagnostics": { "mode": "all" } }.
Стандарты разработки. Замечание BSL LS почти всегда соответствует номеру стандарта 1С. У меня к этому добавлен собственный линтер: запросы, имена платформы, печатные формы. Для начала достаточно, чтобы агент мог открыть текст стандарта по номеру: положите каталог стандартов (открытый репозиторий v8std) рядом с проектом и напишите об этом в правилах.
Справка платформы. Агент может выдумать метод, которого нет, или вызвать серверный метод на клиенте. Это проверяется по справке той версии платформы, на которой вы работаете. У меня для этого свой MCP-сервер (MCP — Model Context Protocol, протокол подключения инструментов к агенту): он отдаёт карточку метода или типа, то есть сигнатуру, параметры, где можно вызывать (клиент, сервер) и версию. Подключение к Claude Code — одна команда, если сервер уже запущен:
claude mcp add --transport http 1c-syntax http://127.0.0.1:8000/mcp
Проверить подключение можно командой claude mcp list: у сервера должно стоять «Connected».
Над справкой у меня стоит ещё одна проверка: ссылки на объекты конфигурации (реквизиты, методы типовой) сверяются с индексом выгрузки нужного релиза, и опечатка в имени ловится за секунды.
Где легко споткнуться.
- Каталог отчёта создавайте сами. BSL LS 1.0.7 его не создаёт: Java падает, а скрипт без второй строки печатает «Замечаний: 0». Код выхода у скрипта всегда 0, поэтому агент должен смотреть на число замечаний, а не на код.
- Кодировка. Без UTF-8 для Java русские сообщения превращаются в кракозябры, и агент читает мусор.
- Шум Java в начале вывода. Ключ
-qне глушит предупреждения Java («Picked up JAVA_TOOL_OPTIONS», WARNING): это не замечания, их надо пропустить до строки «Замечаний». Путь к файлу в замечании печатается какfile:///…. - Режим
allне выключается значениемfalse. На версии 1.0.7 правило, которое включено режимомall, нельзя отключить, записав емуfalseв параметрах. Если правило не нужно, настраивайте режим, а не отдельные значения. - Не стартуйте со всех правил на чужом коде. В моей обработке один из кругов начался с 418 замечаний статики. Начните с проверки только вашего нового кода и расширяйте набор по мере чистки.
Шаг 5. Сборка и загрузка в базу одной командой
Зачем. Агент проверяет себя, только если может запустить результат. Сборка и загрузка должны быть одной командой с понятным итогом: получилось или нет и почему. Тогда агент не придумывает свою, а вы не рискуете, что он вызовет конфигуратор с опасным ключом.
Рабочая версия для внешней обработки у меня такая (build.ps1):
$epf = "$PSScriptRoot\out\Обработка.epf"; $log = "$PSScriptRoot\build.log"
$res = "$PSScriptRoot\build.res"; $t0 = Get-Date
$a = @("DESIGNER", "/F", $env:V8_BUILD_BASE, "/N", "`"$env:V8_USER`"",
"/DisableStartupDialogs", "/DisableStartupMessages",
"/LoadExternalDataProcessorOrReportFromFiles", "$PSScriptRoot\src\Обработка.xml", $epf,
"/Out", $log, "/DumpResult", $res)
$p = Start-Process $env:V8_EXE -ArgumentList $a -Wait -PassThru
Get-Content $log
if (-not (Test-Path $epf) -or (Get-Item $epf).LastWriteTime -lt $t0) {
throw "Файл обработки не создан: смотрите build.log" }
"Собрано: $epf, код возврата " + (Get-Content $res)
Скрипт берёт корневой файл src\Обработка.xml, который положила выгрузка из шага 2. Если исходники выгружены в каталог, корневой файл называется по имени объекта: тогда вместо пути подставьте (Get-ChildItem "$PSScriptRoot\src\*.xml").FullName, в корне выгрузки он один.
Для конфигурации или расширения вместо сборки — две команды подряд в копии базы: /LoadConfigFromFiles "<каталог>", затем /UpdateDBCfg (для расширения с ключом -Extension <имя>). Журнал /Out у этих команд бывает пустым даже при успехе, итог смотрите по коду возврата или файлу /DumpResult.
Где легко споткнуться.
- Пользователь базы. Если в базе есть пользователи, без
/Nконфигуратор пишет «Пользователь ИБ не идентифицирован» и ничего не собирает.Start-Processне берёт аргументы в кавычки сам, поэтому имя пользователя и любой путь с пробелом оберните в кавычки, как в скрипте. - Сборочная база — с той же конфигурацией. Формы обработки ссылаются на типы конфигурации, и на пустой базе сборка падает с исключением XDTO на форме.
1cv8.exeв PowerShell не ждут оператором&: окно запускается и скрипт идёт дальше. НуженStart-Process -Wait, иначе тесты запустятся раньше, чем закончится сборка.- Код возврата «0» ничего не доказывает. Конфигуратор не ловит битый модуль при сборке обработки и всё равно возвращает ноль. Поэтому у меня после сборки обязательна проба: объект создаётся в базе, и только это показывает ошибку в модуле. В вашем минимуме эту пробу делает первый шаг тестов (шаг 6).
- Проверяйте, что файл свежий. Без этого агент примет за результат старый
.epfот прошлого запуска. Журнал при ошибке не всегда называет причину: если корневого файла нет, вbuild.logтолько строки «Загрузка… Корневой файл…», а вbuild.resединица. - Загрузка и обновление базы — две разные команды. Для конфигурации без
/UpdateDBCfgновый код не заработает, хотя загрузка «прошла». - Работайте только с копией. Путь к базе задан переменной окружения, а не аргументом: агенту труднее подставить чужую базу. Эталонную базу никто не меняет, на каждую проверку из неё делается свежая копия.
- Параметр
/Outобязателен: без журнала агент видит только «команда завершилась».
Шаг 6. Тесты YAxUnit на копии демобазы
Зачем. Линтер видит форму, а не смысл. Тест проверяет поведение, и только он скажет, что функция вернула не то. YAxUnit — фреймворк модульных тестов для 1С, он ставится в базу как расширение. Для внешней обработки тест подключает собранный .epf и вызывает его методы.
Подготовка. Установите расширение YAxUnit в копию демобазы. У расширения надо снять флажки «Безопасный режим» и «Защита от опасных действий»: иначе модуль тестов не скомпилируется. Расширение с самими тестами (оно у каждой обработки своё) тоже ставится в копию. У пользователя, под которым идут тесты, снимите «Предупреждать об опасных действиях»: иначе при открытии файла обработки клиент покажет «Предупреждение безопасности» и будет ждать человека без тайм-аута. Тест открывает собранный файл из каталога временных файлов: служебная функция Обработка() в модуле тестов делает ВнешниеОбработки.Создать(КаталогВременныхФайлов() + "Обработка.epf", Истина). Поэтому test.ps1 кладёт файл туда под тем же именем: имя в Copy-Item и в тесте должно совпадать.
Вот реальный тест из моей обработки. Она находит причину незакрытого месяца, и одна из причин в том, что в базе заглушена проверка отрицательных остатков. У каждой типовой своя «заглушка», поэтому тест устроен по ветвям (ветку УТ я здесь опустил):
Процедура ЗаглушеннаяПроверка() Экспорт
Механизм = Механизм();
Если Механизм = "БП" Тогда
ИмяКонстанты = "ОтключитьКонтрольОтрицательныхОстатков";
ОпасноеЗначение = Истина;
Ключ = "РазрешеныОтрицательныеОстатки";
Иначе
ИмяКонстанты = "КонтролироватьОстаткиПриПроведении";
ОпасноеЗначение = Ложь;
Ключ = "УНФ.КонтрольОстатков";
КонецЕсли;
Было = Константы[ИмяКонстанты].Получить();
ЗаписатьКонстанту(ИмяКонстанты, ОпасноеЗначение);
Результат = Обработка().Проверить(Новый Структура("Месяц, Блоки", МесяцПроверки(), "заглушки"));
ЗаписатьКонстанту(ИмяКонстанты, Было);
ЮТест.ОжидаетЧто(КарточкиСКлючом(Результат, Ключ).Количество(), Ключ).Больше(0);
ЮТест.ОжидаетЧто(Обработка().ЛентаHTML(Результат)).Содержит("blk-muted");
КонецПроцедуры
Тест меняет настройку базы, запускает проверку, возвращает настройку и требует, чтобы обработка эту заглушку заметила и показала в ленте. Поэтому тест нужно запускать только на копии.
Запуск. Тесты запускает клиент 1С с параметром RunUnitTests. Настройки лежат в JSON:
{
"reportFormat": "jUnit",
"reportPath": "junit.xml",
"closeAfterTests": true,
"exitCode": "exitcode.txt",
"logging": { "file": "yaxunit.log", "console": false, "level": "info" },
"filter": { "extensions": ["ТестыОбработки"] }
}
# test.ps1
Set-Location $PSScriptRoot
Copy-Item "$PSScriptRoot\out\Обработка.epf" "$env:TEMP\Обработка.epf"
$cfg = "$PSScriptRoot\xUnitParams.json"
$a = @("ENTERPRISE", "/F", "`"$env:V8_BASE_COPY`"", "/N", "`"$env:V8_USER`"", "/DisableStartupDialogs",
"/DisableStartupMessages", "/L", "ru", "/VLru_RU", "/C", "`"RunUnitTests=$cfg`"")
Start-Process $env:V8_EXE -ArgumentList $a -Wait
if (-not (Test-Path "$PSScriptRoot\exitcode.txt")) { "Тесты не дошли до конца: смотрите yaxunit.log"; exit 2 }
$code = Get-Content "$PSScriptRoot\exitcode.txt"
"Код выхода тестов: $code"
exit [int]$code
Где легко споткнуться.
- Язык клиента. Клиент 8.3.20 без
/L ruзапустился по-английски, и YAxUnit не нашёл ни одного теста и не записал журнал. Пустой отчёт выглядел как «всё в порядке». - Относительные пути в JSON считаются от текущей папки. YAxUnit пишет
junit.xml,exitcode.txtи журнал туда, откуда запущен клиент, а не рядом с JSON. Поэтомуtest.ps1первой строкой переходит в свою папку. - Без пользователя клиент выходит молча. Без
/Nв базе с пользователями нет ни отчёта, ни кода выхода, а скрипт завершается с кодом 0. - Пустой результат — это не зелёный результат. Если
exitcode.txtнет, скрипт возвращает 2 (просто[int]от пустого значения дал бы 0, то есть «успех»). Полный итог читайте поjunit.xml: тестов больше нуля, упавших ноль, пропущены не все. Тайм-аута у скрипта нет: зависший тест держит его, пока вы не снимете процесс. - Модальное окно при старте. Новые релизы УТ 11.6 и ERP 2.6 на платформе 8.3.27 показывают окно «Переход на новую версию платформы», и клиент без человека зависает. Для них у меня платформа 8.5.1: берите ту, которую рекомендует конфигурация.
- Тесты меняют данные. Поэтому только копия базы, а перед каждым прогоном свежая копия из эталона: прогон, снятый посередине, оставляет данные, на которых следующий падает. У меня она делается на каждую проверку и удаляется после неё.
- Зелёные тесты ничего не доказывают, если агент написал тест под свой же код. Попросите агента испортить код (подменить условие) и убедитесь, что тест покраснел. У меня этим занят отдельный этап, он описан ниже.
- Зелёные тесты на одной базе не проверяют ветки других типовых. Если у обработки свой код под каждую конфигурацию, на УТ ветка БП просто не выполняется. Смотрите покрытие: какие методы на этой базе не выполнились ни разу (пример в разборе ошибок ниже).
Шаг 7. Сценарные тесты форм
Зачем. YAxUnit проверяет серверные функции, но не форму: не нажимает кнопки и не вводит текст. В одной из моих обработок поле поиска затирало буквы при вводе, и этого не видел ни один тест. Платформа даёт для этого штатный режим автоматизированного тестирования: тест-менеджер (ключ /TESTMANAGER) управляет тест-клиентом (/TESTCLIENT), то есть открывает формы и жмёт кнопки, как пользователь. На этом же режиме работает Vanessa Automation.
Vanessa я пробовал в двух вариантах. Из командной строки она прогнала мои сценарии без участия человека, но два важных для меня места закрывала хуже: затирание букв в поле поиска не ловит, потому что вводит текст целиком, а нажатие ссылки в поле HTML-документа давало зелёный шаг, даже когда ссылки на странице не было. У неё есть и MCP-сервер, через который агент сам управляет формой. Он удобный, но тяжёлый: 48 инструментов, и одно их описание занимает около 100 тысяч символов. По нашей оценке, это 30–40 тысяч токенов в контексте каждой сессии агента ещё до первого вызова, и платить за них пришлось бы на каждом шаге. Поэтому я сделал свой лёгкий тест-менеджер: агент вызывает его обычными командами, и описание инструментов в контексте не висит. Из Vanessa я взял идею шагов ожидания.
Сценарий у меня записан на языке действий в карточке задачи. Вот реальный сценарий: ввести месяц, нажать «Проверить», дождаться, пока кнопка снова станет доступной, и убедиться, что сводка и лента заполнены:
ui_scenarios:
- name: Проверка и лента
steps:
- open
- type: {element: Месяц, text: "Октябрь 2025"}
- click: КнопкаПроверить
- expect: {element: КнопкаПроверить, enabled: true, wait: 180}
- expect: {element: Сводка, filled: true}
- expect: {element: Лента, filled: true}
- click: {element: Лента, html_link: "#blk-minus"}
- shot
Ядро переводит такой сценарий в задание тест-менеджеру. Тест-клиент и менеджер идут двумя сессиями тонкого клиента: клиент открывает форму и держит её, менеджер выполняет шаги, а ядро снимает окно формы после провального шага и шага shot. Если вы начинаете с нуля, проще взять Vanessa Automation: она запускается из командной строки без участия человека, а отчёт получается сразу в нескольких форматах:
1cv8c ENTERPRISE /F mgr-base /N VA /TESTMANAGER /Execute vanessa-automation-single.epf `
/C"StartFeaturePlayer;QuietInstallVanessaExt;DisableFirstRunHelper;VAParams=<VAParams.json>"
Где легко споткнуться.
&не ждёт и клиента 1С. Добавьте| Out-Nullили запускайте черезStart-Process -Wait, а итог берите из отчётов Vanessa (junit), а не из кода возврата. Путиmgr-baseиvanessa-automation-single.epfв строке относительные: запускайте из папки стенда.- Менеджер работает в своей пустой базе, а тестируемая форма открывается в копии. Пользователь менеджера должен быть без предупреждений об опасных действиях, иначе
/Executeостановится на модальном окне безопасности. - Модальные окна. Если после шага платформа показала окно «1С:Предприятие» с ошибкой, дальше сценарий не идёт: это исключение в коде формы или запроса. Такое окно считается дефектом, поэтому делайте снимок после каждого провального шага.
- Долгие операции и таблицы. Переход к строке таблицы идёт подряд от первой строки: на 250 строк с серверным вызовом в
ПриАктивизацииСтрокиу меня вышло 17 секунд. Для таких мест нужен отдельный предел ожидания, а не общий. - Сценарии медленнее тестов. Это минуты на прогон, не секунды, поэтому запускайте их, когда статика и YAxUnit уже зелёные.
Что получилось
Теперь в правилах агента описан цикл: lint.ps1, build.ps1, test.ps1, затем сценарии форм. Задачу формулируете словами («добавь функцию, возвращающую месяц по умолчанию, и тест»), агент пишет код, сам запускает цикл и приходит с зелёным результатом либо с конкретной ошибкой. Вы проверяете git diff и результаты, а не переписываете код.
На этом минимуме можно жить долго. Дальше о том, что вырастает, когда задач и баз становится много.
Что у меня дальше

Ферма демобаз. На нашем сервере стоят 12 демобаз: УТ 11.5 трёх релизов и 11.6, КА 2.5 двух релизов, ERP 2.5 и 2.6, БП 3.0, УНФ 3.0, Бухгалтерия для Казахстана и Розница, на платформах 8.3.24, 8.3.27 и 8.5.1. Обработка должна работать в пяти типовых (УТ 11, КА 2, ERP 2, БП 3.0 и УНФ 3.0), и теперь шаги 5–7 повторяются на каждой базе. Эталонную демобазу никто не меняет, на каждую проверку из неё делается копия.
Конвейер. Те же шаги выросли в цепочку, которую показывает схема. Код пишет Opus, ревью и приёмку отдал Sonnet: он дешевле. Сборку, загрузку, тесты и снимки экрана делает ядро на Python, без модели. Решает, что задача готова, тоже не агент: порядок этапов задаёт ядро. Постановку я веду вместе с моделью: Sonnet или Opus, по сложности задачи, чаще Sonnet; допрос могут вести обе. Агент задаёт мне вопросы, к каждому с рекомендацией, например «Месяц по умолчанию: рекомендую прошлый, закрывают обычно его», а потом собирает карточку задачи. Пока я её не подтвердил, кода нет.
Что проверяется после правки. Порядок такой, от дешёвого к дорогому: описание по схеме; ссылки на объекты типовой по индексу релиза; свой линтер по стандартам; BSL LS; компиляция в базе; прогон на копии и тесты YAxUnit; открытие каждой формы и сценарии; ревью кода отдельным агентом в роли ведущего разработчика заказчика. Отдельно идёт порча кода: агент на Opus намеренно ломает код (например, подменяет условие), а ядро проверяет, краснеют ли тесты. Если тесты остаются зелёными, в них дыра. Правило о ПРЕДСТАВЛЕНИЕ() сейчас уточняется по стандарту 412 и статье ИТС, вместе с быстрой проверкой собранных запросов на каждой базе.
Три ошибки с разных типовых
Три случая из моей обработки: что случилось, почему, как нашли и что сделали.
1. «Неверные параметры "+"» на БП и УНФ.
- *Что случилось.* На первом прогоне по базам запрос сумм без количества на БП 3.0 и УНФ 3.0 падал с ошибкой.
- *Почему.* Агент склеил представления прямо в запросе:
ПРЕДСТАВЛЕНИЕ(Остатки.Счет) + ": " + ПРЕДСТАВЛЕНИЕ(Остатки.Субконто1). СтрокуПРЕДСТАВЛЕНИЕ()собирает платформа уже при чтении результата, в СУБД её нет, поэтому в запросе её нельзя ни склеивать, ни сортировать (статья ИТС о поле Представление). А агент запутался в стандартах: моё правило о представлениях опиралось на стандарт 449, а он только про вывод в табличный документ. ПроПРЕДСТАВЛЕНИЕ()внутри запроса стандарт молчит, и агент достроил остальное сам. - *Как нашли.* Основная база была УТ 11.5, и тесты на ней были зелёными. Но код БП и УНФ на УТ не выполняется вообще: отчёт покрытия показывал эти методы как «без выполненных строк». Ошибку показал первый же прогон на копиях БП и УНФ.
- *Как исправили.* Каждый разрез вынесли в отдельную колонку запроса, а склеивать стали в коде, после выгрузки. На следующий день в мой линтер добавилось правило:
ПРЕДСТАВЛЕНИЕ()в запросе со строкой не складывается.
2. Организация без движений на КА 2.5.
- *Что случилось.* Тест на КА ждал два минуса, а обработка нашла ноль.
- *Почему.* Проверялись только организации с движениями в проверяемом месяце. У одной организации в этом месяце движений нет, а минус от распроведённого поступления прошлого года всё равно держит закрытие.
- *Как нашли.* Прогон на всех базах: на КА 2.5 тест ждал два минуса и получил ноль.
- *Как исправили.* В список организаций добавили те, у кого на конец месяца есть отрицательный остаток (по регистрам «Товары организаций» в УТ, КА, ERP и «Запасы» в УНФ).
3. УПОРЯДОЧИТЬ ПО в запросе с РАЗЛИЧНЫЕ: ошибка после замечания ревьюера.
- *Что случилось.* Агент-ревьюер сослался на стандарт 412 и потребовал упорядочить результаты запросов, чтобы карточки не меняли порядок между запусками. Агент-разработчик добавил
УПОРЯДОЧИТЬ ПОпо полям «вид запасов» и «номер таможенной декларации», которые в этом запросе были представлениями,ПРЕДСТАВЛЕНИЕ(...). Пакет проверки минусов упал целиком: в УТ, КА и ERP покраснели 7 тестов, а в сценарии формы выскочило модальное окно «1С:Предприятие». - *Почему.* Здесь в стандартах запутался ревьюер. Стандарт 412 просит сортировать результат для пользователя по строковым представлениям, но способа не называет и предлагает поля примитивного типа. Ревьюер потребовал
УПОРЯДОЧИТЬ ПОпоПРЕДСТАВЛЕНИЕ(), а платформа такое не пускает, по той же причине, что в ошибке 1. Упорядочить по самим ссылкам тоже нельзя: запрос сРАЗЛИЧНЫЕ, а в нём порядок можно задавать только по выбранным полям. - *Как нашли.* После правки порядка запускалась только статика, а ни BSL LS, ни мой линтер текст запроса, собранный из кусков, не разбирают. Ошибку поймала ферма на следующем круге: сначала красные тесты, затем сценарий формы показал то же исключение окном.
- *Как исправили.*
УПОРЯДОЧИТЬ ПОиз запроса убрали, таблицу сортируют в коде после выгрузки, а причину записали комментарием рядом.
Общее у трёх случаев: агент писал в запросах конструкции, которых язык запросов не допускает, или логику, верную только на данных одной базы. Проверки на одной базе этого не ловили. Текст запроса — строка: статика его почти не видит, и ошибка появляется только при выполнении на нужной базе. Поэтому прогон нужен на всех базах и до выпуска, в том числе после правок по замечаниям ревьюера. А каждую такую ошибку стоит превращать в правило линтера.
Автоматика и ручная проверка
Эта обработка была исследовательской: нужно было разобраться, как закрытие месяца устроено в типовых конфигурациях, какие в нём бывают ошибки и как их понятно показать пользователю. Обработка сложная, конфигураций пять, баз много, и ошибки появляются именно на этом стыке.
Пока процессы и сценарии не были описаны детально, автоматика покрывала не всё. Три дефекта по существу закрытия месяца нашёл я руками на ручной проверке: ложное «чисто» на КА, строки журнала по чужим организациям и выпавший филиал. Все они исправлены. Вывод для вас такой: пока сценарии не описаны, не прогнаны повторно и не стало ясно, что такие ошибки больше не возникают, проверяйте руками на 100 %. Потом доверяйте автоматике по описанным сценариям, и каждый найденный руками дефект превращайте в новый сценарий или тест.
Сколько это стоило и почему так вышло
Вся обработка обошлась в $277,73 по ценам API. Работаю я на подписке, так что эти деньги реально не списывались: сумма показывает, сколько ресурса ушло. За 8 календарных дней (с 22 по 30 октября) было 162 запуска агентов и 154 итерации, около 50 часов машинного времени, и ещё около 20 часов задача стояла и ждала меня. Деньги почти целиком ушли в разработку (85 %), а время в проверки на ферме, где модель не нужна: токены на них не тратятся, но часы идут.
Кругов получилось девять: задача исследовательская и сложная, баз много. Около четверти денег и треть времени съели три поломки самого конвейера, то есть дефекты его настройки, а не кода обработки:
- Тайм-аут одной базы перечёркивал результат остальных. Каждая проверка порчей шла на девяти базах. Предел на тесты YAxUnit был 15 минут: такую константу ядро получило ещё на первых задачах, а позже научилось поднимать предел по замерам прошлых прогонов. Дефект был в том, что замер работал только на основной базе, а на остальных предел так и оставался 15 минут. Тесты к тому времени разрослись с 31 до 69, и на трёх тяжёлых базах (КА 2.5, ERP 2.6 и ERP 2.5) прогон упирался в предел. Ядро считало проверку «без итога», хотя на шести других базах итог был честный, и отправляло всё сначала. В одном из кругов разведку целиком выбросили, и те же четыре порчи гонялись заново, на всех базах с нуля: 3 часа 13 минут. Дефект нашли 28 октября и на следующий день исправили: теперь у каждой базы свой предел по её замерам, с потолком, а если прогон упёрся в потолок, задача уходит мне, а не обратно агенту.
- Требовалось доказательство, которого не бывает. К каждому моему замечанию ядро требовало пару «тест красный на старом коде → зелёный на новом». Но на части замечаний красного не бывает: например, на платформе 8.3.24 ошибку нельзя воспроизвести. Задача возвращалась в разработку за доказательством, и набралось 12 возвратов.
- Базы проверялись поздно и по очереди. Тесты писались и проверялись на одной демобазе, остальные шли в конце круга. Агент возвращался и гонял по новой все базы, даже уже зелёные, а красные на других базах разработка увидеть заранее не могла.
Что поменяли. Полная проверка порчей теперь идёт один раз на версию, после правки проверяются только изменённые методы, а порча гоняется под названные тесты. Мои замечания теперь пишутся конкретно: на какой базе и в каком месте ошибка, что увидит пользователь на форме и как проверить, что она исправлена. Общих требований вроде «ни один тест не должен занимать минуты» в них нет: такое замечание нельзя проверить запуском, и задача крутится впустую. Приёмка возвращает в разработку только сбой (зависание, тайм-аут, модальное окно, красный или молча пропущенный тест). Круг теперь идёт в две ступени: сначала основная база и «горячие», то есть падавшие в этой или прошлой версии, потом все базы один раз на финальной сборке.
Эффект пока не измерен: изменения вошли в самый конец работы, и замера «до и после» нет. Моя ожидаемая цифра, круг с редкой правкой около часа вместо пяти, это оценка, а не замер. Замеры и сравнение будут на следующих итерациях: и при доработке существующих решений, и на новых задачах. Предел стоимости на версию задан в настройках конвейера, и дважды я поднимал его руками, потому что дефекты по сути были настоящими; поломки он поймать не мог, они выглядели как обычная работа.
Вывод для вас. Процесс тестирования на многих базах надо продумать и настроить заранее: какая база основная, какие гоняются на каждом круге, какой тайм-аут и что считать итогом. А сам пайплайн нужно замерять и отслеживать: журнал запусков, сколько стоил каждый возврат в разработку, где ушло время. Агент может крутить круги почти без токенов, просто гоняя скрипты туда и обратно, и тогда это видно по времени: прогоны идут очень долго. Какой-то расход всё равно будет, и он зависит от того, насколько эффективно настроено выполнение. Без замеров вы заметите круги и по счёту, и по времени, но уже после того, как их оплатили.
Если вы уже подключали агента к 1С: какого шага из семи вам не хватило больше всего? Расскажите в комментариях, как у вас устроено.
Вступайте в нашу телеграмм-группу Инфостарт
Вы можете заказать платную адаптацию этой статьи под ваши задачи на «Бирже заказов».
- 0% комиссии — оплата напрямую исполнителю;
- Исполнители любого масштаба — от отдельных специалистов до команд под проект;
- Прямой обмен контактами между заказчиком и исполнителем;
- Безопасная сделка — при необходимости;
- Рейтинги, кейсы и прозрачная система откликов.