Andrey Epifancev d327a0488d docs(openspec): change bug-and-attachments — тип «Ошибка» и вложения (#43)
Дельты commands, hub-api, mcp, data-model, agent: issue_type bug с настройкой
issue_types.bug, хранилище файлов хаба (POST /files, GET /agent/files/{sha256}),
команда ensure_attachment, path в MCP batch_create, агент v11; заодно R-1
(#46) и M-1/M-2 из aep/jira-agent#30.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:42:21 +04:00

7.8 KiB
Raw Blame History

MODIFIED Requirements

Requirement: Чтение состояния

refresh SHALL выполняться запросом search (jql, fields = поля зеркала включая issuelinks, comment и спринт, maxResults = 100, постранично) и отправляться хабу пачками по 100 задач со связями; ключи из issuelinks, которых нет в выборке и в зеркале хаба (хаб сообщает список известных), агент SHALL дочитать одним search по key in (...) и отправить с признаком neighbor. Ошибка хаба при запросе известных ключей или отправке пачки SHALL попадать в error с префиксом «хаб: »; недоступность хаба и его 5xx повторяются, как обрыв связи, с источником «хаб». Каждая задача в состоянии (с v10) SHALL нести comments — все комментарии задачи в порядке Jira, каждый {id, author, created, updated, body}: id — строка; author — отображаемое имя автора, иначе его логин, иначе null; created, updated — время Jira как есть; body — текст как есть (пустой — ""). Если search отдал у задачи меньше комментариев, чем comment.total, агент SHALL дочитать комментарии этой задачи через GET /issue/{key}/comment постранично (maxResults = 100) и передать полный список. Комментарий без id или с пустым id агент SHALL отбросить с записью в лог (ключ задачи), остальные передать. Если дочитывание комментариев задачи вернуло 403 или 404, агент SHALL передать задачу без поля comments (хаб оставит прежние комментарии) с записью в лог; refresh продолжается.

Scenario: Полная синхронизация

  • WHEN refresh {jql: "project = AURORA AND labels = AWPCA"} при 180 задачах
  • THEN 2 вызова search + 1 на соседей; sync_run.issues_count = 180 + соседи

Scenario: Хаб не ответил при отправке состояния

  • WHEN refresh через папку, реле не ответило на отправку пачки ни в одной из 4 попыток
  • THEN отчёт failed с ошибкой «результат неизвестен (обрыв связи с хабом), повтор безопасен: хаб: не ответил через папку …»; в логе повторов — «обрыв связи с хабом»

Scenario: Комментарии в состоянии

  • WHEN у AURORA-1620 в Jira два комментария, автор первого — {name: "petrov", displayName: "Петров Пётр"}, у автора второго нет displayName, его name — ivanov
  • THEN в состоянии AURORA-1620 comments из двух элементов в порядке Jira, author — «Петров Пётр» и «ivanov»; число вызовов search не изменилось

Scenario: Неполный список комментариев

  • WHEN search вернул у AURORA-1620 20 комментариев при comment.total = 130
  • THEN агент дочитал комментарии двумя вызовами GET /issue/AURORA-1620/comment; в состоянии 130 комментариев

Scenario: Комментарий без id

  • WHEN у задачи два комментария, у второго id = null
  • THEN в состоянии один комментарий; в логе строка с ключом задачи; пачка принята хабом

Scenario: Нет доступа к комментариям

  • WHEN GET /issue/AURORA-1620/comment при дочитывании вернул 403
  • THEN AURORA-1620 в состоянии без поля comments; остальные задачи пачки с комментариями; refresh — done

Scenario: Задача без комментариев

  • WHEN у задачи в Jira нет комментариев
  • THEN в её состоянии comments = []

ADDED Requirements

Requirement: Тип задачи и вложения

Агент (с v11) SHALL брать тип для ensure_issue из issue_types.<issue_type>: {id}, если id задан, иначе {name}; нет записи или в ней нет ни id, ни name — ошибка конфигурации «нет настройки issue_types.<issue_type>», failed без вызова Jira.

ensure_attachment {key, file, filename, size} (size дописан хабом при выдаче) агент SHALL выполнять так: 0. size = null — failed «файл удалён с хаба, загрузите заново» без вызова Jira.

  1. GET /rest/api/2/issue/{key}?fields=attachment; вложение с тем же filename и тем же size есть — done с его attachment_id, файл у хаба не запрашивается.
  2. Файл — GET /agent/files/{file}; sha256 и длина декодированного content SHALL совпасть с file и size, иначе — временный сбой (повтор, как обрыв связи с хабом); 404 — failed «файл удалён с хаба, загрузите заново».
  3. POST /rest/api/2/issue/{key}/attachments, multipart/form-data с одной частью file, имя файла — filename в UTF-8 (filename="…" и filename*=UTF-8''…), заголовок X-Atlassian-Token: no-check; результат attachment_id из ответа. Ответ Jira 4xx (в том числе 413) — failed с кодом и текстом Jira. Содержимое файла MUST NOT попадать в журнал и лог (только file, filename, размер). AGENT_VERSION SHALL быть 11.

Scenario: Ошибка по имени типа

  • WHEN ensure_issue {issue_type: bug, …}, issue_types.bug = {name: "Ошибка"}
  • THEN в POST /issue issuetype = {name: "Ошибка"}

Scenario: Нет настройки типа

  • WHEN ensure_issue {issue_type: bug, …}, в issue_types нет bug
  • THEN failed «нет настройки issue_types.bug», вызовов Jira нет

Scenario: Загрузка вложения с кириллическим именем

  • WHEN ensure_attachment {key: X, file: <sha>, filename: "ОСВ сч. 60 за 2 кв. 2026.xlsx"}, у X вложений нет
  • THEN один GET /issue/X, один GET /agent/files/<sha>, один POST /issue/X/attachments; в Jira вложение с этим именем и размером файла; отчёт done с attachment_id

Scenario: Файл повреждён в пути

  • WHEN sha256 полученного content не равен file
  • THEN вложение в Jira не загружается; команда повторяется как при обрыве связи с хабом

Scenario: Старый агент

  • WHEN агент v10 получил ensure_attachment
  • THEN failed «неизвестный тип команды», агент работает дальше (поведение v10, без изменений)