| 1 | # ADR 0067: Graph-backed surfaces — общий контракт для семейства графовых экранов |
| 2 | |
| 3 | **Статус:** Accepted |
| 4 | **Дата:** 2026-04-19 |
| 5 | **Обновлено:** 2026-05-14 — ссылка на размещение общего слоя реализации в **CDS** ([0115](0115-cds-graph-backed-shared-layer.md)), не IDS. Подробности — [§ История](#adr0067-history). |
| 6 | |
| 7 | ## Связанные ADR |
| 8 | |
| 9 | | ADR | Роль | |
| 10 | |-----|------| |
| 11 | | [0065](0065-instrument-categories-domain-taxonomy.md) | Ось `graph_kind`, категории инструментов | |
| 12 | | [0113](0113-hci-semantic-map-orientation-layer.md) | Оси **provenance**, сводка трёх осей | |
| 13 | | [0114](0114-graph-edge-relation-kind-taxonomy.md) | Каталог `relation_kind` на рёбрах | |
| 14 | | [0115](0115-cds-graph-backed-shared-layer.md) | Общий слой реализации в **CDS**, не IDS | |
| 15 | | [0062](0062-git-submodules-semantic-map-subgraph.md) | GitMap — домен данных, общий pipeline | |
| 16 | | [0053](0053-semantic-map-control-flow-pfd.md) | Semantic Map, control flow | |
| 17 | | [0056](0056-semantic-map-pipeline-adoption.md) | Внедрение Skia pipeline в карту | |
| 18 | | [0055](0055-skia-instrument-composition-pipeline.md) | Intent → Declutter → Layout → Render | |
| 19 | | [0039](0039-workspace-navigation-affordances.md) | Навигация, MCP, subgraph | |
| 20 | | [0047](0047-cockpit-instrument-descriptor-and-slot-composition.md) | Instrument, слот, поверхность | |
| 21 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | Зоны внимания PFD/MFD | |
| 22 | | [0066](0066-cockpit-ui-vs-ide-presentation-layer.md) | Поверхность прибора vs хром IDE (`ModalOverlay`) | |
| 23 | |
| 24 | ## Резюме |
| 25 | |
| 26 | - Общий **контракт graph-backed поверхностей**: данные, взаимодействие, layout, sync. |
| 27 | - Семейство: карта намерений, GitMap, будущие графы; реализация — [0115](0115-cds-graph-backed-shared-layer.md). |
| 28 | - Оси **`graph_kind`**, provenance, **`relation_kind`** — в [0065](0065-instrument-categories-domain-taxonomy.md), [0114](0114-graph-edge-relation-kind-taxonomy.md). |
| 29 | |
| 30 | --- |
| 31 | ## Контекст |
| 32 | |
| 33 | В IDE появляется **не один** графовый экран, а **семейство** поверхностей, где пользователь и агент работают с **графом** как с главным объектом: Semantic Map (намерения кода / control flow), GitMap / submodules ([0062](0062-git-submodules-semantic-map-subgraph.md)), возможные будущие графы (зависимости, топология сервисов и т.д.). |
| 34 | |
| 35 | Если каждый сценарий вести **отдельным ad-hoc viewer**, неизбежно дублируются: |
| 36 | |
| 37 | - модель данных и идентичность узла/ребра в workspace; |
| 38 | - взаимодействие (масштаб, прокрутка, hit-test, жесты); |
| 39 | - семантика навигации («перейти к символу», «раскрыть subgraph», «синхронизировать с редактором»); |
| 40 | - абстракция раскладки (чтобы не копировать layout между доменами); |
| 41 | - выделение, фокус, клавиатурный контур; |
| 42 | - согласование с остальным workspace (дерево решения, открытые файлы, MCP, инвалидация при смене ветки/git). |
| 43 | |
| 44 | Нужен **общий архитектурный класс UI** — **graph-backed surface** — и явный **контракт** по измерениям ниже; **различаются домен графа и источник данных**, а не заново изобрётся колесо для каждого use case. |
| 45 | |
| 46 | Задача уровня **архитектуры платформы**, а не просьба «нарисуй узлы и рёбра». |
| 47 | |
| 48 | <a id="adr0067-key"></a> |
| 49 | |
| 50 | ### Ключевая мысль: граф — не только визуализация |
| 51 | |
| 52 | **Graph** в этой IDE — это **не** синоним картинки для отчёта. |
| 53 | |
| 54 | **Graph-backed surface** — это **навигационная поверхность IDE** на тех же правах, что **редактор**, **терминал**, **диагностики**, **обозреватель решения**: не декоративная диаграмма и не export-only preview, а **операционный surface**, через который и человек, и агент могут исследовать структуру, выбирать узлы, переходить к исходникам, фильтровать, фокусироваться и выполнять действия. Визуализация — следствие модели и контракта, а не наоборот. |
| 55 | |
| 56 | --- |
| 57 | |
| 58 | ## Решение |
| 59 | |
| 60 | Зафиксировать понятие **graph-backed surface** (рабочее имя): **инструмент или фрагмент UI**, в котором **первична** работа с **ориентированным (или помеченным) графом** как с объектом навигации и действий, согласованная с кокпитом и workspace по единым правилам; отрисовка — один из слоёв, не определение поверхности. **Размещение общей реализации** переиспользуемых частей этого класса в продукте — в контуре **CDS / Cockpit**, не в **IDS**; см. **[0115](0115-cds-graph-backed-shared-layer.md)**. |
| 61 | |
| 62 | <a id="adr0067-not"></a> |
| 63 | |
| 64 | ### Ограничения: что это не является |
| 65 | |
| 66 | Чтобы реализация и внешние агенты не «уезжали» в одноразовый viewer: |
| 67 | |
| 68 | - это **не** «diagram control» как полный ответ (диаграмма без модели навигации и синхронизации с workspace); |
| 69 | - это **не** слой **только** rendering; |
| 70 | - это **не** фича под **один** CFG / один use case; |
| 71 | - это **расширяемая платформа** для **нескольких** graph-backed инструментов (Semantic Map, GitMap, будущие графы зависимостей / связей и т.д.). |
| 72 | |
| 73 | <a id="adr0067-extra"></a> |
| 74 | |
| 75 | ### Дополнительные требования к платформе |
| 76 | |
| 77 | Помимо [таблицы измерений](#adr0067-dimensions), к целевому контракту относятся: |
| 78 | |
| 79 | - **Единая абстракция документа графа** (например **GraphDocument** или эквивалент): узлы/рёбра, метаданные, привязка к домену и `graph_kind` ([0065](0065-instrument-categories-domain-taxonomy.md)). |
| 80 | - **Единая семантика навигационных команд**: из узла — к **исходникам**, **деталям**, **связанному подграфу** / related graph (формулировки могут отличаться по домену, **канал действий** — один). |
| 81 | - **Сериализуемое состояние** surface: выделение, viewport, фильтры — для восстановления сессии, тестов и согласования с остальными панелями. |
| 82 | - **Agent introspection**: состояние surface **читаемо** агентом и командами (MCP / `ide_*`), без единственной опоры на пиксели. |
| 83 | - **Разные layout engines** как подключаемые стратегии **без** поломки модели документа (см. Layout abstraction и [0055](0055-skia-instrument-composition-pipeline.md)). |
| 84 | |
| 85 | **Инвариант:** Semantic Map, GitMap и последующие графовые экраны — **представления одного класса** в смысле контракта; они **не обязаны** делить один `instrument_id` или один JSON wire-формат, но **обязаны** быть сопоставимы по измерениям [§2](#adr0067-dimensions), чтобы команда и агент могли переносить ожидания между экранами. |
| 86 | |
| 87 | Реализация допускается **поэтапно** (strangler): сначала два потребителя (например Semantic Map + GitMap) выявляют общий минимум; контракт в коде (`interface` / набор протоколов) расширяется без нарушения ADR. |
| 88 | |
| 89 | <a id="adr0067-dimensions"></a> |
| 90 | |
| 91 | ### Измерения контракта (что явно согласовывается) |
| 92 | |
| 93 | | Измерение | Вопрос, на который отвечает слой | Примечание | |
| 94 | |-----------|-----------------------------------|------------| |
| 95 | | **Data model** | Что такое узел и ребро в **этом** домене; стабильный **ключ** в пределах сессии; связь с `graph_kind` и категорией инструмента ([0065](0065-instrument-categories-domain-taxonomy.md)). | Домены ортогональны: код vs git-топология — разные графы, один класс поверхности. | |
| 96 | | **Edge / node provenance** | На каком **источнике правды** держатся связи и узлы для этого экрана: символьная модель (Roslyn), эвристика workspace (MSBuild), полнотекст/vec по корпусу (HCI), композит (например HCI → Roslyn). | Ортогонально **`graph_kind`**: тот же вид карты может сочетать слои с разным provenance; таблица и имена — **[0113 § оси](0113-hci-semantic-map-orientation-layer.md#adr0113-axes)**. | |
| 97 | | **Relation kind** | Какое **отношение** между сущностями утверждает ребро (наследует, ссылается на, partial peer, текстовое совпадение, …). | **[0114](0114-graph-edge-relation-kind-taxonomy.md)**; ортогонально **`graph_kind`** и **provenance**. | |
| 98 | | **Interaction model** | Пан, зум, «перетаскивание» вида, hit-test, ограничения FPS/Dark Cockpit ([0021](0021-pfd-mfd-cockpit-attention-model.md) §6). | Общие паттерны; детали могут отличаться по инструменту. | |
| 99 | | **Navigation semantics** | Что значит «перейти», «открыть», «запросить subgraph», как это стыкуется с MCP и агентом ([0039](0039-workspace-navigation-affordances.md)). | Семантика **действий**, не только отрисовка. | |
| 100 | | **Layout abstraction** | Где граница между данными графа и геометрией: этапы [0055](0055-skia-instrument-composition-pipeline.md); сменяемые **layout engines** под вид графа без дублирования Render. | GitMap и CFG не обязаны иметь один layout engine; обязаны иметь **одинаковую точку подключения** в pipeline. | |
| 101 | | **Selection / focus model** | Один или несколько выбранных узлов; фокус клавиатуры; связь с «текущим» узлом для агента и UI. | Нужна согласованность с остальным кокпитом. | |
| 102 | | **Command routing** | Команды IDE, контекстное меню, хоткеи доходят до surface предсказуемо; не дублировать разрозненные обработчики без политики. | Связь с [0013](0013-command-surface-and-discoverability.md), [0030](0030-command-ids-hotkeys-and-ui-registry-layers.md). | |
| 103 | | **Deep-linking / воспроизводимость** | Переход по ссылке на узел/фильтр/view state; согласование с сериализуемым состоянием. | Не обязательно в v1 полностью; направление зафиксировано. | |
| 104 | | **Sync with workspace** | Связь выделения с редактором, деревом решения, git-состоянием; инвалидация при смене файла, ветки, решения; без второго источника правды. | Явные события или снимки, не скрытые глобалы. | |
| 105 | | **Observability (agent)** | Снимок состояния surface для агента и автоматизации; не только «что нарисовано», но и выделение, фокус, доменные ключи узлов. | См. [доп. требования](#adr0067-extra). | |
| 106 | |
| 107 | Контракт **не** требует одного общего типа `Graph` в памяти для всех доменов — требует **сопоставимости** протоколов и **отсутствия** несогласованных one-off viewer без обоснования. |
| 108 | |
| 109 | <a id="adr0067-agent-prompt"></a> |
| 110 | |
| 111 | ### Стартовый prompt для агента (English) |
| 112 | |
| 113 | Текст ниже можно использовать как единую отправную точку для проектирования и ревью (Cursor и др.): |
| 114 | |
| 115 | We need to design a **reusable graph-surface architecture** for the IDE, not a one-off graph viewer. Existing and upcoming features such as Semantic Map (CFG), Git submodules, and future dependency / relationship graphs should all fit the **same conceptual model**. |
| 116 | |
| 117 | A graph in this IDE is **not** just a visualization; it is an **interactive workspace surface** with navigation, focus, selection, commands, synchronization with other panes, and **agent-readable state** — on par with the editor, terminal, diagnostics, and solution explorer. |
| 118 | |
| 119 | **This is not:** only a diagram control; only a rendering layer; a single feature for one CFG use case. **It should be** an **extensible platform** for multiple graph-backed tools. |
| 120 | |
| 121 | Please propose an architecture for a generic graph-surface framework, including where appropriate: |
| 122 | |
| 123 | - graph **document** model and node/edge metadata; |
| 124 | - **layout** abstraction and pluggable layout engines without breaking the document model; |
| 125 | - **interaction** contract (pan/zoom/hit-test as needed); |
| 126 | - **command routing** and unified navigation semantics (e.g. node → source / details / related graph); |
| 127 | - **selection/focus** and synchronization with the rest of the IDE workspace; |
| 128 | - **deep-linking** and **serializable** surface state; |
| 129 | - **agent introspection** over surface state. |
| 130 | |
| 131 | Cross-check with ADR **0067** (graph-backed surfaces) and related ADRs on `graph_kind`, Semantic Map, GitMap, and the Skia pipeline. |
| 132 | |
| 133 | --- |
| 134 | |
| 135 | ## Последствия |
| 136 | |
| 137 | - Новые графовые фичи проходят проверку: **какое измерение** уже покрыто общим слоем, **что** доменно-специфично. |
| 138 | - Документация и ревью могут ссылаться на **graph-backed surface** и таблицу измерений вместо «ещё одна карта». |
| 139 | - Пайплайн [0055](0055-skia-instrument-composition-pipeline.md) остаётся **общим местом** для Layout/Render; источники графа подключаются как **адаптеры**, а не форки viewer. |
| 140 | |
| 141 | --- |
| 142 | |
| 143 | ## Не-цели (текущая фаза) |
| 144 | |
| 145 | - Единый **универсальный** layout для всех видов графов в одном релизе. |
| 146 | - Полная реализация всех измерений в коде до появления второго и третьего потребителя контракта — допустим **минимальный v0** и расширение. |
| 147 | - Замена [0062](0062-git-submodules-semantic-map-subgraph.md) или [0065](0065-instrument-categories-domain-taxonomy.md): они уточняют **домен**; этот ADR уточняет **класс UI**. |
| 148 | |
| 149 | --- |
| 150 | |
| 151 | ## Альтернативы (кратко) |
| 152 | |
| 153 | | Вариант | Минус | |
| 154 | |--------|--------| |
| 155 | | Отдельный viewer на каждый граф | Дублирование, расхождение навигации и синхронизации с workspace | |
| 156 | | Один жёсткий `GraphView` control на все данные | Не гнётся под разные домены и layout; тормозит эволюцию | |
| 157 | | Только гайд в Markdown без ADR | Нет стабильной ссылки для ревью и онбординга | |
| 158 | |
| 159 | --- |
| 160 | |
| 161 | ## История изменений |
| 162 | |
| 163 | <a id="adr0067-history"></a> |
| 164 | |
| 165 | | Дата | Изменение | |
| 166 | |------|-----------| |
| 167 | | 2026-04-19 | ключевая мысль «операционная surface», ограничения, доп. требования, seed для агента (EN). | |
| 168 | | 2026-05-14 | измерения **Edge / node provenance** ([0113 § оси](0113-hci-semantic-map-orientation-layer.md#adr0113-axes)) и **Relation kind** ([0114](0114-graph-edge-relation-kind-taxonomy.md)); обе ортогональны `graph_kind`. | |
| 169 | | 2026-05-14 | ссылка на размещение общего слоя реализации в **CDS** ([0115](0115-cds-graph-backed-shared-layer.md)), не IDS. | |
| 170 | |