Агент v11: тип «Ошибка», ensure_attachment, устойчивое дочитывание комментариев (#31) #32

Merged
aep merged 7 commits from feat/31-bug-and-attachments into main 2026-10-16 09:10:20 +03:00
Owner

Closes #31. Закрывает M-1 и M-2 из #30 (M-3, M-4 остаются). Пара — aep/jira-hub PR #47 (хранилище файлов, ensure_attachment, GET /agent/files/{sha256}, size при выдаче). Спека — openspec/changes/bug-and-attachments/ в jira-hub; решения агента — openspec/changes/agent-v11-bug-attachments/design.md (R-20…R-27, O-1, O-2).

Что сделано

  • Тип задачи из issue_types: {id}, если задан, иначе {name}; нет записи или ни id, ни name — failed «нет настройки issue_types.<тип>» без вызова Jira (проверка до поиска дубля). Тип bug.
  • ensure_attachment {key, file, filename, size}: size = null → failed «файл удалён с хаба, загрузите заново» без вызовов; GET /issue/{key}?fields=attachment — вложение с тем же именем и размером → done existed; иначе GET /agent/files/{file} (404 → «файл удалён…»; sha256/длина не совпали, base64 нечитаем, 2xx не JSON → повтор как обрыв связи с хабом, без содержимого в ошибке); multipart POST /issue/{key}/attachments (filename="…" + filename*=UTF-8''…, X-Atlassian-Token: no-check, таймаут ≥ 120 с, 429/503 — общий повтор); 4xx — failed с текстом Jira.
  • HTTP: Http.send (готовое тело), JiraClient._retry, JiraClient.upload, HubClient.file; содержимое файла не попадает в журнал, лог и отчёт.
  • refresh (M-1, M-2 из #30): комментарий без id или с пустым id отбрасывается с логом; 403/404 при дочитывании — задача без поля comments (хаб оставит прежние), refresh продолжается; 5xx — повтор, как раньше.
  • AGENT_VERSION = 11; фейки Jira (вложения, строгий multipart, 403 без XSRF-заголовка, обрыв после сохранения, 413) и хаба (/agent/files, size при выдаче); README, ARCHITECTURE.md, CLAUDE.md.

Проверка

  • /usr/bin/python3 -W error::ResourceWarning -m unittest discover -s tests -t . — 262 OK (было 230), Python 3.9.6.
  • Финальное ревью ветки (opus): Critical 0, Important 0; зонды ревьюера — файл 10 МБ по HTTP и через папку (0,13 с), обрезанный ответ без base64 в ошибке.
  • Поведение меняется для task/epic: без настройки — failed «нет настройки…» вместо 400 от Jira на {"name": null} (R-4 хаба).

Выкатка

После merge хаба (#47): jira-hub agent publish …/agent.py (v11) → самообновление → min_agent_version = 11 → живая проверка «Ошибка + вложение с кириллическим именем, повтор пакета без дублей» (единственная проверка того, как Jira банка сохраняет имя из multipart).

Rulings I made

  • R-20 любой 404 от /agent/files — «файл удалён с хаба, загрузите заново». Цена: при откате хаба на версию без маршрута — неверный совет.
  • R-21 таймаут GET /agent/files — обычные 60 с. Цена: на медленной папке — повтор и failed, лечится timeout.
  • R-22 2xx не JSON от хаба — временный сбой без текста HttpError (base64 не попадает в журнал). Цена: беднее диагностика.
  • R-23 ", CR, LF в filename="…" кодируются как у браузеров, поиск сравнивает обе формы имени — запасная защита (хаб с решения 20 такие имена не ставит).
  • R-24 ответ Jira без id — failed без повтора. R-25 загрузка — общий повтор 429/503. R-26 тип проверяется до поиска дубля.
  • R-27 трейлер коммитов исполнения — Sonnet 5.5 (исполнял sonnet; указание окружения приоритетнее текста плана).

Findings

Маркер Суть Статус
R-20…R-26 решения плана fixed cd8213b..93e5595
R-27 трейлер Sonnet 5.5 fixed (процесс)
O-1 README «сейчас 9» при v10 fixed 93e5595
O-2 полный набор ≈2 мин fixed (наблюдение)
M-1 обоснование R-23 устарело после решения 20 хаба fixed 04e7812
M-2 тест «2xx не JSON» подменяет HubClient.file, настоящий транспорт не проверен deferred
M-3 любой 404 /agent/files — «файл удалён» (проверять no_file) deferred
M-4 docstring HubError упоминает только refresh deferred
M-5 ответ на загрузку {} и [123] без теста deferred
M-6 README: timeout без 120 с загрузки deferred

🤖 Generated with Claude Code

Closes #31. Закрывает M-1 и M-2 из #30 (M-3, M-4 остаются). Пара — aep/jira-hub PR #47 (хранилище файлов, `ensure_attachment`, `GET /agent/files/{sha256}`, `size` при выдаче). Спека — `openspec/changes/bug-and-attachments/` в jira-hub; решения агента — `openspec/changes/agent-v11-bug-attachments/design.md` (R-20…R-27, O-1, O-2). ## Что сделано - **Тип задачи из `issue_types`**: `{id}`, если задан, иначе `{name}`; нет записи или ни id, ни name — `failed` «нет настройки issue_types.<тип>» без вызова Jira (проверка до поиска дубля). Тип `bug`. - **`ensure_attachment {key, file, filename, size}`**: `size = null` → `failed` «файл удалён с хаба, загрузите заново» без вызовов; `GET /issue/{key}?fields=attachment` — вложение с тем же именем и размером → `done existed`; иначе `GET /agent/files/{file}` (404 → «файл удалён…»; sha256/длина не совпали, base64 нечитаем, 2xx не JSON → повтор как обрыв связи с хабом, без содержимого в ошибке); multipart `POST /issue/{key}/attachments` (`filename="…"` + `filename*=UTF-8''…`, `X-Atlassian-Token: no-check`, таймаут ≥ 120 с, 429/503 — общий повтор); 4xx — `failed` с текстом Jira. - **HTTP**: `Http.send` (готовое тело), `JiraClient._retry`, `JiraClient.upload`, `HubClient.file`; содержимое файла не попадает в журнал, лог и отчёт. - **refresh (M-1, M-2 из #30)**: комментарий без `id` или с пустым `id` отбрасывается с логом; 403/404 при дочитывании — задача без поля `comments` (хаб оставит прежние), refresh продолжается; 5xx — повтор, как раньше. - `AGENT_VERSION = 11`; фейки Jira (вложения, строгий multipart, 403 без XSRF-заголовка, обрыв после сохранения, 413) и хаба (`/agent/files`, `size` при выдаче); README, ARCHITECTURE.md, CLAUDE.md. ## Проверка - `/usr/bin/python3 -W error::ResourceWarning -m unittest discover -s tests -t .` — 262 OK (было 230), Python 3.9.6. - Финальное ревью ветки (opus): Critical 0, Important 0; зонды ревьюера — файл 10 МБ по HTTP и через папку (0,13 с), обрезанный ответ без base64 в ошибке. - **Поведение меняется для `task`/`epic`**: без настройки — `failed` «нет настройки…» вместо 400 от Jira на `{"name": null}` (R-4 хаба). ## Выкатка После merge хаба (#47): `jira-hub agent publish …/agent.py` (v11) → самообновление → `min_agent_version = 11` → живая проверка «Ошибка + вложение с кириллическим именем, повтор пакета без дублей» (единственная проверка того, как Jira банка сохраняет имя из multipart). ## Rulings I made - **R-20** любой 404 от `/agent/files` — «файл удалён с хаба, загрузите заново». Цена: при откате хаба на версию без маршрута — неверный совет. - **R-21** таймаут `GET /agent/files` — обычные 60 с. Цена: на медленной папке — повтор и `failed`, лечится `timeout`. - **R-22** 2xx не JSON от хаба — временный сбой без текста `HttpError` (base64 не попадает в журнал). Цена: беднее диагностика. - **R-23** `"`, CR, LF в `filename="…"` кодируются как у браузеров, поиск сравнивает обе формы имени — запасная защита (хаб с решения 20 такие имена не ставит). - **R-24** ответ Jira без `id` — `failed` без повтора. **R-25** загрузка — общий повтор 429/503. **R-26** тип проверяется до поиска дубля. - **R-27** трейлер коммитов исполнения — Sonnet 5.5 (исполнял sonnet; указание окружения приоритетнее текста плана). ## Findings | Маркер | Суть | Статус | |---|---|---| | R-20…R-26 | решения плана | fixed cd8213b..93e5595 | | R-27 | трейлер Sonnet 5.5 | fixed (процесс) | | O-1 | README «сейчас 9» при v10 | fixed 93e5595 | | O-2 | полный набор ≈2 мин | fixed (наблюдение) | | M-1 | обоснование R-23 устарело после решения 20 хаба | fixed 04e7812 | | M-2 | тест «2xx не JSON» подменяет `HubClient.file`, настоящий транспорт не проверен | deferred | | M-3 | любой 404 `/agent/files` — «файл удалён» (проверять `no_file`) | deferred | | M-4 | docstring `HubError` упоминает только refresh | deferred | | M-5 | ответ на загрузку `{}` и `[123]` без теста | deferred | | M-6 | README: `timeout` без 120 с загрузки | deferred | 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 7 commits 2026-10-16 01:08:14 +03:00
aep merged commit 6740ccf5b8 into main 2026-10-16 09:10:20 +03:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: aep/jira-agent#32
No description provided.