From e75cf79e79aac8681731538cffa607f317b32e02 Mon Sep 17 00:00:00 2001 From: Alexey Martemyanov Date: Tue, 29 Sep 2026 12:46:04 +0600 Subject: [PATCH] [2026-09-29] eagle: personal/plans/mattermost-mention-thread-autoresponse.md personal/plans/mattermost-mention-thread-autoresponse.md.bak-mention-result personal/tech/hermes-whale-mattermost-transport.md --- .../mattermost-mention-thread-autoresponse.md | 135 ++++++++++++++++++ ...-thread-autoresponse.md.bak-mention-result | 98 +++++++++++++ .../tech/hermes-whale-mattermost-transport.md | 40 ++++++ 3 files changed, 273 insertions(+) create mode 100644 personal/plans/mattermost-mention-thread-autoresponse.md create mode 100644 personal/plans/mattermost-mention-thread-autoresponse.md.bak-mention-result diff --git a/personal/plans/mattermost-mention-thread-autoresponse.md b/personal/plans/mattermost-mention-thread-autoresponse.md new file mode 100644 index 00000000..740990f8 --- /dev/null +++ b/personal/plans/mattermost-mention-thread-autoresponse.md @@ -0,0 +1,135 @@ +--- +tags: + - hermes + - mattermost + - mention + - adapter + - whale +type: plan +namespace: personal +status: implemented — awaiting gateway restart +created: '2026-09-29' +updated: '2026-09-29' +--- +# План: MM mention-gating — авто-ответ в треде с ботом + +**Дата:** 2026-09-29 +**Статус:** Реализовано, ждёт рестарта gateway (приёмка Alex в UI) + +## Итог + +| Что | Значение | +|---|---| +| Файл | `~/.hermes/hermes-agent/plugins/platforms/mattermost/adapter.py` | +| md5 до | `9f3def29d90d00287cdbca3db000c513` | +| md5 после | `ed8c4b7735e3371f697c20cfbd11e421` | +| Бэкап | `~/.hermes/hermes-whale/backups/20260929-mm-mention/adapter.py` | +| Скрипт | `/tmp/mm-thread-mention.py` (идемпотентный) | +| Тесты | `tests/gateway/test_mattermost.py` — 46 passed (было 43, +3) | +| Коммит hermes-agent | `9b46ba791a` feat(mattermost): allow thread replies without @mention | +| Push | `207a1de16c..9b46ba791a main -> main` → github.com:mallexxx/hermes-agent.git | + +### Что именно изменено + +`_handle_ws_event`, перед mention-гейтом: + +```python +is_thread_reply = bool(post.get("root_id")) +... +if ( + require_mention + and not is_free_channel + and not has_mention + and not is_thread_reply +): + return +``` + +Три новых теста: +- `test_thread_reply_without_mention_responds` — тред без меншна → ответ есть +- `test_channel_root_without_mention_still_skipped` — корень канала без меншна → тишина +- `test_thread_reply_with_mention_strips_mention` — меншн в треде всё ещё убирается из текста + +Остаток: рестарт gateway. Без него патч не подхватится (адаптер импортируется при старте). +`gateway run --replace` из активной сессии её убьёт — рестарт делает Alex. + +## Задача (Alex, дословно) + +> «в канале — меншен обязателен, в треде где только с ботом переписка — авто, без меншена» + +## Проблема (подтверждена фактами) + +`plugins/platforms/mattermost/adapter.py:734` — гейт применяется к **любому** не-DM: + +```python +if channel_type_raw != "D": # тред = channel_type "O" → гейт срабатывает + ... + if require_mention and not is_free_channel and not has_mention: + return # молча дроп, inbound не создаётся +``` + +**Доказательство (2026-09-29, канал `hermes-maintenance` = `a6nyh77eyjbn5c1owh1i8eebee`):** + +| Время | Пост | Меншн | inbound в gateway.log | +|---|---|---|---| +| 12:38:01 | `@whale` | ✅ | ✅ есть | +| 12:38:40 | `тут, отлично. как нам сделать бэкап...` | ❌ | ❌ **нет** (ответа не было) | + +Пост 12:38:40 — в треде `pcoiddzrqty3ipqtozgcs9ttte`, начатом ботом. Меншн не нужен, но требуется. + +## Решение + +Пропускать mention-гейт, когда пост находится **в треде** (`root_id` задан). +В корне канала меншн остаётся обязательным. + +### Критерий (выбран) + +**Тред = `root_id` непустой.** Просто, детерминированно, не требует API-запросов. + +Обоснование: чтобы ответить в треде, бот должен быть в канале. Треды канала — общие +рабочие ветки; вовлечение в тред человеком = приглашение. Дополнительный критерий +«бот уже отвечал в этом треде» требует запроса к API на каждое сообщение (латентность + +зависимость от прав) и не даёт выигрыша: в канале бот и так отвечает на `@whale`. + +### Правка + +В `_handle_ws_event` перед mention-гейтом вычислить `root_id` и добавить его в условие: + +```python +is_thread_reply = bool(post.get("root_id")) +... +if require_mention and not is_free_channel and not has_mention and not is_thread_reply: + return +``` + +Плюс: стрип меншна выполнять как раньше (если меншн есть — убрать из текста). + +### Что НЕ меняется + +- Корень канала без `@whale` → по-прежнему молчит. +- `MATTERMOST_FREE_RESPONSE_CHANNELS` — не трогаем. +- DM — не затронуты. +- `MATTERMOST_REQUIRE_MENTION=true` — остаётся. + +## Шаги + +1. Коммит ДО (`hermes-agent`, ветка `main`, HEAD `207a1de16c`). +2. Правка adapter.py — скрипт `python3 /tmp/.py`, не sed. +3. Тест: `pytest plugins/platforms/mattermost/ tests/ -k mattermost -o "addopts="` (если есть). +4. Коммит ПОСЛЕ. +5. Рестарт gateway — **делает Alex** (`gateway run --replace` из этой сессии её убьёт). +6. Приёмка Alex в UI: пост в треде без меншна → ответ есть; пост в корне канала без меншна → ответа нет. + +## Питфоллы + +- 🔴 `gateway run --replace` из этой сессии убивает саму сессию (инцидент 2026-09-29 11:31). +- 🔴 Логи читать из `~/.hermes/hermes-whale/logs/`, не из `~/.hermes/logs/`. +- Адаптер читает `config.extra.*` ИЛИ env — при правке поведение env перебивает config + (см. `_apply_yaml_config`, строки 1108-1114). +- Логи уровня DEBUG не пишутся — `skipping non-DM message without @mention` в `gateway.log` + не виден (`grep -c` вернул 0 при 1.6 МБ лога). Судить по наличию/отсутствию `inbound message`. + +## Связанные заметки + +- [[personal/tech/hermes-whale-mattermost-transport.md]] — транспорт, env-ключи, инцидент с рестартом, диагностика «бот молчит в канале» +- [[personal/tech/hermes-pairing-multi-profile.md]] — pairing diff --git a/personal/plans/mattermost-mention-thread-autoresponse.md.bak-mention-result b/personal/plans/mattermost-mention-thread-autoresponse.md.bak-mention-result new file mode 100644 index 00000000..aadaf2a9 --- /dev/null +++ b/personal/plans/mattermost-mention-thread-autoresponse.md.bak-mention-result @@ -0,0 +1,98 @@ +--- +tags: + - hermes + - mattermost + - mention + - adapter + - whale +type: plan +namespace: personal +status: plan approved — in progress +created: '2026-09-29' +updated: '2026-09-29' +--- +# План: MM mention-gating — авто-ответ в треде с ботом + +**Дата:** 2026-09-29 +**Статус:** план утверждён Alex, выполняется + +## Задача (Alex, дословно) + +> «в канале — меншен обязателен, в треде где только с ботом переписка — авто, без меншена» + +## Проблема (подтверждена фактами) + +`plugins/platforms/mattermost/adapter.py:734` — гейт применяется к **любому** не-DM: + +```python +if channel_type_raw != "D": # тред = channel_type "O" → гейт срабатывает + ... + if require_mention and not is_free_channel and not has_mention: + return # молча дроп, inbound не создаётся +``` + +**Доказательство (2026-09-29, канал `hermes-maintenance` = `a6nyh77eyjbn5c1owh1i8eebee`):** + +| Время | Пост | Меншн | inbound в gateway.log | +|---|---|---|---| +| 12:38:01 | `@whale` | ✅ | ✅ есть | +| 12:38:40 | `тут, отлично. как нам сделать бэкап...` | ❌ | ❌ **нет** (ответа не было) | + +Пост 12:38:40 — в треде `pcoiddzrqty3ipqtozgcs9ttte`, начатом ботом. Меншн не нужен, но требуется. + +## Решение + +Пропускать mention-гейт, когда пост находится **в треде** (`root_id` задан). +В корне канала меншн остаётся обязательным. + +### Критерий (выбран) + +**Тред = `root_id` непустой.** Просто, детерминированно, не требует API-запросов. + +Обоснование: чтобы ответить в треде, бот должен быть в канале. Треды канала — общие +рабочие ветки; вовлечение в тред человеком = приглашение. Дополнительный критерий +«бот уже отвечал в этом треде» требует запроса к API на каждое сообщение (латентность + +зависимость от прав) и не даёт выигрыша: в канале бот и так отвечает на `@whale`. + +### Правка + +В `_handle_ws_event` перед mention-гейтом вычислить `root_id` и добавить его в условие: + +```python +is_thread_reply = bool(post.get("root_id")) +... +if require_mention and not is_free_channel and not has_mention and not is_thread_reply: + return +``` + +Плюс: стрип меншна выполнять как раньше (если меншн есть — убрать из текста). + +### Что НЕ меняется + +- Корень канала без `@whale` → по-прежнему молчит. +- `MATTERMOST_FREE_RESPONSE_CHANNELS` — не трогаем. +- DM — не затронуты. +- `MATTERMOST_REQUIRE_MENTION=true` — остаётся. + +## Шаги + +1. Коммит ДО (`hermes-agent`, ветка `main`, HEAD `207a1de16c`). +2. Правка adapter.py — скрипт `python3 /tmp/.py`, не sed. +3. Тест: `pytest plugins/platforms/mattermost/ tests/ -k mattermost -o "addopts="` (если есть). +4. Коммит ПОСЛЕ. +5. Рестарт gateway — **делает Alex** (`gateway run --replace` из этой сессии её убьёт). +6. Приёмка Alex в UI: пост в треде без меншна → ответ есть; пост в корне канала без меншна → ответа нет. + +## Питфоллы + +- 🔴 `gateway run --replace` из этой сессии убивает саму сессию (инцидент 2026-09-29 11:31). +- 🔴 Логи читать из `~/.hermes/hermes-whale/logs/`, не из `~/.hermes/logs/`. +- Адаптер читает `config.extra.*` ИЛИ env — при правке поведение env перебивает config + (см. `_apply_yaml_config`, строки 1108-1114). +- Логи уровня DEBUG не пишутся — `skipping non-DM message without @mention` в `gateway.log` + не виден (`grep -c` вернул 0 при 1.6 МБ лога). Судить по наличию/отсутствию `inbound message`. + +## Связанные заметки + +- [[personal/tech/hermes-whale-mattermost-transport.md]] — транспорт, env-ключи, инцидент с рестартом +- [[personal/tech/hermes-pairing-multi-profile.md]] — pairing diff --git a/personal/tech/hermes-whale-mattermost-transport.md b/personal/tech/hermes-whale-mattermost-transport.md index 43f3a6b9..9ff8aa07 100755 --- a/personal/tech/hermes-whale-mattermost-transport.md +++ b/personal/tech/hermes-whale-mattermost-transport.md @@ -260,6 +260,46 @@ ssh kraken "docker exec mm-postgres psql -U mmuser -d mattermost -t -c \ ⚠️ Без членства в канале `@whale` не работает даже при `REQUIRE_MENTION=true` — упоминание не создаёт доставку, оно лишь фильтр поверх уже приходящих событий. +### ✅ Тред-посты больше не требуют меншна (патч 2026-09-29) + +**Проблема:** mention-гейт применялся к **любому** не-DM, включая треды. Пост в треде, +начатом ботом, без `@whale` молча дропался (подтверждено: пост 12:38:40 в треде +`pcoiddzrqty3ipqtozgcs9ttte` не попал в `gateway.log`). + +**Решение (коммит `9b46ba791a`, hermes-agent):** + +```python +# plugins/platforms/mattermost/adapter.py, _handle_ws_event +is_thread_reply = bool(post.get("root_id")) +... +if ( + require_mention + and not is_free_channel + and not has_mention + and not is_thread_reply +): + return +``` + +**Правило после патча:** + +| Место поста | Меншн `@whale` | +|---|---| +| Корень канала | ✅ обязателен | +| Тред (`root_id` непустой) | ❌ не нужен | +| DM | ❌ не нужен (был и раньше) | + +`MATTERMOST_REQUIRE_MENTION=true` остаётся; `FREE_RESPONSE_CHANNELS` не тронут. +Если меншн в треде всё же написан — он убирается из текста перед отправкой агенту. + +⚠️ **Патч активен только после рестарта gateway** — адаптер импортируется при старте. +Рестарт делает Alex (`gateway run --replace` из активной сессии её убивает, см. §Инцидент). + +**Файлы:** +- План + итог: [[personal/plans/mattermost-mention-thread-autoresponse.md]] +- Бэкап адаптера: `~/.hermes/hermes-whale/backups/20260929-mm-mention/adapter.py` +- Тесты: `tests/gateway/test_mattermost.py` — 46 passed (3 новых) + ### 📌 Питфолл диагностики: `mattermost psql` В контейнере `mattermost` **нет `psql`** (`exec: "psql": executable file not found`).