ADR 0124: Параметрические слэш-команды — полный паритет каталога IML в Intercom¶
Статус: Accepted · Implemented
Дата: 2026-05-17
Обновлено: 2026-05-17 — расширение ADR до полного описания фичи (каталог, парсер, binders, TOML, тесты).
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0119 | Базовый контур slash в ChatInput (парсер, каталог, autocomplete, local execution) — этот ADR — надстройка для IML-параметрики |
| 0109 | melody_shape, tail_signature, wire_class, binders без поля binder в TOML |
| 0081 | Семантика диапазона строк редактора (1-based, inclusive) |
| 0111 | LineNumber / LineRange |
| 0030 | Канон command_id |
| 0120 | Intercom как CLI сессии |
| 0060 | Melody c: / CascadeChord |
| 0108 | show_web_ai_portal_page |
| 0125 | Workspace/file slash и dynamic completion — ортогонально параметрике этого ADR |
Вне ADR¶
| Документ | Роль |
|---|---|
| intent-melody-language-v1.md | IML v1/v2; slash — отдельная грамматика / |
IntentMelody/intent-catalog.toml |
command-first: melody + slash на одном command_id |
| MCP-PROTOCOL.md | ide_execute_command — тот же wire JSON |
Резюме¶
Фича «параметрический slash» закрывает разрыв между IML v2 (палитра c:, аккорды) и unified command line Intercom (0119):
- Любая команда с
melody_shape = parametricвintent-catalog.tomlможет иметь slash-форму с тем жеcommand_idи теми же JSON-args, что melody и MCP. - Разбор хвоста slash (ArgsTail) диспетчеризуется по
wire_classиз каталога — не по отдельномуswitch (command_id)в Runner. - Slash-пути (
/editor line select,/portal open) задаются вручную в TOML (help,group) для autocomplete; пути не выводятся автоматически изtail_signature. - Bundled v1 покрывает все три параметрических корня каталога; добавление четвёртого — по чеклисту §8.
Не входит в фичу: автогенерация slash-путей, короткие мнемоники /els, новые wire_class без ветки в ChatSlashParametricArgsBuilder.
Связанный, но другой слой: slash с произвольным текстовым хвостом для команд IML simple — см. § Контекст.
Контекст¶
Три слоя «параметра» в Intercom (0119)¶
| Слой | IML в каталоге | Примеры slash | Где удобно | Сборка args |
|---|---|---|---|---|
| A. Structured parametric | melody_shape = parametric, wire_class |
/editor line select 5 10, /portal open url |
Чат; палитра c:els / c:wai |
ChatSlashParametricArgsBuilder → те же binders, что melody |
| B. Free-text tail (prose) | melody_shape = simple, тот же command_id |
/git commit "feat: test", /search pattern, /spine set focus |
Преимущественно чат — пробелы, кавычки, длинный текст | BuildArgs по command_id; хвост = одно поле (message, pattern, …) |
| C. Без хвоста | simple | /git status, /overview |
Чат, autocomplete | только command_id |
Про /git commit: в каталоге это git_commit + melody c:gc (intent-catalog.toml) — это IML-команда, не «чужая» slash. Но форма хвоста — слой B, не A: в TOML нет wire_class для произвольного текста коммита, потому что аккорд/Chord с многословным сообщением неудобен (пробелы, кавычки, таймаут цепочки). В чате слой B как раз «огонь»: /git commit feat: test или /git commit "feat: test" — весь ArgsTail → message (кавычки снимаются, ChatSlashArgsTail).
Путаница «почему не полная параметрика» — смешение A и B. Полная параметрика (A) = все записи melody_shape = parametric в TOML. Git commit намеренно в B до появления, например, text_remainder в 0109 и осознанного chord UX.
Каталог на сегодня (bundled)¶
command_id |
Melody | wire_class |
tail_signature (сокращ.) |
|---|---|---|---|
select |
c:els |
int_chain_colon_space |
<start:ln>:<end:ln> |
apply_edit |
c:eld |
int_chain_colon_space |
то же (удаление через new_text="") |
show_web_ai_portal_page |
c:wai |
url_remainder |
<url:url> |
Других parametric корней в bundled intent-catalog.toml нет — фича считается полной относительно каталога, а не относительно всех возможных будущих wire.
Проблема¶
- Разрыв входов: оператор в Intercom не может выделить/удалить строки или открыть портал по URL без палитры или
c:. - Дублирование binders: без ADR каждая slash-команда тянет свой парсер колонок/URL в
ChatPanelViewModel. - Парсер 0119 §4: путь
/editor line select— три токена namespace, не два. - Discoverability: без записи в TOML slash не попадает в autocomplete (0119 §6).
Решение¶
1. Инварианты фичи¶
| # | Инвариант |
|---|---|
| I1 | Slash-параметрика только для command_id, у которого в каталоге есть ровно один parametric melody-корень (TryGetParametricRootByCommandId). |
| I2 | JSON-args для slash идентичны melody/MCP для того же command_id (те же binders). |
| I3 | Ошибки валидации (файл не открыт, диапазон за файлом) — в пузыре слэш-команды, не silent no-op. |
| I4 | Нераспознанный /… не уходит агенту (0119). |
| I5 | Короткие slash-алиасы (/els) — запрещены; читаемые пути + autocomplete. |
2. Контур исполнения¶
ChatInput (строка с /)
→ ChatSlashCommandParser
flat | namespace+action | namespace+action+subAction (editor line)
→ ChatSlashCommandCatalog.TryResolve(slash path → SlashRouteEntry)
→ ChatSlashCommandRunner
if TryGetParametricRootByCommandId(command_id):
ChatSlashParametricArgsBuilder(argsTail, wire_class, ChatSlashEditorContext)
else:
BuildArgs (ad-hoc)
→ executeIdeCommand(command_id, args) // тот же мост, что MCP
→ пузырь slash в ленте: success / DetailText (ошибка binder)
Контекст редактора (ChatSlashEditorContext): CurrentFilePath, EditorText — из ChatPanelViewModel (_getCurrentFilePath, _getEditorText). Нужен для int_chain_colon_space; для url_remainder передаётся, но не обязателен.
3. Диспетчеризация по wire_class¶
Реализация: ChatSlashParametricArgsBuilder.
wire_class |
TailWireKind |
Условие | Slash ArgsTail | Binder / JSON |
|---|---|---|---|---|
int_chain_colon_space |
DelimitedSlots |
2 numeric slots, line (:ln) |
см. §4 | ParametricLineRangeArgsBuilder → file_path, start_line, start_column, end_line, end_column (+ new_text для delete) |
url_remainder |
SingleRemainder |
URL slot в signature | весь хвост = URL; пустой допустим | null args или { "url": "…" } |
Неподдержанная комбинация wire_class + signature → ошибка: «Форма wire_class … для slash ещё не поддержана» (явный сигнал разработчику добавить ветку).
Связь с melody: для line-range строится синтетический ParametricIntentMelody.ParsedLineRange с Slug из каталога (els/eld), чтобы не дублировать логику колонок.
4. Грамматика ArgsTail: диапазон строк¶
После резолва пути (/editor line select или delete) остаётся только числовой хвост (без повторения slug):
| Ввод | start |
end |
|---|---|---|
5 |
5 | 5 |
5 10 |
5 | 10 |
5:10 |
5 | 10 |
5;10 |
5 | 10 |
Правила:
- Номера 1-based, inclusive (0081).
end < start→ ошибка.- Вне файла / нет
file_path→ ошибка изParametricLineRangeArgsBuilder. - Пустой хвост → ошибка с подсказкой формата.
5. Грамматика ArgsTail: URL (url_remainder)¶
Путь: /portal open → show_web_ai_portal_page.
| Ввод | Args |
|---|---|
/portal open |
null (страница по умолчанию, как c:wai) |
/portal open example.com |
{ "url": "example.com" } |
/portal open https://host/path |
весь хвост после open — одна строка URL |
Пробелы в URL сохраняются в хвосте (редкий случай); нормализация схемы — как у melody (0108).
6. Парсер slash: уровни токенов¶
Расширение ChatSlashCommandParser:
| Форма | Shape |
Поля parse | Пример |
|---|---|---|---|
/overview |
Flat | Head=overview |
Intercom |
/build run |
NamespaceAction | Head, Action, ArgsTail |
IDE |
/editor line select 5 10 |
NamespaceAction + SubAction | Head=editor, Action=line, SubAction=select, ArgsTail=5 10 |
только editor line |
Резолв каталога для SubAction:
slashPath = "/" + Head + " " + Action + " " + SubAction
// → "/editor line select"
Ограничение: SubAction для editor line — только select | delete (маппинг на select / apply_edit через разные slash-пути в TOML, не через один путь с глаголом в хвосте).
7. Каталог TOML (intent-catalog.toml)¶
На каждый parametric [[command]]:
[[command]]
command_id = "select"
melody_slug = "els"
melody_shape = "parametric"
# … melody_* …
[[command.form.slash]]
path = "/editor line select"
help = "Выделить строки …"
group = "Editor"
Правила:
path— ключ вIntentSlashCatalog.SlashRoutes(case-insensitive).help/group— autocomplete и/help(0119).- Статические
[command.form.slash.args](page,surface) — для не-параметрических slash (MFD); параметрика несёт args в ArgsTail, не в TOML-args.
Обнаружение parametric slash в Runner: не флаг в TOML, а IntentMelodyCatalog.TryGetParametricRootByCommandId(command_id).
8. Чеклист: новая parametric-команда¶
- TOML melody:
melody_shape = parametric,tail_signature,wire_class, согласованный с[[tail_wire_class]]. - Binder в коде (0109): melody-путь (
ParametricIntentMelody/ dedicated builder). - Ветка в
ChatSlashParametricArgsBuilderдля этогоwire_class(если новый — ADR-апдейт). [[command.form.slash]]с читаемымpath+help.- Парсер: при нестандартной форме пути — расширение
ChatSlashCommandParser(как SubAction для editor). - Тесты:
ChatSlashParametricTests+ при необходимости melody tests. - Autocomplete:
group/slash_groupв TOML; сортировка — по группе иpathбез хардкода в C#.
9. UX и ошибки¶
- Перед отправкой агенту: пузырь slash-команды в ленте (0119); статус success/fail.
DetailTextпри ошибке binder — текст для оператора (напр. «Диапазон выходит за пределы файла»).- Успех без содержательного JSON — без лишнего «ok» в ленте (как у других slash).
10. Паритет входов (сводная таблица)¶
| Действие | Melody | Slash | MCP |
|---|---|---|---|
| Выделить строки 5–10 | c:els:5:10 |
/editor line select 5 10 |
select + JSON |
| Удалить строки 3–7 | c:eld:3:7 |
/editor line delete 3 7 |
apply_edit + JSON |
| Web AI Portal | c:wai: |
/portal open |
show_web_ai_portal_page |
| Portal + URL | c:wai:host |
/portal open host |
{ "url": "host" } |
Ортогональность входов¶
| Вход | Параметрика редактора / URL |
|---|---|
Палитра c: |
✅ каталог + binders |
| CascadeChord | ✅ тот же каталог |
| Chat slash | ✅ эта фича |
MCP ide_execute_command |
✅ |
| Hotkeys | ❌ (нет line-range в chord по умолчанию) |
Диаграмма¶
flowchart TD
input[ChatInput slash line]
input --> parser[ChatSlashCommandParser]
parser --> catalog[ChatSlashCommandCatalog]
catalog --> runner[ChatSlashCommandRunner]
runner --> q{parametric in catalog?}
q -->|yes| param[ChatSlashParametricArgsBuilder]
q -->|no| adhoc[BuildArgs ad-hoc]
param --> wc{wire_class}
wc -->|int_chain_colon_space| line[ParametricLineRangeArgsBuilder]
wc -->|url_remainder| url[JSON url or null]
line --> exec[executeIdeCommand]
url --> exec
adhoc --> exec
exec --> bubble[Slash bubble in feed]
melody[c: palette chord] --> line
melody --> url
mcp[ide_execute_command] --> exec
Якоря реализации (Implemented)¶
| Компонент | Путь | Роль |
|---|---|---|
| Каталог lookup | IntentMelodyCatalog.cs |
TryGetParametricRootByCommandId |
| Slash args | ChatSlashParametricArgsBuilder.cs |
ArgsTail → JSON по wire_class |
| Editor context | ChatSlashEditorContext.cs |
file + text для line binder |
| Parser SubAction | ChatSlashCommandParser.cs |
/editor line select|delete |
| Catalog resolve | ChatSlashCommandCatalog.cs |
path + SubAction; порядок из TOML group + path |
| Runner | ChatSlashCommandRunner.cs |
ветка parametric vs ad-hoc |
| VM wiring | ChatPanelViewModel.cs |
ChatSlashEditorContext delegate |
| TOML | IntentMelody/intent-catalog.toml |
slash paths + melody |
| Line binder (shared) | ParametricLineRangeArgsBuilder.cs |
melody + slash |
| Melody entry | ParametricIntentMelody.cs |
TryResolveParametricExecution |
| Тесты | ChatSlashParametricTests.cs |
parser, catalog, binders |
Non-goals¶
- Slash для всех
IdeCommandsс любыми args (только каталогparametric+ ad-hoc список 0119). - Автогенерация
[[command.form.slash]]изmelody_slug/tail_signature. - Короткие пути
/els,/wai(коллизии, дубльc:). - Универсальный четырёхуровневый парсер
/a b c dбез curated правил. - Параметрический slash без записи в TOML (нет «скрытых» команд).
Отклонённые альтернативы¶
- Per-command binder в Runner (
switch command_id) — расходится с 0109; отвергнуто. /parametric els 5 10— плохой UX в Intercom, дублирует палитру; отвергнуто./editor select 5(два уровня) — слабая группировка «line operations»; отвергнуто в пользу/editor line select.intent_catalog_schema_version = 2для раскладки TOML — путаница с IML v2; schema файла остаётся 1.
Критерии приёмки (Definition of Done)¶
- [x] Все
melody_shape = parametricв bundled TOML имеют хотя бы один[[command.form.slash]]. - [x] Slash вызывает тот же
command_idи те же args, что melody (тесты наselect,apply_edit,show_web_ai_portal_page). - [x] Ошибки binder отображаются в пузыре slash.
- [x] Autocomplete видит новые пути (
/portal,/editor line …). - [x] ADR + ссылка из 0119 и intent-melody-language-v1.md.
История изменений¶
| Дата | Изменение |
|---|---|
| 2026-05-17 | Proposed: slash-паритет для editor line (/editor line select|delete). |
| 2026-05-17 | Implemented: SubAction, line binder, TOML, тесты. |
| 2026-05-17 | Фича «полная параметрика каталога»: ChatSlashParametricArgsBuilder, /portal open, TryGetParametricRootByCommandId; ADR расширен как норматив фичи. |