@guandata/guancli 1.0.65 → 1.0.67
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 +9 -0
- package/README.md +9 -0
- package/package.json +6 -6
- package/skills/guancli/SKILL.md +10 -1
- package/skills/guancli/evals/evals.json +8 -9
- package/skills/guancli/references/analysis-primitives.md +114 -4
- package/skills/guancli/references/form-chatbi.md +8 -0
- package/skills/guancli/references/metric-batch-query.md +2 -0
- package/skills/guancli/references/metric-commands.md +23 -9
- package/skills/guancli/references/metric-query-recipes.md +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## @guandata/guancli 1.0.67 - 2026-10-15
|
|
4
|
+
|
|
5
|
+
- 表单写入后明确提示刷新目标数据集,并区分数据刷新与字段结构同步。
|
|
6
|
+
|
|
7
|
+
## @guandata/guancli 1.0.66 - 2026-10-14
|
|
8
|
+
|
|
9
|
+
- 新增本地 `analyze` 表格处理与 `report` 排名分析入口,可对 CSV/JSON 结果进行字段对齐、计算、分组排名和占比输出。
|
|
10
|
+
- 修复指标查询中计算字段作为维度或排序列时的列名解析错误。
|
|
11
|
+
|
|
3
12
|
## @guandata/guancli 1.0.65 - 2026-10-12
|
|
4
13
|
|
|
5
14
|
- 子表行更新前校验分页总数与行标识;读取不完整时停止操作,避免误删现有行。
|
package/README.md
CHANGED
|
@@ -45,6 +45,15 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
|
|
|
45
45
|
|
|
46
46
|
## 版本更新
|
|
47
47
|
|
|
48
|
+
### @guandata/guancli 1.0.67
|
|
49
|
+
|
|
50
|
+
- 表单写入后明确提示刷新目标数据集,并区分数据刷新与字段结构同步。
|
|
51
|
+
|
|
52
|
+
### @guandata/guancli 1.0.66
|
|
53
|
+
|
|
54
|
+
- 新增本地 `analyze` 表格处理与 `report` 排名分析入口,可对 CSV/JSON 结果进行字段对齐、计算、分组排名和占比输出。
|
|
55
|
+
- 修复指标查询中计算字段作为维度或排序列时的列名解析错误。
|
|
56
|
+
|
|
48
57
|
### @guandata/guancli 1.0.65
|
|
49
58
|
|
|
50
59
|
- 子表行更新前校验分页总数与行标识;读取不完整时停止操作,避免误删现有行。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guandata/guancli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.67",
|
|
4
4
|
"description": "观远 BI 命令行工具 - 通过 API 操作 ETL、数据集、页面、表单等资源,并提供 ChatBI 问数/洞察能力",
|
|
5
5
|
"bin": {
|
|
6
6
|
"guancli": "bin/run.js"
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
"node": ">=14"
|
|
43
43
|
},
|
|
44
44
|
"optionalDependencies": {
|
|
45
|
-
"@guandata/guancli-darwin-arm64": "1.0.
|
|
46
|
-
"@guandata/guancli-darwin-x64": "1.0.
|
|
47
|
-
"@guandata/guancli-linux-x64": "1.0.
|
|
48
|
-
"@guandata/guancli-linux-arm64": "1.0.
|
|
49
|
-
"@guandata/guancli-win32-x64": "1.0.
|
|
45
|
+
"@guandata/guancli-darwin-arm64": "1.0.67",
|
|
46
|
+
"@guandata/guancli-darwin-x64": "1.0.67",
|
|
47
|
+
"@guandata/guancli-linux-x64": "1.0.67",
|
|
48
|
+
"@guandata/guancli-linux-arm64": "1.0.67",
|
|
49
|
+
"@guandata/guancli-win32-x64": "1.0.67"
|
|
50
50
|
},
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"registry": "https://registry.npmjs.org/",
|
package/skills/guancli/SKILL.md
CHANGED
|
@@ -140,6 +140,14 @@ guancli 在这条链路上只出只读的那一环:`guancli page search` / `pa
|
|
|
140
140
|
|
|
141
141
|
## Form 关键规则
|
|
142
142
|
|
|
143
|
+
**表单与数据集同步边界**:SurveyEngine 表单是数据源,BI 仅在主动更新或已配置的调度运行时抽取。`guancli form add/update/delete` 的成功回执只针对表单操作,不证明关联 GUAN_FORM 数据集已更新;CLI 不会自动刷新。刷新以整个业务任务为边界,不以接口批次或 CLI 调用次数为边界。分批写入或修改结构期间,禁止因每次成功提示逐批刷新或同步结构;提示本身不构成立即更新数据集的指令。全部批次及结构修改完成、核对成功与失败结果后,仅当用户需要下游 ETL/卡片使用最新结构或数据时,对每个关联数据集统一更新一次;只要求写入表单时,不主动刷新。比如 1 万条拆成 100 批写入,应全部完成后按需刷新一次,不能每批刷新。数据更新使用 `guands dataset refresh <dsId> --overwrite --wait`。新建填报数据集默认不开启定时更新。使用已确认关联该 fmId 的 dsId,不能按同名猜测。
|
|
144
|
+
|
|
145
|
+
字段新增、删除、改名或类型变化且需要更新下游时,等本次业务任务的全部结构修改与数据写入完成后,统一先执行 `guands dataset sync-schema plan <dsId> --out plan.json`,检查字段映射与删除项,再执行 `guands dataset sync-schema apply <dsId> --plan plan.json --mode schema-only --dry-run`,核对后移除 `--dry-run` 执行;结构同步完成后再主动执行 `guands dataset refresh <dsId> --overwrite --wait`。默认使用 `schema-only`;只有用户明确授权重置数据集时才使用 `reset`,该模式更新结构并全量抽取。普通 refresh(含 --overwrite)不替代模型结构同步。结构编辑是 `guands form update <fmId> form.js`,数据行更新是 `guancli form update <fmId> <rowId>`。
|
|
146
|
+
|
|
147
|
+
**刷新等待超时**:`guands dataset refresh <dsId> --wait` 默认等待 300 秒,可在首次触发时用 `--timeout <秒数>` 调整(如 `--timeout 1800`)。等待超时或调用工具停止等待只表示结果尚未确认,不等于服务端更新失败,也不会取消已提交的更新。遇到超时,先执行只读命令 `guands dataset get <dsId>` 查看当前更新状态,结合本次提交回执、任务标识(若返回)及执行时间确认是否为本次更新:仍在更新时继续只读查询状态;确认本次已成功时直接回读数据验证,不再刷新;只有确认本次已失败或取消、排除其他正在执行的更新并查明原因后,才按原授权范围决定是否重试。状态读取失败、信息不足或无法确认本次结果时,报告“更新结果待确认”,不得推断失败并重发 refresh。不要把再次执行 `refresh --wait` 当作纯等待接口:若原任务已结束,该命令可能提交新的更新;`--overwrite` 同样不能用于超时后盲目重试。
|
|
148
|
+
|
|
149
|
+
`form query` 回读表单数据,`ds preview` 回读 BI 数据集;两者不是同一个读取阶段。确认刷新失败且决定重试时,只重试刷新,不重复已成功的表单写入。`--overwrite` 遇到已有更新会拒绝,应等其结束后重新提交;不能只等待写入前已启动的旧任务就认定本次写入已被抽取。开启审批时应先确认审批通过及数据实际生效,再更新数据集。
|
|
150
|
+
|
|
143
151
|
- `form query --filter` 在**服务端**执行,格式 `"列名 操作符 [值]"`,可重复;多条件默认
|
|
144
152
|
`AND`,用 `--combine-type OR` 改成 `OR`。操作符可用性取决于字段控件类型:比较和区间
|
|
145
153
|
操作符(`GT`/`GE`/`LT`/`LE`/`BT` 系列)只支持 `NUMBER` 和 `DATE_TIME`,
|
|
@@ -162,8 +170,9 @@ guancli 在这条链路上只出只读的那一环:`guancli page search` / `pa
|
|
|
162
170
|
- 必须解析的命令不得用 `2>/dev/null` 隐藏 stderr,也不得用 `2>&1` 将错误文本送入 JSON 解码器。不要用会让末端命令成功掩盖上游失败的管道;允许组合执行时用 `&&` 衔接“输出到文件 → 解析摘要”,不为读取文件另起一轮推理,必须使用管道时先启用 `set -o pipefail`。
|
|
163
171
|
- 同类语法错误只允许出现一次;第一次失败后先执行对应命令的 `--help` 或读取本 Skill 的参考文档,再按真实契约纠正,不连续尝试相近写法。
|
|
164
172
|
- 普通 `--filter`、可重复 `--filter-json`、单个 `--filter-file` 三选一,禁止混用。复杂筛选优先使用 `--filter-json`(可重复)或 `--filter-file` 条件树。Agent 执行任意单条 `metric query`(包括无参数的基础查询)前都必须先用同一组查询参数追加 `--explain-requests -f json`,核对真实接口顺序和最终 request body;只有 `valid=true`、`executable=true` 且 body 符合业务意图时,才移除 explain 执行真实查询。`batch-query` 是独立批量契约,不支持 explain,不套用这条单条查询门禁;它仍按上文同轮批量规则使用。只需人工快速检查维度/筛选时可用 `--dry-run -f json`,但不能替代 Agent 的 explain-first 门禁。explain 会调用与真实执行相同的 request builder:泛化查询给出最终 `metric-data/v2` body,基础查询只读保存的 card edit meta 后给出完整 session/modify/data 计划;它不创建 edit session、不执行 POST、不取数。完整模式矩阵见 `references/metric-query-recipes.md`。dry-run 只读取指标详情做查询维度、筛选字段和类型校验,不执行指标取数,也不支持普通文件或 stderr 输出目标;保存卡片高级计算列不在指标详情中,因此这类排序候选在 dry-run 中不会被猜测为有效,explain/真实执行会读取既有 card 配置校验。不支持的 `--dim`、普通 `--filter` 的字段、`--sort-asc`/`--sort-desc` 的字段都按指标详情中的字段(适用维度 / 时间维度 / 指标字段名)校验,未命中返回 `METRIC_UNSUPPORTED_DIMENSION`;结构化 `--filter-json`/`--filter-file` 在解析阶段按同一份字段集合校验,未命中返回 `FILTER_UNKNOWN_FIELD`。两类错误都不会静默忽略条件或透传未知字段。普通展示别名只对 `--dim` 与排序生效;若指标详情的 `publicDimensionMap` 把唯一公共维度名映射到一个适用维度,则 `--dim`、排序和筛选也可使用该公共维度名,CLI 会保留物理 `fdId` 并把公共维度名作为 alias;同名映射到多个物理字段时拒绝猜测。仅由 CLI 为排序注入、以指标 ID 充当 `fdId` 的“指标名伪字段”不能用于筛选,若指标详情的 `fdInfos` 本身含同名原始字段和真实 `fdId`,仍可正常筛选。`--sort-asc`/`--sort-desc` 额外接受保存卡片中真实存在的高级计算列,以及泛化查询的结果列名 `<指标名>_<后缀>`(`_yoy`/`_mom`/`_qoq`/`_wow`/`_dod`/`_ytd`/`_qtd`/`_mtd`/`_wtd`/`_dtd`/`_last`/`_recent_*`/`_percentage`/`_rank`)。遇到这些错误时先用 `guancli metric get` 读取适用维度再改字段。条件组使用 `combineType: AND|OR` 和 `conditions` 数组,叶子使用 `field/operator/value|values`;`IN` 至少一个值,`BT` 恰好两个值。当前指标取数接口不能无损表达多分支 OR,真实执行会在取数前返回 `FILTER_OR_EXECUTION_UNSUPPORTED`,不得拆成多次聚合查询后拼接。失败时按稳定错误码修正,不猜错误文本。
|
|
173
|
+
- 查询计算字段维度或按计算字段排序时,直接使用指标详情中的字段名(日期子维度仍可加 `toMonth` 等粒度),无需手工传公式;CLI 会从指标详情把 `formula` 带入基础卡片和泛化查询的维度/排序请求。先用 `metric get <id> --raw` 核对计算字段的 `formula/fdType`,再用同参数的 `--explain-requests -f json` 检查最终请求体。若不再报 `UNRESOLVED_COLUMN`,但维度值为空或筛选报 `DATATYPE_MISMATCH`,对照 `ds get --raw` 与 `ds preview` 核查公式实际结果和字段声明类型;不能把请求成功当成维度结果正确。详见 [计算字段查询排查](references/metric-query-recipes.md#计算字段维度与排序)。
|
|
165
174
|
- 搜索并同时查看业务口径、数据集和适用维度等详情时,优先使用 `guancli metric search --fuzzy <keyword> --limit <N> --with-detail --brief -f json`,不要先 search 再逐个 get,也不要为终端阅读额外拼 jq。只查单个指标详情时优先使用 `guancli metric get <metric_id> --brief`;只裁剪指标查询结果列时使用 `metric query --columns`。可复制模板见 `references/metric-commands.md`。
|
|
166
|
-
-
|
|
175
|
+
- `metric search --fuzzy` 的每项关键词按原文匹配,不自动拆词或解析型号、客户等筛选实体;多个关键词使用重复的 `--fuzzy` 参数,彼此为 OR。后端最多接受 10 个关键词,每项最长 100 个字符。候选发现默认首轮最多 5 个去重关键词;禁止相同范围下换序、轻微改写或取子集重复搜索。仅发现具体错误或新线索时,说明依据和参数修正,最多追加一轮纠错;单纯无命中不是重查依据。仍不能确定则说明关键词、范围和原因,必要时请用户补充信息,不断言指标不存在。完整协议及纠错边界见 `references/metric-commands.md`。
|
|
167
176
|
- 指标结果加工前,先读取成功 query envelope 的实际 `columns` 和行对象 keys,按业务含义选择列;禁止硬编码或猜测指标展示列名(包括高级计算后缀),也不能按列位置取值。使用 `python3 references/examples/metric-query-rows.py <envelope.json> --list-columns` 发现列,再用 `--column "<已确认的实际列名>"` 精确选择;候选缺失或多义时停止并返回实际列集合,不猜近似名称。该参数属于消费 recipe,不是 `guancli metric query` 的参数。
|
|
168
177
|
- 普通指标数据查询用 `guancli metric query <metric_id>`,可加 `--dim`、筛选、排序、列筛选、输出格式等。数值默认按指标配置的 `format` 输出(查询响应有更具体的列级格式时优先),没有有效格式时才按 `--precision` 回退;需要标准表格/JSON/CSV/Excel 中保留原始数值时传 `--value-format raw`,不要和直接返回后端响应的全局 `--raw` 混淆。使用 `-f json` 时,未指定 `-o/--output` 且结果超过 1000 行会自动写入 `metric_<metricId>_<timestamp>_<unique>.json`,stdout 返回 `resultMode=file` 和绝对 `path`,不得再从中文提示猜文件名。唯一后缀用于避免同秒并发或重试覆盖已有结果。默认文本、CSV/Excel 和 `--raw` 保持原行为。回答指标数据查询结果时,必须检查输出中的 `查询加速` summary 或 `_queryAccelerate` 列:命中时明确说明“本次查询命中查询加速”,并列出源指标 ID、加速指标 ID 和页面查询顺序;未命中时说明“未命中查询加速”;如果显示 `未知: 后端未返回`,说明当前后端未返回命中 metadata,不能推断是否命中。注意:输出中的 `优先级N` 来自后端 `acceleratePriority` 排序权重,数字越大越先尝试;不要把它直接解释成页面“查询顺序”。需要和页面对齐时,额外执行 `guancli metric accelerate list <metric_id>`,按 `acceleratePriority` 倒序排列后换算页面查询顺序(倒序第 1 个即页面查询顺序 1)。
|
|
169
178
|
- 同一批量查询既用于计算又用于展示时,使用 `valueFormat: "both"`;原始 `rows` 用于计算,`formattedRows` 用于展示,不按格式重复取数。仅需一种格式时使用 raw 或 formatted,避免额外输出。
|
|
@@ -52,29 +52,28 @@
|
|
|
52
52
|
{
|
|
53
53
|
"id": 5,
|
|
54
54
|
"prompt": "帮我找‘复购成交贡献’相关指标。附件给出了本轮可重复的指标搜索返回,请展示你会执行的候选发现命令和最终答复。",
|
|
55
|
-
"expected_output": "
|
|
55
|
+
"expected_output": "代理应说明 --fuzzy 每项原文匹配、各项 OR 的契约,使用重复参数构造关键词;附件空结果仅证明该次搜索未命中,后续发现与停止遵循调用方业务指令,不由 CLI 强制一轮结束。",
|
|
56
56
|
"files": [
|
|
57
57
|
"fixtures/metric-candidate-empty-search.json"
|
|
58
58
|
],
|
|
59
59
|
"expectations": [
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"不把附件中的直接名称搜索计入候选发现 fuzzy 轮次"
|
|
60
|
+
"多个关键词使用重复的 --fuzzy 参数,说明原文匹配且各项 OR",
|
|
61
|
+
"遵守单次请求最多 10 个关键词、每项最长 100 字符的接口限制",
|
|
62
|
+
"报告本次实际关键词和搜索范围,不将空结果断言为指标不存在",
|
|
63
|
+
"不把 CLI 接口限制当成业务发现轮数或固定停止规则"
|
|
65
64
|
]
|
|
66
65
|
},
|
|
67
66
|
{
|
|
68
67
|
"id": 6,
|
|
69
68
|
"prompt": "上一请求曾按附件记录搜索‘复购成交贡献’且没有候选。现在这是一个新的用户请求:再帮我找一次‘复购成交贡献’相关指标。请给出本次请求的下一条候选发现命令;不要沿用附件发生时的指标可见性。",
|
|
70
|
-
"expected_output": "
|
|
69
|
+
"expected_output": "代理不能把上一请求的空结果作为本次指标不存在的证明;本次搜索基于当前可见范围,关键词与停止条件遵循当前调用方指令和接口限制。",
|
|
71
70
|
"files": [
|
|
72
71
|
"fixtures/metric-candidate-prior-request.json"
|
|
73
72
|
],
|
|
74
73
|
"expectations": [
|
|
75
74
|
"即使附件记录上一请求无结果,本次仍生成一条新的 metric search --fuzzy 命令",
|
|
76
|
-
"
|
|
77
|
-
"
|
|
75
|
+
"使用重复的 --fuzzy 参数表达多个关键词,不将它们拼接成一句话",
|
|
76
|
+
"遵守单次请求最多 10 个关键词、每项最长 100 字符的接口限制",
|
|
78
77
|
"不把上一请求的 stop_reason 当成本次请求的搜索结果"
|
|
79
78
|
]
|
|
80
79
|
},
|
|
@@ -17,7 +17,35 @@
|
|
|
17
17
|
|
|
18
18
|
- CLI 只提供 loader、字段对齐、安全四则运算、分组排序、TopN 和占比。
|
|
19
19
|
- “本期/同期/预算”“同比/达成率”“毛利贡献”“价格/成本效应”等属于上层分析 recipe。调用方应显式选择字段并组合通用原语,禁止假设 CLI 内置这些业务口径。
|
|
20
|
-
-
|
|
20
|
+
- 优先用下述 report 统一入口;需要其他组合时再逐步调用原语。命令失败后读取错误并修正字段或策略,不用临时 Python 脚本绕过契约。
|
|
21
|
+
|
|
22
|
+
## 首选:统一排名分析入口 report
|
|
23
|
+
|
|
24
|
+
常见“每组 TopN+补充同键指标/贡献占比/比率”用一条命令,不必生成中间文件,也不需要 DSL:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 两份查询按相同品类、型号粒度取 raw,并先核实取数完整。
|
|
28
|
+
guancli analyze report profit.json --group-by 品类 --value-field 毛利额 \
|
|
29
|
+
--limit 1 --complete-input --enrich margin-rate.json --key 品类,型号 \
|
|
30
|
+
-o category-leaders.json
|
|
31
|
+
|
|
32
|
+
# 全局收入排名+占比+同键利润安全除法复核。
|
|
33
|
+
guancli analyze report income.json --global --value-field 收入 \
|
|
34
|
+
--limit 4 --share-field contribution --complete-input \
|
|
35
|
+
--enrich profit.json --key 客户 --operator divide \
|
|
36
|
+
--left-field extra.毛利额 --right-field 收入 --output-field margin \
|
|
37
|
+
-o income-ranking.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- 沿用 loader;batch 主文件用 --result-id,补充文件用独立 --enrich-result-id。单查 raw、batch raw/both。
|
|
41
|
+
- 固定流程:规范化 → 可选 left 对齐完整候选池 → 可选安全计算 → 分组排名/占比。只输出最终 analysis/v1,operation 为 report。
|
|
42
|
+
- 必须显式二选一 --group-by / --global;“各品类哪款最高”上游同时取品类+型号,并按品类分组,不是全局排名。
|
|
43
|
+
- --complete-input 必须先核验后声明;不证明分页完结或补抓数据。query 默认 50 行不能当全量,report 的 limit 只是每组输出数量。
|
|
44
|
+
- 补充指标须指定完整组合键,默认任一侧重复键失败,即使最终不入榜。显式传 `--allow-repeated-source-keys` 可用唯一补充行匹配多条主输入行(多对一),补充侧重复键仍拒绝;不增加、合并或聚合主输入行。右侧额外对象不进入结果,缺失补充值保持 null。普通 `align` 仍要求两侧键唯一。
|
|
45
|
+
- 补充后非键列为 source.<原列> / extra.<原列>。value-field、group-by、计算操作数可用主输入原列名(自动映射),补充列须 extra.<原列>;计算结果列使用 output-field 原名。
|
|
46
|
+
- operator/left-field/right-field/output-field 必须一起传入。空值传播,除零返回 null;不猜测财务口径。
|
|
47
|
+
- share 分母为截断前完整分区合计。多个指标独立排名应分别从完整原始输入调用 report,不能用已截断子集推算另一指标全池排名。
|
|
48
|
+
- 跨期、严格除零、自定义排序或其他 join 仍使用下面原语;report 不替代所有分析能力。
|
|
21
49
|
|
|
22
50
|
## 规范化
|
|
23
51
|
|
|
@@ -28,10 +56,10 @@ guancli analyze normalize raw.json --input-format json -o normalized.json
|
|
|
28
56
|
|
|
29
57
|
- 自动识别 CSV/JSON,也可以用 `--input-format` 明确指定。
|
|
30
58
|
- 去除 UTF-8 BOM;JSON 嵌套对象扁平化为 `父字段.子字段`。
|
|
31
|
-
- CSV 按记录读取,JSON
|
|
59
|
+
- CSV 按记录读取,JSON 对象数组按元素读取,envelope/二维 rows 通过同一 loader 适配;最终规范化表仍会保留在内存中,超大结果应在上游先过滤。
|
|
32
60
|
- JSON 数字按原始十进制文本解析并原样写回,超过 JavaScript 安全整数范围的 ID 不会先转成浮点数而丢失精度。
|
|
33
61
|
- CSV/JSON 字符串中的空字符串、`null`、`None`、`<nil>` 默认转成 JSON `null`。需要其他契约时可重复传 `--null-value`;一旦显式传入,就只使用调用方给出的集合。
|
|
34
|
-
- JSON 顶层支持对象数组、单个对象、`rows`
|
|
62
|
+
- JSON 顶层支持对象数组、单个对象、`rows`/`data` 对象数组、`columns`+二维 `rows`、`analysis/v1` 和下述 query/batch envelope。列名保持精确匹配。
|
|
35
63
|
- 使用 `-o` 时先写同目录临时文件并同步,成功后再原子替换目标;写入、同步或关闭失败时保留原输出文件。
|
|
36
64
|
|
|
37
65
|
## 对齐
|
|
@@ -90,6 +118,88 @@ guancli analyze topn calculated.json \
|
|
|
90
118
|
```
|
|
91
119
|
|
|
92
120
|
- `--group-by` 是分区字段,不指定时对全表排序。
|
|
93
|
-
-
|
|
121
|
+
- 占比分母是输入文件中该分区全部非空行的数值之和,不是 TopN 截断后的合计;只有输入覆盖完整候选池,才可称为该分区全量占比。
|
|
94
122
|
- 空值排在有效数值之后,占比为 `null`;分区合计为 0 时占比同样为 `null`。
|
|
95
123
|
- `topn` 不做隐式聚合。存在重复粒度时,先使用具备明确聚合口径的上游查询或工具处理。
|
|
124
|
+
|
|
125
|
+
## 查询 → 本地加工(无需解包脚本)
|
|
126
|
+
|
|
127
|
+
单查实际生产契约是 `schemaVersion:"1.0", command:"metric.query"`,inline 的 `columns` 为字符串数组,`data` 为对象行数组。file 模式的绝对 `path` 指向对象行数组文件,loader 自动读取该文件,并校验 rowCount 和必需列;文件缺失、列缺失、版本或类型变化会失败。单查 envelope 不记录 valueFormat,查询时必须显式选择 `--value-format raw`,不要拿格式化字符串做数值计算。
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
# 替换为已确认的指标 ID、维度和实际输出列;此处示例业务字段为“区域”“金额”。
|
|
131
|
+
guancli metric query <metricId> --dim 区域 --limit 10000 --value-format raw -f json > query.json
|
|
132
|
+
# 先检查 rowCount/实际返回行数和候选池完整性;10000也不保证全量。
|
|
133
|
+
guancli analyze normalize query.json -o normalized.json
|
|
134
|
+
# 只有确认候选池完整后才排名;否则继续取数或标明结果仅覆盖已取窗口。
|
|
135
|
+
guancli analyze topn normalized.json --value-field 金额 --limit 10 -o topn.json
|
|
136
|
+
# 单查大结果返回 file envelope 时,仍将 stdout 保存为 query.json,使用相同命令。
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
batch 的生产契约是 `results[].result.columns:[{name,role}]` + 二维 `rows`,**不是**单查 `data` 对象数组。必须按输入项精确 id 选择:所有子命令支持 `--result-id`;align 左侧用此参数,右侧用 `--right-result-id`。不按顺序猜项,不自动拼接整批结果。所选项必须 status=success;planned/error、重复或不存在的 id、行宽/rowCount 不一致都失败。partial_failure 中的明确成功项可以单独加工,失败项错误中会保留 code/message/httpStatus/businessStatus。只接受 raw/both;both 消费 `rows`,不消费展示用 `formattedRows`。
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# queries.json 先按 metric-batch-query.md 编写,显式填写 limit/offset;current/prior 是用户定义的查询项 id。
|
|
143
|
+
# 两个结果都确认覆盖完整、同口径候选池后,才执行下面的排名链路。
|
|
144
|
+
guancli metric batch-query --input queries.json -f json > batch.json
|
|
145
|
+
guancli analyze normalize batch.json --result-id current -o current.json
|
|
146
|
+
guancli analyze align --left batch.json --result-id current \
|
|
147
|
+
--right batch.json --right-result-id prior --key 区域 \
|
|
148
|
+
--left-prefix current --right-prefix prior -o aligned.json
|
|
149
|
+
guancli analyze calculate aligned.json --operator subtract \
|
|
150
|
+
--left-field current.金额 --right-field prior.金额 --output-field difference -o delta.json
|
|
151
|
+
guancli analyze topn delta.json --value-field difference --limit 10 -o topn.json
|
|
152
|
+
# 直接在 batch 成功项内计算两个已确认的字段也可行:
|
|
153
|
+
guancli analyze calculate batch.json --result-id current --operator divide \
|
|
154
|
+
--left-field 金额 --right-field 预算 --output-field ratio --zero-divisor null -o ratio.json
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
只有位置式输入需要 `columns` 映射单元格;重复/空列名会拒绝,JSON 数字精度及 null 处理复用原 loader。空查询结果仍保留声明的 columns。CLI 只加工所选查询已返回的行,不补抓分页、不推断聚合口径;分组键和计算字段从实际列及业务意图确定。旧 CSV/对象数组/analysis/v1 输入和输出契约保持兼容。
|
|
158
|
+
|
|
159
|
+
## 排名前确认完整候选池
|
|
160
|
+
|
|
161
|
+
`metric query` 和 batch 每项的默认 limit 都是 **50**。`analyze topn --limit` 只是本地每个分区保留的排名数,不能代替上游查询 limit。开始排名或占比前,先明确筛选范围、分组粒度、候选池和预期资源量,显式规划查询 limit/offset,再根据实际返回和权威总量/上限证据确认取数完结。
|
|
162
|
+
|
|
163
|
+
- `rowCount == limit` 或返回量碰到已知后端/卡片上限时,视为可能截断,继续分页/扩大取数窗口或核对权威完结证据;不能直接对前50行宣称各品类 Top1。`rowCount < limit` 也须排除更小的后端上限、查询失败或范围不一致。
|
|
164
|
+
- 单查 query **没有 --offset**,不要编造该参数;可增大显式 limit 后重新取完整窗口,或使用 batch 的 offset/limit。batch 非零 offset 必须显式设置稳定排序,offset+limit 不超过10000;排序同值与跨请求数据变化可能导致重复/漏行,需按唯一键、同一筛选范围和数据一致性核对。分页契约见 [batch-query](metric-batch-query.md)。
|
|
165
|
+
- 例如下面两页仅用于规划和核查;不能直接把任一页送入 topn 后称全量结果。若确认候选池低于10000,可重新用 offset=0、足够的 limit 取完整候选池后加工。若仍超上限,按有依据的互斥筛选范围拆分并核实覆盖,或明确报告完整性未确认。CLI 不自动补抓/拼接分页,也不做业务聚合。
|
|
166
|
+
|
|
167
|
+
```json
|
|
168
|
+
[
|
|
169
|
+
{"id":"sales-p0","metricId":"<已确认指标ID>","dimensions":["品类","商品"],"sortAsc":"商品","offset":0,"limit":1000,"valueFormat":"raw"},
|
|
170
|
+
{"id":"sales-p1","metricId":"<已确认指标ID>","dimensions":["品类","商品"],"sortAsc":"商品","offset":1000,"limit":1000,"valueFormat":"raw"}
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
排序示例要求“商品”在候选池中唯一且为指标支持字段;不满足时先选择有依据的唯一排序/互斥查询范围。检查每页 status、rowCount、offset/limit 和键覆盖。排名输入必须覆盖每个分区完整候选池;份额计算的各指标还须覆盖相同口径的完整候选池。
|
|
175
|
+
|
|
176
|
+
## 按分区 Top1 后关联同键比率
|
|
177
|
+
|
|
178
|
+
前提:`sales.json` 已覆盖全部“品类+商品”候选,`margin-rate.json` 按相同粒度包含所选商品的毛利率。实际列名从查询结果确认;比率直接关联,不按商品外的粒度猜值。先选销售额 Top1,再以 Top1 为左表、**显式 --join left** 关联;full join 会重新引入未入选商品。
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
guancli analyze topn sales.json --group-by 品类 --value-field 销售额 \
|
|
182
|
+
--limit 1 --rank-field sales_rank -o sales-top1.json
|
|
183
|
+
guancli analyze align --left sales-top1.json --right margin-rate.json \
|
|
184
|
+
--key 品类 --key 商品 --join left --left-prefix selected --right-prefix rate \
|
|
185
|
+
-o sales-top1-with-rate.json
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
输出行集合仍是每品类选中的 Top1,毛利率列为 `rate.毛利率`;缺少同键比率时保留 null,核实缺失原因,不猜0,也无需再用 Node/Python 过滤整池。重复组合键会报错,先核实上游粒度。并列值按原输入顺序取一个,若业务要保留并列需另行确认口径。
|
|
189
|
+
|
|
190
|
+
## 多指标对齐后分别排名与占比
|
|
191
|
+
|
|
192
|
+
前提:销售额与毛利额查询均覆盖相同筛选范围、相同“品类+商品”粒度的完整候选池。这里 full join 用于保留并核查两侧全集;不用于给已截断的 Top1 补列。对齐后的缺失指标保持 null;不把缺失当0或声称口径已完整,确认后再执行排名。
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
guancli analyze align --left sales.json --right gross-profit.json \
|
|
196
|
+
--key 品类 --key 商品 --join full --left-prefix sales --right-prefix profit \
|
|
197
|
+
-o all-metrics.json
|
|
198
|
+
# 核对两侧键集合/缺失值与完整性;两条 topn 都读取尚未截断的 all-metrics.json。
|
|
199
|
+
guancli analyze topn all-metrics.json --group-by 品类 --value-field sales.销售额 \
|
|
200
|
+
--limit 1 --rank-field sales_rank --share-field sales_share -o sales-leaders.json
|
|
201
|
+
guancli analyze topn all-metrics.json --group-by 品类 --value-field profit.毛利额 \
|
|
202
|
+
--limit 1 --rank-field profit_rank --share-field profit_share -o profit-leaders.json
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`sales_share` 的分母是该品类完整候选池的销售额合计,`profit_share` 的分母是同池的毛利额合计。不要把 sales-leaders.json 再用于毛利额排名或全池占比;销售领先与毛利领先可能是不同商品。合计为0时占比为null,负值仍按实际数值求和,业务解释由调用方确认。
|
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
类似 Airtable 风格的表单数据 CRUD,用户始终用**字段名**操作,CLI 内部自动映射到 fdId。
|
|
6
6
|
|
|
7
|
+
**表单与数据集同步边界**:SurveyEngine 表单是数据源,BI 仅在主动更新或已配置的调度运行时抽取。`guancli form add/update/delete` 的成功回执只针对表单操作,不证明关联 GUAN_FORM 数据集已更新;CLI 不会自动刷新。刷新以整个业务任务为边界,不以接口批次或 CLI 调用次数为边界。分批写入或修改结构期间,禁止因每次成功提示逐批刷新或同步结构;提示本身不构成立即更新数据集的指令。全部批次及结构修改完成、核对成功与失败结果后,仅当用户需要下游 ETL/卡片使用最新结构或数据时,对每个关联数据集统一更新一次;只要求写入表单时,不主动刷新。比如 1 万条拆成 100 批写入,应全部完成后按需刷新一次,不能每批刷新。数据更新使用 `guands dataset refresh <dsId> --overwrite --wait`。新建填报数据集默认不开启定时更新。使用已确认关联该 fmId 的 dsId,不能按同名猜测。
|
|
8
|
+
|
|
9
|
+
字段新增、删除、改名或类型变化且需要更新下游时,等本次业务任务的全部结构修改与数据写入完成后,统一先执行 `guands dataset sync-schema plan <dsId> --out plan.json`,检查字段映射与删除项,再执行 `guands dataset sync-schema apply <dsId> --plan plan.json --mode schema-only --dry-run`,核对后移除 `--dry-run` 执行;结构同步完成后再主动执行 `guands dataset refresh <dsId> --overwrite --wait`。默认使用 `schema-only`;只有用户明确授权重置数据集时才使用 `reset`,该模式更新结构并全量抽取。普通 refresh(含 --overwrite)不替代模型结构同步。结构编辑是 `guands form update <fmId> form.js`,数据行更新是 `guancli form update <fmId> <rowId>`。
|
|
10
|
+
|
|
11
|
+
**刷新等待超时**:`guands dataset refresh <dsId> --wait` 默认等待 300 秒,可在首次触发时用 `--timeout <秒数>` 调整(如 `--timeout 1800`)。等待超时或调用工具停止等待只表示结果尚未确认,不等于服务端更新失败,也不会取消已提交的更新。遇到超时,先执行只读命令 `guands dataset get <dsId>` 查看当前更新状态,结合本次提交回执、任务标识(若返回)及执行时间确认是否为本次更新:仍在更新时继续只读查询状态;确认本次已成功时直接回读数据验证,不再刷新;只有确认本次已失败或取消、排除其他正在执行的更新并查明原因后,才按原授权范围决定是否重试。状态读取失败、信息不足或无法确认本次结果时,报告“更新结果待确认”,不得推断失败并重发 refresh。不要把再次执行 `refresh --wait` 当作纯等待接口:若原任务已结束,该命令可能提交新的更新;`--overwrite` 同样不能用于超时后盲目重试。
|
|
12
|
+
|
|
13
|
+
`form query` 回读表单数据,`ds preview` 回读 BI 数据集;两者不是同一个读取阶段。确认刷新失败且决定重试时,只重试刷新,不重复已成功的表单写入。`--overwrite` 遇到已有更新会拒绝,应等其结束后重新提交;不能只等待写入前已启动的旧任务就认定本次写入已被抽取。开启审批时应先确认审批通过及数据实际生效,再更新数据集。
|
|
14
|
+
|
|
7
15
|
### 列出表单
|
|
8
16
|
|
|
9
17
|
```bash
|
|
@@ -80,3 +80,5 @@ lite/kit 执行会在 replay 轮汇集独立请求;只读请求可标为 paral
|
|
|
80
80
|
- 只观察到指标引用了某个旧 ID,而没有对相同维度键的实际值做比较。
|
|
81
81
|
|
|
82
82
|
最终结果至少区分 `same`、`different`、`query_error`、`inconclusive_truncated`。汇报 `different` 时给出第一个真正相同维度键下的值差异;汇报 `inconclusive_truncated` 时给出双方行数、限制参数和建议的分片方式。
|
|
83
|
+
|
|
84
|
+
`guancli analyze` 可直接消费单查 inline/file 与 batch 成功项;batch 使用 `--result-id`,align 右侧使用 `--right-result-id`。查询→规范化→对齐→计算→TopN 完整示例见 [本地分析原语](analysis-primitives.md)。计算选择 raw/both,both 读取 raw rows;是否使用此加工方式由调用方决定。
|
|
@@ -87,17 +87,22 @@ guancli metric search [keyword] [flags]
|
|
|
87
87
|
- `--with-detail` 需要组合多个接口的结果,因此不兼容 `--raw`、`-f csv` 和 `-f excel`。
|
|
88
88
|
- `[keyword]` 走旧指标名称搜索接口;`--fuzzy` 走新的统一模糊搜索接口,二者不能同时使用。
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
-
|
|
94
|
-
-
|
|
95
|
-
-
|
|
96
|
-
- 如果单批搜索无候选,立即结束本轮候选发现。回答必须包含:`attempted_keywords`、`search_scope`、无结果原因“当前可见指标的名称、业务口径和可搜索业务属性均未命中”,以及 `stop_reason=no_candidate_within_budget`。
|
|
97
|
-
- 只有请求本身因可识别的认证、网络或服务错误失败时,才按对应错误恢复流程处理;业务无命中不是重试理由。
|
|
98
|
-
- 不缓存、不持久化、也不跨请求复用“未找到指标”的结论。每个新请求都必须基于当时的指标可见性、权限和指标内容重新判断。
|
|
90
|
+
模糊搜索输入与结果边界:
|
|
91
|
+
|
|
92
|
+
- 每项关键词按原文匹配,不自动拆词,也不把型号、客户等实体解析为取数筛选。多个关键词使用重复参数,例如 `--fuzzy "毛利率" --fuzzy "标准成本"`,彼此为 OR。
|
|
93
|
+
- 后端硬上限是 10 个关键词,每个关键词最长 100 个字符;这是单次请求的接口限制,不是业务发现轮数或停止条件。
|
|
94
|
+
- 空结果只表示本次关键词在当前可见范围未命中,不证明指标不存在。
|
|
95
|
+
- 搜索结果受当前权限、范围和指标内容影响,不作为跨请求有效的“指标不存在”证明。
|
|
99
96
|
- 已知指标主题 ID 时用 `-d <metric_topic_id>` 缩小 `search_scope`;未知主题时要说明搜索覆盖当前用户可见的全部指标主题。一次 CLI 调用在未知主题时可能内部扫描多个主题,不能把它表述成一次 HTTP 请求。
|
|
100
97
|
|
|
98
|
+
候选发现预算与纠错重查:
|
|
99
|
+
|
|
100
|
+
- 首轮保留用户原词,合并必要同义词后批量搜索,默认最多 5 个关键词;先 trim、合并连续空白,并按大小写不敏感语义去重。
|
|
101
|
+
- 禁止无效重复:相同关键词和范围的重复请求、仅换序、轻微改写或取已搜关键词子集,都不构成新的搜索依据。已有候选先核验,不因候选不唯一就重复搜索。
|
|
102
|
+
- 默认一轮;仅发现具体错误或新线索时,最多追加一轮纠错搜索。例如误把型号当指标名、选错指标主题,或候选详情提供了此前未知的业务名称。重查前说明依据、原参数的问题及本次修正;单纯“没找到”或猜测更多同义词不是纠错依据。
|
|
103
|
+
- 没有明确纠错依据,或纠错一轮后仍不能确定时停止,说明已尝试的关键词、搜索范围及未能确认的原因;必要时请用户补充信息,不断言指标不存在。用户补充新信息后重新判断,不跨请求复用“未找到”的结论。
|
|
104
|
+
- 认证、网络或服务错误按对应恢复流程处理,不将业务无命中当成服务错误重试。
|
|
105
|
+
|
|
101
106
|
回答要求:
|
|
102
107
|
|
|
103
108
|
- 必须逐条返回命中的指标,至少包含指标 ID、指标名称、状态、类型。
|
|
@@ -519,6 +524,15 @@ guancli metric_attribution query <metric_tree_id> --profile test43 --target dim
|
|
|
519
524
|
|
|
520
525
|
### 查询结果消费
|
|
521
526
|
|
|
527
|
+
`guancli analyze` 支持规范化、对齐、四则运算、TopN/占比,可直接读取 query envelope:
|
|
528
|
+
|
|
529
|
+
```bash
|
|
530
|
+
guancli analyze normalize query-envelope.json -o normalized.json
|
|
531
|
+
guancli analyze normalize batch.json --result-id current -o current.json
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
batch 必须选择 success 的 raw/both 项;both 使用 raw rows。batch 使用 `--result-id`,align 右侧使用 `--right-result-id`。完整查询→加工链路见 [本地分析原语](analysis-primitives.md)。以下为 Python/jq 消费示例;使用哪种加工方式由调用方决定。
|
|
535
|
+
|
|
522
536
|
机器查询统一用 `-f json`。`query` 的 `data` 和文件载荷都是行对象数组;search 的 `data` 是指标数组,get/tree 的 `data` 是单个对象。`rowCount` 属于 stdout envelope,不能从行数组读取。query 的 `columns` 保留真实业务列名,可以是中文;search/get 的 `id/name/dimensions` 是 canonical 英文字段。
|
|
523
537
|
|
|
524
538
|
下面示例在 Skill 目录执行;先确认 CLI 成功,再解析 stdout,stderr 单独保存:
|
|
@@ -49,6 +49,12 @@ guancli metric query <metric_id> --profile <profile> <查询参数> --explain-re
|
|
|
49
49
|
|
|
50
50
|
`--dry-run` 和 `--explain-requests` 是两个互斥的计划模式,不能同时传。
|
|
51
51
|
|
|
52
|
+
### 计算字段维度与排序
|
|
53
|
+
|
|
54
|
+
指标详情的适用维度、时间维度或日期子维度若带有 `formula`,`--dim` 和 `--sort-asc/--sort-desc` 使用字段名即可;CLI 会把公式随维度和排序对象送入基础卡片查询的 `zoneData.row/sorting`,或泛化查询的 `dimensions/sorting`。只传排序、不传 `--dim` 时也需要保留公式。`--percentage-dim`、`--rank-dim` 和时间类高级计算使用字段 ID,筛选由服务端按字段 ID 解析计算字段;`--columns` 只在客户端处理。
|
|
55
|
+
|
|
56
|
+
排查计算字段时先看 `metric get <id> --raw` 中字段的 `fdId/fdType/formula`,再用同参数的 `--explain-requests -f json` 检查实际请求中的维度与排序对象。`--dry-run` 的 `resolvedDimensions` 只展示部分字段,不足以确认公式是否进入最终请求。请求不再报 `UNRESOLVED_COLUMN` 仍不代表结果正确:若公式返回整数却把字段声明为 `DATE`,日期筛选可能报 `DATATYPE_MISMATCH`,分组值也可能异常或为空;应对照 `ds get --raw` 与 `ds preview` 核查字段类型和实际值。
|
|
57
|
+
|
|
52
58
|
## 3. 每种模式的最小合法命令
|
|
53
59
|
|
|
54
60
|
```bash
|