@thinkingai/ae-cli 6.1.10 → 6.1.12

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 (232) 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-DRLGDVS4.js} +24 -17
  6. package/dist/{capability-YPOQX6PL.js → capability-P6GK3AQH.js} +24 -17
  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 +94 -35
  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-experiment-N63WF7XA.js → te-experiment-2T2HEZML.js} +189 -10
  48. package/dist/{te-experiment-D32TB6ZB.js → te-experiment-PVEY7AEZ.js} +189 -10
  49. package/dist/{te-kb-E7NSCBRB.js → te-kb-VRMEY3D4.js} +6 -6
  50. package/dist/{te-meta-GBDTMPEL.js → te-meta-53BVXPFI.js} +7 -7
  51. package/dist/{te-meta-ZTLTSHXC.js → te-meta-TOCBPBXI.js} +7 -7
  52. package/dist/{te-system-AH7DMCAQ.js → te-system-XGS5EQIQ.js} +4 -4
  53. package/dist/{te-team-BQ3SKSZV.js → te-team-BZRDV2CM.js} +7 -7
  54. package/dist/{update-DKG6UXEM.js → update-HEDXGOJH.js} +8 -6
  55. package/package.json +5 -2
  56. package/skills/ae-agent/SKILL.md +178 -16
  57. package/skills/ae-agent/references/add-skill.md +22 -10
  58. package/skills/ae-agent/references/edit-skill.md +24 -14
  59. package/skills/ae-agent/references/find-archived-conversations.md +82 -0
  60. package/skills/ae-agent/references/restore-conversation.md +54 -0
  61. package/skills/ae-agent/references/upload-skill.md +24 -14
  62. package/skills/ae-analysis/SKILL.md +1 -1
  63. package/skills/ae-analysis/references/command_index.md +104 -42
  64. package/skills/ae-analysis/references/entity_id_import_options.md +1 -1
  65. package/skills/ae-analysis/references/project_access_detail_get.md +3 -3
  66. package/skills/ae-analysis/references/project_data_power_delete.md +3 -3
  67. package/skills/ae-analysis/references/project_data_power_get.md +3 -3
  68. package/skills/ae-analysis/references/project_data_power_list.md +3 -3
  69. package/skills/ae-analysis/references/project_data_power_upsert.md +3 -3
  70. package/skills/ae-analysis/references/project_entity_create.md +3 -3
  71. package/skills/ae-analysis/references/project_entity_delete.md +3 -3
  72. package/skills/ae-analysis/references/project_entity_event_list.md +3 -3
  73. package/skills/ae-analysis/references/project_entity_get.md +3 -3
  74. package/skills/ae-analysis/references/project_entity_list.md +3 -3
  75. package/skills/ae-analysis/references/project_entity_update.md +3 -3
  76. package/skills/ae-analysis/references/project_function_list.md +3 -3
  77. package/skills/ae-analysis/references/project_info_create.md +25 -0
  78. package/skills/ae-analysis/references/project_info_delete.md +24 -0
  79. package/skills/ae-analysis/references/project_info_get.md +3 -3
  80. package/skills/ae-analysis/references/project_info_list.md +3 -3
  81. package/skills/ae-analysis/references/project_info_update.md +3 -3
  82. package/skills/ae-analysis/references/project_mark_time_create.md +3 -3
  83. package/skills/ae-analysis/references/project_mark_time_delete.md +3 -3
  84. package/skills/ae-analysis/references/project_mark_time_list.md +3 -3
  85. package/skills/ae-analysis/references/project_mark_time_update.md +3 -3
  86. package/skills/ae-analysis/references/project_member_add.md +3 -3
  87. package/skills/ae-analysis/references/project_member_batch_update.md +3 -3
  88. package/skills/ae-analysis/references/project_member_candidate_list.md +3 -3
  89. package/skills/ae-analysis/references/project_member_handover_export.md +3 -3
  90. package/skills/ae-analysis/references/project_member_handover_run.md +3 -3
  91. package/skills/ae-analysis/references/project_member_import.md +3 -3
  92. package/skills/ae-analysis/references/project_member_list.md +3 -3
  93. package/skills/ae-analysis/references/project_member_receiver_list.md +3 -3
  94. package/skills/ae-analysis/references/project_member_remove.md +3 -3
  95. package/skills/ae-analysis/references/project_member_update.md +3 -3
  96. package/skills/ae-analysis/references/project_owner_update.md +3 -3
  97. package/skills/ae-analysis/references/project_permission_binding_list.md +3 -3
  98. package/skills/ae-analysis/references/project_receive_status_update.md +3 -3
  99. package/skills/ae-analysis/references/project_role_delete.md +3 -3
  100. package/skills/ae-analysis/references/project_role_function_list.md +3 -3
  101. package/skills/ae-analysis/references/project_role_get.md +3 -3
  102. package/skills/ae-analysis/references/project_role_list.md +3 -3
  103. package/skills/ae-analysis/references/project_role_upsert.md +3 -3
  104. package/skills/ae-analysis/references/project_role_user_list.md +3 -3
  105. package/skills/ae-analysis/references/project_space_list.md +1 -1
  106. package/skills/ae-analysis/references/project_timezone_get.md +3 -3
  107. package/skills/ae-analysis/references/project_timezone_overview.md +3 -3
  108. package/skills/ae-analysis/references/project_timezone_update.md +3 -3
  109. package/skills/ae-analysis/references/project_user_id_items_update.md +3 -3
  110. package/skills/ae-analysis/references/system_admin_function_list.md +22 -0
  111. package/skills/ae-analysis/references/system_admin_function_update.md +26 -0
  112. package/skills/ae-analysis/references/system_admin_list.md +21 -0
  113. package/skills/ae-analysis/references/system_admin_remove.md +25 -0
  114. package/skills/ae-analysis/references/system_admin_upsert.md +25 -0
  115. package/skills/ae-analysis/references/system_function_list.md +21 -0
  116. package/skills/ae-analysis/references/system_member_add.md +25 -0
  117. package/skills/ae-analysis/references/system_member_candidate_list.md +22 -0
  118. package/skills/ae-analysis/references/system_member_delete.md +25 -0
  119. package/skills/ae-analysis/references/system_member_list.md +24 -0
  120. package/skills/ae-analysis/references/system_member_mfa_unbind.md +25 -0
  121. package/skills/ae-analysis/references/system_member_password_reset.md +32 -0
  122. package/skills/ae-analysis/references/system_member_project_batch_update.md +27 -0
  123. package/skills/ae-analysis/references/system_member_status_update.md +26 -0
  124. package/skills/ae-analysis/references/system_member_update.md +23 -0
  125. package/skills/ae-analysis/references/system_mfa_get.md +21 -0
  126. package/skills/ae-analysis/references/system_mfa_update.md +25 -0
  127. package/skills/ae-analysis/references/system_node_monitor_list.md +24 -0
  128. package/skills/ae-analysis/references/system_oauth2_update.md +22 -0
  129. package/skills/ae-analysis/references/system_ops_alert_contact_delete.md +25 -0
  130. package/skills/ae-analysis/references/system_ops_alert_contact_list.md +23 -0
  131. package/skills/ae-analysis/references/system_ops_alert_contact_test.md +29 -0
  132. package/skills/ae-analysis/references/system_ops_alert_contact_upsert.md +39 -0
  133. package/skills/ae-analysis/references/system_preference_get.md +21 -0
  134. package/skills/ae-analysis/references/system_preference_update.md +22 -0
  135. package/skills/ae-analysis/references/system_project_usage_list.md +28 -0
  136. package/skills/ae-analysis/references/system_query_alert_rule_list.md +21 -0
  137. package/skills/ae-analysis/references/system_query_alert_rule_update.md +26 -0
  138. package/skills/ae-analysis/references/system_query_monitor_overview.md +26 -0
  139. package/skills/ae-analysis/references/system_query_task_cancel.md +25 -0
  140. package/skills/ae-analysis/references/system_query_task_export.md +49 -0
  141. package/skills/ae-analysis/references/system_query_task_get.md +23 -0
  142. package/skills/ae-analysis/references/system_query_task_list.md +35 -0
  143. package/skills/ae-analysis/references/system_query_task_options.md +27 -0
  144. package/skills/ae-analysis/references/system_receiver_address_delete.md +26 -0
  145. package/skills/ae-analysis/references/system_receiver_address_overview.md +21 -0
  146. package/skills/ae-analysis/references/system_receiver_address_project_list.md +21 -0
  147. package/skills/ae-analysis/references/system_receiver_address_promote.md +24 -0
  148. package/skills/ae-analysis/references/system_receiver_address_upsert.md +27 -0
  149. package/skills/ae-analysis/references/system_receiver_detection_get.md +22 -0
  150. package/skills/ae-analysis/references/system_receiver_detection_run.md +22 -0
  151. package/skills/ae-analysis/references/system_receiver_detection_update.md +25 -0
  152. package/skills/ae-analysis/references/system_role_delete.md +26 -0
  153. package/skills/ae-analysis/references/system_role_function_list.md +22 -0
  154. package/skills/ae-analysis/references/system_role_get.md +22 -0
  155. package/skills/ae-analysis/references/system_role_list.md +24 -0
  156. package/skills/ae-analysis/references/system_role_upsert.md +27 -0
  157. package/skills/ae-analysis/references/system_role_user_list.md +22 -0
  158. package/skills/ae-analysis/references/system_seat_list.md +25 -0
  159. package/skills/ae-analysis/references/system_seat_update.md +26 -0
  160. package/skills/ae-analysis/references/system_smtp_delete.md +24 -0
  161. package/skills/ae-analysis/references/system_smtp_get.md +21 -0
  162. package/skills/ae-analysis/references/system_smtp_test.md +22 -0
  163. package/skills/ae-analysis/references/system_smtp_upsert.md +31 -0
  164. package/skills/ae-analysis/references/system_third_party_login_disable.md +25 -0
  165. package/skills/ae-analysis/references/system_third_party_login_list.md +21 -0
  166. package/skills/ae-analysis/references/system_third_party_login_upsert.md +33 -0
  167. package/skills/ae-analysis/references/system_usage_overview.md +21 -0
  168. package/skills/ae-analysis/references/system_usage_trend_export.md +44 -0
  169. package/skills/ae-analysis/references/system_usage_trend_query.md +28 -0
  170. package/skills/ae-dataops/SKILL.md +1 -1
  171. package/skills/ae-dataops/references/dataops-flow-create.md +51 -16
  172. package/skills/ae-engage/SKILL.md +67 -27
  173. package/skills/ae-engage/references/activity-activity.md +3 -0
  174. package/skills/ae-engage/references/activity-approval.md +12 -4
  175. package/skills/ae-engage/references/activity-data-detail.md +61 -0
  176. package/skills/ae-engage/references/activity-task.md +21 -6
  177. package/skills/ae-engage/references/activity-topic.md +31 -13
  178. package/skills/ae-engage/references/add-channel.md +170 -41
  179. package/skills/ae-engage/references/build-task-save-guide.md +66 -29
  180. package/skills/ae-engage/references/channel-update-config.md +3 -2
  181. package/skills/ae-engage/references/common-metric.md +88 -115
  182. package/skills/ae-engage/references/flow-detail.md +13 -0
  183. package/skills/ae-engage/references/preset-event.md +14 -32
  184. package/skills/ae-engage/references/save-flow.md +141 -64
  185. package/skills/ae-engage/references/save-task.md +231 -58
  186. package/skills/ae-engage/references/scene-config-metric.md +3 -0
  187. package/skills/ae-engage/references/scene-preset-metric.md +8 -37
  188. package/skills/ae-engage/references/scene-strategy-audience.md +56 -643
  189. package/skills/ae-engage/references/scene-strategy.md +6 -6
  190. package/skills/ae-engage/references/task-detail.md +10 -0
  191. package/skills/ae-engage/references/task-submit-approval.md +45 -0
  192. package/skills/ae-engage/references/validate-flow-node-config.md +1 -1
  193. package/skills/ae-experiment/SKILL.md +38 -5
  194. package/skills/ae-experiment/references/check_experiment_ready.md +2 -0
  195. package/skills/ae-experiment/references/delete_metric.md +2 -0
  196. package/skills/ae-experiment/references/query_experiment_detail.md +6 -0
  197. package/skills/ae-experiment/references/query_experiment_list.md +4 -0
  198. package/skills/ae-experiment/references/query_experiment_list_archived.md +3 -0
  199. package/skills/ae-experiment/references/query_experiment_metric_trend.md +5 -5
  200. package/skills/ae-experiment/references/query_experiment_report_summary.md +4 -3
  201. package/skills/ae-experiment/references/query_experiment_sample_size_report.md +6 -5
  202. package/skills/ae-experiment/references/query_metric_detail.md +5 -0
  203. package/skills/ae-experiment/references/query_metric_list.md +3 -0
  204. package/skills/ae-experiment/references/save_build_guide.md +39 -0
  205. package/skills/ae-experiment/references/save_experiment.md +53 -3
  206. package/skills/ae-experiment/references/save_metric.md +67 -1
  207. package/skills/ae-experiment/references/save_submit_experiment.md +3 -0
  208. package/skills/ae-experiment/references/save_validate.md +33 -0
  209. package/skills/ae-experiment-design/SKILL.md +149 -0
  210. package/skills/ae-experiment-design/agents/openai.yaml +4 -0
  211. package/skills/ae-experiment-design/references/client-experiment-sdk.md +147 -0
  212. package/skills/ae-experiment-design/references/experiment-creation.md +108 -0
  213. package/skills/ae-experiment-design/references/experiment-sdk-contract.md +100 -0
  214. package/skills/ae-experiment-design/references/exposure-contract.md +91 -0
  215. package/skills/ae-experiment-design/references/hybrid-experiment-sdk.md +74 -0
  216. package/skills/ae-experiment-design/references/metric-readiness.md +143 -0
  217. package/skills/ae-experiment-design/references/platform-operations.md +105 -0
  218. package/skills/ae-experiment-design/references/sdk-index.md +76 -0
  219. package/skills/ae-experiment-design/references/sdk-integration.md +114 -0
  220. package/skills/ae-experiment-design/references/sdk-troubleshooting.md +139 -0
  221. package/skills/ae-experiment-design/references/server-experiment-sdk.md +78 -0
  222. package/skills/ae-experiment-design/scripts/calculate_experiment_plan.py +450 -0
  223. package/skills/ae-experiment-insight/SKILL.md +149 -0
  224. package/skills/ae-experiment-insight/agents/openai.yaml +4 -0
  225. package/skills/ae-experiment-insight/references/decision-framework.md +69 -0
  226. package/skills/ae-experiment-insight/references/diagnostic-playbook.md +225 -0
  227. package/skills/ae-experiment-insight/references/platform-operations.md +82 -0
  228. package/skills/ae-experiment-insight/scripts/analyze_experiment.py +478 -0
  229. package/skills/ae-generate-tracking-code/SKILL.md +2 -2
  230. package/skills/ae-metadata/SKILL.md +1 -1
  231. package/dist/config-BSSALXEN.js +0 -128
  232. package/dist/sync-QFP4XFN3.js +0 -485
@@ -24,9 +24,9 @@ ae-cli engage-scene strategy update --project-id <project_id> \
24
24
  # Query a strategy's log
25
25
  ae-cli engage-scene strategy log --project-id <project_id> --strategy-uuid <uuid>
26
26
 
27
- # Predict custom-audience size (mix QP)
27
+ # Predict custom-audience size
28
28
  ae-cli engage-scene strategy predict --project-id <project_id> \
29
- --qp '<targetClusterQp JSON string>' \
29
+ --definition-request '{"type":"condition","conditions":{...}}' \
30
30
  --zone-offset 8 \
31
31
  [--strategy-uuid <uuid>]
32
32
 
@@ -48,7 +48,7 @@ ae-cli engage-scene strategy manage --project-id <project_id> --config-id <confi
48
48
  | create | `--project-id`, `--payload` | payload = `ConfigStrategyAddDTO`. |
49
49
  | update | `--project-id`, `--payload` | payload = `ConfigStrategyModifyDTO` (`strategyUuid` + fields). |
50
50
  | log | `--project-id`, `--strategy-uuid` | read. |
51
- | predict | `--project-id`, `--qp`, `--zone-offset` | Optional `--strategy-uuid`, `--request-id`. read. |
51
+ | predict | `--project-id`, `--definition-request`, `--zone-offset` | Optional `--strategy-uuid`, `--request-id`. read. |
52
52
  | batch-copy | `--project-id`, `--config-id`, `--strategy-ids` | `--op-mode` optional (default `batch`). |
53
53
  | manage | `--project-id`, `--config-id`, `--action` | Lifecycle actions require `--strategy-uuid-list`; review actions require `--strategy-list`; write. |
54
54
 
@@ -67,10 +67,10 @@ ae-cli engage-scene strategy manage --project-id <project_id> --config-id <confi
67
67
  - Discover real strategy UUIDs / config IDs first; never invent IDs.
68
68
  - **Custom audience (`targetClusterType=1`)** — follow [`scene-strategy-audience.md`](scene-strategy-audience.md) end-to-end:
69
69
  1. Preflight every **用户满足** user property and **用户行为** event via `analysis-meta property get` / `event get`; if missing, **stop** and list available properties — never invent or drop.
70
- 2. Assemble mix QP with **two-block layout**: `totalCFilter.filts[0]` = 用户满足, `totalCFilter.filts[1]` = 用户行为; `totalCFilter.relation` = 且/或 between them. **Never** nest `event` inside user-side `COMPOUND`.
71
- 3. `JSON.stringify` `targetClusterQp`; then `strategy create|update`.
70
+ 2. Build an Analysis-compatible semantic condition in `payload.definitionRequest`.
71
+ 3. Reuse the same definition with `strategy predict --definition-request`.
72
72
  4. **Do not** call `analysis user-cluster create` unless the user explicitly asks for an existing/named cluster.
73
- - Full QP spec + examples A/B/C: [`scene-strategy-audience.md`](scene-strategy-audience.md).
73
+ - Semantic contract and examples: [`scene-strategy-audience.md`](scene-strategy-audience.md).
74
74
  - **`create` requires an enabled template** on the same config item. Enable workflow: `config-param batch-add` → `template create` → `template update` (non-empty `config[]` with real `paramId`) → `template update-status --status 1`. Otherwise `create` returns `TEMPLATE_ENABLE`.
75
75
  - `create` output field is `data.strategy_uuid` (not `strategy_id`).
76
76
  - `manage` supports `online`, `offline`, `suspend`, `delete`, `approve`, `deny`, and `cancel`; it is a write operation.
@@ -5,6 +5,16 @@ Query the details of a single task.
5
5
 
6
6
  Mapped command: `ae-cli engage-task task get`
7
7
 
8
+ For a custom target audience, the response hides persisted `qp` and returns:
9
+
10
+ - `definition_status`: `AVAILABLE`, `UNAVAILABLE`, or `NOT_APPLICABLE`
11
+ - `definition_request`: the Analysis-compatible semantic audience definition when available
12
+ - `definition_unavailable_reason`: present only when a historical QP cannot be reversed
13
+
14
+ Reuse `definition_request` as `req.targetConfig.definitionRequest` when updating a task.
15
+ Soft-deleted tasks are treated as unavailable and return `TASK_NOT_FOUND`, matching task-list
16
+ visibility.
17
+
8
18
  ## Flags
9
19
 
10
20
  | Flag | Type | Required | Description |
@@ -0,0 +1,45 @@
1
+ # engage-task task submit-approval
2
+
3
+ Submit an existing draft engagement task for approval. The legacy full save-and-submit request remains supported.
4
+ This is a regular write operation.
5
+
6
+ > Capability id: `engage-task.task.submit-approval` · Domain: `engage`.
7
+
8
+ ```bash
9
+ ae-cli engage-task task submit-approval --project-id <project_id> --task-id <task_id>
10
+ ```
11
+
12
+ ## Parameters
13
+
14
+ | Flag | Required | Notes |
15
+ |---|---|---|
16
+ | `--project-id` / `-p` | yes | Numeric project ID. |
17
+ | `--task-id` | conditional | Existing draft task ID. Recommended after `task save`. |
18
+ | `--request` | conditional | Legacy `ApprovalSaveAndSubmitDTO` / `OperationTaskOpDTO` JSON (camelCase or snake_case). |
19
+
20
+ Provide exactly one of `--task-id` or `--request`.
21
+
22
+ ## Output
23
+
24
+ - `data.task_id`
25
+
26
+ ## Request notes
27
+
28
+ - Prefer `task save` followed by `submit-approval --task-id`. The server loads the persisted draft, validates its
29
+ trigger rule, and reuses the existing save-and-submit approval workflow.
30
+ - Do not reconstruct or pass `trigger_rule`. It is an internal persisted field.
31
+ - The legacy `--request` mode remains available for existing callers.
32
+ - Required body fields (server validates): `task_name`, `channel_type`, `channel_id`, `group_content_list`, `target_cluster_type`, `trigger_type`, `completion_indicator_def`, `frequency_limits`, `enable_channel_touch_limits`, `group_id`, `trigger_time_strategy`.
33
+ - Missing `expConfig` is auto-filled as `{"enableExp":false}` (same as activity task create/update).
34
+ - TEXT channel params missing `config` are auto-filled with Slate.js JSON from `value`.
35
+ - For schedule-single (`triggerType=0`), include a future `triggerTime` (and `tzOffset` / `triggerTimeStrategy` as needed).
36
+ - Prefer save → submit by task ID; do not invent `taskId` / `channelId`.
37
+
38
+ ## Common Errors
39
+
40
+ | code | when |
41
+ |---|---|
42
+ | `APPROVAL_INPUT_INVALID` | neither or both of `task_id` and `request` supplied |
43
+ | `REQUEST_REQUIRED` | `--request` missing or not an object |
44
+ | `REQUEST_FIELDS_REQUIRED` | required body fields absent/blank |
45
+ | `CAPABILITY_EXECUTION_FAILED` | unmapped domain failure; check `invocation_id` / Hermes logs |
@@ -30,7 +30,7 @@ Use `--operation-mode save_flow` for the current exposed MCP protocol. Use `save
30
30
  Important current rules:
31
31
 
32
32
  - `event_trigger` / `event_judge` A segment: use `periodStart`, `periodEnd`, `periodTimeSymbol`; do not use branch-style `delayTime`.
33
- - `event_split_flow` branch segment: use `delayTime`, `delayTimeSymbol`, `targetClusterType`; omit `triggerRule` on default branches.
33
+ - `event_split_flow` branch segment: use `delayTime`, `delayTimeSymbol`, `targetClusterType`; omit `triggerDefinition` on default branches.
34
34
  - `event_trigger targetUserType=2` is invalid.
35
35
  - Push `OBJ_ARRAY.value` must be a JSON array, not a stringified array.
36
36
  - Push `contentList[].content` should be a JSON array, but a JSON-stringified array is accepted for compatibility.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: ae-experiment
3
- version: 1.0.0
3
+ version: 1.0.1
4
4
  description: "Use when managing Atlas AB experiments, traffic layers, Features, metrics, buckets, and experiment reports through ae-cli"
5
5
  ---
6
6
 
@@ -14,6 +14,7 @@ AE CLI (`ae-cli`) exposes Atlas AB Experiment capabilities through the `experime
14
14
  - Use `--project-id` / `-p` for project-scoped commands.
15
15
  - Use `--req` JSON for complex save, status, and delete DTOs.
16
16
  - Do not invent experiment IDs, traffic layer IDs, bucket IDs, Feature keys, metric IDs, or payload field names.
17
+ - Bind only metric IDs returned by `experiment metric list`; create and verify a missing metric before saving the experiment.
17
18
  - Read commands can run directly after IDs are verified.
18
19
  - Write commands require explicit user intent and normally keep the confirmation prompt. Use `--dry-run` before write calls when composing JSON.
19
20
 
@@ -22,8 +23,23 @@ Naming and response boundary:
22
23
  - CLI command segments and flags use kebab-case.
23
24
  - Outer Capability input and all response keys use snake_case.
24
25
  - Nested business DTOs passed through `--req` keep their native camelCase fields.
26
+ - **CRITICAL:** `save build-guide` / `save validate` responses recursively snake_case
27
+ `example_args.req`. Never copy those keys into `--req`. Use camelCase
28
+ (`expName`, `metricId`, …). Authoritative names:
29
+ `ae-cli capability inspect experiment.experiment.save` (or the matching final save id)
30
+ → `input_schema.properties.req`. `save validate` `valid: true` is **not** a final-save
31
+ schema pass — snake_case `req` can still fail on `experiment … save`.
32
+ - Audience QP is semantic at the CLI boundary: write `targeting.definitionRequest`; read
33
+ `targeting.definition_request`. Never generate or submit `targetConfig`.
34
+ - Metric QP is semantic at the CLI boundary: write `metricDefinition`; read
35
+ `metric_definition`. Never generate or submit `metricConfig`, `calcType`, or `Axxx` codes.
36
+ - For metric aggregations `sum` / `avg` / `max` / `distinct_count`, `metricDefinition.property`
37
+ is **required** and must be a concrete available event property from Analysis metadata.
38
+ Never create property aggregations without `property` (for example `metric_avg_no_property_*`).
39
+ - Event-count aggregations `total_count` / `user_count` / `active_days` omit `property`.
40
+ - Resolve event and property names with Analysis metadata before saving semantic definitions.
25
41
  - Lists return `data.items` and `data.total`; detail commands return `data.item`.
26
- - Readiness returns `data.readiness`; reports return `data.report`; writes return `data.result`.
42
+ - Readiness returns `data.readiness`; reports return `data.report`; save guides return `data.guide`; save dry-run validation returns `data.validation`; writes return `data.result`.
27
43
  - Query cancellation returns `data.success`.
28
44
 
29
45
  ## Typical Workflow
@@ -34,6 +50,8 @@ Naming and response boundary:
34
50
  - `experiment feature list`
35
51
  - `experiment metric list`
36
52
  2. Create missing assets if needed:
53
+ - `experiment save build-guide --operation-mode save_metric` when save validation fails or req shape is unclear
54
+ - `experiment save validate --operation-mode save_metric --req '{...}'` before retrying a failed save
37
55
  - `experiment traffic-layer save`
38
56
  - `experiment feature save`
39
57
  - `experiment metric save`
@@ -41,14 +59,19 @@ Naming and response boundary:
41
59
  4. Check readiness with `experiment experiment ready-check`.
42
60
  5. For a non-mutex traffic layer, run `experiment experiment conflict-check` before submit (needs `feature_key_list` from context or `experiment get`).
43
61
  6. Move status with `experiment experiment manage`.
44
- 7. Query reports with summary, sample-size, and metric-trend commands.
62
+ 7. Query reports with `experiment report summary`, `experiment report sample-size`, and `experiment report metric-trend`.
63
+
64
+ If an experiment save returns `error_code: METRIC_NOT_FOUND`, list metrics for the same project. Create and verify the metric before retrying; never retry with another invented ID. Metric deletion returns `error_code: METRIC_IN_USE` while an active experiment binding exists.
45
65
 
46
66
  ## Parameter Conventions
47
67
 
68
+ - Experiment save payloads distinguish two allocation fields: experiment-level `req.allocation` (**integer only; no decimals**) and group-level `req.groups[].allocation` (**integer only; sum must equal `100` exactly**).
69
+
48
70
  ```bash
49
71
  ae-cli experiment experiment get --project-id 1 --exp-id exp_123
50
72
  ae-cli experiment experiment save --project-id 1 --req '{"expName":"Demo"}' --dry-run
51
- ae-cli capability run experiment.report.metric-trend --input '{"project_id":1,"exp_id":"exp_123","metric_id":"metric_1","start_time":"2026-07-01","end_time":"2026-07-07"}'
73
+ ae-cli experiment metric save --project-id 1 --req '{"metricId":"login_users","metricName":"Login users","createType":"event","goalDirection":"up","metricDesc":"Users who logged in","metricDefinition":{"type":"event","event":"login","aggregation":"user_count"}}' --dry-run
74
+ ae-cli experiment report metric-trend --project-id 1 --exp-id exp_123 --metric-id metric_1 --start-time 2026-07-01 --end-time 2026-07-07
52
75
  ```
53
76
 
54
77
  Optional global parameters work as in other domains: `--host`, `--mcp-url`, `--format`, `--jq`, `--dry-run`, and `--yes`.
@@ -57,6 +80,16 @@ Optional global parameters work as in other domains: `--host`, `--mcp-url`, `--f
57
80
 
58
81
  Open the matching file in `references/` before using a command, especially for write operations and JSON payloads.
59
82
 
83
+ ### Save Helpers
84
+
85
+ `experiment save build-guide`, `experiment save validate`
86
+
87
+ When a save command returns `next_tool: experiment.save.build-guide`, call the guide first, then `experiment save validate`, then retry the final save capability.
88
+
89
+ Read [`save_build_guide.md`](references/save_build_guide.md) and
90
+ [`save_validate.md`](references/save_validate.md) before using these helpers. Rebuild
91
+ `--req` in camelCase from `inspect` / skill references; do not paste `example_args.req`.
92
+
60
93
  ### Experiment
61
94
 
62
95
  `experiment experiment save`, `capability run experiment.experiment.save-submit`, `experiment experiment list`, `experiment experiment list-archived`, `experiment experiment get`, `experiment experiment ready-check`, `experiment experiment conflict-check`, `experiment experiment manage`, `experiment experiment update-group`, `experiment experiment batch-delete`, `experiment operation-log query`
@@ -67,7 +100,7 @@ Open the matching file in `references/` before using a command, especially for w
67
100
 
68
101
  ### Reports
69
102
 
70
- `capability run experiment.report.summary`, `capability run experiment.report.sample-size`, `capability run experiment.report.metric-trend`, `capability run experiment.query.cancel`
103
+ `experiment report summary`, `experiment report sample-size`, `experiment report metric-trend`, `capability run experiment.query.cancel`
71
104
 
72
105
  ### Metric and Feature
73
106
 
@@ -12,4 +12,6 @@ Flags:
12
12
 
13
13
  Use this before `experiment experiment manage` moves an experiment to `pending`, `testing`, or `running`.
14
14
 
15
+ Common `groups` failure: `atlas.service.error.experiment.group.allocation.invalid`. Rule: each `groups[].allocation` must be an **integer**, and **sum = 100 exactly** (for example `34 + 33 + 33 = 100`).
16
+
15
17
  Response shape: the readiness result is in `data.readiness`, with recursively snake_case keys.
@@ -9,3 +9,5 @@ ae-cli experiment metric delete --project-id <id> --metric-id <metricId> [--yes]
9
9
  Flags:
10
10
  - `--project-id`, `-p`: Project ID.
11
11
  - `--metric-id`: Metric ID.
12
+
13
+ Deletion is rejected with `error_code: METRIC_IN_USE` while the metric has an active experiment binding. Remove the metric from the related experiment before retrying.
@@ -11,3 +11,9 @@ Flags:
11
11
  - `--exp-id`: Experiment ID.
12
12
 
13
13
  Response shape: the experiment is in `data.item`, with recursively snake_case keys such as `exp_id` and `feature_key_list`.
14
+
15
+ When targeting contains reversible QP, it is returned as
16
+ `targeting.definition_request` with `targeting.definition_status=AVAILABLE`.
17
+ An absent definition is `NOT_APPLICABLE`; a historical unsupported definition is
18
+ `UNAVAILABLE` with `definition_unavailable_reason`. The internal `target_config`
19
+ field is never returned.
@@ -16,3 +16,7 @@ Flags:
16
16
  - `--query-name`: Optional fuzzy match against experiment name (`exp_name LIKE`). Does not match `exp_id`.
17
17
 
18
18
  Response shape: `data.items` contains the experiments, `data.total` contains the count, and item keys are recursively snake_case.
19
+
20
+ Targeting follows the same semantic projection as detail:
21
+ `targeting.definition_request` plus `targeting.definition_status`; internal
22
+ `target_config` is not returned.
@@ -13,3 +13,6 @@ Flags:
13
13
  - `--project-id`, `-p`: Project ID.
14
14
 
15
15
  Response shape: `data.items` contains the archived experiments, `data.total` contains the count, and item keys are recursively snake_case.
16
+
17
+ Targeting is returned through `targeting.definition_request` and
18
+ `targeting.definition_status`; internal `target_config` is not returned.
@@ -1,12 +1,12 @@
1
- # capability run experiment.report.metric-trend
1
+ # experiment report metric-trend
2
2
 
3
3
  Query experiment metric trend report.
4
4
 
5
5
  ```bash
6
- ae-cli capability run experiment.report.metric-trend --input '{"project_id":1,"exp_id":"exp_123","metric_id":"metric_1","start_time":"2026-07-01","end_time":"2026-07-07"}'
6
+ ae-cli experiment report metric-trend --project-id 1 --exp-id exp_123 --metric-id metric_1 --start-time 2026-07-01 --end-time 2026-07-07
7
7
  ```
8
8
 
9
- Required input: `project_id`, `exp_id`, `metric_id`, `start_time`, `end_time`.
10
- Optional input: `request_id`, `force_refresh`.
9
+ Required flags: `--project-id`, `--exp-id`, `--metric-id`, `--start-time`, `--end-time`.
10
+ Optional: `--request-id`, `--force-refresh`.
11
11
 
12
- Response shape: `data.report`, with recursively snake_case keys. Preserve `request_id` for cancellation.
12
+ Response shape: `data.report`, with recursively snake_case keys. Preserve `request_id` for cancellation via `capability run experiment.query.cancel`.
@@ -1,11 +1,12 @@
1
- # capability run experiment.report.summary
1
+ # experiment report summary
2
2
 
3
3
  Query experiment report summary.
4
4
 
5
5
  ```bash
6
- ae-cli capability run experiment.report.summary --input '{"project_id":1,"exp_id":"exp_123","force_refresh":false}'
6
+ ae-cli experiment report summary --project-id 1 --exp-id exp_123
7
+ ae-cli experiment report summary --project-id 1 --exp-id exp_123 --force-refresh true
7
8
  ```
8
9
 
9
- Required input: `project_id`, `exp_id`. Optional input: `force_refresh`.
10
+ Required flags: `--project-id`, `--exp-id`. Optional: `--force-refresh`.
10
11
 
11
12
  Response shape: `data.report`, with recursively snake_case keys.
@@ -1,12 +1,13 @@
1
- # capability run experiment.report.sample-size
1
+ # experiment report sample-size
2
2
 
3
3
  Query experiment sample-size report.
4
4
 
5
5
  ```bash
6
- ae-cli capability run experiment.report.sample-size --input '{"project_id":1,"exp_id":"exp_123","start_time":"2026-07-01","end_time":"2026-07-07","by_hour":false}'
6
+ ae-cli experiment report sample-size --project-id 1 --exp-id exp_123 --start-time 2026-07-01 --end-time 2026-07-07
7
+ ae-cli experiment report sample-size --project-id 1 --exp-id exp_123 --start-time 2026-07-01 --end-time 2026-07-07 --by-hour true
7
8
  ```
8
9
 
9
- Required input: `project_id`, `exp_id`, `start_time`, `end_time`.
10
- Optional input: `request_id`, `force_refresh`, `by_hour`.
10
+ Required flags: `--project-id`, `--exp-id`, `--start-time`, `--end-time`.
11
+ Optional: `--request-id`, `--force-refresh`, `--by-hour`.
11
12
 
12
- Response shape: `data.report`, with recursively snake_case keys. Preserve `request_id` for cancellation.
13
+ Response shape: `data.report`, with recursively snake_case keys. Preserve `request_id` for cancellation via `capability run experiment.query.cancel`.
@@ -11,3 +11,8 @@ Flags:
11
11
  - `--metric-id`: Metric ID.
12
12
 
13
13
  Response shape: the metric is in `data.item`, with recursively snake_case keys.
14
+
15
+ Reversible QP is returned as `metric_definition` with
16
+ `metric_definition_status=AVAILABLE`. Missing QP is `NOT_APPLICABLE`; unsupported
17
+ historical QP is `UNAVAILABLE` with `metric_definition_unavailable_reason`.
18
+ Internal `metric_config` and `calc_type` are never returned.
@@ -10,3 +10,6 @@ Flags:
10
10
  - `--project-id`, `-p`: Project ID.
11
11
 
12
12
  Response shape: `data.items` contains metrics, `data.total` contains the count, and item keys are recursively snake_case.
13
+
14
+ Each item uses `metric_definition` and `metric_definition_status`. Internal
15
+ `metric_config` and `calc_type` are never returned.
@@ -0,0 +1,39 @@
1
+ # experiment save build-guide
2
+
3
+ Build a read-only save guide for feature, traffic layer, experiment, or metric saves.
4
+
5
+ ```bash
6
+ ae-cli experiment save build-guide --project-id <id> --operation-mode save_experiment
7
+ ```
8
+
9
+ Flags:
10
+ - `--project-id`, `-p`: Project ID.
11
+ - `--operation-mode`: `save_feature`, `save_traffic_layer`, `save_experiment`, or `save_metric`.
12
+
13
+ ## CRITICAL — do not copy `example_args.req` keys verbatim
14
+
15
+ Guide responses are recursively snake_cased for display. That wrongly rewrites nested DTO
16
+ placeholders inside `data.guide.example_args.req` (for example `expName` → `exp_name`,
17
+ `metricId` → `metric_id`).
18
+
19
+ Those snake_case keys are **not** valid `--req` fields for the final save commands.
20
+
21
+ Authoritative field names:
22
+
23
+ | Mode | Inspect / final save | Nested `--req` style |
24
+ | --- | --- | --- |
25
+ | `save_experiment` | `experiment.experiment.save` | camelCase (`expName`, `trafficLayerId`, …) |
26
+ | `save_metric` | `experiment.metric.save` | camelCase (`metricId`, `metricDefinition`, …) |
27
+ | `save_feature` | `experiment.feature.save` | camelCase (`featureKey`, `targetPlatform`, …) |
28
+ | `save_traffic_layer` | `experiment.traffic-layer.save` | camelCase (`bucketId`, `layerName`, …) |
29
+
30
+ Before composing `--req`:
31
+
32
+ 1. Read `data.guide.required_fields` / `mode_rules` for **what** is required (names there may
33
+ already be camelCase).
34
+ 2. Treat `example_args.req` as structure-only placeholders; **rename keys to camelCase**.
35
+ 3. Prefer `ae-cli capability inspect <final-save-capability-id>` `input_schema.properties.req`
36
+ when unsure.
37
+ 4. Then run `experiment save validate` and the final `experiment … save`.
38
+
39
+ Response shape: `data.guide`.
@@ -16,6 +16,12 @@ Flags:
16
16
  - Capability input uses outer `project_id`; nested `req` fields remain native camelCase. Hermes overwrites `req.projectId` with the outer project ID.
17
17
  - Never call this with `req=null`, `req={}`, or a modify payload containing only `expId`; those are terminal validation failures.
18
18
  - On `valid=false`, do not retry the same payload. Fix the reported field(s) or ask the user for missing input.
19
+ - **Do not** paste `save build-guide` / `save validate` `example_args.req` keys into `--req`.
20
+ Those responses snake_case nested placeholders (`exp_name`). Final save requires camelCase
21
+ (`expName`, `expSupposition`, `trafficLayerId`, `featureKeyList`, `metrics[].metricId`, …).
22
+ If unsure, run `ae-cli capability inspect experiment.experiment.save` and copy
23
+ `input_schema.properties.req` field names. `save validate` may return `valid: true` for
24
+ snake_case `req` and still fail here with `unknown field …`.
19
25
 
20
26
  Response shape is `data.result`. Object keys inside the result are recursively snake_case. A create commonly returns the new experiment ID as `data.result`; a patch commonly returns `true`.
21
27
 
@@ -26,12 +32,17 @@ Nested payload fields must match the server DTO types, not just the visible CLI
26
32
  | Field | Correct shape | Incorrect shape |
27
33
  | --- | --- | --- |
28
34
  | `featureKeyList` | `["payment_color"]` | `[{"featureKey":"payment_color"}]` |
35
+ | `allocation` | integer (e.g. `20`) | `20.5`, `33.33` |
36
+ | `groups[].allocation` | integer; all groups sum to `100` (e.g. `34+33+33`) | `33.33`, or sum `99`/`101` |
29
37
  | `groups[].expGroupValue` | `"[\"green\"]"` | `["green"]` |
30
38
  | `metrics` | `[{"metricId":"payment","metricRole":"primary"}]` | `["payment"]` |
31
39
 
32
40
  - `featureKeyList` is an array of Feature key strings, not Feature objects. For feature experiments, pass one Feature key string.
41
+ - `allocation` (experiment-level) and `groups[].allocation` are validated at the CLI interface: **integers only, decimals rejected** (for example `33.33` fails before save).
42
+ - `groups[].allocation` rule: each value must be an **integer**, and the **sum of all group allocations must equal `100` exactly** (for example `34 + 33 + 33 = 100`, not `33 + 33 + 33 = 99` and not decimal thirds).
33
43
  - `groups[].expGroupValue` is a JSON-encoded string of a string array. Pass a string whose content is a JSON array, not a native JSON array.
34
44
  - `metrics` is an array of metric binding objects. Each object contains `metricId` and `metricRole`.
45
+ - Every `metricId` must come from `experiment metric list` for the same project. If save returns `error_code: METRIC_NOT_FOUND`, create the metric with `experiment metric save`, verify it, and then retry the experiment save.
35
46
 
36
47
  ## Modes
37
48
 
@@ -88,12 +99,44 @@ ae-cli experiment experiment save --project-id 1 --req '{"expId":"exp_123","allo
88
99
 
89
100
  - `isExpSharing=1` uses a shared traffic layer from `experiment traffic-layer list`; pick a `trafficLayerId` whose available idle traffic can cover `allocation`.
90
101
  - `isExpSharing=0` uses exclusive traffic with `bucketId`; select the bucket with `experiment bucket list`.
91
- - `allocation` is optional during draft construction, but before readiness it must be greater than `0` and no more than `100`.
102
+ - `allocation` (experiment-level) is the experiment's share of the traffic layer. It is optional during draft construction, but before readiness it must be greater than `0` and no more than `100`. **Integer only** (for example `20`); decimals such as `20.5` are rejected at the CLI interface.
103
+ - `groups[].allocation` (group-level): **integer only; sum must equal `100` exactly**. Example for 3 groups: `34 + 33 + 33 = 100`. Decimals such as `33.33` are rejected at the CLI interface before save.
92
104
  - `expCycle.cycleType` can be `day` or `sample`; when `cycleType=day`, `dayNum` is `1..90`. Blank cycle defaults to day + 30.
93
- - Before readiness, `groups` must be non-empty, contain exactly one control group, total allocation must equal `100`, and each `expGroupValue` must be a non-empty JSON string array.
105
+ - Before readiness, `groups` must be non-empty, contain exactly one control group (`isControl=1`), group allocations must sum to exactly `100`, and each `expGroupValue` must be a non-empty JSON string array.
94
106
  - Feature experiments must bind `featureKeyList` before readiness. `featureKeyList` contains Feature key strings, not Feature objects. The MCP currently supports one `featureKey` for feature experiments.
95
107
  - Metrics use `metricRole=primary|secondary|guardrail|observation`; before readiness at least one primary metric is required.
96
108
  - `targeting` replaces the saved targeting object when provided.
109
+ - Custom audience QP must be supplied as the semantic object
110
+ `targeting.definitionRequest`. Do not submit the internal `targeting.targetConfig`
111
+ JSON or any `Cxx`/`Axxx` code. Resolve event and property names with Analysis
112
+ metadata first.
113
+
114
+ Semantic audience example:
115
+
116
+ ```json
117
+ {
118
+ "targeting": {
119
+ "definitionRequest": {
120
+ "type": "condition",
121
+ "conditions": {
122
+ "relation": "and",
123
+ "items": [
124
+ {"type": "user", "field": "country", "operator": "eq", "values": ["CN"]},
125
+ {
126
+ "type": "event",
127
+ "event": "purchase",
128
+ "operator": "gte",
129
+ "value": 2,
130
+ "aggregation": "sum",
131
+ "property": "amount",
132
+ "time_range": {"mode": "recent", "unit": "day", "value": 7}
133
+ }
134
+ ]
135
+ }
136
+ }
137
+ }
138
+ }
139
+ ```
97
140
 
98
141
  ## Payload Examples
99
142
 
@@ -103,12 +146,18 @@ Patch a Feature binding. `featureKeyList` is a string array:
103
146
  ae-cli experiment experiment save --project-id 2 --req '{"expId":"e024","featureKeyList":["payment_color"]}'
104
147
  ```
105
148
 
106
- Patch groups. `expGroupValue` is a JSON-encoded string, not a native array:
149
+ Patch groups. `expGroupValue` is a JSON-encoded string, not a native array. `groups[].allocation` must be integers that sum to exactly `100`:
107
150
 
108
151
  ```bash
109
152
  ae-cli experiment experiment save --project-id 2 --req '{"expId":"e024","groups":[{"expGroupName":"control","isControl":1,"allocation":50,"expGroupValue":"[\"green\"]"},{"expGroupName":"variant","isControl":0,"allocation":50,"expGroupValue":"[\"red\"]"}]}'
110
153
  ```
111
154
 
155
+ Three-group even split example:
156
+
157
+ ```bash
158
+ ae-cli experiment experiment save --project-id 2 --req '{"expId":"e024","groups":[{"expGroupName":"control","isControl":1,"allocation":34,"expGroupValue":"[\"A\"]"},{"expGroupName":"variant_b","isControl":0,"allocation":33,"expGroupValue":"[\"B\"]"},{"expGroupName":"variant_c","isControl":0,"allocation":33,"expGroupValue":"[\"C\"]"}]}'
159
+ ```
160
+
112
161
  Patch metrics. `metrics` is an object array:
113
162
 
114
163
  ```bash
@@ -122,6 +171,7 @@ ae-cli experiment experiment save --project-id 2 --req '{"expId":"e024","metrics
122
171
  If execution reports a DTO type mismatch after a clean dry-run, inspect nested field types first:
123
172
 
124
173
  - `featureKeyList` must be a string array.
174
+ - `groups[].allocation` must be an integer, and all group allocations must sum to exactly `100`.
125
175
  - `groups[].expGroupValue` must be a JSON-encoded string.
126
176
  - `metrics` must be an object array with `metricId` and `metricRole`.
127
177
 
@@ -8,6 +8,72 @@ ae-cli experiment metric save --project-id <id> --req '<json>'
8
8
 
9
9
  Flags:
10
10
  - `--project-id`, `-p`: Project ID.
11
- - `--req`: Metric save request JSON object.
11
+ - `--req`: Metric save request JSON object (**camelCase** keys such as `metricId`, `metricDefinition`).
12
12
 
13
13
  Create mode requires metric identifiers and metric configuration. Modify mode uses `update=true`.
14
+
15
+ Do not paste `save build-guide` / `save validate` `example_args.req` keys (`metric_id`, …) into
16
+ `--req`. Those responses snake_case nested placeholders; final save requires camelCase.
17
+ See [`save_build_guide.md`](save_build_guide.md) / [`save_validate.md`](save_validate.md).
18
+
19
+ ## Semantic Metric Contract
20
+
21
+ - Supply metric QP as `req.metricDefinition`.
22
+ - Never submit internal `metricConfig`, `calcType`, or an `Axxx` calculation code.
23
+ - Experiment metrics currently accept event definitions only.
24
+ - Supported aggregations:
25
+ - Event-count (no property): `total_count`, `user_count`, `active_days`
26
+ - Property-based (**`property` REQUIRED**): `sum`, `avg`, `max`, `distinct_count`
27
+
28
+ ### Property rule (mandatory)
29
+
30
+ When `aggregation` is `sum`, `avg`, `max`, or `distinct_count`:
31
+
32
+ 1. Resolve the event's available properties with Analysis metadata first
33
+ (`ae-cli analysis-meta property list` / `get` for that event).
34
+ 2. Pass one concrete available property name in `metricDefinition.property`.
35
+ 3. Do **not** invent placeholder metrics without a property (for example
36
+ `metric_avg_no_property_*`). Hermes rejects property aggregations with a blank
37
+ or missing `property`.
38
+
39
+ When `aggregation` is `total_count`, `user_count`, or `active_days`, omit `property`.
40
+
41
+ ### Correct example (avg with property)
42
+
43
+ ```bash
44
+ ae-cli experiment metric save --project-id 1 --req '{
45
+ "metricId":"startup_style_payment_avg_20260729",
46
+ "metricName":"Startup style payment avg",
47
+ "createType":"event",
48
+ "goalDirection":"up",
49
+ "metricDesc":"Average payment amount",
50
+ "metricDefinition":{
51
+ "type":"event",
52
+ "event":"payment",
53
+ "aggregation":"avg",
54
+ "property":"amount"
55
+ }
56
+ }'
57
+ ```
58
+
59
+ ### Wrong example (avg without property — rejected)
60
+
61
+ ```json
62
+ {
63
+ "metricId": "metric_avg_no_property_actual_20260729_144230",
64
+ "metricDefinition": {
65
+ "type": "event",
66
+ "event": "payment",
67
+ "aggregation": "avg"
68
+ }
69
+ }
70
+ ```
71
+
72
+ ### Event-count example (no property)
73
+
74
+ ```bash
75
+ ae-cli experiment metric save --project-id 1 --req '{"metricId":"purchase_users","metricName":"Purchase users","createType":"event","goalDirection":"up","metricDesc":"Unique purchasers","metricDefinition":{"type":"event","event":"purchase","aggregation":"user_count"}}'
76
+ ```
77
+
78
+ Filters use the semantic `filters` tree with `relation=and|or` and items containing
79
+ `field`, `operator`, and `values`.
@@ -8,6 +8,9 @@ ae-cli capability run experiment.experiment.save-submit --input '{"project_id":1
8
8
 
9
9
  Input fields: `project_id` and `req`. The outer input is snake_case; fields inside `req` keep the native camelCase DTO shape.
10
10
 
11
+ Custom audiences use semantic `req.targeting.definitionRequest`. Never pass the
12
+ internal `targetConfig` field or hand-write `Cxx`/`Axxx` codes.
13
+
11
14
  Response shape: `data.result`, with object keys recursively converted to snake_case.
12
15
 
13
16
  Prefer `experiment experiment save` for progressive draft construction.
@@ -0,0 +1,33 @@
1
+ # experiment save validate
2
+
3
+ Dry-run helper for save payloads. Does **not** persist data.
4
+
5
+ ```bash
6
+ ae-cli experiment save validate --project-id <id> --operation-mode save_experiment --req '{"expName":"Demo"}'
7
+ ```
8
+
9
+ Flags:
10
+ - `--project-id`, `-p`: Project ID.
11
+ - `--operation-mode`: `save_feature`, `save_traffic_layer`, `save_experiment`, or `save_metric`.
12
+ - `--req`: Candidate save request object. **Must use native camelCase DTO keys.**
13
+
14
+ ## CRITICAL — `valid: true` is not a save schema pass
15
+
16
+ `experiment.save.validate` checks operation-mode / outer helper contract. It does **not**
17
+ fully enforce the final save capability `input_schema`.
18
+
19
+ Consequences:
20
+
21
+ - `--req '{"exp_name":"Demo"}'` can return `valid: true`.
22
+ - The same payload fails on `experiment experiment save` with `unknown field exp_name`.
23
+
24
+ Rules:
25
+
26
+ 1. Never submit snake_case DTO keys in `--req` (`exp_name`, `metric_id`, `feature_key`, …).
27
+ 2. Do not trust `data.validation.example_args.req` key casing; rebuild with camelCase.
28
+ 3. After `valid: true`, still use camelCase and prefer
29
+ `ae-cli … save --dry-run` / `capability inspect` before a real write.
30
+ 4. On final save `INVALID_CAPABILITY_INPUT` / `unknown field`, fix casing — do not widen
31
+ the payload with more snake_case keys.
32
+
33
+ Response shape: `data.validation`.