@guandata/guanmetric 0.1.18 → 0.1.20
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.
- package/CHANGELOG.md +10 -0
- package/README.md +23 -3
- package/bin/run.js +14 -1
- package/package.json +6 -6
- package/skills/guanmetric/SKILL.md +53 -8
- package/skills/guanmetric/evals/evals.json +117 -0
- package/skills/guanmetric/evals/fixtures/atomic-detail-read-model.json +18 -0
- package/skills/guanmetric/evals/fixtures/confirmed-template-summary.json +12 -0
- package/skills/guanmetric/evals/fixtures/create-result-unknown-state.json +13 -0
- package/skills/guanmetric/evals/forward-eval-2026-09-21.json +62 -0
- package/skills/guanmetric/references/metric-api-contract-examples.json +690 -0
- package/skills/guanmetric/references/metric-api-contract.schema.json +349 -0
- package/skills/guanmetric/references/metric-api-contracts.md +436 -0
- package/skills/guanmetric/references/metric-atomic-mutation.md +11 -0
- package/skills/guanmetric/references/metric-business-dictionary-api-contract-examples.json +53 -0
- package/skills/guanmetric/references/metric-business-dictionary-api-contract.schema.json +26 -0
- package/skills/guanmetric/references/metric-business-dictionary.md +4 -0
- package/skills/guanmetric/references/metric-composite-mutation.md +15 -17
- package/skills/guanmetric/references/metric-derived-mutation.md +14 -16
- package/skills/guanmetric/references/metric-excel-template.md +14 -4
- package/skills/guanmetric/references/metric-flow-generate-example.json +79 -0
- package/skills/guanmetric/references/metric-flow-generate.schema.json +93 -0
- package/skills/guanmetric/references/metric-flow.md +218 -0
- package/skills/guanmetric/references/metric-hierarchy-api-contract-examples.json +171 -0
- package/skills/guanmetric/references/metric-hierarchy-api-contract.schema.json +167 -0
- package/skills/guanmetric/references/metric-hierarchy-api-contracts.md +193 -0
- package/skills/guanmetric/references/metric-mutation.md +13 -9
- package/skills/guanmetric/references/metric-public-dimension-api-contract-examples.json +62 -0
- package/skills/guanmetric/references/metric-public-dimension-api-contract.schema.json +47 -0
- package/skills/guanmetric/references/metric-public-dimension.md +4 -0
- package/skills/guanmetric/references/metric-tree-api-contract-examples.json +277 -0
- package/skills/guanmetric/references/metric-tree-api-contract.schema.json +263 -0
- package/skills/guanmetric/references/metric-tree-api-contracts.md +53 -0
- package/skills/guanmetric/references/metric-tree-mutation.md +31 -3
- package/skills/guanmetric/references/metric-validation-ownership.md +74 -0
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# 衍生指标创建与编辑
|
|
2
2
|
|
|
3
|
+
六种衍生配置的创建请求、真实详情响应和读写映射见 `metric-api-contracts.md`;机器样例见
|
|
4
|
+
`metric-api-contract-examples.json`。
|
|
5
|
+
|
|
3
6
|
衍生指标用于在基础指标之上配置同比/环比、最近 N、累计、期末值、业务限定,或通过组合衍生公式引用多个指标。
|
|
4
7
|
|
|
5
8
|
## 触发场景
|
|
@@ -411,7 +414,7 @@
|
|
|
411
414
|
|
|
412
415
|
## 创建步骤
|
|
413
416
|
|
|
414
|
-
`guanmetric create`
|
|
417
|
+
单个衍生指标使用 `guanmetric derived create`;对话式批量创建或基础指标也在本批创建时,优先按 `metric-flow.md` 使用 `guanmetric flow`。
|
|
415
418
|
|
|
416
419
|
1. 先输出指标创建计划,按 `metric-mutation.md` 的“指标创建计划”要求展示环境、主题、目录、基础指标或组合衍生引用指标、衍生配置、时间维度、格式、业务属性和保存方式。
|
|
417
420
|
2. 用户确认计划后,生成 `/tmp/derived_metric.json`。
|
|
@@ -421,7 +424,8 @@
|
|
|
421
424
|
6. 提交真实创建:
|
|
422
425
|
|
|
423
426
|
```bash
|
|
424
|
-
guanmetric
|
|
427
|
+
guanmetric derived create --file /tmp/derived_metric.json --dry-run
|
|
428
|
+
guanmetric derived create --file /tmp/derived_metric.json
|
|
425
429
|
```
|
|
426
430
|
|
|
427
431
|
7. 响应返回指标 ID 后回读确认。
|
|
@@ -430,26 +434,20 @@ guanmetric fetch POST /api/metric-platform/metrics/derived-metrics --stdin < /tm
|
|
|
430
434
|
|
|
431
435
|
衍生指标没有原子指标的 save-precheck;主要校验基础指标、衍生配置或筛选变化是否影响下游指标/卡片。
|
|
432
436
|
|
|
433
|
-
1.
|
|
434
|
-
|
|
435
|
-
```bash
|
|
436
|
-
guancli metric get <metric_id> --raw
|
|
437
|
-
```
|
|
438
|
-
|
|
439
|
-
2. 基于当前详情生成完整编辑 payload,例如 `/tmp/derived_metric_update.json`。至少包含 `projectId`、`subType`、`name`、`baseMetricId`(普通衍生)、`deriveSetting`、`desc`、`publish`。
|
|
440
|
-
3. 如果修改了 `baseMetricId`、`deriveSetting` 或 `filter`,先调用影响校验:
|
|
437
|
+
1. 准备只包含本次变更字段的 patch,例如 `/tmp/derived_metric_patch.json`;不要复制或回写详情读模型。
|
|
438
|
+
2. 先 dry-run。命令会读取当前详情,把 `baseMetric.id` 映射为 `baseMetricId`,按衍生指标 Update DTO 白名单构造完整写模型并输出影响校验和更新步骤:
|
|
441
439
|
|
|
442
440
|
```bash
|
|
443
|
-
guanmetric
|
|
441
|
+
guanmetric derived edit <metric_id> --file /tmp/derived_metric_patch.json --dry-run
|
|
444
442
|
```
|
|
445
443
|
|
|
446
|
-
|
|
447
|
-
5. 提交真实编辑:
|
|
444
|
+
3. 提交真实编辑。命令自动调用 `validate-update-impact`;存在下游影响时会阻断并返回影响清单,用户确认后才追加 `--confirm`:
|
|
448
445
|
|
|
449
446
|
```bash
|
|
450
|
-
guanmetric
|
|
447
|
+
guanmetric derived edit <metric_id> --file /tmp/derived_metric_patch.json
|
|
448
|
+
guanmetric derived edit <metric_id> --file /tmp/derived_metric_patch.json --confirm
|
|
451
449
|
```
|
|
452
450
|
|
|
453
|
-
|
|
451
|
+
4. 命令保存后自动回读,校验名称、口径、基础指标和 `deriveSetting` 等已提交字段。
|
|
454
452
|
|
|
455
|
-
|
|
453
|
+
编辑命令内部读取后端详情,但只通过白名单生成写模型;`baseMetric`、`creator`、`statisticsData` 等读模型字段绝不能原样提交。
|
|
@@ -102,7 +102,7 @@ guanmetric template normalize <input.xlsx> \
|
|
|
102
102
|
- 指标主题名称找不到时,`问题说明` 要说明:若用户确认使用该名称,创建计划将默认新建该指标主题。
|
|
103
103
|
- `保存至` 找不到时,`问题说明` 要说明:若用户确认使用该路径,创建计划将默认在目标主题下新建该目录。
|
|
104
104
|
- 原始文件没有提供指标目录 ID/路径时,不要写成“目录未找到”;应提示“未提供目录,确认主题后创建计划将默认保存到指标主题根目录”。
|
|
105
|
-
- 后续如果确实需要新建主题/目录,应在所有标准化问题收敛后,由 agent 在创建计划中明确列出将创建的主题/目录,等待用户确认后再执行 `
|
|
105
|
+
- 后续如果确实需要新建主题/目录,应在所有标准化问题收敛后,由 agent 在创建计划中明确列出将创建的主题/目录,等待用户确认后再执行 `guanmetric project create` / `guanmetric directory create`。
|
|
106
106
|
|
|
107
107
|
## 标准模板字段
|
|
108
108
|
|
|
@@ -271,6 +271,8 @@ agent 根据标准模板生成创建 payload 时,必须识别这些成组字
|
|
|
271
271
|
- `公式来源数据集ID` / `公式来源数据集`:token 对应数据集字段、需要先创建或复用基础原子指标时填写。
|
|
272
272
|
- `公式字段映射`:token 对应字段和聚合方式,必须使用 `token=字段,聚合方式` 形式,例如 `repr=repr,SUM; total_buyer=buyer_id,CNT_DISTINCT`。
|
|
273
273
|
|
|
274
|
+
`公式来源数据集` 和 `公式字段映射` 只用于说明如何补建基础原子指标,不会让 Flow 隐式创建模板中不存在的指标。无论 token 是裸写法 `sales` 还是方括号写法 `[sales]`,若只出现在字段映射而没有出现在 `引用指标`,normalize 都会用 `TEMPLATE_INVALID_REFERENCE` 阻断该复合行;先把对应原子指标加入原子模板,再补 `token=本批原子指标名称` 的引用映射。
|
|
275
|
+
|
|
274
276
|
如果 `计算公式` 中存在未用 `[]` 包裹的裸 token,但没有提供 `引用指标` 或 `公式字段映射`,该行必须标记为 `错误`。如果只提供了部分映射,也要在 `问题说明` 中指出缺失的 token。agent 不要猜测 `repr`、`total_buyer` 对应哪个已有指标或字段。
|
|
275
277
|
|
|
276
278
|
## 客户 Excel 语义理解
|
|
@@ -280,7 +282,7 @@ agent 根据标准模板生成创建 payload 时,必须识别这些成组字
|
|
|
280
282
|
- `原子指标模板` 行必须明确 `指标类型=原子指标`,并尽量填写数据集、计算方式、适用维度等原子指标字段。计算方式可以是 `来源字段` + `聚合方式`,也可以是 `字段表达式`,但不能同时填写两种。
|
|
281
283
|
- 各衍生指标模板行必须明确 `指标类型=衍生指标`,并根据用户语义放入对应衍生 sheet;例如同比/环比放入 `同比环比衍生模板`,最近 N 天/周/月放入 `最近N衍生模板`,累计放入 `累计衍生模板`,期末值放入 `期末值衍生模板`,业务筛选限定放入 `业务限定衍生模板`,组合衍生放入 `组合衍生模板`。
|
|
282
284
|
- `复合指标模板` 行必须明确 `指标类型=复合指标`,并尽量填写计算公式、引用指标、公式来源数据集和公式字段映射等复合指标字段。
|
|
283
|
-
- 复合指标计算公式中的 `[指标名]
|
|
285
|
+
- 复合指标计算公式中的 `[指标名]`,以及通过 `引用指标` 映射的裸 token,都必须能对应到已有或本批先创建的原子指标/复合指标,不能对应衍生指标或快捷引用指标。同批模板发现复合公式引用衍生指标时会把该行标为 `错误`;线上已有指标则在创建计划和 `guanmetric fetch` 提交前读取详情核对 `subType`。缺失依赖应按真实语义补到原子指标模板或复合指标模板,不要一律补成原子指标;无法确定建模方式或必要字段时,在 `问题说明` 中列出待确认项。
|
|
284
286
|
- 衍生指标的 `衍生自` 也必须能对应到已有指标或本次将创建的指标。如果 `衍生自` 是本批也要创建的指标,必须在标准模板阶段就把它列入 `原子指标模板` 或 `复合指标模板`;创建计划阶段只核对和排序,不临时新增模板外基础指标。若该基础指标线上不存在且模板中也没有对应行,agent 必须回到模板补充基础指标行;补充所需信息不足时,在基础指标行或衍生指标行的 `问题说明` 中列出缺失的数据集、来源字段、聚合方式、复合公式、引用指标映射、适用维度或时间维度。
|
|
285
287
|
- 客户表中的“表达式”“统计口径”“分子/分母”“达成率”“同比/环比”“最近 N”“累计”“期末值”“业务限定”“维度勾选”等语义,不应靠 CLI 写死列名猜测;agent 应结合整张表和上下文理解后写入标准字段。
|
|
286
288
|
- 标准模板生成后必须检查 `汇总` sheet 的指标总数和衍生指标数,并结合 report.notes 检查是否存在衍生类型缺类。如果业务口径或用户输入中出现明显衍生语义,而对应衍生 sheet 为空,需要回到 `ai_mapped.xlsx` 重做或在交付摘要中明确说明这些语义为什么不创建衍生指标。
|
|
@@ -324,7 +326,15 @@ guanmetric fetch GET /api/metric-attr-config
|
|
|
324
326
|
- 标准化报告中的 `remoteLookups` 用于记录远程查询次数。
|
|
325
327
|
- 对上千行文件,转换阶段的远程请求数应接近环境配置数量,而不是指标行数。
|
|
326
328
|
|
|
327
|
-
|
|
329
|
+
用户确认标准模板且所有真实指标行为“可创建”后,执行:
|
|
330
|
+
|
|
331
|
+
```bash
|
|
332
|
+
guanmetric flow generate --file standard_metrics.xlsx --out metric_flow.json
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
不要再由 Agent 手写 `metric_flow.json`。generate 会解析字段、责任人、业务属性、已有指标和批内依赖,并立即运行只读 plan 校验;解析失败时按返回的 Sheet、行、列诊断修改模板。同一标准模板不能混合“上线”和“草稿”,需要先拆分或统一保存方式。
|
|
336
|
+
|
|
337
|
+
后续批量创建继续遵守:
|
|
328
338
|
|
|
329
339
|
- 先从标准模板收集唯一 `projectId`、`parentDirId`、`dsId`、引用指标名,再批量查询和缓存。
|
|
330
340
|
- 相同数据集 schema 只读取一次。
|
|
@@ -341,7 +351,7 @@ guanmetric fetch GET /api/metric-attr-config
|
|
|
341
351
|
- 自动填充了哪些字段和业务属性。
|
|
342
352
|
- 哪些行可创建、待确认或有错误。
|
|
343
353
|
4. 如果存在 `错误` 或 `待确认` 行,把标准 Excel 返回给用户修改;用户改完再次传回后,重复执行本流程。
|
|
344
|
-
5. 只有当所有行都是 `可创建`
|
|
354
|
+
5. 只有当所有行都是 `可创建` 且用户确认标准 Excel 后,才执行 `guanmetric flow generate` 自动生成并校验指标创建计划。
|
|
345
355
|
6. 用户确认创建计划后,才执行 dry-run/precheck/真实创建。
|
|
346
356
|
|
|
347
357
|
## 示例
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": "1.0",
|
|
3
|
+
"command": "flow.generate",
|
|
4
|
+
"generated": true,
|
|
5
|
+
"output": "metric_flow.json",
|
|
6
|
+
"acceptance": "usable",
|
|
7
|
+
"metricCount": 2,
|
|
8
|
+
"diagnostics": [],
|
|
9
|
+
"plan": {
|
|
10
|
+
"schemaVersion": "1.0",
|
|
11
|
+
"operation": "plan",
|
|
12
|
+
"valid": true,
|
|
13
|
+
"acceptance": {
|
|
14
|
+
"mode": "usable"
|
|
15
|
+
},
|
|
16
|
+
"environment": {
|
|
17
|
+
"profile": "demo",
|
|
18
|
+
"baseUrl": "https://bi.example.com",
|
|
19
|
+
"domain": "example"
|
|
20
|
+
},
|
|
21
|
+
"executionOrder": [
|
|
22
|
+
"metric_001",
|
|
23
|
+
"metric_002"
|
|
24
|
+
],
|
|
25
|
+
"items": [
|
|
26
|
+
{
|
|
27
|
+
"key": "metric_001",
|
|
28
|
+
"subType": "ATOMIC",
|
|
29
|
+
"path": "/api/metric-platform/metrics/atomic-metrics",
|
|
30
|
+
"dependencies": [],
|
|
31
|
+
"body": {
|
|
32
|
+
"projectId": "project_demo",
|
|
33
|
+
"subType": "ATOMIC",
|
|
34
|
+
"dsId": "ds_orders",
|
|
35
|
+
"name": "销售额",
|
|
36
|
+
"fdId": "fd_amount",
|
|
37
|
+
"aggrType": "SUM",
|
|
38
|
+
"applicableDims": [
|
|
39
|
+
"fd_date",
|
|
40
|
+
"fd_region"
|
|
41
|
+
],
|
|
42
|
+
"timeDim": "fd_date",
|
|
43
|
+
"desc": "订单销售额合计",
|
|
44
|
+
"parentDirId": "dir_demo",
|
|
45
|
+
"businessOwner": "user_owner",
|
|
46
|
+
"publish": true
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
"key": "metric_002",
|
|
51
|
+
"subType": "DERIVED",
|
|
52
|
+
"path": "/api/metric-platform/metrics/derived-metrics",
|
|
53
|
+
"dependencies": [
|
|
54
|
+
"metric_001"
|
|
55
|
+
],
|
|
56
|
+
"body": {
|
|
57
|
+
"projectId": "project_demo",
|
|
58
|
+
"subType": "DERIVED",
|
|
59
|
+
"name": "销售额同比",
|
|
60
|
+
"baseMetricId": "${metric:metric_001}",
|
|
61
|
+
"deriveSetting": {
|
|
62
|
+
"deriveType": "ORDINARY",
|
|
63
|
+
"advType": "COMPARATIVE",
|
|
64
|
+
"advValue": {
|
|
65
|
+
"advType": "COMPARATIVE",
|
|
66
|
+
"dateFdId": "fd_date"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"desc": "销售额同比变化",
|
|
70
|
+
"parentDirId": "dir_demo",
|
|
71
|
+
"businessOwner": "user_owner",
|
|
72
|
+
"publish": true
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
],
|
|
76
|
+
"diagnostics": [],
|
|
77
|
+
"planHash": "example-plan-hash"
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://guandata.dev/schemas/guanmetric/metric-flow-generate-1.0.json",
|
|
4
|
+
"title": "guanmetric flow generate result v1.0",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"additionalProperties": false,
|
|
7
|
+
"required": [
|
|
8
|
+
"schemaVersion",
|
|
9
|
+
"command",
|
|
10
|
+
"generated",
|
|
11
|
+
"metricCount",
|
|
12
|
+
"diagnostics"
|
|
13
|
+
],
|
|
14
|
+
"properties": {
|
|
15
|
+
"schemaVersion": {
|
|
16
|
+
"const": "1.0"
|
|
17
|
+
},
|
|
18
|
+
"command": {
|
|
19
|
+
"const": "flow.generate"
|
|
20
|
+
},
|
|
21
|
+
"generated": {
|
|
22
|
+
"type": "boolean"
|
|
23
|
+
},
|
|
24
|
+
"output": {
|
|
25
|
+
"type": "string"
|
|
26
|
+
},
|
|
27
|
+
"acceptance": {
|
|
28
|
+
"enum": [
|
|
29
|
+
"usable",
|
|
30
|
+
"draft"
|
|
31
|
+
]
|
|
32
|
+
},
|
|
33
|
+
"metricCount": {
|
|
34
|
+
"type": "integer",
|
|
35
|
+
"minimum": 0
|
|
36
|
+
},
|
|
37
|
+
"diagnostics": {
|
|
38
|
+
"type": "array",
|
|
39
|
+
"items": {
|
|
40
|
+
"$ref": "#/$defs/diagnostic"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"plan": {
|
|
44
|
+
"type": "object",
|
|
45
|
+
"additionalProperties": true,
|
|
46
|
+
"required": [
|
|
47
|
+
"schemaVersion",
|
|
48
|
+
"operation",
|
|
49
|
+
"valid",
|
|
50
|
+
"acceptance",
|
|
51
|
+
"environment",
|
|
52
|
+
"executionOrder",
|
|
53
|
+
"items",
|
|
54
|
+
"diagnostics"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"$defs": {
|
|
59
|
+
"diagnostic": {
|
|
60
|
+
"type": "object",
|
|
61
|
+
"additionalProperties": false,
|
|
62
|
+
"required": [
|
|
63
|
+
"code",
|
|
64
|
+
"severity",
|
|
65
|
+
"message"
|
|
66
|
+
],
|
|
67
|
+
"properties": {
|
|
68
|
+
"code": {
|
|
69
|
+
"type": "string"
|
|
70
|
+
},
|
|
71
|
+
"severity": {
|
|
72
|
+
"enum": [
|
|
73
|
+
"error",
|
|
74
|
+
"warning"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
"sheet": {
|
|
78
|
+
"type": "string"
|
|
79
|
+
},
|
|
80
|
+
"row": {
|
|
81
|
+
"type": "integer",
|
|
82
|
+
"minimum": 1
|
|
83
|
+
},
|
|
84
|
+
"field": {
|
|
85
|
+
"type": "string"
|
|
86
|
+
},
|
|
87
|
+
"message": {
|
|
88
|
+
"type": "string"
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# 指标创建 Flow
|
|
2
|
+
|
|
3
|
+
`guanmetric flow` 面向 Agent 根据对话一次梳理并创建一组相互依赖的原子、复合和衍生指标。它新增独立入口,不改变历史 `create`、`edit`、`fetch` 行为。
|
|
4
|
+
|
|
5
|
+
## 命令
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 从用户确认后的标准模板生成计划;只读解析并立即执行 plan 校验
|
|
9
|
+
guanmetric flow generate --file standard_metrics.xlsx --out metric_flow.json
|
|
10
|
+
|
|
11
|
+
# 校验 Flow 编排契约、前端独有规则、筛选结构、原子 save-precheck 和依赖排序;不会创建指标
|
|
12
|
+
guanmetric flow plan --file metric_flow.json
|
|
13
|
+
|
|
14
|
+
# 不带 --confirm 时只输出 apply-preview,并以非零状态结束
|
|
15
|
+
guanmetric flow apply --file metric_flow.json --state metric_flow.state.json
|
|
16
|
+
|
|
17
|
+
# 确认后创建;每创建一个指标就立即保存状态
|
|
18
|
+
guanmetric flow apply --file metric_flow.json --state metric_flow.state.json --confirm
|
|
19
|
+
|
|
20
|
+
# 审批通过或故障恢复后重新验证,不会重复创建
|
|
21
|
+
guanmetric flow verify --state metric_flow.state.json
|
|
22
|
+
|
|
23
|
+
# 创建结果未知时,先只读核对候选;默认只预览,不修改 state
|
|
24
|
+
guanmetric flow reconcile --file metric_flow.json --state metric_flow.state.json \
|
|
25
|
+
--key sales --metric-id metric_xxx
|
|
26
|
+
|
|
27
|
+
# 确认候选与原计划一致后,只把真实 ID 写回本地 state,不创建或编辑 BI 指标
|
|
28
|
+
guanmetric flow reconcile --file metric_flow.json --state metric_flow.state.json \
|
|
29
|
+
--key sales --metric-id metric_xxx --confirm
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`--query-timeout` 控制 `usable` 模式下单个指标数据查询的超时时间,默认 `60s`。
|
|
33
|
+
|
|
34
|
+
## 从标准模板生成计划
|
|
35
|
+
|
|
36
|
+
`flow generate` 是 `template normalize` 与 Flow 执行之间的唯一自动桥接入口。输入必须是当前版本标准模板,且每个真实指标行的“行状态”均为“可创建”。命令只读取 BI 元数据,不创建或编辑指标:
|
|
37
|
+
|
|
38
|
+
- 解析数据集字段名/别名为 `fdId`,原子表达式中的 `[字段]` 同样改写为字段 ID。
|
|
39
|
+
- 将“当前登录用户”解析为 `/api/user/profile` 返回的 `uId`;责任人名称、邮箱或登录名通过用户搜索唯一解析,也可用 `--business-owner-id` 统一覆盖。
|
|
40
|
+
- 读取业务属性配置,将标准模板业务属性列转换成 `bizAttrs`。
|
|
41
|
+
- 将复合/组合衍生公式的显式 `token=指标名称或ID` 映射改写为真实 `[metricId]` 或批内 `[${metric:key}]`。
|
|
42
|
+
- 将普通衍生的基础指标改写为真实 ID 或 `${metric:key}`,并从基础指标继承 `advValue.dateFdId`。
|
|
43
|
+
- 所有行均为“上线”时生成 `acceptance.mode=usable`;所有行均为“草稿”时生成 `draft`。混合保存方式会返回 `FLOW_GENERATE_MIXED_ACCEPTANCE`,不会自动覆盖或拆分。
|
|
44
|
+
- 转换完成后立即运行与 `flow plan` 相同的只读校验;只有转换诊断为空且 plan 有效时才写入 `--out`。输出文件已存在时默认拒绝,明确追加 `--force` 才覆盖。
|
|
45
|
+
|
|
46
|
+
生成的 Flow 是后续真实写请求的事实源。执行 `flow apply --confirm` 前必须把计划与用户确认的标准模板逐项核对,至少确认原子取数定义(`fdId+aggrType` 或 `formulaField`)、`applicableDims/timeDim`、`bizAttrs`、`businessOwner`、`format`、复合/衍生引用和 `publish` 没有跨阶段丢失。仓库中的 `TestMetricTemplateToFlowPipelineMatchesGolden` 会贯通 normalize、标准 Excel 读取、Flow 生成和依赖排序,锁定这些字段的请求契约;它不替代真实 BI 环境的创建、回读和查询验证。
|
|
47
|
+
|
|
48
|
+
命令结果是 `schemaVersion=1.0` 的机器契约。真实脱敏样例见 `metric-flow-generate-example.json`,Schema 见 `metric-flow-generate.schema.json`。诊断固定包含 `code/severity/message`,定位信息使用 `sheet/row/field`,Agent 不得从中文 message 反推机器语义。
|
|
49
|
+
|
|
50
|
+
generate 新增的只读 API 依赖:`GET /api/user/profile` 与 `POST /api/user/search` 需要 `BASE.READ`,`GET /api/data-source/{id}` 需要 `DATASET.READ`,指标搜索/详情需要 `METRIC_PLATFORM.READ`。2026-09-21 已在 test71 使用账号密码验证标准原子模板生成成功;PAT 对照未执行,状态必须标记为“未验证”。
|
|
51
|
+
|
|
52
|
+
同日还在 test153 使用账号密码完成真实 Flow 矩阵:一个带四个适用维度和六个必填业务属性的原子指标,依次创建月环比增长率、月累计、自然期末值、单条件业务限定和引用“累计/期末值”的组合衍生。六个指标均成功上线、详情回读为 `PUBLISHED/canUse=true`、查询返回一行;回读确认基础取数字段、时间维度、六个业务属性、五种 `deriveSetting`、业务限定 `filter` 和组合公式均正确保存。测试指标随后按逆依赖顺序全部删除,并按统一名称前缀搜索确认为零残留。该验证只覆盖账号密码登录态,不构成 PAT 证据。
|
|
53
|
+
|
|
54
|
+
2026-09-21 还在 test153 使用账号密码对 `flow reconcile` 做了纯只读验证:以一个已发布复合指标作为候选,预览成功校验环境、planHash、类型和关键定义,并完成详情回读与一行数据查询;命令前后本地 state 文件 SHA-256 完全一致。未执行 `--confirm`,也没有创建、编辑或删除任何 BI 资源。test71 当时登录态返回 401,因此未用于本项验证;PAT 仍未验证。
|
|
55
|
+
|
|
56
|
+
## 输入契约 1.0
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"schemaVersion": "1.0",
|
|
61
|
+
"acceptance": {
|
|
62
|
+
"mode": "usable"
|
|
63
|
+
},
|
|
64
|
+
"metrics": [
|
|
65
|
+
{
|
|
66
|
+
"key": "sales",
|
|
67
|
+
"subType": "ATOMIC",
|
|
68
|
+
"body": {
|
|
69
|
+
"projectId": "project_xxx",
|
|
70
|
+
"subType": "ATOMIC",
|
|
71
|
+
"dsId": "ds_xxx",
|
|
72
|
+
"name": "销售额",
|
|
73
|
+
"fdId": "fd_amount",
|
|
74
|
+
"aggrType": "SUM",
|
|
75
|
+
"applicableDims": ["fd_date", "fd_region"],
|
|
76
|
+
"timeDim": "fd_date",
|
|
77
|
+
"desc": "订单实付金额合计",
|
|
78
|
+
"parentDirId": "dir_xxx",
|
|
79
|
+
"businessOwner": "user_xxx",
|
|
80
|
+
"publish": true
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"key": "profit_rate",
|
|
85
|
+
"subType": "COMPOSITE",
|
|
86
|
+
"body": {
|
|
87
|
+
"projectId": "project_xxx",
|
|
88
|
+
"subType": "COMPOSITE",
|
|
89
|
+
"name": "利润率",
|
|
90
|
+
"formula": "[metric_profit_existing] / [${metric:sales}]",
|
|
91
|
+
"applicableDims": ["fd_date", "fd_region"],
|
|
92
|
+
"useExpressionMetricCommonDims": false,
|
|
93
|
+
"timeDim": "fd_date",
|
|
94
|
+
"desc": "利润除以销售额",
|
|
95
|
+
"parentDirId": "dir_xxx",
|
|
96
|
+
"businessOwner": "user_xxx",
|
|
97
|
+
"publish": true
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"key": "sales_yoy",
|
|
102
|
+
"subType": "DERIVED",
|
|
103
|
+
"body": {
|
|
104
|
+
"projectId": "project_xxx",
|
|
105
|
+
"subType": "DERIVED",
|
|
106
|
+
"name": "销售额同比",
|
|
107
|
+
"baseMetricId": "${metric:sales}",
|
|
108
|
+
"deriveSetting": {
|
|
109
|
+
"deriveType": "ORDINARY",
|
|
110
|
+
"advType": "COMPARATIVE",
|
|
111
|
+
"advValue": {
|
|
112
|
+
"advType": "COMPARATIVE"
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
"desc": "销售额同比变化",
|
|
116
|
+
"parentDirId": "dir_xxx",
|
|
117
|
+
"businessOwner": "user_xxx",
|
|
118
|
+
"publish": true
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
顶层和指标条目采用严格字段契约,未知字段会被拒绝;`body` 保持各指标类型的领域请求结构。
|
|
126
|
+
|
|
127
|
+
### acceptance.mode
|
|
128
|
+
|
|
129
|
+
| 值 | 请求约束 | 验收门槛 |
|
|
130
|
+
| --- | --- | --- |
|
|
131
|
+
| `usable` | 每项 `publish=true` | 回读 `status=PUBLISHED`、`canUse=true`,再执行一次 `metric query --limit 1 -f json`;组合衍生引用带固定高级计算粒度的指标时自动追加唯一兼容日期粒度;0 行也是合法查询结果 |
|
|
132
|
+
| `draft` | 每项 `publish=false` | 用 `fromDraft=true` 回读定义;不执行数据查询 |
|
|
133
|
+
|
|
134
|
+
如果服务端启用发布审批,`usable` 模式会把 `approvalStatus=PENDING` 记录为 `pending`。此时创建 ID 已写入状态文件;审批通过后执行 `flow verify`,不要重新创建。
|
|
135
|
+
|
|
136
|
+
Flow 会在每个指标创建后立即完成当前模式的验收,再创建依赖它的下游指标。上游处于审批中或验证失败时,后续指标不会被提交;审批通过后先执行 `flow verify`,再用同一计划和状态文件重新执行 `flow apply --confirm` 继续创建剩余项。
|
|
137
|
+
|
|
138
|
+
### 组合衍生的粒度感知查询验收
|
|
139
|
+
|
|
140
|
+
组合衍生可以引用 `RECENT_X`、`XTD`、`COMPARATIVE` 等带固定时间粒度的高级计算指标。对此类指标执行无维度查询时,BI 可能按原始日期字段计算并返回时间粒度不匹配。Flow 不把这种错误误报为创建失败,而是在查询前构造最小兼容查询:
|
|
141
|
+
|
|
142
|
+
1. 从组合衍生详情的 `referencedMetrics` 读取真实引用 ID;嵌套组合衍生继续递归解析。
|
|
143
|
+
2. 收集引用指标 `deriveSetting.advValue.granularity`,忽略空值和 `NONE`。
|
|
144
|
+
3. 只有得到唯一共同粒度时才追加日期子维度,例如 `MONTH -> 日期 toMonth`、`WEEK -> 日期 toWeek`。
|
|
145
|
+
4. state 的 `query` 摘要记录 `dimensions/granularity/strategy=derived-compatible-granularity`,说明本次验收实际使用的查询条件。
|
|
146
|
+
|
|
147
|
+
多个引用要求不同粒度时不循环试错,也不把任意一次成功当成定义正确,而是以 `stage=query` 和稳定错误码 `FLOW_QUERY_GRANULARITY_CONFLICT` 失败。无法找到时间维度、粒度不受支持或引用详情读取失败分别使用 `FLOW_QUERY_TIME_DIMENSION_MISSING`、`FLOW_QUERY_GRANULARITY_UNSUPPORTED`、`FLOW_QUERY_DEPENDENCY_READ_FAILED`。普通指标和不要求固定粒度的组合衍生继续使用原有默认查询,避免扩大行为变化。
|
|
148
|
+
|
|
149
|
+
2026-09-21 在 test1 使用账号密码登录态对真实批量创建结果做了只读回归:`AI35490_组合衍生_最近N_月_118`、`AI35490_组合衍生_最近N_周_090`、`AI35490_组合衍生_公式_月_119` 原先均因无粒度默认查询返回时间粒度不匹配;修复后的同一 `flow verify` 自动选择 `日期 toMonth`、`日期 toWeek`、`日期 toMonth`,三条均查询返回一行,state 汇总为 3/3 verified。验证只读取 BI 指标和数据,并写本地临时 state,没有创建、编辑或删除 BI 资源;PAT 仍未验证。
|
|
150
|
+
|
|
151
|
+
## 批内引用与顺序
|
|
152
|
+
|
|
153
|
+
- `key` 仅允许英文字母、数字、点、下划线和连字符,且不能以符号开头;计划内必须唯一。
|
|
154
|
+
- 普通衍生指标:`baseMetricId` 可完整填写 `${metric:key}`。
|
|
155
|
+
- 复合指标和组合衍生:`formula` / `deriveSetting.formula` 中必须使用 `[${metric:key}]`。
|
|
156
|
+
- 已有线上指标仍直接使用真实 `[metricId]` 或 `baseMetricId`,不声明成批内依赖。
|
|
157
|
+
- 已有引用仍应是可用的已发布指标,复合指标仍只能引用后端允许的类型;这些指标定义和权限规则由创建接口最终校验,Flow 不额外复制远端判断。
|
|
158
|
+
- 本批复合指标引用衍生指标应在创建计划 Excel 生成前由语义规划门禁拒绝;如果绕过 Excel 直接编写 Flow JSON,引用类型由后端创建接口裁决,Flow 不再维护同一规则副本。
|
|
159
|
+
- `draft` 模式不允许批内引用;前端公式和衍生配置只能选择已发布指标,因此相互依赖的一批指标应使用 `usable` 模式按顺序创建。
|
|
160
|
+
- 占位符不能用于主题、目录、数据集、用户、字段等其它参数。
|
|
161
|
+
- `plan` 会拒绝未知 key、自引用和循环依赖,并按原输入顺序稳定地拓扑排序。
|
|
162
|
+
|
|
163
|
+
`flow plan` 只承诺计划与客户端编排可构造,不表示后端指标业务校验一定通过。复合和衍生指标当前没有独立的 create-precheck,真实创建仍由后端接口裁决。
|
|
164
|
+
|
|
165
|
+
## 状态、失败和续跑
|
|
166
|
+
|
|
167
|
+
状态文件是 `schemaVersion=1.0` 的机器契约,包含:
|
|
168
|
+
|
|
169
|
+
- 计划哈希和 BI 环境身份,防止换计划或换环境误续跑;
|
|
170
|
+
- 每个逻辑 key 对应的真实 `metricId`;
|
|
171
|
+
- 创建 POST 前持久化的 canonical `submittedDefinition`,用于结果未知后的精确 reconcile;
|
|
172
|
+
- `planned`、`creating`、`created`、`verified`、`pending`、`blocked`、`failed` 状态;
|
|
173
|
+
- 当前失败阶段、定义回读摘要和查询摘要;
|
|
174
|
+
- 可选的结构化 `error`,包含 flow 稳定错误码、错误类别、HTTP/业务状态码和服务端原始消息;
|
|
175
|
+
- 创建、验证、待审批和失败计数。
|
|
176
|
+
|
|
177
|
+
`flow plan` 的输出也包含当前非敏感环境身份(profile、base URL、domain),用户确认计划时应一并核对目标环境。
|
|
178
|
+
|
|
179
|
+
每个创建成功的 ID 会立刻写入状态文件。再次执行 `flow apply` 时,有 ID 的条目只重新验证,不重复创建。原子指标发布前若检测到口径冲突,flow 固定 `blocked`;它不会把 `--confirm` 解释成忽略口径冲突。部分成功后也不会删除已创建指标做回滚,因为指标 ID、权限、审批和下游引用不能由客户端无损恢复。
|
|
180
|
+
|
|
181
|
+
原生 Unix/Windows 中,confirmed `flow apply` 会在读取计划或访问 BI 前取得 state 锁,`flow verify` 和 `flow reconcile` 也在读取 state 或访问 BI 前取得锁;三者对同一个 state 路径持有完整生命周期的跨进程独占锁,避免两个 Agent 同时创建或互相覆盖状态。apply preview 不读取 state,因此不持锁。锁文件固定为 `<state>.lock`,只是 OS advisory lock 的稳定载体,可以长期保留;进程正常退出或崩溃时锁由操作系统自动释放,不依赖删除文件判断是否过期。锁已被占用时命令直接失败,不降级成无锁执行。WASI/非原生运行时没有可审计的跨 guest 文件锁契约,因此明确拒绝这三个生命周期命令,只保留 `flow generate`、`flow plan` 等只读能力。
|
|
182
|
+
|
|
183
|
+
提交创建请求前,状态会把 `creating` 与本次真正提交的 canonical `submittedDefinition` 一次性落盘。若进程在请求期间中断,或服务端响应没有返回可记录的 ID,后续执行会进入 `blocked/reconcile`,不会自动重试写请求;这是为了避免“服务端其实已创建、客户端却因断线再次创建”的重复指标。`reconcile` 只允许把候选详情与这个不可变快照比较,不重新按当前服务端维度元数据生成请求;旧状态若缺少该快照会拒绝绑定。Agent 可以按环境、项目、类型、真实名称和指标定义只读核对线上候选,但不能把 Flow 逻辑 key 当作指标名称,也不能只凭同名就认领资源。
|
|
184
|
+
|
|
185
|
+
只读核对得到真实 ID 后,使用 `flow reconcile --file <原计划> --state <原状态> --key <条目key> --metric-id <真实ID>`。默认执行预览:校验当前环境身份、原计划 `planHash`、条目状态、指标 ID/类型、该 ID 未被同一 state 的其他 key 绑定,以及计划中已解析的项目、目录、真实名称、责任人和各类型关键定义;随后按原 acceptance 做详情回读与查询验证,但不修改 state。同一 state 内一个非空 `metricId` 最多属于一个逻辑 key。只有预览无定义冲突且用户确认后才追加 `--confirm`。确认操作只原子写回本地 state,不调用任何 BI 创建或编辑接口;指标仍在审批中或查询失败时会保留已绑定 ID 及 `pending/failed` 状态,后续用 `flow verify` 重试验证。不得手改 state,也不得用 `flow apply` 代替 reconcile;`apply` 对无 ID 的 `blocked/reconcile` 条目保持硬阻断。
|
|
186
|
+
|
|
187
|
+
创建接口执行的不只是校验,还包含写指标、写草稿、同步血缘/权限和上线或审批等多个步骤。因此,即使后端返回了结构化业务错误,也不能仅凭错误码证明前序步骤一定没有落库。Flow 会保留 `businessStatus`、`httpStatus`、`method`、`path` 及服务端原始 `message`,同时记录 `error.code=FLOW_CREATE_RESULT_UNKNOWN` 并进入 `blocked/reconcile`;断线、超时和无法取得创建 ID 的响应采用同样的安全策略。Agent 必须先按名称和计划范围核对线上资源,不能直接重试。Flow 不通过匹配中英文错误文案推断业务语义。
|
|
188
|
+
|
|
189
|
+
## 机器错误与退出语义
|
|
190
|
+
|
|
191
|
+
`flow plan` 输出固定的 `diagnostics[]`,每项包含 `code`、`severity`、`key`、`field` 和展示用 `message`。Agent 必须按 `code` 和 `field` 分支,不能匹配中文 `message`。
|
|
192
|
+
|
|
193
|
+
- 计划存在 error:输出 `valid=false`,非零退出。
|
|
194
|
+
- `apply` 未带 `--confirm`:输出 `operation=apply-preview`,不写 BI,非零退出。
|
|
195
|
+
- `reconcile` 未带 `--confirm`:输出 `operation=reconcile-preview`、`dryRun=true` 和预览 state,不写 state、不写 BI,非零退出。
|
|
196
|
+
- `reconcile --confirm`:输出 `operation=reconcile`、`dryRun=false`;只在定义一致时写本地 state,从不写 BI。绑定后尚未达到 acceptance 时保留状态并非零退出。
|
|
197
|
+
- 有 `pending`、`blocked` 或 `failed`:保存状态,非零退出。
|
|
198
|
+
- 所有指标达到所选验收模式:`status=succeeded`,零退出。
|
|
199
|
+
|
|
200
|
+
创建合法性由 BI 后端最终裁决。Flow 的单指标业务校验只实现当前 Web 创建页已有而后端创建链路缺失的规则;后端已有规则不复制,前后端都没有的规则不新增。`FLOW_FRONTEND_RULE_INVALID` 表示命中这一差集,具体字段见 diagnostic 的 `field`。Flow 另外负责计划结构、批内依赖、占位符、环境/状态一致性和验收编排。当前职责证据和逐条差异见 `metric-validation-ownership.md`。
|
|
201
|
+
|
|
202
|
+
## Domain and Contract
|
|
203
|
+
|
|
204
|
+
Flow 复用现有接口,没有创造新的 BI method/path:
|
|
205
|
+
|
|
206
|
+
| 客户端接口 | 后端路由 | PAT 权限 |
|
|
207
|
+
| --- | --- | --- |
|
|
208
|
+
| `POST /api/metric-platform/metrics/atomic-metrics` | `POST /metric-platform/metrics/atomic-metrics` | `METRIC_PLATFORM / CREATE` |
|
|
209
|
+
| `POST /api/metric-platform/metrics/atomic-metrics/save-precheck` | `POST /metric-platform/metrics/atomic-metrics/save-precheck` | `METRIC_PLATFORM / CREATE` |
|
|
210
|
+
| `POST /api/metric-platform/metrics/composite-metrics` | `POST /metric-platform/metrics/composite-metrics` | `METRIC_PLATFORM / CREATE` |
|
|
211
|
+
| `POST /api/metric-platform/metrics/derived-metrics` | `POST /metric-platform/metrics/derived-metrics` | `METRIC_PLATFORM / CREATE` |
|
|
212
|
+
| `GET /api/metric-platform/metrics/{id}` | `GET /metric-platform/metrics/{id}` | `METRIC_PLATFORM / READ` |
|
|
213
|
+
|
|
214
|
+
路由和权限注解来源为 BI 后端 `MetricManagementNgController`。数据冒烟委托当前环境中的 `guancli metric query`,沿用它的查询接口、兼容策略和权限错误契约。
|
|
215
|
+
|
|
216
|
+
机器契约兼容范围:本功能首次发布为 `schemaVersion=1.0`,后端业务字段继续保留在动态 `body` 中;Flow 自己赋予稳定语义的计划、诊断、状态和汇总字段由类型化模型生成。`reconcile` 响应同样由类型化模型生成,固定包含 `schemaVersion/operation/dryRun/valid/key/metricId/state`。同一 state 被其它生命周期命令占用时会在任何 state/BI 读写前稳定失败,且不修改 state。新增可选字段时保持 1.0 向后兼容;字段改名、退出语义变化或不兼容的占位符规则必须新增版本。
|
|
217
|
+
|
|
218
|
+
真实 PAT 对照验证仍需在目标 BI 环境执行:同一用户分别使用登录态和 PAT,覆盖 CREATE/READ、无权和资源不存在;`usable` 模式还需覆盖查询权限。CLI 单元测试只证明请求构造与编排,不能替代该验证。
|