@guandata/guanmetric 0.1.17 → 0.1.19
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 +11 -0
- package/README.md +25 -3
- package/bin/platforms.js +44 -0
- package/bin/run.js +99 -44
- package/package.json +16 -4
- 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
- package/binaries/guanmetric-darwin-arm64 +0 -0
- package/binaries/guanmetric-darwin-x64 +0 -0
- package/binaries/guanmetric-linux-arm64 +0 -0
- package/binaries/guanmetric-linux-x64 +0 -0
- package/binaries/guanmetric-win32-x64.exe +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guanmetric 0.1.19 - 2026-09-24
|
|
4
|
+
|
|
5
|
+
- 新增指标创建 Flow:从标准模板生成计划,按依赖顺序创建、回读并验证指标;创建结果不确定时可核对已有资源并恢复进度,避免重复创建。
|
|
6
|
+
- 原子、复合、衍生指标的创建与编辑改用明确的写入模型,编辑时保留取数字段;补齐指标主题、目录、指标树及相关资源的管理命令。
|
|
7
|
+
- 完善模板、筛选条件和创建前校验,并提供可复核的接口契约示例。
|
|
8
|
+
|
|
9
|
+
## @guandata/guanmetric 0.1.18 - 2026-09-19
|
|
10
|
+
|
|
11
|
+
- 安装包按平台拆分:主包只保留启动器、Skill 与文档,原生程序由同版本的 `@guandata/guanmetric-<平台>-<架构>` 可选依赖提供,安装时只下载当前系统的一份,安装命令与 CLI 行为不变。
|
|
12
|
+
- 平台包缺失或主包与平台包版本不一致时给出可操作提示;新增 `pack:all`、`verify:platforms` 与自动选包/注册表门禁,发布前校验五个平台包。
|
|
13
|
+
|
|
3
14
|
## @guandata/guanmetric 0.1.17 - 2026-09-18
|
|
4
15
|
|
|
5
16
|
- 同步本次发布的内部依赖更新,无用户可见行为变化。
|
package/README.md
CHANGED
|
@@ -10,6 +10,8 @@ npm install -g --foreground-scripts @guandata/guanmetric
|
|
|
10
10
|
|
|
11
11
|
> 全局安装/升级时会通过 postinstall 自动执行一次 `guanmetric install-skill` 刷新 AI skill。`--foreground-scripts` 用于显示明确的成功、失败或跳过结果;失败时按提示手动运行 `guanmetric install-skill`。CI 等无需 skill 的环境可设 `GUAN_SKIP_INSTALL_SKILL=1` 跳过。
|
|
12
12
|
|
|
13
|
+
安装包会通过 npm `optionalDependencies` 自动选择当前系统的原生二进制。不要使用 `--omit=optional` 或 `optional=false`;企业 npm 镜像也需要同步对应的 `@guandata/guanmetric-<平台>-<架构>` 包。若平台包缺失,CLI 会显示对应包名和重新安装方法。
|
|
14
|
+
|
|
13
15
|
## 常用命令
|
|
14
16
|
|
|
15
17
|
```bash
|
|
@@ -18,9 +20,18 @@ guanmetric template init --type atomic --out atomic_metrics.xlsx
|
|
|
18
20
|
guanmetric template normalize 客户指标.xlsx --check-only --output json-v1
|
|
19
21
|
guanmetric template normalize 客户指标.xlsx --out standard.xlsx --report report.json
|
|
20
22
|
guanmetric template explain-error report.json --json
|
|
21
|
-
guanmetric project
|
|
22
|
-
guanmetric
|
|
23
|
+
guanmetric project create 经营指标 --dry-run
|
|
24
|
+
guanmetric project edit <project_id> --name 经营分析指标 --dry-run
|
|
25
|
+
guanmetric directory create 广告分析 --project-id <project_id> --dry-run
|
|
26
|
+
guanmetric directory edit <project_id> <dir_id> --name 广告经营分析 --dry-run
|
|
23
27
|
guanmetric create --file atomic_metric.json --dry-run
|
|
28
|
+
guanmetric composite create --file composite_metric.json --dry-run
|
|
29
|
+
guanmetric derived create --file derived_metric.json --dry-run
|
|
30
|
+
guanmetric flow generate --file standard.xlsx --out metric_flow.json
|
|
31
|
+
guanmetric flow plan --file metric_flow.json
|
|
32
|
+
guanmetric flow apply --file metric_flow.json --state metric_flow.state.json --confirm
|
|
33
|
+
guanmetric flow verify --state metric_flow.state.json
|
|
34
|
+
guanmetric flow reconcile --file metric_flow.json --state metric_flow.state.json --key <flow_key> --metric-id <metric_id> --confirm
|
|
24
35
|
guanmetric edit <metric_id> --file patch.json --dry-run
|
|
25
36
|
guanmetric delete <metric_id>
|
|
26
37
|
guanmetric public-dim create --file public_dim.json --dry-run
|
|
@@ -36,8 +47,19 @@ guanmetric metric-tree update-config <metric_tree_id> --file metric_tree_config.
|
|
|
36
47
|
|
|
37
48
|
指标模板命令提供机器可读 schema、原子/复合指标最小模板和无副作用预检。`--check-only` 不写 Excel/report,也不创建或修改指标;失败结果通过稳定的 `TEMPLATE_*` 错误码以及 Sheet、行、列、期望值和修正示例定位。
|
|
38
49
|
|
|
50
|
+
`guanmetric flow generate` 把用户确认后的标准 Excel 转换为版本化 Flow 计划,自动解析字段、责任人、业务属性、已有指标和批内依赖,并立即执行只读 plan 校验。`flow apply` 按 `${metric:key}` 依赖稳定排序,创建后逐项回读;`usable` 模式还要求指标已发布、当前用户可用且数据查询冒烟成功。状态文件保存真实指标 ID,审批或故障后可继续执行,并避免重复创建。创建结果未知时,`flow apply` 不会重发创建;先用 `flow reconcile` 预览候选与原计划是否一致,确认后只把真实 ID 安全绑定回本地 state。
|
|
51
|
+
|
|
39
52
|
## 版本更新
|
|
40
53
|
|
|
54
|
+
### @guandata/guanmetric 0.1.19
|
|
55
|
+
|
|
56
|
+
- 新增指标创建 Flow:从标准模板生成可审阅计划,按依赖创建、回读和验证;创建结果不确定时可核对已有资源并恢复进度。
|
|
57
|
+
- 创建和编辑原子、复合、衍生指标时使用明确的写入模型,保护已有取数字段;补齐指标主题、目录和指标树等资源的管理能力。
|
|
58
|
+
|
|
59
|
+
### @guandata/guanmetric 0.1.18
|
|
60
|
+
|
|
61
|
+
- 安装时自动选择当前系统和架构的原生程序,减少下载量与磁盘占用,原有安装命令不变;离线安装也支持自动选包。
|
|
62
|
+
|
|
41
63
|
### @guandata/guanmetric 0.1.17
|
|
42
64
|
|
|
43
65
|
- 同步本次发布的内部依赖更新,无用户可见行为变化。
|
|
@@ -55,7 +77,7 @@ guanmetric metric-tree update-config <metric_tree_id> --file metric_tree_config.
|
|
|
55
77
|
### @guandata/guanmetric 0.1.14
|
|
56
78
|
|
|
57
79
|
- 统一指标 JSON 输入契约、模板和消费示例,便于跨工具稳定传递指标定义。
|
|
58
|
-
-
|
|
80
|
+
- 对话式 Flow 只补 Web 创建页已有而后端缺失的校验,避免与服务端重复维护同一业务规则。
|
|
59
81
|
|
|
60
82
|
### @guandata/guanmetric 0.1.13
|
|
61
83
|
|
package/bin/platforms.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
// Single source of truth for the optionalDependencies platform-package split.
|
|
4
|
+
// bin/run.js, scripts/build.js and the build/preflight tests all read this file
|
|
5
|
+
// so that the matrix, the package names and the embedded binary names can never
|
|
6
|
+
// drift apart.
|
|
7
|
+
|
|
8
|
+
const PACKAGE_PREFIX = "@guandata/guanmetric";
|
|
9
|
+
const CLI_NAME = "guanmetric";
|
|
10
|
+
const BINARY_NAMES = ["guanmetric"];
|
|
11
|
+
|
|
12
|
+
const PLATFORM_TARGETS = [
|
|
13
|
+
{ platform: "darwin", arch: "arm64", suffix: "darwin-arm64", ext: "" },
|
|
14
|
+
{ platform: "darwin", arch: "x64", suffix: "darwin-x64", ext: "" },
|
|
15
|
+
{ platform: "linux", arch: "x64", suffix: "linux-x64", ext: "" },
|
|
16
|
+
{ platform: "linux", arch: "arm64", suffix: "linux-arm64", ext: "" },
|
|
17
|
+
{ platform: "win32", arch: "x64", suffix: "win32-x64", ext: ".exe" },
|
|
18
|
+
].map((target) => ({
|
|
19
|
+
...target,
|
|
20
|
+
key: `${target.platform}-${target.arch}`,
|
|
21
|
+
packageName: `${PACKAGE_PREFIX}-${target.suffix}`,
|
|
22
|
+
binaries: BINARY_NAMES.map((name) => `${name}${target.ext}`),
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
function targetForRuntime(platform, arch) {
|
|
26
|
+
return PLATFORM_TARGETS.find(
|
|
27
|
+
(target) => target.platform === platform && target.arch === arch
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function optionalDependencies(version) {
|
|
32
|
+
return Object.fromEntries(
|
|
33
|
+
PLATFORM_TARGETS.map((target) => [target.packageName, version])
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
module.exports = {
|
|
38
|
+
CLI_NAME,
|
|
39
|
+
PACKAGE_PREFIX,
|
|
40
|
+
BINARY_NAMES,
|
|
41
|
+
PLATFORM_TARGETS,
|
|
42
|
+
optionalDependencies,
|
|
43
|
+
targetForRuntime,
|
|
44
|
+
};
|
package/bin/run.js
CHANGED
|
@@ -7,34 +7,79 @@ const path = require("path");
|
|
|
7
7
|
const fs = require("fs");
|
|
8
8
|
const os = require("os");
|
|
9
9
|
const { createInstallChildEnv, reexecInstallCommand } = require("./install-env");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
const {
|
|
11
|
+
BINARY_NAMES,
|
|
12
|
+
PACKAGE_PREFIX,
|
|
13
|
+
PLATFORM_TARGETS,
|
|
14
|
+
targetForRuntime,
|
|
15
|
+
} = require("./platforms");
|
|
16
|
+
|
|
17
|
+
// The native binaries are delivered by per-platform optional dependencies, so
|
|
18
|
+
// an installation only downloads and unpacks the current OS/architecture.
|
|
19
|
+
function resolvePlatformBinaries(options = {}) {
|
|
20
|
+
const platform = options.platform || process.platform;
|
|
21
|
+
const arch = options.arch || process.arch;
|
|
22
|
+
const resolvePackage = options.resolvePackage || require.resolve;
|
|
23
|
+
const exists = options.exists || fs.existsSync;
|
|
24
|
+
const readJson =
|
|
25
|
+
options.readJson || ((filename) => JSON.parse(fs.readFileSync(filename, "utf8")));
|
|
26
|
+
const key = `${platform}-${arch}`;
|
|
27
|
+
const target = targetForRuntime(platform, arch);
|
|
28
|
+
if (!target) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Unsupported platform: ${key}\nSupported: ${PLATFORM_TARGETS.map((item) => item.key).join(", ")}`
|
|
25
31
|
);
|
|
26
|
-
process.exit(1);
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
|
|
34
|
+
try {
|
|
35
|
+
const packageJson = resolvePackage(`${target.packageName}/package.json`);
|
|
36
|
+
const platformVersion = readJson(packageJson).version;
|
|
37
|
+
const mainVersion = readJson(path.join(__dirname, "..", "package.json")).version;
|
|
38
|
+
if (platformVersion !== mainVersion) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
`Platform package ${target.packageName} version ${platformVersion} does not match ` +
|
|
41
|
+
`${PACKAGE_PREFIX} ${mainVersion}. Reinstall ${PACKAGE_PREFIX}.`
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
const binDir = path.join(path.dirname(packageJson), "bin");
|
|
45
|
+
const binaryPaths = {};
|
|
46
|
+
for (const binary of target.binaries) {
|
|
47
|
+
const binaryPath = path.join(binDir, binary);
|
|
48
|
+
if (!exists(binaryPath)) {
|
|
49
|
+
throw new Error(
|
|
50
|
+
`Platform package ${target.packageName} is installed but its binary is missing: ${binaryPath}. ` +
|
|
51
|
+
`Reinstall ${PACKAGE_PREFIX}.`
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
binaryPaths[binary.replace(/\.exe$/, "")] = binaryPath;
|
|
55
|
+
}
|
|
56
|
+
return { target, binaryPaths };
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (err.message && err.message.startsWith("Platform package ")) throw err;
|
|
59
|
+
|
|
60
|
+
// Local development fallback. The generated directory is excluded from
|
|
61
|
+
// the published main package, so installed users always use the optional
|
|
62
|
+
// platform dependency above.
|
|
63
|
+
const localBinDir = path.join(__dirname, "..", "platforms", target.suffix, "bin");
|
|
64
|
+
const binaryPaths = {};
|
|
65
|
+
for (const binary of target.binaries) {
|
|
66
|
+
const binaryPath = path.join(localBinDir, binary);
|
|
67
|
+
if (!exists(binaryPath)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Missing optional platform package ${target.packageName} for ${key}.\n` +
|
|
70
|
+
`Reinstall without disabling optional dependencies:\n` +
|
|
71
|
+
` npm install -g ${PACKAGE_PREFIX}\n` +
|
|
72
|
+
`If you used --omit=optional or optional=false, remove that setting first.`
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
binaryPaths[binary.replace(/\.exe$/, "")] = binaryPath;
|
|
76
|
+
}
|
|
77
|
+
return { target, binaryPaths };
|
|
35
78
|
}
|
|
79
|
+
}
|
|
36
80
|
|
|
37
|
-
|
|
81
|
+
function getBinaryPath(options = {}) {
|
|
82
|
+
return resolvePlatformBinaries(options).binaryPaths[BINARY_NAMES[0]];
|
|
38
83
|
}
|
|
39
84
|
|
|
40
85
|
function copyDirectory(src, dest) {
|
|
@@ -81,7 +126,7 @@ function installBuddySkills(pkgRoot, skill) {
|
|
|
81
126
|
}
|
|
82
127
|
}
|
|
83
128
|
|
|
84
|
-
if (process.argv[2] === "version" && process.argv.length === 3) {
|
|
129
|
+
if (require.main === module && process.argv[2] === "version" && process.argv.length === 3) {
|
|
85
130
|
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf8"));
|
|
86
131
|
console.log(pkg.version);
|
|
87
132
|
process.exit(0);
|
|
@@ -111,7 +156,7 @@ function resolveNpxInvocation() {
|
|
|
111
156
|
return { command: "npx", argsPrefix: [] };
|
|
112
157
|
}
|
|
113
158
|
|
|
114
|
-
if (process.argv[2] === "install-skill") {
|
|
159
|
+
if (require.main === module && process.argv[2] === "install-skill") {
|
|
115
160
|
reexecInstallCommand(__filename, process.argv.slice(2));
|
|
116
161
|
const pkgRoot = path.join(__dirname, "..");
|
|
117
162
|
const extraArgs = process.argv.slice(3);
|
|
@@ -143,28 +188,38 @@ if (process.argv[2] === "install-skill") {
|
|
|
143
188
|
process.exit(status);
|
|
144
189
|
}
|
|
145
190
|
|
|
146
|
-
|
|
191
|
+
if (require.main === module) {
|
|
192
|
+
let binary;
|
|
193
|
+
try {
|
|
194
|
+
binary = getBinaryPath();
|
|
195
|
+
} catch (err) {
|
|
196
|
+
console.error(err.message);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
147
199
|
|
|
148
|
-
try {
|
|
149
|
-
|
|
150
|
-
|
|
200
|
+
try {
|
|
201
|
+
if (process.platform !== "win32") {
|
|
202
|
+
fs.chmodSync(binary, 0o755);
|
|
203
|
+
}
|
|
204
|
+
} catch (_) {
|
|
205
|
+
// chmod may fail in read-only environments
|
|
151
206
|
}
|
|
152
|
-
} catch (_) {
|
|
153
|
-
// chmod may fail in read-only environments
|
|
154
|
-
}
|
|
155
207
|
|
|
156
|
-
if (process.platform === "win32") {
|
|
157
|
-
|
|
158
|
-
}
|
|
208
|
+
if (process.platform === "win32") {
|
|
209
|
+
try { execSync("chcp 65001", { stdio: "ignore" }); } catch (_) {}
|
|
210
|
+
}
|
|
159
211
|
|
|
160
|
-
try {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
} catch (err) {
|
|
166
|
-
|
|
167
|
-
|
|
212
|
+
try {
|
|
213
|
+
execFileSync(binary, process.argv.slice(2), {
|
|
214
|
+
stdio: "inherit",
|
|
215
|
+
env: { ...process.env, GUANMETRIC_PROG_NAME: "guanmetric" },
|
|
216
|
+
});
|
|
217
|
+
} catch (err) {
|
|
218
|
+
if (err.status != null) {
|
|
219
|
+
process.exit(err.status);
|
|
220
|
+
}
|
|
221
|
+
throw err;
|
|
168
222
|
}
|
|
169
|
-
throw err;
|
|
170
223
|
}
|
|
224
|
+
|
|
225
|
+
module.exports = { getBinaryPath, resolvePlatformBinaries };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guandata/guanmetric",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.19",
|
|
4
4
|
"description": "观远 BI 指标写操作工具 - 指标创建编辑删除、指标目录、公共维度、Excel 标准化",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guanmetric": "bin/run.js"
|
|
@@ -8,13 +8,17 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"postinstall": "node bin/postinstall.js",
|
|
10
10
|
"build": "node scripts/build.js && node scripts/sync-skill.js",
|
|
11
|
+
"pack:all": "node scripts/pack-all.js",
|
|
12
|
+
"test:build-script": "node scripts/platform-tests.js build && node scripts/platform-tests.js run",
|
|
13
|
+
"test:package-layout": "node scripts/platform-tests.js layout && node scripts/platform-tests.js install-smoke",
|
|
14
|
+
"test:auto-select": "node scripts/platform-tests.js auto-select",
|
|
15
|
+
"verify:platforms": "node scripts/verify-platforms.js",
|
|
11
16
|
"changelog": "node ../../scripts/generate-release-changelog.js .",
|
|
12
17
|
"check-changelog": "node ../../scripts/check-release-changelog.js .",
|
|
13
|
-
"prepublishOnly": "npm run check-changelog && npm run build && node scripts/preflight.js"
|
|
18
|
+
"prepublishOnly": "npm run test:build-script && npm run check-changelog && npm run build && node scripts/preflight.js && npm run test:package-layout && npm run test:auto-select"
|
|
14
19
|
},
|
|
15
20
|
"files": [
|
|
16
21
|
"bin/",
|
|
17
|
-
"binaries/",
|
|
18
22
|
"skills/",
|
|
19
23
|
"CHANGELOG.md",
|
|
20
24
|
"LICENSE",
|
|
@@ -36,7 +40,15 @@
|
|
|
36
40
|
"engines": {
|
|
37
41
|
"node": ">=14"
|
|
38
42
|
},
|
|
43
|
+
"optionalDependencies": {
|
|
44
|
+
"@guandata/guanmetric-darwin-arm64": "0.1.19",
|
|
45
|
+
"@guandata/guanmetric-darwin-x64": "0.1.19",
|
|
46
|
+
"@guandata/guanmetric-linux-x64": "0.1.19",
|
|
47
|
+
"@guandata/guanmetric-linux-arm64": "0.1.19",
|
|
48
|
+
"@guandata/guanmetric-win32-x64": "0.1.19"
|
|
49
|
+
},
|
|
39
50
|
"publishConfig": {
|
|
40
|
-
"registry": "https://registry.npmjs.org/"
|
|
51
|
+
"registry": "https://registry.npmjs.org/",
|
|
52
|
+
"access": "public"
|
|
41
53
|
}
|
|
42
54
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: guanmetric
|
|
3
|
-
description: 当用户要创建、编辑、删除观远 BI
|
|
3
|
+
description: 当用户要创建、编辑、删除观远 BI 指标,增删改查指标主题/指标目录,创建或配置指标树(含维度拆解、指标拆解公式、复合指标公式展开),批量标准化 Excel 指标模板,管理指标公共维度,或查询目录树及增删改查业务字典时使用本 skill。查询指标详情、搜索指标、指标数据查询仍使用 guancli。
|
|
4
4
|
compatibility: "Requires Node.js 14+. Install via npm link --foreground-scripts (local) or npm install -g --foreground-scripts @guandata/guanmetric (from internal Nexus registry) so the AI skill refresh result is visible. CLI command: guanmetric."
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -17,9 +17,23 @@ guanmetric template init --type composite --out composite_metrics.xlsx
|
|
|
17
17
|
guanmetric template normalize 客户指标.xlsx --check-only --output json-v1 --skip-biz-attrs --skip-id-resolve
|
|
18
18
|
guanmetric template normalize 客户指标.xlsx --out standard.xlsx --report report.json
|
|
19
19
|
guanmetric template explain-error report.json --json
|
|
20
|
-
guanmetric project
|
|
21
|
-
guanmetric
|
|
20
|
+
guanmetric project create 经营指标 --dry-run
|
|
21
|
+
guanmetric project edit <project_id> --name 经营分析指标 --dry-run
|
|
22
|
+
guanmetric project delete <project_id>
|
|
23
|
+
guanmetric directory create 广告分析 --project-id <project_id> --dry-run
|
|
24
|
+
guanmetric directory edit <project_id> <dir_id> --name 广告经营分析 --dry-run
|
|
25
|
+
guanmetric directory delete <project_id> <dir_id>
|
|
22
26
|
guanmetric create --file atomic_metric.json --dry-run
|
|
27
|
+
guanmetric composite create --file composite_metric.json --dry-run
|
|
28
|
+
guanmetric composite edit <metric_id> --set desc=新口径 --dry-run
|
|
29
|
+
guanmetric derived create --file derived_metric.json --dry-run
|
|
30
|
+
guanmetric derived edit <metric_id> --file patch.json --dry-run
|
|
31
|
+
guanmetric flow plan --file metric_flow.json
|
|
32
|
+
guanmetric flow generate --file standard.xlsx --out metric_flow.json
|
|
33
|
+
guanmetric flow apply --file metric_flow.json --state metric_flow.state.json --confirm
|
|
34
|
+
guanmetric flow verify --state metric_flow.state.json
|
|
35
|
+
guanmetric flow reconcile --file metric_flow.json --state metric_flow.state.json --key <flow_key> --metric-id <metric_id>
|
|
36
|
+
guanmetric flow reconcile --file metric_flow.json --state metric_flow.state.json --key <flow_key> --metric-id <metric_id> --confirm
|
|
23
37
|
guanmetric edit <metric_id> --file patch.json --dry-run
|
|
24
38
|
guanmetric delete <metric_id>
|
|
25
39
|
guanmetric batch online --id <metric_id_1> --id <metric_id_2> --dry-run
|
|
@@ -38,12 +52,17 @@ guanmetric accelerate priority <metric_id> --priority <accelerate_metric_id>=2 -
|
|
|
38
52
|
guanmetric accelerate delete <accelerate_metric_id> --confirm
|
|
39
53
|
guanmetric metric-tree create 销售额指标树 --metric-id <metric_id> --parent-dir-id <metric_tree_dir_id> --dry-run
|
|
40
54
|
guanmetric metric-tree update-config <metric_tree_id> --file metric_tree_config.json --dry-run
|
|
41
|
-
guanmetric
|
|
55
|
+
guanmetric metric-tree delete <metric_tree_id>
|
|
56
|
+
guanmetric metric-tree directory tree
|
|
57
|
+
guanmetric metric-tree directory create 经营分析 --dry-run
|
|
58
|
+
guanmetric metric-tree directory edit <dir_id> --name 销售经营分析 --dry-run
|
|
59
|
+
guanmetric metric-tree directory delete <dir_id>
|
|
60
|
+
guanmetric fetch POST /api/metric-platform/<unwrapped_endpoint> --file request.json
|
|
42
61
|
```
|
|
43
62
|
|
|
44
63
|
## 编辑红线:编辑 ≠ 删除重建
|
|
45
64
|
|
|
46
|
-
|
|
65
|
+
用户要求**编辑/重命名/修改**已有指标时,原子指标必须用 `guanmetric edit <metric_id>`,复合指标用 `guanmetric composite edit <metric_id>`,衍生指标用 `guanmetric derived edit <metric_id>` 原地更新;改名可用 `--set name=新名`。指标主题用 `project edit`,指标目录用 `directory edit`;业务字典用 `business-dict edit`;公共维度用 `public-dim edit`;查询加速用 `accelerate edit <accelerate_metric_id>` 原地更新或 `accelerate priority <metric_id>` 调整顺序;指标树用 `metric-tree rename`、`metric-tree move` 或 `metric-tree update-config` 原地更新。**严禁**用"delete 后重新 create 一个同名资源"来模拟编辑或改名:资源 ID 被其他对象引用,删除重建会导致引用、权限或历史配置丢失。业务字典删除时,服务端会先解除正式指标和草稿的 `bizMetricId`,并把字典的业务口径和业务属性保留到指标,再逻辑删除字典;因此删除前必须先查看关联指标并取得明确确认。指标树删除重建还会改变指标树 ID,导致归因入口、目录引用和外部链接失效。`delete` 只用于用户明确要求删除资源本身。主题和目录删除也必须先展示精确目标,追加 `--confirm` 才提交;目录根节点不能单独删除。无论通过哪个命令或接口,都不得把"编辑"拆成"删除 + 重建"的组合来绕过这条红线。只有用户明确指示"先新建替代、再删除旧的"时才允许该流程,且执行前必须列出会断链和丢失的内容并获得确认。
|
|
47
66
|
|
|
48
67
|
批量创建指标时,必须先生成固定结构的标准 Excel 返回给用户确认;确认前不生成最终 payload,不提交真实创建。
|
|
49
68
|
|
|
@@ -59,13 +78,22 @@ guanmetric fetch POST /api/metric-platform/metrics/composite-metrics --file comp
|
|
|
59
78
|
|
|
60
79
|
标准 Excel 第一张固定为 `汇总` sheet,用于给用户总览本次待创建指标总数、按类型计数、指标名称、指标类型、所在模板、关键来源、行状态和问题说明;创建 payload 仍以各指标类型模板 sheet 为事实源,不从 `汇总` sheet 创建。
|
|
61
80
|
|
|
62
|
-
生成复合指标模板时,`计算公式`
|
|
81
|
+
生成复合指标模板时,`计算公式` 的每个引用都必须解析为已上线或本批先创建的原子指标/复合指标。复合指标不能引用衍生指标或快捷引用指标;在写入 `*.ai_mapped.xlsx` 或标准创建计划 Excel 前,先建立“指标名称 → 指标类型”索引并拒绝这类引用,不能先生成错误 Excel 再留给 Flow/后端报错。`template normalize --check-only` 也会用 `TEMPLATE_INVALID_REFERENCE` 阻断本批复合指标引用衍生指标。引用对象不在模板中时,先判断它应建为原子指标还是复合指标并补充对应行,不要一律补成原子指标。若业务公式确实要组合最近 N、累计、期末值等衍生结果,按 `metric-derived-mutation.md` 评估组合衍生,并向用户说明改模后的业务语义。
|
|
63
82
|
|
|
64
83
|
生成衍生指标模板时,如果 `衍生自` 指标不是已明确存在的线上指标,而是本批也要创建的指标,必须在标准模板中补充对应的原子指标或复合指标行;信息不足时先补行并在该基础指标行的 `问题说明` 中列出缺失的数据集、来源字段、聚合方式、计算公式、适用维度等。不要等到创建计划阶段才临时新增基础指标。
|
|
65
84
|
|
|
66
|
-
`fetch`
|
|
85
|
+
复合指标和衍生指标的单条创建/编辑必须使用 `composite create|edit`、`derived create|edit` 专用命令。三类编辑命令优先读取草稿;仅当结构化业务状态明确表示草稿不存在时才回退正式详情,然后把读模型转换成对应 Update DTO 白名单再合并 patch。原子 `edit --replace` 已停用。禁止把详情响应直接交给 `fetch` 回写;`fetch` 会先按服务端路由语义解码并规范化 URL,再硬拒绝三类指标已封装的 create/edit 写路由,百分号编码、点段或矩阵参数不能绕过,只用于尚未封装的低层端点或诊断。指标定义写入时,专用命令和其余允许的 `fetch` 请求都会规范化并校验顶层 `filter`:将兼容别名和 `not: true` 转成 Web 编辑器可识别的明确筛选类型,为空值筛选补 `filterValue: []`,并从当前指标或基础指标的 `applicableDims` 补齐字段元数据;无法无损转换时拒绝提交。业务限定衍生指标还会确认每个条件的 `fdId` 都存在于基础指标 `applicableDims`。
|
|
86
|
+
|
|
87
|
+
构造或解析指标创建、编辑、详情和列表请求时,先读取 `metric-api-contracts.md`。其中包含三类指标的真实脱敏响应、原子字段/表达式两种模式、六种衍生配置、JSON Schema 以及读模型到写模型映射。详情响应是读模型:`fdInfos`、对象数组形式的 `applicableDims`、对象形式的 `timeDim`、`baseMetric` 和用户对象不能原样提交;编辑请求必须按对应 Update DTO 白名单显式构造。列表请求的 `subTypes` 是逗号分隔字符串,不是 JSON 数组。
|
|
88
|
+
|
|
89
|
+
构造或解析指标主题/指标目录的创建、编辑、详情/列表/目录树和删除请求时,先读取 `metric-hierarchy-api-contracts.md`。主题编辑只提交 `name/icon/iconColor`;目录编辑只提交 `name/parentDirId/dirType`,其中 `dirType` 固定为 `METRIC_PLATFORM`。指标目录没有单条详情接口,`directory get` 是从指定 Project 的目录树按 ID 提取节点。创建和编辑必须写后回读;删除默认只展示目标,必须追加 `--confirm`。本轮不提供指标 move 或指标 owner 转移命令。
|
|
90
|
+
|
|
91
|
+
用户通过对话提出一批相互依赖的指标创建需求时,优先使用 `guanmetric flow`,不要逐个调用 `create`/`fetch` 后自行判断成功。标准模板经用户确认且所有真实指标行为“可创建”后,必须优先执行 `flow generate --file <standard.xlsx> --out <metric_flow.json>`,不要由 Agent 手写计划。该命令会解析数据集字段、当前责任人/唯一用户、业务属性、已有指标和批内引用,生成稳定 key 与占位符,并立即运行 `flow plan`;无法唯一解析时输出带 Sheet/行/列的稳定诊断且不写计划。同一模板不能混合“上线”和“草稿”:全部上线生成 `usable`,全部草稿生成 `draft`,混合时必须拆分模板。提交真实创建前必须检查生成计划中的取数定义(`fdId+aggrType` 或 `formulaField`)、适用维度、时间维度、业务属性、责任人、格式、复合/衍生引用和 `publish` 均与确认后的标准模板一致;任一关键字段缺失都不得执行 `flow apply --confirm`。生成后仍可单独运行 `flow plan`;用户确认后运行带 `--confirm` 的 `flow apply`,并始终提供 `--state` 状态文件以便失败或审批后续跑。`acceptance.mode=usable` 要求请求 `publish=true`,最终状态为 `PUBLISHED`、当前用户 `canUse=true`,且 `guancli metric query --limit 1 -f json` 成功;组合衍生引用带固定高级计算粒度的指标时,Flow 会读取引用定义并自动追加唯一兼容的 `--dim "<时间维度> toMonth/toWeek/..."`,同时把实际维度、粒度和策略写入 state 的 `query` 证据。引用粒度不一致时返回 `FLOW_QUERY_GRANULARITY_CONFLICT`,不能靠循环尝试不同粒度掩盖定义冲突。`acceptance.mode=draft` 要求 `publish=false`,只验证草稿定义能够回读。审批中的指标返回 `pending`,不能汇报为已可用。创建结果未知时,`flow apply` 会永久保持该条目为 `blocked/reconcile`,绝不重发创建;创建前已将真正提交的 canonical 请求保存到 state 的 `submittedDefinition`,`reconcile` 只能据此核对候选,不能按实时元数据重建请求,而且同一 state 内一个非空 metricId 只能绑定一个 key。Agent 先只读核对线上候选,再执行不带 `--confirm` 的 `flow reconcile --file ... --state ... --key ... --metric-id ...` 预览,确认环境、planHash、类型、候选 ID 未被占用和关键定义完全一致后,才追加 `--confirm` 把真实 ID 写回 state。原生 Unix/Windows 中,confirmed apply 会在读取计划或访问 BI 前取得 state 锁,verify/reconcile 也在读取 state 或访问 BI 前取得锁,三者由跨进程独占锁串行化;apply preview 不读取 state,因此不持锁。遇到“正由另一个操作占用”时等待对方结束后重试,禁止改用另一个 state 绕过。WASI/非原生运行时因无法证明跨 guest 单写者,明确禁用 apply/verify/reconcile,只保留 generate/plan 等只读能力。部分指标已创建后禁止自动删除回滚,修正问题后复用同一计划和状态文件继续验证。完整契约见 `metric-flow.md`。
|
|
92
|
+
`flow verify` 的 `usable` 只证明指标已发布、可使用且查询成功,不证明它与另一个指标数值等价。只有用户明确要求新旧指标或两组指标数值对比时,才使用 `guancli metric batch-query` 执行独立的等价验证;必须固定相同粒度、筛选范围、排序和 raw 数值,按维度键对齐,并把可能截断的结果报告为 `inconclusive`,禁止用无排序的默认前 50 行按位置比较后宣称指标定义错误。详细 recipe 见 guancli skill 的 `references/metric-batch-query.md`。
|
|
93
|
+
|
|
94
|
+
指标定义是否合法由 BI 后端最终裁决。Flow 的单指标业务校验必须取“当前 Web 创建页已有规则”减去“当前后端创建链路已有规则”的差集:只补前端有而后端没有的规则,不复制后端已有规则,也不擅自新增前后端都没有的规则。当前差集包括草稿名称格式/长度、英文名格式/长度、业务口径最大长度、原子 `fdId+aggrType` 配对完整性、普通衍生 `baseMetricId+advType` 必填、自定义业务属性文本长度以及原子 save-precheck;计划结构、批内依赖、占位符、环境/状态一致性和验收编排属于 Flow 自身契约。创建接口还会执行落库、权限和上线等后置步骤,因此任何未返回可记录 `metricId` 的创建错误都必须保留结构化业务状态并进入 `reconcile`,不能自动重试。校验职责基线见 `metric-validation-ownership.md`。
|
|
67
95
|
查询加速写操作已封装为 `accelerate` 专用命令;查询加速列表查询使用 `guancli metric accelerate list <metric_id>`。查询加速筛选条件使用和指标定义一致的 `WebFilterData` 结构,可放在完整请求体的 `filter` 字段,也可通过 `--filter-json` 或 `--filter-file` 传入;合法节点仅为 `condition/operator/composition`,禁止使用 `group/combineType/conditions`。查询加速无法从指标适用维度自动补齐另一数据集的字段元数据,因此条件必须显式提供 `dsId/fdId/name/fdType/metaType`;清空筛选条件可传 `--filter-json null`。完整契约和嵌套示例见 `metric-common-fields.md`。
|
|
68
|
-
|
|
96
|
+
指标树及其目录的创建、修改和删除已封装为 `metric-tree` 专用命令,优先使用专用命令,不要再用裸 `fetch` 直接调用写接口。构造或解析指标树及目录的请求时,先读取 `metric-tree-api-contracts.md`;详情/搜索名称字段是 `metricTreeName`,父目录列表及编辑返回对象名称字段是 `name`,目录树用 `id/name`、目录详情用 `dirId/dirName`,读模型不得整体回写。指标树和目录删除默认只展示详情,明确追加 `--confirm` 才提交。指标树目录必须用 `metric-tree directory` 管理并固定 `dirType=METRIC_TREE`;不要把 `METRIC_PLATFORM` 指标目录 ID 当作指标树目录 ID。用户给出指标拆解公式时,按 `metric-tree-mutation.md` 解析成 `metricRelationTree`;遇到复合指标时读取指标详情中的 `formula`,按规则递归展开或在计划中标注不能无损展开的原因。
|
|
69
97
|
|
|
70
98
|
指标批量上下线使用 `batch online|offline`,输入可重复传 `--id`,或用 `--file` 提供 `{"ids":[...]}`,两者互斥。必须先执行 `--dry-run`。批量上线支持原子、复合和衍生指标:逐项读取 `fromDraft=true` 草稿,原子指标执行 save-precheck,全部类型执行 validate-update-impact,再按类型原地更新;快捷引用指标不支持上线。预检冲突或下游影响默认将该项标记为 `blocked`,只有用户确认后才追加 `--confirm`。批量下线逐项调用权威单指标下线接口,以保留稳定的逐项成功/失败归因。两种操作都是 best-effort:单项失败后继续,已成功项不回滚,最终 JSON 使用 `schemaVersion=1.0` 并在存在 `failed`/`blocked` 时非零退出。服务端可能启用指标审批,因此“上线请求成功”不等同于最终已上线,最终状态必须回读确认。完整契约见 `metric-batch-status.md`。
|
|
71
99
|
|
|
@@ -78,6 +106,23 @@ guanmetric fetch POST /api/metric-platform/metrics/composite-metrics --file comp
|
|
|
78
106
|
- `metric-composite-mutation.md`
|
|
79
107
|
- `metric-derived-mutation.md`
|
|
80
108
|
- `metric-public-dimension.md`
|
|
109
|
+
- `metric-public-dimension-api-contract-examples.json`
|
|
110
|
+
- `metric-public-dimension-api-contract.schema.json`
|
|
81
111
|
- `metric-business-dictionary.md`
|
|
112
|
+
- `metric-business-dictionary-api-contract-examples.json`
|
|
113
|
+
- `metric-business-dictionary-api-contract.schema.json`
|
|
82
114
|
- `metric-tree-mutation.md`
|
|
115
|
+
- `metric-tree-api-contracts.md`
|
|
116
|
+
- `metric-tree-api-contract-examples.json`
|
|
117
|
+
- `metric-tree-api-contract.schema.json`
|
|
83
118
|
- `metric-batch-status.md`
|
|
119
|
+
- `metric-flow.md`
|
|
120
|
+
- `metric-flow-generate-example.json`
|
|
121
|
+
- `metric-flow-generate.schema.json`
|
|
122
|
+
- `metric-validation-ownership.md`
|
|
123
|
+
- `metric-api-contracts.md`
|
|
124
|
+
- `metric-api-contract-examples.json`
|
|
125
|
+
- `metric-api-contract.schema.json`
|
|
126
|
+
- `metric-hierarchy-api-contracts.md`
|
|
127
|
+
- `metric-hierarchy-api-contract-examples.json`
|
|
128
|
+
- `metric-hierarchy-api-contract.schema.json`
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "guanmetric",
|
|
3
|
+
"evals": [
|
|
4
|
+
{
|
|
5
|
+
"id": 1,
|
|
6
|
+
"prompt": "我想梳理一套销售指标体系:销售额、退款额、净销售额、订单数、客单价、销售额月环比、最近7天销售额。现在只有这段文字,你先帮我整理并创建。",
|
|
7
|
+
"expected_output": "代理应先做语义拆分和依赖建模,把销售额/退款额/订单数识别为原子指标,净销售额/客单价识别为复合指标,月环比/最近7天识别为衍生指标;信息不足时生成 ai_mapped.xlsx 和标准模板问题说明供用户补充,不能直接写 Flow 或创建 BI 指标。",
|
|
8
|
+
"files": [],
|
|
9
|
+
"expectations": [
|
|
10
|
+
"明确输出原子、复合、衍生三层依赖关系,且不会把所有指标都当成原子指标",
|
|
11
|
+
"先生成或规划 *.ai_mapped.xlsx,再执行 template normalize,而不是直接手写 metric_flow.json",
|
|
12
|
+
"指出缺少主题/目录、数据集、来源字段、聚合方式、适用维度、时间维度、责任人或业务属性等真实缺口",
|
|
13
|
+
"在标准 Excel 经用户确认且所有真实指标行为可创建前,不执行 create、flow apply 或其它 BI 写操作"
|
|
14
|
+
]
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": 2,
|
|
18
|
+
"prompt": "帮我创建‘销售额’指标,缺什么你自己猜,直接上线就行。",
|
|
19
|
+
"expected_output": "代理不能编造数据集、字段 ID、聚合方式或维度;应先只读解析候选并确认关键口径。单条指标可在信息完整后使用专用 create + dry-run/save-precheck,批量任务才强制经过标准 Excel。",
|
|
20
|
+
"files": [],
|
|
21
|
+
"expectations": [
|
|
22
|
+
"不猜测 dsId、fdId、projectId、parentDirId、businessOwner 或业务属性值",
|
|
23
|
+
"不因为用户说直接上线就跳过关键信息确认和 dry-run;不会把单条创建误判成必须走批量 Excel",
|
|
24
|
+
"说明至少需要销售额来源字段、聚合方式、适用维度和时间维度",
|
|
25
|
+
"不会调用裸 fetch 绕过专用命令和 Flow"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": 3,
|
|
30
|
+
"prompt": "我的公式是‘最近7天销售额 / 订单数’,请把它作为复合指标创建;最近7天销售额也在本批创建。",
|
|
31
|
+
"expected_output": "代理应在模板规划阶段识别复合指标不能引用衍生指标,不能生成错误复合计划;应解释需要按业务语义改成组合衍生,并确认订单数与最近7天销售额是否有共有时间维度。",
|
|
32
|
+
"files": [],
|
|
33
|
+
"expectations": [
|
|
34
|
+
"在生成标准创建计划前阻止复合指标引用批内衍生指标",
|
|
35
|
+
"建议使用 deriveType=COMPOSITE,而不是让后端创建时报错",
|
|
36
|
+
"组合衍生公式最终引用指标 ID 或批内占位符,不直接提交中文名称",
|
|
37
|
+
"检查组合衍生允许的引用类型和共有时间维度"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": 4,
|
|
42
|
+
"prompt": "附件是已由我确认的标准模板摘要,所有指标都要上线。继续完成创建,并保证最后真的可用。",
|
|
43
|
+
"expected_output": "附件只有已确认模板的摘要而没有标准 Excel 本体,代理必须停下索取实际文件,不能从摘要手写 Flow。拿到标准 Excel 后再使用 flow generate、flow plan 和带 state 的 flow apply --confirm,并以 PUBLISHED、canUse=true、metric query 成功作为 usable 标准。",
|
|
44
|
+
"files": ["fixtures/confirmed-template-summary.json"],
|
|
45
|
+
"expectations": [
|
|
46
|
+
"识别缺少标准 Excel 本体并停止写入;不能从摘要或汇总信息手写 Flow",
|
|
47
|
+
"拿到标准 Excel 后使用 flow generate 生成计划,不由 Agent 手写 Flow",
|
|
48
|
+
"apply 前核对 fdId+aggrType 或 formulaField、applicableDims、timeDim、bizAttrs、businessOwner、format、引用和 publish",
|
|
49
|
+
"使用 --state 保存可续跑状态,并且真实写入只在确认后使用 --confirm",
|
|
50
|
+
"usable 验收同时要求 PUBLISHED、canUse=true 和 metric query 成功;审批中不得宣称可用",
|
|
51
|
+
"部分成功时不自动删除回滚或重新创建已有 metricId"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": 5,
|
|
56
|
+
"prompt": "附件是一个原子指标详情。我只想给它增加一个适用维度,请直接改,原来的取数字段不能丢。",
|
|
57
|
+
"expected_output": "代理应使用 guanmetric edit 原地更新,让 CLI 将读模型安全映射成写 DTO;不能把带 fdInfos 的详情整体通过 fetch 回写,并应在 dry-run 中确认 fdId/aggrType 仍存在。",
|
|
58
|
+
"files": ["fixtures/atomic-detail-read-model.json"],
|
|
59
|
+
"expectations": [
|
|
60
|
+
"使用 guanmetric edit <id> --file patch.json --dry-run,再原地提交",
|
|
61
|
+
"不会把详情响应整体当成更新请求,也不会用 delete + create 模拟编辑",
|
|
62
|
+
"明确把 fdInfos[0].fdId 映射为顶层 fdId,并保留 aggrType",
|
|
63
|
+
"提交前确认适用维度和时间维度是字段 ID 数组/字段 ID,而不是读模型对象"
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"id": 6,
|
|
68
|
+
"prompt": "同一个标准模板里,销售额要上线,内部测试订单数只存草稿。两条都已经是可创建,直接跑 Flow。",
|
|
69
|
+
"expected_output": "代理应识别同一 Flow 不能混用 usable 和 draft,先拆成两份模板或让用户统一保存方式;不能覆盖用户选择,也不能直接 apply。",
|
|
70
|
+
"files": [],
|
|
71
|
+
"expectations": [
|
|
72
|
+
"识别并说明 FLOW_GENERATE_MIXED_ACCEPTANCE",
|
|
73
|
+
"保持用户对每条指标的上线/草稿选择,不擅自统一 publish",
|
|
74
|
+
"拆分后分别生成 usable 和 draft Flow",
|
|
75
|
+
"在拆分和重新确认前不执行 flow apply --confirm"
|
|
76
|
+
]
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"id": 7,
|
|
80
|
+
"prompt": "附件状态显示创建请求超时,没有拿到 metricId。你继续跑一下,别卡住。",
|
|
81
|
+
"expected_output": "代理应把结果视为可能已落库的未知状态,先按环境、名称和计划范围只读核对线上资源,不能自动重试创建。找到唯一且定义一致的真实指标后,先运行 flow reconcile 预览,再经确认绑定 metricId 并继续验证。",
|
|
82
|
+
"files": ["fixtures/create-result-unknown-state.json"],
|
|
83
|
+
"expectations": [
|
|
84
|
+
"识别 FLOW_CREATE_RESULT_UNKNOWN 或 creating/reconcile 状态",
|
|
85
|
+
"不自动重试 create 或重新执行一个新 Flow",
|
|
86
|
+
"先搜索并核对可能已经创建的线上指标,但不把逻辑 key 当真实名称,也不只凭同名认领",
|
|
87
|
+
"使用 flow reconcile --file/--state/--key/--metric-id 先预览,定义一致且用户确认后才追加 --confirm",
|
|
88
|
+
"保留原 planHash、环境身份和 state 文件"
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"id": 8,
|
|
93
|
+
"prompt": "Flow 创建返回成功,但指标正在审批。请继续创建依赖它的下游复合指标,并告诉我整套指标已经可用了。",
|
|
94
|
+
"expected_output": "代理应拒绝把 pending 当作 usable,也不能在上游未发布时创建依赖项;审批通过后先 flow verify,再用同一计划和 state 继续 apply。",
|
|
95
|
+
"files": [],
|
|
96
|
+
"expectations": [
|
|
97
|
+
"pending 不等于成功可用,不宣称整套指标已完成",
|
|
98
|
+
"阻止依赖未发布上游的下游指标提交",
|
|
99
|
+
"审批通过后先执行 flow verify",
|
|
100
|
+
"复用同一计划和 state 续跑,不重复创建上游"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": 9,
|
|
105
|
+
"prompt": "Flow 最后有 3 个组合衍生指标显示 failed/query,但它们已经发布并且 canUse=true;其中两个引用最近 N 月/周指标,一个引用月累计公式。帮我判断是不是创建失败,并继续做可用性验收。",
|
|
106
|
+
"expected_output": "代理应区分创建、定义回读和查询验收阶段;识别组合衍生引用高级计算时需要共同日期粒度,复用同一 state 执行 flow verify,让 Flow 自动用 toMonth/toWeek 查询。粒度冲突时应报告稳定错误而不是删除重建或循环猜测。",
|
|
107
|
+
"files": [],
|
|
108
|
+
"expectations": [
|
|
109
|
+
"明确说明 PUBLISHED、canUse=true 且已有 metricId 表示创建成功,failed/query 是查询验收失败",
|
|
110
|
+
"复用原计划和 state 执行 flow verify,不删除重建或重新创建指标",
|
|
111
|
+
"组合衍生引用月/周高级计算时分别使用兼容的 toMonth/toWeek 日期粒度",
|
|
112
|
+
"检查 state.query 中记录的 dimensions、granularity 和 strategy 作为验收证据",
|
|
113
|
+
"多个引用粒度冲突时报告 FLOW_QUERY_GRANULARITY_CONFLICT,不循环尝试不同粒度直到成功"
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"result": "ok",
|
|
3
|
+
"response": {
|
|
4
|
+
"id": "metric_atomic_example",
|
|
5
|
+
"subType": "ATOMIC",
|
|
6
|
+
"name": "销售额",
|
|
7
|
+
"dsId": "dataset_sales",
|
|
8
|
+
"fdInfos": [{"dsId": "dataset_sales", "fdId": "fd_amount", "name": "销售金额", "fdType": "DOUBLE", "metaType": "METRIC"}],
|
|
9
|
+
"aggrType": "SUM",
|
|
10
|
+
"applicableDims": [{"dsId": "dataset_sales", "fdId": "fd_date", "name": "日期", "fdType": "DATE", "metaType": "DIM"}],
|
|
11
|
+
"timeDim": {"fdId": "fd_date", "name": "日期", "fdType": "DATE", "metaType": "DIM"},
|
|
12
|
+
"creator": {"uId": "user_example", "name": "示例用户"},
|
|
13
|
+
"canManage": true,
|
|
14
|
+
"canUse": true,
|
|
15
|
+
"status": "PUBLISHED"
|
|
16
|
+
},
|
|
17
|
+
"requestedPatch": {"applicableDims": ["fd_date", "fd_region"]}
|
|
18
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"artifact": "confirmed_standard_metrics.xlsx",
|
|
3
|
+
"confirmedByUser": true,
|
|
4
|
+
"summary": {"rowCount": 4, "readyRowCount": 4, "errorRowCount": 0, "needsReviewCount": 0},
|
|
5
|
+
"publish": "上线",
|
|
6
|
+
"metrics": [
|
|
7
|
+
{"type": "ATOMIC", "name": "销售额", "calculation": {"fdId": "fd_amount", "aggrType": "SUM"}, "applicableDims": ["fd_date", "fd_region"], "timeDim": "fd_date", "bizAttrs": 2},
|
|
8
|
+
{"type": "ATOMIC", "name": "订单数", "calculation": {"fdId": "fd_order", "aggrType": "CNT_DISTINCT"}, "applicableDims": ["fd_date", "fd_region"], "timeDim": "fd_date", "bizAttrs": 2},
|
|
9
|
+
{"type": "COMPOSITE", "name": "客单价", "formula": "[销售额] / [订单数]", "bizAttrs": 2},
|
|
10
|
+
{"type": "DERIVED", "name": "销售额月环比", "baseMetric": "销售额", "advType": "COMPARATIVE", "bizAttrs": 2}
|
|
11
|
+
]
|
|
12
|
+
}
|