@wubaoqi/guancopilot 0.0.0-stage → 0.2.0

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 (239) hide show
  1. package/NOTICE.md +17 -0
  2. package/README.md +146 -2
  3. package/assets/coreutils.wasm +0 -0
  4. package/assets/find.wasm +0 -0
  5. package/assets/guanbi.wasm +4 -0
  6. package/assets/guancli.wasm +0 -0
  7. package/assets/guanhelm.wasm +0 -0
  8. package/assets/jq.wasm +0 -0
  9. package/assets/openskills.wasm +0 -0
  10. package/assets/rg.wasm +0 -0
  11. package/assets/sed.wasm +0 -0
  12. package/bin/guancopilot +0 -0
  13. package/bin/guanvm +0 -0
  14. package/bin/platforms.cjs +6 -0
  15. package/bin/run.cjs +39 -0
  16. package/bin/runtime.cjs +44 -0
  17. package/licenses/Go-LICENSE +27 -0
  18. package/licenses/browser-_speed-highlight_core-LICENSE +121 -0
  19. package/licenses/browser-_speed-highlight_core-package.json +14 -0
  20. package/licenses/browser-dompurify-LICENSE +202 -0
  21. package/licenses/browser-dompurify-LICENSE-MPL +373 -0
  22. package/licenses/browser-dompurify-package.json +10 -0
  23. package/licenses/browser-marked-LICENSE +44 -0
  24. package/licenses/browser-marked-package.json +10 -0
  25. package/licenses/coreutils-LICENSE +18 -0
  26. package/licenses/findutils-LICENSE +18 -0
  27. package/licenses/github.com_BurntSushi_toml_v1.6.0-COPYING +21 -0
  28. package/licenses/github.com_dustin_go-humanize_v1.0.1-LICENSE +21 -0
  29. package/licenses/github.com_google_jsonschema-go_v0.4.3-LICENSE +21 -0
  30. package/licenses/github.com_google_uuid_v1.6.0-LICENSE +27 -0
  31. package/licenses/github.com_jackc_pgpassfile_v1.0.0-LICENSE +22 -0
  32. package/licenses/github.com_jackc_pgservicefile_v0.0.0-20240606120523-5a60cdf6a761-LICENSE +22 -0
  33. package/licenses/github.com_jackc_pgx_v5_v5.11.0-LICENSE +22 -0
  34. package/licenses/github.com_jackc_puddle_v2_v2.2.2-LICENSE +22 -0
  35. package/licenses/github.com_mattn_go-isatty_v0.0.20-LICENSE +9 -0
  36. package/licenses/github.com_modelcontextprotocol_go-sdk_v1.8.0-LICENSE +216 -0
  37. package/licenses/github.com_ncruces_go-strftime_v1.0.0-LICENSE +21 -0
  38. package/licenses/github.com_remyoudompheng_bigfft_v0.0.0-20230129092748-24d4a6f8daec-LICENSE +27 -0
  39. package/licenses/github.com_santhosh-tekuri_jsonschema_v6_v6.0.3-LICENSE +175 -0
  40. package/licenses/github.com_segmentio_asm_v1.1.3-LICENSE +21 -0
  41. package/licenses/github.com_segmentio_encoding_v0.5.4-LICENSE +21 -0
  42. package/licenses/github.com_tetratelabs_wazero_v1.12.0-LICENSE +201 -0
  43. package/licenses/github.com_tetratelabs_wazero_v1.12.0-NOTICE +2 -0
  44. package/licenses/github.com_yosida95_uritemplate_v3_v3.0.2-LICENSE +25 -0
  45. package/licenses/golang.org_x_image_v0.44.0-LICENSE +27 -0
  46. package/licenses/golang.org_x_net_v0.58.0-LICENSE +27 -0
  47. package/licenses/golang.org_x_oauth2_v0.36.0-LICENSE +27 -0
  48. package/licenses/golang.org_x_sync_v0.22.0-LICENSE +27 -0
  49. package/licenses/golang.org_x_sys_v0.47.0-LICENSE +27 -0
  50. package/licenses/golang.org_x_text_v0.41.0-LICENSE +27 -0
  51. package/licenses/golang.org_x_time_v0.15.0-LICENSE +27 -0
  52. package/licenses/guanbi-skills-LICENSE +133 -0
  53. package/licenses/guanbi-skills-LICENSE.README.md +28 -0
  54. package/licenses/guanbi-skills-LICENSE.zh-CN +82 -0
  55. package/licenses/jq-COPYING +176 -0
  56. package/licenses/modernc.org_libc_v1.73.4-LICENSE +27 -0
  57. package/licenses/modernc.org_libc_v1.73.4-LICENSE-3RD-PARTY.md +305 -0
  58. package/licenses/modernc.org_mathutil_v1.7.1-LICENSE +27 -0
  59. package/licenses/modernc.org_memory_v1.11.0-LICENSE +27 -0
  60. package/licenses/modernc.org_memory_v1.11.0-LICENSE-GO +27 -0
  61. package/licenses/modernc.org_memory_v1.11.0-LICENSE-LOGO +1 -0
  62. package/licenses/modernc.org_memory_v1.11.0-LICENSE-MMAP-GO +25 -0
  63. package/licenses/modernc.org_sqlite_v1.53.0-LICENSE +26 -0
  64. package/licenses/mvdan.cc_sh_v3_v3.13.1-LICENSE +27 -0
  65. package/licenses/ripgrep-COPYING +3 -0
  66. package/licenses/ripgrep-LICENSE-MIT +21 -0
  67. package/licenses/sed-LICENSE +21 -0
  68. package/manifest.json +972 -0
  69. package/package.json +30 -4
  70. package/plugin/guancopilot.js +193 -0
  71. package/skills-bundle/.guanvm-skills-bundle +0 -0
  72. package/skills-bundle/_recipes/dashboard/gates/page_check.js +16 -0
  73. package/skills-bundle/_recipes/dashboard/gates/report_check.js +4 -0
  74. package/skills-bundle/_recipes/dashboard/knowledge/01.md +1 -0
  75. package/skills-bundle/_recipes/dashboard/knowledge/02.md +1 -0
  76. package/skills-bundle/_recipes/dashboard/knowledge/03.md +1 -0
  77. package/skills-bundle/_recipes/dashboard/knowledge/04.md +1 -0
  78. package/skills-bundle/_recipes/dashboard/knowledge/05.md +1 -0
  79. package/skills-bundle/_recipes/dashboard/knowledge/06.md +1 -0
  80. package/skills-bundle/_recipes/dashboard/template.json +41 -0
  81. package/skills-bundle/_recipes/etl/gates/etl_live_check.js +10 -0
  82. package/skills-bundle/_recipes/etl/gates/etl_report_check.js +3 -0
  83. package/skills-bundle/_recipes/etl/knowledge/01.md +1 -0
  84. package/skills-bundle/_recipes/etl/knowledge/02.md +9 -0
  85. package/skills-bundle/_recipes/etl/knowledge/03.md +1 -0
  86. package/skills-bundle/_recipes/etl/knowledge/04.md +1 -0
  87. package/skills-bundle/_recipes/etl/knowledge/05.md +1 -0
  88. package/skills-bundle/_recipes/etl/template.json +39 -0
  89. package/skills-bundle/_recipes/hints.json +46 -0
  90. package/skills-bundle/guancli/.commandface.json +155 -0
  91. package/skills-bundle/guancli/SKILL.md +342 -0
  92. package/skills-bundle/guancli/evals/evals.json +156 -0
  93. package/skills-bundle/guancli/evals/fixtures/metric-candidate-empty-search.json +13 -0
  94. package/skills-bundle/guancli/evals/fixtures/metric-candidate-prior-request.json +13 -0
  95. package/skills-bundle/guancli/evals/fixtures/metric-consumption-columns.json +46 -0
  96. package/skills-bundle/guancli/evals/fixtures/metric-consumption-metadata.json +36 -0
  97. package/skills-bundle/guancli/evals/fixtures/metric-consumption-query.json +18 -0
  98. package/skills-bundle/guancli/references/analysis-primitives.md +95 -0
  99. package/skills-bundle/guancli/references/auth-and-config.md +131 -0
  100. package/skills-bundle/guancli/references/examples/metric-date-in.json +7 -0
  101. package/skills-bundle/guancli/references/examples/metric-query-rows.py +83 -0
  102. package/skills-bundle/guancli/references/examples/metric-query.sh +6 -0
  103. package/skills-bundle/guancli/references/form-chatbi.md +199 -0
  104. package/skills-bundle/guancli/references/gateway.md +148 -0
  105. package/skills-bundle/guancli/references/metric-batch-query.md +82 -0
  106. package/skills-bundle/guancli/references/metric-commands.md +562 -0
  107. package/skills-bundle/guancli/references/metric-generic-query.md +215 -0
  108. package/skills-bundle/guancli/references/metric-json-migration.md +18 -0
  109. package/skills-bundle/guancli/references/metric-query-recipes.md +358 -0
  110. package/skills-bundle/guancli/references/preview-and-output.md +192 -0
  111. package/skills-bundle/guancli/references/resource-query.md +101 -0
  112. package/skills-bundle/guands/SKILL.md +281 -0
  113. package/skills-bundle/guands/references/calc-fields-boundaries-and-pitfalls.md +160 -0
  114. package/skills-bundle/guands/references/command-reference.md +267 -0
  115. package/skills-bundle/guands/references/incremental-and-schedule.md +157 -0
  116. package/skills-bundle/guands/references/workflows.md +256 -0
  117. package/skills-bundle/guanetl/SKILL.md +391 -0
  118. package/skills-bundle/guanetl/evals/evals.json +41 -0
  119. package/skills-bundle/guanetl/references/ETL_AI_DEVELOP.md +456 -0
  120. package/skills-bundle/guanmetric/SKILL.md +144 -0
  121. package/skills-bundle/guanmetric/evals/evals.json +117 -0
  122. package/skills-bundle/guanmetric/evals/fixtures/atomic-detail-read-model.json +18 -0
  123. package/skills-bundle/guanmetric/evals/fixtures/confirmed-template-summary.json +12 -0
  124. package/skills-bundle/guanmetric/evals/fixtures/create-result-unknown-state.json +13 -0
  125. package/skills-bundle/guanmetric/evals/forward-eval-2026-09-21.json +62 -0
  126. package/skills-bundle/guanmetric/references/metric-api-contract-examples.json +690 -0
  127. package/skills-bundle/guanmetric/references/metric-api-contract.schema.json +349 -0
  128. package/skills-bundle/guanmetric/references/metric-api-contracts.md +436 -0
  129. package/skills-bundle/guanmetric/references/metric-atomic-mutation.md +238 -0
  130. package/skills-bundle/guanmetric/references/metric-batch-status.md +71 -0
  131. package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract-examples.json +53 -0
  132. package/skills-bundle/guanmetric/references/metric-business-dictionary-api-contract.schema.json +26 -0
  133. package/skills-bundle/guanmetric/references/metric-business-dictionary.md +76 -0
  134. package/skills-bundle/guanmetric/references/metric-common-fields.md +246 -0
  135. package/skills-bundle/guanmetric/references/metric-composite-mutation.md +165 -0
  136. package/skills-bundle/guanmetric/references/metric-delete-mutation.md +70 -0
  137. package/skills-bundle/guanmetric/references/metric-derived-mutation.md +453 -0
  138. package/skills-bundle/guanmetric/references/metric-excel-template.md +365 -0
  139. package/skills-bundle/guanmetric/references/metric-expression-rules.md +146 -0
  140. package/skills-bundle/guanmetric/references/metric-flow-generate-example.json +79 -0
  141. package/skills-bundle/guanmetric/references/metric-flow-generate.schema.json +93 -0
  142. package/skills-bundle/guanmetric/references/metric-flow.md +218 -0
  143. package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract-examples.json +171 -0
  144. package/skills-bundle/guanmetric/references/metric-hierarchy-api-contract.schema.json +167 -0
  145. package/skills-bundle/guanmetric/references/metric-hierarchy-api-contracts.md +193 -0
  146. package/skills-bundle/guanmetric/references/metric-mutation.md +155 -0
  147. package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract-examples.json +62 -0
  148. package/skills-bundle/guanmetric/references/metric-public-dimension-api-contract.schema.json +47 -0
  149. package/skills-bundle/guanmetric/references/metric-public-dimension.md +155 -0
  150. package/skills-bundle/guanmetric/references/metric-tree-api-contract-examples.json +277 -0
  151. package/skills-bundle/guanmetric/references/metric-tree-api-contract.schema.json +263 -0
  152. package/skills-bundle/guanmetric/references/metric-tree-api-contracts.md +53 -0
  153. package/skills-bundle/guanmetric/references/metric-tree-mutation.md +500 -0
  154. package/skills-bundle/guanmetric/references/metric-validation-ownership.md +74 -0
  155. package/skills-bundle/guanvis/SKILL.md +333 -0
  156. package/skills-bundle/guanvis/evals/china_map/card_01_basic_map.js +13 -0
  157. package/skills-bundle/guanvis/evals/china_map/card_02_world_map.js +10 -0
  158. package/skills-bundle/guanvis/evals/china_map/card_03_point_map.js +12 -0
  159. package/skills-bundle/guanvis/evals/china_map/page.js +10 -0
  160. package/skills-bundle/guanvis/evals/china_map/schema.js +10 -0
  161. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/README.md +30 -0
  162. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/card_01_comparative_mvp.js +72 -0
  163. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/page.js +6 -0
  164. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/schema.js +22 -0
  165. package/skills-bundle/guanvis/evals/comparative_mvp_roundtrip/verify_default_roundtrip.sh +92 -0
  166. package/skills-bundle/guanvis/evals/complex_report_pro/card_01_monthly.js +63 -0
  167. package/skills-bundle/guanvis/evals/complex_report_pro/page.js +6 -0
  168. package/skills-bundle/guanvis/evals/complex_report_pro/schema.js +6 -0
  169. package/skills-bundle/guanvis/evals/custom_chart_echarts/card_01_bar.js +13 -0
  170. package/skills-bundle/guanvis/evals/custom_chart_echarts/card_02_pie.js +13 -0
  171. package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/bar.js +11 -0
  172. package/skills-bundle/guanvis/evals/custom_chart_echarts/charts/pie.js +15 -0
  173. package/skills-bundle/guanvis/evals/custom_chart_echarts/page.js +5 -0
  174. package/skills-bundle/guanvis/evals/custom_chart_echarts/schema.js +9 -0
  175. package/skills-bundle/guanvis/evals/custom_chart_sdk/card_01_level_nodes.js +19 -0
  176. package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.css +51 -0
  177. package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.html +1 -0
  178. package/skills-bundle/guanvis/evals/custom_chart_sdk/charts/level_nodes.js +28 -0
  179. package/skills-bundle/guanvis/evals/custom_chart_sdk/page.js +5 -0
  180. package/skills-bundle/guanvis/evals/custom_chart_sdk/schema.js +7 -0
  181. package/skills-bundle/guanvis/evals/dynamic_fields/card_01_dynamic_dataset.js +20 -0
  182. package/skills-bundle/guanvis/evals/dynamic_fields/card_02_dynamic_metric_chart.js +16 -0
  183. package/skills-bundle/guanvis/evals/dynamic_fields/metrics.js +19 -0
  184. package/skills-bundle/guanvis/evals/dynamic_fields/page.js +9 -0
  185. package/skills-bundle/guanvis/evals/dynamic_fields/schema.js +7 -0
  186. package/skills-bundle/guanvis/evals/dynamic_fields/verify_default_roundtrip.sh +137 -0
  187. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/README.md +26 -0
  188. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_01_percentage_advcalc.js +44 -0
  189. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/card_02_scroll_percentage.js +12 -0
  190. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/page.js +6 -0
  191. package/skills-bundle/guanvis/evals/percentage_advcalc_roundtrip/schema.js +22 -0
  192. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/README.md +28 -0
  193. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/card_01_rank_advcalc.js +59 -0
  194. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/page.js +6 -0
  195. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/schema.js +22 -0
  196. package/skills-bundle/guanvis/evals/rank_advcalc_roundtrip/verify_default_roundtrip.sh +135 -0
  197. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/README.md +15 -0
  198. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/card_01_running_total_advcalc.js +74 -0
  199. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/page.js +6 -0
  200. package/skills-bundle/guanvis/evals/running_total_advcalc_roundtrip/schema.js +22 -0
  201. package/skills-bundle/guanvis/evals/sales_dashboard/card_01_revenue_column.js +10 -0
  202. package/skills-bundle/guanvis/evals/sales_dashboard/card_02_trend_line.js +9 -0
  203. package/skills-bundle/guanvis/evals/sales_dashboard/card_03_kpi.js +6 -0
  204. package/skills-bundle/guanvis/evals/sales_dashboard/card_04_pie.js +9 -0
  205. package/skills-bundle/guanvis/evals/sales_dashboard/card_05_calc_field_test.js +12 -0
  206. package/skills-bundle/guanvis/evals/sales_dashboard/page.js +11 -0
  207. package/skills-bundle/guanvis/evals/sales_dashboard/schema.js +14 -0
  208. package/skills-bundle/guanvis/evals/sales_dashboard/selector_01_region.js +10 -0
  209. package/skills-bundle/guanvis/evals/split_charts/card_01_column_split.js +10 -0
  210. package/skills-bundle/guanvis/evals/split_charts/card_02_line_split.js +10 -0
  211. package/skills-bundle/guanvis/evals/split_charts/card_03_combo_split.js +11 -0
  212. package/skills-bundle/guanvis/evals/split_charts/page.js +10 -0
  213. package/skills-bundle/guanvis/evals/split_charts/schema.js +14 -0
  214. package/skills-bundle/guanvis/evals/tab_layout/card_00_total_revenue.js +6 -0
  215. package/skills-bundle/guanvis/evals/tab_layout/card_01_revenue.js +10 -0
  216. package/skills-bundle/guanvis/evals/tab_layout/card_02_trend.js +9 -0
  217. package/skills-bundle/guanvis/evals/tab_layout/card_03_story.js +11 -0
  218. package/skills-bundle/guanvis/evals/tab_layout/page.js +23 -0
  219. package/skills-bundle/guanvis/evals/tab_layout/schema.js +11 -0
  220. package/skills-bundle/guanvis/evals/tab_layout/selector_01_region.js +8 -0
  221. package/skills-bundle/guanvis/references/api-reference.md +476 -0
  222. package/skills-bundle/guanvis/references/builder-reference.md +1676 -0
  223. package/skills-bundle/guanvis/references/chart-properties.md +2101 -0
  224. package/skills-bundle/guanvis/references/checkout-editing.md +53 -0
  225. package/skills-bundle/guanvis/references/complex-report-pro-patterns.md +398 -0
  226. package/skills-bundle/guanvis/references/dir-and-page-management.md +48 -0
  227. package/skills-bundle/guanvis/references/metric-chart-reference.md +258 -0
  228. package/skills-bundle/guanvis/references/publish-and-constraints.md +60 -0
  229. package/skills-bundle/guanvis/references/selector-reference.md +431 -0
  230. package/skills-bundle/guanvis/references/tableau-migration.md +73 -0
  231. package/skills-bundle/guanvis/references/theme.md +123 -0
  232. package/skills-bundle/guanvis/references/troubleshooting.md +25 -0
  233. package/skills-bundle/guanvis/references/validation-and-chart-patterns.md +205 -0
  234. package/skills-bundle/guanwf/SKILL.md +543 -0
  235. package/skills-bundle/guanwf/references/ETL_AI_DEVELOP.md +456 -0
  236. package/skills-bundle/guanwf/references/TASK_NODE_CONTRACTS.md +64 -0
  237. package/skills-bundle/guanwf/references/WORKFLOW_DSL.md +536 -0
  238. package/skills-bundle/guanwf/references/WORKFLOW_NODES.md +166 -0
  239. package/skills-bundle/js/SKILL.md +145 -0
@@ -0,0 +1,500 @@
1
+ # 指标树创建 / 修改指引
2
+
3
+ 本文用于指导 Agent 创建、配置和原地修改指标树。查询、搜索、归因分析仍优先使用 `guancli metric_attribution`;写操作使用 `guanmetric metric-tree`。
4
+
5
+ ## 读取顺序
6
+
7
+ 处理指标树需求时按需读取:
8
+
9
+ 1. 先读本文,判断用户是创建壳、创建并配置维度拆解、创建并配置指标拆解、修改配置、改名、移动,还是目录管理。
10
+ 2. 如果需要根指标或下级指标,读取 `metric-common-fields.md` 的环境、资源查询和通用字段规则。
11
+ 3. 如果用户需要先创建根指标或子指标,再建指标树,按 `metric-mutation.md` 完成指标创建闭环,拿到指标 ID 后再回到本文。
12
+ 4. 如果指标拆解里出现复合指标公式,读取 `metric-composite-mutation.md` 和 `metric-expression-rules.md`,理解 `formula` 中 `[metricId]` 的含义。
13
+ 5. 构造请求或解析响应前读取 `metric-tree-api-contracts.md`,不要混用详情、列表和写入模型。
14
+ 6. 只在最终提交时使用 `guanmetric metric-tree`;不要用裸 `fetch` 调指标树写接口。
15
+
16
+ ## 能力边界
17
+
18
+ `guanmetric metric-tree` 覆盖:
19
+
20
+ - `create`:创建指标树。
21
+ - `get`:回读指标树详情。
22
+ - `rename`:原地更新指标树名称。
23
+ - `move`:原地移动指标树目录。
24
+ - `update-config`:原地更新指标树配置。
25
+ - `delete`:默认展示待删除详情,追加 `--confirm` 后删除指标树。
26
+
27
+ 不要用删除重建模拟指标树编辑。指标树 ID 可能被归因入口、页面链接、目录和外部系统引用,删除重建会造成断链。
28
+
29
+ ## 前端同款流程
30
+
31
+ `guandata-web` 前端创建指标树分两步:
32
+
33
+ 1. 创建壳:选择根指标,提交 `{ metricId, parentDirId, name }` 到 `POST /api/metric-platform/metric-tree/add`。
34
+ 2. 编辑配置:进入 `/metrics-store/hierarchy/{metricTreeId}/edit/dimension`,保存时提交 `{ name, config }` 到 `POST /api/metric-platform/metric-tree/{metricTreeId}/update-config`。
35
+
36
+ 因此 Agent 推荐也按两阶段执行:先创建指标树壳,再按用户确认的配置执行 `update-config`。只有用户明确要求“创建时带完整 config”时,才在 create payload 中携带 `config`。
37
+
38
+ 默认名称可模拟前端格式:
39
+
40
+ ```text
41
+ 未命名的指标树_YYYY_MM_DD_HH_mm_ss
42
+ ```
43
+
44
+ 默认配置应模拟前端初始化。根指标必须有时间维度;没有时间维度时不得创建指标树,应提示用户先为指标配置时间维度。未显式指定对比方式时,CLI 会默认生成同环比 + 日环比配置,并开启对比和贡献计算:
45
+
46
+ ```json
47
+ {
48
+ "timeComparisonSetting": {
49
+ "advType": "COMPARATIVE",
50
+ "advValue": {
51
+ "advType": "COMPARATIVE",
52
+ "dateFdId": "<root_metric_time_dim_fd_id>",
53
+ "dateFdName": "<root_metric_time_dim_name>",
54
+ "valueType": "RAWDATA",
55
+ "offset": 1,
56
+ "offsetType": "DAY",
57
+ "granularity": "DAY",
58
+ "window": {
59
+ "period": ["<today:YYYY-MM-DD>"],
60
+ "withMacro": false
61
+ },
62
+ "mode": "NORMAL"
63
+ }
64
+ },
65
+ "comparisonEnabled": true,
66
+ "contributionCalcEnabled": true,
67
+ "dimensionDecompositionContent": {
68
+ "decomposableDimensionIds": [],
69
+ "multipleDimensionEnabled": false,
70
+ "multipleDimensionList": [],
71
+ "nodeNum": 5,
72
+ "orderBy": "valueDesc",
73
+ "drillDownLevels": []
74
+ },
75
+ "metricDecompositionContent": {
76
+ "metricRelationTree": [
77
+ {
78
+ "metricId": "<root_metric_id>",
79
+ "parentId": null,
80
+ "operation": "",
81
+ "decomposeMode": "calculation"
82
+ }
83
+ ]
84
+ },
85
+ "reportDisplaySetting": {
86
+ "conclusionSetting": null
87
+ }
88
+ }
89
+ ```
90
+
91
+ 如果根指标有时间维度,前端会初始化同环比 `timeComparisonSetting`。当前 CLI 已内置同款默认生成器:当提交的 config 未包含 `timeComparisonSetting` 或为 `null` 时,会基于根指标时间维度补齐默认配置,并把 `comparisonEnabled`、`contributionCalcEnabled` 置为 `true`。
92
+
93
+ ## 意图判断
94
+
95
+ | 用户意图 | 判断 | 推荐流程 |
96
+ | --- | --- | --- |
97
+ | 给某指标建一个指标树 | 只创建壳 | 查根指标、查 `METRIC_TREE` 目录、计划确认、create |
98
+ | 按地区/渠道拆某指标 | 维度拆解 | 查根指标适用维度、生成 config、create 后 update-config |
99
+ | A = B + C / A 拆成 B、C | 指标拆解计算模式 | 解析公式、查指标 ID、生成 `metricRelationTree` |
100
+ | A 关系拆解为 B、C | 指标拆解关系模式 | 生成 relation 模式,子节点 operation 为空 |
101
+ | 根指标或子指标是复合指标 | 自动读取复合公式 | 根据 `formula` 可控展开 |
102
+ | 打开贡献分析/贡献排序 | 时间对比 + 贡献计算 | 必须根指标时间配置合法 |
103
+ | 改名 | 原地重命名 | `metric-tree rename` |
104
+ | 移动目录 | 原地移动 | 查 `METRIC_TREE` 目录,`metric-tree move` |
105
+ | 删除指标树 | 高风险删除 | `metric-tree delete <id>` 预览,明确确认后追加 `--confirm` |
106
+ | 重建同名指标树替换旧的 | 高风险 | 阻断并说明断链,除非用户明确二次确认 |
107
+
108
+ ## 删除流程
109
+
110
+ 删除前必须先读取并展示指标树详情:
111
+
112
+ ```bash
113
+ guanmetric metric-tree delete <metric_tree_id>
114
+ ```
115
+
116
+ 默认不会提交删除。用户确认目标无误后执行:
117
+
118
+ ```bash
119
+ guanmetric metric-tree delete <metric_tree_id> --confirm
120
+ ```
121
+
122
+ 需要查看完整调用计划但仍不写入时使用:
123
+
124
+ ```bash
125
+ guanmetric metric-tree delete <metric_tree_id> --confirm --dry-run
126
+ ```
127
+
128
+ 服务端最终校验删除权限。删除会使指标树 ID、归因入口和外部链接失效,不能恢复,也不能用删除重建模拟改名、移动或配置编辑。
129
+
130
+ ## 资源解析规则
131
+
132
+ 使用当前已登录环境,不主动询问 profile;写操作前可执行:
133
+
134
+ ```bash
135
+ guancli auth status
136
+ ```
137
+
138
+ 根指标和下级指标:
139
+
140
+ - 有 ID:用 `guancli metric get <metric_id> --brief` 或 `-f json` 回读确认。
141
+ - 只有名称:用 `guancli metric search <keyword> -f json` 搜索;多候选必须让用户指定 ID。
142
+ - 需要配置维度、时间对比或复合指标展开时,必须用 `guancli metric get <metric_id> --raw` 读取完整详情。
143
+
144
+ 指标树父目录来自 `METRIC_TREE` 目录体系:
145
+
146
+ ```bash
147
+ guancli metric_attribution tree -f json
148
+ ```
149
+
150
+ 不要使用 `guancli metric tree` 返回的 `METRIC_PLATFORM` 指标目录 ID 创建指标树。只有目录名时,按路径唯一匹配;重复时必须让用户指定目录 ID。
151
+
152
+ ## 维度拆解配置规则
153
+
154
+ 维度拆解需要先读取根指标详情,确认 `applicableDims`、`publicDimensionMap` 和 `timeDim`。
155
+
156
+ 规则:
157
+
158
+ - 拆解维度必须在根指标 `applicableDims` 中。
159
+ - 不要把根指标时间维度作为拆解维度。
160
+ - 交叉维度每组至少 2 个维度,最多 5 个维度。
161
+ - 交叉维度中的每个维度必须已经在 `decomposableDimensionIds` 中。
162
+ - `multipleDimensionEnabled=true` 时,至少保留一组合法交叉维度;长度小于等于 1 的组合应提前过滤并提示。
163
+ - `drillDownLevels` 统一写 `dimensionIds`,不要写历史 `dimensionId`。
164
+ - `nodeNum` 默认 5,合法范围 5-20。
165
+ - `orderBy` 默认 `valueDesc`。
166
+ - `contributionCalcEnabled=false` 时只允许 `valueAsc` 和 `valueDesc`。
167
+ - 关闭对比时必须同时关闭贡献计算。
168
+ - 关闭贡献计算时,贡献排序要降级:`contributionAsc -> valueAsc`,`contributionDesc -> valueDesc`。
169
+
170
+ ## 时间对比和贡献计算
171
+
172
+ 根指标没有时间维度时,不允许创建指标树;必须提示用户先为指标配置时间维度。
173
+
174
+ 根指标已经是同环比衍生指标时,不要再配置时间对比。
175
+
176
+ 如果启用贡献计算:
177
+
178
+ - 必须 `comparisonEnabled=true`。
179
+ - `timeComparisonSetting` 必须合法。
180
+ - 排序可使用 `contributionAsc` 或 `contributionDesc`。
181
+
182
+ 如果用户只说“按贡献排序”,Agent 应解释该能力依赖时间对比和贡献计算,先确认时间配置。
183
+
184
+ ## 指标拆解公式理解
185
+
186
+ 用户可能直接给出自然语言公式,Agent 需要转换为 `metricDecompositionContent.metricRelationTree`。
187
+
188
+ 示例输入:
189
+
190
+ ```text
191
+ 销售额 = 订单数 * 客单价
192
+ 利润 = 销售额 - 成本
193
+ 转化率 = 下单人数 / 访问人数
194
+ ```
195
+
196
+ 处理流程:
197
+
198
+ 1. 识别公式左侧父指标和右侧子指标。
199
+ 2. 如果用户只给右侧,例如“按 B + C 拆 A”,父指标来自当前根指标或上下文。
200
+ 3. 对公式中的每个指标名解析唯一指标 ID;不能按名称猜。
201
+ 4. 构造关系树节点:
202
+ - 父节点必须存在。
203
+ - 第一个子节点 `operation` 为空。
204
+ - 第二个及之后子节点的 `operation` 取它前面的运算符。
205
+ 5. 输出计划时展示用户公式、ID 公式和关系表。
206
+
207
+ 公式:
208
+
209
+ ```text
210
+ 销售额 = 订单数 * 客单价
211
+ ```
212
+
213
+ 生成:
214
+
215
+ ```json
216
+ [
217
+ {
218
+ "metricId": "metric_sales",
219
+ "parentId": null,
220
+ "operation": "",
221
+ "decomposeMode": "calculation"
222
+ },
223
+ {
224
+ "metricId": "metric_orders",
225
+ "parentId": "metric_sales",
226
+ "operation": "",
227
+ "decomposeMode": "calculation"
228
+ },
229
+ {
230
+ "metricId": "metric_aov",
231
+ "parentId": "metric_sales",
232
+ "operation": "*",
233
+ "decomposeMode": "calculation"
234
+ }
235
+ ]
236
+ ```
237
+
238
+ 关系拆解:
239
+
240
+ ```text
241
+ 销售额 关系拆解为 线上销售额、线下销售额
242
+ ```
243
+
244
+ 生成:
245
+
246
+ ```json
247
+ [
248
+ {
249
+ "metricId": "metric_sales",
250
+ "parentId": null,
251
+ "operation": "",
252
+ "decomposeMode": "relation"
253
+ },
254
+ {
255
+ "metricId": "metric_online_sales",
256
+ "parentId": "metric_sales",
257
+ "operation": "",
258
+ "decomposeMode": "calculation"
259
+ },
260
+ {
261
+ "metricId": "metric_offline_sales",
262
+ "parentId": "metric_sales",
263
+ "operation": "",
264
+ "decomposeMode": "calculation"
265
+ }
266
+ ]
267
+ ```
268
+
269
+ ## 公式能力边界
270
+
271
+ 前端指标树关系模型是“父节点 = 直接子指标按顺序四则运算”。因此:
272
+
273
+ - 支持 `A = B + C - D`、`A = B * C`、`A = B / C`。
274
+ - 支持多层级:对子指标继续配置子节点。
275
+ - 不要无损承诺任意括号优先级,例如 `A = (B + C) / D`。
276
+
277
+ 遇到括号、常量、函数、条件表达式或窗口表达式时:
278
+
279
+ 1. 如果括号内已有线上复合指标,例如 `X = B + C`,用 `X` 作为中间节点。
280
+ 2. 如果没有中间指标,提示用户指标树不能完整表达该公式优先级,建议先创建中间复合指标。
281
+ 3. 不要把 `A = (B + C) / D` 强行转成 `A = B + C / D`。
282
+
283
+ ## 复合指标自动拆解
284
+
285
+ 触发场景:
286
+
287
+ - 根指标本身是 `subType=COMPOSITE`。
288
+ - 用户公式中的某个子指标是复合指标。
289
+ - 用户明确说“按复合指标公式展开”。
290
+
291
+ 处理规则:
292
+
293
+ 1. 对每个参与指标执行 `guancli metric get <metric_id> --raw`。
294
+ 2. 如果 `subType=COMPOSITE`,读取其 `formula` 字段。
295
+ 3. 从 `formula` 中提取 `[metricId]` 引用和 `+ - * /` 运算符。
296
+ 4. 把复合指标作为节点保留,再把公式引用指标作为它的子节点。
297
+ 5. 递归处理公式里的复合指标。
298
+ 6. 设置 `decomposeMode=calculation`。
299
+ 7. 检测循环引用和重复路径;同一条路径中重复出现的指标必须停止展开并提示。
300
+ 8. 默认最大递归深度为 3;超过时停止并在计划中标记“未展开,需要确认”。
301
+
302
+ 根指标是复合指标:
303
+
304
+ ```text
305
+ 客单价(metric_aov) = 销售额(metric_sales) / 订单数(metric_orders)
306
+ ```
307
+
308
+ 生成:
309
+
310
+ ```json
311
+ [
312
+ {
313
+ "metricId": "metric_aov",
314
+ "parentId": null,
315
+ "operation": "",
316
+ "decomposeMode": "calculation"
317
+ },
318
+ {
319
+ "metricId": "metric_sales",
320
+ "parentId": "metric_aov",
321
+ "operation": "",
322
+ "decomposeMode": "calculation"
323
+ },
324
+ {
325
+ "metricId": "metric_orders",
326
+ "parentId": "metric_aov",
327
+ "operation": "/",
328
+ "decomposeMode": "calculation"
329
+ }
330
+ ]
331
+ ```
332
+
333
+ 注意:前端关系图用 `metricId` 作为节点 ID,同一指标 ID 多父节点可能产生展示冲突。对子复合指标展开时,如果会让同一指标出现在多个父节点下,推荐默认不展开该子复合指标,并在计划中说明。用户可选择:
334
+
335
+ - 不展开子复合指标,只保留复合指标节点。
336
+ - 展开子复合指标,但调整顶层公式,避免重复节点。
337
+ - 先创建新的中间指标或调整拆解公式。
338
+
339
+ ## 指标树创建计划
340
+
341
+ 创建计划确认前,不生成最终 config,不执行 dry-run,不真实写入。
342
+
343
+ 计划至少包含:
344
+
345
+ - 当前环境。
346
+ - 指标树名称。
347
+ - 根指标:ID、名称、主题、时间维度、指标类型。
348
+ - 目标指标树目录:路径、ID。
349
+ - 维度拆解配置:拆解维度、交叉维度、下钻层级、展示个数、排序。
350
+ - 指标拆解配置:每条父子关系、模式、运算符、来源。
351
+ - 指标拆解来源:用户公式、复合指标公式、手工关系。
352
+ - 自动展开结果:展开了哪些复合指标,跳过了哪些复合指标,以及原因。
353
+ - 时间对比和贡献计算开关。
354
+ - 后续步骤:create dry-run、真实 create、update-config dry-run、真实 update-config、回读和可选归因查询。
355
+
356
+ 关系表示例:
357
+
358
+ | 父指标 | 子指标 | 模式 | 运算符 | 来源 |
359
+ | --- | --- | --- | --- | --- |
360
+ | 销售额 | 订单数 | calculation | 空 | 用户公式 |
361
+ | 销售额 | 客单价 | calculation | * | 用户公式 |
362
+ | 客单价 | 商品单价 | calculation | 空 | 复合指标公式 |
363
+ | 客单价 | 购买件数 | calculation | * | 复合指标公式 |
364
+
365
+ ## JSON 生成
366
+
367
+ 建议生成两个 JSON。
368
+
369
+ `metric_tree_create.json`:
370
+
371
+ ```json
372
+ {
373
+ "metricId": "<root_metric_id>",
374
+ "name": "<tree_name>",
375
+ "parentDirId": "<metric_tree_dir_id>"
376
+ }
377
+ ```
378
+
379
+ `metric_tree_config.json`:
380
+
381
+ ```json
382
+ {
383
+ "config": {
384
+ "timeComparisonSetting": null,
385
+ "comparisonEnabled": true,
386
+ "contributionCalcEnabled": true,
387
+ "dimensionDecompositionContent": {
388
+ "decomposableDimensionIds": ["fd-region", "fd-channel"],
389
+ "multipleDimensionEnabled": true,
390
+ "multipleDimensionList": [["fd-region", "fd-channel"]],
391
+ "nodeNum": 5,
392
+ "orderBy": "valueDesc",
393
+ "drillDownLevels": [
394
+ {
395
+ "dimensionIds": ["fd-region"]
396
+ }
397
+ ]
398
+ },
399
+ "metricDecompositionContent": {
400
+ "metricRelationTree": [
401
+ {
402
+ "metricId": "metric-root",
403
+ "parentId": null,
404
+ "operation": "",
405
+ "decomposeMode": "calculation"
406
+ },
407
+ {
408
+ "metricId": "metric-child-1",
409
+ "parentId": "metric-root",
410
+ "operation": "",
411
+ "decomposeMode": "calculation"
412
+ },
413
+ {
414
+ "metricId": "metric-child-2",
415
+ "parentId": "metric-root",
416
+ "operation": "+",
417
+ "decomposeMode": "calculation"
418
+ }
419
+ ]
420
+ },
421
+ "reportDisplaySetting": {
422
+ "conclusionSetting": null
423
+ }
424
+ }
425
+ }
426
+ ```
427
+
428
+ 如果只创建壳,不生成 config;若用户要求“Web 同款可编辑初始配置”,可生成默认 config 并执行 `update-config`。
429
+
430
+ ## 执行顺序
431
+
432
+ 创建:
433
+
434
+ ```bash
435
+ guanmetric metric-tree create --file metric_tree_create.json --dry-run
436
+ guanmetric metric-tree create --file metric_tree_create.json
437
+ ```
438
+
439
+ 创建成功后拿到 `metricTreeId`。如果有配置:
440
+
441
+ ```bash
442
+ guanmetric metric-tree update-config <metric_tree_id> --file metric_tree_config.json --dry-run
443
+ guanmetric metric-tree update-config <metric_tree_id> --file metric_tree_config.json
444
+ ```
445
+
446
+ 原地修改:
447
+
448
+ ```bash
449
+ guanmetric metric-tree rename <metric_tree_id> 新名称 --dry-run
450
+ guanmetric metric-tree move <metric_tree_id> --parent-dir-id <metric_tree_dir_id> --dry-run
451
+ guanmetric metric-tree update-config <metric_tree_id> --file metric_tree_config.json --dry-run
452
+ ```
453
+
454
+ ## 验证和回读
455
+
456
+ 回读详情:
457
+
458
+ ```bash
459
+ guanmetric metric-tree get <metric_tree_id>
460
+ guancli metric_attribution get <metric_tree_id> -f json
461
+ ```
462
+
463
+ 验证维度拆解:
464
+
465
+ ```bash
466
+ guancli metric_attribution query <metric_tree_id> --target dim --dim <维度名>
467
+ ```
468
+
469
+ 验证指标拆解:
470
+
471
+ ```bash
472
+ guancli metric_attribution query <metric_tree_id> --target index
473
+ ```
474
+
475
+ 不要把 dry-run 成功描述成指标树已经创建或修改成功。只有真实写入并回读确认后,才能报告线上更新成功。
476
+
477
+ ## 命令和接口速查
478
+
479
+ | 操作 | 命令 | 后端接口 |
480
+ | --- | --- | --- |
481
+ | 创建指标树 | `guanmetric metric-tree create` | `POST /api/metric-platform/metric-tree/add` |
482
+ | 回读指标树 | `guanmetric metric-tree get` | `GET /api/metric-platform/metric-tree/{id}` |
483
+ | 重命名 | `guanmetric metric-tree rename` | `POST /api/metric-platform/metric-tree/{id}/rename` |
484
+ | 移动 | `guanmetric metric-tree move` | `POST /api/metric-platform/metric-tree/{id}/move` |
485
+ | 更新配置 | `guanmetric metric-tree update-config` | `POST /api/metric-platform/metric-tree/{id}/update-config` |
486
+ | 查询目录树 | `guanmetric metric-tree directory tree` | `GET /api/directory/METRIC_TREE/authorized-tree` |
487
+ | 目录详情 | `guanmetric metric-tree directory get` | `GET /api/directory/METRIC_TREE` |
488
+ | 创建目录 | `guanmetric metric-tree directory create` | `POST /api/metric-platform/directory/create` |
489
+ | 编辑目录 | `guanmetric metric-tree directory edit` | `POST /api/metric-platform/directory/{id}/update` |
490
+ | 删除目录 | `guanmetric metric-tree directory delete` | `POST /api/metric-platform/directory/{id}/delete` |
491
+
492
+ ## 后续 CLI 增强建议
493
+
494
+ 当前 skill 可通过 `guancli` 查询、手写 JSON 和 `guanmetric metric-tree` 完成闭环。后续可考虑新增:
495
+
496
+ - `metric-tree init-config <root_metric_id>`:按前端初始化逻辑生成默认 config。
497
+ - `metric-tree validate-config`:离线校验维度、交叉维度、指标关系树和时间对比开关。
498
+ - `metric-tree plan`:从简化 DSL 或用户公式生成 create/config JSON。
499
+
500
+ 编辑载荷和公式/格式复制使用 `--raw` 的后端详情,成功后从后端 `response` 读取字段;不能把后端响应当成 canonical envelope。普通机器发现使用 `-f json` 并从 `data` 取值,canonical 详情不承诺完整编辑字段。
@@ -0,0 +1,74 @@
1
+ # 指标创建校验职责
2
+
3
+ 本文件记录 `guanmetric flow`、BI 后端和 Web 创建页之间的校验边界。指标业务校验采用差集原则:**Flow 只实现当前 Web 创建页已有、但当前后端创建链路没有覆盖的规则**。后端已有的规则不复制;前后端都没有的规则也不由 Flow 擅自新增。Flow 自身的跨指标编排契约单独列出,不属于单指标业务校验差集。
4
+
5
+ ## 基线
6
+
7
+ - BI 后端:`guandata-core` `origin/master@baeb7d55ca`
8
+ - Web 前端:`guandata-web` `origin/master@633f656934`
9
+ - Flow:`guanmetric` `schemaVersion=1.0`
10
+
11
+ 前后端主线变化后,应重新核对本表。未合入主线的字段或功能不进入 Flow 稳定契约。
12
+
13
+ 维护时按规则粒度计算差集,不按字段名粗略判断:同一字段可能在草稿和发布态、不同指标类型下由不同层负责。只有 `Web=true && Backend=false` 才能进入 Flow 单指标业务校验;后端补齐后,必须同步删除 Flow 规则及其“应阻断”测试,改成验证请求交给后端。
14
+
15
+ ## 单指标业务校验差集
16
+
17
+ | 规则 | Web 创建页 | BI 后端创建链路 | Flow 处理 |
18
+ | --- | --- | --- | --- |
19
+ | 草稿名称最长 50,且仅含中文、字母、数字、下划线 | 三类指标表单始终校验 | `MetricAbility.isNameValid` 仅在 `publish=true` 执行;草稿只校验非空 | `publish=false` 时校验;发布态不重复 |
20
+ | 英文名最长 50,且仅含字母、数字、下划线 | 三类指标表单校验 | 只校验英文名重复,不校验格式和长度 | 校验格式和长度 |
21
+ | 业务口径最长 1000 | `MetricBusinessSection.descRules` | 只校验非空 | 校验最大长度 |
22
+ | 原子字段来源模式必须同时有 `fdId` 和 `aggrType` | 两个字段分别必填 | `onlyOneExisted` 只保证字段来源组至少有一个值,未保证两个都存在 | 仅在二者一有一无时阻断;二者都无由后端处理 |
23
+ | 普通衍生必须选择 `baseMetricId` 和 `deriveSetting.advType` | 普通/快捷创建表单必填 | DTO 将两者作为可空值,普通衍生创建链路未统一拒绝缺失值 | `deriveType=ORDINARY` 时校验两个字段 |
24
+ | 自定义业务属性文本长度 | `BizAttrs.tsx` 根据在线配置限制短文本 50、长文本 200 | 普通创建 DTO 不校验配置中的文本长度 | 复用在线属性配置校验文本长度;尚未声称覆盖全部表单交互约束 |
25
+ | 原子指标“口径相同但适用维度不同”冲突 | 发布前调用 save-precheck 并要求二次确认 | 创建接口不等价于前端确认门禁;另有权威 save-precheck | 调用同一后端 save-precheck;有冲突时阻断自动创建 |
26
+ | 草稿只能引用已发布指标 | 单指标公式和衍生选择器不提供草稿指标 | 草稿创建只做部分引用类型校验,未统一校验引用状态 | `acceptance.mode=draft` 禁止批内引用 |
27
+
28
+ 时间维度的前端规则依赖页面实时计算出的候选时间字段集合。Flow 当前请求体只有字段 ID,没有同等候选元数据,因此本阶段不复制一个不完整的本地判断;后续若要补齐,必须复用与 Web 相同的权威字段来源,而不能仅凭 `applicableDims` 猜测字段类型。
29
+
30
+ ## 创建计划 Excel 门禁
31
+
32
+ Excel 是用户确认前的语义计划,不应包含已知不可创建的模型。生成 `*.ai_mapped.xlsx` 或标准创建计划 Excel 前,Agent 先建立本批“指标名称 → 指标类型”索引;复合指标公式引用本批衍生指标时直接停止生成,改为引用原子/复合指标,或在业务语义适用时改建组合衍生指标。`template normalize --check-only` 提供第二道确定性门禁,以 `TEMPLATE_INVALID_REFERENCE` 和具体 Sheet/row/column 返回错误。
33
+
34
+ 这条规则不放入 `flow plan`:后端创建接口已有复合引用类型校验,Flow 再做会重复维护;Excel 门禁的目的则是在形成用户评审产物之前阻止错误建模,职责阶段不同。
35
+
36
+ ## 明确不重复的后端规则
37
+
38
+ | 校验面 | 后端权威实现 | Flow 行为 |
39
+ | --- | --- | --- |
40
+ | 名称/描述/责任人等必填、发布态名称格式和长度 | `Create*MetricRO.paramCheck`、`MetricAbility.*ValidationCheck` | 不重复;由创建接口返回结构化错误 |
41
+ | 项目、目录、资源与创建权限 | `checkProjectAndMetricAuth`、Spring `METRIC_PLATFORM / CREATE` | 不根据本地快照判断权限 |
42
+ | 原子来源类型互斥、数据集字段、表达式与适用维度 | `CreateAtomicMetricRO.paramCheck`、`checkAtomicSourceField`、`getByFdIdsInDs` | 不复制字段/聚合兼容矩阵 |
43
+ | 名称、英文名和指标定义重复 | `MetricAbility.*MetricValidationCheck` | 不复制重复判定 |
44
+ | 复合/组合衍生公式、引用类型、引用状态和嵌套深度 | `CompositeDerivedFormulaValidator`、`compositeMetricReferenceTypeValidationCheck`、`validateCompositeDerivedMetricReferences`、`checkNestTimes` | 既有指标由后端裁决;仅保留批内依赖拓扑检查 |
45
+ | 期末值、业务限定和业务指标关联 | `DerivedMetricBusinessValidator`、`derivedMetricValidationCheck`、`validateBizMetricCanAssociateForCreate` | 不复制业务类型矩阵和关联状态规则 |
46
+
47
+ ## Flow 编排契约(非单指标业务校验)
48
+
49
+ | 编排面 | 为什么只能由 Flow 负责 |
50
+ | --- | --- |
51
+ | 逻辑 key、批内占位符、未知引用、自引用、循环依赖、稳定拓扑顺序 | Web 单指标页面和后端单次创建接口没有批次概念 |
52
+ | 计划哈希、目标环境、断点状态和重复创建保护 | 后端没有跨多次创建请求的计划状态 |
53
+ | 发布审批、`canUse` 和数据查询可用性 | Flow 负责逐项回读和验收,未可用时不创建下游 |
54
+
55
+ ## 错误归属
56
+
57
+ Flow 不匹配后端中英文错误文案。后端创建链路在校验后还会写指标、写草稿、同步血缘/权限并执行上线或审批;当前没有覆盖全链路的原子性或幂等契约。因此所有未返回可记录 `metricId` 的创建错误都按结果不确定处理:
58
+
59
+ - 结构化 API 错误:保留 `businessStatus`、`httpStatus`、`method`、`path` 和原始 `message`,记录 `blocked/reconcile`、`FLOW_CREATE_RESULT_UNKNOWN`。
60
+ - 非结构化子进程错误、断线或超时:记录 `blocked/reconcile`、`FLOW_CREATE_RESULT_UNKNOWN`。
61
+ - 响应成功但取不到创建 ID:无法安全判断和续跑,记录 `blocked/reconcile`、`FLOW_CREATE_RESULT_UNKNOWN`。
62
+
63
+ 状态文件的可选 `error` 字段保存 `code`、`kind`、`httpStatus`、`businessStatus`、`method`、`path` 和服务端原始 `message`。这是 Flow 1.0 的向后兼容增量字段。
64
+
65
+ ## 主线证据
66
+
67
+ - Web 表单:`atomic-rules.ts`、`composite-rules.ts`、`derived-rules.ts`、`MetricBusinessSection.tsx`、`BizAttrs.tsx`
68
+ - Web 保存编排:`MetricEdit.tsx`、`common/metric-save-precheck.ts`
69
+ - 后端路由与 PAT:`MetricManagementNgController.java`
70
+ - 后端请求和基础参数:`application/metric_platform/request/MetricRO.scala`
71
+ - 后端业务编排:`application/metric_platform/MetricUseCase.scala`
72
+ - 后端定义重复和发布校验:`domain/metric_platform/ability/impl/MetricAbilityImpl.scala`、`domain/metric_platform/ability/util/ParamCheckUtil.scala`
73
+
74
+ 普通创建继续使用现有原子、复合、衍生创建接口。复合和衍生当前没有单独的 create-precheck,本阶段沿用创建请求中的后端权威校验,不新增接口。