| 1 | # ADR 0172: Session graph habitat — Intercom как рабочая память сессии |
| 2 | |
| 3 | **Статус:** Proposed (концепт / north-star) |
| 4 | **Дата:** 2026-07-10 |
| 5 | **Обновлено:** 2026-07-12 — habitat ≠ TOML axis; G1 = `primary_work_surface` default; session_graph prefs — future UI only |
| 6 | |
| 7 | ## Резюме |
| 8 | |
| 9 | Часть операторов живёт **почти целиком в Intercom**; редактор — по attach/reveal. Их stance — **conversation-first** [0120](0120-primary-work-surface-intercom-or-editor.md). |
| 10 | |
| 11 | **Моат CIDE — не «ещё один чат»**, а **нелинейная сессия**: темы, ветки, rewind, scope на экране [0031](0031-agent-chat-clarification-batches-and-threading.md), [0116](0116-intercom-session-tree-and-agent-message-steering.md). Линейная flat feed — **проекция одной ветки**, не единственная правда. |
| 12 | |
| 13 | [0171](0171-presentation-tiers-compact-vs-cockpit.md) задаёт tier (compact/cockpit). **0172** задаёт **habitat** (имя session-graph canvas в глоссарии) для conversation-first: **Session graph canvas** в Forward, код on demand. **Habitat — не ось `settings.toml`**; продукт conversation-first выражается через `primary_work_surface = intercom` [0120](0120-primary-work-surface-intercom-or-editor.md). |
| 14 | |
| 15 | **Принято направление (концепт):** |
| 16 | |
| 17 | 1. **Session graph habitat** — Forward = Intercom canvas (scope + worklines + tree/timeline); не отдельный переключатель `habitat = …` в TOML. |
| 18 | 2. **Topics = worklines index** — параллельные `ThreadNode` [0072](0072-chat-topic-cards-intent-melody-keyboard-contract.md); **не** аналог Cursor New Chat. |
| 19 | 3. **Detail default** — scope strip + **Tree | Timeline**; flat feed только для **выбранной ветки** [0170](0170-intercom-feed-readability-mlp.md). |
| 20 | 4. **Composer modes:** continue · **steer** · **follow-up** [0116](0116-intercom-session-tree-and-agent-message-steering.md). |
| 21 | 5. **Harness неизменен** [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md). |
| 22 | |
| 23 | ## Design thesis |
| 24 | |
| 25 | Классические IDE заточены под **написание кода**: редактор в центре, а сопутствующее — решения, intent, история рассуждения, «почему так» — размазано по боковым панелям, файлам в репо и внешним тредам, и **читается плохо**. В agentic-цикле **писать код в основном берёт на себя агент**; работа человека смещается к **пониманию, направлению и фиксации решений**. Редактор не исчезает — он для проверки и точечных правок, когда нужно руками. |
| 26 | |
| 27 | Session graph habitat — ответ на эту ось: Intercom — не «ещё один чат», а **инфраструктура восприятия сессии** (ветки, scope, worklines, batches). Moat — удобство **читать и управлять** нелинейной работой, а не паритет линейной ленты с Cursor. |
| 28 | |
| 29 | --- |
| 30 | |
| 31 | ## Связанные ADR |
| 32 | |
| 33 | | ADR | Роль | |
| 34 | |-----|------| |
| 35 | | [0031](0031-agent-chat-clarification-batches-and-threading.md) | Пакеты уточнений; обзор размаха; ветвления | |
| 36 | | [0045](0045-agent-chat-persistence-event-log-and-projections.md) | Append-only события; проекции | |
| 37 | | [0072](0072-chat-topic-cards-intent-melody-keyboard-contract.md) | Topic overview/detail/back | |
| 38 | | [0096](0096-intercom-topic-card-summary-and-product-spine.md) | Сводка; spine ортогонален main | |
| 39 | | [0116](0116-intercom-session-tree-and-agent-message-steering.md) | Session tree; rewind; steer/follow-up | |
| 40 | | [0120](0120-primary-work-surface-intercom-or-editor.md) | `primary_work_surface = intercom` | |
| 41 | | [0126](0126-intercom-inspect-slash-and-compact-chrome-status.md) | `/topic tree`, inspect | |
| 42 | | [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md) | Harness ≠ habitat | |
| 43 | | [0170](0170-intercom-feed-readability-mlp.md) | Comfortable flat feed внутри ветки | |
| 44 | | [0171](0171-presentation-tiers-compact-vs-cockpit.md) | Compact ≠ session-graph default | |
| 45 | | [0173](0173-intercom-intent-card-session-decision-capture.md) | Intent card: фиксация решений в workline; event log; эскалация в ADR | |
| 46 | | [0174](0174-sedm-software-engineering-decision-making-ux-spine.md) | SEDM: операционная модель; context card; UX spine; SM/CRS перепривязка | |
| 47 | |
| 48 | --- |
| 49 | |
| 50 | ## Дифференциация от линейного agent chat (Cursor и аналоги) |
| 51 | |
| 52 | | | Linear agent chat | Session graph (CIDE) | |
| 53 | |--|-----------------|----------------------| |
| 54 | | Единица «нового» | New Chat / New Agent | **Fork branch** / новая **workline** в той же сессии | |
| 55 | | История | Хронология | **Дерево** + хронология как проекция | |
| 56 | | Восстановление контекста | Скролл | **Scope strip** + tree | |
| 57 | | Уточнения плана | Одна строка | **Clarification batch** [0031](0031-agent-chat-clarification-batches-and-threading.md) | |
| 58 | | Долгий tool-run | Сообщение в ленту | **Steer** vs **follow-up** [0116](0116-intercom-session-tree-and-agent-message-steering.md) | |
| 59 | | Продуктовая нить | — | **Spine** [0096](0096-intercom-topic-card-summary-and-product-spine.md) | |
| 60 | |
| 61 | **Anti-pattern moat loss:** topics как список чатов + только flat feed в detail → **паритет с Cursor без нелинейности**. |
| 62 | |
| 63 | --- |
| 64 | |
| 65 | ## Контекст |
| 66 | |
| 67 | ### Три оси (не смешивать) |
| 68 | |
| 69 | ```text |
| 70 | Tier (пространство) : compact | cockpit ← [display.presentation] tier |
| 71 | Forward [0120] : intercom | editor ← [workspace] primary_work_surface |
| 72 | Stance (продукт) : session-graph-first ← не TOML; Agent/Intent/Conversation-first |
| 73 | ``` |
| 74 | |
| 75 | **Не путать:** **Habitat** в глоссарии = имя canvas (scope + worklines + tree/timeline), не четвёртая ось настроек рядом с tier и `primary_work_surface`. |
| 76 | |
| 77 | ### Оператор session-graph-first |
| 78 | |
| 79 | | ~99% | Intercom canvas: worklines, scope, tree/timeline, composer | |
| 80 | | Редко | Editor reveal из attach | |
| 81 | | Фон | Solution warmup; **не** SE tree вместо чата после `load_solution` | |
| 82 | |
| 83 | --- |
| 84 | |
| 85 | ## Решение |
| 86 | |
| 87 | ### 1. Session graph canvas (не «lanes + feed») |
| 88 | |
| 89 | ```text |
| 90 | ┌─ Scope: N branches · open batch · last decision @msg ─────────┐ |
| 91 | │ Worklines │ [ Tree ] [ Timeline ] │ |
| 92 | │ index │ graph of selected topic / branch │ |
| 93 | │ (rows) │ + flat feed (THIS branch only, measure cap) │ |
| 94 | ├───────────┴──────────────────────────────────────────────────────┤ |
| 95 | │ Composer: Continue | Steer | Follow-up + slash │ |
| 96 | └──────────────────────────────────────────────────────────────────┘ |
| 97 | Code · Terminal — on demand (MFD / mon2 / reveal) |
| 98 | ``` |
| 99 | |
| 100 | ### 2. Слои UI |
| 101 | |
| 102 | | Слой | Назначение | Cursor-like? | |
| 103 | |------|------------|--------------| |
| 104 | | **Worklines index** | Параллельные темы; строка + branch count + open Q | Внешне как channel list | |
| 105 | | **Scope strip** | Снимок сессии/темы без скролла | **Нет** | |
| 106 | | **Tree view** | Ветки, rewind, continue from | **Нет** | |
| 107 | | **Timeline view** | Flat feed выбранной ветки | Да (гигиена читаемости) | |
| 108 | | **Spine** | Ортогональная продуктовая линия | **Нет** | |
| 109 | |
| 110 | ### 3. Инварианты |
| 111 | |
| 112 | | # | Инвариант | |
| 113 | |---|-----------| |
| 114 | | S1 | Канон — **event log / session tree** [0045](0045-agent-chat-persistence-event-log-and-projections.md); лента — проекция | |
| 115 | | S2 | Forward default = **Intercom** (`primary_work_surface = intercom`) | |
| 116 | | S3 | Overview worklines = **строки** (title + branches + summary), не hero cards | |
| 117 | | S4 | Detail **не** только timeline; есть **Tree** и scope | |
| 118 | | S5 | **Continue from here** на узле → новые события как потомки [0116](0116-intercom-session-tree-and-agent-message-steering.md) | |
| 119 | | S6 | `load_solution` не переключает на SE/Terminal | |
| 120 | | S7 | Measure cap в timeline ветки [0170](0170-intercom-feed-readability-mlp.md) | |
| 121 | |
| 122 | ### 4. Мониторы |
| 123 | |
| 124 | #### 1 × 16:9 |
| 125 | |
| 126 | Forward ~90% = полный session canvas (index + scope + tree/timeline + composer). |
| 127 | |
| 128 | #### 2 × 16:9 (operator default) |
| 129 | |
| 130 | | Primary | Secondary | |
| 131 | |---------|-----------| |
| 132 | | Session graph maximized | Editor host **on reveal**; иначе пусто/браузер | |
| 133 | |
| 134 | Не `(P+F)(M)` cockpit. |
| 135 | |
| 136 | ### 5. Настройки (целевые) |
| 137 | |
| 138 | ```toml |
| 139 | [workspace] |
| 140 | primary_work_surface = "intercom" # conversation-first default [0120] |
| 141 | |
| 142 | [display.presentation] |
| 143 | tier = "compact" |
| 144 | # compact_intercom_placement = "side" | "bottom" — см. [0171](0171-presentation-tiers-compact-vs-cockpit.md) |
| 145 | |
| 146 | # Будущие UI-префы session graph (не ось habitat): |
| 147 | # [display.presentation.session_graph] |
| 148 | # workline_rail_width_px = 200 |
| 149 | # feed_max_measure_ch = 72 |
| 150 | # detail_default_view = "tree" # tree | timeline |
| 151 | # overview_style = "rows" |
| 152 | |
| 153 | [intercom] |
| 154 | feed_metrics = "comfortable" |
| 155 | ``` |
| 156 | |
| 157 | **Убрано из target settings:** `habitat = "session-graph"` — продукт уже conversation-first; отдельный runtime knob дублировал бы `primary_work_surface` и tier. |
| 158 | |
| 159 | ### 6. Anti-patterns |
| 160 | |
| 161 | | Anti-pattern | Почему | |
| 162 | |--------------|--------| |
| 163 | | Detail = только flat feed | = Cursor; моат мёртв | |
| 164 | | Topics = New Chat | Линейные сессии вместо worklines | |
| 165 | | Hero cards overview | Кринж на wide canvas | |
| 166 | | SE после load_solution | Отбирает session canvas | |
| 167 | |
| 168 | ### 7. Concept vs implementation ladder |
| 169 | |
| 170 | Wireframe v2 — **north-star poster**, не acceptance criteria для первого PR. На кадре всё уже случилось: scope заполнен, tree и timeline согласованы, worklines с branch count, пустые состояния скрыты. В коде слои появляются **по фазам**; сравнение poster ↔ G1 почти всегда выглядит как «фиаско», хотя это **непровал moat**, а незавершённая лестница. |
| 171 | |
| 172 | **Два класса артефактов:** |
| 173 | |
| 174 | | Артефакт | Роль | Критерий успеха | |
| 175 | |----------|------|-----------------| |
| 176 | | Wireframe / генерация | Сжатая визуальная гипотеза; согласование stance | «Понятно, куда смотрим» | |
| 177 | | Фаза Gn | Ship-единицу с проверяемым инвариантом | Deliverable фазы + S1–S7, **не** pixel-match PNG | |
| 178 | |
| 179 | **Что ожидать по фазам (намеренно «уродливо» — ок):** |
| 180 | |
| 181 | | Фаза | UI может выглядеть как | Это **не** провал, если | |
| 182 | |------|------------------------|-------------------------| |
| 183 | | **G1** | Обычный Intercom + flat feed | Forward = Intercom; `load_solution` не отбирает чат (S6) | |
| 184 | | **G2** | Лента + тонкая полоска scope (2–3 поля) | Scope читается **без скролла**; данные из log/projection | |
| 185 | | **G3** | Tree на mock/реальном `parent_id`; timeline = та же ветка | Toggle Tree↔Timeline; **continue from** пишет потомка в log (S5) | |
| 186 | | **G4** | Composer с явным steer/follow-up | Режим влияет на **когда** и **куда** в дереве попадает user msg [0116](0116-intercom-session-tree-and-agent-message-steering.md) | |
| 187 | | **G5+** | Batch UI, spine polish | Clarification batch виден в scope/tree | |
| 188 | |
| 189 | **Реальный провал moat** (стоп-кран, не «ещё не дорисовали»): |
| 190 | |
| 191 | - Detail застрял **только** на timeline без плана G3 (anti-pattern §6). |
| 192 | - Topics = New Chat / линейные сессии вместо worklines. |
| 193 | - Нет `parent_id`/ветки в log, но UI притворяется session graph. |
| 194 | - Сравниваем с wireframe и **откатываем** G2–G4 ради «красивой ленты». |
| 195 | |
| 196 | **Порядок работ:** сначала **data** (event log, `parent_id`, head, branch path [0116](0116-intercom-session-tree-and-agent-message-steering.md)), потом chrome. Timeline (Skia feed) уже есть — tree/scope **надстраиваются**, не переписывают Intercom с нуля. |
| 197 | |
| 198 | **Один инвариант за спринт** — не «habitat как v2», а например: «scope strip с N branches + open batch» (G2) или «toggle + continue from на одной workline» (G3). |
| 199 | |
| 200 | ### 8. API boundary (stateless FM) |
| 201 | |
| 202 | Session graph — **клиентская** модель. Cloud.ru Foundation Models и любой OpenAI-compatible провайдер — **stateless** `POST /v1/chat/completions`: массив `messages[]`, опционально tools. API **не** знает topics, tree, timeline, steer/follow-up, `session_id` от CIDE. |
| 203 | |
| 204 | ```text |
| 205 | ┌──────────────── CIDE (локально) ─────────────────┐ |
| 206 | │ Event log NDJSON ← канон [0045] │ |
| 207 | │ Session tree ← parent_id, branch, head │ |
| 208 | │ Worklines / scope ← продуктовые проекции │ |
| 209 | │ │ │ |
| 210 | │ ▼ │ |
| 211 | │ Orchestrator │ |
| 212 | │ · messages[] только для АКТИВНОЙ ветки │ |
| 213 | │ · ContextMinimizer / compactor [0166] │ |
| 214 | │ · MCP tools → ide_execute_command │ |
| 215 | │ · steer / follow-up → семантика вставки user │ |
| 216 | └─────────┼──────────────────────────────────────────┘ |
| 217 | ▼ |
| 218 | ┌──────────────── Cloud.ru FM (stateless) ───────────┐ |
| 219 | │ messages: [system, user, assistant, tool, …] │ |
| 220 | │ stream; нет branch_id / rewind на стороне API │ |
| 221 | └────────────────────────────────────────────────────┘ |
| 222 | ``` |
| 223 | |
| 224 | | Слой | Где живёт | FM API видит? | |
| 225 | |------|-----------|---------------| |
| 226 | | Session tree, ветки | Локальный log + Tree UI | **Нет** | |
| 227 | | Topics / worklines | Проекция + meta | **Нет** (кроме summary в system при compact) | |
| 228 | | Timeline | UI + источник для prompt | **Да** — как `messages[]` одной ветки | |
| 229 | | Steer / follow-up | Оркестратор CIDE | **Косвенно** — состав следующего request | |
| 230 | | Clarification batch | События `clarification_*` [0031](0031-agent-chat-clarification-batches-and-threading.md) | Структурированный user content в turn | |
| 231 | |
| 232 | **Один ход:** user msg → событие в log → проекция пути `root → head` → orchestrator собирает `messages[]` (только эта ветка; соседние ветки **не** жгут токены [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md)) → stream FM → `message_completed` с `parent_id` = текущий head → tool loop при function calling. |
| 233 | |
| 234 | **Fork / continue from:** меняется head и `parent_id` нового сообщения; следующий request несёт **другой путь** — без переписывания истории на стороне API (её там нет). Pay-per-token: нелинейность — **экономия**, не overhead. |
| 235 | |
| 236 | Конфиг провайдера (пример): `[ai.cloud.openai]` `base_url = https://foundation-models.api.cloud.ru`; harness [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md) не меняется от habitat. |
| 237 | |
| 238 | ### 9. Worklines — ретро-проекция, не форум |
| 239 | |
| 240 | Оператор **не обязан** создавать тему до разговора. Один composer, один поток реплик — как в обычном чате. **Workline** — имя и граница **уже идущей** линии работы, которую система и агент выводят из event log (и при необходимости уточняют одной фразой). |
| 241 | |
| 242 | | Принцип | Смысл | |
| 243 | |---------|--------| |
| 244 | | Разговор первичен | Структура следует за диалогом, не наоборот | |
| 245 | | Индекс сбоку | Параллельные линии видны без скролла всей сессии | |
| 246 | | Большинство реплик | Остаются в **активной** workline без split | |
| 247 | | Инициатор split | Оператор, агент или checkpoint — **предложение**, не модалка «создай топик» | |
| 248 | |
| 249 | **Anti-pattern:** обязательный title/summary или New-Chat-подобный вход перед первым сообщением. |
| 250 | |
| 251 | ### 10. Переключение worklines и доделывание хвостов |
| 252 | |
| 253 | Переключение строки в **worklines index** — смена **фокуса**, не новая сессия. У каждой workline свой **head** в session tree; при возврате head сохранён. |
| 254 | |
| 255 | ```text |
| 256 | Оператор кликает workline B |
| 257 | → timeline = flat feed ветки B до head_B |
| 258 | → tree/scope = проекция workline B |
| 259 | → composer пишет в B (новые события — потомки head_B) |
| 260 | → orchestrator: messages[] только путь active workline |
| 261 | ``` |
| 262 | |
| 263 | **Доделать в старой линии:** зайти в workline → закрыть open item (коммит, smoke, ADR) → при желании отметить в meta «closed» → вернуться в предыдущую workline (parked, head не сдвинулся). Scope strip показывает несколько open worklines без слияния их в один prompt. |
| 264 | |
| 265 | Статусы в индексе (продуктовые, не обязательный протокол): **active** · **parked** · open count на строке. |
| 266 | |
| 267 | ### 11. Spin-off — вынесение диапазона сообщений |
| 268 | |
| 269 | Когда линия внутри workline или целый смысловой блок вырос в отдельную работу, стороны договариваются **в чате**, система фиксирует **событие** (канон [0045](0045-agent-chat-persistence-event-log-and-projections.md)): |
| 270 | |
| 271 | ```text |
| 272 | 1. Предложение (user или agent): «вынести msg A…B в workline X?» |
| 273 | 2. Согласие или отказ одной короткой репликой |
| 274 | 3. Событие spin_off (имя в log уточняется при реализации): |
| 275 | source_workline, target_workline, msg_range, agreed |
| 276 | 4. Проекция: сообщения rehome в target; в source — collapsed marker |
| 277 | ``` |
| 278 | |
| 279 | **UI в timeline (активная ветка source):** system card / спойлер, свёрнут по умолчанию: |
| 280 | |
| 281 | ```text |
| 282 | ┌─ Вынесено в «VDS» (msg 840–1020) ─── [перейти] [развернуть] ─┐ |
| 283 | └───────────────────────────────────────────────────────────────┘ |
| 284 | ``` |
| 285 | |
| 286 | Сообщения **не удаляются** из log; меняется **принадлежность workline** и материализация prompt. Отказ на шаге 2 — no-op, лента без изменений. |
| 287 | |
| 288 | **Отличие от fork branch:** fork — ветвление **внутри** workline (tree); spin-off — перенос **диапазона** в другую workline (или новую). |
| 289 | |
| 290 | ### 12. Materialization для агента (двухслойный роутинг) |
| 291 | |
| 292 | Ограниченный контекст FM и дефицит внимания оператора — **одна экономика**. Агент не «живёт во всём графе»; habitat задаёт, **что попадает в ход**. |
| 293 | |
| 294 | | Слой | Что решает | Аналог | |
| 295 | |------|------------|--------| |
| 296 | | **Структурный** | Какая workline активна; путь `root → head` в дереве | Активная ветка в `messages[]` | |
| 297 | | **Семантический** | Какие знания и тулы подтянуть | KB: status → playbook → pull; `route_context` [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md) | |
| 298 | |
| 299 | Соседние ветки и worklines **не** входят в `messages[]`, пока не станут активными. Scope strip и one-liner в system — сжатая карта («2 open worklines»), не полный dump. Решения и checkpoint — KB / export, chat context — кэш. |
| 300 | |
| 301 | Workline может нести **intent tag** (например `cascade-ide/habitat`) → bias для `route_context` и MCP pull без чтения всей сессии. |
| 302 | |
| 303 | **Intent card** [0173](0173-intercom-intent-card-session-decision-capture.md) — типизированная фиксация решения **внутри** workline (`outcome`, `trigger`, `considered[]`, `chosen_approach` + `selection_rationale`); не заменяет intent tag и не равна ADR. В лестнице **SEDM** [0174](0174-sedm-software-engineering-decision-making-ux-spine.md) — артефакт **T1**; **context card** (T2) — Perceive для файла в scope strip. |
| 304 | |
| 305 | --- |
| 306 | |
| 307 | ## Фазы |
| 308 | |
| 309 | | Фаза | Содержание | Moat? | |
| 310 | |------|------------|-------| |
| 311 | | **G0** | ADR + wireframe v2 | Док | |
| 312 | | **G1** | `primary_work_surface = intercom` + Intercom Forward (без coercion tier→editor) | Habitat | |
| 313 | | **G2** | Scope strip (minimal) | **Да** | |
| 314 | | **G3** | Tree ↔ Timeline toggle; continue from | **Да** | |
| 315 | | **G4** | Steer/follow-up в composer | **Да** | |
| 316 | | **G5** | Clarification batch UI | **Да** | |
| 317 | | **G6** | 2-mon wizard | Habitat | |
| 318 | |
| 319 | **Приоритет moat:** G2–G4 выше ширины панели и hero polish. |
| 320 | |
| 321 | --- |
| 322 | |
| 323 | ## Визуальный концепт |
| 324 | |
| 325 | - v1 (устарел для moat): [cide-conversation-habitat-concept.png](../design/cide-conversation-habitat-concept.png) |
| 326 | - **v2 (актуальный):** [cide-session-graph-habitat-concept-v2.png](../design/cide-session-graph-habitat-concept-v2.png) |
| 327 | |
| 328 | **North-star:** |
| 329 | |
| 330 | > **Одна сессия — много линий и веток; scope и tree на экране; лента — вид одной ветки; код по attach.** |
| 331 | |