@thinkingai/ae-cli 6.1.11 → 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 (27) hide show
  1. package/dist/{capability-TPORIKRQ.js → capability-DRLGDVS4.js} +5 -2
  2. package/dist/{capability-VQNC5CF7.js → capability-P6GK3AQH.js} +5 -2
  3. package/dist/index.js +3 -3
  4. package/dist/{te-engage-FMYAYCNV.js → te-engage-L72HWRGO.js} +396 -26
  5. package/dist/{te-engage-F7V55KVW.js → te-engage-QWM4GFS7.js} +396 -26
  6. package/dist/{te-experiment-UPDMHCAJ.js → te-experiment-2T2HEZML.js} +109 -3
  7. package/dist/{te-experiment-JWXOYJ3W.js → te-experiment-PVEY7AEZ.js} +109 -3
  8. package/package.json +2 -2
  9. package/skills/ae-engage/SKILL.md +12 -2
  10. package/skills/ae-engage/references/activity-data-detail.md +61 -0
  11. package/skills/ae-engage/references/build-task-save-guide.md +25 -1
  12. package/skills/ae-engage/references/common-metric.md +45 -0
  13. package/skills/ae-engage/references/preset-event.md +2 -0
  14. package/skills/ae-engage/references/save-flow.md +14 -0
  15. package/skills/ae-engage/references/save-task.md +35 -0
  16. package/skills/ae-engage/references/scene-strategy-audience.md +12 -7
  17. package/skills/ae-experiment/SKILL.md +17 -4
  18. package/skills/ae-experiment/references/delete_metric.md +2 -0
  19. package/skills/ae-experiment/references/query_experiment_metric_trend.md +5 -5
  20. package/skills/ae-experiment/references/query_experiment_report_summary.md +4 -3
  21. package/skills/ae-experiment/references/query_experiment_sample_size_report.md +6 -5
  22. package/skills/ae-experiment/references/save_build_guide.md +39 -0
  23. package/skills/ae-experiment/references/save_experiment.md +7 -0
  24. package/skills/ae-experiment/references/save_metric.md +5 -1
  25. package/skills/ae-experiment/references/save_validate.md +33 -0
  26. package/skills/ae-experiment-design/references/platform-operations.md +9 -3
  27. package/skills/ae-experiment-insight/references/platform-operations.md +9 -3
@@ -37,6 +37,9 @@ function readRequiredStringArray(ctx, name) {
37
37
  function addOptionalString(input, name, value) {
38
38
  if (value !== "") input[name] = value;
39
39
  }
40
+ function addOptionalBoolean(input, ctx, flagName, fieldName) {
41
+ if (ctx.str(flagName) !== "") input[fieldName] = ctx.bool(flagName);
42
+ }
40
43
 
41
44
  // src/commands/te-experiment/bucket/list.ts
42
45
  var bucketList = createExperimentCapabilityCommand({
@@ -481,7 +484,7 @@ var saveBuildGuide = createExperimentCapabilityCommand({
481
484
  resource: "save",
482
485
  command: "build-guide",
483
486
  capabilityId: "experiment.save.build-guide",
484
- description: "Build a read-only save guide for feature, traffic layer, experiment, or metric saves.",
487
+ description: "Build a read-only save guide for feature, traffic layer, experiment, or metric saves. WARNING: data.guide.example_args.req keys are recursively snake_cased for display; do not copy them into --req. Final save DTOs require camelCase (e.g. expName). Prefer capability inspect <final-save-id> input_schema.properties.req.",
485
488
  flags: [
486
489
  { name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
487
490
  {
@@ -509,7 +512,7 @@ var saveValidate = createExperimentCapabilityCommand({
509
512
  resource: "save",
510
513
  command: "validate",
511
514
  capabilityId: "experiment.save.validate",
512
- description: "Dry-run validation for feature, traffic layer, experiment, or metric save requests.",
515
+ description: "Dry-run validation for feature, traffic layer, experiment, or metric save requests. WARNING: valid=true is not a final-save schema pass; snake_case req keys (e.g. exp_name) can still fail on experiment \u2026 save. Always pass camelCase --req. Do not copy example_args.req key casing from this response.",
513
516
  flags: [
514
517
  { name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
515
518
  {
@@ -518,7 +521,12 @@ var saveValidate = createExperimentCapabilityCommand({
518
521
  required: true,
519
522
  desc: "Save operation mode: save_feature, save_traffic_layer, save_experiment, or save_metric."
520
523
  },
521
- { name: "req", type: "json", required: true, desc: "Candidate camelCase save request object." }
524
+ {
525
+ name: "req",
526
+ type: "json",
527
+ required: true,
528
+ desc: "Candidate camelCase save request object (expName/metricId/\u2026). Never use snake_case DTO keys."
529
+ }
522
530
  ],
523
531
  risk: "read",
524
532
  validate: (ctx) => {
@@ -535,6 +543,98 @@ var saveValidate = createExperimentCapabilityCommand({
535
543
  })
536
544
  });
537
545
 
546
+ // src/commands/te-experiment/report/metric-trend.ts
547
+ var reportMetricTrend = createExperimentCapabilityCommand({
548
+ resource: "report",
549
+ command: "metric-trend",
550
+ capabilityId: "experiment.report.metric-trend",
551
+ description: "Query an experiment metric trend report for a date range.",
552
+ flags: [
553
+ { name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
554
+ { name: "exp-id", type: "string", required: true, desc: "Experiment ID." },
555
+ { name: "metric-id", type: "string", required: true, desc: "Metric ID." },
556
+ { name: "start-time", type: "string", required: true, desc: "Start date in yyyy-MM-dd format." },
557
+ { name: "end-time", type: "string", required: true, desc: "End date in yyyy-MM-dd format." },
558
+ {
559
+ name: "request-id",
560
+ type: "string",
561
+ required: false,
562
+ desc: "Optional caller-supplied cli_<32 lowercase hex> lifecycle ID. ae-cli generates and prints one before dispatch when omitted."
563
+ },
564
+ { name: "force-refresh", type: "boolean", required: false, desc: "Force refresh report data." }
565
+ ],
566
+ risk: "read",
567
+ buildInput: (ctx) => {
568
+ const input = {
569
+ project_id: ctx.num("project-id"),
570
+ exp_id: ctx.str("exp-id"),
571
+ metric_id: ctx.str("metric-id"),
572
+ start_time: ctx.str("start-time"),
573
+ end_time: ctx.str("end-time")
574
+ };
575
+ addOptionalString(input, "request_id", ctx.str("request-id"));
576
+ addOptionalBoolean(input, ctx, "force-refresh", "force_refresh");
577
+ return input;
578
+ }
579
+ });
580
+
581
+ // src/commands/te-experiment/report/sample-size.ts
582
+ var reportSampleSize = createExperimentCapabilityCommand({
583
+ resource: "report",
584
+ command: "sample-size",
585
+ capabilityId: "experiment.report.sample-size",
586
+ description: "Query an experiment sample-size report for a date range.",
587
+ flags: [
588
+ { name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
589
+ { name: "exp-id", type: "string", required: true, desc: "Experiment ID." },
590
+ { name: "start-time", type: "string", required: true, desc: "Start date in yyyy-MM-dd format." },
591
+ { name: "end-time", type: "string", required: true, desc: "End date in yyyy-MM-dd format." },
592
+ {
593
+ name: "request-id",
594
+ type: "string",
595
+ required: false,
596
+ desc: "Optional caller-supplied cli_<32 lowercase hex> lifecycle ID. ae-cli generates and prints one before dispatch when omitted."
597
+ },
598
+ { name: "force-refresh", type: "boolean", required: false, desc: "Force refresh report data." },
599
+ { name: "by-hour", type: "boolean", required: false, desc: "Break results down by hour." }
600
+ ],
601
+ risk: "read",
602
+ buildInput: (ctx) => {
603
+ const input = {
604
+ project_id: ctx.num("project-id"),
605
+ exp_id: ctx.str("exp-id"),
606
+ start_time: ctx.str("start-time"),
607
+ end_time: ctx.str("end-time")
608
+ };
609
+ addOptionalString(input, "request_id", ctx.str("request-id"));
610
+ addOptionalBoolean(input, ctx, "force-refresh", "force_refresh");
611
+ addOptionalBoolean(input, ctx, "by-hour", "by_hour");
612
+ return input;
613
+ }
614
+ });
615
+
616
+ // src/commands/te-experiment/report/summary.ts
617
+ var reportSummary = createExperimentCapabilityCommand({
618
+ resource: "report",
619
+ command: "summary",
620
+ capabilityId: "experiment.report.summary",
621
+ description: "Query an experiment report summary.",
622
+ flags: [
623
+ { name: "project-id", type: "number", required: true, alias: "p", desc: "Numeric project ID." },
624
+ { name: "exp-id", type: "string", required: true, desc: "Experiment ID." },
625
+ { name: "force-refresh", type: "boolean", required: false, desc: "Force refresh report data." }
626
+ ],
627
+ risk: "read",
628
+ buildInput: (ctx) => {
629
+ const input = {
630
+ project_id: ctx.num("project-id"),
631
+ exp_id: ctx.str("exp-id")
632
+ };
633
+ addOptionalBoolean(input, ctx, "force-refresh", "force_refresh");
634
+ return input;
635
+ }
636
+ });
637
+
538
638
  // src/commands/te-experiment/traffic-layer/batch-delete.ts
539
639
  var trafficLayerBatchDelete = createExperimentCapabilityCommand({
540
640
  resource: "traffic-layer",
@@ -616,6 +716,9 @@ var commands = [
616
716
  trafficLayerGet,
617
717
  trafficLayerList,
618
718
  trafficLayerBatchDelete,
719
+ reportSummary,
720
+ reportSampleSize,
721
+ reportMetricTrend,
619
722
  metricSave,
620
723
  metricGet,
621
724
  metricList,
@@ -654,6 +757,9 @@ export {
654
757
  metricList,
655
758
  metricSave,
656
759
  operationLogQuery,
760
+ reportMetricTrend,
761
+ reportSampleSize,
762
+ reportSummary,
657
763
  saveBuildGuide,
658
764
  saveValidate,
659
765
  trafficLayerBatchDelete,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thinkingai/ae-cli",
3
- "version": "6.1.11",
3
+ "version": "6.1.12",
4
4
  "description": "CLI tool for ThinkingAI (AE) analytics platform",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,7 +34,7 @@
34
34
  "verify:metadata-capability": "npx tsx test/metadata-capability-commands.test.mjs",
35
35
  "verify:community-capability": "node test/community-capability-routing.test.mjs",
36
36
  "verify:community-report": "npx tsx tests/community-report-standard-v5.test.ts && npx tsx tests/community-report-client.test.ts && npx tsx tests/community-report-framework.test.ts && npx tsx tests/community-data-report-command.test.ts && node test/community-data-report-skill.test.mjs",
37
- "verify:engage-capability": "tsx test/engage/engage-capability-command.test.mjs && node test/engage/engage-skill-capability.test.mjs",
37
+ "verify:engage-capability": "tsx test/engage/engage-capability-command.test.mjs && tsx test/engage/semantic-qp-validation.test.mjs && node test/engage/engage-skill-capability.test.mjs",
38
38
  "verify:retired-analysis-commands": "node --test test/retired-analysis-commands.test.mjs",
39
39
  "verify:analysis-meta-tools": "node scripts/verify-te-meta-tools.mjs",
40
40
  "verify:analysis-common-tools": "node scripts/verify-te-common-tools.mjs",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ae-engage
3
3
  version: 1.0.0
4
- description: "AE Engage capability gateway: config center, flows, push/config channels, strategies, templates, and task management. Trigger words: config center, scene config, push channel, config channel, operation strategy, operation task, template, config item, Engage, Hermes, engage-scene, engage-setting, engage-flow, engage-task."
4
+ description: "AE Engage capability gateway: config center, flows, push/config channels, strategies, templates, task management, and operation activities. Trigger words: config center, scene config, push channel, config channel, operation strategy, operation task, operation activity, template, config item, Engage, Hermes, engage-scene, engage-setting, engage-flow, engage-task, engage-activity."
5
5
  ---
6
6
 
7
7
  # ae-engage
@@ -56,6 +56,7 @@ When the user mentions a product term below (including common Chinese UI labels)
56
56
  | **Config channel** | Config-center Webhook/client config channels (not the same as push channels) | `engage-scene` | `references/scene-config-channel.md` | `channel-mgmt.md` (create/enable-disable/copy/delete workflows). User params in `config.customsParamList` require `columnName` with `user:` prefix (e.g. `user:#account_id`); preflight names with ae-analysis `analysis-meta property list/get`. |
57
57
  | **Operation strategy** | Ops/delivery strategies under a config item | `engage-scene` | `references/scene-strategy.md` | Custom audience: [`scene-strategy-audience.md`](references/scene-strategy-audience.md) — semantic `definitionRequest` (Analysis condition shape); do not pass `targetClusterQp`/`qp`; preflight props (stop + list if missing); template: `scene-template.md` |
58
58
  | **Operation task** | Hermes push/engagement tasks (list, save, lifecycle, reports) | `engage-task` | `references/task-list.md` | `task-detail.md` (get), `save-task.md`, `build-task-save-guide.md`, `task-stats.md`, `task-delete.md`, `push-record-query.md`, `task-data-overview.md`, `task-data-detail.md`, `task-metric-detail.md`, `task-experiment-report.md` |
59
+ | **Operation activity** | Campaign activity management and delivery trends by activity, topic, or standalone task | `engage-activity` | `references/activity-activity.md` | `activity-data-detail.md`, `activity-topic.md`, `activity-task.md`, `activity-approval.md` |
59
60
  | **Template** | Strategy templates under a config item | `engage-scene` | `references/scene-template.md` | `scene-config-param.md` (template fields reference `paramId`); enable via `template update` then `template update-status` before strategy create |
60
61
 
61
62
  **Easy to confuse:**
@@ -75,6 +76,7 @@ Naming boundary:
75
76
 
76
77
  - CLI flags use kebab-case; outer Capability input and all Capability response keys use snake_case.
77
78
  - Nested business DTOs passed through `--req` or `--payload` keep their documented native camelCase fields. Do not mechanically convert those nested DTO keys to snake_case.
79
+ - Semantic audience, event, trigger, completion, and metric definitions are closed contracts. The CLI rejects malformed or unknown semantic fields locally; `--validate` applies the same precise Hermes capability schema without writing.
78
80
  - Successful migrated commands return their business payload under `data`; read the matching reference's Response shape before selecting fields.
79
81
 
80
82
  ## JSON Parameter Format
@@ -375,6 +377,9 @@ ae-cli engage-setting channel list --project-id <projectId>
375
377
  5. `engage-flow flow save` is **operation-based** (protocol v2). The `--req` object must carry an `operation` of `build`, `preview`, or `commit`. Do **not** use the old `nodeList` / `edgeList` field names — use `nodes` / `edges` with `operation=build`. A legacy `nodeList`/`edgeList` payload (or a missing `operation`) is rejected with `Unsupported save_flow operation: null`.
376
378
  6. Run the lifecycle: `build` (returns `data.result.status = ready_to_preview` or `need_input`) → resolve any `data.result.next_slot` → `preview` (re-issues response fields `data.result.draft_version` + `data.result.confirm_token`) → `commit` (maps those values to request fields `draftVersion` + `confirmToken`) → reads the final ID from `data.result.result.flow_uuid`.
377
379
  7. `nodes[].config` / `edges[].config` may be a JSON object or a JSON string. Custom audience nodes and branches use semantic `targetDefinitionRequest`; Hermes compiles it to the node's stored execution format.
380
+ Never send `targetClusterQp`. Each audience `event` and `behavior_sequence` must include
381
+ its own `time_range`; Flow entry dates do not replace that range. Use only properties that
382
+ resolve through the Flow editor's current project, timezone, and user-entity metadata scope.
378
383
  8. You must self-check before previewing/committing:
379
384
  - There is exactly one entry node
380
385
  - There is at least one `exit_flow`
@@ -456,6 +461,7 @@ More detailed single-command guidance is available in the business-oriented `ref
456
461
  - `references/config-item-analysis-report.md` (`engage-scene.report.config-item-analysis`, L3)
457
462
  - `references/config-item-strategy-comparison.md` (`engage-scene.report.strategy-comparison`, L3)
458
463
  - `references/activity-activity.md` (`engage-activity.activity.{create,update,delete,list,get,pause,end,stats,info-list}`)
464
+ - `references/activity-data-detail.md` (`engage-activity.activity-data.detail`, L3)
459
465
  - `references/activity-approval.md` (`engage-activity.approval.{submit,approve,reject,cancel}`)
460
466
  - `references/activity-topic.md` (`engage-activity.topic.{create,update,remove-task,delete,get,copy}`)
461
467
  - `references/activity-activity-type.md` (`engage-activity.activity-type.{list,batch-add,update,batch-delete}`)
@@ -533,7 +539,9 @@ For task draft creation or update, use this workflow:
533
539
  `channelType`, `triggerType`, and `eventTriggerType` to `build-save-guide`, then use its
534
540
  type-specific semantic event shape. Accumulated events are aggregate conditions, continuous
535
541
  events use count/eq with a value of at least 2, ordered events use sequence-step envelopes,
536
- and every-completion events use count/eq/1. Never construct persisted QP fields.
542
+ and every-completion events use count/eq/1. Completion target and experiment main-goal event
543
+ filters must not use properties whose metadata `select_type` is `datetime`. Never construct
544
+ persisted QP fields.
537
545
  4. `ae-cli engage-task task save --project-id <projectId> --req '{...}'`
538
546
  5. `ae-cli engage-task task submit-approval --project-id <projectId> --task-id <taskId>`
539
547
 
@@ -551,3 +559,5 @@ Audience creation is not a fixed preflight step. For custom task audiences, use
551
559
  `definition_request`. `clientConfig.clientQp` is server-authored and must be omitted from
552
560
  Capability requests; partial updates preserve existing server state. Do not assemble raw QP
553
561
  manually.
562
+ For a `behavior_sequence`, omit second-step `relative_to_first` or set it to `false`; reserve
563
+ `true` for step 3 or later when the window is measured from step 1.
@@ -0,0 +1,61 @@
1
+ # engage-activity.activity-data.detail
2
+
3
+ Query activity delivery trends through the L3 Capability Gateway.
4
+
5
+ Mapped command:
6
+
7
+ ```bash
8
+ ae-cli capability run engage-activity.activity-data.detail --input '<json>'
9
+ ```
10
+
11
+ ## Input
12
+
13
+ Required fields:
14
+
15
+ - `project_id`: project that owns the activity.
16
+ - `activity_id`: activity to query.
17
+ - `start_time`: inclusive start date in `yyyy-MM-dd` format.
18
+ - `end_time`: inclusive end date in `yyyy-MM-dd` format.
19
+
20
+ Optional fields:
21
+
22
+ - `time_particle_size`: `T1` (day), `T2` (week), `T3` (month), or `T5` (total). Defaults to `T1`.
23
+ - `source`: `activity` or `topic_and_task`. Defaults to `activity`.
24
+ - `topic_id_list`: selected topic IDs.
25
+ - `task_id_list`: selected standalone task IDs.
26
+ - `request_id`: cancelable query ID. A UUID is generated when omitted.
27
+
28
+ When `source=topic_and_task` and both ID lists are omitted or empty, the capability selects every topic and standalone task in the activity. When either list is provided, only the explicitly selected resources are queried. Selected resources must belong to the activity and project.
29
+
30
+ ## Recent seven-day topic trend
31
+
32
+ Use an inclusive seven-day range, `T1`, and `topic_and_task`:
33
+
34
+ ```bash
35
+ ae-cli capability run engage-activity.activity-data.detail --input \
36
+ '{"project_id":1,"activity_id":"act-1","start_time":"2026-07-25","end_time":"2026-07-31","time_particle_size":"T1","source":"topic_and_task","request_id":"<uuid>"}'
37
+ ```
38
+
39
+ The report exposes the existing activity-page indicators:
40
+
41
+ - `plan`: planned trigger users.
42
+ - `actualTrigger`: actual push users.
43
+ - `trigger`: successful push users.
44
+
45
+ It does not expose `view` (actual arrival) or `click`. Use the returned header values instead of treating `trigger` as an actual-arrival metric.
46
+
47
+ ## Output
48
+
49
+ Successful output contains:
50
+
51
+ - `data.request_id`: the request ID used by the query.
52
+ - `data.result_generate_time`: ISO-8601 generation time.
53
+ - `data.data.x`: summary/date axis.
54
+ - `data.data.headers`: indicator keys.
55
+ - `data.data.total`: activity totals aligned with `headers`.
56
+ - `data.data.values`: topic or standalone-task rows aligned with `x` and `headers`.
57
+ - `data.data.topic_list`: selected source IDs and names using `topic_id` and `topic_name`.
58
+
59
+ The first `x`/`total` row is the overall summary. For non-total time grains, subsequent rows are the requested date buckets.
60
+
61
+ Use `engage-setting.query.cancel` with the same `request_id` to cancel a running query.
@@ -23,7 +23,18 @@ Use this sequence when creating or updating a task draft:
23
23
  Build event primitives from `ae-analysis` user-cluster / audience models. Hermes wraps those
24
24
  primitives in the task-specific envelope selected by `channelType`, `triggerType`, and
25
25
  `eventTriggerType`, then validates the final persisted QP before save. Never construct persisted
26
- execution QP.
26
+ execution QP. Follow the documented closed semantic shapes: unknown fields are rejected, and a
27
+ property `field` may be a technical-name string or a `{name,type}` reference.
28
+ Every custom-audience `event` and `behavior_sequence` requires its own `time_range`. For
29
+ `recent` and `previous`, use a positive integer `value` and only `unit=day`; `custom` requires
30
+ both `start_time` and `end_time`.
31
+
32
+ Custom audiences support `behavior_sequence` nodes, including sequence/step windows, step
33
+ filters, `completed`, and `relative_to_first`. A task `get` may return top-level `compound`
34
+ nodes when the stored member-group, event-group, and outer relations differ. Preserve those
35
+ compounds when reusing `definition_request`; flattening them changes audience semantics.
36
+ For the second sequence step, omit `relative_to_first` or set it to `false`; use `true` only
37
+ from the third step onward when its window must be measured from step 1.
27
38
 
28
39
  For existing-cluster audiences (`targetClusterType=2`), you may copy server-authored definitions via:
29
40
 
@@ -266,6 +277,19 @@ The guide treats the A rule as a discriminated envelope:
266
277
  Do not copy the accumulated example and only change `eventTriggerType`. Hermes rejects a final QP
267
278
  whose event structure does not match its envelope.
268
279
 
280
+ #### `fieldRules.blocks.controlConfig.completionIndicatorDef.filterPropertySelectTypes`
281
+
282
+ Treat this as the source of truth for completion target and experiment main-goal event-filter
283
+ property types:
284
+
285
+ - `allowed` lists the supported metadata `select_type` values.
286
+ - `excluded` lists values that must not be used.
287
+ - `datetime` is excluded because the task completion-indicator editor cannot display it.
288
+
289
+ Apply this rule only to
290
+ `completionIndicatorDef.completionIndicators[].eventDefinition.filters`. Trigger-event filters have
291
+ their own scenario rules and are not subject to this completion-filter restriction.
292
+
269
293
  ### 4.9 `handoff`
270
294
 
271
295
  This is the final section before `save_task`.
@@ -3,6 +3,13 @@
3
3
  > Trigger keywords: common metric, shared metric · Capability ids: `engage-setting.common-metric.{list,get,create,update,delete}` · Permission: `opsEditSetting`.
4
4
 
5
5
  Common metric capabilities expose semantic event/formula definitions. Do not submit or reuse `metric_qp`, `Axxx`, display metadata, formula dependency internals, or property metadata.
6
+ Metric definitions and formula dependencies reject unknown fields. Event filter `field` accepts
7
+ either a technical-name string or `{"name":"...","type":"event_property"}`.
8
+
9
+ When metadata reports an event property as `array_row`, express it as an `object_group` filter
10
+ with `any_satisfy`, `none_satisfy`, or `all_satisfy`; its nested `conditions.items` may reference
11
+ only child properties of that parent. Flat filters on the `array_row` parent are rejected before
12
+ the metric is saved.
6
13
 
7
14
  ## Commands
8
15
 
@@ -39,8 +46,41 @@ ae-cli engage-setting common-metric delete --project-id <project_id> --metric-na
39
46
  }
40
47
  ```
41
48
 
49
+ Object-group filter example:
50
+
51
+ ```json
52
+ {
53
+ "type": "object_group",
54
+ "field": "equipment_list",
55
+ "operator": "any_satisfy",
56
+ "conditions": {
57
+ "relation": "and",
58
+ "items": [
59
+ {
60
+ "field": "equipment_list.item_level",
61
+ "operator": "gte",
62
+ "values": [10]
63
+ }
64
+ ]
65
+ }
66
+ }
67
+ ```
68
+
42
69
  Supported aggregations include `total_count`, `user_count`, `per_user_count`, `sum`, `avg`, `avg_per_user`, `max`, `min`, `distinct_count`, `median`, `percentile`, `variance`, and `stddev`.
43
70
 
71
+ Property aggregations require `property`. `percentile` additionally requires a numeric
72
+ `percentile` greater than `0` and at most `100`:
73
+
74
+ ```json
75
+ {
76
+ "type": "event",
77
+ "event": "purchase",
78
+ "aggregation": "percentile",
79
+ "property": "amount",
80
+ "percentile": 90
81
+ }
82
+ ```
83
+
44
84
  ## Formula metric
45
85
 
46
86
  ```json
@@ -65,6 +105,11 @@ Supported aggregations include `total_count`, `user_count`, `per_user_count`, `s
65
105
  }
66
106
  ```
67
107
 
108
+ Every dependency requires a non-empty, unique `key`, and every key must be used in
109
+ `expression`. Write bare keys only: use `purchases/refunds`, never `purchases.A100/refunds.A100`.
110
+ Aggregation codes are derived from each dependency. Formula dependencies follow the same
111
+ property and percentile requirements as event metrics.
112
+
68
113
  Resolve every event and property through `ae-cli analysis-meta event list` and the corresponding property metadata before writing. `get` and `list` return `metric_definition`, `metric_definition_status`, and an optional unavailable reason. Raw metric QP is hidden.
69
114
 
70
115
  `metric_type=1` remains required for setting-page common metrics. Metric windows remain separate from the semantic definition, and their unit must be `minute` / `hour` / `day`.
@@ -12,6 +12,8 @@ ae-cli engage-setting preset-event update --project-id <project_id> \
12
12
  ```
13
13
 
14
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.
15
17
 
16
18
  List hides the stored event QP and returns each semantic field plus its conversion status:
17
19
 
@@ -177,6 +177,14 @@ ae-cli analysis user-cluster get --project-id <projectId> --cluster-names '["<co
177
177
  ```
178
178
 
179
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
 
@@ -239,6 +247,12 @@ Inside action nodes: `channel_name` → real `channelId`; `content` → `content
239
247
  3. Every path must eventually end at `exit_flow`.
240
248
  4. `config` may be a JSON object or a JSON string. `targetDefinitionRequest` itself is a JSON object.
241
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
 
@@ -120,6 +120,39 @@ Task aggregate and completion event definitions support:
120
120
  - `aggregation`: `count`, `sum`, or `distinct_count`
121
121
  - `operator`: `gt`, `gte`, or `eq`
122
122
 
123
+ Completion target and experiment main-goal event filters must not use properties whose metadata
124
+ `select_type` is `datetime`. The supported filter-property select types are `string`, `number`,
125
+ `bool`, `bool-s`, `date`, `array`, `array_string`, `row`, and `array_row`. This restriction applies
126
+ to `completionIndicatorDef.completionIndicators[].eventDefinition.filters`; it does not apply to
127
+ trigger-event filters.
128
+
129
+ For an event property whose metadata `select_type` is `array_row`, never submit it as a flat
130
+ property filter. Use an object-group filter and place only that parent's child properties inside
131
+ `conditions`:
132
+
133
+ ```json
134
+ {
135
+ "type": "object_group",
136
+ "field": "equipment_list",
137
+ "operator": "any_satisfy",
138
+ "conditions": {
139
+ "relation": "and",
140
+ "items": [
141
+ {
142
+ "field": "equipment_list.item_level",
143
+ "operator": "gte",
144
+ "values": [10]
145
+ }
146
+ ]
147
+ }
148
+ }
149
+ ```
150
+
151
+ Object-group operators are `any_satisfy`, `none_satisfy`, and `all_satisfy`. Resolve the parent
152
+ and child fields from current metadata. Hermes validates the metadata type, child-parent
153
+ relationship, and supported operators before saving, so do not flatten `array_row` or invent child
154
+ field names.
155
+
123
156
  Trigger events have an additional envelope contract selected by `eventTriggerType`. Do not apply
124
157
  one aggregate event shape to every trigger type. Use the matrix and examples in section 4.4.
125
158
 
@@ -381,6 +414,8 @@ Minimum required field:
381
414
 
382
415
  When the guide points to event-based completion or experiment-driven main-goal rules, build
383
416
  `completionIndicatorDef.completionIndicators[].eventDefinition` from the semantic event contract.
417
+ Read `fieldRules.blocks.controlConfig.completionIndicatorDef.filterPropertySelectTypes` and exclude
418
+ every property type listed under `excluded` before constructing its `filters`.
384
419
 
385
420
  Important constraints that still apply:
386
421
 
@@ -25,19 +25,19 @@ Use the same condition definition accepted by Analysis user-cluster commands:
25
25
  "relation": "and",
26
26
  "items": [
27
27
  {
28
- "type": "user_property",
29
- "property": "vip_level",
28
+ "type": "user",
29
+ "field": "vip_level",
30
30
  "operator": "eq",
31
- "value": "gold"
31
+ "values": ["gold"]
32
32
  },
33
33
  {
34
- "type": "event_behavior",
34
+ "type": "event",
35
35
  "event": "purchase",
36
36
  "aggregation": "count",
37
37
  "operator": "gte",
38
38
  "value": 2,
39
- "time": {
40
- "type": "relative",
39
+ "time_range": {
40
+ "mode": "recent",
41
41
  "unit": "day",
42
42
  "value": 7
43
43
  }
@@ -48,8 +48,13 @@ Use the same condition definition accepted by Analysis user-cluster commands:
48
48
  ```
49
49
 
50
50
  Before writing, resolve real event and property names through Analysis metadata commands. Never invent names or copy internal calculation codes from historical output.
51
+ Use only the documented semantic fields. Unknown fields are rejected; property `field` accepts a
52
+ technical-name string or a `{name,type}` reference.
51
53
 
52
- Nested `and`/`or`, user properties, event behavior, include/exclude existing clusters, relative time, and custom time use the Analysis semantic shape documented by `ae-analysis`.
54
+ Nested `and`/`or`, user properties, event behavior, `behavior_sequence`, include/exclude existing
55
+ clusters, relative time, and custom time use the Analysis semantic shape documented by
56
+ `ae-analysis`. A `get` response may contain top-level `compound` nodes when stored member,
57
+ event, and outer relations differ. Preserve those compounds when updating the strategy.
53
58
 
54
59
  ## Create or update
55
60
 
@@ -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,6 +23,12 @@ 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`.
25
32
  - Audience QP is semantic at the CLI boundary: write `targeting.definitionRequest`; read
26
33
  `targeting.definition_request`. Never generate or submit `targetConfig`.
27
34
  - Metric QP is semantic at the CLI boundary: write `metricDefinition`; read
@@ -52,7 +59,9 @@ Naming and response boundary:
52
59
  4. Check readiness with `experiment experiment ready-check`.
53
60
  5. For a non-mutex traffic layer, run `experiment experiment conflict-check` before submit (needs `feature_key_list` from context or `experiment get`).
54
61
  6. Move status with `experiment experiment manage`.
55
- 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.
56
65
 
57
66
  ## Parameter Conventions
58
67
 
@@ -62,7 +71,7 @@ Naming and response boundary:
62
71
  ae-cli experiment experiment get --project-id 1 --exp-id exp_123
63
72
  ae-cli experiment experiment save --project-id 1 --req '{"expName":"Demo"}' --dry-run
64
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
65
- 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"}'
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
66
75
  ```
67
76
 
68
77
  Optional global parameters work as in other domains: `--host`, `--mcp-url`, `--format`, `--jq`, `--dry-run`, and `--yes`.
@@ -77,6 +86,10 @@ Open the matching file in `references/` before using a command, especially for w
77
86
 
78
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.
79
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
+
80
93
  ### Experiment
81
94
 
82
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`
@@ -87,7 +100,7 @@ When a save command returns `next_tool: experiment.save.build-guide`, call the g
87
100
 
88
101
  ### Reports
89
102
 
90
- `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`
91
104
 
92
105
  ### Metric and Feature
93
106
 
@@ -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.
@@ -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.