11 KiB
MODIFIED Requirements
Requirement: Команда — желаемый результат на одной задаче
Каждая команда SHALL описывать желаемое состояние одной задачи Jira и выполняться агентом как «прочитать → сравнить →
записать только разницу». Повторное выполнение любой команды с тем же результатом в Jira SHALL завершаться done
без записи. Типы команд и их контракт:
| Тип | Параметры | Что читает | Что пишет |
|---|---|---|---|
ensure_issue |
temp_key (new:<n>), issue_type (task/epic), summary, description, priority, duedate, planned_start, planned_end, labels, epic_key, assignee |
поиск project = <proj> AND reporter = currentUser() AND created >= -7d, точное сравнение summary |
при отсутствии — POST /issue (для эпика — с epic_name_field_id); результат key |
ensure_fields |
key, любое подмножество: summary, description, priority, duedate, planned_start, planned_end, labels_add, labels_remove, epic_key, assignee |
GET /issue/{key} |
PUT /issue/{key} только с отличающимися полями; эпик — по epic_link.mode |
ensure_comment |
key, marker, body |
GET /issue/{key}/comment |
комментарий с marker в начале: PUT если текст отличается, POST если нет |
ensure_status |
key, target (имя статуса или список-путь) |
GET /issue/{key} (статус), GET /issue/{key}/transitions на каждом шаге |
POST /transitions по шагам пути; при отсутствии перехода — failed с перечнем доступных |
ensure_link |
source, target, link_type (логическое имя из link_types), replace (bool) |
GET /issue/{source} (issuelinks), GET /issueLinkType (симметричность) |
нужная связь есть — ничего; нет нужной и нет конфликта — POST /issueLink; конфликт (другой тип из link_types в любом направлении или обратное направление несимметричного типа) и replace — DELETE лишней, затем POST; конфликт без replace — failed с описанием |
ensure_sprint |
key, sprint (имя или backlog) |
GET /issue/{key} (поле спринта), список спринтов доски из board_id (активные и будущие) |
POST /rest/agile/1.0/sprint/{id}/issue или POST /rest/agile/1.0/backlog/issue |
refresh |
keys (список) или jql |
search с полями зеркала, по 100 на страницу; плюс дочитывание соседей по issuelinks |
ничего в Jira; состояние уходит в хаб |
Семантика ensure_link: source блокирует/ссылается на target; агент в POST /issueLink SHALL ставить source в
inwardIssue, target в outwardIssue (проверено на Jira банка 11.10.2026). Тип связи симметричен, если в Jira у него
inward == outward; для симметричного типа связь target→source равнозначна source→target («нужная связь есть»).
Scenario: Повтор уже выполненной команды
- WHEN
ensure_fields {key: AURORA-1533, duedate: 2026-10-23}выполняется, а в Jira срок уже 23.10 - THEN агент не делает
PUT, отчётdone,jira_calls = 1
Scenario: Замена связи
- WHEN
ensure_link {source: AURORA-1537, target: AURORA-1538, link_type: "связанные", replace: true}и в Jira между ними «блокирует начало» 1537→1538 - THEN
DELETEстарой связи, пауза по политике,POSTновой; отчётdoneс обеими операциями
Scenario: Связь-конфликт без replace
- WHEN та же команда с
replace: false - THEN
failed, вerrorнайденная связь, Jira не изменена
Scenario: Симметричная связь в обратную сторону
- WHEN
ensure_link {source: AURORA-1445, target: AURORA-1446, link_type: "связанные"}, тип симметричен, в Jira есть «Связанные» 1446→1445 - THEN агент ничего не пишет, отчёт
doneсexisted: true
Scenario: Переход по пути
- WHEN
ensure_status {key: X, target: ["Разработка", "Готово"]}и X в «Ожидание разработки» - THEN два
POST /transitionsс паузой между ними; если X уже «Готово» —doneбез записи
Scenario: Создание с проверкой дубля
- WHEN
ensure_issueповторяется после падения агента, а задача с той же темой от нас уже создана час назад - THEN агент не создаёт вторую, отчёт
doneс ключом найденной
Requirement: Пакет и порядок выполнения
Пакет SHALL создаваться одним вызовом с автором, заголовком и списком команд; хаб SHALL назначить seq по порядку списка
и добавить в хвост refresh по всем ключам пакета (кроме пакетов, состоящих только из refresh). Пакет с двумя и более
ensure_issue с одинаковой summary (после обрезки пробелов по краям) SHALL отвергаться (422). Очередь SHALL выдавать
команды в порядке (batch.created_at, seq), одну в полёте. Пакет и его queued команды MAY быть отменены; claimed
команда MUST NOT отменяться автоматически.
Scenario: Оценка длительности
- WHEN создаётся пакет из 3
ensure_fieldsи 2ensure_comment - THEN
estimate_seconds= сумма пауз по политике для последовательности типов + паузаrefresh
Requirement: Ошибки и подтверждение по состоянию
Ошибка команды SHALL записываться в error (HTTP-код, текст Jira до 1500 символов), пакет продолжается.
Повторная выдача. Агент запрашивает новую команду, только когда у него нет незавершённой (см. agent), поэтому
команда в claimed к моменту следующего claim считается не доставленной или потерянной агентом. При claim хаб SHALL
сначала выдать снова самую старую (по claimed_at, затем id) команду в claimed: тот же id и параметры,
pause_seconds по текущей политике темпа, новый claimed_at, deliveries + 1. Если у неё уже deliveries >= 3, хаб SHALL
перевести её в failed с error = "агент не отчитался после 3 выдач" и перейти к следующей (довыдача другой claimed
или следующая queued). Довыдача — доставка той же выдачи, а не повтор команды.
Подтверждение по состоянию. Если после любого refresh желаемый результат команды в claimed виден в зеркале, хаб SHALL
перевести её в confirmed_by_state:
ensure_issue— задача с той жеsummary,reporter = agent_status.jira_user, созданная не раньше 7 дней назад; покаjira_userнеизвестен — не подтверждается;ensure_fields— все поля совпадают;ensure_status— статус равен последнему в пути;ensure_sprint— спринт совпадает;ensure_link— нужная связь есть (source→targetнужного типа или, для типа изagent_status.symmetric_link_types,target→sourceтого же типа) и нет конфликта (связи другого типа изlink_typesмежду теми же задачами в любом направлении, обратной связи несимметричного типа). Дляensure_commentиrefreshподтверждения по состоянию нет: такая команда ждёт отчёта агента, довыдачи или отмены человеком. Новых команд хаб MUST NOT создавать сам: повтор послеfailed— новая команда с теми же параметрами по запросу интерфейса.
Scenario: Отчёт потерян, факт на месте
- WHEN
ensure_sprint {key: X, sprint: "Спринт 2"}вclaimed20 минут, агент перезапущен,refreshпоказал X в «Спринт 2» - THEN команда
confirmed_by_state, следующая команда очереди выдаётся
Scenario: Ответ на claim потерян
- WHEN команда 40 выдана (
deliveries = 1), ответ до агента не дошёл, агент снова прислалclaim - THEN
claimотдаёт команду 40,deliveries = 2; в очереди естьqueuedкоманды, но выдаётся 40
Scenario: Предел выдач
- WHEN команда 41 в
claimedсdeliveries = 3, агент снова прислалclaim, в очереди есть команда 42 - THEN 41 —
failed«агент не отчитался после 3 выдач»;claimотдаёт 42
Scenario: Создание подтверждается по состоянию
- WHEN
ensure_issue {summary: "Шахматка: комментарии"}вclaimed,agent_status.jira_user = "bridge-user",refreshзагрузил задачу с этой темой,reporter = "bridge-user", созданную сегодня - THEN команда
confirmed_by_stateс ключом задачи; заметкаnew:Nперенесена на ключ
Scenario: Связь симметричного типа в обратную сторону
- WHEN
ensure_link {source: A, target: B, link_type: "связанные"}вclaimed, тип вsymmetric_link_types, в зеркале есть только «Связанные» B→A - THEN команда
confirmed_by_state