Andrey Epifancev 54d87225bd OpenSpec: change attachment-fetch — вложения из Jira по запросу (#83)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 13:59:37 +04:00

7.3 KiB
Raw Blame History

MODIFIED Requirements

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

refresh SHALL выполняться запросом search (jql, fields = поля зеркала включая issuelinks, comment, attachment и спринт, 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 продолжается. Каждая задача в состоянии (с v14) SHALL нести attachments — все вложения задачи из поля attachment ответа search в порядке Jira, каждое {id, filename, size, mime_type, author, created}: id — строка; filename — имя как есть; size — целое (байт) или null; mime_type — mimeType Jira или null; author — как у комментария; created — время Jira как есть. Содержимое вложений при refresh MUST NOT скачиваться. Вложение без id агент SHALL отбросить с записью в лог (ключ задачи). Нет поля attachment в ответе (поле скрыто настройками Jira) — attachments = [].

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 = []

Scenario: Вложения в состоянии

  • WHEN у AURORA-1650 в Jira два вложения: «скрин 1.png» (mimeType = image/png, 240000 байт, автор {name: "potapova", displayName: "Потапова Анна"}) и «ОСВ 60.xlsx»
  • THEN в состоянии AURORA-1650 attachments из двух элементов в порядке Jira, у первого filename = "скрин 1.png", size = 240000, mime_type = "image/png", author = "Потапова Анна"; число вызовов search не изменилось, обращений к содержимому вложений нет

ADDED Requirements

Requirement: Скачивание вложения

Агент v14 SHALL выполнять fetch_attachment по контракту commands («Скачивание вложения по запросу»). Метод JiraClient для содержимого SHALL отдавать байты ответа без разбора JSON, с тем же счётом вызовов, повтором 429/503 и учётом времени последнего вызова, что и прочие вызовы Jira. Отправка хабу — HubClient (POST /agent/files), работает и через общую папку. В журнал агента (journal.jsonl) и в лог содержимое файла MUST NOT попадать — только id, имя, размер и sha256.

Scenario: Скачивание через общую папку

  • WHEN агент с hub_url = folder:… выполняет fetch_attachment вложения 3 МБ
  • THEN содержимое уходит хабу одним запросом POST /agent/files через папку (тело ≈ 4 МБ base64); отчёт done с file и size; в journal.jsonl нет содержимого файла