@thinkingai/ae-cli 6.0.38 → 6.0.40

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 (194) hide show
  1. package/README.md +25 -3
  2. package/README.zh.md +25 -3
  3. package/dist/{auth-56Z45UVR.js → auth-GDV3H5I4.js} +18 -8
  4. package/dist/{auth-ENM3FE6L.js → auth-NN55553T.js} +3 -3
  5. package/dist/{capability-2H6PAOA3.js → capability-TPORIKRQ.js} +19 -15
  6. package/dist/{capability-YPOQX6PL.js → capability-VQNC5CF7.js} +19 -15
  7. package/dist/chunk-4NN5IWVN.js +26 -0
  8. package/dist/{chunk-DB4Q3ANU.js → chunk-6A2FUCIS.js} +3 -3
  9. package/dist/{chunk-PVBYJWC2.js → chunk-7KQWSBSL.js} +4 -4
  10. package/dist/{chunk-24BAVOX3.js → chunk-AXDXJTPC.js} +3 -1
  11. package/dist/{chunk-CPVTECJ3.js → chunk-DT6Y3TD7.js} +5 -5
  12. package/dist/{chunk-EGEIXA2Z.js → chunk-DWO43OIB.js} +0 -248
  13. package/dist/{chunk-V6FR6WTW.js → chunk-GJJA4CQZ.js} +34 -2
  14. package/dist/{chunk-RGXCNC4N.js → chunk-GS2P7LFD.js} +50 -17
  15. package/dist/{chunk-LYVNONC4.js → chunk-JHENBQ5B.js} +35 -0
  16. package/dist/{chunk-3P3562ZX.js → chunk-MVDZ7DBQ.js} +5 -5
  17. package/dist/{chunk-LCXU3AAT.js → chunk-NBPKWKRA.js} +2 -2
  18. package/dist/{chunk-HQ2A7ITL.js → chunk-RBNKI5ZW.js} +50 -17
  19. package/dist/{chunk-LHVM35J4.js → chunk-TS6BUGUY.js} +4 -4
  20. package/dist/chunk-TUKQZTMI.js +250 -0
  21. package/dist/{chunk-J7MZHDHQ.js → chunk-VKD5WQKN.js} +5 -5
  22. package/dist/{chunk-3KI3RRXX.js → chunk-VTXHDCBW.js} +3 -3
  23. package/dist/{chunk-KTYR3U6D.js → chunk-YTG6Q75E.js} +10 -6
  24. package/dist/{chunk-IR4ZLVPW.js → chunk-YV52FB5G.js} +25 -3
  25. package/dist/{chunk-E7UXXHO3.js → chunk-Z3OXWCIA.js} +3 -3
  26. package/dist/{cli-token-4SBMXAUK.js → cli-token-GL5MS5FK.js} +4 -4
  27. package/dist/{client-PP5FETMW.js → client-DAIPF7XN.js} +4 -4
  28. package/dist/{community-report-client-KK2QBANO.js → community-report-client-M2RW4MXD.js} +2 -2
  29. package/dist/config-4VZNLBKF.js +489 -0
  30. package/dist/index.js +96 -37
  31. package/dist/memory-RWJW4XFO.js +892 -0
  32. package/dist/memory-VO2ZJCRT.js +892 -0
  33. package/dist/{metadata-JIQ77HFY.js → metadata-YGTHR2XJ.js} +8 -8
  34. package/dist/{metadata-AN3YFZEV.js → metadata-ZRN2GHPN.js} +8 -8
  35. package/dist/{model-JASQVOFD.js → model-CLUIK3K5.js} +7 -5
  36. package/dist/{raw-XJCAT3HX.js → raw-52B4UKO4.js} +8 -7
  37. package/dist/sync-3REDHGY6.js +10259 -0
  38. package/dist/{te-agent-JHUG6DVV.js → te-agent-XNPELAKX.js} +580 -84
  39. package/dist/{te-analysis-ITKTO6JS.js → te-analysis-GJI5FZUL.js} +1152 -13
  40. package/dist/{te-analysis-RAC67YYD.js → te-analysis-N2BRDJZ5.js} +1152 -13
  41. package/dist/{te-community-QOYIYEJI.js → te-community-SQXKE5OO.js} +7 -7
  42. package/dist/{te-community-UFKI6ONP.js → te-community-TYSNU3NQ.js} +7 -7
  43. package/dist/{te-dataops-PZQ5NQLY.js → te-dataops-5TM7WZDI.js} +370 -189
  44. package/dist/{te-dataops-XTWVTJCA.js → te-dataops-OWIADNSM.js} +370 -189
  45. package/dist/{te-engage-NLZUPSBK.js → te-engage-L72HWRGO.js} +716 -118
  46. package/dist/{te-engage-E7F4HTXU.js → te-engage-QWM4GFS7.js} +716 -118
  47. package/dist/{te-kb-E7NSCBRB.js → te-kb-VRMEY3D4.js} +6 -6
  48. package/dist/{te-meta-GBDTMPEL.js → te-meta-53BVXPFI.js} +7 -7
  49. package/dist/{te-meta-ZTLTSHXC.js → te-meta-TOCBPBXI.js} +7 -7
  50. package/dist/{te-system-AH7DMCAQ.js → te-system-XGS5EQIQ.js} +4 -4
  51. package/dist/{te-team-BQ3SKSZV.js → te-team-BZRDV2CM.js} +7 -7
  52. package/dist/{update-DKG6UXEM.js → update-HEDXGOJH.js} +8 -6
  53. package/package.json +5 -2
  54. package/skills/ae-agent/SKILL.md +178 -16
  55. package/skills/ae-agent/references/add-skill.md +22 -10
  56. package/skills/ae-agent/references/edit-skill.md +24 -14
  57. package/skills/ae-agent/references/find-archived-conversations.md +82 -0
  58. package/skills/ae-agent/references/restore-conversation.md +54 -0
  59. package/skills/ae-agent/references/upload-skill.md +24 -14
  60. package/skills/ae-analysis/SKILL.md +1 -1
  61. package/skills/ae-analysis/references/command_index.md +104 -42
  62. package/skills/ae-analysis/references/entity_id_import_options.md +1 -1
  63. package/skills/ae-analysis/references/project_access_detail_get.md +3 -3
  64. package/skills/ae-analysis/references/project_data_power_delete.md +3 -3
  65. package/skills/ae-analysis/references/project_data_power_get.md +3 -3
  66. package/skills/ae-analysis/references/project_data_power_list.md +3 -3
  67. package/skills/ae-analysis/references/project_data_power_upsert.md +3 -3
  68. package/skills/ae-analysis/references/project_entity_create.md +3 -3
  69. package/skills/ae-analysis/references/project_entity_delete.md +3 -3
  70. package/skills/ae-analysis/references/project_entity_event_list.md +3 -3
  71. package/skills/ae-analysis/references/project_entity_get.md +3 -3
  72. package/skills/ae-analysis/references/project_entity_list.md +3 -3
  73. package/skills/ae-analysis/references/project_entity_update.md +3 -3
  74. package/skills/ae-analysis/references/project_function_list.md +3 -3
  75. package/skills/ae-analysis/references/project_info_create.md +25 -0
  76. package/skills/ae-analysis/references/project_info_delete.md +24 -0
  77. package/skills/ae-analysis/references/project_info_get.md +3 -3
  78. package/skills/ae-analysis/references/project_info_list.md +3 -3
  79. package/skills/ae-analysis/references/project_info_update.md +3 -3
  80. package/skills/ae-analysis/references/project_mark_time_create.md +3 -3
  81. package/skills/ae-analysis/references/project_mark_time_delete.md +3 -3
  82. package/skills/ae-analysis/references/project_mark_time_list.md +3 -3
  83. package/skills/ae-analysis/references/project_mark_time_update.md +3 -3
  84. package/skills/ae-analysis/references/project_member_add.md +3 -3
  85. package/skills/ae-analysis/references/project_member_batch_update.md +3 -3
  86. package/skills/ae-analysis/references/project_member_candidate_list.md +3 -3
  87. package/skills/ae-analysis/references/project_member_handover_export.md +3 -3
  88. package/skills/ae-analysis/references/project_member_handover_run.md +3 -3
  89. package/skills/ae-analysis/references/project_member_import.md +3 -3
  90. package/skills/ae-analysis/references/project_member_list.md +3 -3
  91. package/skills/ae-analysis/references/project_member_receiver_list.md +3 -3
  92. package/skills/ae-analysis/references/project_member_remove.md +3 -3
  93. package/skills/ae-analysis/references/project_member_update.md +3 -3
  94. package/skills/ae-analysis/references/project_owner_update.md +3 -3
  95. package/skills/ae-analysis/references/project_permission_binding_list.md +3 -3
  96. package/skills/ae-analysis/references/project_receive_status_update.md +3 -3
  97. package/skills/ae-analysis/references/project_role_delete.md +3 -3
  98. package/skills/ae-analysis/references/project_role_function_list.md +3 -3
  99. package/skills/ae-analysis/references/project_role_get.md +3 -3
  100. package/skills/ae-analysis/references/project_role_list.md +3 -3
  101. package/skills/ae-analysis/references/project_role_upsert.md +3 -3
  102. package/skills/ae-analysis/references/project_role_user_list.md +3 -3
  103. package/skills/ae-analysis/references/project_space_list.md +1 -1
  104. package/skills/ae-analysis/references/project_timezone_get.md +3 -3
  105. package/skills/ae-analysis/references/project_timezone_overview.md +3 -3
  106. package/skills/ae-analysis/references/project_timezone_update.md +3 -3
  107. package/skills/ae-analysis/references/project_user_id_items_update.md +3 -3
  108. package/skills/ae-analysis/references/system_admin_function_list.md +22 -0
  109. package/skills/ae-analysis/references/system_admin_function_update.md +26 -0
  110. package/skills/ae-analysis/references/system_admin_list.md +21 -0
  111. package/skills/ae-analysis/references/system_admin_remove.md +25 -0
  112. package/skills/ae-analysis/references/system_admin_upsert.md +25 -0
  113. package/skills/ae-analysis/references/system_function_list.md +21 -0
  114. package/skills/ae-analysis/references/system_member_add.md +25 -0
  115. package/skills/ae-analysis/references/system_member_candidate_list.md +22 -0
  116. package/skills/ae-analysis/references/system_member_delete.md +25 -0
  117. package/skills/ae-analysis/references/system_member_list.md +24 -0
  118. package/skills/ae-analysis/references/system_member_mfa_unbind.md +25 -0
  119. package/skills/ae-analysis/references/system_member_password_reset.md +32 -0
  120. package/skills/ae-analysis/references/system_member_project_batch_update.md +27 -0
  121. package/skills/ae-analysis/references/system_member_status_update.md +26 -0
  122. package/skills/ae-analysis/references/system_member_update.md +23 -0
  123. package/skills/ae-analysis/references/system_mfa_get.md +21 -0
  124. package/skills/ae-analysis/references/system_mfa_update.md +25 -0
  125. package/skills/ae-analysis/references/system_node_monitor_list.md +24 -0
  126. package/skills/ae-analysis/references/system_oauth2_update.md +22 -0
  127. package/skills/ae-analysis/references/system_ops_alert_contact_delete.md +25 -0
  128. package/skills/ae-analysis/references/system_ops_alert_contact_list.md +23 -0
  129. package/skills/ae-analysis/references/system_ops_alert_contact_test.md +29 -0
  130. package/skills/ae-analysis/references/system_ops_alert_contact_upsert.md +39 -0
  131. package/skills/ae-analysis/references/system_preference_get.md +21 -0
  132. package/skills/ae-analysis/references/system_preference_update.md +22 -0
  133. package/skills/ae-analysis/references/system_project_usage_list.md +28 -0
  134. package/skills/ae-analysis/references/system_query_alert_rule_list.md +21 -0
  135. package/skills/ae-analysis/references/system_query_alert_rule_update.md +26 -0
  136. package/skills/ae-analysis/references/system_query_monitor_overview.md +26 -0
  137. package/skills/ae-analysis/references/system_query_task_cancel.md +25 -0
  138. package/skills/ae-analysis/references/system_query_task_export.md +49 -0
  139. package/skills/ae-analysis/references/system_query_task_get.md +23 -0
  140. package/skills/ae-analysis/references/system_query_task_list.md +35 -0
  141. package/skills/ae-analysis/references/system_query_task_options.md +27 -0
  142. package/skills/ae-analysis/references/system_receiver_address_delete.md +26 -0
  143. package/skills/ae-analysis/references/system_receiver_address_overview.md +21 -0
  144. package/skills/ae-analysis/references/system_receiver_address_project_list.md +21 -0
  145. package/skills/ae-analysis/references/system_receiver_address_promote.md +24 -0
  146. package/skills/ae-analysis/references/system_receiver_address_upsert.md +27 -0
  147. package/skills/ae-analysis/references/system_receiver_detection_get.md +22 -0
  148. package/skills/ae-analysis/references/system_receiver_detection_run.md +22 -0
  149. package/skills/ae-analysis/references/system_receiver_detection_update.md +25 -0
  150. package/skills/ae-analysis/references/system_role_delete.md +26 -0
  151. package/skills/ae-analysis/references/system_role_function_list.md +22 -0
  152. package/skills/ae-analysis/references/system_role_get.md +22 -0
  153. package/skills/ae-analysis/references/system_role_list.md +24 -0
  154. package/skills/ae-analysis/references/system_role_upsert.md +27 -0
  155. package/skills/ae-analysis/references/system_role_user_list.md +22 -0
  156. package/skills/ae-analysis/references/system_seat_list.md +25 -0
  157. package/skills/ae-analysis/references/system_seat_update.md +26 -0
  158. package/skills/ae-analysis/references/system_smtp_delete.md +24 -0
  159. package/skills/ae-analysis/references/system_smtp_get.md +21 -0
  160. package/skills/ae-analysis/references/system_smtp_test.md +22 -0
  161. package/skills/ae-analysis/references/system_smtp_upsert.md +31 -0
  162. package/skills/ae-analysis/references/system_third_party_login_disable.md +25 -0
  163. package/skills/ae-analysis/references/system_third_party_login_list.md +21 -0
  164. package/skills/ae-analysis/references/system_third_party_login_upsert.md +33 -0
  165. package/skills/ae-analysis/references/system_usage_overview.md +21 -0
  166. package/skills/ae-analysis/references/system_usage_trend_export.md +44 -0
  167. package/skills/ae-analysis/references/system_usage_trend_query.md +28 -0
  168. package/skills/ae-dataops/SKILL.md +1 -1
  169. package/skills/ae-dataops/references/dataops-flow-create.md +51 -16
  170. package/skills/ae-engage/SKILL.md +67 -27
  171. package/skills/ae-engage/references/activity-activity.md +3 -0
  172. package/skills/ae-engage/references/activity-approval.md +12 -4
  173. package/skills/ae-engage/references/activity-data-detail.md +61 -0
  174. package/skills/ae-engage/references/activity-task.md +21 -6
  175. package/skills/ae-engage/references/activity-topic.md +31 -13
  176. package/skills/ae-engage/references/add-channel.md +170 -41
  177. package/skills/ae-engage/references/build-task-save-guide.md +66 -29
  178. package/skills/ae-engage/references/channel-update-config.md +3 -2
  179. package/skills/ae-engage/references/common-metric.md +88 -115
  180. package/skills/ae-engage/references/flow-detail.md +13 -0
  181. package/skills/ae-engage/references/preset-event.md +14 -32
  182. package/skills/ae-engage/references/save-flow.md +141 -64
  183. package/skills/ae-engage/references/save-task.md +231 -58
  184. package/skills/ae-engage/references/scene-config-metric.md +3 -0
  185. package/skills/ae-engage/references/scene-preset-metric.md +8 -37
  186. package/skills/ae-engage/references/scene-strategy-audience.md +56 -643
  187. package/skills/ae-engage/references/scene-strategy.md +6 -6
  188. package/skills/ae-engage/references/task-detail.md +10 -0
  189. package/skills/ae-engage/references/task-submit-approval.md +45 -0
  190. package/skills/ae-engage/references/validate-flow-node-config.md +1 -1
  191. package/skills/ae-generate-tracking-code/SKILL.md +2 -2
  192. package/skills/ae-metadata/SKILL.md +1 -1
  193. package/dist/config-BSSALXEN.js +0 -128
  194. package/dist/sync-QFP4XFN3.js +0 -485
@@ -10,6 +10,19 @@ Mapped command: `ae-cli engage-flow flow get`
10
10
  The flow detail is under `data.flow`. Every response key is snake_case, for example
11
11
  `data.flow.mapping_status`, `data.flow.version_type`, and `data.flow.node_list[].type`.
12
12
 
13
+ For custom-audience nodes, `node_list[].config` remains a JSON string. Parse it and read
14
+ `targetDefinitionRequest`, `definitionStatus`, and optional
15
+ `definitionUnavailableReason`. Branch audiences use the same fields inside
16
+ `branchList[]`. Stored execution QP is hidden. Reuse `targetDefinitionRequest` when
17
+ building the next flow save request.
18
+
19
+ Top-level `completion_indicators` and `current_flow_completion_indicators` are exposed
20
+ as arrays. Each indicator uses semantic `event_definition`; stored `event` execution
21
+ QP is removed. Check `completion_indicators_definition_status` and
22
+ `current_flow_completion_indicators_definition_status` before reusing them. A
23
+ non-`AVAILABLE` status may also include the corresponding
24
+ `*_definition_unavailable_reason`.
25
+
13
26
  ## Flags
14
27
 
15
28
  | Flag | Type | Required | Description |
@@ -1,42 +1,24 @@
1
- # engage-setting preset-event
1
+ # Preset event semantic definitions
2
2
 
3
- > Capability ids: `engage-setting.preset-event.{list,update}` · Domain: `engage`.
4
-
5
- ## Commands
3
+ Project preset add/active/recharge events use the same semantic event model as trigger events.
6
4
 
7
5
  ```bash
8
- # Query the project preset-event config
9
6
  ae-cli engage-setting preset-event list --project-id <project_id>
10
7
 
11
- # Update the project preset-event config
12
- ae-cli engage-setting preset-event update --project-id <project_id> [--add-event-desc <qp>] [--active-event-desc <qp>] [--recharge-event-desc <qp>]
8
+ ae-cli engage-setting preset-event update --project-id <project_id> \
9
+ --add-event-definition '{"type":"event","event":"register","aggregation":"count","operator":"gte","value":1}' \
10
+ --active-event-definition '{"type":"event","event":"login","aggregation":"count","operator":"gte","value":1}' \
11
+ --recharge-event-definition '{"type":"event","event":"purchase","aggregation":"sum","property":"amount","operator":"gt","value":0}'
13
12
  ```
14
13
 
15
- ## Parameters
16
-
17
- ### list
18
-
19
- | Parameter | Required | Description |
20
- |---|---|---|
21
- | `--project-id` / `-p` | Yes | Numeric project ID. |
22
-
23
- ### update
24
-
25
- | Parameter | Required | Description |
26
- |---|---|---|
27
- | `--project-id` / `-p` | Yes | Numeric project ID. |
28
- | `--add-event-desc` | No | Add-event qp definition. |
29
- | `--active-event-desc` | No | Active-event qp definition. |
30
- | `--recharge-event-desc` | No | Recharge-success-event qp definition. |
31
-
32
- At least one `*-event-desc` must be provided for `update`.
33
-
34
- ## Output
14
+ At least one definition is required for update. Event filters use semantic `field`, `operator`, `values`, and `and`/`or`; Hermes resolves project metadata and compiles the stored event object.
15
+ `field` accepts a technical-name string or `{"name":"...","type":"event_property"}`. Unknown
16
+ semantic fields, unsupported relations/operators, and invalid time ranges are rejected.
35
17
 
36
- - `list`: `data.add_event_desc`, `data.active_event_desc`, `data.recharge_event_desc` (each may be `null`).
37
- - `update`: `data.success` — whether the config was updated.
18
+ List hides the stored event QP and returns each semantic field plus its conversion status:
38
19
 
39
- ## Decision Rules
20
+ - `add_event_definition`
21
+ - `active_event_definition`
22
+ - `recharge_event_definition`
40
23
 
41
- - Use these commands when the user asks to query or configure preset events for the analysis workbench.
42
- - `update` replaces the provided desc fields; omitting a field clears it. Before clearing a field that is in use, the backend rejects the update if metrics still depend on it.
24
+ UI-saved preset events are often incomplete event selections. List fills write-path defaults (`operator=eq`, `value=1`) so these stay `AVAILABLE`. If conversion still fails for other reasons, status is `UNAVAILABLE` with an unavailable-reason field. Do not reconstruct definitions from raw internal QP codes.
@@ -33,7 +33,7 @@ You still organize user requirements into an intermediate intent first, then map
33
33
  ## 2. Workflow
34
34
 
35
35
  1. Identify the flow intent from the user input and produce a unified intent JSON.
36
- 2. Build a semantic condition request from `ae-analysis/references/user_cluster_models.md`, create the audience directly with `analysis user-cluster create`, and prefer its `cluster_name`/`clusterKey`. When node schema requires QP-derived fields (`targetClusterQp`, `triggerRule`, etc.), call `ae-cli engage-setting query cluster-qp-skill --project-id <projectId>` first; never assemble raw QP manually.
36
+ 2. Build a semantic condition request from `ae-analysis/references/user_cluster_models.md`. Use it directly as `targetDefinitionRequest` for custom-audience node configs and branches. Create a named Analysis cluster only when the flow intentionally references an existing reusable cluster.
37
37
  3. Run `ae-cli engage-setting channel list --project-id <projectId>` to get the available channels and match real `channelId` values for touchpoint nodes. For `webhook_push`, also run `ae-cli engage-setting channel get` and use `data.item.config.params_list` to build request field `contentList` (camelCase; snake_case aliases are normalized during validate).
38
38
  4. Query `ae-cli engage-flow node-config schema --project-id <project_id> --node-type <type>` before constructing each non-trivial node config, then run `ae-cli engage-flow node-config validate --project-id <project_id> --node-type <type> --operation-mode save_flow --config '<config-json-string>'` before placing the config into `nodes` or `nodeConfigs`.
39
39
  5. Map the intent JSON to `nodes` and `edges` (compact form, see §7 / §8).
@@ -176,7 +176,15 @@ ae-cli analysis user-cluster create --project-id <projectId> --cluster-name <con
176
176
  ae-cli analysis user-cluster get --project-id <projectId> --cluster-names '["<condition_cluster_name>"]'
177
177
  ```
178
178
 
179
- Prefer the created cluster reference. Only when the node schema requires `targetClusterQp` or `triggerRule.events`, copy the corresponding server-authored fields returned by `user-cluster get`.
179
+ Prefer the created cluster reference for an existing-cluster audience. For a custom audience, pass the semantic definition as `targetDefinitionRequest`; do not copy or construct stored execution QP.
180
+ Use only the documented semantic fields. Unknown fields are rejected, and property `field` values
181
+ may be technical-name strings or `{name,type}` references.
182
+
183
+ Custom flow audiences support `behavior_sequence`. When `flow get` returns relation-preserving
184
+ top-level `compound` nodes, retain them unchanged in subsequent saves; they preserve distinct
185
+ member-group, event-group, and outer relations.
186
+ For the second sequence step, omit `relative_to_first` or set it to `false`; use `true` only
187
+ from the third step onward when its window must be measured from step 1.
180
188
 
181
189
  ### 5.2 Project Channels
182
190
 
@@ -221,8 +229,8 @@ There must be exactly one entry node.
221
229
 
222
230
  | Semantic type | Target field |
223
231
  |---|---|
224
- | Audience segmentation / feature judgment / feature split branch | `targetClusterQp` |
225
- | Event trigger / behavioral judgment / behavioral split branch | `triggerRule[].events[]` |
232
+ | Audience segmentation / feature judgment / feature split branch | `targetDefinitionRequest` |
233
+ | Event trigger / behavioral judgment / behavioral split branch | `triggerDefinition.rules[].events[]` |
226
234
 
227
235
  ### 6.4 Touchpoint Node Mapping
228
236
 
@@ -237,8 +245,14 @@ Inside action nodes: `channel_name` → real `channelId`; `content` → `content
237
245
  1. `node.id` must be unique within the request.
238
246
  2. Any `branchId` later referenced by `edge.sourceBranchId` must be declared in that node's `config` first.
239
247
  3. Every path must eventually end at `exit_flow`.
240
- 4. `config` may be a JSON object or a JSON string. (`targetClusterQp` inside it is usually a `JSON.stringify`'d string — see §9.)
241
- 5. The backend normalizes some compatible input forms before validation: leading apostrophes on field names are stripped, property names are matched case-insensitively when unambiguous, `enableChannelTouchLimits` booleans become `1`/`0`, `targetClusterQp` relation strings `"0"`/`"1"` become numeric values inside the JSON string, and `clusterPredictCount: null` becomes `0`.
248
+ 4. `config` may be a JSON object or a JSON string. `targetDefinitionRequest` itself is a JSON object.
249
+ 5. Hermes compiles `targetDefinitionRequest` and Flow-specific `triggerDefinition` fields (including branch definitions) on `nodes[]`, `nodeConfigs[]`, and `slotAnswer.nodeConfig.config` before legacy node validation. `node-config validate` uses the same compile path. Other compatible input normalization remains unchanged.
250
+ 6. Never send `targetClusterQp`; it is a server-authored execution field. Every `event` and
251
+ `behavior_sequence` inside `targetDefinitionRequest` must include its own `time_range`.
252
+ Entry-node `startDate` / `endDate` values do not provide an audience-event time range.
253
+ 7. Audience fields must resolve through the current Flow editor metadata scope. If Hermes
254
+ rejects a field, choose another property returned for the same project, timezone, and user
255
+ entity instead of constructing persisted metadata manually.
242
256
 
243
257
  ### 7.2 Common Node Types
244
258
 
@@ -254,36 +268,36 @@ Before writing any config below, call `engage-flow node-config schema` for the e
254
268
  { "targetUserType": 2, "triggerTime": "<YYYY-MM-DD HH:mm>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "targetClusterName": "<existing clusterName>" }
255
269
  ```
256
270
 
257
- For custom users, use `targetUserType=1` and fill `targetClusterQp` with the QP JSON string returned by the cluster QP workflow. For existing clusters (`targetUserType=2`), fill `targetClusterName` from a real current-project cluster list queried with the flow `tzOffset`; do not fill `targetClusterQp`. `clusterPredictCount` defaults to `0` and `clusterPredictTime` defaults to `""` when omitted.
271
+ For custom users, use `targetUserType=1` and fill `targetDefinitionRequest` with the Analysis-compatible semantic definition. For existing clusters (`targetUserType=2`), fill `targetClusterName` from a real current-project cluster list queried with the flow `tzOffset`; do not fill `targetDefinitionRequest`. `clusterPredictCount` defaults to `0` and `clusterPredictTime` defaults to `""` when omitted.
258
272
 
259
273
  #### `repeat_trigger`
260
274
 
261
275
  ```json
262
- { "targetUserType": 1, "startDate": "<YYYY-MM-DD>", "endDate": "<YYYY-MM-DD>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "crontab": "0 00 09 * * ?", "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterName": null, "targetClusterQp": "<JSON.stringify(qp)>" }
276
+ { "targetUserType": 1, "startDate": "<YYYY-MM-DD>", "endDate": "<YYYY-MM-DD>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "crontab": "0 00 09 * * ?", "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterName": null, "targetDefinitionRequest": { "type": "condition", "conditions": { ... } } }
263
277
  ```
264
278
 
265
- `entry.segment` → `targetClusterQp`; `entry.schedule` → `crontab` (common default `0 00 09 * * ?`). `clusterPredictCount` defaults to `0` and `clusterPredictTime` defaults to `""` when omitted. For existing clusters (`targetUserType=2`), fill `targetClusterName` from a real current-project cluster list queried with the flow `tzOffset`; do not fill `targetClusterQp`.
279
+ `entry.segment` → `targetDefinitionRequest`; `entry.schedule` → `crontab` (common default `0 00 09 * * ?`). `clusterPredictCount` defaults to `0` and `clusterPredictTime` defaults to `""` when omitted. For existing clusters (`targetUserType=2`), fill `targetClusterName` from a real current-project cluster list queried with the flow `tzOffset`; do not fill `targetDefinitionRequest`.
266
280
 
267
281
  #### `event_trigger`
268
282
 
269
283
  ```json
270
- { "triggerType": 3, "targetUserType": 1, "startDate": "<YYYY-MM-DD HH:mm>", "endDate": "<YYYY-MM-DD HH:mm>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "triggerRule": [ { "periodStart": "<startDate>", "periodEnd": "<endDate>", "periodTimeSymbol": "TS02", "eventTriggerType": 0, "events": [] } ], "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetClusterQp": "<JSON.stringify(qp) or null>" }
284
+ { "triggerType": 3, "targetUserType": 1, "startDate": "<YYYY-MM-DD HH:mm>", "endDate": "<YYYY-MM-DD HH:mm>", "flowEndDate": "<YYYY-MM-DD HH:mm>", "triggerDefinition": { "rules": [ { "periodStart": "<startDate>", "periodEnd": "<endDate>", "periodTimeSymbol": "TS02", "eventTriggerType": 0, "events": [] } ] }, "entryControlLimits": { "enableMultEntry": false, "disableConcurrentEntry": false }, "targetDefinitionRequest": { "type": "condition", "conditions": { ... } } }
271
285
  ```
272
286
 
273
- `entry.trigger_event` → `triggerRule[0].events`; generate `targetClusterQp` only when `entry.segment` exists. `triggerType` supports `3`, `4`, and `5`; `targetUserType=2` existing cluster is not supported for `event_trigger`; use `1` custom or `3` all users. For non-branch trigger rules, use `periodStart` / `periodEnd` / `periodTimeSymbol`. `realtime`, `clusterRefresh`, `clusterRefreshTime`, `clusterPredictTime`, and `triggerRule[].zoneoffset` can be omitted and are defaulted by the backend.
287
+ `entry.trigger_event` → `triggerDefinition.rules[0].events`; add `targetDefinitionRequest` only when `entry.segment` exists. `triggerType` supports `3`, `4`, and `5`; `targetUserType=2` existing cluster is not supported for `event_trigger`; use `1` custom or `3` all users. For non-branch trigger rules, use `periodStart` / `periodEnd` / `periodTimeSymbol`. `realtime`, `clusterRefresh`, `clusterRefreshTime`, `clusterPredictTime`, and rule `zoneoffset` can be omitted and are defaulted by the backend.
274
288
 
275
289
  #### `event_split_flow`
276
290
 
277
291
  ```json
278
- { "splitFlowType": 1, "branchList": [ { "branchId": "<branchId>", "branchName": "<label>", "branchType": 1, "targetClusterType": 3, "triggerRule": [ { "delayTimeSymbol": "<minute|hour|day>", "delayTime": "<number>", "eventTriggerType": "<0|-1|1|2>", "events": [] } ] } ] }
292
+ { "splitFlowType": 1, "branchList": [ { "branchId": "<branchId>", "branchName": "<label>", "branchType": 1, "targetClusterType": 3, "triggerDefinition": { "rules": [ { "delayTimeSymbol": "<minute|hour|day>", "delayTime": "<number>", "eventTriggerType": "<0|-1|1|2>", "events": [] } ] } } ] }
279
293
  ```
280
294
 
281
- `time_limit` → `delayTimeSymbol` + `delayTime`; `0` = happened, `-1` = not happened. For `branchType=1`, fill `targetClusterType`; use `3` for all users. If `targetClusterType` is not `3`, fill `clusterKey`. `occasionKeys` is optional, but each item must contain at least four colon-separated parts. Fallback branch keeps only `{ "branchId": "<branchId>", "branchType": 2 }` and must omit `triggerRule`.
295
+ `time_limit` → `delayTimeSymbol` + `delayTime`; `0` = happened, `-1` = not happened. For `branchType=1`, fill `targetClusterType`; use `3` for all users. If `targetClusterType` is not `3`, fill `clusterKey`. `occasionKeys` is optional, but each item must contain at least four colon-separated parts. Fallback branch keeps only `{ "branchId": "<branchId>", "branchType": 2 }` and must omit `triggerDefinition`.
282
296
 
283
297
  #### `feature_split_flow`
284
298
 
285
299
  ```json
286
- { "splitFlowType": 1, "branchList": [ { "branchId": "<branchId>", "branchName": "<label>", "branchType": 1, "realtime": 0, "clusterRefresh": 12, "clusterPredictCount": null, "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>", "targetClusterQp": "<JSON.stringify(qp)>" } ] }
300
+ { "splitFlowType": 1, "branchList": [ { "branchId": "<branchId>", "branchName": "<label>", "branchType": 1, "realtime": 0, "clusterRefresh": 12, "clusterPredictCount": null, "clusterPredictTime": "<YYYY-MM-DD HH:mm:ss>", "targetDefinitionRequest": { "type": "condition", "conditions": { ... } } } ] }
287
301
  ```
288
302
 
289
303
  Fallback branch keeps only `branchId` + `branchType: 2`.
@@ -297,7 +311,7 @@ Fallback branch keeps only `branchId` + `branchType: 2`.
297
311
  #### `event_judge`
298
312
 
299
313
  ```json
300
- { "transferType": 1, "meetBranchId": "<meetBranchId>", "notMeetBranchId": "<notMeetBranchId>", "triggerRule": [ { "periodStart": "<YYYY-MM-DD HH:mm>", "periodEnd": "<YYYY-MM-DD HH:mm>", "periodTimeSymbol": "TS02", "eventTriggerType": 0, "events": [] } ] }
314
+ { "transferType": 1, "meetBranchId": "<meetBranchId>", "notMeetBranchId": "<notMeetBranchId>", "triggerDefinition": { "rules": [ { "periodStart": "<YYYY-MM-DD HH:mm>", "periodEnd": "<YYYY-MM-DD HH:mm>", "periodTimeSymbol": "TS02", "eventTriggerType": 0, "events": [] } ] } }
301
315
  ```
302
316
 
303
317
  `event_judge` is a non-branch flow task. Use `periodStart`, `periodEnd`, and `periodTimeSymbol` in the A segment; use `delayTime` / `delayTimeSymbol` only for a B segment when the schema/example requires it. `eventTriggerType` supports `0`, `1`, and `2`.
@@ -305,7 +319,7 @@ Fallback branch keeps only `branchId` + `branchType: 2`.
305
319
  #### `feature_judge`
306
320
 
307
321
  ```json
308
- { "transferType": 1, "meetBranchId": "<meetBranchId>", "notMeetBranchId": "<notMeetBranchId>", "clusterPredictCount": null, "clusterPredictTime": "", "targetClusterQp": "<JSON.stringify(qp)>" }
322
+ { "transferType": 1, "meetBranchId": "<meetBranchId>", "notMeetBranchId": "<notMeetBranchId>", "clusterPredictCount": null, "clusterPredictTime": "", "targetDefinitionRequest": { "type": "condition", "conditions": { ... } } }
309
323
  ```
310
324
 
311
325
  #### `message_push` / `webhook_push`
@@ -373,63 +387,128 @@ Minimum usable `config`: `{}`.
373
387
 
374
388
  ---
375
389
 
376
- ## 9. QP Validation Rules (high-frequency pitfalls)
390
+ ## 9. Semantic trigger-event definitions
377
391
 
378
- When a node config carries a QP (`targetClusterQp`, `triggerRule[].events[]`, etc.), the v2 backend validates it strictly:
392
+ Use `triggerDefinition` instead of `triggerRule`. Flow uses the same Analysis semantic event fields
393
+ as Task, but it does **not** use the Task trigger envelope contract. Select the Flow envelope from
394
+ the matrix below and let Hermes compile and validate the persisted `triggerRule`.
379
395
 
380
- 1. **`relation` must be integer `0` or `1`** — not the string `"0"`/`"1"`. Applies to `totalCFilter.relation`, `eventCondition.relation`, `filts[].relation`. Error: `invalid_qp_relation: QP relation must be number 0 or 1`.
381
- 2. **`userCondition` leaves must include `columnType` and `columnDesc`** — `columnName`/`selectType`/`tableType`/`calcuSymbol`/`ftv` alone is not enough. Error: `invalid_qp_leaf: QP property leaf must contain columnType/columnDesc`. (Even legacy stored QPs that omit these now fail.)
382
- 3. **`taPropQuota` must include `quotaDesc`, `quota`, `analysisParams`** — giving only `analysis`/`analysisDesc` fails with `required_by_minimal_valid`. Minimal passing shape: `{ "analysis": ..., "analysisDesc": ..., "quota": "", "quotaDesc": "", "analysisParams": "" }`. Applies to both `triggerRule.events[].taPropQuota` and the entry node's `eventCondition.taPropQuota`.
396
+ | Flow context | Allowed A-rule `eventTriggerType` |
397
+ | --- | --- |
398
+ | `event_trigger` | `0`, `1`, `2` |
399
+ | `event_judge` | `0`, `1`, `2` |
400
+ | non-fallback `event_split_flow` branch | `-1`, `0`, `1`, `2` |
383
401
 
384
- `targetClusterQp` is usually a `JSON.stringify`'d string, e.g. `{ "targetClusterQp": "{\"totalCFilter\":{\"relation\":1,\"filts\":[]}}" }`.
402
+ `eventTriggerType=3` is the Task client-channel EVERY mode and is not valid for Flow. A second B
403
+ rule, when present, is always an accumulated (`0`) aggregate rule. It must not contain
404
+ `blackList`, `relationProps`, rule-level window fields, or sequence-step fields.
385
405
 
386
- ### 9.1 Operator codes (`uceCalcuSymbol` / `calcuSymbol`)
406
+ ### 9.1 Accumulated or not-happened: `0` / `-1`
387
407
 
388
- Condition leaves use string operator codes, not literal operators:
408
+ Use aggregate semantic events. Flow aggregate triggers support `count` and `sum`, with `eq`, `lt`,
409
+ `lte`, `gt`, or `gte`; `sum` requires `property`. `-1` means “did not happen” and is valid only
410
+ for a non-fallback `event_split_flow` branch; it cannot have a B rule.
389
411
 
390
- | Code | Meaning | Value type |
391
- |---|---|---|
392
- | `C00` | equals | all |
393
- | `C01` | not equals | all |
394
- | `C02` / `C020` | less than / less than or equal | number |
395
- | `C03` / `C030` | greater than / greater than or equal | number |
396
- | `C04` / `C05` | has value / no value | all |
397
- | `C06` / `C060` | range / date range | number / date |
398
- | `C07` / `C08` | contains / does not contain | string |
399
- | `C09` / `C10` | true / false | bool |
400
- | `C11` / `C12` | regex match / not match | string |
412
+ ```json
413
+ {
414
+ "triggerDefinition": {
415
+ "rules": [
416
+ {
417
+ "eventTriggerType": 0,
418
+ "events": [
419
+ {
420
+ "type": "event",
421
+ "event": "login",
422
+ "aggregation": "count",
423
+ "operator": "gte",
424
+ "value": 1
425
+ }
426
+ ]
427
+ }
428
+ ]
429
+ }
430
+ }
431
+ ```
401
432
 
402
- ### 9.2 Event-count condition (`A200`) `invalid_preset_count_expression`
433
+ Do not include `blackList`, `relationProps`, `windowGap`, `windowGapTimeUnit`,
434
+ `eventTriggerCaliberType`, `hasDone`, or `hasDistanceStart` in this envelope.
403
435
 
404
- For an event condition that counts occurrences with an **empty `taPropQuota`** (analysis `A200`, the default "count" case), the backend treats it as a *preset count* and is strict:
436
+ ### 9.2 Continuous completion: `1`
405
437
 
406
- - `uceCalcuSymbol` **must be `C030`** (greater-than-or-equal), and
407
- - `num` **must be `"1"`** (string).
438
+ Use exactly one count event with `operator=eq`. `blackList` accepts semantic events that Hermes
439
+ compiles as non-aggregate selectors. `relationProps` and the rule-level window are optional; when
440
+ using a window, provide both fields.
408
441
 
409
- Any other operator/number with an empty quota fails with `invalid_preset_count_expression: A200 empty quota means preset count and must use C030 with num=1`.
442
+ ```json
443
+ {
444
+ "eventTriggerType": 1,
445
+ "windowGap": 7,
446
+ "windowGapTimeUnit": "day",
447
+ "relationProps": [],
448
+ "events": [
449
+ {
450
+ "type": "event",
451
+ "event": "login",
452
+ "aggregation": "count",
453
+ "operator": "eq",
454
+ "value": 3
455
+ }
456
+ ],
457
+ "blackList": [
458
+ {
459
+ "type": "event",
460
+ "event": "logout",
461
+ "aggregation": "count",
462
+ "operator": "eq",
463
+ "value": 1
464
+ }
465
+ ]
466
+ }
467
+ ```
410
468
 
411
- A working event-condition leaf (used inside `triggerRule[].events[]` for `event_judge` / `event_trigger` / `event_split_flow`):
469
+ ### 9.3 Ordered completion: `2`
470
+
471
+ Each sequence item wraps its semantic event in `eventDefinition`. The last step must have
472
+ `hasDone=true`, and at least one step must be completed. Optional intermediate steps may use
473
+ `hasDone=false`. Step windows require both `windowGap` and `windowGapTimeUnit`.
412
474
 
413
475
  ```json
414
476
  {
415
- "conditionType": "event",
416
- "eventCondition": {
417
- "eventName": "ta@active_user",
418
- "eventDesc": "User active",
419
- "eventType": "event",
420
- "uceCalcuSymbol": "C030",
421
- "num": "1",
422
- "taPropQuota": { "analysis": "A200", "analysisDesc": "Count", "quota": "", "quotaDesc": "", "analysisParams": "" },
423
- "recentDay": "0-30",
424
- "startTime": "",
425
- "endTime": "",
426
- "filts": [],
427
- "relation": 1
428
- }
477
+ "eventTriggerType": 2,
478
+ "relationProps": [],
479
+ "events": [
480
+ {
481
+ "eventDefinition": {
482
+ "type": "event",
483
+ "event": "login",
484
+ "aggregation": "count",
485
+ "operator": "eq",
486
+ "value": 1
487
+ },
488
+ "hasDone": false,
489
+ "hasDistanceStart": false
490
+ },
491
+ {
492
+ "eventDefinition": {
493
+ "type": "event",
494
+ "event": "purchase",
495
+ "aggregation": "count",
496
+ "operator": "eq",
497
+ "value": 1
498
+ },
499
+ "hasDone": true,
500
+ "hasDistanceStart": false,
501
+ "windowGap": 2,
502
+ "windowGapTimeUnit": "day"
503
+ }
504
+ ]
429
505
  }
430
506
  ```
431
507
 
432
- Wrap the leaves with `{ "totalCFilter": { "filts": [ ... ], "relation": 1 } }`, then `JSON.stringify` for `targetClusterQp`.
508
+ Do not put persisted aggregate fields (`taPropQuota`, `uceCalcuSymbol`, `num`) directly on an
509
+ ordered step, and do not copy Task ORDER/EVERY examples into Flow. Hermes supplies metadata and
510
+ numeric Flow relations. Flow get returns `triggerDefinition` plus conversion status and hides
511
+ `triggerRule`.
433
512
 
434
513
  ---
435
514
 
@@ -462,7 +541,7 @@ The CLI injects `projectId` into both the top level and `req`; you do not write
462
541
 
463
542
  - **`data.result.errors` empty + `data.result.next_slot` present** → server needs one more node config (trigger / channel / targetCluster). Answer with request fields `operation=build` + `draftId` + `expectedVersion` + `slotAnswer`. If response `next_slot.target_node_id` is present, request `slotAnswer.nodeConfig` may contain only `config`; otherwise include `nodeId` or `id`. **`slotAnswer.nodeConfig.config` merges into the existing node config** — send only the fields you are adding or changing, not the full config.
464
543
  - For existing-cluster entry nodes (`targetUserType=2`), use `targetClusterName` or `clusterId` alias.
465
- - For custom audiences, call `ae-cli engage-setting query cluster-qp-skill --project-id <projectId>` before filling `targetClusterQp`.
544
+ - For custom audiences, build an Analysis-compatible `targetDefinitionRequest`.
466
545
  - For `event_trigger`, `endDate` must be **strictly earlier than** `flowEndDate`.
467
546
  - **`data.result.errors` non-empty** → hard validation failure. Fix `nodes`/`edges` and `build` again (a new `data.result.draft_id` is issued; the stale draft is cleaned by TTL).
468
547
 
@@ -525,15 +604,13 @@ Output the complete `req` JSON for debugging plus a clear failure reason.
525
604
  | `Unsupported save_flow operation: null` | Legacy `nodeList`/`edgeList` payload, or `operation` missing | Put `operation` = `build`/`preview`/`commit` in `req`, use `nodes`/`edges` |
526
605
  | `Flag --req.sourceFlowUuid is no longer supported` | Removed clone mode from an older protocol | Call `engage-flow flow get`, convert `data.flow.node_list`/`data.flow.edge_list` into compact request `nodes`/`edges`, then create with `operation=build` |
527
606
  | operation rejected (`SAVE`/`DRAFT`/`SUBMIT`/`mode`/`action`…) | Wrong field or wrong enum | `operation` is at `req.operation`; enum is only `build`/`preview`/`commit` |
528
- | `invalid_qp_relation: QP relation must be number 0 or 1` | `relation` sent as string | Use integer `0`/`1` |
529
- | `invalid_qp_leaf: QP property leaf must contain columnType/columnDesc` | userCondition leaf missing fields | Add `columnType` + `columnDesc` |
530
- | `required_by_minimal_valid` | `taPropQuota` missing fields | Add `quotaDesc` + `quota` + `analysisParams` |
531
- | `invalid_preset_count_expression` | Event count condition (`A200`) with empty quota uses wrong operator/num | Use `uceCalcuSymbol = C030` + `num = "1"` (see §9.2) |
607
+ | semantic definition rejected | Unsupported condition type, operator, aggregation, or time range | Rebuild the Analysis-compatible semantic definition; see `ae-analysis` user-cluster models |
608
+ | `invalid_preset_count_expression` | Event count condition uses an unsupported semantic operator/value | Use `operator = "gte"` + `value = 1` (see §9.2) |
532
609
  | `... branch must use its own dedicated exit ...` | Multiple paths share one `exit_flow` | Give every terminal branch its own `exit_flow` node (see §10.4) |
533
610
  | `disabled_channel: channelId must reference an enabled channel` | Response `channel_status = 0` | `engage-setting channel update-status --status 1` first |
534
611
  | commit token/version mismatch | Used build's `confirm_token`/`draft_version` | Use the values returned by **preview** |
535
612
  | `flowDesc` rejected | Over 200 chars | Trim to ≤ 200 |
536
- | `config` rejected as object where string expected | Wrong shape for `targetClusterQp` / TEXT rich-text | `JSON.stringify` those inner values |
613
+ | `config` rejected as object where string expected | Wrong shape for TEXT rich-text or another legacy string field | `JSON.stringify` only the documented inner string values |
537
614
 
538
615
  ---
539
616
 
@@ -544,7 +621,7 @@ Output the complete `req` JSON for debugging plus a clear failure reason.
544
621
  3. **Time units must be lowercase** — `day`, `hour`, `minute`, `week`, `month` (not `DAY`/`HOUR`).
545
622
  4. **Do not invent `channelId`** — get it from `ae-cli engage-setting channel list`.
546
623
  5. **Define branch IDs before referencing them** — `edge.sourceBranchId` must already exist in the upstream node `config`; for two-edge push action nodes, use `meetBranchId` and `notMeetBranchId`.
547
- 6. **`targetClusterQp` is usually a string** — `JSON.stringify` the QP object.
624
+ 6. **Custom audiences are semantic objects** — use `targetDefinitionRequest`; do not stringify or construct execution QP.
548
625
  7. **TEXT rich-text `config` must also be a string** — not an object.
549
626
  8. **`commit` uses preview's token/version** — not build's.
550
627
  9. **Do not merge branches again when `splitFlowType = 2`**.
@@ -553,4 +630,4 @@ Output the complete `req` JSON for debugging plus a clear failure reason.
553
630
 
554
631
  ## 14. One-Sentence Summary
555
632
 
556
- Drive `engage-flow flow save` as a state machine — `build` (`nodes`/`edges`, not `nodeList`/`edgeList` or `sourceFlowUuid`) → resolve any `need_input` slots → `preview` (map response `draft_version` + `confirm_token` to request `draftVersion` + `confirmToken`) → `commit` → verify with `engage-flow flow get`; keep QP `relation` integer, fill `columnType`/`columnDesc` on userCondition leaves and `quotaDesc`/`quota`/`analysisParams` on `taPropQuota`, and ensure touchpoint channels are enabled before referencing them.
633
+ Drive `engage-flow flow save` as a state machine — `build` (`nodes`/`edges`, not `nodeList`/`edgeList` or `sourceFlowUuid`) → resolve any `need_input` slots → `preview` (map response `draft_version` + `confirm_token` to request `draftVersion` + `confirmToken`) → `commit` → verify with `engage-flow flow get`; submit only semantic audience and trigger definitions, and ensure touchpoint channels are enabled before referencing them.