Forge
markdowndeeb25a2
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
37Lens — **клиентская проекция** над 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
74flowchart 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
132Melody/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
View only · write via MCP/CIDE