## Why У хаба накопились отложенные находки трёх change'ей: самообновления (#25), пакета C (#16) и первого change'а (#4, «на потом»). Разбор против `main` 8229bba (15.10.2026) показал, что актуальны все пункты, кроме M-4 #25, который исправило слияние web-app. Вред у одного пользователя небольшой, но заметный: - при полном диске `jira-hub agent publish` падает с трейсбеком и оставляет публикацию в состоянии «404 до следующей публикации»; - после перезапуска хаба `agent_status` пишет «без запускателя», хотя агент под `run.py`; - потерянный отчёт `ensure_fields` по задаче, у которой описание с `\r\n` (71 из 180 правлены в UI), закрывается довыдачей вместо подтверждения по состоянию; - в тестах 87 незакрытых соединений sqlite и пробелы в покрытии. Решения владельца 15.10.2026: всё актуальное — одним пакетом; M-4 #25 закрыть, minor-2 #16 отклонить; агентский #26 в пакет не входит; работать параллельно с #29 (web-app follow-ups), она трогает только `h_app`. ## What Changes - **Публикация агента** (`release.py`, `cli.py`): запись с `fsync`; прежний `agent.py` переименовывается в `agent.py.prev`, при сбое записи манифеста возвращается; `OSError` → «не удалось записать публикацию: <ошибка>», код 1, временные файлы удалены; манифест годен, только если `version` — целое (не bool) и `sha256` — 64 hex-символа; не-UTF-8 файл при совпавшем sha — 404, а не 500; предупреждение о битом манифесте — один раз на каждую новую ошибку. - **`GET /agent`**: поле `agent_reported` (был ли `claim` с момента запуска хаба); пока его нет — подсказки про `run.py` нет; MCP `agent_status` пишет «запускатель: неизвестно (агент ещё не выходил на связь после перезапуска хаба)». - **`PUT /settings`**: ответ — все настройки, как `GET /settings` (включая `settings_version`). - **Очередь**: зависимая команда, пропущенная из-за force-отменённой `ensure_issue`, получает «создание задачи new:N отменено». - **Подтверждение по состоянию**: строки `ensure_fields` сравниваются без различия `\r\n` и `\n`. - **Реле**: обработанные папки сравниваются по `resolve()`. - **Тесты**: bool в строковом параметре и пустой список; `finished_at` у `sync_run` только для `refresh`; 501 на прочие методы; `epics.csv` без ключа; «подготовлена заново» в реле; предупреждение `min_agent_version`; офлайн-агент; `tick` с проверками; ноль `ResourceWarning`; читаемый `commands._type_error`. ## Capabilities ### New Capabilities ### Modified Capabilities - `hub-api`: ответ `PUT /settings`; публикация версии агента (сбой записи, проверка манифеста, `agent_reported`). - `mcp`: строка запускателя в `agent_status`. - `commands`: текст `skipped` при отменённом создании; подтверждение `ensure_fields` без различия перевода строки. ## Non-Goals - сохранение `launcher_version` в БД (запись на каждый claim; «неизвестно» честнее устаревшего значения); - агент (aep/jira-agent#26) — в следующий change агента; - minor-2 #16 (дубль предупреждения при неудачном `chmod`) — отклонено; - раздача веб-приложения (`h_app`) — в #29. ## Impact - jira-hub (issue aep/jira-hub#32): `src/jira_hub/release.py`, `cli.py`, `api.py` (`Hub`, `h_agent_get`, `h_settings_put`), `queue.py` (`_next`), `commands.py` (`check_confirmed`, `_type_error`), `relay.py` (`_cleaned`), `mcp_server.py` (`fmt_agent`), `tests/`, ARCHITECTURE.md при необходимости. - Пересечение с `feat/29-web-app-followups`: `api.py` (другие функции) и одна строка `tests/test_api.py`; дельты спек трогают разные требования (`hub-api` «Раздача веб-приложения» у #29). - Выкатка: после merge — pull на Mac mini, перезапуск хаба (владелец), `/mcp` → reconnect в сессиях Claude.