Агент v9 и run.py v2: устойчивость самообновления, диагностика, фейки (#23) #24

Merged
aep merged 14 commits from feat/23-agent-v9 into main 2026-10-14 23:51:05 +03:00
Owner

Closes #23. Закрывает отложенные находки #22 (M-3…M-7, M-10), #18 (M-2, M-3, M-5, M-6), #4 (M-10).
Спека: aep/jira-hub#26, change agent-v9-hardening (openspec/specs/agent).

Что сделано

  • run.py v2 (LAUNCHER_VERSION = 2): сверка update.json с sha256 agent.py при старте (reconcile) и перед каждым запуском (in_trial): staged при уже подменённом файле → trial (M-5); устаревший trial → rolled_back «пробный период прерван» (M-3); повторная проверка ok после таймаута пробного периода (M-4); код 73 — не сбой версии (M-7); OSError при подмене → rejected «подмена не удалась», запускатель не падает (M-6); удаление *.tmp при старте (M-10).
  • agent.py v9: код 73 при занятом журнале; OSError при подготовке и подтверждении версии — временный сбой / лог; проверка формата agent_release (M-10); одна строка лога при времени журнала в будущем (M-2 #18); HubError — ошибки хаба в refresh с префиксом «хаб: » и «обрыв связи с хабом» (M-6 #18); чистка _take (M-5 #18).
  • Фейки: project = и created >= -Nd в поиске дубля, долгий claim фейка хаба (M-10 #4).
  • Тесты: 227 OK (/usr/bin/python3 -W error::ResourceWarning -m unittest discover -s tests -t .), в т. ч. on_sigterm, trial при перезапуске run.py, будущее время журнала + остановка в паузе (M-3 #18).

Rulings I made

  • R-1…R-5 — в design.md хаба (код 73; подлежащее «хаб: » при обёртке в refresh; неверный agent_release — игнор с логом раз в час; ok в последний момент — перезапуск без паузы; объём правки фейков).
  • R-6 — в тесте 4xx refresh токен ASCII: кириллица в Authorization падает до запроса.
  • R-7 — пустой/None sha256 при trial — устаревший пробный период (нечитаемый agent.py иначе «совпадал» бы).
  • R-8 — фраза про код 73 в README — в конце абзаца «Остановка…» (якорь плана не совпал).
  • R-9 — раздельные таймеры подсказок в Updater (решение 10 дизайна хаба обновлено).
  • R-10 — финальное ревью I-1: подтверждённая версия не откатывается, если агент после ok сам перезаписал update.json и упал.

Находки ревью

  • Исправлены: I-1 (6b31098), M-3 (b57f815), M-4 = T2.1 (af3e9c4), M-8 (2559318, записан как R-9).
  • Отклонены: T2.2 (_drop_new глотает OSError — по плану, безопасно), T3.2 (_hub оборачивает только ConnectionError/HttpError — вне спеки), M-7 (порядок слов лога кода 73 — смысл совпадает).
  • Deferred (в follow-up при закрытии): T1.1, T3.1, T4.1, T4.2, T4.3, T4.4 / M-9 (гигиена тестов и фейков), T5.1 / M-1 / O-3 (OSError в os.replace при rollback/reconcile), T5.2 / M-2 (reconcile не проверяет результат записи trial), M-5 / O-2 (не-ASCII токен хаба роняет агента — было до ветки), M-6 (rejected при н��записанном trial без текста ошибки), M-10 (trial_sha считается дважды).

Выкатка (порядок важен)

  1. Merge этого PR и aep/jira-hub#26-PR.
  2. uv run --project ../jira-hub jira-hub agent publish src/agent.py из основного checkout на main (v9; v6–v8 заняты живой проверкой).
  3. Дождаться в agent_status «обновление: ok v8 → v9».
  4. Владелец: launchctl unload ~/Library/LaunchAgents/ru.aepif.jira-agent.plist, скопировать run.py в ~/jira-agent-bundle, launchctl load … → «запускатель: v2».

🤖 Generated with Claude Code

Closes #23. Закрывает отложенные находки #22 (M-3…M-7, M-10), #18 (M-2, M-3, M-5, M-6), #4 (M-10). Спека: aep/jira-hub#26, change `agent-v9-hardening` (`openspec/specs/agent`). ## Что сделано - **run.py v2** (`LAUNCHER_VERSION = 2`): сверка `update.json` с sha256 `agent.py` при старте (`reconcile`) и перед каждым запуском (`in_trial`): `staged` при уже подменённом файле → `trial` (M-5); устаревший `trial` → `rolled_back` «пробный период прерван» (M-3); повторная проверка `ok` после таймаута пробного периода (M-4); код 73 — не сбой версии (M-7); `OSError` при подмене → `rejected` «подмена не удалась», запускатель не падает (M-6); удаление `*.tmp` при старте (M-10). - **agent.py v9**: код 73 при занятом журнале; `OSError` при подготовке и подтверждении версии — временный сбой / лог; проверка формата `agent_release` (M-10); одна строка лога при времени журнала в будущем (M-2 #18); `HubError` — ошибки хаба в `refresh` с префиксом «хаб: » и «обрыв связи с хабом» (M-6 #18); чистка `_take` (M-5 #18). - **Фейки**: `project =` и `created >= -Nd` в поиске дубля, долгий `claim` фейка хаба (M-10 #4). - Тесты: 227 OK (`/usr/bin/python3 -W error::ResourceWarning -m unittest discover -s tests -t .`), в т. ч. `on_sigterm`, `trial` при перезапуске `run.py`, будущее время журнала + остановка в паузе (M-3 #18). ## Rulings I made - **R-1…R-5** — в design.md хаба (код 73; подлежащее «хаб: » при обёртке в refresh; неверный `agent_release` — игнор с логом раз в час; `ok` в последний момент — перезапуск без паузы; объём правки фейков). - **R-6** — в тесте 4xx `refresh` токен ASCII: кириллица в Authorization падает до запроса. - **R-7** — пустой/`None` sha256 при `trial` — устаревший пробный период (нечитаемый `agent.py` иначе «совпадал» бы). - **R-8** — фраза про код 73 в README — в конце абзаца «Остановка…» (якорь плана не совпал). - **R-9** — раздельные таймеры подсказок в `Updater` (решение 10 дизайна хаба обновлено). - **R-10** — финальное ревью I-1: подтверждённая версия не откатывается, если агент после `ok` сам перезаписал `update.json` и упал. ## Находки ревью - Исправлены: I-1 (6b31098), M-3 (b57f815), M-4 = T2.1 (af3e9c4), M-8 (2559318, записан как R-9). - Отклонены: T2.2 (`_drop_new` глотает OSError — по плану, безопасно), T3.2 (`_hub` оборачивает только ConnectionError/HttpError — вне спеки), M-7 (порядок слов лога кода 73 — смысл совпадает). - **Deferred** (в follow-up при закрытии): T1.1, T3.1, T4.1, T4.2, T4.3, T4.4 / M-9 (гигиена тестов и фейков), T5.1 / M-1 / O-3 (`OSError` в `os.replace` при `rollback`/`reconcile`), T5.2 / M-2 (`reconcile` не проверяет результат записи `trial`), M-5 / O-2 (не-ASCII токен хаба роняет агента — было до ветки), M-6 (`rejected` при н��записанном `trial` без текста ошибки), M-10 (`trial_sha` считается дважды). ## Выкатка (порядок важен) 1. Merge этого PR и aep/jira-hub#26-PR. 2. `uv run --project ../jira-hub jira-hub agent publish src/agent.py` из основного checkout на main (v9; v6–v8 заняты живой проверкой). 3. Дождаться в `agent_status` «обновление: ok v8 → v9». 4. Владелец: `launchctl unload ~/Library/LaunchAgents/ru.aepif.jira-agent.plist`, скопировать `run.py` в `~/jira-agent-bundle`, `launchctl load …` → «запускатель: v2». 🤖 Generated with [Claude Code](https://claude.com/claude-code)
aep added 14 commits 2026-10-14 23:48:40 +03:00
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Диск полон или нет прав при записи agent.py.new, selftest или update.json
больше не роняет агент трейсбеком: это временный сбой, повтор через 5 минут.
Ошибка записи update.json при отказе версии только логируется.
Неполная публикация (version не int, sha256 не 64 hex в нижнем регистре)
отбрасывается с подсказкой не чаще раза в час; таймеры подсказок разделены по видам.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
wait_child запоминает подтверждение (любое состояние update.json, кроме trial этой версии, пока агент жив),
а итоговое решение учитывает и случай, когда ok и следующая запись уложились между опросами.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aep merged commit f28df32f66 into main 2026-10-14 23:51:05 +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#24
No description provided.