Andrey Epifancev 529d7f3b2d docs: рулинг R-13 (F-1 deferred)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014Typ5sXWNMFirr2va2uL8o
2026-10-12 00:41:04 +04:00

22 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# bridge-core (агент) — решения
Спека изменения лежит в репозитории jira-hub: `jira-hub/openspec/changes/bridge-core/` (specs/agent, specs/commands, specs/hub-api, design.md). Здесь — только решения, принятые при реализации агента без обсуждения с человеком.
## Decisions made without discussion
| # | Дата | Решение | Обоснование | Цена ошибки |
|---|---|---|---|---|
| 1 | 2026-10-11 | `tests/__init__.py` добавляет каталог `tests/` в `sys.path` (R-1) | Тесты из плана импортируют `_common`/`fake_jira` по простому имени, при `discover -s tests -t .` иначе ImportError | Мелкая: переписать импорты в тестах на относительные |
| 2 | 2026-10-11 | Потолок на `Retry-After` не вводим (R-2) | Спека: «ждать `Retry-After`»; потолок тихо нарушает требование сервера | Агент может уснуть надолго при аномальном заголовке; лечится потолком позже |
| 3 | 2026-10-11 | Журнал: не лечим права существующего файла и не блокируем prune/append flock'ом; запрет `prune` при работающем агенте — в README (R-3) | Журнал создаётся этим же кодом (0600); `prune` — ручная команда раз в месяц | Редкая потеря записи журнала при гонке prune/run; лечится flock |
| 4 | 2026-10-11 | Minor-замечания ревью Task 3 (T3.1, T3.3–T3.6, T3.8: пагинация поиска дубля, флаги existed/created, режим epic_link, префикс маркера, общий except в run, тесты) чиним одной финальной волной, а не по месту (R-4) | Не блокируют Task 4–5; одна волна дешевле | Task 4–5 унаследуют общий `run`; ошибки будут чиниться после |
| 5 | 2026-10-11 | Неизвестный `link_type` берётся как сырое имя типа Jira (fallback), без `failed` (R-5) | Так же делает хаб в `check_confirmed`; допускает ручной ввод имён Jira | Опечатка в типе даст HTTP-ошибку Jira вместо понятной ошибки агента |
| 6 | 2026-10-11 | Спринт в `refresh` берётся из Agile API по активным/будущим спринтам доски, а не из поля `search`; закрытые спринты дают `sprint = null` (R-6) | В настройках хаба нет id поля спринта (`field_ids` его не содержит); план Task 5 выбрал Agile | Исторические имена спринтов затрутся при полном refresh; лечится полем спринта в настройках |
| 7 | 2026-10-11 | Бисекция чанка `key in (...)` при 400 принята без лимита вызовов (до ~2·m·log2(n)); если не найден ни один ключ — ошибка, а не `missing` (R-7) | Иначе refresh с удалённой задачей падает целиком; лимит вызовов усложняет без выгоды при редких удалениях | При массовом удалении задач — всплеск запросов и риск 429 (агент их переживает) |
| 8 | 2026-10-11 | Общий `except Exception` стоит в `Runner.execute` (не в `Executor.run`); minor-находки T3.x/T5.x/T6.x чиним одной финальной волной, включая ложный `failed` для `ensure_issue` при ConnectionError из Jira (R-8) | Исключение вне HttpError/ConnectionError не должно ронять цикл и вызывать зацикленное восстановление; одна волна дешевле | Ложный `failed` у `ensure_issue` оставит временный ключ неразрешённым, а задача в Jira уже создана |
| 9 | 2026-10-12 | В журнал пишется запись `claimed` сразу после `claim`, до паузы; `unfinished_started`, `recover`, `prune` считают её открывающей; `started` по-прежнему после паузы (R-9) | Иначе остановка агента в паузе/claim оставляет команду `claimed` в хабе навсегда (хаб не переиздаёт), а лечение cancel+retry не восстанавливает зависимые команды пакета | Формат журнала шире, чем в спеке (лишний `kind`); старые журналы совместимы |
| 10 | 2026-10-12 | `Runner.execute` повторяет команду до 3 раз через проверку при ConnectionError/HTTP 5xx, не записывая `finished`; затем `failed` «результат неизвестен, повтор безопасен» (R-10) | Неоднозначный исход записи в Jira (обрыв после POST) нельзя отдавать как `failed`: для `ensure_issue` хаб пропустит зависимые команды; все команды идемпотентны | Лишние задержки при недоступной Jira |
| 11 | 2026-10-12 | Запрошенное, но не настроенное поле (epic_key, planned_start/end) даёт `failed`, а не молчаливый `done` (R-11) | Ложный успех хаб запишет в зеркало как выполненный | Команды падают, пока хаб не настроен |
| 12 | 2026-10-12 | `agent_version` добавляется в отчёт и в `/agent/state` (R-12) | Спека: версия «в каждом отчёте»; хаб лишние поля игнорирует | Нет |
| 13 | 2026-10-12 | F-1 (повтор по R-10 не ждёт 30 с, если Jira недоступна с первого вызова и `last_call_at` старый) оставлен как есть, deferred (R-13) | Вторая волна фиксов не предусмотрена процессом; последствие — три быстрых повтора и `failed «результат неизвестен», повтор безопасен`: без потери данных и без дублей (поиск дубля идемпотентен) | Недоступная Jira даст `failed` за секунды вместо ~90 с; лечится фиксированным сном `max(pause,30)` от момента отказа в ветке retry |