@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.
Files changed (35) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +23 -3
  3. package/bin/run.js +14 -1
  4. package/package.json +6 -6
  5. package/skills/guanmetric/SKILL.md +53 -8
  6. package/skills/guanmetric/evals/evals.json +117 -0
  7. package/skills/guanmetric/evals/fixtures/atomic-detail-read-model.json +18 -0
  8. package/skills/guanmetric/evals/fixtures/confirmed-template-summary.json +12 -0
  9. package/skills/guanmetric/evals/fixtures/create-result-unknown-state.json +13 -0
  10. package/skills/guanmetric/evals/forward-eval-2026-09-21.json +62 -0
  11. package/skills/guanmetric/references/metric-api-contract-examples.json +690 -0
  12. package/skills/guanmetric/references/metric-api-contract.schema.json +349 -0
  13. package/skills/guanmetric/references/metric-api-contracts.md +436 -0
  14. package/skills/guanmetric/references/metric-atomic-mutation.md +11 -0
  15. package/skills/guanmetric/references/metric-business-dictionary-api-contract-examples.json +53 -0
  16. package/skills/guanmetric/references/metric-business-dictionary-api-contract.schema.json +26 -0
  17. package/skills/guanmetric/references/metric-business-dictionary.md +4 -0
  18. package/skills/guanmetric/references/metric-composite-mutation.md +15 -17
  19. package/skills/guanmetric/references/metric-derived-mutation.md +14 -16
  20. package/skills/guanmetric/references/metric-excel-template.md +14 -4
  21. package/skills/guanmetric/references/metric-flow-generate-example.json +79 -0
  22. package/skills/guanmetric/references/metric-flow-generate.schema.json +93 -0
  23. package/skills/guanmetric/references/metric-flow.md +218 -0
  24. package/skills/guanmetric/references/metric-hierarchy-api-contract-examples.json +171 -0
  25. package/skills/guanmetric/references/metric-hierarchy-api-contract.schema.json +167 -0
  26. package/skills/guanmetric/references/metric-hierarchy-api-contracts.md +193 -0
  27. package/skills/guanmetric/references/metric-mutation.md +13 -9
  28. package/skills/guanmetric/references/metric-public-dimension-api-contract-examples.json +62 -0
  29. package/skills/guanmetric/references/metric-public-dimension-api-contract.schema.json +47 -0
  30. package/skills/guanmetric/references/metric-public-dimension.md +4 -0
  31. package/skills/guanmetric/references/metric-tree-api-contract-examples.json +277 -0
  32. package/skills/guanmetric/references/metric-tree-api-contract.schema.json +263 -0
  33. package/skills/guanmetric/references/metric-tree-api-contracts.md +53 -0
  34. package/skills/guanmetric/references/metric-tree-mutation.md +31 -3
  35. package/skills/guanmetric/references/metric-validation-ownership.md +74 -0
@@ -0,0 +1,171 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "source": {
4
+ "environment": "test71",
5
+ "capturedAt": "2026-09-21",
6
+ "note": "由 test71 隔离临时资源真实请求采集后脱敏;ID 和名称不可直接用于调用"
7
+ },
8
+ "project": {
9
+ "createRequest": {
10
+ "name": "经营指标",
11
+ "icon": "finance_subject",
12
+ "iconColor": "#1A827F"
13
+ },
14
+ "createResponse": {
15
+ "result": "ok",
16
+ "response": {
17
+ "id": "project_example"
18
+ }
19
+ },
20
+ "updateRequest": {
21
+ "name": "经营分析指标",
22
+ "icon": "binoculars_subject",
23
+ "iconColor": "#799BFF"
24
+ },
25
+ "updateResponse": {
26
+ "result": "ok",
27
+ "response": {
28
+ "id": "project_example"
29
+ }
30
+ },
31
+ "detailResponse": {
32
+ "result": "ok",
33
+ "response": {
34
+ "id": "project_example",
35
+ "domId": "example_domain",
36
+ "name": "经营分析指标",
37
+ "icon": "binoculars_subject",
38
+ "iconColor": "#799BFF",
39
+ "dirId": "dir_project_root",
40
+ "canManage": true,
41
+ "canUse": true
42
+ }
43
+ },
44
+ "listResponse": {
45
+ "result": "ok",
46
+ "response": [
47
+ {
48
+ "id": "project_example",
49
+ "domId": "example_domain",
50
+ "name": "经营分析指标",
51
+ "icon": "binoculars_subject",
52
+ "iconColor": "#799BFF",
53
+ "dirId": "dir_project_root",
54
+ "canManage": true,
55
+ "canUse": true
56
+ }
57
+ ]
58
+ },
59
+ "deleteResponse": {
60
+ "result": "ok",
61
+ "response": "delete success."
62
+ }
63
+ },
64
+ "directory": {
65
+ "createRequest": {
66
+ "name": "销售分析",
67
+ "parentDirId": "dir_project_root",
68
+ "dirType": "METRIC_PLATFORM"
69
+ },
70
+ "createResponse": {
71
+ "result": "ok",
72
+ "response": {
73
+ "dirId": "dir_sales",
74
+ "dirName": "销售分析",
75
+ "dirType": "METRIC_PLATFORM",
76
+ "parentDirId": "dir_project_root",
77
+ "parentDirName": "经营分析指标",
78
+ "dirPath": [
79
+ {
80
+ "dirId": "dir_global_root",
81
+ "dirName": "根目录"
82
+ },
83
+ {
84
+ "dirId": "dir_project_root",
85
+ "dirName": "经营分析指标"
86
+ },
87
+ {
88
+ "dirId": "dir_sales",
89
+ "dirName": "销售分析"
90
+ }
91
+ ]
92
+ }
93
+ },
94
+ "updateRequest": {
95
+ "name": "销售经营分析",
96
+ "parentDirId": "dir_project_root",
97
+ "dirType": "METRIC_PLATFORM"
98
+ },
99
+ "updateResponse": {
100
+ "result": "ok",
101
+ "response": {
102
+ "dirId": "dir_sales",
103
+ "dirName": "销售经营分析",
104
+ "dirType": "METRIC_PLATFORM",
105
+ "parentDirId": "dir_project_root",
106
+ "parentDirName": "经营分析指标",
107
+ "dirPath": [
108
+ {
109
+ "dirId": "dir_global_root",
110
+ "dirName": "根目录"
111
+ },
112
+ {
113
+ "dirId": "dir_project_root",
114
+ "dirName": "经营分析指标"
115
+ },
116
+ {
117
+ "dirId": "dir_sales",
118
+ "dirName": "销售经营分析"
119
+ }
120
+ ]
121
+ }
122
+ },
123
+ "detailResponse": {
124
+ "id": "dir_sales",
125
+ "parentDirId": "dir_project_root",
126
+ "name": "销售经营分析",
127
+ "type": "DIRECTORY",
128
+ "contents": [],
129
+ "canManage": true,
130
+ "canUse": true,
131
+ "ctime": "2026-09-21T10:15:32.00Z",
132
+ "utime": "2026-09-21T10:15:48.00Z",
133
+ "metricCnt": 0,
134
+ "allMetricCnt": 0
135
+ },
136
+ "treeResponse": {
137
+ "result": "ok",
138
+ "response": {
139
+ "id": "dir_project_root",
140
+ "parentDirId": "dir_global_root",
141
+ "name": "根目录",
142
+ "type": "DIRECTORY",
143
+ "contents": [
144
+ {
145
+ "id": "dir_sales",
146
+ "parentDirId": "dir_project_root",
147
+ "name": "销售经营分析",
148
+ "type": "DIRECTORY",
149
+ "contents": [],
150
+ "canManage": true,
151
+ "canUse": true,
152
+ "ctime": "2026-09-21T10:15:32.00Z",
153
+ "utime": "2026-09-21T10:15:48.00Z",
154
+ "metricCnt": 0,
155
+ "allMetricCnt": 0
156
+ }
157
+ ],
158
+ "canManage": true,
159
+ "canUse": true,
160
+ "ctime": "2026-09-21T10:15:19.00Z",
161
+ "utime": "2026-09-21T10:15:49.00Z",
162
+ "metricCnt": 0,
163
+ "allMetricCnt": 0
164
+ }
165
+ },
166
+ "deleteResponse": {
167
+ "result": "ok",
168
+ "response": "Directory deleted"
169
+ }
170
+ }
171
+ }
@@ -0,0 +1,167 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://guandata.dev/schemas/guanmetric/metric-hierarchy-api-contract-1.0.json",
4
+ "title": "GuanData metric project and directory API contract",
5
+ "description": "用于 Agent 构造指标主题/目录请求并解析真实后端响应。响应允许后端新增字段。",
6
+ "oneOf": [
7
+ { "$ref": "#/$defs/projectWriteRequest" },
8
+ { "$ref": "#/$defs/projectMutationResponse" },
9
+ { "$ref": "#/$defs/projectDetailResponse" },
10
+ { "$ref": "#/$defs/projectListResponse" },
11
+ { "$ref": "#/$defs/projectDeleteResponse" },
12
+ { "$ref": "#/$defs/directoryWriteRequest" },
13
+ { "$ref": "#/$defs/directoryMutationResponse" },
14
+ { "$ref": "#/$defs/directoryNode" },
15
+ { "$ref": "#/$defs/directoryTreeResponse" },
16
+ { "$ref": "#/$defs/directoryDeleteResponse" }
17
+ ],
18
+ "$defs": {
19
+ "nonEmptyString": {
20
+ "type": "string",
21
+ "minLength": 1
22
+ },
23
+ "projectWriteRequest": {
24
+ "type": "object",
25
+ "required": ["name", "icon", "iconColor"],
26
+ "properties": {
27
+ "name": { "$ref": "#/$defs/nonEmptyString" },
28
+ "icon": { "$ref": "#/$defs/nonEmptyString" },
29
+ "iconColor": { "$ref": "#/$defs/nonEmptyString" }
30
+ },
31
+ "additionalProperties": false
32
+ },
33
+ "project": {
34
+ "type": "object",
35
+ "required": ["id", "domId", "name", "icon", "iconColor", "dirId", "canManage", "canUse"],
36
+ "properties": {
37
+ "id": { "$ref": "#/$defs/nonEmptyString" },
38
+ "domId": { "$ref": "#/$defs/nonEmptyString" },
39
+ "name": { "$ref": "#/$defs/nonEmptyString" },
40
+ "icon": { "$ref": "#/$defs/nonEmptyString" },
41
+ "iconColor": { "$ref": "#/$defs/nonEmptyString" },
42
+ "dirId": { "$ref": "#/$defs/nonEmptyString" },
43
+ "canManage": { "type": "boolean" },
44
+ "canUse": { "type": "boolean" }
45
+ },
46
+ "additionalProperties": true
47
+ },
48
+ "projectMutationResponse": {
49
+ "type": "object",
50
+ "required": ["result", "response"],
51
+ "properties": {
52
+ "result": { "const": "ok" },
53
+ "response": {
54
+ "type": "object",
55
+ "required": ["id"],
56
+ "properties": { "id": { "$ref": "#/$defs/nonEmptyString" } },
57
+ "additionalProperties": true
58
+ }
59
+ },
60
+ "additionalProperties": true
61
+ },
62
+ "projectDetailResponse": {
63
+ "type": "object",
64
+ "required": ["result", "response"],
65
+ "properties": {
66
+ "result": { "const": "ok" },
67
+ "response": { "$ref": "#/$defs/project" }
68
+ },
69
+ "additionalProperties": true
70
+ },
71
+ "projectListResponse": {
72
+ "type": "object",
73
+ "required": ["result", "response"],
74
+ "properties": {
75
+ "result": { "const": "ok" },
76
+ "response": { "type": "array", "items": { "$ref": "#/$defs/project" } }
77
+ },
78
+ "additionalProperties": true
79
+ },
80
+ "projectDeleteResponse": {
81
+ "type": "object",
82
+ "required": ["result", "response"],
83
+ "properties": {
84
+ "result": { "const": "ok" },
85
+ "response": { "type": "string" }
86
+ },
87
+ "additionalProperties": true
88
+ },
89
+ "directoryWriteRequest": {
90
+ "type": "object",
91
+ "required": ["name", "parentDirId", "dirType"],
92
+ "properties": {
93
+ "name": { "$ref": "#/$defs/nonEmptyString" },
94
+ "parentDirId": { "$ref": "#/$defs/nonEmptyString" },
95
+ "dirType": { "const": "METRIC_PLATFORM" }
96
+ },
97
+ "additionalProperties": false
98
+ },
99
+ "directoryPathItem": {
100
+ "type": "object",
101
+ "required": ["dirId", "dirName"],
102
+ "properties": {
103
+ "dirId": { "$ref": "#/$defs/nonEmptyString" },
104
+ "dirName": { "type": "string" }
105
+ },
106
+ "additionalProperties": true
107
+ },
108
+ "directoryMutationPayload": {
109
+ "type": "object",
110
+ "required": ["dirId", "dirName", "dirType", "parentDirId", "parentDirName", "dirPath"],
111
+ "properties": {
112
+ "dirId": { "$ref": "#/$defs/nonEmptyString" },
113
+ "dirName": { "$ref": "#/$defs/nonEmptyString" },
114
+ "dirType": { "const": "METRIC_PLATFORM" },
115
+ "parentDirId": { "$ref": "#/$defs/nonEmptyString" },
116
+ "parentDirName": { "type": "string" },
117
+ "dirPath": { "type": "array", "items": { "$ref": "#/$defs/directoryPathItem" } }
118
+ },
119
+ "additionalProperties": true
120
+ },
121
+ "directoryMutationResponse": {
122
+ "type": "object",
123
+ "required": ["result", "response"],
124
+ "properties": {
125
+ "result": { "const": "ok" },
126
+ "response": { "$ref": "#/$defs/directoryMutationPayload" }
127
+ },
128
+ "additionalProperties": true
129
+ },
130
+ "directoryNode": {
131
+ "type": "object",
132
+ "required": ["id", "parentDirId", "name", "type", "contents", "canManage", "canUse", "metricCnt", "allMetricCnt"],
133
+ "properties": {
134
+ "id": { "$ref": "#/$defs/nonEmptyString" },
135
+ "parentDirId": { "type": "string" },
136
+ "name": { "type": "string" },
137
+ "type": { "const": "DIRECTORY" },
138
+ "contents": { "type": "array", "items": { "$ref": "#/$defs/directoryNode" } },
139
+ "canManage": { "type": "boolean" },
140
+ "canUse": { "type": "boolean" },
141
+ "ctime": { "type": "string" },
142
+ "utime": { "type": "string" },
143
+ "metricCnt": { "type": "integer", "minimum": 0 },
144
+ "allMetricCnt": { "type": "integer", "minimum": 0 }
145
+ },
146
+ "additionalProperties": true
147
+ },
148
+ "directoryTreeResponse": {
149
+ "type": "object",
150
+ "required": ["result", "response"],
151
+ "properties": {
152
+ "result": { "const": "ok" },
153
+ "response": { "$ref": "#/$defs/directoryNode" }
154
+ },
155
+ "additionalProperties": true
156
+ },
157
+ "directoryDeleteResponse": {
158
+ "type": "object",
159
+ "required": ["result", "response"],
160
+ "properties": {
161
+ "result": { "const": "ok" },
162
+ "response": { "type": "string" }
163
+ },
164
+ "additionalProperties": true
165
+ }
166
+ }
167
+ }
@@ -0,0 +1,193 @@
1
+ # 指标主题与指标目录 CRUD API 契约
2
+
3
+ 本文供 Agent 创建和维护指标体系的组织骨架。真实脱敏样例见
4
+ `metric-hierarchy-api-contract-examples.json`,机器可读约束见
5
+ `metric-hierarchy-api-contract.schema.json`。
6
+
7
+ ## 证据与边界
8
+
9
+ - 2026-09-21 在 test71 使用隔离临时主题和目录完成 create、edit、detail/list/tree、delete 全链路实测。
10
+ - test71 实测使用 `robot@guandata.com` 的账号密码登录态。按本次范围不再创建 PAT;PAT 对照尚未验证,发布或 MR 的 `Domain and Contract` 不能将 PAT 兼容性标记为已通过。
11
+ - 临时目录和主题均在采集完成后删除,没有保留测试资源。
12
+ - 样例保留真实字段、空值和响应形态,ID、Domain 和名称已脱敏,不能直接用于真实调用。
13
+ - 后端响应可能增加字段,Schema 的响应对象允许 `additionalProperties: true`。
14
+ - 本契约只覆盖 `METRIC_PLATFORM` 指标目录,不可拿去修改 `METRIC_TREE`、`BUSINESS_METRIC` 等其他目录类型。
15
+ - 不包含指标 move 和指标 owner 转移;这是本轮明确排除的范围。
16
+
17
+ ## 命令速查
18
+
19
+ ```bash
20
+ # 主题
21
+ guanmetric project list
22
+ guanmetric project get <project_id>
23
+ guanmetric project create 经营指标 --dry-run
24
+ guanmetric project create 经营指标
25
+ guanmetric project edit <project_id> --name 经营分析指标 --dry-run
26
+ guanmetric project edit <project_id> --name 经营分析指标
27
+ guanmetric project delete <project_id>
28
+ guanmetric project delete <project_id> --confirm
29
+
30
+ # 指标目录
31
+ guanmetric directory tree <project_id>
32
+ guanmetric directory get <project_id> <dir_id>
33
+ guanmetric directory create 销售分析 --project-id <project_id> --dry-run
34
+ guanmetric directory create 销售分析 --project-id <project_id>
35
+ guanmetric directory edit <project_id> <dir_id> --name 销售经营分析 --dry-run
36
+ guanmetric directory edit <project_id> <dir_id> --name 销售经营分析
37
+ guanmetric directory delete <project_id> <dir_id>
38
+ guanmetric directory delete <project_id> <dir_id> --confirm
39
+ ```
40
+
41
+ 旧命令 `project-create` 和 `dir-create` 为兼容保留。新流程优先使用分组命令,便于发现完整 CRUD。
42
+
43
+ ## 接口矩阵
44
+
45
+ | 资源 | 操作 | 客户端方法与路径 | 权限 |
46
+ | --- | --- | --- | --- |
47
+ | Project | create | `POST /api/metric-platform/projects` | `METRIC_PLATFORM.CREATE` |
48
+ | Project | update | `POST /api/metric-platform/projects/{id}` | `METRIC_PLATFORM.UPDATE` |
49
+ | Project | detail | `GET /api/metric-platform/projects/{id}` | `METRIC_PLATFORM.READ` |
50
+ | Project | list | `GET /api/metric-platform/projects` | `METRIC_PLATFORM.READ` |
51
+ | Project | delete | `POST /api/metric-platform/projects/delete/{id}` | `METRIC_PLATFORM.DELETE` |
52
+ | Directory | create | `POST /api/metric-platform/directory/create` | `METRIC_PLATFORM.CREATE` |
53
+ | Directory | update | `POST /api/metric-platform/directory/{id}/update` | `METRIC_PLATFORM.UPDATE` |
54
+ | Directory | tree/read | `GET /api/directory/METRIC_PLATFORM/unauthorized-tree?projectId={id}` | `BASE.READ` |
55
+ | Directory | delete | `POST /api/metric-platform/directory/{id}/delete` | `METRIC_PLATFORM.DELETE` |
56
+
57
+ 以上是客户端真实路径;后端 Spring 路由是去掉 `/api` 后的同路径。新增写调用需要在正式交付前完成同一用户、同一 Domain 下账号密码与 PAT 对照验证。本次按用户选择只使用账号密码,因此 PAT 仍是明确的待验证门禁,不能由单元测试或账密实测替代。
58
+
59
+ ## Project 写模型
60
+
61
+ 创建和更新使用同一完整写模型:
62
+
63
+ ```json
64
+ {
65
+ "name": "经营分析指标",
66
+ "icon": "binoculars_subject",
67
+ "iconColor": "#799BFF"
68
+ }
69
+ ```
70
+
71
+ 更新不是自由 patch。`guanmetric project edit` 先读取详情,只从详情白名单提取
72
+ `name/icon/iconColor`,再合并命令行修改;`id/domId/dirId/canManage/canUse` 是读模型字段,不能原样提交。
73
+
74
+ 创建和更新成功响应相同:
75
+
76
+ ```json
77
+ {"result":"ok","response":{"id":"project_example"}}
78
+ ```
79
+
80
+ 只收到 HTTP 2xx 但 `result` 不为 `ok`,或 `response.id` 为空,不能认为成功。CLI 会在创建/编辑后回读详情,校验 `name/icon/iconColor` 与请求一致。
81
+
82
+ ## Project 详情与列表
83
+
84
+ 详情的真实结构:
85
+
86
+ ```json
87
+ {
88
+ "result": "ok",
89
+ "response": {
90
+ "id": "project_example",
91
+ "domId": "example_domain",
92
+ "name": "经营分析指标",
93
+ "icon": "binoculars_subject",
94
+ "iconColor": "#799BFF",
95
+ "dirId": "dir_project_root",
96
+ "canManage": true,
97
+ "canUse": true
98
+ }
99
+ }
100
+ ```
101
+
102
+ 列表的 `response` 是上述对象数组。`dirId` 是该主题对应的根目录 ID,创建一级指标目录时应把它作为 `parentDirId`。不要把主题 `id` 当目录 ID。
103
+
104
+ 删除成功响应是字符串:
105
+
106
+ ```json
107
+ {"result":"ok","response":"delete success."}
108
+ ```
109
+
110
+ 主题删除没有独立影响预检接口。CLI 默认只回读并展示目标;只有 `--confirm` 才提交,资源依赖和最终可删性由后端裁决。
111
+
112
+ ## Directory 写模型
113
+
114
+ 创建和更新都使用完整 `DirectoryAPI` 子集:
115
+
116
+ ```json
117
+ {
118
+ "name": "销售经营分析",
119
+ "parentDirId": "dir_project_root",
120
+ "dirType": "METRIC_PLATFORM"
121
+ }
122
+ ```
123
+
124
+ 三个字段均不可省略。更新目录时,即使只改名称,也必须保留当前 `parentDirId` 和固定的
125
+ `dirType=METRIC_PLATFORM`。`guanmetric directory edit` 会先读取目录树并显式构造写模型,禁止把树节点详情直接提交。
126
+
127
+ 创建/更新响应不是只有 ID,而是目录路径对象:
128
+
129
+ ```json
130
+ {
131
+ "result": "ok",
132
+ "response": {
133
+ "dirId": "dir_sales",
134
+ "dirName": "销售经营分析",
135
+ "dirType": "METRIC_PLATFORM",
136
+ "parentDirId": "dir_project_root",
137
+ "parentDirName": "经营分析指标",
138
+ "dirPath": [
139
+ {"dirId":"dir_global_root","dirName":"根目录"},
140
+ {"dirId":"dir_project_root","dirName":"经营分析指标"},
141
+ {"dirId":"dir_sales","dirName":"销售经营分析"}
142
+ ]
143
+ }
144
+ }
145
+ ```
146
+
147
+ CLI 在创建/编辑前校验父目录属于指定 Project 的 `METRIC_PLATFORM` 树,并在写后重新读取目录树,确认名称和父目录均与请求一致。不能把目录移动到自身或自己的子目录。
148
+
149
+ ## Directory 的“详情”来自目录树
150
+
151
+ 后端没有指标目录单条详情接口。权威读取接口返回整个 Project 的目录树:
152
+
153
+ ```http
154
+ GET /api/directory/METRIC_PLATFORM/unauthorized-tree?projectId={projectId}
155
+ ```
156
+
157
+ 树节点结构如下:
158
+
159
+ ```json
160
+ {
161
+ "id": "dir_sales",
162
+ "parentDirId": "dir_project_root",
163
+ "name": "销售经营分析",
164
+ "type": "DIRECTORY",
165
+ "contents": [],
166
+ "canManage": true,
167
+ "canUse": true,
168
+ "ctime": "2026-09-21T10:15:32.00Z",
169
+ "utime": "2026-09-21T10:15:48.00Z",
170
+ "metricCnt": 0,
171
+ "allMetricCnt": 0
172
+ }
173
+ ```
174
+
175
+ `guanmetric directory get <project_id> <dir_id>` 是客户端从这棵树按 ID 提取节点,不对应新的后端 API。`contents` 递归包含子目录;`metricCnt` 是当前目录指标数,`allMetricCnt` 是包含后代的指标总数。
176
+
177
+ 删除成功响应:
178
+
179
+ ```json
180
+ {"result":"ok","response":"Directory deleted"}
181
+ ```
182
+
183
+ CLI 禁止通过 directory 命令删除 Project 根目录;删除整个主题必须用 `project delete`。普通目录删除默认只展示节点及其子树/指标计数,追加 `--confirm` 才提交;依赖由后端最终校验。
184
+
185
+ ## Agent 使用约束
186
+
187
+ 1. 先创建 Project,再从 Project 详情/列表取得真实根目录 `dirId`。
188
+ 2. 创建目录时固定 `dirType=METRIC_PLATFORM`,并校验 `parentDirId` 在该 Project 目录树内。
189
+ 3. 编辑只能原地更新,不能删除重建。
190
+ 4. Project 更新只提交 `name/icon/iconColor`;Directory 更新只提交 `name/parentDirId/dirType`。
191
+ 5. 所有创建和编辑都必须写后回读;HTTP 成功不等于最终状态正确。
192
+ 6. 删除必须先展示精确目标,并要求 `--confirm`;不能自行扩展为批量删除。
193
+ 7. 本契约不授权指标 move、指标 owner 转移或其他目录类型管理。
@@ -2,6 +2,9 @@
2
2
 
3
3
  本文是指标写操作的入口索引,用于指导 AI 选择应加载的细分文档,避免一次性读取所有指标类型的长配置。当前覆盖原子指标、复合指标、衍生指标的创建/编辑预检查;删除的完整交互流程后续补充。
4
4
 
5
+ 创建、编辑、详情和列表接口的真实脱敏响应、JSON Schema 及读写模型映射见
6
+ `metric-api-contracts.md`。Agent 构造写请求前应先按该契约选择指标类型和具体变体。
7
+
5
8
  ## 读取顺序
6
9
 
7
10
  处理指标写操作时按需读取:
@@ -64,8 +67,8 @@ guanmetric template normalize <input.xlsx> --out <standard.xlsx> --report <repor
64
67
  3. 信息不全时先查 ID,不凭空猜:
65
68
  - 指标主题:`guancli metric project [keyword] -f json`
66
69
  - 指标目录:`guancli metric tree -f json`
67
- - 新建指标主题:`guanmetric project-create <name> --dry-run`,确认后去掉 `--dry-run`
68
- - 新建指标目录:`guanmetric dir-create <name> --project-id <metric_topic_id> --dry-run`,也可用 `--project-name <metric_topic_name>`;确认后去掉 `--dry-run`。创建子目录可传 `--parent-dir-id`,也可传 `--parent-dir-name`。若主题名称重复必须让用户指定主题 ID;若父目录名称重复必须让用户指定目录 ID
70
+ - 新建指标主题:`guanmetric project create <name> --dry-run`,确认后去掉 `--dry-run`
71
+ - 新建指标目录:`guanmetric directory create <name> --project-id <metric_topic_id> --dry-run`,确认后去掉 `--dry-run`。创建子目录可传 `--parent-dir-id`
69
72
  - 指标详情:`guancli metric search <keyword> -f json`、`guancli metric get <metric_id> --brief`
70
73
  - 数据集字段:`guancli ds search <keyword>`、`guancli ds get <dsId> --brief`
71
74
  4. 如果输入来自标准模板,按 `metric-excel-template.md` 的“创建阶段读取规则”生成 payload:
@@ -76,11 +79,11 @@ guanmetric template normalize <input.xlsx> --out <standard.xlsx> --report <repor
76
79
  - 复合指标的每个引用必须解析并核对为 `ATOMIC`/`COMPOSITE`;发现 `DERIVED`/快捷引用指标时停止计划,按业务语义改建为组合衍生或“先复合、后衍生”。
77
80
  - `适用维度`、`时间维度`、业务属性列都需要解析成接口字段,不要把中文名原样提交给后端。
78
81
  5. 读取启用的指标业务属性配置,补齐必填 `bizAttrs`。
79
- 6. 生成“指标创建计划”,让用户 review;用户确认计划前,不生成最终提交 JSON,不执行 dry-run/precheck/真实创建。
80
- 7. 用户确认计划后,生成 JSON 文件,先做 dry-run 或人工摘要,向用户确认当前环境、目标目录、指标口径、计算配置、业务属性和保存方式。
81
- 8. 用户确认后,仍需按 Web 同款交互执行保存前校验或影响校验。
82
- 9. 校验通过、无对应校验,或用户对冲突/影响完成二次确认后,才提交真实创建或编辑。
83
- 10. 写入成功后用 `guancli metric get <metric_id> --brief` 回读确认。
82
+ 6. 基于标准模板输出“指标创建计划”摘要,让用户 review;用户确认计划前,不生成最终提交 JSON,不执行真实创建。
83
+ 7. 用户确认标准 Excel 后,执行 `guanmetric flow generate --file <standard.xlsx> --out <metric_flow.json>` 自动生成 `schemaVersion=1.0` 计划并完成只读 plan 校验;不要由 Agent 手写 Flow JSON。单个、不经过标准模板的原子指标仍可使用 `create --dry-run`。
84
+ 8. 用户确认环境、目录、口径、计算配置、业务属性、保存方式和 Flow 执行顺序后,使用 `flow apply --state ... --confirm`;旧的单指标命令继续按各类型文档执行。
85
+ 9. Flow 会执行前端有而后端缺失的字段规则、原子 save-precheck、逐项创建和逐项验收;后端已有的引用状态、权限和指标定义规则由创建接口裁决,不在 Flow 重复查询。口径冲突、审批中或上游不可用时停止下游创建并保存状态。
86
+ 10. `acceptance.mode=usable` 只有在 `PUBLISHED`、`canUse=true` 且 `metric query` 冒烟成功后才算完成;`draft` 模式只验证草稿定义回读。旧命令写入成功后仍至少用 `metric get` 回读,不能把它描述为已完成 Flow 的可用性验收。
84
87
 
85
88
  不要把“dry-run 成功”“precheck 通过”或“影响校验无阻塞”描述成指标已经创建/编辑成功。
86
89
 
@@ -145,7 +148,8 @@ guanmetric template normalize <input.xlsx> --out <standard.xlsx> --report <repor
145
148
 
146
149
  ## 命令能力边界
147
150
 
148
- - `guanmetric create` 和 `guanmetric edit` 当前是原子指标专用命令。
149
- - 复合指标和衍生指标创建/编辑使用 `guanmetric fetch POST ... --stdin < payload.json`。
151
+ - `guanmetric create` 和 `guanmetric edit` 是原子指标专用命令。
152
+ - 复合指标使用 `guanmetric composite create|edit`,衍生指标使用 `guanmetric derived create|edit`。专用编辑命令负责详情读模型到 Update DTO 白名单的转换、影响校验和写后回读;不要再用裸 `fetch` 回写指标详情。
153
+ - 对话式批量创建或包含依赖的原子/复合/衍生指标统一使用 `guanmetric flow generate|plan|apply|verify`;Flow 是新增入口,不改变上述旧命令。
150
154
  - 指标删除使用 `guanmetric delete <metric_id>`;默认只做影响校验,追加 `--confirm` 才会在无下游依赖时提交删除。
151
155
  - 指标批量上下线使用 `guanmetric batch online|offline`;详细输入、输出和失败语义见 `metric-batch-status.md`。
@@ -0,0 +1,62 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "source": {
4
+ "environment": "test153",
5
+ "capturedAt": "2026-09-21",
6
+ "authentication": "account-password",
7
+ "note": "由隔离临时公共维度真实 CRUD 请求采集后脱敏;PAT 未验证,示例 ID 不可用于调用。"
8
+ },
9
+ "createRequest": {
10
+ "name": "区域",
11
+ "businessOwner": "user_example",
12
+ "relatedFields": [{"dsId": "dataset_example", "fdId": "field_region"}]
13
+ },
14
+ "createResponse": {"result": "ok", "response": {"id": "public_dim_example"}},
15
+ "updateRequest": {
16
+ "name": "经营区域",
17
+ "businessOwner": "user_example",
18
+ "relatedFields": [{"dsId": "dataset_example", "fdId": "field_region"}]
19
+ },
20
+ "updateResponse": {"result": "ok", "response": {"id": "public_dim_example"}},
21
+ "detailResponse": {
22
+ "result": "ok",
23
+ "response": {
24
+ "id": "public_dim_example",
25
+ "domId": "example_domain",
26
+ "name": "经营区域",
27
+ "businessOwner": {"uId": "user_example", "name": "示例用户", "email": "user@example.com", "avatar": "", "isDel": false},
28
+ "relatedFields": [{
29
+ "dsInfo": {"dsId": "dataset_example", "name": "销售明细"},
30
+ "fdInfo": {"dsId": "dataset_example", "fdId": "field_region", "name": "省份", "metaType": "DIM", "fdType": "STRING"}
31
+ }],
32
+ "creator": {"uId": "user_example", "name": "示例用户", "email": "user@example.com", "avatar": "", "isDel": false},
33
+ "ctime": "2026-09-21 14:05:05",
34
+ "utime": "2026-09-21 14:05:15"
35
+ }
36
+ },
37
+ "listResponse": {
38
+ "result": "ok",
39
+ "response": {
40
+ "contents": [{
41
+ "id": "public_dim_example",
42
+ "domId": "example_domain",
43
+ "name": "经营区域",
44
+ "businessOwner": {"uId": "user_example", "name": "示例用户", "email": "user@example.com", "avatar": "", "isDel": false},
45
+ "relatedFieldsDisplay": "省份(销售明细)",
46
+ "fdType": "STRING",
47
+ "creator": {"uId": "user_example", "name": "示例用户", "email": "user@example.com", "avatar": "", "isDel": false},
48
+ "ctime": "2026-09-21 14:05:05",
49
+ "utime": "2026-09-21 14:05:15"
50
+ }],
51
+ "count": 1,
52
+ "limit": 20,
53
+ "offset": 0
54
+ }
55
+ },
56
+ "fieldMapResponse": {
57
+ "result": "ok",
58
+ "response": {"field_region": {"id": "public_dim_example", "name": "经营区域"}}
59
+ },
60
+ "dependCheckResponse": {"result": "ok", "response": {"isDepended": false}},
61
+ "deleteResponse": {"result": "ok", "response": "delete success."}
62
+ }