Forge
markdowndeeb25a2
1# ADR 0081: Параметрические Intent Melody — диапазоны строк редактора (`:start:end`)
2
3**Статус:** Accepted · Implemented
4**Дата:** 2026-04-20
5## Связанные ADR
6
7| ADR | Роль |
8|-----|------|
9| [0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) | Command Melody, CascadeChord, keyboard-first |
10| [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md) | `command_id` и слои UI |
11| [0013](0013-command-surface-and-discoverability.md) | палитра и discoverability |
12| [0070](0070-command-palette-direct-overlay-surface.md) | палитра как overlay |
13| [0079](0079-ide-display-system-ids-overlay-pipeline.md) | IDS — композиция оверлея ввода |
14| [0072](0072-chat-topic-cards-intent-melody-keyboard-contract.md) | intent-first входы в домене чата |
15| [0075](0075-ui-topic-index-and-mfd-page-conventions.md) | зоны внимания / MFD |
16| [0039](0039-workspace-navigation-affordances.md) | Навигация по workspace — несколько представлений и «текущий файл + связанные» |
17| [0080](0080-intercom-naming-and-multi-party-channel-model.md#adr0080-future-modalities) | якоря на код — смежная тема, не дублирует этот ADR |
18| [0110](0110-roslyn-refactor-intent-melody-bridge.md) | Рефакторинги Roslyn по диапазону — мост Intent Melody / IDE и Roslyn MCP |
19
20## Резюме
21
22- Параметрические **Intent Melody:** суффикс `:startLine:endLine` для операций над текстом.
23- Валидация диапазона; мост к Roslyn — [0110](0110-roslyn-refactor-intent-melody-bridge.md).
24
25
26### Вне ADR
27
28| Документ | Роль |
29|----------|------|
30| [intent-melody-language-v1.md](../intent-melody-language-v1.md) | IML v1: грамматика `c:` и реестр alias |
31| [`IntentMelody/intent-melody-aliases.toml`](../../IntentMelody/intent-melody-aliases.toml) | оверлей alias → `command_id` |
32| [Roslyn MCP](../../../roslyn-mcp/README.md) | Roslyn MCP |
33
34---
35## Контекст
36
37В IML v1 хвост после `c:` — это **мнемоника**, резолвящаяся в **`command_id`** через реестр ([`intent-melody-aliases.toml`](../../IntentMelody/intent-melody-aliases.toml), [ADR 0060 §11](0060-keyboard-chord-stack-fms-tactical-strategic.md#adr0060-p11)). Для команд уровня «Git status» или «открыть страницу Chat» этого достаточно: контекст задаётся фокусом и текущим решением.
38
39Операции над **текстом активного редактора** (выделить диапазон строк, удалить диапазон, **Extract Method** и другие рефакторинги Roslyn по диапазону) принципиально требуют **параметра** — хотя бы **диапазон строк** — иначе одна и та же мнемоника неоднозначна или вынуждена опираться только на текущее выделение, что хуже для сценариев «знаю номера строк».
40
41---
42
43## Проблема
44
451. **Разрыв «намерение → команда»:** без параметров пользователь вынужден сначала выделить текст мышью/клавиатурой, затем вызывать команду; для power-user с номерами из лога/диффа это медленнее, чем **одна строка ввода** с диапазоном.
462. **Паритет поверхностей:** если параметр доступен только через меню или отдельный диалог, страдает принцип **те же `command_id` и те же входы**, что палитра и Melody ([0060](0060-keyboard-chord-stack-fms-tactical-strategic.md), [0008](0008-mcp-contracts-and-testable-infrastructure.md)).
473. **Ошибки ввода:** диапазон вне файла или `start > end` не должны приводить к **молчаливому** разрушительному эффекту или к правке не того фрагмента.
48
49---
50
51## Решение (предлагаемое)
52
53<a id="adr0081-p1"></a>
54
55### 1. Суффикс диапазона строк
56
57После **зарегистрированного** короткого alias (корень мелодии без `c:` в терминах реестра) допускается **опциональный** суффикс вида **`:startLine:endLine`**:
58
59- **`startLine`**, **`endLine`** — целые числа, **1-based**, **включительно** (согласовано с номерами строк в редакторе и типичными сообщениями компилятора).
60- Разделитель полей — **`:`**; парсер после матча базового alias **сначала** резолвит префикс в `command_id` / доменную операцию, затем, если хвост продолжается шаблоном `:digits:digits`, интерпретирует пару как диапазон строк.
61
62**Иллюстративные примеры** (финальные мнемоники и привязка к `command_id` — решение реестра и продукта, не жёстко зашитые в парсер):
63
64| Ввод (фрагмент после `c:`) | Намерение (ориентир) |
65|---------------------------|----------------------|
66| `els:5:15` | Editor → Line → Select строки 5–15 в активном документе |
67| `eld:5:15` | Editor → Line → Delete в указанном диапазоне |
68
69Канон этой ADR-ветки:
70
71- Для операций над диапазоном строк использовать модель **Editor → Line** (`el*`), без legacy/синонимов `es*`.
72- Семейство мелодий **Refactor → …** по диапазону (`rmx`, `rix`, …) и связка с Roslyn / **Roslyn MCP** (`roslyn_get_code_actions` / `roslyn_apply_code_action`) **не входят в обязательный минимум этого ADR** — см. [0110](0110-roslyn-refactor-intent-melody-bridge.md).
73
74Расширение **IML v1** в [`intent-melody-language-v1.md`](../intent-melody-language-v1.md) (новый подпункт про параметрический хвост) — **отдельным шагом** после стабилизации формата; до тех пор этот ADR — **норматив направления** для реализации и документации.
75
76<a id="adr0081-p2"></a>
77
78### 2. Валидация и отказ
79
80- Диапазон **обязан** укладываться в текущую длину документа (в строках); при нарушении — **явная обратная связь** (строка состояния палитры, краткий annunciator в IDS — по [0079](0079-ide-display-system-ids-overlay-pipeline.md)), **без** применения деструктивного действия «как получится».
81- Условие **`startLine <= endLine`**; иначе — тот же класс ошибки, что и выход за границы.
82
83<a id="adr0081-p3"></a>
84
85### 3. Рефакторинги Roslyn (Extract Method и аналоги)
86
87Команды, которые в IDE уже ожидают **выделение** в редакторе (в т.ч. Roslyn: `roslyn_get_code_actions` с диапазоном для Extract method и аналогов), должны вести себя предсказуемо:
88
89- Если есть **непустое выделение** в активном документе — возможен **приоритет выделения** над числовым суффиксом (продуктовое правило: «явный жест побеждает») **или** однозначная политика «суффикс всегда задаёт диапазон» — **зафиксировать при реализации** и отразить в help.
90- Если выделения нет — **синтетическое выделение** по строкам `startLine`–`endLine` (целые строки, включая переводы строк по принятому в редакторе правилу) перед вызовом того же пути, что и из UI.
91
92<a id="adr0081-p4"></a>
93
94### 4. UX: discoverability и режим ввода
95
96- **Индикатор распознанной мелодии:** при активном **command mode** / вводе в палитре показывать краткий разбор: базовый alias + числовой диапазон (и при ошибке — причину). Цель — снизить ошибки «я думал, что ввёл другое» без обязательного длинного лога.
97- **Chord vs только палитра:** открытый вопрос — разрешать ли параметрический хвост в **CascadeChord** (`Ctrl+K` → последовательность букв) или ограничить **палитрой** ради меньшего числа опечаток без превью. Решение — отдельно; этот ADR допускает оба варианта как реализации.
98
99---
100
101## Последствия
102
103- Расширение разборщика строки палитры / Melody и связки с VM: команды редактора, принимающие диапазон, получают **единый** контракт из IML, а не только из pointer.
104- Реестр [`intent-melody-aliases.toml`](../../IntentMelody/intent-melody-aliases.toml) может ссылать **те же** `command_id`, что и без параметров; семантика «с параметром / без» — в обработчике команды или тонком адаптере.
105- Документация MCP / `IdeCommands`: для соответствующих команд при необходимости уточняются **args** или параллельный путь «из палитры с диапазоном».
106
107---
108
109## Отклонённые альтернативы
110
111- **Только MCP с явными аргументами** — ломает keyboard-first и единую строку намерения в IDE для человека.
112- **Только пробел как разделитель** (`5 15`) — конфликтует с направлением IML v1 «пробелы внутри хвоста не режут токены» ([§3.4](../intent-melody-language-v1.md#34-пробелы)); суффикс с **`:`** после полного матча alias воспроизводимее.
113- **Привязка только к mouse / gutter** — не отменяется, но не заменяет параметрический ввод для пользователей без указателя на строке.
114
115---
116
117## Открытые вопросы
118
1191. Ограничить параметрические формы **только палитрой** на первом релизе или сразу разрешить chord-ввод.
1202. Нужны ли в следующей итерации **столбцы** или **поддиапазоны внутри строки** — вынести за пределы минимального `:start:end` по строкам.
1213. Синхронизация с будущими **якорями на код** из [0080](0080-intercom-naming-and-multi-party-channel-model.md) (deep link): общий слой «диапазон в документе» или отдельные контракты.
122
View only · write via MCP/CIDE