Мануальные тест-кейсы в Allure TestOps через REST API: поиск дублей, шаги деревом, ожидаемый результат, вложения curl и SQL, общие шаги, предусловия, custom fields, связь с Jira. Знает недокументированные контракты и ловушки TestOps. Используй всегда, когда просят «заведи ТК», «создай тест-кейс», «добавь шаги», «сделай общий шаг», «поправь тест-кейс», даже без слова Allure. English: Allure TestOps, manual test case, test steps, shared steps, TMS.
2 stars
0 votes
0 copies
1 view
Added October 16, 2026
testingpythonbashsqltestingapi
Works with
api
mcp
Security analysis
B75/100
criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study
Installs into .claude/skills of the current project.
Are you the author of Allure Testops Cases?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/konstantinvch-allure-testops-cases)
---
name: allure-testops-cases
description: "Мануальные тест-кейсы в Allure TestOps через REST API: поиск дублей, шаги деревом, ожидаемый результат, вложения curl и SQL, общие шаги, предусловия, custom fields, связь с Jira. Знает недокументированные контракты и ловушки TestOps. Используй всегда, когда просят «заведи ТК», «создай тест-кейс», «добавь шаги», «сделай общий шаг», «поправь тест-кейс», даже без слова Allure. English: Allure TestOps, manual test case, test steps, shared steps, TMS."
license: MIT
compatibility: "Python 3 с пакетом requests; доступ к инстансу Allure TestOps и API-токен. Опционально: Chrome/Chromium для скриншотов, доступ к Confluence для чтения спецификаций."
metadata:
author: KonstantinVCH
version: "1.0.0"
language: ru
---
# Мануальные тест-кейсы в Allure TestOps
Скилл собран из боевых сессий: каждый контракт ниже проверен живым вызовом, ловушки — реальные
грабли. Документация TestOps описывает API не полностью, поэтому опирайся на этот файл и
[references/api-map.md](references/api-map.md), а при расхождении — на свежий живой вызов.
## Настройка под проект
Всё специфичное для проекта (URL, id проекта и дерева, id полей и статусов, регламент, эталонные
кейсы, стенды) собрано в [references/project-config.md](references/project-config.md). Перед первой
работой заполни его. Если у команды есть база знаний, сначала прочитай в ней страницу о тестовой
документации и о сервисе, на который пишешь кейс.
Нужен только Python с `requests` и API-токен — MCP-серверы и браузер не обязательны.
```bash
export ALLURE_URL=https://allure.example.com
export ALLURE_TOKEN=<токен> # {ALLURE_URL} → аватар → API tokens
export ALLURE_PROJECT_ID=<id проекта>
export ALLURE_TREE_ID=<id дерева> # для find
python scripts/allure_tc.py show <id любого кейса> # проверка доступа
```
Токена нет — попроси пользователя создать его в профиле TestOps и положить в переменную
окружения. Токены и пароли в формы не вводи и в чат не проси.
## Команды скрипта
| Команда | Что делает |
|---|---|
| **`find <подстрока>`** | **ШАГ 0**: ветка дерева (Feature→Story→Layer), существующие кейсы метода и CF референса |
| `create --name … --description …` | создать кейс (Draft, Manual) |
| `precondition <tc> --text …` / `description <tc> --text …` | заполнить поля карточки |
| **`add-step --body … [--er …] [--attach файл] [--tc N \| --shared N] [--parent N]`** | шаг + ОР + вложения одной командой, в безопасном порядке — **основной способ наполнять сценарий** |
| `er <step> --step-body … --text … [--tc N \| --shared N]` | сделать уже существующий шаг «шагом с ОР» |
| `screenshot --url … --name … [--tc N \| --shared N] [--parent N]` | снимок страницы → вложение → привязка к шагу (или `--file` для готового PNG) |
| `attach <tc> --file …` / `attach-step <tc> --parent N --attachment A` | вложение к кейсу / привязать вложение к шагу |
| `shared-create --name …` / `insert-shared <tc> --shared N [--before N]` | создать общий шаг / вставить его в кейс |
| `cf <tc> --from-etalon <tc>` | скопировать Feature/Story/Layer с эталона (иначе кейс не попадёт в дерево) |
| `issue <tc> --key PROJ-123` | связать с задачей Jira (replace-семантика) |
| **`audit <tc>`** | проверка по конвенции: стоп-слова, длина названия, ссылка на документацию, нумерация предусловий, ОР у каждого шага, составные шаги, SQL в теле шага, связь с Jira, статус, custom fields |
| `show <tc>` | дерево шагов человекочитаемо, включая содержимое контейнеров ОР |
| `delete-step <step> --tc <tc>` | удалить шаг (вместе с вложениями детей) |
Наполнять сценарий парой `step` + `er` не нужно: `add-step` делает то же самое в порядке,
который не затирает ОР.
## Шаг 0 (до всего остального) — найти референс и дубли
Никогда не начинай с `create`. Сначала выясни, есть ли у метода папка в дереве и не покрыт ли
сценарий существующим кейсом:
```bash
python scripts/allure_tc.py find "/orders/{id}/status"
```
Команда печатает ветку дерева (Feature → Story → Layer → кейс) и CF референсного кейса. Дальше два
исхода:
- **папка метода найдена** → просмотри её ЦЕЛИКОМ (`find` раскрывает группу без фильтра, скрытые
кейсы помечены «был скрыт фильтром»). Новый кейс клади туда же
(`cf <новый> --from-etalon <любой кейс папки>`). Перед созданием прочитай соседние кейсы: если
сценарий уже описан и изменился лишь ожидаемый результат — **обнови существующий кейс, а не
заводи новый**. Дубль дороже правки;
- **папка не найдена** → метод в дереве не покрыт: возьми CF у соседнего метода **того же сервиса**
(`find "<другой метод сервиса>"`) и повтори его синтаксис имён.
Кроме дерева проверь документацию: если команда ведёт перечень описанных методов, ссылка на
страницу метода обязательна в описании кейса.
### Синтаксис имён (пример схемы Services)
| Уровень | CF | Значение | Пример |
|---|---|---|---|
| 1 | **Feature** | категория | `Services` |
| 2 | **Story** | имя сервиса | `order-service` |
| 3 | **Layer** | **папка метода**: `[<HTTP-МЕТОД>] /<путь> - Метод <назначение>` | `[GET] /orders/{id}/status - Метод получения статуса заказа` |
| 4 | Name кейса | `/<путь> - <суть проверки>` — **HTTP-метод в имени кейса НЕ повторяется** | `/orders/{id}/status - Получение статуса оплаченного заказа` |
`[GET]` живёт только в названии папки (Layer). В имени самого кейса его нет — иначе дублируется то,
что уже задано папкой. Значение Layer может переиспользоваться между сервисами (один и тот же id
значения), ветки разводит Story. Если у метода есть одноимённая ручка в другом сервисе — имя кейса
начинается с имени сервиса (`api-gateway /orders/{id}/status - ...`).
**Сценарные кейсы (не про конкретную ручку) живут по другой схеме:** Feature = `Клиентский путь`,
Story = функциональность (`Оформление заказа с оплатой картой`), Layer не заполняется. Определи
схему до создания: кейс на метод → схема Services; кейс на пользовательский сценарий → схема
клиентского пути. Фактическую схему своего проекта запиши в `project-config.md`.
## Железные правила
0. **Сначала Шаг 0** (`find`), потом всё остальное. Кейс, созданный без поиска дублей, — дефект
работы: он либо ляжет мимо дерева, либо продублирует существующий.
1. **Не создавай кейс без явного «да, создавай»** от пользователя. Черновик сначала покажи в чате:
кейс в общей TMS видят все, а удалять чужие ошибки придётся руками.
2. **Формат бери из эталона, не выдумывай.** Регламент команды и эталонные кейсы перечислены в
`project-config.md`. Нет регламента — действует раздел «Формат ТК» ниже.
3. **Перед созданием прочитай эталон соседней ветки** (`GET /api/testcase/{id}` + `/step` +
custom fields) и скопируй структуру: CF, стиль имён, форму шагов.
4. **Кейс атомарный и самодостаточный:** не ссылайся на внешние инструменты («запрос в Postman»,
«коллекция у меня») — всё нужное лежит в самом кейсе: curl во вложениях, плейсхолдеры вида
`<НОВЫЙ UUID>`, в шаге — что именно заменить.
## Перед правкой кейса — свежая версия спецификации
Кейс правится под требования, а не под наблюдаемое поведение. Поэтому до любой правки ОР перечитай
спецификацию метода и посмотри **историю её изменений**: номер версии, дату, автора. Спека могла
измениться час назад, и «дефект», который ты собираешься зафиксировать в ОР, уже узаконен
аналитиком (или наоборот — поведение объявлено ошибкой).
Через MCP Atlassian, если подключён (например, публичный `mcp-atlassian`):
```
confluence_get_page(page_id) # текущее содержимое
confluence_get_page_diff(page_id, from_version=N, to_version=M) # что поменяли и в рамках какой задачи
```
⚠️ **Ловушка: зачёркнутый текст теряется при конвертации в markdown.** И `get_page`, и
`get_page_diff` отдают удалённый пункт как обычную строку — по ним условие выглядит действующим.
Проверяй HTML:
```python
import os, requests
r = requests.get(f"{os.environ['CONFLUENCE_URL']}/rest/api/content/{page_id}?expand=body.view,version",
headers={"Authorization": f"Bearer {os.environ['CONFLUENCE_TOKEN']}"})
r.json()["version"]["number"], r.json()["version"]["by"]["displayName"] # версия и автор
"text-decoration: line-through" in fragment # пункт вычеркнут = требования больше нет
```
*Как это выстрелило:* по markdown-версии спеки условие `trace_id is not null` читалось как активное
требование, поведение ему не соответствовало — был заведён баг. В HTML тот же пункт оказался
зачёркнут: аналитик убрал условие намеренно в рамках той же задачи. Правильный ОР был
противоположным тому, который собирались записать.
Отдельно: плашка с номером задачи рядом со строкой спеки означает лишь, что строку затронули в
рамках этой задачи, — не обязательно, что требование новое. Возраст требования смотри по diff версий.
## Формат ТК
| Поле | Правило |
|---|---|
| **Name** | `[CONSUMER ]<очередь \| /эндпоинт \| метод> - <суть>`. Стоп-слова: «Позитивный», «Негативный», «Проверка» — они ничего не говорят о сути |
| **Description** | Краткое описание **логики метода** + **обязательная ссылка на спецификацию** + пояснение контекста, если функционал специфичный. Принятое начало: «Тест-кейс позволяет проверить …». Без ссылок на Postman/Bruno-коллекции |
| **Precondition** | ТОЛЬКО подготовка данных, шаги пронумерованы. К **каждому комплексному** шагу — ссылка на кейс-предшественник. Отправка сообщений и проверки результата — НЕ сюда, а в сценарий. Вложения к предусловию API не поддерживает: curl грузи вложением кейса и ссылайся на него по имени |
| **Сценарий** | Действие (неопределённая форма: создать, выполнить, открыть) → Expected Result (совершённый вид: создана, обновлён). Скриншоты для UI-шагов |
| **Шаг атомарен** | Один шаг = **одно действие в одном месте**. «Перейти в БД и проверить статус заказа» — шаг; «Перейти в Jaeger и открыть трейс» — отдельный шаг. Союз «и» между разными местами (БД и Jaeger, UI и очередь, API и БД) означает, что шагов должно быть два: иначе непонятно, что упало при провале, и ОР смешивает несвязанные проверки |
| **Запросы в шагах** | **Упомянул — приведи.** Назвал таблицу → к шагу приложен готовый `SELECT`; назвал метод → `curl`; назвал очередь → тело сообщения. «Проверить статус в `orders.order_status`» без запроса недостаточно: следующий тестировщик не должен сочинять SQL сам. **Запрос кладётся вложением `text/plain`**, в теле шага — короткая инструкция со ссылкой на вложение. Изменяемые значения — плейсхолдерами: `'<id заказа>'`, `<customerId>` |
| **Custom fields** | Feature/Story/Layer — скопировать с эталонного кейса той же ветки, иначе кейс упадёт в корень дерева |
| **Связь с Jira** | Ключ **родительской** задачи (не подзадачи «Тестирование») |
| **После создания** | Статус «на ревью» (id в `project-config.md`), автор проставлен; ссылку в канал ревью публикует пользователь |
### Общие шаги (shared steps)
Сначала посмотри существующие (`GET /api/sharedstep?projectId=…`) и повтори их стиль
(«Отправить запрос из вложения, предварительно указав: 1…N» + вложение + Expected Result).
**Граница общего шага — его универсальность.** В него входит только то, что одинаково для всех
кейсов, которые его подключат: подготовка и сам повторяемый блок. Не входит:
- шаги, после которых сценарии расходятся (переход, запускающий проверяемый метод) — это шаг кейса;
- ОР с конкретным исходом («если данные не совпали — экран ошибки») — навязывает сценарий всем;
- скриншоты и вложения одного из исходов (негативного) — им место в соответствующем кейсе;
- диагностические проверки, дублирующие ОР предыдущего шага — их лучше дописать в этот ОР.
Проверка на универсальность: «подключу этот блок в негативный кейс — он всё ещё корректен?»
Если нет — шаг лишний. Пример: общий шаг «Эмуляция ответа платёжного шлюза» заканчивается
сохранением ответа шлюза; возврат на страницу заказа по `returnUrl` и всё, что после, — уже шаги
конкретного кейса.
## Порядок работы
1. Согласуй с пользователем: название, место в дереве (эталонный сосед), состав шагов. Жди «да».
2. `allure_tc.py create` → id. Затем: precondition → шаги через `add-step` (шаг → ОР → вложения) →
общие шаги → custom fields (`cf`) → связь с Jira (`issue`) → статус ревью.
3. Самопроверка по конвенции:
- название короткое, содержит метод, без стоп-слов;
- в описании есть ссылка на спецификацию;
- предусловия пронумерованы, у комплексных — ссылки на кейсы-предшественники;
- **у каждого шага-действия есть ОР**; действия в неопределённой форме («выполнить»,
«перейти»), результат — в совершенном/настоящем («создана запись», «отображается экран»);
- в кейсе нет шагов-«контейнеров» без действия: данные предусловий живут в предусловиях;
- связь с Jira — родительская задача, статус ревью.
Автопроверка: `allure_tc.py audit <id>`. Глазами: `allure_tc.py show <id>`.
**Порядок правок шага:** сначала текст (`PATCH .../step/{id} {"body"}`), потом ОР. Обратный порядок
затирает `expectedResultId` — ОР придётся создавать заново (ловушка 4).
## API-карта (шпаргалка)
Полные контракты с примерами — [references/api-map.md](references/api-map.md).
| Операция | Вызов |
|---|---|
| Создать кейс | `POST /api/testcase` — **обязательны `workflowId` (Manual) и `statusId` (Draft)**, иначе 400 |
| Precondition / Description | `PATCH /api/testcase/{id}` `{"precondition"/"description"}` |
| Шаг сценария | `POST /api/testcase/step` `{"testCaseId","body"[,"parentId"]}` → `createdStepId`. ⚠️ НЕ `/scenario` — тот пишет сценарий автотестов, в UI мануального кейса невидим |
| **Expected Result (нативный)** | `PATCH .../step/{id}?withExpectedResult=true` с телом `{"body":"<текст шага>","expectedResult":""}` → `expectedResultId`; текст ОР — **дочерним узлом** контейнера: `POST .../step {parentId: erId, body: "…"}`. Конвертировать можно только шаг **без детей**, вложения добавляются после |
| Вложение к кейсу | `POST /api/testcase/attachment?testCaseId=` multipart `file`; **имя латиницей**, потом при желании `PATCH /api/testcase/attachment/{id}` rename |
| Вложение к шагу | `POST /api/testcase/step` `{"testCaseId","parentId","attachmentId"}` |
| Скриншот UI | `allure_tc.py screenshot --url … --name ui_x --tc N --parent <step>`; из живой Playwright-сессии — `page.request.post(…/attachment, multipart)`, см. api-map |
| Общий шаг | `POST /api/sharedstep` `{"projectId","name"}`; шаги `POST /api/sharedstep/step` `{"sharedStepId",...}`; вложения `POST /api/sharedstep/attachment?sharedStepId=` |
| Вставить общий шаг | `POST /api/testcase/step` `{"testCaseId","sharedStepId"}`; позиция: `POST /api/testcase/step/{id}/move` `{"testCaseId","beforeId":X}` |
| Связь с Jira | `POST /api/testcase/{id}/issue` `[{"name","url","integrationId"}]` — семантика **replace** |
| Удалить шаг | `DELETE /api/testcase/step/{stepId}?testCaseId=` — ⚠️ удаляет и вложения его детей |
## Ловушки (все пойманы живьём)
1. ❌ **Инструмент `set_test_case_issues` MCP-сервера Allure привязывает ВЕСЬ справочник задач
проекта** (сотни связей разом). Связи — только REST `POST /{id}/issue` (replace).
2. ❌ **`POST /api/testcase/{id}/scenario` — не то хранилище**: 200 OK, но карточка мануального
кейса остаётся пустой (пользователь увидел «пустые кейсы»).
3. ❌ `POST /api/testcase` без `workflowId`+`statusId` → 400 `workflow and status are required`.
4. ❌ `PATCH /api/testcase/step/{id}` затирает `expectedResultId` шага — ОР создавать заново.
5. ❌ Кириллица в имени multipart-файла превращается в мусор — грузи латиницей
(`curl_order_create`), переименовывай после при необходимости.
6. ❌ Свои значения Feature/Story/Layer кладут кейс в корень дерева — копируй CF эталона.
7. ❌ Удаление шага-контейнера уносит вложения его детей — перед переносом блока в предусловие
перезалей вложения на уровень кейса.
8. ❌ `GET /api/testcase/{id}/issue` возвращает привязанные задачи; после ловушки 1 там окажется
весь справочник — чинится тем же POST-replace с одним элементом.
9. ❌ **Блоков кода в теле шага не существует**: `PATCH` с `codeBlock` в `bodyJson` → 400, а
многострочный текст схлопывается в один абзац — SQL и curl превращаются в нечитаемую простыню.
Скрипты только вложением.
10. ❌ **Контейнер ОР может остаться пустым молча**: `expectedResultId` создан, текста внутри нет —
API отдаёт шаг «с ОР», а в UI поле пустое. После записи ОР проверяй, что в `children`
контейнера есть непустой узел (`add-step` делает это сам).
11. ❌ **Текст ОР в самом контейнере `expectedResultId` в UI не виден** — пиши дочерним узлом.
12. ❌ `PATCH` тела узла, вставленного как общий шаг, превращает его в обычный текстовый шаг —
общий шаг из кейса пропадает.
13. ❌ **`DELETE` шага уносит вложения, висевшие на нём и его детях** — они пропадают из списка
вложений сущности целиком. Перед пересборкой дерева перезаливай файлы, старые id не годятся.
14. RQL-поиск: `name ~= "строка"` (оператор `~` даёт 400 invalid.aql); кириллица в `name ~=`
работает, но по `cf["Story"]` надёжнее.
15. ❌ **`PATCH …/step/{id}?withExpectedResult=true` может вернуть 200 БЕЗ `expectedResultId`**
(у шага уже были дети-вложения). Контейнер ОР при этом создаётся, но id в ответе нет — и
`POST …/step` с `parentId=None` кладёт текст ОР **корневым шагом** сценария. После конвертации
перечитывай дерево (`GET …/step`) и бери `expectedResultId` оттуда.
16. ❌ **Параметр `search` дерева фильтрует и ЛИСТЬЯ, а не только группы**: по подстроке в ветке из
10 кейсов видны только те, чьё ИМЯ её содержит (1 из 10). Так был заведён дубль существующего
кейса. Найдя группу, раскрывай её повторным запросом с пустым `search` (`find` делает это сам).
RQL `__search?rql=name ~= "..."` — дополнительная страховка, но тоже ищет только по имени;
сценарные кейсы с описательными названиями по имени метода не находятся.
17. ❌ `POST …/step/{id}/move` с `{"index":N}` отвечает 200, но порядок не меняет — только
`beforeId`/`afterId`.
## Доступы, которые нужны для проверок в шагах
Прежде чем писать в ОР «в БД такой-то статус», выполни запрос вживую — иначе в кейс попадёт SQL с
несуществующей колонкой (так уже было: `payment_provider_code` вместо `provider_code`).
Адреса БД стендов, схемы, Jaeger и логи — в `project-config.md`. Подключения MCP к БД часто
работают только на чтение; для записи фикстур подключайся драйвером (`psycopg2` и т.п.) с тем же DSN.
Ссылку на трейс в ОР давай на конкретный спан (`{JAEGER_URL}/trace/<traceId>?uiFind=<spanId>`),
а не на трейс целиком.
## Самокритика перед сдачей кейса
Кейс пишется один раз, а читают его люди, которые не сидели в твоей сессии. Поэтому до сдачи
пройди по нему как чужой человек и ответь на вопросы ниже. Каждый ловил реальную ошибку.
**1. Атомарность: кейс проверяет одно, шаг делает одно?**
Если в названии кейса есть «и» или ОР описывает два разных исхода — это два кейса. Позитив и
негатив не живут в одном кейсе: у них разные предусловия и разные ОР. На уровне шага то же
правило: **одно действие в одном месте**. Проверка сразу в БД и в Jaeger — два шага: иначе при
провале непонятно, какая часть не сошлась.
*Промахи:* ОР вида «…если данные не совпали — экран ошибки» (кейс покрывал оба исхода) и шаг
«Выполнить запросы к БД и открыть трейс в Jaeger» (два места действия в одном шаге).
**2. Достаточность: по кейсу пройдёт человек, который не видел сессию?**
Прочитай сверху вниз и на каждом шаге спроси «а откуда я возьму это значение?». Id сущности,
hash, номер стенда, тестовые данные — всё должно браться из предыдущих шагов или предусловий, а
не «из контекста».
*Промах:* в шаге стояло «указать orderId», а откуда он берётся — знал только автор.
**3. Границы: этот шаг вообще относится к тому, что проверяет кейс?**
Данные предусловий — в предусловия, а не шагом-контейнером в сценарий. Диагностические проверки,
дублирующие ОР соседнего шага, — в этот ОР. Шаг, после которого сценарии расходятся, — в кейс,
а не в общий шаг.
**4. Каждое упоминание проверки подкреплено запросом?**
Если в шаге есть слово «проверить» — рядом должно быть то, чем проверяют: SQL, curl, тело
сообщения в очередь или ссылка на трейс. Запрос выполнен вживую до вставки в кейс.
**5. Поведение изменилось — это правка ОР или новый кейс?**
Первым делом — свежая версия спеки (раздел «Перед правкой кейса»). Изменился ожидаемый результат
у уже описанного сценария → **обнови существующий кейс**. Новый нужен, только если появился
сценарий, которого раньше не было. Прежде чем объявить кейс «устаревшим», проверь три вещи:
(1) что говорит **актуальная версия спеки** — старый пункт может быть уже зачёркнут;
(2) на **каком стенде** проверено — фикс мог быть раскатан не везде (проверяй несколько стендов
одним запросом); (3) **автоматизирован** ли кейс (`automated` в карточке) — если да, правка ОР без
синхронной правки автотеста ломает прогон.
*Промах:* вывод «кейсы устарели» сделан по одному стенду, а на двух других метод ещё отдавал
старую ошибку.
**6. ОР проверяем и полон?**
«Запрос прошёл успешно» — не ОР. ОР — перечень того, что смотрят: код ответа, поля тела, статусы
в БД с именами таблиц, наличие/отсутствие ошибки в трейсе, что видит пользователь. Если по ОР
нельзя однозначно сказать «прошёл/не прошёл» — он недописан.
**7. Картинки и вложения ОТКРЫТЫ и прочитаны, а не просто «есть»?**
Правя кейс, скачай и **посмотри содержимое** каждого вложения — и в шагах, и в предусловиях
(`GET /api/testcase/attachment/{id}/content`, картинку прочитай как изображение). «Файл отдаётся,
200 OK» недостаточно: скриншот может показывать ответ старой версии сервиса, и обновлённый текст
ОР вступит в противоречие с картинкой. Вложения ОР лежат внутри контейнера `expectedResultId` —
обходи и его детей (`show` делает это сам).
*Промахи:* в ОР остались скрины со списком способов оплаты `["CARD","SBP"]`, снятые до появления
`WALLET`, при новом тексте ОР; и прогон «активной подписки» сделан на записи с `is_active=false`,
хотя картинка предусловия явно показывала `is_active=true` — читай предусловие буквально,
включая то, что нарисовано на скриншоте.
**8. ОР пишется по спецификации, а не по факту прогона.**
Если поведение расходится со спекой — ОР остаётся по спеке, а расхождение оформляется багом
(скилл `bug-report`). ОР, переписанный «как отвечает сервис», узаконивает дефект и делает кейс
бесполезным.
*Промах:* метод игнорирует условие `trace_id is not null` из спеки — ОР оставлен по спеке, кейс
намеренно красный, дефект заведён отдельно.
## Границы скилла
Скилл заводит и правит кейсы. Прогон кейса, тест-данные на стендах, деплой — другие скиллы
(`qa-task-testing`, `bamboo-deploy`). Ничего не публикуй в Jira или чатах от имени
пользователя: публикация — его решение.