@josephyan/qingflow-app-user-mcp 1.0.9 → 1.1.2
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/README.md +6 -2
- package/npm/bin/qingflow-app-user-mcp.mjs +33 -2
- package/npm/lib/runtime.mjs +386 -15
- package/npm/scripts/postinstall.mjs +7 -2
- package/package.json +1 -1
- package/pyproject.toml +2 -1
- package/skills/qingflow-app-builder/SKILL.md +276 -0
- package/skills/qingflow-app-builder/agents/openai.yaml +4 -0
- package/skills/qingflow-app-builder/references/build-complete-system.md +428 -0
- package/skills/qingflow-app-builder/references/build-single-app.md +530 -0
- package/skills/qingflow-app-builder/references/create-app.md +149 -0
- package/skills/qingflow-app-builder/references/environments.md +63 -0
- package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +123 -0
- package/skills/qingflow-app-builder/references/gotchas.md +108 -0
- package/skills/qingflow-app-builder/references/match-rules.md +114 -0
- package/skills/qingflow-app-builder/references/public-surface-sync.md +75 -0
- package/skills/qingflow-app-builder/references/solution-playbooks.md +52 -0
- package/skills/qingflow-app-builder/references/tool-selection.md +107 -0
- package/skills/qingflow-app-builder/references/update-flow.md +186 -0
- package/skills/qingflow-app-builder/references/update-layout.md +68 -0
- package/skills/qingflow-app-builder/references/update-schema.md +72 -0
- package/skills/qingflow-app-builder/references/update-views.md +291 -0
- package/skills/qingflow-app-builder-code-integrations/SKILL.md +137 -0
- package/skills/qingflow-app-builder-code-integrations/agents/openai.yaml +4 -0
- package/skills/qingflow-app-builder-code-integrations/references/code-block.md +66 -0
- package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +77 -0
- package/skills/qingflow-app-user/SKILL.md +2 -1
- package/skills/qingflow-app-user/references/data-gotchas.md +5 -3
- package/skills/qingflow-app-user/references/public-surface-sync.md +6 -3
- package/skills/qingflow-app-user/references/record-patterns.md +14 -4
- package/skills/qingflow-mcp-setup/SKILL.md +111 -0
- package/skills/qingflow-mcp-setup/agents/openai.yaml +4 -0
- package/skills/qingflow-mcp-setup/references/claude-desktop.md +34 -0
- package/skills/qingflow-mcp-setup/references/environments.md +61 -0
- package/skills/qingflow-mcp-setup/references/generic-stdio.md +31 -0
- package/skills/qingflow-mcp-setup/scripts/check_local_server.sh +38 -0
- package/skills/qingflow-record-analysis/SKILL.md +94 -186
- package/skills/qingflow-record-analysis/agents/openai.yaml +2 -2
- package/skills/qingflow-record-analysis/references/analysis-gotchas.md +54 -113
- package/skills/qingflow-record-analysis/references/analysis-patterns.md +95 -134
- package/skills/qingflow-record-analysis/references/business-context.md +74 -0
- package/skills/qingflow-record-analysis/references/confidence-reporting.md +47 -74
- package/skills/qingflow-record-analysis/references/data-access-playbook.md +106 -0
- package/skills/qingflow-record-analysis/references/pandas-recipes.md +172 -0
- package/skills/qingflow-record-analysis/references/report-format.md +76 -0
- package/skills/qingflow-record-insert/SKILL.md +28 -7
- package/skills/qingflow-record-update/SKILL.md +3 -1
- package/skills/qingflow-workflow-builder/SKILL.md +96 -0
- package/skills/qingflow-workflow-builder/manifest.yaml +8 -0
- package/skills/qingflow-workflow-builder/references/01-overview.md +45 -0
- package/skills/qingflow-workflow-builder/references/02-update-mode.md +53 -0
- package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +57 -0
- package/skills/qingflow-workflow-builder/references/04-stage1-business-modeling.md +131 -0
- package/skills/qingflow-workflow-builder/references/05-stage2-members-roles.md +29 -0
- package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +165 -0
- package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +33 -0
- package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +51 -0
- package/skills/qingflow-workflow-builder/references/09-stage6-summary.md +88 -0
- package/skills/qingflow-workflow-builder/references/10-node-config-reference.md +93 -0
- package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +15 -0
- package/skills/qingflow-workflow-builder/scripts/diff_flow_spec.py +275 -0
- package/skills/qingflow-workflow-builder/scripts/validate_flow_spec.py +605 -0
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/backend_client.py +55 -1
- package/src/qingflow_mcp/builder_facade/models.py +532 -48
- package/src/qingflow_mcp/builder_facade/service.py +9194 -2384
- package/src/qingflow_mcp/builder_facade/workflow_spec.py +111 -0
- package/src/qingflow_mcp/cli/commands/app.py +3 -16
- package/src/qingflow_mcp/cli/commands/builder.py +354 -56
- package/src/qingflow_mcp/cli/commands/record.py +112 -6
- package/src/qingflow_mcp/cli/formatters.py +102 -2
- package/src/qingflow_mcp/cli/main.py +245 -3
- package/src/qingflow_mcp/public_surface.py +12 -9
- package/src/qingflow_mcp/response_trim.py +287 -22
- package/src/qingflow_mcp/server.py +29 -20
- package/src/qingflow_mcp/server_app_builder.py +108 -30
- package/src/qingflow_mcp/server_app_user.py +28 -23
- package/src/qingflow_mcp/solution/compiler/__init__.py +1 -3
- package/src/qingflow_mcp/solution/compiler/icon_utils.py +294 -0
- package/src/qingflow_mcp/solution/executor.py +3 -133
- package/src/qingflow_mcp/tools/ai_builder_tools.py +2617 -440
- package/src/qingflow_mcp/tools/app_tools.py +53 -8
- package/src/qingflow_mcp/tools/package_tools.py +16 -2
- package/src/qingflow_mcp/tools/record_tools.py +14283 -9162
- package/src/qingflow_mcp/tools/resource_read_tools.py +3 -0
- package/src/qingflow_mcp/tools/solution_tools.py +30 -2
- package/src/qingflow_mcp/tools/workflow_tools.py +3 -31
- package/src/qingflow_mcp/version.py +110 -0
- package/skills/qingflow-record-analysis/references/dsl-templates.md +0 -93
- package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +0 -173
|
@@ -1,151 +1,112 @@
|
|
|
1
1
|
# Analysis Patterns
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
Use this skill when the user asks for:
|
|
6
|
-
|
|
7
|
-
- 分布
|
|
8
|
-
- 占比
|
|
9
|
-
- 平均值
|
|
10
|
-
- 排名 / top-N
|
|
11
|
-
- 趋势
|
|
12
|
-
- 洞察
|
|
13
|
-
- 最终统计结论
|
|
14
|
-
- 全量范围内的 business summary
|
|
15
|
-
|
|
16
|
-
## Canonical analysis sequence
|
|
3
|
+
## Canonical Sequence
|
|
17
4
|
|
|
18
5
|
1. `app_get`
|
|
19
6
|
2. `record_browse_schema_get`
|
|
20
|
-
3. decide
|
|
21
|
-
4. choose
|
|
7
|
+
3. decide metric intent
|
|
8
|
+
4. choose `record_access.columns / where / order_by`
|
|
22
9
|
5. `record_access`
|
|
23
10
|
6. Python over every returned CSV shard
|
|
24
|
-
7. `record_list` only for sample
|
|
11
|
+
7. optional `record_list` or `record_get` only for sample/detail verification
|
|
25
12
|
|
|
26
|
-
|
|
13
|
+
Metric intent must be one of:
|
|
27
14
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
9. `record_access.scope`
|
|
15
|
+
- `count`
|
|
16
|
+
- `sum`
|
|
17
|
+
- `avg`
|
|
18
|
+
- `distinct_count`
|
|
19
|
+
- ratio with numerator and denominator
|
|
20
|
+
- sorted ranking
|
|
21
|
+
- time trend
|
|
22
|
+
- period comparison
|
|
37
23
|
|
|
38
|
-
|
|
24
|
+
## Distribution
|
|
39
25
|
|
|
40
|
-
|
|
26
|
+
1. Fetch grouping field and filter fields.
|
|
27
|
+
2. Run the field-quality profile for the grouping field.
|
|
28
|
+
3. If the field passes quality gates, group by the readable field-id anchored column such as `项目状态__field_343283094`.
|
|
29
|
+
4. Count rows and calculate share from the sum of counts.
|
|
30
|
+
5. Report top groups plus total row count.
|
|
41
31
|
|
|
42
|
-
|
|
32
|
+
If the grouping field is ambiguous, ask the user to choose from a short candidate list.
|
|
43
33
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
##
|
|
63
|
-
|
|
64
|
-
1.
|
|
65
|
-
2.
|
|
66
|
-
3.
|
|
67
|
-
4.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
- sort by the count alias
|
|
71
|
-
5. Run `record_access`
|
|
72
|
-
6. Use Python to group the CSV rows
|
|
73
|
-
6. Report:
|
|
74
|
-
- `result.totals.metric_totals`
|
|
75
|
-
- `safe_for_final_conclusion`
|
|
76
|
-
- `completeness.statement_scope`
|
|
77
|
-
- `completeness.warnings`
|
|
78
|
-
7. If grouped rows are truncated, describe the answer as `主要分组` or `已返回分组中`, not `各部门` or `全部`
|
|
79
|
-
|
|
80
|
-
## penetration / conversion / share-of-total pattern
|
|
81
|
-
|
|
82
|
-
1. Run `record_browse_schema_get`
|
|
83
|
-
2. Write down the business definition in plain language:
|
|
84
|
-
- numerator
|
|
85
|
-
- denominator
|
|
86
|
-
- grouping dimension, if any
|
|
87
|
-
3. Build separate `record_access` requests when numerator and denominator are not the same filtered population
|
|
88
|
-
4. Query the numerator first
|
|
89
|
-
5. Query the denominator second
|
|
90
|
-
6. Only compute the ratio in Python after both source results are complete and use compatible scopes
|
|
91
|
-
7. If the denominator is missing, do not call the output `渗透率`, `转化率`, `占比`, or `%`
|
|
92
|
-
|
|
93
|
-
## Average / ranking pattern
|
|
94
|
-
|
|
95
|
-
1. Run `record_browse_schema_get`
|
|
96
|
-
2. Choose one dimension field and one numeric metric field
|
|
97
|
-
3. Fetch the dimension and numeric metric fields with `record_access`
|
|
98
|
-
4. Use Python for grouped `count/sum/avg/min/max`
|
|
99
|
-
5. If the answer uses ranking language, make the ranking come from structured sorted results
|
|
100
|
-
6. Prefer the structured `ranking` block when it exists instead of inferring order from loose text
|
|
101
|
-
7. Use list mode only to inspect examples after the aggregate result is understood
|
|
102
|
-
|
|
103
|
-
## Trend pattern
|
|
104
|
-
|
|
105
|
-
1. Run `record_browse_schema_get`
|
|
106
|
-
2. Choose a date/time field from `suggested_time_fields`
|
|
107
|
-
3. Fetch the date/time field and needed metric fields with `record_access`
|
|
108
|
-
4. Use Python to bucket by day/week/month/quarter/year
|
|
109
|
-
5. Treat the result as final only if `safe_for_final_conclusion=true`
|
|
110
|
-
6. If the user asked for a relative time phrase such as `最近一个完整自然月`, translate it into an explicit legal date range before building the DSL
|
|
111
|
-
|
|
112
|
-
## Sample inspection pattern
|
|
113
|
-
|
|
114
|
-
Only use `record_list` after schema/access when you need:
|
|
115
|
-
|
|
116
|
-
- example rows
|
|
117
|
-
- spot checks
|
|
118
|
-
- representative samples
|
|
119
|
-
- manual inspection of records behind an aggregate bucket
|
|
120
|
-
|
|
121
|
-
Never use list mode alone to justify final averages, shares, rankings, or regional distribution claims.
|
|
122
|
-
|
|
123
|
-
## Statement-to-query discipline
|
|
124
|
-
|
|
125
|
-
- If you want to say `单量低` or `volume low`, query `count`
|
|
126
|
-
- If you want to say `金额高`, query `sum`
|
|
127
|
-
- If you want to say `客单价高`, query `avg` or trusted `sum + count`
|
|
128
|
-
- If you want to say `增长` or `下降`, query a time bucket
|
|
129
|
-
- If you want to say `渗透率` or `占比`, query both numerator and denominator
|
|
130
|
-
- If you want to say `各部门` / `全部渠道` / `完整名单`, make sure `completeness.statement_scope=full_population` and `completeness.rows_truncated=false`
|
|
131
|
-
- If you want to say `Top N` or `排名`, make sure the result is explicitly sorted and the conclusion follows that returned order
|
|
132
|
-
- If the task is complex, default to `先结构、后解读`
|
|
133
|
-
|
|
134
|
-
## Ambiguous field recovery
|
|
135
|
-
|
|
136
|
-
If the user asks for something like “来源分布” or “类型占比” and the exact field is unclear:
|
|
137
|
-
|
|
138
|
-
1. run `record_browse_schema_get`
|
|
139
|
-
2. inspect titles, aliases, and suggested fields
|
|
140
|
-
3. if one candidate is clearly dominant, proceed
|
|
141
|
-
4. if multiple candidates are still plausible, ask the user to confirm which field they want
|
|
34
|
+
## Dimension Selection
|
|
35
|
+
|
|
36
|
+
When the user asks for a semantic bucket such as `板块`, `模块`, `业务线`, or `来源`, inspect candidate fields and choose the most reliable one:
|
|
37
|
+
|
|
38
|
+
1. Match schema titles to the user's wording.
|
|
39
|
+
2. Fetch candidate fields together if they are cheap.
|
|
40
|
+
3. Profile `blank_rate`, period coverage, and distinct count.
|
|
41
|
+
4. Prefer the candidate with clear semantics and usable coverage.
|
|
42
|
+
5. If the literal field is sparse, downgrade it to `已填写样本观察` and use the nearest reliable fallback for the main conclusion.
|
|
43
|
+
|
|
44
|
+
Example: if `缺陷所属模块` is mostly empty but `缺陷所属平台` and `所属产品` are complete, use platform/product for the main conclusion and state that module-level analysis is limited.
|
|
45
|
+
|
|
46
|
+
Quality gates:
|
|
47
|
+
|
|
48
|
+
- Overall `blank_rate > 0.4`: not a primary conclusion dimension.
|
|
49
|
+
- Any compared period `blank_rate > 0.8`: not valid for period comparison.
|
|
50
|
+
- High-cardinality description/id fields are not dimensions unless the user explicitly asks for record-level ranking.
|
|
51
|
+
|
|
52
|
+
## Ratio / Conversion / Penetration
|
|
53
|
+
|
|
54
|
+
1. Define numerator and denominator in plain language.
|
|
55
|
+
2. Fetch both populations with compatible scope.
|
|
56
|
+
3. Compute ratio in Python.
|
|
57
|
+
4. Report `numerator / denominator = percentage`.
|
|
58
|
+
|
|
59
|
+
If denominator is missing or scope differs, do not call the result a rate.
|
|
142
60
|
|
|
143
|
-
|
|
61
|
+
## Average / Sum
|
|
144
62
|
|
|
145
|
-
|
|
63
|
+
1. Fetch grouping field and numeric metric field.
|
|
64
|
+
2. Convert the metric column with `pd.to_numeric(errors="coerce")`.
|
|
65
|
+
3. Report count, sum, and average together when useful.
|
|
66
|
+
4. State how blanks/non-numeric values were handled if material.
|
|
146
67
|
|
|
147
|
-
|
|
68
|
+
## Ranking
|
|
69
|
+
|
|
70
|
+
1. Build the metric in Python.
|
|
71
|
+
2. Sort explicitly.
|
|
72
|
+
3. Report Top N with metric values.
|
|
73
|
+
4. Do not infer ranking from unsorted sample rows.
|
|
74
|
+
|
|
75
|
+
## Trend
|
|
76
|
+
|
|
77
|
+
1. Choose a date/time field from `suggested_time_fields`.
|
|
78
|
+
2. Convert relative phrases into exact date ranges.
|
|
79
|
+
3. Fetch the date field and metrics.
|
|
80
|
+
4. Bucket in pandas by day/week/month/quarter/year.
|
|
81
|
+
5. Report both absolute values and changes.
|
|
82
|
+
|
|
83
|
+
## Same-Period Comparison
|
|
84
|
+
|
|
85
|
+
For `今年5月 vs 去年5月`:
|
|
86
|
+
|
|
87
|
+
1. Use the same date field for both periods.
|
|
88
|
+
2. Fetch the full combined date range or two separate compatible ranges.
|
|
89
|
+
3. Apply identical business filters.
|
|
90
|
+
4. Compute absolute delta and percentage delta.
|
|
91
|
+
5. State both periods explicitly.
|
|
92
|
+
|
|
93
|
+
## Sample Inspection
|
|
94
|
+
|
|
95
|
+
Use `record_list` only after the aggregate result is complete, and only for:
|
|
96
|
+
|
|
97
|
+
- representative examples
|
|
98
|
+
- checking surprising categories
|
|
99
|
+
- manually inspecting records behind a bucket
|
|
100
|
+
|
|
101
|
+
Never use `record_list` alone for final averages, shares, rankings, trends, or distributions.
|
|
102
|
+
|
|
103
|
+
## Ambiguous Field Recovery
|
|
104
|
+
|
|
105
|
+
If the exact field is unclear:
|
|
106
|
+
|
|
107
|
+
1. inspect `record_browse_schema_get.fields`
|
|
108
|
+
2. use titles and suggested fields
|
|
109
|
+
3. if one candidate is clearly dominant, proceed
|
|
110
|
+
4. otherwise ask the user to confirm
|
|
148
111
|
|
|
149
|
-
|
|
150
|
-
2. state which parts are still unresolved
|
|
151
|
-
3. do not present the answer as fully complete
|
|
112
|
+
Do not retry tools with guessed field names.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Business Context
|
|
2
|
+
|
|
3
|
+
Use this when analysis depends on organization, aliases, ownership, stage semantics, or user-provided business definitions.
|
|
4
|
+
|
|
5
|
+
## When To Check Context
|
|
6
|
+
|
|
7
|
+
Check for business context when the request mentions:
|
|
8
|
+
|
|
9
|
+
- department / team / group / region
|
|
10
|
+
- owner / assignee / sales rep / partner
|
|
11
|
+
- stage / status / funnel / conversion
|
|
12
|
+
- product line / business line
|
|
13
|
+
- same-period comparison
|
|
14
|
+
- "北斗部门", "SMB", "伙伴", or any named internal scope
|
|
15
|
+
|
|
16
|
+
## Mapping Rules
|
|
17
|
+
|
|
18
|
+
Use explicit mappings in this order:
|
|
19
|
+
|
|
20
|
+
1. the user's message in the current thread
|
|
21
|
+
2. attached or local business context files
|
|
22
|
+
3. schema-visible fields and sample records
|
|
23
|
+
4. short clarification to the user
|
|
24
|
+
|
|
25
|
+
Do not infer hidden org hierarchy from memory. If the mapping changes the denominator or grouping, state it in the final answer.
|
|
26
|
+
|
|
27
|
+
Example:
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
dept_map = {
|
|
31
|
+
"烈焰组": "北斗部门",
|
|
32
|
+
"飓风组": "北斗部门",
|
|
33
|
+
}
|
|
34
|
+
df["部门口径"] = df["field_40"].replace(dept_map)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Final wording:
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
部门口径:将「烈焰组」「飓风组」合并计入「北斗部门」。
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Ratio Definitions
|
|
44
|
+
|
|
45
|
+
Before computing rates, define:
|
|
46
|
+
|
|
47
|
+
- numerator
|
|
48
|
+
- denominator
|
|
49
|
+
- time range
|
|
50
|
+
- grouping dimension
|
|
51
|
+
- exclusions
|
|
52
|
+
|
|
53
|
+
If any part is ambiguous, ask. Do not rename a count as a rate.
|
|
54
|
+
|
|
55
|
+
## Time Scope
|
|
56
|
+
|
|
57
|
+
Normalize relative dates to exact dates before calling `record_access`.
|
|
58
|
+
|
|
59
|
+
Examples:
|
|
60
|
+
|
|
61
|
+
- `今年5月` -> `2026-05-01` to `2026-05-31` when current year is 2026
|
|
62
|
+
- `去年同期` -> same month range in the previous year
|
|
63
|
+
- `最近一个完整自然月` -> previous calendar month, not the last 30 days
|
|
64
|
+
|
|
65
|
+
## Cross-App Reconciliation
|
|
66
|
+
|
|
67
|
+
If the analysis needs multiple apps:
|
|
68
|
+
|
|
69
|
+
1. run the standard sequence per app
|
|
70
|
+
2. keep each dataset's scope and completeness separately
|
|
71
|
+
3. join in Python only on explicit ids or trusted business keys
|
|
72
|
+
4. disclose join keys and unmatched records
|
|
73
|
+
|
|
74
|
+
If no reliable key exists, report the gap instead of forcing a join.
|
|
@@ -1,96 +1,69 @@
|
|
|
1
1
|
# Confidence Reporting
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Full Conclusion Gate
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
1. `全量可信结论`
|
|
8
|
-
2. `样本观察`
|
|
9
|
-
3. `待验证假设`
|
|
10
|
-
|
|
11
|
-
## Full conclusion gate
|
|
12
|
-
|
|
13
|
-
Only write `全量可信结论` when:
|
|
5
|
+
Use `全量可信结论` only when:
|
|
14
6
|
|
|
15
7
|
- `record_browse_schema_get` was used
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
- `
|
|
19
|
-
-
|
|
20
|
-
-
|
|
8
|
+
- data came from `record_access`
|
|
9
|
+
- all returned CSV shards were read in Python
|
|
10
|
+
- `record_access.complete=true`
|
|
11
|
+
- `record_access.truncated=false`
|
|
12
|
+
- `record_access.safe_for_final_conclusion=true`
|
|
13
|
+
- metric definitions are complete
|
|
14
|
+
- denominator exists for every ratio
|
|
15
|
+
- time fields and date ranges are explicit
|
|
16
|
+
- primary grouping dimensions pass field-quality gates
|
|
21
17
|
|
|
22
|
-
##
|
|
18
|
+
## Initial Observation Gate
|
|
23
19
|
|
|
24
|
-
|
|
20
|
+
Use `初步观察` when:
|
|
25
21
|
|
|
26
|
-
- it came from `record_list`
|
|
27
|
-
- the tool reports `row_cap_hit`
|
|
28
|
-
- the tool reports `sample_only`
|
|
29
|
-
- the result is compact/capped and not complete
|
|
30
22
|
- `record_access.status=needs_scope`
|
|
31
23
|
- `record_access.status=partial`
|
|
32
|
-
- `record_access.complete=false`
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
## Anti-mixing rule
|
|
39
|
-
|
|
40
|
-
Do not combine:
|
|
41
|
-
|
|
42
|
-
- full totals from `record_analyze`
|
|
43
|
-
- full CSV-derived conclusions from `record_access`
|
|
44
|
-
- sample-only details from `record_list`
|
|
45
|
-
|
|
46
|
-
into one sentence like “基于全部数据分析...”.
|
|
47
|
-
|
|
48
|
-
Instead:
|
|
49
|
-
|
|
50
|
-
- full totals and distributions go into `全量可信结论`
|
|
51
|
-
- illustrative rows go into `样本观察`
|
|
52
|
-
|
|
53
|
-
## Semantic gate
|
|
54
|
-
|
|
55
|
-
Even when `safe_for_final_conclusion=true`, do not overstate the answer if:
|
|
56
|
-
|
|
57
|
-
- the metric definition is incomplete
|
|
58
|
-
- the denominator was not queried
|
|
59
|
-
- the conclusion mentions trend but no time bucket was queried
|
|
60
|
-
- the conclusion mentions单量/volume but no `count` metric was queried
|
|
61
|
-
- the conclusion depends on a derived metric the DSL cannot natively express
|
|
62
|
-
- `completeness.statement_scope=returned_groups_only`
|
|
63
|
-
- `completeness.rows_truncated=true`
|
|
64
|
-
|
|
65
|
-
## Grouped enumeration gate
|
|
24
|
+
- `record_access.complete=false`
|
|
25
|
+
- `record_access.truncated=true`
|
|
26
|
+
- `record_access.safe_for_final_conclusion=false`
|
|
27
|
+
- evidence came from `record_list`
|
|
28
|
+
- scope or saved view filter is unverified
|
|
66
29
|
|
|
67
|
-
|
|
30
|
+
## Anti-Mixing Rule
|
|
68
31
|
|
|
69
|
-
|
|
70
|
-
- use `已返回分组中`, `主要分组`, or `前 N 个分组`
|
|
71
|
-
- keep full-population statements only for metrics that still cover the full analyzed population
|
|
32
|
+
Do not combine full CSV-derived totals and sample-only rows in one sentence.
|
|
72
33
|
|
|
73
|
-
|
|
34
|
+
Correct split:
|
|
74
35
|
|
|
75
|
-
|
|
36
|
+
- full totals/distributions: `全量可信结论`
|
|
37
|
+
- illustrative examples: `样本观察`
|
|
76
38
|
|
|
77
|
-
|
|
78
|
-
- explicitly disclose which parts are not yet complete
|
|
79
|
-
- do not collapse the answer into one all-clear conclusion
|
|
39
|
+
## Semantic Gate
|
|
80
40
|
|
|
81
|
-
|
|
41
|
+
Even with `safe_for_final_conclusion=true`, downgrade if:
|
|
82
42
|
|
|
83
|
-
|
|
43
|
+
- metric definition is incomplete
|
|
44
|
+
- denominator was not queried
|
|
45
|
+
- conclusion mentions trend but no time field was used
|
|
46
|
+
- conclusion mentions volume but no count was computed
|
|
47
|
+
- grouping depends on unconfirmed business aliases
|
|
48
|
+
- custom view scope is not verified
|
|
49
|
+
- primary grouping field has high missingness or poor period coverage
|
|
84
50
|
|
|
85
|
-
|
|
86
|
-
- `safe_for_final_conclusion=true`
|
|
87
|
-
- 这里写最终业务结论
|
|
51
|
+
## Partial Disclosure
|
|
88
52
|
|
|
89
|
-
|
|
53
|
+
If only part of the user request is complete:
|
|
90
54
|
|
|
91
|
-
-
|
|
92
|
-
-
|
|
55
|
+
- say which parts are complete
|
|
56
|
+
- say which parts are unresolved
|
|
57
|
+
- do not collapse into one all-clear conclusion
|
|
93
58
|
|
|
94
|
-
|
|
59
|
+
## Compact Disclosure Template
|
|
95
60
|
|
|
96
|
-
|
|
61
|
+
```text
|
|
62
|
+
可信度:全量可信 / 初步观察
|
|
63
|
+
数据完整性:complete=..., truncated=..., safe_for_final_conclusion=...
|
|
64
|
+
字段质量:primary dimension blank_rate=..., period coverage=...
|
|
65
|
+
取数字段:...
|
|
66
|
+
时间范围:...
|
|
67
|
+
业务口径:...
|
|
68
|
+
限制:...
|
|
69
|
+
```
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Data Access Playbook
|
|
2
|
+
|
|
3
|
+
This file is the operational state machine for `record_access`.
|
|
4
|
+
|
|
5
|
+
## Required Sequence
|
|
6
|
+
|
|
7
|
+
1. `app_get`
|
|
8
|
+
2. choose `view_id` from `accessible_views`
|
|
9
|
+
3. `record_browse_schema_get(app_key, view_id)`
|
|
10
|
+
4. build `record_access.columns / where / order_by` from field ids
|
|
11
|
+
5. run `record_access`
|
|
12
|
+
6. read every CSV shard with Python
|
|
13
|
+
|
|
14
|
+
Do not call `record_access` with field titles, guessed ids, page controls, row limits, or profile.
|
|
15
|
+
CSV columns are readable and field-id anchored, for example `项目状态__field_343283094`; do not look for extra `schema.json` or README files.
|
|
16
|
+
|
|
17
|
+
## Finding `record_access`
|
|
18
|
+
|
|
19
|
+
`record_access` can be available as an MCP tool or as a CLI subcommand. If the MCP surface does not show a top-level `record_access` tool, look under the Qingflow CLI record group before choosing any other path:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
qingflow record --help
|
|
23
|
+
qingflow record access --help
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The CLI call is:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
qingflow record access \
|
|
30
|
+
--app-key APP_KEY \
|
|
31
|
+
--view-id VIEW_ID \
|
|
32
|
+
--columns-file columns.json \
|
|
33
|
+
--where-file where.json \
|
|
34
|
+
--order-by-file order_by.json \
|
|
35
|
+
--json
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
This is the same analysis path: it writes CSV shards and metadata for Python. Do not replace it with list browsing, export, QingBI, or aggregate helpers just because the MCP tool is not visible.
|
|
39
|
+
|
|
40
|
+
## Request Patterns
|
|
41
|
+
|
|
42
|
+
### Count or distribution
|
|
43
|
+
|
|
44
|
+
Fetch the grouping field and any time/business filter field.
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"app_key": "APP_KEY",
|
|
49
|
+
"view_id": "system:all",
|
|
50
|
+
"columns": [{ "field_id": 18 }],
|
|
51
|
+
"where": [{ "field_id": 2, "op": "between", "value": ["2026-05-01", "2026-05-31"] }],
|
|
52
|
+
"order_by": []
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Trend
|
|
57
|
+
|
|
58
|
+
Fetch the date/time field plus metric fields.
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{
|
|
62
|
+
"app_key": "APP_KEY",
|
|
63
|
+
"view_id": "system:all",
|
|
64
|
+
"columns": [{ "field_id": 2 }, { "field_id": 18 }],
|
|
65
|
+
"where": [{ "field_id": 2, "op": "between", "value": ["2026-01-01", "2026-12-31"] }],
|
|
66
|
+
"order_by": [{ "field_id": 2, "direction": "asc" }]
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Ratio
|
|
71
|
+
|
|
72
|
+
If numerator and denominator use different filters, run separate `record_access` calls. Only compute the ratio after both source datasets are complete and compatible.
|
|
73
|
+
|
|
74
|
+
## Status Decisions
|
|
75
|
+
|
|
76
|
+
| Status | Meaning | Agent action |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| `success` + `safe_for_final_conclusion=true` | Full retrieved scope is reliable | Give final conclusion |
|
|
79
|
+
| `needs_scope` | Tool refused large unbounded scan, no CSV | Ask for scope or retry with explicit period/business filter |
|
|
80
|
+
| `partial` | Some CSV files written, but not full data | Give only subset observation |
|
|
81
|
+
| `complete=false` | Not all requested data is available | Do not present full-population conclusion |
|
|
82
|
+
| `truncated=true` | Tool had to stop before full scope | Disclose and narrow scope |
|
|
83
|
+
|
|
84
|
+
## `needs_scope` Recovery
|
|
85
|
+
|
|
86
|
+
Use the returned `scope` object:
|
|
87
|
+
|
|
88
|
+
- `reported_total`: explain why scope is needed
|
|
89
|
+
- `suggested_time_fields`: choose likely date fields
|
|
90
|
+
- `recommended_where_examples`: reuse if they match the user request
|
|
91
|
+
|
|
92
|
+
If the user already provided a concrete month/quarter/year, retry with that period. If no business boundary is available, ask one short clarification.
|
|
93
|
+
|
|
94
|
+
## `partial` Recovery
|
|
95
|
+
|
|
96
|
+
You may read the files, but must label output as partial:
|
|
97
|
+
|
|
98
|
+
- say which files/rows were analyzed
|
|
99
|
+
- do not use `全部`, `所有`, `整体`, or `全量`
|
|
100
|
+
- suggest narrowing time or business scope before final conclusion
|
|
101
|
+
|
|
102
|
+
## View Scope
|
|
103
|
+
|
|
104
|
+
For custom views, the result is scoped to that saved view. If `verification.view_filter_verified=false`, disclose that the saved-filter scope could not be fully verified.
|
|
105
|
+
|
|
106
|
+
For board/gantt views, switch to a table-style view or `system:all` plus explicit filters.
|