## Why Мост в ежедневной работе с 13.10.2026; пакеты A (`bridge-reliability`, #9) и B (проверки на живой Jira) закрыты. Осталось три follow-up issue в каждом репозитории (hub#4, #8, #12; agent#4, #8, #12). Пакет D (разбор хвоста hub#4/agent#4, 14.10.2026) разделил их на «в C», «отклонить», «на потом». Этот change — пакет C: мелкие исправления, приведение спек к коду и гигиена, одним change на оба репозитория. Новых возможностей нет. Что чинится по существу: - **M-7 (hub#4)** — каталог данных хаба `0755`, база `0644`, а в базе токены: читаемы любым локальным пользователем. - **M-3 (hub#4, PR #2)** — `rename_note` при переносе `new:N` → ключ удаляет заметку, уже стоящую под настоящим ключом. - **T2.3 (agent#4)** — `prune` перезаписывает журнал без блокировки: запись `finished`, добавленная работающим агентом, теряется (потерянный отчёт). - **M-4 (hub#12)** — поздний `done` с ключом по `ensure_issue`, ставшей `failed` по пределу выдач, отбрасывается: заметка `new:N` не переезжает; у `refresh`, ставшего `failed` по пределу, `sync_run.finished_at` пуст. - **M-5 (hub#12)** — повторное выполнение `refresh` после довыдачи удваивает счётчики `sync_run`. - **M-12 (hub#4)** — полный прогон, вернувший 0 задач, помечает всё зеркало соседями. - **T5.6 (hub#4)** — отменённый пакет с частью выполненных команд показывается «завершён». - **M-3, M-4 (hub#8)** — реле: `HTTPException` от своего HTTP не превращается в 502; `work/` чистится при каждой повторной подготовке, а не только при старте. - **M-2 (hub#12)** — параллельные `connect` к базе старой версии делают по копии на соединение. - **M-3 (hub#12)** — нестроковый `summary` в `ensure_issue` даёт 500 вместо 422. - **M-2 (agent#8)** — ответ папки с неверными типами `status`/`body` роняет агента. - **M-6 (agent#12)** — время последней записи журнала в будущем отключает паузу темпа. - **M-7 (agent#12)** — после перезапуска в `claim` уходит время записи журнала как «последний вызов Jira». - **T3.9 (agent#4)** — Jira хранит текст, правленный в UI, с `\r\n`; агент сравнивает с `\n` из команды и делает лишний `PUT` описания/комментария (проверено на живой Jira 13.10.2026: 71 из 180 задач). Решения владельца 14.10.2026 (разбор D и brainstorming): - состав пакета C — по таблице разбора D (комментарии hub#4 #3323, agent#4 #3326), плюс M-12 и подсказка про `labels`; - T-n без сохранившегося текста ревью — отклонены пачкой; - живая проверка потери отчёта, довыдачи и force-cancel — отдельно, не в этом change; - M-4 (hub#12): поздний отчёт по `failed` по пределу выдач — как по отменённой (ключ в результат, заметка переезжает, статус остаётся `failed`); `refresh`, ставший `failed` по пределу, получает `sync_run.finished_at`; - M-7 (agent#12): в `claim` уходит только время настоящего вызова Jira; оценка из журнала — только для паузы; - CRLF: агент сравнивает описание и тело комментария после замены `\r\n` на `\n`, отправляет как есть; хаб не меняется. ## What Changes - **jira-hub**: - права `0700` на каталог данных и `backups/` (при создании и при старте); - `rename_note` сливает заметки: поле под настоящим ключом сохраняется, если у временной заметки оно пустое; - статус пакета `cancelled`, если пакет отменён и все его команды в терминальных статусах; - `report_result` обрезает `error` до 1500 символов; - поздний отчёт `done` с ключом по `ensure_issue` в `failed` без результата — как по `cancelled`; при переводе `refresh` в `failed` по пределу выдач — `sync_run.finished_at`; - довыдача `refresh` обнуляет `issues_count`/`links_count` его `sync_run`; - полный прогон с `issues_count = 0` не помечает задачи соседями; - `commands.validate`: строковые параметры проверяются на тип (422); - миграция: копия перед миграцией и сама миграция — под одной блокировкой записи, копия одна; - реле: `http.client.HTTPException` → 502; `work/` чистится только при старте реле; строка лога при повторной подготовке не говорит «перезапуск»; - ответ `POST /batches/{id}/cancel` и MCP `batch_cancel` сообщают о команде пакета, уже взятой агентом; - MCP `batch_create`: в описании инструмента — передавать базовые метки (`labels`) в `ensure_issue`; - тесты: `serve --host ` для реле, переименование `test_fresh_definer_still_blocks_queue`, сквозной тест «база v1 → миграция → довыдача 1 → 2»; - `.wt/` в `.gitignore`; `ARCHITECTURE.md` — реле и `relay_dir`. - **jira-agent** (версия 4): - сравнение описания и тела комментария без различия `\r\n`/`\n`; - время журнала в будущем — принимается за «сейчас» (полная пауза); - в `claim` — только время настоящего вызова Jira в этом процессе; - ответ папки с неверными типами `status`/`body` — `ConnectionError` (как нечитаемый JSON); - `prune` берёт блокировку журнала и отказывает при работающем агенте; README; - лог «хаб: хаб не ответил…» без повтора слова. - Спеки: `hub-api`, `data-model`, `commands`, `agent`, `mcp`, `migration` — MODIFIED. Кроме исправлений, спеки приводятся к коду (разбор D): нет настройки `sprint_names`; коды ответов 413/500/502 и 501 на прочие методы; `page`/`last_page` информационные; `GET /issues` — поля зеркала; автообновление — от последнего `sync_run`; MCP `refresh` — id пакета; `new:<строка>` — только для `new_tasks.csv`. Раздел `## Purpose` всех шести спек заполняется (сейчас — заглушка `TBD`, из-за неё падает `openspec validate --specs --strict`). ## Non-goals - Живые проверки потери отчёта, довыдачи, force-cancel и `ensure_link` (agent#12 O-1) — отдельно, на тестовой задаче. - «На потом» из разбора D: ResourceWarning в тестах хаба (M-9/O-4), пробелы тестов (M-10 хаба), точность фейков агента (M-10 агента). - Отклонённые в разборе D пункты (M-4, M-8/T6.12, T5.4, T5.11, T6.5, T6.6, T9.1, T1.1, M-6, M-11 хаба; FM-1…FM-3, O-2, T1.9, N-3, T2.7, T3.2, T3.3, T4.7, T4.11, T5.2, T7.6, «Task 2 minor» агента; T-n без текста). - Автодобавление базовых меток хабом или агентом (T3.7): только подсказка в описании инструмента. - MCP-инструмент отмены отдельной команды: `batch_cancel` лишь подсказывает про `force`. - Подъём `min_agent_version` до 4. ## Impact - `jira-hub`: `paths.py`, `db.py` (миграция под блокировкой, права), `mirror.py` (`rename_note`), `queue.py` (`_status_of`, `report_result`, `_redeliver`, `claim`, `cancel_batch`), `commands.py` (`validate`), `relay.py`, `api.py` (ответ отмены пакета), `mcp_server.py` (`batch_cancel`, `batch_create`), тесты, `.gitignore`, `ARCHITECTURE.md`. - `jira-agent`: `src/agent.py` (`do_ensure_fields`, `do_ensure_comment`, `restore_pace`, `JiraClient.last_call_iso`, `FolderTransport`, `cmd prune`, лог), `README.md`, тесты, `.gitignore`; версия 4. - Контракт хаб ↔ агент: тела запросов не меняются; ответ отмены пакета получает поле `still_claimed`. - Выкатка: хаб — `git pull` + перезапуск launchd (схема не меняется), проверить права каталога; агент v4 — через общую папку, как v3. - Issues: aep/jira-hub#13, aep/jira-agent#15; закрывают hub#8, hub#12, agent#8, agent#12, а hub#4/agent#4 — кроме «на потом».