@elastic.io/mcp 1.0.1-dev10 → 1.0.1-dev11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +37 -19
  2. package/dist/api/client.d.ts.map +1 -1
  3. package/dist/api/client.js +3 -1
  4. package/dist/api/client.js.map +1 -1
  5. package/dist/api/verification.d.ts +6 -0
  6. package/dist/api/verification.d.ts.map +1 -0
  7. package/dist/api/verification.js +71 -0
  8. package/dist/api/verification.js.map +1 -0
  9. package/dist/setup.d.ts.map +1 -1
  10. package/dist/setup.js +25 -6
  11. package/dist/setup.js.map +1 -1
  12. package/dist/tools/definitions.d.ts.map +1 -1
  13. package/dist/tools/definitions.js +34 -2
  14. package/dist/tools/definitions.js.map +1 -1
  15. package/dist/tools/flow-build.d.ts +18 -0
  16. package/dist/tools/flow-build.d.ts.map +1 -0
  17. package/dist/tools/flow-build.js +291 -0
  18. package/dist/tools/flow-build.js.map +1 -0
  19. package/dist/tools/flow-evidence.d.ts +62 -0
  20. package/dist/tools/flow-evidence.d.ts.map +1 -0
  21. package/dist/tools/flow-evidence.js +128 -0
  22. package/dist/tools/flow-evidence.js.map +1 -0
  23. package/dist/tools/flow-state-machine.d.ts +68 -0
  24. package/dist/tools/flow-state-machine.d.ts.map +1 -0
  25. package/dist/tools/flow-state-machine.js +292 -0
  26. package/dist/tools/flow-state-machine.js.map +1 -0
  27. package/dist/tools/handlers/auth.d.ts.map +1 -1
  28. package/dist/tools/handlers/auth.js +10 -144
  29. package/dist/tools/handlers/auth.js.map +1 -1
  30. package/dist/tools/handlers/component.d.ts.map +1 -1
  31. package/dist/tools/handlers/component.js +26 -6
  32. package/dist/tools/handlers/component.js.map +1 -1
  33. package/dist/tools/handlers/data-sample.d.ts.map +1 -1
  34. package/dist/tools/handlers/data-sample.js +36 -5
  35. package/dist/tools/handlers/data-sample.js.map +1 -1
  36. package/dist/tools/handlers/dynamic.d.ts.map +1 -1
  37. package/dist/tools/handlers/dynamic.js +42 -13
  38. package/dist/tools/handlers/dynamic.js.map +1 -1
  39. package/dist/tools/handlers/flow.d.ts.map +1 -1
  40. package/dist/tools/handlers/flow.js +144 -616
  41. package/dist/tools/handlers/flow.js.map +1 -1
  42. package/dist/tools/handlers/log.d.ts.map +1 -1
  43. package/dist/tools/handlers/log.js.map +1 -1
  44. package/dist/tools/handlers/raw.d.ts.map +1 -1
  45. package/dist/tools/handlers/raw.js +3 -0
  46. package/dist/tools/handlers/raw.js.map +1 -1
  47. package/dist/tools/handlers/search.d.ts.map +1 -1
  48. package/dist/tools/handlers/search.js +31 -0
  49. package/dist/tools/handlers/search.js.map +1 -1
  50. package/dist/tools/handlers/session.d.ts.map +1 -1
  51. package/dist/tools/handlers/session.js +7 -1
  52. package/dist/tools/handlers/session.js.map +1 -1
  53. package/dist/tools/handlers.d.ts.map +1 -1
  54. package/dist/tools/handlers.js +7 -2
  55. package/dist/tools/handlers.js.map +1 -1
  56. package/dist/tools/types.d.ts +6 -0
  57. package/dist/tools/types.d.ts.map +1 -1
  58. package/dist/tools/validation.d.ts +16 -1
  59. package/dist/tools/validation.d.ts.map +1 -1
  60. package/dist/tools/validation.js +163 -141
  61. package/dist/tools/validation.js.map +1 -1
  62. package/package.json +4 -2
  63. package/resources/docs/flow-creation-stages.md +195 -0
  64. package/resources/docs/flow-state-machine-audit.md +162 -0
@@ -0,0 +1,195 @@
1
+ # Flow Lifecycle (State Machine)
2
+
3
+ One continuous cycle. After LOGS the flow is RUNNING — any modification request loops back through the modification stages.
4
+
5
+ ```
6
+ INIT → DISCOVERY → SKELETON → METADATA → MAPPERS → PUBLISH_DRAFT → START → RUN_NOW → LOGS → RUNNING
7
+ ↓
8
+ user requests a change ↓
9
+ ↓
10
+ INSPECT → STOP → DISCOVERY(changed) → IMPACT
11
+ ↓
12
+ re-do affected stages (see below)
13
+ ↓
14
+ PUBLISH_DRAFT → START → RUN_NOW → LOGS → RUNNING
15
+ ↓
16
+ ...
17
+ ```
18
+
19
+ ---
20
+
21
+ ## Stage 1: INIT
22
+
23
+ **Trigger:** `create_flow` — creates an empty flow (no graph).
24
+
25
+ **What happens:**
26
+ - Flow is registered in the platform
27
+ - State machine initialized for this flow ID
28
+
29
+ **Gate to next stage:** flow ID exists.
30
+
31
+ ---
32
+
33
+ ## Stage 2: DISCOVERY
34
+
35
+ **Trigger:** `get_component`, `list_credentials`, `list_secrets` for each component used in the flow.
36
+
37
+ **What happens:**
38
+ - Component schemas (actions, triggers, fields, dynamicMetadata flags) are fetched and cached
39
+ - Available credentials and secrets are listed
40
+ - Components requiring auth are flagged
41
+ - Components with `dynamicMetadata: true` are recorded — these will need metadata retrieval later
42
+
43
+ **Gate to next stage:** every `component_id` that will appear in the skeleton must have a corresponding `get_component` call. Every `credentials_id` / `secret_id` must come from `list_credentials` / `list_secrets`.
44
+
45
+ ---
46
+
47
+ ## Stage 3: SKELETON
48
+
49
+ **Trigger:** `update_flow_draft` with nodes + edges but **no mappers** on edges.
50
+
51
+ **What happens:**
52
+ - Draft is saved with the flow structure: which steps exist, how they connect
53
+ - No data mapping yet — edges have no `config.mapper`
54
+ - The system analyzes which steps have `dynamicMetadata: true` and builds a list of pending metadata calls
55
+
56
+ **Gate to next stage:** skeleton must be saved successfully. If any component wasn't discovered in Stage 2, the call is rejected.
57
+
58
+ ---
59
+
60
+ ## Stage 4: METADATA
61
+
62
+ **Trigger:** `init_dynamic_metadata` for each step that has `dynamicMetadata: true`.
63
+
64
+ **What happens:**
65
+ - For each step with dynamic metadata, the actual input/output schema is retrieved from the component using live credentials
66
+ - This gives real field names (not guessed ones) for building mappers
67
+ - Each successful call marks that component:action combo as "metadata retrieved"
68
+
69
+ **Gate to next stage:** all pending metadata combos (identified in Stage 3) must be retrieved. If a step doesn't have `dynamicMetadata: true`, it's skipped automatically.
70
+
71
+ **Skip condition:** if no steps in the skeleton have `dynamicMetadata: true`, this stage is auto-completed.
72
+
73
+ ---
74
+
75
+ ## Stage 5: MAPPERS
76
+
77
+ **Trigger:** `update_flow_draft` again, this time with `config.mapper` on edges.
78
+
79
+ **What happens:**
80
+ - Mappers are built using real field names from Stage 4
81
+ - Mapper values reference upstream steps via `$getPassthrough().step_id.body.fieldName`
82
+ - Mapper keys are the target step's input field names (from metadata)
83
+
84
+ **Gate to next stage:** draft must be saved with mappers. The system rejects the call if:
85
+ - Skeleton wasn't saved first (Stage 3 skipped)
86
+ - Metadata wasn't retrieved for steps that need it (Stage 4 skipped)
87
+
88
+ ---
89
+
90
+ ## Stage 6: PUBLISH DRAFT
91
+
92
+ **Trigger:** `update_flow` (PATCH) — publishes the draft, making it the live flow configuration.
93
+
94
+ **What happens:**
95
+ - Impact analysis is shown (diff between current live flow and the draft)
96
+ - User must confirm with `confirmed: true`
97
+ - Draft becomes the active configuration, draft is deleted
98
+
99
+ **Gate to next stage:** flow must have completed the MAPPERS stage. Cannot publish from INIT, DISCOVERY, SKELETON, or METADATA phases.
100
+
101
+ ---
102
+
103
+ ## Stage 7: START
104
+
105
+ **Trigger:** `start_flow`
106
+
107
+ **What happens:**
108
+ - Pre-start health check runs (credentials valid, required fields set, components accessible)
109
+ - If health check has errors, start is blocked
110
+ - If health check passes, flow begins executing on its cron schedule
111
+
112
+ ---
113
+
114
+ ## Stage 8: RUN NOW
115
+
116
+ **Trigger:** `run_flow_now`
117
+
118
+ **What happens:**
119
+ - Forces an immediate execution of the flow (outside of its cron schedule)
120
+ - Useful to verify the flow works end-to-end before waiting for the next scheduled run
121
+
122
+ **Gate:** flow must be started (Stage 7).
123
+
124
+ ---
125
+
126
+ ## Stage 9: LOGS
127
+
128
+ **Trigger:** `get_logs` for the flow
129
+
130
+ **What happens:**
131
+ - Check execution logs to verify the flow ran successfully
132
+ - Identify errors, warnings, or unexpected behavior in the execution
133
+ - If issues found — diagnose and loop back to the appropriate stage to fix
134
+
135
+ **After this stage:** flow transitions to RUNNING state.
136
+
137
+ ---
138
+
139
+ ## Stage 10: RUNNING
140
+
141
+ Flow is live and executing on schedule. State machine stays here until the user requests a modification.
142
+
143
+ **On modification request** → enter the modification cycle below.
144
+
145
+ ---
146
+
147
+ ## Modification Cycle (from RUNNING)
148
+
149
+ When the user asks to change something in a running flow, the state machine loops back through these stages:
150
+
151
+ ### Step M1: INSPECT
152
+
153
+ **Trigger:** `get_flow` — fetch the current flow configuration.
154
+
155
+ **Gate:** must be called before any modification.
156
+
157
+ ### Step M2: STOP
158
+
159
+ **Trigger:** `stop_flow` — stop the running flow.
160
+
161
+ **Skip condition:** if flow is already inactive.
162
+
163
+ ### Step M3: DISCOVERY (only for changed components)
164
+
165
+ Re-run `get_component`, `list_credentials`, `list_secrets` only for:
166
+ - New components being added
167
+ - Components whose credentials are changing
168
+
169
+ Already-discovered components from the previous cycle are still cached.
170
+
171
+ ### Step M4: IMPACT ANALYSIS
172
+
173
+ **Trigger:** first call to `update_flow` or `update_flow_draft` (without `confirmed: true`).
174
+
175
+ **What happens:**
176
+ - The system compares old vs. new graph and shows a domino-effect impact report
177
+ - Lists: added/removed/changed steps, broken passthrough references, stale data samples
178
+ - Identifies which downstream steps are affected
179
+
180
+ ### Step M5: RE-DO AFFECTED STAGES
181
+
182
+ Based on what changed, repeat only the relevant stages:
183
+
184
+ | What changed | Stages to repeat |
185
+ |---|---|
186
+ | New step added | DISCOVERY → METADATA (if dynamicMetadata) → SKELETON → MAPPERS |
187
+ | Component replaced in step | DISCOVERY → METADATA → MAPPERS |
188
+ | Credentials changed | DISCOVERY (list_credentials) → verify_credentials |
189
+ | Step fields changed | MAPPERS (if output schema affected) + refresh data samples |
190
+ | Step removed | MAPPERS (fix broken passthrough refs) |
191
+ | Mapper changed | refresh data samples for downstream steps |
192
+
193
+ ### Step M6: PUBLISH DRAFT → START → RUN NOW → LOGS → RUNNING
194
+
195
+ Same as stages 6–10. The cycle repeats.
@@ -0,0 +1,162 @@
1
+ # Анализ Flow State Machine и план улучшений
2
+
3
+ Статус: результаты анализа и предложения по реализации.
4
+
5
+ Сейчас машина состояний не гарантирует соблюдение процесса сборки: часть фаз выставляется по факту вызова инструмента, без подтверждения результата. При этом некоторые корректные последовательности блокируются.
6
+
7
+ Проверен текущий код и воспроизведены проблемы в 13 локальных сценариях с mock API и валидаторами. TypeScript-сборка проходит. Эти проверки не являются подтверждением успешного выполнения реального flow на платформе.
8
+
9
+ ## 1. Metadata считается готовой слишком рано
10
+
11
+ `init_dynamic_metadata` сразу отмечает metadata полученной, хотя вернулся только запуск асинхронной операции. Даже последующая ошибка не отменяет эту отметку.
12
+
13
+ Ключ `componentId:action` смешивает разные настройки: metadata JDBC для таблицы A засчитывается и для таблицы B. Результат также не привязан к версии компонента, credentials и конкретному шагу.
14
+
15
+ **Изменение:** сохранять подтверждение только после успешного завершения execution и проверки полученной схемы. Связывать результат с шагом, версией компонента, credentials и конфигурацией. Изменение этих параметров должно делать старое подтверждение недействительным.
16
+
17
+ Код: [handlers/dynamic.ts](../../src/tools/handlers/dynamic.ts), [flow-state-machine.ts](../../src/tools/flow-state-machine.ts).
18
+
19
+ ## 2. Проверка credentials допускает ложный успех
20
+
21
+ Discovery запрещает только credentials с уже известной ошибкой; отсутствие проверки разрешено. Отдельный health check считает отсутствие execution ID и таймаут успехом. Локально воспроизведено принятие `result.data.verified: false` за `OK`.
22
+
23
+ **Изменение:** использовать единый механизм проверки со статусами `UNKNOWN / PENDING / VERIFIED / FAILED`. Публикация должна требовать `VERIFIED` для используемой конфигурации, если компонент требует авторизации. Отсутствие результата и таймаут не должны превращаться в успех.
24
+
25
+ Код: `checkDiscoveryState`, `verifyCredentialForHealthCheck` и `healthCheckFlow` в [validation.ts](../../src/tools/validation.ts); [handlers/auth.ts](../../src/tools/handlers/auth.ts).
26
+
27
+ ## 3. Порядок samples → mappers создаёт зависимость по кругу
28
+
29
+ Требуются samples всех шагов до добавления мапперов, но action часто получает корректный sample только после подготовки входных данных через mapper. При этом `autoConfirmSamples` запускает каждый шаг с `{}`.
30
+
31
+ Существующий sample считается подтверждённым только по наличию ID. Новый sample отмечается подтверждённым ещё до успешного сохранения его привязки в draft. Подтверждения, полученные до регистрации skeleton и списка необходимых samples, не приводят к автоматическому пересчёту фазы.
32
+
33
+ **Изменение:** обрабатывать шаги по связям графа:
34
+
35
+ 1. Получить или проверить выход предыдущего шага.
36
+ 2. Подготовить mapper по схемам source и target.
37
+ 3. Проверить преобразованный вход следующего шага.
38
+ 4. Получить его sample, когда это необходимо.
39
+ 5. Сохранить привязку sample в draft и подтвердить результат.
40
+
41
+ Sample должен соответствовать компоненту, методу, версии и актуальной конфигурации шага. Наличие ID само по себе не подтверждает его пригодность. Выполнение action для получения sample должно быть явной операцией, поскольку оно может изменять данные во внешней системе.
42
+
43
+ Код: `autoConfirmSamples` и `update_flow_draft` в [handlers/flow.ts](../../src/tools/handlers/flow.ts), [handlers/data-sample.ts](../../src/tools/handlers/data-sample.ts).
44
+
45
+ ## 4. Одна общая фаза плохо описывает готовность flow
46
+
47
+ `MAPPERS` выставляется при наличии хотя бы одного маппера. Обязательные мапперы остальных рёбер могут отсутствовать. Обратная проблема: flow, которому мапперы вообще не нужны, застревает перед публикацией.
48
+
49
+ **Изменение:** хранить готовность каждого шага и ребра, включая явное `NOT_REQUIRED`. Готовность к публикации вычислять из всех необходимых условий, а не из наличия одного маппера или истории вызовов инструментов.
50
+
51
+ Код: `update_flow_draft` в [handlers/flow.ts](../../src/tools/handlers/flow.ts), `validatePublish` в [flow-state-machine.ts](../../src/tools/flow-state-machine.ts).
52
+
53
+ ## 5. Восстановление состояния и переходы дают тупики
54
+
55
+ Локально подтверждены следующие случаи:
56
+
57
+ - Опубликованный неактивный flow нельзя перевести в редактирование: draft запрещён в `PUBLISHED`, `stop_flow` также запрещён, а `get_flow` не меняет эту фазу.
58
+ - После переподключения опубликованный неактивный flow определяется как `MAPPERS`, и запуск требует повторной публикации.
59
+ - Отсутствие состояния отключает проверки фаз: валидаторы возвращают пустой список ошибок.
60
+
61
+ Текущее восстановление по наличию мапперов слишком грубое: оно не различает draft и опубликованную конфигурацию и не восстанавливает доказательства проверок. Изоляция MCP-сессий полезна, но сама по себе не обеспечивает восстановление процесса сборки.
62
+
63
+ **Изменение:** получать граф и статус из API, а подтверждения проверок восстанавливать из сохранённых данных либо помечать как `UNKNOWN` для повторной проверки. Неизвестное состояние не должно автоматически разрешать переход. Чтение flow должно обновлять факты, а остановка уже неактивного flow не должна быть обязательной для редактирования.
64
+
65
+ Код: `markInspected`, `validateDraftUpdate`, `validateStart`, `validateStop` в [flow-state-machine.ts](../../src/tools/flow-state-machine.ts).
66
+
67
+ ## 6. Публикация не привязана к проверенной версии draft
68
+
69
+ `validatePublish` проверяет фазу, затем `update_flow` отправляет переданный `body`. Можно проверить один граф, а публиковать изменённый.
70
+
71
+ После публикации снова вызывается `autoConfirmSamples`, который способен создать новый draft. Изменения через raw API обходят проверки процесса сборки.
72
+
73
+ **Изменение:** проверять конкретную ревизию draft, публиковать именно её и читать результат обратно для подтверждения. Подготовку samples завершать до публикации. Все изменения flow через инструменты, включая raw API, должны проходить общий механизм проверок.
74
+
75
+ Код: `update_flow` в [handlers/flow.ts](../../src/tools/handlers/flow.ts), [handlers/raw.ts](../../src/tools/handlers/raw.ts).
76
+
77
+ ## 7. RUNNING не подтверждает успешное выполнение
78
+
79
+ `RUNNING` выставляется после принятия `run_now` или чтения логов — даже пустых. Нет подтверждения, что нужное выполнение завершилось успешно и относится к текущей опубликованной версии.
80
+
81
+ **Изменение:** отдельно хранить факт активности flow и результат конкретного выполнения: `NOT_RUN / PENDING / PASSED / FAILED / NO_DATA`. Чтение логов должно оставаться чтением; успешность устанавливается после анализа результата execution, связанного с опубликованной версией.
82
+
83
+ Код: `run_flow_now` в [handlers/flow.ts](../../src/tools/handlers/flow.ts), [handlers/log.ts](../../src/tools/handlers/log.ts).
84
+
85
+ ## 8. Инструкции противоречат друг другу
86
+
87
+ - Playbook требует создавать пустой flow.
88
+ - Prompt предлагает создавать flow сразу с первым шагом.
89
+ - Описание `create_flow` предполагает граф в payload.
90
+ - Обработчики samples ожидают `flowId` и `stepId`, но этих параметров нет в опубликованных схемах соответствующих инструментов.
91
+
92
+ Агент, следующий разным инструкциям, получает разные последовательности действий.
93
+
94
+ **Изменение:** определить одну каноническую спецификацию процесса и согласовать с ней prompts, tool descriptions, схемы аргументов и серверные проверки. Инструкции должны учитывать уже принятые пользователем решения и разрешённую степень самостоятельности.
95
+
96
+ Источники: [system-instructions.md](system-instructions.md), [flow-building-guide.md](flow-building-guide.md), [flow-creation-stages.md](flow-creation-stages.md), [server.ts](../../src/server.ts), [definitions.ts](../../src/tools/definitions.ts).
97
+
98
+ ## Предлагаемая модель
99
+
100
+ Механизм должен опираться на проверяемые условия готовности конкретного draft.
101
+
102
+ | Что отслеживаем | Основание |
103
+ |---|---|
104
+ | Сборка | Конфигурация, metadata, credentials, samples и мапперы каждого шага |
105
+ | Публикация | Проверенная ревизия совпадает с публикуемой |
106
+ | Активность | Статус, подтверждённый API |
107
+ | Проверка работы | Результат конкретного execution |
108
+
109
+ При изменении `fields`, версии компонента или credentials соответствующие проверки становятся устаревшими. Зависимые samples и мапперы должны перепроверяться. Это относится и к замене компонента или credentials при сохранении прежнего `node.id`: сейчас такая замена может пропустить discovery-проверки.
110
+
111
+ `get_flow` обновляет факты из API. Общая фаза сборки вычисляется по текущим условиям. Валидаторы не должны менять состояние до сохранения: сейчас `validateDraftUpdate` способен перевести flow из `INIT` в `DISCOVERY` ещё до запроса записи.
112
+
113
+ Для агента нужен `get_flow_build_status`, возвращающий:
114
+
115
+ - `revision` — проверяемую версию draft;
116
+ - `blockers` — конкретные невыполненные условия по шагам и рёбрам;
117
+ - `nextActions` — разрешённые операции с необходимыми аргументами;
118
+ - `readyToPublish` — итог проверки готовности.
119
+
120
+ Следующую разрешённую операцию определяет сервер. Получение metadata, polling, проверка результата и запись состояния выполняются одним согласованным процессом. Запуск flow остаётся отдельным действием, соответствующим запросу пользователя.
121
+
122
+ ## Порядок внедрения
123
+
124
+ 1. Устранить ложный успех metadata, credentials и execution; исправить тупики переходов.
125
+ 2. Ввести проверки по шагам и ревизиям; согласовать инструкции и схемы tools.
126
+ 3. Добавить единый сервис сборки, последовательную запись изменений одного flow и восстановление после прерываний.
127
+ 4. Усилить проверку графа. Сейчас локально проходят цикл, дублирующийся node ID и ссылка на несуществующий passthrough. Повторные POST после таймаута также требуют защиты от дублирования.
128
+
129
+ ## Проверенные локальные сценарии
130
+
131
+ | Сценарий | Наблюдаемое поведение |
132
+ |---|---|
133
+ | Flow отсутствует в хранилище состояния | Проверки фаз draft, publish и start возвращают пустой список ошибок |
134
+ | Редактирование опубликованного неактивного flow | Draft и stop одновременно запрещены |
135
+ | Восстановление опубликованного неактивного flow | Фаза `MAPPERS`, start требует повторной публикации |
136
+ | Flow без необходимости в мапперах | Публикация блокируется в `METADATA` |
137
+ | Metadata execution ещё pending | Metadata уже отмечена полученной |
138
+ | Samples подтверждены до регистрации skeleton | Все samples есть, фаза остаётся `METADATA` |
139
+ | Чтение пустых логов после start | Фаза становится `RUNNING` |
140
+ | Замена компонента и credentials при прежнем node ID | Discovery-проверка не сообщает ошибок |
141
+ | Цикл, повтор node ID и несуществующий passthrough | Проверка графа не сообщает ошибок |
142
+ | Credentials ещё не проверялись | Discovery-проверка допускает их использование |
143
+ | Credential verification возвращает вложенное `verified: false` | Health check сообщает `OK` |
144
+ | Выполнена только валидация draft без записи | Фаза меняется на `DISCOVERY` |
145
+ | Проверка схем инструментов samples | `flowId` и `stepId` не объявлены |
146
+
147
+ ## Критерии приёмки
148
+
149
+ Главный инвариант: **flow публикуется только тогда, когда выполнены все необходимые проверки именно его текущей ревизии**.
150
+
151
+ Обязательные сценарии для автоматизированных тестов:
152
+
153
+ - Полный цикл создания и изменения flow.
154
+ - Flow без мапперов, ветвление через Router, несколько шагов одного компонента с разными настройками.
155
+ - Переподключение или перезапуск на каждом этапе сборки.
156
+ - Pending, ошибка и таймаут metadata, credentials и execution.
157
+ - Смена конфигурации, credentials или версии компонента после успешной проверки.
158
+ - Ошибка сохранения привязки sample после создания sample.
159
+ - Изменение графа между проверкой и публикацией.
160
+ - Два одновременных обновления одного flow.
161
+ - Повтор запроса после неоднозначного результата записи или сетевого таймаута.
162
+ - Отсутствие побочных изменений состояния при валидации и чтении логов.