## Why 25.10.2026 сверка открытых follow-up issue с кодом подтвердила дефекты бэкенда хаба. Один из них уже приводит к неверной команде агенту: ключ с пробелами из `ensure_rank` уходит в Jira как есть. Остальные проявляются при нестандартном входе: на кривой запрос хаб отвечает 500 вместо понятного 422, один и тот же кириллический файл превращается в два вложения, при пустом `SDLC_HUB_HOME` данные пишутся в рабочий каталог процесса, после прерванной публикации агента может потеряться прежняя версия. Владелец с ними не сталкивался и не хочет столкнуться. Это пакет C сверки (sdlc-hub#129). ## What Changes - **Параметры команд** (#111 T-F1, #49 M-4): при постановке пакета хаб приводит параметры к каноническому виду. Идентификаторы (ключи, имена спринтов, тип связи, логин, даты, маркер комментария, id вложения) и элементы списков обрезаются по краям. `filename` у `ensure_attachment` обрезается и приводится к NFC, в том числе имя по умолчанию из пути в MCP. Текст (`summary`, `description`, `body`, `goal`) хранится как задан. - **Цифры — только ASCII** (#86 F.1): `attachment_id`, id вложений в состоянии агента, версия агента — только `0-9`. Сейчас `"²"` проходит `isdigit()` и роняет `int()` с 500. - **Форма тела — 422, не 500** (#42 T2.1, #94 T8.1): элемент `issues` в `POST /agent/state` должен быть объектом со строковым `key`, `project` в `POST /wiki/sync` должен быть строкой. - **Файлы хранилища** (#49 M-3): ошибка доступа к файлу (`PermissionError`, `IsADirectoryError` и любая `OSError`) обрабатывается как «файла нет» с предупреждением в лог, а не 500. - **Пустой `SDLC_HUB_HOME`** (#102 T3.2): трактуется как незаданный, каталог данных по умолчанию. - **Публикация агента** (#39 T2.2, M-6): перед публикацией хаб восстанавливает `agent.py` из `agent.py.prev`, если прошлая публикация прервалась; годный `agent.py.prev` не перезаписывается содержимым, не совпадающим с манифестом. - **Уборка настроек** (#64 «выкатка»): ключи `base_jql` и `board_id` объявлены устаревшими и удаляются из `setting` при открытии хаба, как `status_labels`/`transitions_map`. ## Non-Goals - O-3 из закрытой #4 (`check_confirmed` и симметричные типы связей): хаб не знает, какие типы связей симметричны, это знает только агент. Чинится в пакете B: агент передаёт симметричные типы, хаб учитывает их при подтверждении по состоянию. До этого последствие безвредное: вместо подтверждения по состоянию команда ждёт отчёта агента (R-1). - Изменения агентов, веба, MCP-инструментов (кроме имени вложения по умолчанию) и схемы базы. - Прочие маркеры исходных issue остаются в своих issue. ## Impact - Спеки: `commands` (нормализация параметров, цифровые id), `hub-api` (форма тела, файлы хранилища, публикация, каталог данных), `data-model` (требование «Настройки»). - Код: `modules/jira/commands.py`, `modules/jira/hooks.py`, `modules/jira/mirror.py`, `modules/jira/mcp.py`, `modules/jira/fetch.py`, `modules/jira/attachments.py`, `modules/jira/settings.py`, `modules/wiki/api.py`, `core/files.py`, `core/paths.py`, `core/release.py`. - Живая база: при первом старте нового кода из `setting` уйдут `base_jql` и `board_id`. Резервная копия базы делается штатно. - После merge — комментарии в #111, #42, #94, #86, #49, #102, #39, #64 о закрытых маркерах; O-3 — в пакет B.