| 1 | # ADR 0143: Intercom — participant lens ленты (All / Humans / Agents / System) |
| 2 | |
| 3 | **Статус:** Accepted |
| 4 | **Дата:** 2026-05-24 |
| 5 | |
| 6 | ## Связанные ADR |
| 7 | |
| 8 | | ADR | Роль | |
| 9 | |-----|------| |
| 10 | | [0080](0080-intercom-naming-and-multi-party-channel-model.md) | Intercom как канал; роли human / agent / system | |
| 11 | | [0045](0045-agent-chat-persistence-event-log-and-projections.md) | Event log — полный log; lens = **проекция** | |
| 12 | | [0123](0123-intercom-full-skia-surface-evolution.md) | Skia chrome + лента; lens в **chrome**, не в скролле | |
| 13 | | [0127](0127-intercom-spine-and-topic-tabs-chrome-navigation.md) | Spine + topic tabs; lens — **ортогональная** ось в том же chrome | |
| 14 | | [0142](0142-intercom-open-wire-pluggable-transports.md) | Wire по `sender_role`; lens **не** transport channel | |
| 15 | | [0119](0119-chat-slash-commands-intercom-surface.md) | `IntercomMessageAudience.SelfOnly` vs `Channel` — доставка, не lens | |
| 16 | | [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) | Export/MCP — полный log, без фильтра lens | |
| 17 | | [0144](0144-intercom-team-transport-cide-sync-and-reference-service.md) | Transport v1 — human fan-out; lens Agents/System остаются локальными | |
| 18 | |
| 19 | ### Вне ADR |
| 20 | |
| 21 | | Документ / код | Роль | |
| 22 | |----------------|------| |
| 23 | | [intercom-ux-reference-slack-mattermost-v1.md](../design/intercom-ux-reference-slack-mattermost-v1.md) | Flat feed, role rail — lens дополняет, не пузыри | |
| 24 | | [`IntercomMessageAudience`](../../Models/Intercom/IntercomMessageAudience.cs) | **Audience** = кому *доставлено* сообщение; **не** путать с lens | |
| 25 | |
| 26 | ## Резюме |
| 27 | |
| 28 | **Принято:** в Intercom вводится **participant lens** (вид ленты) — переключатель в **Skia chrome**, который фильтрует **отображение** сообщений текущей темы по роли отправителя: |
| 29 | |
| 30 | | Lens | Показывает | |
| 31 | |------|------------| |
| 32 | | **All** | human + agent + system (по умолчанию) | |
| 33 | | **Humans** | только `human` | |
| 34 | | **Agents** | только `agent` | |
| 35 | | **System** | только `system` (сборка, git, MCP-статус, slash-outcome и т.п.) | |
| 36 | |
| 37 | Lens — **клиентская проекция** над event log; **не** отдельные комнаты в transport, **не** дублирование **topic**, **не** замена [`IntercomMessageAudience.Channel`](../../Models/Intercom/IntercomMessageAudience.cs). |
| 38 | |
| 39 | --- |
| 40 | |
| 41 | ## Контекст |
| 42 | |
| 43 | В длинной теме лента смешивает реплики людей, агента и системные строки. Оператору нужно быстро: |
| 44 | |
| 45 | - читать **только команду** (Humans); |
| 46 | - разбирать **только ход агента** (Agents); |
| 47 | - смотреть **только инфраструктурный шум** (System) — CI, git, tool status; |
| 48 | - или видеть **всё** (All). |
| 49 | |
| 50 | Идея «каналов Agent/Humans» обсуждалась в связи с [0142](0142-intercom-open-wire-pluggable-transports.md); без фиксации границ возникает путаница с: |
| 51 | |
| 52 | - **topic** ([0072](0072-chat-topic-cards-intent-melody-keyboard-contract.md)) — *о чём* линия работы; |
| 53 | - **`IntercomMessageAudience`** — *кому доставлено* (`Channel` / `SelfOnly`); |
| 54 | - **transport channel** (Matrix room, MM channel) — слой B [0132](0132-intercom-federated-transport-and-multi-client-boundary.md). |
| 55 | |
| 56 | --- |
| 57 | |
| 58 | ## Решение |
| 59 | |
| 60 | ### 1. Термины (нормативно) |
| 61 | |
| 62 | | Термин | Значение | |
| 63 | |--------|----------| |
| 64 | | **Participant lens** (`FeedParticipantLens`) | UI-фильтр ленты по `sender_role` | |
| 65 | | **Topic** | Линия работы / тред; lens применяется **внутри** выбранной темы | |
| 66 | | **Audience** | Доставка исходящего (`Channel` \| `SelfOnly`); **ортогонально** lens | |
| 67 | | **Transport channel** | Внешний store (Matrix/MM); **не** lens | |
| 68 | |
| 69 | В продуктовом тексте **не** называть lens «каналом» без уточнения «вид ленты». |
| 70 | |
| 71 | ### 2. Модель lens |
| 72 | |
| 73 | ```mermaid |
| 74 | flowchart LR |
| 75 | subgraph log["Event log (полный)"] |
| 76 | H[human] |
| 77 | A[agent] |
| 78 | S[system] |
| 79 | end |
| 80 | subgraph lenses["Participant lens (chrome)"] |
| 81 | All[All] |
| 82 | Hum[Humans] |
| 83 | Ag[Agents] |
| 84 | Sys[System] |
| 85 | end |
| 86 | log --> All |
| 87 | H --> Hum |
| 88 | A --> Ag |
| 89 | S --> Sys |
| 90 | ``` |
| 91 | |
| 92 | | `FeedParticipantLens` | Предикат на сообщение | |
| 93 | |----------------------|------------------------| |
| 94 | | `All` | всегда `true` | |
| 95 | | `Humans` | `role == human` | |
| 96 | | `Agents` | `role == agent` | |
| 97 | | `System` | `role == system` | |
| 98 | |
| 99 | **Роль** — та же, что в wire [0142](0142-intercom-open-wire-pluggable-transports.md) и event types [0045](0045-agent-chat-persistence-event-log-and-projections.md). Новое поле в событии **не требуется** для v1. |
| 100 | |
| 101 | **Классификация `system`:** при записи события отправитель уже помечен `system` (build, git, orchestration, локальный slash-outcome в ленте с меткой «Система» — см. [intercom-ux-reference](../design/intercom-ux-reference-slack-mattermost-v1.md)). Lens **не** переклассифицирует задним числом. |
| 102 | |
| 103 | ### 3. UI и chrome ([0127](0127-intercom-spine-and-topic-tabs-chrome-navigation.md)) |
| 104 | |
| 105 | - Переключатель lens — в **Skia chrome** (segmented control / chips), **над** скроллом ленты, **рядом** с topic tabs / spine — не внутри Items ленты. |
| 106 | - **По умолчанию:** `All`. |
| 107 | - **Сохранение:** последний lens — в `[code_navigation_map]`-подобной секции или `[intercom]` в settings (имя TOML — при внедрении); опционально **per-topic** память (v1.1). |
| 108 | - **Пустая лента:** явная подпись «Нет сообщений для Humans» + опционально «N скрыто» при активном фильтре ≠ All. |
| 109 | - **Role rail** ([0123](0123-intercom-full-skia-surface-evolution.md)): при узком lens все видимые строки одной роли — rail может **схлопываться** или оставаться (продуктовый выбор при реализации; default — оставить для единообразия hit-target). |
| 110 | |
| 111 | ### 4. Composer и исходящие сообщения |
| 112 | |
| 113 | | Правило | Содержание | |
| 114 | |---------|------------| |
| 115 | | Lens ≠ адресация | Выбор **Humans** **не** означает «отправить только людям» | |
| 116 | | Compose | По-прежнему в общий поток темы (`IntercomMessageAudience.Channel`), если не задан иной audience | |
| 117 | | SelfOnly | Slash / `/help` — `SelfOnly`; не показываются в lens Humans/Agents/System, только в All (или отдельная политика: SelfOnly всегда только локально и не в export) | |
| 118 | |
| 119 | Приватная адресация «только агенту» — **не** этот ADR; отдельное расширение audience/recipient при необходимости. |
| 120 | |
| 121 | ### 5. Wire, transport, MCP |
| 122 | |
| 123 | | Слой | Поведение | |
| 124 | |------|-----------| |
| 125 | | **Локальный log** | Хранит **все** события | |
| 126 | | **Projection / Skia feed** | Применяет lens | |
| 127 | | **Export / MCP / [0132](0132-intercom-federated-transport-and-multi-client-boundary.md)** | **Полный** log без lens | |
| 128 | | **Matrix/MM bridge** | Не создаёт отдельные room per lens | |
| 129 | |
| 130 | ### 6. Клавиатура (опционально v1.1) |
| 131 | |
| 132 | Melody/Chords — по аналогии с [0127](0127-intercom-spine-and-topic-tabs-chrome-navigation.md): цикл lens или прямые chord’ы (`Ctrl+K → S → …`) — **отдельный** шаг intent-catalog при внедрении; v1 достаточно клика в chrome. |
| 133 | |
| 134 | --- |
| 135 | |
| 136 | ## Последствия |
| 137 | |
| 138 | ### Положительные |
| 139 | |
| 140 | - Меньше когнитивного шума без разбиения store и без дублирования topics. |
| 141 | - **System** отдельно — удобно для «что упало в CI» без прокрутки диалога агента. |
| 142 | - Согласуется с [0142](0142-intercom-open-wire-pluggable-transports.md): роль на wire, проекции на клиенте. |
| 143 | |
| 144 | ### Отрицательные / риски |
| 145 | |
| 146 | - Пользователь может **не заметить** скрытые сообщения — нужен счётчик/подпись. |
| 147 | - Четыре lens + topic tabs + spine — риск перегруза chrome; compact Forward — приоритет **4 коротких метки** (All / Hum / Agt / Sys) или иконки + tooltip. |
| 148 | |
| 149 | --- |
| 150 | |
| 151 | ## Не цели |
| 152 | |
| 153 | - Отдельные transport-каналы или Matrix rooms per lens. |
| 154 | - Замена topic navigation или spine. |
| 155 | - Фильтрация export/MCP по lens. |
| 156 | - Переименование `IntercomMessageAudience.Channel` в этом ADR. |
| 157 | |
| 158 | --- |
| 159 | |
| 160 | ## Anti-patterns |
| 161 | |
| 162 | | Anti-pattern | Почему | |
| 163 | |--------------|--------| |
| 164 | | Хранить только отфильтрованные сообщения в log | Ломает export, ветвление, rewind [0116](0116-intercom-session-tree-and-agent-message-steering.md) | |
| 165 | | Lens меняет `sender_role` | Роль — факт события | |
| 166 | | «Канал Agents» в UI без слова «вид» | Путаница с MM/Matrix и `Audience.Channel` | |
| 167 | | Скрыть system внутри Humans | **System — отдельный lens** (принято здесь) | |
| 168 | |
| 169 | --- |
| 170 | |
| 171 | ## Фазы |
| 172 | |
| 173 | | Фаза | Содержание | |
| 174 | |------|------------| |
| 175 | | **v1** | Enum + chrome switcher + фильтр projection; default All; подпись пустого состояния | |
| 176 | | **v1.1** | Persist lens в settings; chord в intent-catalog | |
| 177 | | **v2** | Per-topic remembered lens; badge «N hidden» | |
| 178 | |
| 179 | --- |
| 180 | |
| 181 | ## Отклонённые альтернативы (кратко) |
| 182 | |
| 183 | | Альтернатива | Почему не принято | |
| 184 | |--------------|-------------------| |
| 185 | | Три lens без System (system в All/Humans) | Запрос продукта: **System отдельно** | |
| 186 | | System внутри Agents | Смешивает tool-loop и CI/git | |
| 187 | | Отдельные sub-logs в БД | Дорого; lens достаточно | |
| 188 | | Slack-style channels как store | [0142](0142-intercom-open-wire-pluggable-transports.md), [0132](0132-intercom-federated-transport-and-multi-client-boundary.md) | |
| 189 | |
| 190 | --- |
| 191 | |
| 192 | <a id="adr0143-history"></a> |
| 193 | |
| 194 | ## История |
| 195 | |
| 196 | | Дата | Изменение | |
| 197 | |------|-----------| |
| 198 | | 2026-05-24 | Accepted: participant lens All / Humans / Agents / System; client projection; не transport channel. | |
| 199 | |