ADR 0130: Подсветка диапазона кода для агента без изменения selection¶
Статус: Accepted · Implemented
Дата: 2026-05-19
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0128 | Якоря в Intercom; reveal из ленты (intercom.reveal_attachment) — тот же presentation mode |
| 0030 | command_id; паритет MCP / UI |
| 0013 | Discoverability; highlight_control как прецедент |
| 0111 | LineRange 1-based в домене и MCP args |
| 0084 | Редактор — источник правды; reveal не подменяет правку |
| 0124 | /editor line select — меняет selection |
| 0120 | Активный редактор в Forward / Mfd |
| 0131 | /editor select code [M:…] — тот же bracket-parse, select в буфере, не attach |
Вне ADR (playbook)¶
| Документ | Роль |
|---|---|
| intercom-ux-reference-slack-mattermost-v1.md | Reveal = рамка, не selection; паритет с highlight_control |
| cascade-ide-ui-layout-v1.md | AgentHighlightOverlay для контролов |
Резюме¶
Зафиксировать безопасный показ участка кода человеку по запросу агента (MCP), без сообщения в Intercom и без изменения Selection / каретки в буфере редактора.
command_id:editor.reveal_range· MCP:reveal_editor_range/ide_reveal_editor_range.- Эффект: при необходимости open файла → scroll into view → transient фон строк (gutter-band,
IBackgroundRenderer) ~3 с; опционально рамка по цвету агента (#FF6B9D, какhighlight_control). - Не делает:
SelectInEditor,ApplyEdit, attach в event log. - Ортогонально:
go_to_position(агент готовит правку → select);intercom.reveal_attachment(клик человека из ленты поAttachmentAnchor).
v1 реализация: line-based file_path + start_line + end_line; общий сервис EditorAgentRangeReveal на активном TextEditor.
Фаза 2 (реализовано): опциональные member_key, syntax_scope (JSON), duration_ms; re-resolve в .cs через AttachmentAnchorRoslynResolver (один файл, documentation id или простое имя; scope — for/if/… + indexInParent).
Не входит (позже фазы 3+): overlay-рамка поверх глифов; длительность reveal в TOML (сейчас — duration_ms в MCP); паритет hotkey «reveal range» для человека; полный MSBuildWorkspace по solution.
Контекст¶
Сегодня агент, чтобы «показать» фрагмент, вынужден вызывать go_to_position, который внутри вызывает SelectInEditor. Это меняет выделение в буфере: оператор может случайно затереть фрагмент одной клавишей после подсказки агента.
Для контролов уже есть highlight_control: transient рамка (UiAgentHighlight / AgentHighlightOverlay), без чата, без изменения состояния контрола.
Для кода 0128 описывает тот же UX для клика по attach в Intercom, но не выделяет отдельный MCP для агента — этот ADR закрывает пробел.
Решение¶
1. Термины¶
| Термин | Значение |
|---|---|
| Reveal (editor) | Показать диапазон в редакторе: scroll + transient highlight, не selection |
| Select (editor) | Изменить Selection / каретку — go_to_position, /editor line select |
| Attach | Payload в сообщении Intercom — 0128 |
Reveal и select — разные команды и разный побочный эффект в буфере, но не взаимоисключающие: обе доступны; для одного жеста (клик по chip) задаётся только дефолт, модификатор (Shift) и отдельные MCP переключают режим.
2. command_id и MCP¶
| Слой | Идентификатор |
|---|---|
| Канон | editor.reveal_range |
| MCP wire | reveal_editor_range |
| Префикс IDE MCP | ide_reveal_editor_range |
Аргументы v1 (1-based):
| Поле | Обязательность | Смысл |
|---|---|---|
file_path |
да | Путь к файлу; при необходимости open/activate вкладку |
start_line |
да | Первая строка диапазона (inclusive) |
end_line |
да | Последняя строка (inclusive); ≥ start_line |
Возврат: OK или текст ошибки (файл не открыт, нет редактора, невалидный диапазон).
3. Поведение (паритет highlight_control)¶
| Шаг | Действие |
|---|---|
| 1 | Нормализовать file_path; если вкладки нет — open_file / activate document |
| 2 | Найти TextEditor для пути (EditorActiveDockResolver) |
| 3 | Прокрутить диапазон в видимую область без смены Caret.Offset и без Selection |
| 4 | Установить transient highlight на строки start_line…end_line (EditorAgentRangeRevealBackgroundRenderer) |
| 5 | Снять highlight через ~3 с (как UiAgentHighlight) |
Цвет v1: фон Color.FromArgb(48, 255, 107, 157); одна рамка pen #FF6B9D вокруг единого прямоугольника на весь диапазон строк (не построчные «плитки») — визуальная связь с AgentHighlightOverlay.
4. Ортогональность¶
| Действие | Меняет selection? | Сообщение в Intercom? |
|---|---|---|
editor.reveal_range |
нет | нет |
go_to_position |
да | нет |
intercom.reveal_attachment |
нет, если дефолт навигации = reveal; да при select / Shift+клик | контекст из ленты |
/attach selection |
нет | да (черновик/отправка) |
5. Связь с 0128¶
- Общий presentation mode: transient range highlight, не selection.
- Разные входы:
- 0128 —
AttachmentAnchor+ клик / будущий reveal по anchor id; - 0130 — прямой MCP от агента по
file_path+ lines (или позже member). - Реализация должна переиспользовать
EditorAgentRangeReveal(одинIBackgroundRenderer+ таймер), чтобы не плодить два визуальных языка.
6. Фазы¶
| Фаза | Содержание |
|---|---|
| 0 (текущий PR) | ADR; reveal_editor_range; EditorAgentRangeReveal + line range |
| 1 | intercom.reveal_attachment вызывает тот же сервис после re-resolve anchor (0128 §8) |
| 2 | Те же поля, что у AttachmentAnchor в wire: опциональные memberKey, syntaxScope (JSON-объект, не prose [M:…]), duration_ms; re-resolve member/scope у получателя (Roslyn). MCP не парсит скобки в тексте сообщения — только структурированные args / anchor_json |
| 3 (done) | [intercom.attachments.code].navigate в TOML; MCP intercom.reveal_attachment без select → дефолт из настроек; IntercomAttachmentNavigator для UI-клика (Shift → select) |
Фаза 3: дефолт жеста, не XOR инструментов¶
Фаза 3 не выбирает «только reveal или только select» в продукте. Оба остаются:
| Режим | Когда | Команда / жест |
|---|---|---|
| Reveal | «Посмотри сюда», буфер не трогать | editor.reveal_range, intercom.reveal_attachment (дефолт клика), select: false в MCP |
| Select | «Работай с этим фрагментом» | go_to_position, /editor line select, Shift+клик по chip, select: true в intercom.reveal_attachment |
Фаза 3 добавляет только политику по умолчанию для одного UX-жеста — обычный клик по метке attach в ленте (0128 §8):
[intercom.attachments.code]navigate = "reveal"(ожидаемый дефолт) → scroll + transient highlight;navigate = "select"→SelectInEditorпосле open/re-resolve;reveal_load_solution = "when_needed"|"never"— грузить .sln перед reveal (см.IntercomAttachmentsCodeSettings);- Shift+клик → select независимо от дефолта (как в 0128 §8 шаг 5).
Агент по-прежнему выбирает явную команду: показать → reveal_editor_range; править → go_to_position. Дефолт в TOML на клик человека из чата не отменяет MCP.
Последствия¶
Плюсы: безопасный «укажи глазами» для агента; симметрия с highlight_control; меньше случайных правок после go_to_position.
Минусы: два смысла навигации по коду — агенту и оператору нужна дисциплина: показать → reveal, править → select; путать их опасно для буфера, хотя инструменты сосуществуют.
Отклонённые альтернативы¶
| Альтернатива | Почему нет |
|---|---|
Флаг highlight_only у go_to_position |
Смешивает navigate-for-edit и reveal; ломает контракт существующего тула |
| Только attach в чат | Агент не должен слать сообщение, чтобы подсветить код |
| Всегда selection | Небезопасно для оператора — 0128 §8 |
История¶
| Дата | Изменение |
|---|---|
| 2026-05-19 | Proposed: отдельный ADR; v1 MCP + EditorAgentRangeReveal. |
| 2026-05-19 | Фаза 2: member_key, syntax_scope, duration_ms; Roslyn re-resolve. |
| 2026-05-19 | Уточнение фазы 3: дефолт клика по attach (reveal | select), не взаимоисключение инструментов. |
| 2026-05-19 | Accepted: фазы 0–3 в коде (IntercomSettings, IntercomAttachmentNavigator, MCP default select). |
| 2026-05-20 | Accepted · Implemented; кластер с 0128 / 0131. |