qa.log
66 subscribers
18 photos
8 videos
45 links
Feedback -> @wlasadd
Download Telegram
qa.log
RE-usable Claude Code Skills для автотестирования Чаты уходят в прошлое, и на замену им приходят полноценные агенты со скиллами. Это вызвано в первую очередь возможностью экономии ресурсов на поддержание контекста. Создаем агента под генерацию данных для…
upd: git commit -m "Add event-streaming skill”

Добавлена логика по работе с распределенными системами и асинхронным получением данных от брокеров.

Хочется не просто вызывать метод и проверять ответ, а убедиться, что нужное событие появилось в брокере с правильными данными в правильный момент. Это retry-логика, сравнение с допуском по времени, отдельная обработка генерируемых полей.

Скилл задаёт универсальную архитектуру слоями Test → Steps → Manager → Client, паттерн checkEvent прямо в тест-классе, шаблоны createExpectedEvent и compareEvents с готовой логикой сравнения. Секции [НАСТРОИТЬ] под брокер, доменную модель, статусы.
Работает с любым стеком на JVM: Kafka, RabbitMQ, любой другой брокер. Проект на Kotlin + JUnit5, но паттерны переносятся на Java без изменений.

Доработка в репо https://github.com/wlasadd/claude-autotest-skills
👍1
Claude skills с инструкциями по прикладной работе с автоматизацией могут быть так же дополнены шаблонами по непосредственной экономии памяти.

GitHub - JuliusBrussee/caveman

- решает проблему лимитов токенов на лету.

Храним отдельные инструкции по шаблонизированию проекта + caveman скилл по оптимизации наполнения контекста. На выходе получаем агента, который не только структурировано, но и дешево воспроизводит и дополняет логику проекта.
Новая задача Valid Palindrome

ОПИСАНИЕ:
Фраза является палиндромом, если после преобразования всех заглавных букв в строчные и удаления всех неалфавитно-цифровых символов она читается одинаково как в прямом, так и в обратном направлении. К алфавитно-цифровым символам относятся буквы и цифры.

Для заданной строки s верните true, если она является палиндромом, иначе верните false.


ПРИМЕРЫ:

Input: s = "A man, a plan, a canal: Panama"
Output: true
Explanation: "amanaplanacanalpanama" is a palindrome.

Input: s = "race a car"
Output: false
Explanation: "raceacar" is not a palindrome.

Input: s = " "
Output: true
Explanation: s is an empty string "" after removing non-alphanumeric characters.
Since an empty string reads the same forward and backward, it is a palindrome.
СОБЕСЕДОВАНИЕ:

Раздел: Сериализация, десериализация
Вопрос: Популярные библиотеки и причины их выбора.
Jackson - библиотека, по умолчанию интегрированная во многие HTTP-клиенты, популярна для работы с JSON в Kotlin.

• Умеет автоматически сериализовать и десериализовать data class по именам полей
• Поддерживается в большинстве API-клиентов (Feign, RestTemplate и др.)
• Позволяет кастомизировать процесс через аннотации

Аннотации Jackson:
@JsonProperty - задаёт явное имя ключа в JSON:

data class Product(
val productId: UUID,
@JsonProperty("brandInfo")
val brand: Brand?
)
// JSON: { "brandInfo": "Nike" }


@JsonIgnore - исключает поле из сериализации и десериализации. Поле присутствует в объекте, но не попадает в JSON:

data class Product(
val productId: UUID,
@JsonIgnore
val brand: Brand?
)
// brand не попадёт в JSON


@JsonInclude - указывает какие поля включать в JSON. Удобно для отправки «чистых» запросов без лишних полей:

@JsonInclude(JsonInclude.Include.NON_NULL)
data class Pet(
val name: String,
val description: String? = null
)
// если description == null — поле не попадёт в JSON


@JsonProperty на enum - переименовывает конкретные константы в JSON:

enum class Status {
@JsonProperty("available") AVAILABLE,
@JsonProperty("pending") PENDING,
@JsonProperty("sold") SOLD
}
// JSON вернёт "available" вместо "AVAILABLE"


@JsonValue - говорит Jackson использовать значение конкретного поля для сериализации всего объекта. В отличие от @JsonProperty на константах, здесь значение берётся из поля, переданного в конструктор:

enum class Status(@JsonValue val value: String) {
AVAILABLE("available"),
PENDING("pending"),
SOLD("sold")
}
// Jackson сериализует enum как строку "available", беря значение из поля value


К популярным библиотекам относятся так же: Kotlinx Serialization, Moshi, Gson.
Вектор разработки все больше смещается с написания кода в сторону умения работать с настройками конфигов агентов.

Claude Code, Codex, Cursor и тп - успешные коммерческие продукты, которые уже успели себя зарекомендовать.

Попробуем разобраться с мультимодельными опенсорсными провайдерами, например, opencode (установка описана внутри), и настроить конфиг для него.

Что обещано:
Что такое OpenCode?
OpenCode — это агент с открытым исходным кодом, который помогает писать код в терминале, IDE или на рабочем столе.

[*] Поддержка LSP Автоматическая загрузка подходящих LSP для LLM
[*] Многосессионность Параллельный запуск нескольких агентов в рамках одного проекта
[*] Поделиться ссылкой Поделитесь ссылкой на любую сессию для справки или отладки
[*] GitHub Copilot Войдите через GitHub, чтобы использовать свою учетную запись Copilot
[*] ChatGPT Plus/Pro Войдите через OpenAI, чтобы использовать свою учетную запись ChatGPT Plus или Pro
[*] Любая модель Более 75 поставщиков LLM через Models.dev, включая локальные модели
[*] Любой редактор Доступно в виде интерфейса терминала, настольного приложения и расширения IDE


Минимальные требования:
- opencode.json - машинная конфигурация инструмента. Здесь: какие модели использовать, какие MCP-серверы подключить, какие права давать агенту, какие под-агенты создать. Это аналог settings.json в Claude Code.
- AGENTS.md - текстовые инструкции для модели на естественном языке. Это системный промпт проекта: правила кодстайла, поведение, формат ответов. Аналог CLAUDE.md.

Далее разберем каждый из файлов подробно и достаточно для первого запуска.
Блок 1. opencode.json: верхнеуровневые параметры

По ссылке расположен универсальный конфиг-шаблон, предоставляемый самим провайдером для более гибкой настройки.

Это поля на корневом уровне объекта, которые задают общее поведение инструмента до того, как дело дойдёт до моделей и агентов.


"$schema": "https://opencode.ai/config.json", // схема конфигурации
"lsp": true, // включает Language Server Protocol. opencode поднимает языковые серверы (для Kotlin/Java и т.д.) и за счёт этого «видит» ошибки компиляции, типы, определения символов.
"formatter": true, // разрешает авто-форматирование изменённых файлов через настроенные форматтеры
"default_agent": "plan", // какой из под-агентов запускается по умолчанию при старте сессии. plan - это read-only агент без права менять файлы и запускать команды.
"shell": "/bin/zsh", // какой shell использовать для bash-команд
"logLevel": "INFO", // уровень логирования самого opencode. INFO - стандартный
"share": "disabled", // запрещает шаринг сессий (выгрузку диалога в облако opencode по ссылке)
"autoupdate": "notify", // при выходе новой версии opencode только уведомляет, но не обновляется сам
"snapshot": true, // включает снапшоты состояния файлов перед изменениями, чтобы можно было откатить правки агента
Блок 2. opencode.json - providers, model, small_model, disabled_providers

Это сердце конфига: какие LLM использовать. Тут две связанные части - отключение «чужих» провайдеров и подключение своих, внутренних.

disabled_providers:

"disabled_providers": [ // opencode «из коробки» знает кучу провайдеров (Anthropic, OpenAI, Google, OpenRouter и тп. Это нужно, чтобы агент не мог случайно уйти во внешний публичный провайдер (данные не должны утекать наружу); чтобы в списке выбора моделей остались только свои, внутренние модели
"openrouter",
"opencode",
"anthropic",
"openai",
"github-copilot",
"google"
],


provider:

"provider": {
"": { // имя провайдера
"npm": "@ai-sdk/openai-compatible", // какой драйвер использовать - любой сервис с OpenAI-совместимым /v1 подключается этим драйвером
"name": "", // отображаемое имя провайдера в UI выбора
"options": {
"baseURL": "", // эндпоинт шлюза
"apiKey": "{env:YOUR_API_KEY}", // ключ не хранится в файле, а подставляется из переменной окружения. Синтаксис {env:ИМЯ} - это подстановка opencode. Так конфиг безопасно коммитить в git
"timeout": 300000, // общий таймаут запроса, 300 сек (5 мин)
"chunkTimeout": 120000 // таймаут между чанками стрима - защита от «зависания»
},
"models": { // массив моделей внутри провайдера
"": {
"name": "", // отображаемое имя
"tool_call": true, // модель умеет вызывать инструменты (без этого агент не сможет редактировать файлы/звать MCP)
"temperature": true // управление «фантазией» модели
}
}
},
"": { ... аналогично, ... }
}


model и small_model:

"model": "", // основная модель. Используется агентами по умолчанию
"small_model": "", // «дешёвая» модель для вспомогательных задач
Блок 3. opencode.json — mcp (Allure и Atlassian)

MCP (Model Context Protocol) - это способ дать агенту доступ к внешним системам через стандартизированные «серверы инструментов».

Умеет читать задачи из jira и их описание из confluence.


"mcp": {
"allure": { // TMS
"type": "remote", // уже где-то запущен, opencode просто ходит к нему по HTTP
"enabled": true,
"url": "http:…”, // адрес MCP-эндпоинта во внутренней сети
"oauth": false, // авторизация через OAuth не используется
"timeout": 30000
},
"atlassian": { // Jira, Conflueence и тп
"type": "local", // opencode сам запускает процесс на локальной машине
"enabled": true,
"command": [
"/opt/homebrew/bin/uvx",
"mcp-atlassian==0.21.1"
], // как запускать. uvx (из пакета uv, Python) скачивает и запускает пакет mcp-atlassian строго версии 0.21.1. Версия зафиксирована, чтобы поведение не менялось при апдейтах. Путь /opt/homebrew/bin/uvx - homebrew-установка на macOS
"environment": {
"CONFLUENCE_URL": "https:…, // внутренние адреса систем
"CONFLUENCE_PERSONAL_TOKEN": "{env:CONFLUENCE_TOKEN}", // токен в окружении
"JIRA_URL": "https:…”, // внутренние адреса систем
"JIRA_PERSONAL_TOKEN": "{env:JIRA_TOKEN}" // токен в окружении
},
"timeout": 30000
}
}
Блок 4. opencode.json — tools, experimental, watcher, tool_output, compaction

Это группа «технических» настроек: что агенту доступно из инструментов, как он управляет контекстом и за какими файлами следит.

tools:

"tools": {
"webfetch": false, // запрет на скачивание страниц по URL
"websearch": false // запрет на поиск в интернете
}


experimental:

"experimental": {
"batch_tool": true, // разрешает агенту вызывать несколько инструментов одним батчем (параллельно), а не строго по одному
"continue_loop_on_deny": true // при отклонении какого-либо вызова инструментом (например, запрет на правку), агент не падает и не прерывает сессию, а продолжает работу, учтя отказ
}


watcher:

"watcher": {
"ignore": [
"build/**", ".gradle/**", ".idea/**", "out/**", "target/**",
"node_modules/**", "src/test/resources/app/**",
"*.iml", "*.class", "*.jar", "*.log", "*.apk", "*.ipa", "*.app"
]
} // не засорять контекст и не реагировать на тысячи генерируемых файлов


tool_output:

"tool_output": {
"max_lines": 10000,
"max_bytes": 500000 // защита от того, чтобы гигантский вывод команды (например, лог сборки) не забил весь контекст модели
}


compaction:

"compaction": {
"auto": true, // сжимать автоматически при заполнении окна
"prune": true, // выкидывать устаревшие/ненужные куски
"tail_turns": 8, // последние 8 ходов диалога сохранять как есть, не сжимая
"preserve_recent_tokens": 24000, // гарантированно беречь ~24k токенов недавнего контекста от сжатия
"reserved": 8000 // резерв токенов под служебные нужды/ответ
}
Блок 5. opencode.json - permission (глобальные права)

Определяет, что агент может делать сам, что - только с твоего разрешения, а что - запрещено полностью.


"permission": {
"read": "allow",
"list": "allow",
"glob": "allow",
"grep": "allow",
"edit": "ask",
"bash": {
"git status": "allow",
"git diff": "allow",
"git log*": "allow",
"ls": "allow",
"pwd": "allow",
"rg *": "allow",
"find *": "ask",
"./gradlew *": "ask",
"rm *": "deny",
"kubectl delete*": "deny",
"git push*": "deny",
"git reset --hard*": "deny",
"docker system prune*": "deny"
},
"webfetch": "deny",
"websearch": "deny",
"external_directory": "ask",
"question": "allow",
"todowrite": "allow",
"atlassian_jira_*": "ask",
"atlassian_jira_get_*": "allow",
"atlassian_jira_search*": "allow"
}


Три значения:
• "allow" (без спроса),
• “ask" (спросить),
• "deny" (запретить наглухо).


Логика всего блока:
- читать — свободно;
- менять файлы — только с подтверждением;
- деструктив — запрещён намертво;
- внешние системы — читать можно, писать только с подтверждением;
- запрет дублируется и на уровне tools, и на уровне permission.
Блок 6. opencode.json - agent (plan / build / reviewer)

Переписывает под-агентов - три профиля поведения с разными правами и промптами.

plan - безопасный анализ:

"plan": {
"model": "",
"description": "Безопасный агент для анализа, планирования и объяснения кода без изменения файлов и запуска команд",
"temperature": 0.1, // почти детерминированный, минимум «фантазии»
"steps": 30, // максимум шагов (итераций инструментов) за один прогон
"permission": {
"edit": "deny",
"bash": "deny" // вообще не может менять файлы и запускать команды. Чистый read-only режим
},
"prompt": "Всегда отвечай на русском... Анализируй задачу, код и архитектуру без изменения файлов. Давай краткий план, риски и рекомендуемый минимальный вариант решения." // личная инструкция именно этому агенту
}


build - рабочий агент:

"build": {
"model": "",
"description": "Основной рабочий агент для изменения кода, рефакторинга, исправления ошибок...",
"temperature": 0.2,
"steps": 30,
"permission": {
"read": "allow", "list": "allow", "glob": "allow", "grep": "allow",
"edit": "ask",
"bash": {
"./gradlew *": "ask",
"git status*": "allow",
"git diff*": "allow",
"ls*": "allow",
"rg *": "allow",
"pwd": "allow"
}
},
"prompt": "Всегда отвечай на русском... Перед изменением кода сначала изучи существующую архитектуру. Предпочитай минимальные безопасные изменения. Не добавляй новые библиотеки без явной необходимости."
}


reviewer - ревью изменений:

"reviewer": {
"mode": "all",
"description": "Агент для ревью изменений в ветке: анализирует git diff, ищет риски в Kotlin-автотестах и не изменяет файлы",
"model": "",
"temperature": 0.1,
"steps": 40,
"prompt": "Всегда отвечай на русском... Проводи ревью изменений относительно master. Используй git-команды для анализа diff. Не изменяй файлы. Разделяй замечания на: Критично, Важно, Можно улучшить...",
"permission": {
"read": "allow", "list": "allow", "glob": "allow", "grep": "allow",
"edit": "deny",
"task": "deny",
"bash": {
"rg *": "allow",
"git status*": "allow", "git diff*": "allow", "git log*": "allow",
"git branch*": "allow", "git rev-parse*": "allow",
"git merge-base*": "allow", "git show*": "allow", "git ls-files*": "allow"
}
}
}
Что касается второй части работы с opencode - AGENTS.md: существует огромное множество предзаполненных шаблонов инструкций для агентов в сети.

Можно использовать такой вариант wlasadd/claude-autotest-skills, а можно самостоятельно попросить подключенного агента изучить проект и сагрегировать некий набор шаблонов и практик, уже принятых за образец, и двигаться далее в том же стиле.
qa.log
Вектор разработки все больше смещается с написания кода в сторону умения работать с настройками конфигов агентов. Claude Code, Codex, Cursor и тп - успешные коммерческие продукты, которые уже успели себя зарекомендовать. Попробуем разобраться с мультимодельными…
Не одним конфигурационным файлом для использования AI-агентов единым - попробуем создать свой подключаемый mcp-сервер на примере опенсорсного продукта rocket.chat вкупе с соответсвующим файлом-инструкцией AGENTS.md

rocket.chat - мессенджер, первый неструктурированный слой, в котором можно получить сообщение/тред с “проблемой”, ссылками на требования и прогоны тестов с ошибками. И не вникать в содержимое многочисленных рассуждений коллег самостоятельно.

Какой результат мы можем получить при условии такого сервера в связке с прочими mcp (например, allure, atlassian (jira, confluence, и тп)).
1. Читай. По ссылке/артефакту вызови getThread/getMessageContext и собери связное нейтральное описание (кто, что, шаги воспроизведения, договорённости).
2. Дедуплицируй до создания. Перед заведением задачи проверь, нет ли уже похожего тикета в таск-трекере и не помечен ли тред как обработанный. Не плоди дубли.
3. Верифицируй и обогащай. Если доступны MCP системы тестирования / базы знаний — подтяни подтверждающие прогоны и релевантный регламент с требованиями; добавь ссылки на них.
4. Фиксируй со ссылкой назад. При создании задачи всегда вставляй обратный permalink на исходный тред, плюс ссылки из шага 3.
5. Замыкай контур (write-back) — только с подтверждением. Ответ в тред / маркер «обработано» делает результат видимым в чате.

Поскольку вносимые изменения необратимы и «наружу», запрашивается явное подтверждение пользователя перед любой записью. Сам rocketchat-mcp write-back не выполняет — запись идёт через соответствующий инструмент или человеком.

Более подробно Цикл разработки как замкнутый контур MCP описан тут. Берем готовый репозиторий mcp-мессенджера rocketchat-mcp и пробуем.
Классический релиз держится на негласном допущении: поведение системы живёт в коде сервиса. Поэтому мы версионируем код - теги, чарты, образы.
С появлением агентов работа над проверкой работоспособности версий сервисов становится не просто недоутилизированной, но и архаичной.

Кроме того, из-за новизны тренда и отсутствия систематизации наблюдается увеличение числа самописных вариантов инстуркций для агентов и сабагентов.

Все это наталкивает на мысль о необходимости унификации и принятии нового стандарта в отношении работы с агентами, а так же - в восприятии новой парадигмы работы над продуктом, где код больше не является предметной областью.

Выход: оркестрация - метазвено, которое само код не пишет, а декомпозирует задачу, делегирует субагентам, создаваемым на лету; а те, в свою очередь - обращаются к внешним mcp-серверам, библиотекам скиллов и RAG-ам, на версионность которых и смещается фокус.
qa.log
Классический релиз держится на негласном допущении: поведение системы живёт в коде сервиса. Поэтому мы версионируем код - теги, чарты, образы. С появлением агентов работа над проверкой работоспособности версий сервисов становится не просто недоутилизированной…
Собираем агента-оркестратора, подключаем к нему mcp-сервер и библиотеку со скиллам той или иной версии в качестве шаблона/каркаса одного из новых звеньев разработки.

Отдаем задачу и получаем готовое решение, перенаправляя усилия на создание дата-сетов, сценариев и аналитики под тестирование версий теперь уже серверов и библиотек.

И замыкаем более верхнеуровневый новый цикл работы над продуктом.

Это больше не инжиниринг, не тестирование, не архитектура в том виде, в котором это существовало ранее. И не систем дизайн, поскольку сама система изменилась.

Closed box -> Shift Right
qa.log
Собираем агента-оркестратора, подключаем к нему mcp-сервер и библиотеку со скиллам той или иной версии в качестве шаблона/каркаса одного из новых звеньев разработки. Отдаем задачу и получаем готовое решение, перенаправляя усилия на создание дата-сетов, сценариев…
Стоит так же упомянуть, что высокая детализированность параметров оркестратора или частных агентских инструкций может казаться полезной только на первый взгляд.

Однако при наличии строгих указаний о принципах работы агента исчезает основной смысл использования LLM-моделей - недетерминированность.

То, что может казаться проблемой, с обратной стороны, является и преимуществом, поскольку в ином случае простор «мысли» модели оборачивается в жесткую рамку, превращая вариативность решения в подобие code-alike структуры с теми же условиями и ограничениями.

Некоторые проводят аналогии с детьми: зашейте строго в память, что, if укусит уличная собака, then нужно срочно обращаться к врачу, и, когда ребенка укусит крыса, аналогии не возникнет. Нужно учиться не правилам, а принципам и взаимосвязям.

Описание становится оправданным только в формате верхнеуровневых положений и конвенциональных концепций исполнения. А реализация отдается на откуп качеству моделей, методов мсп-серверов, рагов и тп. Что и становится новым предметом анализа, архитектуры, разработки и тестирования.
qa.log
Вакансия #aqa #autoqa #стажировка Отклик - в директ канала
Оффтоп по откликам на вакансию
Все заявки отправлены
Ответы в отрицательных случаях не гарантируемы, но запрошены
qa.log
Стоит так же упомянуть, что высокая детализированность параметров оркестратора или частных агентских инструкций может казаться полезной только на первый взгляд. Однако при наличии строгих указаний о принципах работы агента исчезает основной смысл использования…
Поднимаем абстракцию еще выше

Мы готовим инфраструктуру вокруг агента с версионированием - это разработка (context engineering)

Затем продумываем пайпы, по которым будет происходить взаимодействие процессов между собой - это девопс (delivery engineering)

И в конце собираем сценарии, проверяющие, что те или иные задачи по-прежнему решаются в пределах ожидаемого; поднимаем проекты, как тестовые данные - это тестирование (validation)

Продукт = способность системы решать задачи (ERS - Engineering of Reasoning Systems)

Вот так может выглядеть новая парадигма; а может не выглядеть - в этом нам еще предстоит убедиться или опровергнуть
#vacancy #computervision #hardwareengineer

Vision Hardware Engineer

AI-based quality control system for a production line in Thailand. The system inspects soft plastic packaging on a conveyor belt and detects defects such as tears, dents, deformations, and damaged packaging in real time.

Looking for an engineer with hands-on experience in:
-industrial cameras (Basler, FLIR, Hikrobot, etc.)
-lighting / optics / controllers
-conveyor / PLC integration
-machine vision setup for production environments

Tasks:
-HW procurement & purchasing
-business trips to SEA region (China / Japan )
-on-site installation & setup
-image quality optimization for AI inspection systems

All travel & equipment expenses covered by the company.

DM for CV