Forge
markdowndeeb25a2
1# ADR 0173: Intent card — структурированная фиксация решений в session graph
2
3**Статус:** Proposed
4**Дата:** 2026-07-12
5
6## Резюме
7
8В agentic-сессии большинство решений — **не ADR**: «почему так в этом ходе», «почему не вариант B», «как проверим». Эта информация **ищется** ежедневно (code review, debug, steer), но **почти не записывается** в VCS — см. эмпирику rationale (Al Safwan & Servant, ESEC/FSE 2019; Tao et al., FSE 2012).
9
10**Intent card** — мелкий **сессионный** артефакт: типизированное событие в append-only log [0045](0045-agent-chat-persistence-event-log-and-projections.md), проекция в Intercom timeline, материализация в harness [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md). Не заменяет ADR; может **питать** черновик ADR при checkpoint.
11
12Схема v1: **outcome** (что) · **trigger** (боль/зачем сейчас) · **considered[]** (отвергнутые варианты) · **chosen_approach** + **selection_rationale** (что выбрали и почему) · **constraints** · **validation_plan**.
13
14IOP [0121](0121-intent-oriented-programming-paradigm.md): capture **в потоке** workline, без обязательной формы на 15 полей и без Confluence.
15
16---
17
18## Связанные ADR
19
20| ADR | Роль |
21|-----|------|
22| [0045](0045-agent-chat-persistence-event-log-and-projections.md) | Канон хранения: новый тип события `intent_card_recorded` |
23| [0072](0072-chat-topic-cards-intent-melody-keyboard-contract.md) | Topic card = контейнер темы; intent card = решение внутри workline |
24| [0096](0096-intercom-topic-card-summary-and-product-spine.md) | Сводка workline может ссылаться на последнюю intent card |
25| [0116](0116-intercom-session-tree-and-agent-message-steering.md) | Steer/fork — триггеры предложения карточки |
26| [0121](0121-intent-oriented-programming-paradigm.md) | Парадигма IOP; дисциплина намерения |
27| [0155](0155-documentation-code-correspondence-and-architectural-drift.md) | L4 (event log) → L0 (ADR); сборка invariant из карточек |
28| [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md) | Сжатая материализация карточки в system one-liner |
29| [0172](0172-conversation-first-habitat.md) | Workline, scope strip, spin-off; habitat для карточек |
30| [0174](0174-sedm-software-engineering-decision-making-ux-spine.md) | SEDM: фазы, context card (T2), UX spine; intent card = T1 |
31
32### Вне ADR
33
34| Документ | Роль |
35|----------|------|
36| [iop-manifest-v1.md](../iop-manifest-v1.md) | IOP: явные намерения vs хаос потока |
37| KB `kb-cide-sdm-decision-making-research-v1` (agent-notes) | SDM / information needs → обоснование схемы |
38
39---
40
41## Контекст
42
43### Проблема индустрии
44
45| Симптом | Источник |
46|---------|----------|
47| «Зачем это изменение?» — самый важный и часто самый болезненный вопрос | Tao I-1 (парадокс: easy только при хорошем commit message) |
48| «Почему не по-другому?» — доминирует в review threads | Pascarella N1 (alternatives) |
49| Alternatives, constraints, side effects **ищут**, но **не записывают** | Al Safwan RQ4 (record gap) |
50| Ревьюер прыгает issue tracker ↔ diff ↔ CI ↔ chat | CRDM 2025 (tool backpack) |
51
52Session graph habitat [0172](0172-conversation-first-habitat.md) даёт **worklines и scope**, но без типизированной фиксации решений оператор и агент **повторяют archaeology** при возврате в parked workline или при checkpoint.
53
54### Чем intent card не является
55
56| Артефакт | Отличие |
57|----------|---------|
58| **ADR** | Долгоживущий, для команды/продукта, `docs/adr/`, invariant |
59| **Topic / workline card** | Индекс линии работы; контейнер, не схема решения |
60| **Commit message** | Описывает diff, часто post-hoc |
61| **Clarification batch** [0031](0031-agent-chat-clarification-batches-and-threading.md) | Ответы на пакет вопросов агента; другой lifecycle |
62| **Intent tag** на workline [0172 §12](0172-conversation-first-habitat.md#adr0172-materialization) | Короткий route-hint для MCP; не полный rationale |
63
64### Параллель с User Story / Job Story
65
66Intent card — **гибрид** product story и decision record:
67
68| Поле карточки | Аналог |
69|---------------|--------|
70| `trigger` | Job Story: *When [situation]…* / боль |
71| `outcome` | *…so I can [outcome]* / observable result |
72| `validation_plan` | Acceptance criteria |
73| `considered[]` + `selection_rationale` | **Не** в классической US (там solution в story — анти-паттерн); здесь **обязательно** — закрывает N1 и record gap |
74
75В agentic-цикле человек **выбирает путь**, а не только формулирует backlog item — карточка фиксирует **Process**-фазу SDM (см. KB SDM).
76
77---
78
79## Решение
80
81### 1. Единица и носитель
82
831. **Intent card** — immutable payload, привязанный к `workline_id` и опционально к `message_id` (сообщение, после которого зафиксировано решение).
842. Канон — событие **`intent_card_recorded`** в `*.events.ndjson` [0045](0045-agent-chat-persistence-event-log-and-projections.md), `schema_version` в payload.
853. UI — **system card** в timeline активной workline (свёрнута по умолчанию после checkpoint); не отдельная панель.
864. Редактирование — только **компенсирующее событие** (аналог `message_edited`), не rewrite истории.
87
88### 2. Схема payload v1
89
90```json
91{
92 "type": "intent_card_recorded",
93 "schema_version": 1,
94 "workline_id": "wl-…",
95 "message_id": "msg-…",
96 "card": {
97 "outcome": "В scope strip видны все open worklines без скролла всей сессии",
98 "trigger": "При 2+ линиях оператор забывает хвост в parked workline",
99 "chosen_approach": "Проекция open worklines из session meta",
100 "selection_rationale": "New Chat на тему рвёт session graph и head-per-workline (moat 0172); meta сохраняет один composer",
101 "constraints": "Без модалки «создай топик» до первого сообщения [0172 §9]",
102 "validation_plan": "2 worklines → switch → head сохранён → strip показывает обе"
103 },
104 "considered": [
105 {
106 "approach": "New Chat per topic",
107 "rejected_because": "плоский чат, нет workline/head"
108 },
109 {
110 "approach": "Один длинный тред без индекса",
111 "rejected_because": "скролл, та же потеря контекста"
112 }
113 ]
114}
115```
116
117#### Семантика полей
118
119| Поле | Смысл | Не путать с |
120|------|--------|-------------|
121| `outcome` | **Что** должно стать правдой (результат) | «зачем» — это `trigger` |
122| `trigger` | **Боль / ситуация / зачем сейчас** | goal в смысле Al Safwan = outcome |
123| `chosen_approach` | Короткая метка выбранного пути | не заменяет обоснование |
124| `selection_rationale` | **Почему этот путь, а не considered** | обязательна при нетривиальном выборе |
125| `constraints` | Ограничения (ADR, время, «не трогать X») | |
126| `validation_plan` | Как проверим (smoke, test, checkpoint) | Perform SDM |
127| `considered[]` | Отвергнутые варианты + `rejected_because` | tier A, не «потом в tier B» |
128
129**Tier B (опционально, `schema_version` ≥ 2 или nested):** `side_effects[]`, `dependencies[]`, ссылки `kb_path`, `adr_ref`.
130
131### 3. Правила полноты (валидация)
132
133Карточка **неполная** (агент должен дособрать или запросить одну реплику), если:
134
1351. Есть `chosen_approach`, но нет `selection_rationale`.
1362. Нет ни одного элемента в `considered` (кроме явно тривиального «status quo / ничего не менять»).
1373. `outcome` или `trigger` пусты.
138
139Продукт **не блокирует** сохранение черновика; scope strip / export помечает **incomplete**.
140
141### 4. Кто и когда создаёт
142
143| Инициатор | Сценарий |
144|-----------|----------|
145| **Агент** | После steer, предложения spin-off [0172 §11](0172-conversation-first-habitat.md#adr0172-spinoff), fork, смены scope — «зафиксирую intent?» |
146| **Оператор** | Slash / chord «intent capture» на активной workline |
147| **Checkpoint** | Перед export / закрытием workline — prompt «5 полей за 30 сек», если карточки не было |
148
149Согласие: одна короткая реплика («да» / правка одного поля), не модалка на 15 полей.
150
151### 5. UI (целевое)
152
153```text
154┌─ Intent · G2 scope strip ─────────────────────────┐
155│ Trigger: теряю хвост при switch │
156│ Outcome: strip показывает open worklines │
157│ Rejected: New Chat — рвёт session graph │
158│ Chosen: meta-проекция — head per workline │
159│ Check: 2 worklines, switch, head OK │
160│ [edit] [→ KB] [draft ADR] │
161└───────────────────────────────────────────────────┘
162```
163
164- **Perceive (SDM):** collapsed в ленте; active card в scope strip one-liner.
165- **Process:** раскрыть `considered[]`.
166- **Perform:** `validation_plan` → ссылка на verify ladder [0148](0148-agent-execution-environment-verification-ladder-and-native-tooling.md).
167
168Кнопки эскалации:
169
170| Действие | Куда |
171|----------|------|
172| **→ KB** | Scratch / handoff (agent-notes MCP) |
173| **draft ADR** | Шаблон: triggers → Context, considered+chosen → Options/Decision, validation → Consequences; **человек accept** — не автосоздание ADR |
174
175### 6. Materialization для harness
176
177Оркестратор [0166](0166-agent-centric-harness-model-comfort-and-pay-per-token-economics.md) может включать в system one-liner **сжатую** последнюю intent card активной workline (outcome + chosen, ≤ N токенов), не полный dump. Соседние worklines — только через scope strip («2 open»), не все карточки в `messages[]`.
178
179### 7. Сборка ADR из карточек (направление)
180
181```text
182N intent cards в workline / по intent tag
183 → checkpoint: кластер по feature
184 → draft ADR (Context · Decision · Consequences)
185 → оператор: Accept / правка / отклонить
186 → ADR в docs/adr/ + correspondence [0155](0155-documentation-code-correspondence-and-architectural-drift.md)
187```
188
189Intent cards остаются в session export как **provenance**; ADR не дублирует их дословно.
190
191### 8. Decision history (агент) — addendum v1.1
192
193См. unified model §12 (KB `kb-cide-sedm-unified-model-v1`): после исследования агент пишет **`decision_recorded`** — те же поля `card` + `considered[]`, плюс **`findings[]`** (сжатые находки) и **`basis`** (`revision`, `touched_paths`).
194
195| Событие | Кто | Зачем |
196|---------|-----|--------|
197| `intent_card_recorded` | оператор | намерение / выбор пути |
198| `decision_recorded` | агент | след «находки → решение»; не grep снова при возврате |
199| `decision_marked_stale` | система / оператор | код ушёл (другая workline, commit) |
200| `decision_superseded` | любой | замена записи (аналог Superseded в ADR) |
201
202**Cross-workline:** workline A parked, B меняет `touched_paths` из basis A → decisions A → **stale**; при activate A — re-verify, не слепой trust. Materialization: только **active** + one-liner по **stale**.
203
204---
205
206## Отклонённые альтернативы
207
208| Альтернатива | Почему отклонена |
209|--------------|------------------|
210| Только длиннее commit message | Не закрывает alternatives; post-hoc; не в потоке steer |
211| 15 полей Al Safwan в обязательной форме | Record gap показывает: не заполняют; satisficing ломается |
212| Одно поле `selected_alternative` без `considered` | Воспроизводит record gap; не отвечает на N1 |
213| Отдельный ADR на каждую intent card | Bloat; карточка — атом сессии, ADR — кристалл invariant |
214| Хранить только в KB, не в event log | Теряется связь workline ↔ решение ↔ message; ломает L4 [0155](0155-documentation-code-correspondence-and-architectural-drift.md) |
215
216---
217
218## Последствия
219
220- Расширение типов событий [0045](0045-agent-chat-persistence-event-log-and-projections.md) и проекций Intercom feed.
221- Промпты агента / slash: когда предлагать карточку; валидация полноты.
222- Export readable: секция «Decisions» из intent cards workline.
223- Тесты: round-trip event → projection → harness one-liner.
224
225---
226
227## Фазы внедрения
228
229| Фаза | Содержание |
230|------|------------|
231| **P0** | ADR + схема payload v1 (этот документ) |
232| **P1** | `intent_card_recorded` + `decision_recorded` в log + system card в timeline |
233| **P2** | Агент propose + operator approve; scope strip one-liner |
234| **P3** | → KB, draft ADR template, incomplete marker |
235
236**Приоритет:** P1–P2 вместе с scope strip [0172 G2](0172-conversation-first-habitat.md#adr0172-phases) — один смысл «решения на экране».
237
238---
239
240## Открытые вопросы
241
242- Имя slash-команды и `command_id` (кандидат: `/intercom intent record`).
243- Версионирование: одна active card на workline или история карточек (рекомендация: **история** в log, **последняя** в scope strip).
244- Связь с `ClarificationBatch`: карточка после закрытия пакета vs отдельное событие.
245- Локализация UI-лейблов (Trigger/Outcome) vs wire на EN.
246
247---
248
249## Punchline
250
251> **Intent card** — User Story + Decision Record для session graph: **outcome, trigger, considered, chosen+rationale, check** — в event log, не в голове автора. **ADR** собирается из кластера карточек, когда решение стало invariant.
252
View only · write via MCP/CIDE