Перейти к содержанию

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.tomlsettings.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.

  1. PFD vs MFD / второе окно / presentation vs window. Закрыто: канон (PFD)(Forward)(MFD) и scan pattern для кокпитной навигации; в строке presentation нет токена window, но MfdHostWindow может следовать из топологии и мониторов (0017). См. §3, сводку.

  2. Semantic Map: переключатель уровня абстракции узлов (файл / тип / «фича») и где хранить дефолты (settings.toml vs workspace.toml vs сессия). Закрыто: переключатель — режим представления панели; дефолты и приоритет merge — в Semantic Map: уровень абстракции узлов. (Какие уровни абстракции войдут в первую поставку — остаётся частью открытого п.1, если не уточнено отдельно.)

  3. Semantic Map: что такое «численные капы» и ориентир 7±2 (Miller). Закрыто как определение и эвристика: капы — отсечки по числу узлов/рёбер (и смежные лимиты: таймаут укладки, возможно глубина обхода); выше порога — деградация в список или иной fallback; 7±2 — ориентир обозримости, не жёсткое N в коде. См. §4. Конкретные численные значения по умолчанию — не закрыты, см. открытый п.3.

  4. Semantic Map: данные vs пресеты vs presentation — где «узлы» (слой конфигурации, не СУБД). Закрыто: Roslyn-first истина в runtime; пресеты / workspace.toml — не обязательное хранилище графа; опционально позже — аннотации в .cascade/; кэш в %LocalAppData% — производительность. См. Semantic Map: источник истины и слой конфигурации.

  5. MCP get_code_navigation_context: стабильные имена видов связей, пресеты, предсказуемый ответ. Закрыто для контракта агента: канон строковых видов (partial_peer, …), базовые пресеты в шипнутом CodeNavigation/presets.toml, overlay — [[code_navigation.presets]] в settings.toml (0028), merge по id с бандлом и merge аргументов вызова с пресетом, эхо kind_filter, в subgraphkind на узлах и related_kind на рёбрах. См. § Agent/MCP. Углубление эвристик и новые виды связей — итерации продукта, не ломая канон без мажорной версии контракта.

Открытые вопросы

  1. Минимальный набор представлений для первой поставки навигации в Cascade (в рамках C#-first). (Частично направлено гибридом v1 в §4: список «связанные» + опциональная мини-карта; финальный минимум и обязательные вкладки/режимы — TBD.)

  2. Канон «связанных» для C# (Roslyn): полный контракт данных и UX в панелях IDE; для MCP зафиксированы имена видов связей и ответ с эхом фильтра — см. § Agent/MCP. Расширение на другие языки — отдельная фаза, вне north-star.

  3. 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 область языков; «Продуктовая метафора».