Forge
markdowndeeb25a2
1# ADR 0130: Подсветка диапазона кода для агента без изменения selection
2
3**Статус:** Accepted · Implemented
4**Дата:** 2026-05-19
5
6## Связанные ADR
7
8| ADR | Роль |
9|-----|------|
10| [0128](0128-intercom-attachment-anchors-and-code-references.md) | Якоря в Intercom; **reveal из ленты** (`intercom.reveal_attachment`) — тот же presentation mode |
11| [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md) | `command_id`; паритет MCP / UI |
12| [0013](0013-command-surface-and-discoverability.md) | Discoverability; `highlight_control` как прецедент |
13| [0111](0111-editor-linenumber-linerange-value-objects.md) | `LineRange` 1-based в домене и MCP args |
14| [0084](0084-agent-edits-editor-source-of-truth-presence-channel.md) | Редактор — источник правды; reveal не подменяет правку |
15| [0124](0124-slash-parametric-editor-line-commands.md) | `/editor line select` — **меняет** selection |
16| [0120](0120-primary-work-surface-intercom-or-editor.md) | Активный редактор в Forward / Mfd |
17| [0131](0131-editor-slash-select-code-by-bracket-reference.md) | `/editor select code [M:…]` — тот же bracket-parse, **select** в буфере, не attach |
18
19### Вне ADR (playbook)
20
21| Документ | Роль |
22|----------|------|
23| [intercom-ux-reference-slack-mattermost-v1.md](../design/intercom-ux-reference-slack-mattermost-v1.md) | Reveal = рамка, не selection; паритет с `highlight_control` |
24| [cascade-ide-ui-layout-v1.md](../ui-ux/cascade-ide-ui-layout-v1.md) | `AgentHighlightOverlay` для контролов |
25
26## Резюме
27
28Зафиксировать **безопасный показ участка кода человеку по запросу агента** (MCP), **без** сообщения в Intercom и **без** изменения `Selection` / каретки в буфере редактора.
29
301. **`command_id`:** `editor.reveal_range` · MCP: `reveal_editor_range` / `ide_reveal_editor_range`.
312. **Эффект:** при необходимости open файла → scroll into view → **transient** фон строк (gutter-band, `IBackgroundRenderer`) ~3 с; опционально рамка по цвету агента (`#FF6B9D`, как `highlight_control`).
323. **Не делает:** `SelectInEditor`, `ApplyEdit`, attach в event log.
334. **Ортогонально:** `go_to_position` (агент готовит правку → select); `intercom.reveal_attachment` (клик человека из ленты по `AttachmentAnchor`).
34
35**v1 реализация:** line-based `file_path` + `start_line` + `end_line`; общий сервис `EditorAgentRangeReveal` на активном `TextEditor`.
36
37**Фаза 2 (реализовано):** опциональные `member_key`, `syntax_scope` (JSON), `duration_ms`; re-resolve в `.cs` через `AttachmentAnchorRoslynResolver` (один файл, documentation id или простое имя; scope — `for`/`if`/… + `indexInParent`).
38
39**Не входит (позже фазы 3+):** overlay-рамка поверх глифов; длительность reveal в TOML (сейчас — `duration_ms` в MCP); паритет hotkey «reveal range» для человека; полный MSBuildWorkspace по solution.
40
41---
42
43## Контекст
44
45Сегодня агент, чтобы «показать» фрагмент, вынужден вызывать **`go_to_position`**, который внутри вызывает **`SelectInEditor`**. Это меняет выделение в буфере: оператор может случайно затереть фрагмент одной клавишей после подсказки агента.
46
47Для **контролов** уже есть **`highlight_control`**: transient рамка (`UiAgentHighlight` / `AgentHighlightOverlay`), без чата, без изменения состояния контрола.
48
49Для **кода** [0128](0128-intercom-attachment-anchors-and-code-references.md) описывает тот же UX для **клика по attach** в Intercom, но **не выделяет** отдельный MCP для агента — этот ADR закрывает пробел.
50
51---
52
53## Решение
54
55<a id="adr0130-p1"></a>
56
57### 1. Термины
58
59| Термин | Значение |
60|--------|----------|
61| **Reveal (editor)** | Показать диапазон в редакторе: scroll + transient highlight, **не** selection |
62| **Select (editor)** | Изменить `Selection` / каретку — `go_to_position`, `/editor line select` |
63| **Attach** | Payload в сообщении Intercom — [0128](0128-intercom-attachment-anchors-and-code-references.md) |
64
65Reveal и select — **разные команды и разный побочный эффект в буфере**, но **не взаимоисключающие**: обе доступны; для одного жеста (клик по chip) задаётся только **дефолт**, модификатор (Shift) и отдельные MCP переключают режим.
66
67<a id="adr0130-p2"></a>
68
69### 2. `command_id` и MCP
70
71| Слой | Идентификатор |
72|------|----------------|
73| Канон | `editor.reveal_range` |
74| MCP wire | `reveal_editor_range` |
75| Префикс IDE MCP | `ide_reveal_editor_range` |
76
77**Аргументы v1 (1-based):**
78
79| Поле | Обязательность | Смысл |
80|------|----------------|--------|
81| `file_path` | да | Путь к файлу; при необходимости open/activate вкладку |
82| `start_line` | да | Первая строка диапазона (inclusive) |
83| `end_line` | да | Последняя строка (inclusive); ≥ `start_line` |
84
85**Возврат:** `OK` или текст ошибки (файл не открыт, нет редактора, невалидный диапазон).
86
87<a id="adr0130-p3"></a>
88
89### 3. Поведение (паритет `highlight_control`)
90
91| Шаг | Действие |
92|-----|----------|
93| 1 | Нормализовать `file_path`; если вкладки нет — `open_file` / activate document |
94| 2 | Найти `TextEditor` для пути ([`EditorActiveDockResolver`](../Services/EditorActiveDockResolver.cs)) |
95| 3 | Прокрутить диапазон в видимую область **без** смены `Caret.Offset` и **без** `Selection` |
96| 4 | Установить transient highlight на строки `start_line`…`end_line` (`EditorAgentRangeRevealBackgroundRenderer`) |
97| 5 | Снять highlight через ~3 с (как `UiAgentHighlight`) |
98
99**Цвет v1:** фон `Color.FromArgb(48, 255, 107, 157)`; **одна** рамка pen `#FF6B9D` вокруг **единого** прямоугольника на весь диапазон строк (не построчные «плитки») — визуальная связь с `AgentHighlightOverlay`.
100
101<a id="adr0130-p4"></a>
102
103### 4. Ортогональность
104
105| Действие | Меняет selection? | Сообщение в Intercom? |
106|----------|-------------------|------------------------|
107| `editor.reveal_range` | **нет** | нет |
108| `go_to_position` | **да** | нет |
109| `intercom.reveal_attachment` | нет, если дефолт навигации = reveal; да при select / Shift+клик | контекст из ленты |
110| `/attach selection` | нет | **да** (черновик/отправка) |
111
112<a id="adr0130-p5"></a>
113
114### 5. Связь с [0128](0128-intercom-attachment-anchors-and-code-references.md)
115
116- **Общий presentation mode:** transient range highlight, не selection.
117- **Разные входы:**
118 - **0128** — `AttachmentAnchor` + клик / будущий reveal по anchor id;
119 - **0130** — прямой MCP от агента по `file_path` + lines (или позже member).
120- Реализация **должна переиспользовать** `EditorAgentRangeReveal` (один `IBackgroundRenderer` + таймер), чтобы не плодить два визуальных языка.
121
122<a id="adr0130-p6"></a>
123
124### 6. Фазы
125
126| Фаза | Содержание |
127|------|------------|
128| **0** *(текущий PR)* | ADR; `reveal_editor_range`; `EditorAgentRangeReveal` + line range |
129| **1** | `intercom.reveal_attachment` вызывает тот же сервис после re-resolve anchor ([0128](0128-intercom-attachment-anchors-and-code-references.md) §8) |
130| **2** | Те же поля, что у `AttachmentAnchor` в wire: опциональные **`memberKey`**, **`syntaxScope`** (JSON-объект, не prose `[M:…]`), **`duration_ms`**; re-resolve member/scope у получателя (Roslyn). MCP **не** парсит скобки в тексте сообщения — только структурированные args / `anchor_json` |
131| **3** *(done)* | `[intercom.attachments.code].navigate` в TOML; MCP `intercom.reveal_attachment` без `select` → дефолт из настроек; `IntercomAttachmentNavigator` для UI-клика (Shift → select) |
132
133<a id="adr0130-p6b"></a>
134
135#### Фаза 3: дефолт жеста, не XOR инструментов
136
137Фаза 3 **не** выбирает «только reveal или только select» в продукте. Оба остаются:
138
139| Режим | Когда | Команда / жест |
140|-------|--------|----------------|
141| Reveal | «Посмотри сюда», буфер не трогать | `editor.reveal_range`, `intercom.reveal_attachment` (дефолт клика), `select: false` в MCP |
142| Select | «Работай с этим фрагментом» | `go_to_position`, `/editor line select`, Shift+клик по chip, `select: true` в `intercom.reveal_attachment` |
143
144**Фаза 3 добавляет только политику по умолчанию** для **одного** UX-жеста — обычный клик по метке attach в ленте ([0128](0128-intercom-attachment-anchors-and-code-references.md) §8):
145
146- `[intercom.attachments.code]` `navigate = "reveal"` (ожидаемый дефолт) → scroll + transient highlight;
147- `navigate = "select"` → `SelectInEditor` после open/re-resolve;
148- `reveal_load_solution = "when_needed"` \| `"never"` — грузить .sln перед reveal (см. `IntercomAttachmentsCodeSettings`);
149- Shift+клик → select **независимо** от дефолта (как в 0128 §8 шаг 5).
150
151Агент по-прежнему выбирает **явную** команду: *показать* → `reveal_editor_range`; *править* → `go_to_position`. Дефолт в TOML на клик человека из чата не отменяет MCP.
152
153---
154
155## Последствия
156
157**Плюсы:** безопасный «укажи глазами» для агента; симметрия с `highlight_control`; меньше случайных правок после `go_to_position`.
158
159**Минусы:** два **смысла** навигации по коду — агенту и оператору нужна дисциплина: *показать* → reveal, *править* → select; путать их опасно для буфера, хотя инструменты сосуществуют.
160
161---
162
163## Отклонённые альтернативы
164
165| Альтернатива | Почему нет |
166|--------------|------------|
167| Флаг `highlight_only` у `go_to_position` | Смешивает navigate-for-edit и reveal; ломает контракт существующего тула |
168| Только attach в чат | Агент не должен слать сообщение, чтобы подсветить код |
169| Всегда selection | Небезопасно для оператора — [0128](0128-intercom-attachment-anchors-and-code-references.md) §8 |
170
171---
172
173## История
174
175| Дата | Изменение |
176|------|-----------|
177| 2026-05-19 | Proposed: отдельный ADR; v1 MCP + `EditorAgentRangeReveal`. |
178| 2026-05-19 | Фаза 2: `member_key`, `syntax_scope`, `duration_ms`; Roslyn re-resolve. |
179| 2026-05-19 | Уточнение фазы 3: дефолт клика по attach (`reveal` \| `select`), не взаимоисключение инструментов. |
180| 2026-05-19 | Accepted: фазы 0–3 в коде (`IntercomSettings`, `IntercomAttachmentNavigator`, MCP default `select`). |
181| 2026-05-20 | **Accepted · Implemented**; кластер с [0128](0128-intercom-attachment-anchors-and-code-references.md) / [0131](0131-editor-slash-select-code-by-bracket-reference.md). |
182
View only · write via MCP/CIDE