ADR 0039: Навигация по workspace — несколько представлений и «текущий файл + связанные»¶
Статус: Accepted · Implemented
Дата: 2026-04-16
Обновлено: 2026-04-16 — область языков; «Продуктовая метафора». Подробности — § История.
Реализация (MCP-слой): зафиксирована в коде (2026-04): пресеты в settings.toml, эхо фильтра, семантика subgraph; см. § Agent/MCP. Полноценная Semantic Map в UI и ILayoutEngine — вне этого статуса.
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0021 | PFD, якорь «где я» |
| 0037 | Навигация ≠ строгая PFD-поверхность |
| 0010 | Пресеты UI |
| 0030 | Команды, палитра |
| 0017 | presentation, размещение поверхностей |
| 0058 | Агент ↔ Roslyn MCP в settings.toml |
| 0059 | Профили Roslyn, Manager, EFB |
| 0065 | graph_kind, карта намерений |
| 0067 | Контракт graph-backed поверхностей |
Снимок реализации¶
| Элемент | Значение |
|---|---|
| — | MCP get_code_navigation_context, пресеты и фильтры в settings.toml |
| — | полноценный UI Semantic Map / ILayoutEngine — по плану, см. текст ADR |
Резюме¶
- Навигация C# / .NET first: Roslyn и solution — north-star, не «IDE на все языки».
- Несколько представлений workspace + режим «вокруг активного документа» вместо одного дерева.
- MCP-слой (пресеты, subgraph,
get_code_navigation_context) — implemented; полный UI Semantic Map — roadmap. - Ортогонально строгой PFD-поверхности (0037).
Контекст¶
Классическое дерево файлов (обозреватель решения) в основном изоморфно структуре проекта на диске. На крупных репозиториях глубокая иерархия даёт высокий когнитивный налог: держать в голове путь, многократно раскрывать узлы, промахиваться мимо нужной ветки. При этом разработчик часто думает не «путь в дереве», а сущностями: текущий символ, соседний файл по смыслу, тест к классу, граница слоя.
Cascade IDE позиционируется как agent-first кокпит с явной моделью внимания (0021); не обязана копировать паттерн «одно дерево — единственная навигация» из классических IDE. Напротив: предложить несколько согласованных представлений workspace и режим «вокруг активного документа» — осознанный продуктовый дифференциатор.
Область языков (north-star)¶
Цель ближайших итераций — C# / экосистема .NET, а не «IDE на все языки мира». Глубина семантики навигации («связанные» файлы, символы, граф) в первую очередь опирается на Roslyn и рабочий цикл .sln / проектов. UI самой IDE на Avalonia; в продуктовом контуре могут быть сценарии Blazor и иной .NET-стек — без обязательства паритета языковых сервисов с VS/Rider для Python, Java, Go и т.д.
После открытия продукта дополнительные языки (редактор, LSP, навигация) возможны и не запрещены — но это не северная звезда и не критерий успеха v1. Формулировки в этом ADR про «универсальный» вид или «языки без семантики» читаются в свете C#-first: универсальность не является обязательством команды на этапе зрелости кокпита и агента.
Продуктовая метафора и целевое направление (обсуждение)¶
«Шкаф vs карта боя»: классическое дерево проекта ближе к архивному шкафу (физический адрес на диске), чем к карте текущего боя. В голове у разработчика часто живут логические связи («сервис — контракт — тесты»), а не путь src/domain/.... На больших решениях обозреватель превращается в длинный скролл и поиск «иголки в стоге сена» — это аргумент за альтернативные первичные представления, а не за отказ от дерева навсегда.
Граф связей и situational awareness: целевой образ — динамический граф релевантного контекста вокруг активного файла или задачи: узел «где я» и лучи к местам, которые работа затрагивает (зависимости, контракты, тесты, схема данных). В терминах кокпита это ближе к ситуационной осведомлённости (0021: устойчивый контур внимания), чем к статичной картинке каталога папок. Полная реализация графа всего решения остаётся вне обязательного scope v1 (см. раздел Не цели ниже).
Agent-first и «дерево от цели»: человек и агент в типичном сценарии мыслят зависимостями и задачей, а не вложенностью каталогов. Навигация «от цели / от активного узла», а не «от корня диска», выравнивает UX с тем, как уже ведут себя инструменты вроде Cursor — при сохранении честной работы с файлами на диске под капотом.
PFD vs MFD для вида «шкаф»: допустима политика: живой контекст (связанные узлы, граф, семантическая карта) — в зоне первичного внимания (0021 — регион PFD), а классическое дерево файлов оставить как вторичный инструмент (перемещение файлов, редкий обзор структуры) — в MFD или эквиваленте вторичного контура (0021 — MFD). Точное размещение — пресет (0010); принцип: не конкурировать за один якорь внимания двумя несовместимыми ментальными моделями без явного переключения режима.
Semantic Map и размещение: целевой UX-образ — семантическая карта (узлы уровня «Payment Logic», «DB Schema», «API Endpoint» со связями), а не обязательно строка пути src/.../payment.cs. Топология зон кокпита (где на экранах сидят PFD / Forward / MFD) задаётся строкой presentation и [presentation_grammar] — по EBNF в 0017 в ней только три якоря зон, без отдельного литерала «window». После разбора топология может привести ко второму TopLevel (например MfdHostWindow на другом дисплее) — это следствие якорей и числа экранов (0017, в т.ч. п. 8), а не «магический токен в строке». Окна вроде настроек и элементы плавающего хрома — по другим правилам (0012, код, 0028). Пресеты — 0010, 0021. Детали полей Semantic Map — вне этого ADR.
(Сводка: presentation задаёт якоря и экраны → из этого вытекает, будет ли второй TopLevel под MFD. Не вытекает из неё произвольное «окно настроек» — там нет такого токена в EBNF.)
Решение (принципы)¶
1. Дерево файлов — не единственный канон¶
Правило: продукт поддерживает классический обозреватель решения как знакомый и полезный режим (обзор структуры репозитория, операции с файлами там, где уместно), но не закрепляет его как единственный способ ответить на вопрос «где я и что рядом со мной в работе».
Дополняющие формы навигации (направления реализации; не обязательно всё в одной версии):
- «Текущий файл и связанные» — соседи по папке или namespace, partial-классы, пары код/тест по соглашению, недавние документы в том же срезе задачи;
- навигация по символам (типы, члены) и outline активного документа;
- несколько представлений в одном регионе: вкладки или split (дерево | связанные | символы) с синхронизацией выбора с активным документом.
2. Связь с зоной PFD и 0037¶
Навигационные панели в регионе PFD по-прежнему выполняют роль якоря «где я в работе» (0021; 0037 — глоссарий). Они не обязаны быть помечены как строгая PFD-поверхность: интерактив (клики, раскрытие узлов) остаётся допустимым. Новые виды навигации не ослабляют инварианты приборов (EICAS, компактное здоровье workspace, статус агента и т.д.), явно помеченных контрактом 0037.
3. Пресеты, размещение и канон раскладки (зафиксировано)¶
Канон варианта раскладки: (PFD)(Forward)(MFD) — три региона в одной оболочке главного окна: зона первичного внимания (PFD), основная рабочая область (Forward — редактор, документ), вторичный контур (MFD). Порядок слева направо (или эквивалент в вертикальном пресете) задаёт предсказуемый scan pattern — устойчивый путь взгляда и руки по кокпиту (0021).
Окна и внимание (продуктовый дефолт, не запрет ОС): для навигации по workspace и смежных основных панелей работы предпочтительно держать их в регионах той же оболочки (PFD)(Forward)(MFD): так сохраняется scan pattern — один непрерывный контур «прибор — работа — вторичка». Отдельные top-level окна для этого контура легко разрывают этот путь взгляда и моторики.
Строка presentation и TopLevel: в тексте строки нет токена «window» — только якоря PFD / Forward / MFD (0017 § EBNF). Но результат разбора (несколько экранов, MFD на втором) может включать открытие MfdHostWindow — второго TopLevel под полным MFD (0017 п. 8); это не противоречит «топология из presentation», это её интерпретация вместе с мониторами. Окно настроек, плавающий хром и прочие окна вне этой семантики — по коду и 0012, 0028, 0010. Канон (PFD)(Forward)(MFD) в одном главном окне остаётся дефолтом для scan pattern; см. также сводку выше.
Мульти-монитор: предпочтительно расширять ту же логическую схему (например перенос целого региона на второй дисплей как один связанный фрагмент оболочки), а не плодить дублирующие плавающие окна навигации «на втором экране» без жёсткой связи с основным scan path. Детали — пресеты (0010, 0017); этот ADR фиксирует принцип, не пиксель-в-пиксель.
Набор и плотность инструментов внутри PFD/MFD по-прежнему может зависеть от режима UI / пресета.
4. Semantic Map — стратегия v1 и абстракция укладки (зафиксировано)¶
Гибридная поставка (v1):
- Базовый режим — список «связанные» (и при необходимости outline) — без обязательного графа.
- Мини-карта — граф ограниченного подграфа (капы = верхние границы по числу узлов и рёбер, плюс операционные лимиты вроде таймаута укладки; см. Не цели, закрыто: определение капов, открыто: конкретные числа п.3). Смысл — не перегружать внимание в PFD; при проектировании конкретных N уместен ориентир 7±2 одновременно обозримых сущностей (Miller), понимая что инженерный порог может быть выше за счёт кластеризации/свёртки. При превышении — деградация к списку, а не «ломать» PFD.
- Укладка для мини-карты: на первых итерациях допустим простой встроенный layout (например иерархический/силовой на C#) или внешний движок (в т.ч. обсуждаемый вариант Skia + GraphViz: GraphViz для раскладки, Skia/Avalonia для отрисовки и взаимодействия) — выбор за реализацией
ILayoutEngine, не за UI.
Абстракция ILayoutEngine (имя — каноническое для кода; в тексте ADR — «движок укладки»):
- Вход: нейтральное описание графа (узлы, рёбра, метаданные для подписей).
- Выход: позиции узлов и геометрия рёбер (или эквивалент для рендерера), либо отказ с причиной (таймаут, слишком большой граф).
- Несколько реализаций (простая managed-укладка, GraphViz, при необходимости MSAGL и др.) — взаимозаменяемы без переписывания панели навигации; сравнение подходов — по мере опыта, не блокер v1.
Операционные ограничения: таймаут на укладку, явный кап по размеру графа, предсказуемый fallback — обязательны в контракте использования движка.
Последствия¶
- Появляется явное разрешение проектировать навигацию как набор режимов ответа на «где я», а не только как копию дерева файлов из других IDE; канон
(PFD)(Forward)(MFD)и scan pattern — дефолт для кокпита; связкаpresentation→ топология → возможныйMfdHostWindowи окна вне EBNF — §3, сводка, 0017. - MCP: агент может опираться на
get_code_navigation_contextс пресетами, эхом фильтра и явной семантикой рёбер вsubgraph— см. § Agent/MCP; это снижает риск «списка файлов без смысла» в сценариях 0042, не заменяя UI-карту. - Реализация потребует: модель связанных файлов (эвристики, соглашения, при наличии — семантика Roslyn для C#), UX синхронизации между представлениями, команды переключения вида (0030); для Semantic Map — движок укладки за абстракцией
ILayoutEngineи общий контракт рендера (например Skia), см. §4; источник истины графа и слой TOML — зафиксированы. - Онбординг и discoverability (0027) могут объяснять пользователю зачем несколько видов навигации, а не один.
- Метафора PFD = карта боя / живой контекст, MFD = шкаф по необходимости задаёт язык для пресетов и маркетинга; реализация по шагам, без обязательства «убрать дерево» в первом релизе.
Не цели¶
- Полный граф зависимостей всего решения как обязательный экран первой версии.
- Замена поиска по файлам, Go to symbol и палитры команд — ортогональны этому ADR.
- Паритет навигации и языковых сервисов для всех языков, как у «полного» polyglot IDE: north-star остаётся C# / .NET (область языков); отдельные языки позже — по продуктовой очереди, не как условие успеха v1.
Semantic Map: уровень абстракции узлов (слои конфигурации)¶
Переключатель в UI — это режим представления панели Semantic Map (аналог «масштаба слоя» карты): он задаёт, что считается узлом и как строится граф. Это не обязано дублироваться командной политикой в репозитории.
Дефолты и память — не то же самое, что мгновенный режим «сейчас»:
settings.toml(0028) — личный дефолт уровня абстракции на этой машине (для всех workspace, если нет командного override).<repo>/.cascade/workspace.toml(merge с бандлом, 0010) — опционально: командное соглашение для этого репо («здесь карту ведём в типах / в фичах»).- Сессионное состояние (и при договорённости — путь как у прочей «памяти» UI по workspace, см. 0017, 0028) — последний выбор на переключателе в UI; не коммитится.
Приоритет при открытии workspace: merge workspace.toml (команда) → settings.toml (личный дефолт) → встроенный дефолт продукта.
Что именно за численные капы (пороги по числу узлов/рёбер, плюс таймаут укладки) и принцип деградации в список — закрыты; конкретные значения N — открытый вопрос п.3. Ориентир для «сразу обозримого» подграфа в PFD — порядок 7±2 сущностей (Miller), без фиксации как единственного закона.
Semantic Map: источник истины и слой конфигурации (зафиксировано)¶
Позиция: для C# структура графа «что с чем связано в коде» — источник истины в runtime: Roslyn + решение (и эвристики поверх), а не обязательное дублирование узлов и рёбер в TOML — иначе рассинхрон с репозиторием.
Пресеты и <repo>/.cascade/workspace.toml (merge с бандлом, 0010) — про раскладку и режимы UI, не про обязательное ручное перечисление узлов Semantic Map. Строка presentation (0017) не расширяется семантикой карты.
Опционально позже: закоммиченные аннотации (подписи фич, ручные кластеры, то, что из кода не вывести или что команда хочет зафиксировать для агента/онбординга) — отдельная секция или файл под .cascade/, если появится продуктовая потребность; v1 может обходиться без этого слоя.
Кэш индекса или подграфа в %LocalAppData% (0028) — производительность и объём, не договорённость с командой в Git; сброс без потери истины.
Agent/MCP — реализованный контракт (Pareto-слой)¶
IDE-команда get_code_navigation_context (ide_execute_command) — режимы related (список связанных файлов с кратким обоснованием) и subgraph (узлы и рёбра с численными капами max_nodes / max_edges и max_related для списка). Якорь — активный документ в редакторе или явный file_path. Источник файлов — дерево загруженного решения; семантика связей — эвристики C# / partial / XAML / тесты / namespace / каталог (0028 не про граф в TOML, но про канал пользовательских настроек).
Базовые пресеты — один источник в репо (CodeNavigation/presets.toml): файл копируется рядом с exe (как UiModes/, Hotkeys/); при отсутствии файла на диске тот же текст подхватывается из встроенного ресурса сборки (без дублирующего литерала в коде). Содержимое по умолчанию: peers_only, no_namespace_noise, tests_and_peers, structure_only.
Репозиторий (команда) — в .cascade/workspace.toml в корне открытого решения, секция [code_navigation] и [[code_navigation.presets]] (тот же формат, что в settings.toml). Merge по id поверх бандла IDE; приоритет ниже пользовательского слоя (см. ниже). Согласовано с паттерном overlay метрик UI из 0021 (UiWorkspaceToml + репо).
Пользовательский overlay — в %LocalAppData%\CascadeIDE\settings.toml, [[code_navigation.presets]]: у каждой таблицы id, опционально include_kinds / exclude_kinds. Запись с тем же id перекрывает и бандл, и репо. Итоговый порядок: бандл → .cascade/workspace.toml → settings.toml.
Аргументы MCP: помимо режима и путей, поддерживаются preset (имя из объединённого набора пресетов), include_kinds, exclude_kinds. Правило merge: непустой include_kinds в запросе заменяет include пресета; exclude_kinds из запроса объединяется с exclude пресета (дедупликация по каноническому имени вида). Неизвестный пресет или ошибка в данных пресетов → ответ с error: bad_preset.
Канон имён видов связей (стабильный контракт для агента): partial_peer, project_peer, xaml_codebehind_pair, test_counterpart, same_namespace, same_directory. Неизвестные токены в списках игнорируются; пустой белый список после нормализации трактуется как «без ограничения по include» (см. реализацию фильтра).
Эхо фильтра в JSON: в ответах обоих режимов присутствует объект kind_filter: preset (запрошенное имя или null), include_kinds_effective, exclude_kinds_effective — канонические списки после merge, чтобы агент видел эффективный фильтр без повторного чтения настроек.
Режим subgraph: узел несёт семантический kind — вид связи с якорем (не обобщённое «related»). Ребро несёт related_kind для пары узлов. Так агент различает, например, соседа по проекту и совпадение по namespace.
Канон вызова и таблица аргументов — docs/MCP-PROTOCOL.md; пошаговые сценарии для агентов — workspace-navigation-mcp-cookbook.md.
Этот слой не заменяет полноценную Semantic Map в UI и не фиксирует выбор ILayoutEngine; он даёт агенту предсказуемый JSON поверх текущих эвристик.
Закрытые вопросы (сняты с повестки открытых)¶
Ранее стояли в списке «открытых»; решение перенесено в тело ADR или во внешние ADR.
-
PFD vs MFD / второе окно /
presentationvswindow. Закрыто: канон(PFD)(Forward)(MFD)и scan pattern для кокпитной навигации; в строкеpresentationнет токенаwindow, ноMfdHostWindowможет следовать из топологии и мониторов (0017). См. §3, сводку. -
Semantic Map: переключатель уровня абстракции узлов (файл / тип / «фича») и где хранить дефолты (
settings.tomlvsworkspace.tomlvs сессия). Закрыто: переключатель — режим представления панели; дефолты и приоритет merge — в Semantic Map: уровень абстракции узлов. (Какие уровни абстракции войдут в первую поставку — остаётся частью открытого п.1, если не уточнено отдельно.) -
Semantic Map: что такое «численные капы» и ориентир 7±2 (Miller). Закрыто как определение и эвристика: капы — отсечки по числу узлов/рёбер (и смежные лимиты: таймаут укладки, возможно глубина обхода); выше порога — деградация в список или иной fallback; 7±2 — ориентир обозримости, не жёсткое N в коде. См. §4. Конкретные численные значения по умолчанию — не закрыты, см. открытый п.3.
-
Semantic Map: данные vs пресеты vs
presentation— где «узлы» (слой конфигурации, не СУБД). Закрыто: Roslyn-first истина в runtime; пресеты /workspace.toml— не обязательное хранилище графа; опционально позже — аннотации в.cascade/; кэш в%LocalAppData%— производительность. См. Semantic Map: источник истины и слой конфигурации. -
MCP
get_code_navigation_context: стабильные имена видов связей, пресеты, предсказуемый ответ. Закрыто для контракта агента: канон строковых видов (partial_peer, …), базовые пресеты в шипнутомCodeNavigation/presets.toml, overlay —[[code_navigation.presets]]вsettings.toml(0028), merge поidс бандлом и merge аргументов вызова с пресетом, эхоkind_filter, вsubgraph—kindна узлах иrelated_kindна рёбрах. См. § Agent/MCP. Углубление эвристик и новые виды связей — итерации продукта, не ломая канон без мажорной версии контракта.
Открытые вопросы¶
-
Минимальный набор представлений для первой поставки навигации в Cascade (в рамках C#-first). (Частично направлено гибридом v1 в §4: список «связанные» + опциональная мини-карта; финальный минимум и обязательные вкладки/режимы — TBD.)
-
Канон «связанных» для C# (Roslyn): полный контракт данных и UX в панелях IDE; для MCP зафиксированы имена видов связей и ответ с эхом фильтра — см. § Agent/MCP. Расширение на другие языки — отдельная фаза, вне north-star.
-
Semantic Map: численные значения по умолчанию — конкретные пороги по числу узлов и рёбер в подграфе мини-карты, таймаут укладки, при необходимости глубина обхода; пороги деградации в список; профилирование на очень больших решениях. (Принцип капов и эвристика 7±2 — закрыты п.3;
ILayoutEngine— §4. Слой данных и пресеты — закрыты п.4.)
История изменений¶
| Дата | Изменение |
|---|---|
| — | Agent/MCP: get_code_navigation_context. |
| — | блок открытые vs закрытые вопросы; канон (PFD)(Forward)(MFD) (scan pattern; уточнение: строка presentation ≠ токен window); Semantic Map: ILayoutEngine. Ещё |
| 2026-04-11 | Semantic Map: источник истины и слой конфигурации (зафиксировано). |
| 2026-04-13 | расширен контракт MCP: именованные пресеты, kind_filter, subgraph: kind / related_kind; cookbook: workspace-navigation-mcp-cookbook.md. |
| 2026-04-16 | область языков; «Продуктовая метафора». |