@qingflow-tech/qingflow-app-user-mcp 1.0.3 → 1.0.5
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 +2 -2
- package/package.json +1 -1
- package/pyproject.toml +2 -1
- package/skills/qingflow-app-user/SKILL.md +2 -1
- package/skills/qingflow-app-user/references/data-gotchas.md +5 -2
- package/skills/qingflow-app-user/references/public-surface-sync.md +5 -3
- package/skills/qingflow-app-user/references/record-patterns.md +9 -0
- package/skills/qingflow-record-analysis/SKILL.md +103 -166
- package/skills/qingflow-record-analysis/agents/openai.yaml +2 -2
- package/skills/qingflow-record-analysis/references/analysis-gotchas.md +56 -110
- package/skills/qingflow-record-analysis/references/analysis-patterns.md +106 -119
- package/skills/qingflow-record-analysis/references/business-context.md +74 -0
- package/skills/qingflow-record-analysis/references/confidence-reporting.md +49 -72
- 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 +2 -2
- package/skills/qingflow-record-update/SKILL.md +1 -1
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/backend_client.py +164 -1
- package/src/qingflow_mcp/builder_facade/button_style_catalog.py +282 -0
- package/src/qingflow_mcp/builder_facade/models.py +44 -5
- package/src/qingflow_mcp/builder_facade/service.py +21 -8
- package/src/qingflow_mcp/cli/commands/__init__.py +2 -1
- package/src/qingflow_mcp/cli/commands/app.py +47 -1
- package/src/qingflow_mcp/cli/commands/builder.py +7 -0
- package/src/qingflow_mcp/cli/commands/exports.py +111 -0
- package/src/qingflow_mcp/cli/commands/record.py +44 -5
- package/src/qingflow_mcp/cli/commands/task.py +644 -22
- package/src/qingflow_mcp/cli/commands/workspace.py +64 -2
- package/src/qingflow_mcp/cli/context.py +3 -0
- package/src/qingflow_mcp/cli/formatters.py +240 -5
- package/src/qingflow_mcp/cli/interaction.py +72 -0
- package/src/qingflow_mcp/cli/main.py +5 -0
- package/src/qingflow_mcp/cli/terminal_ui.py +218 -0
- package/src/qingflow_mcp/errors.py +2 -2
- package/src/qingflow_mcp/export_store.py +14 -0
- package/src/qingflow_mcp/public_surface.py +7 -1
- package/src/qingflow_mcp/response_trim.py +188 -10
- package/src/qingflow_mcp/server.py +37 -9
- package/src/qingflow_mcp/server_app_builder.py +4 -0
- package/src/qingflow_mcp/server_app_user.py +115 -10
- package/src/qingflow_mcp/session_store.py +57 -6
- package/src/qingflow_mcp/tools/ai_builder_tools.py +59 -16
- package/src/qingflow_mcp/tools/auth_tools.py +26 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +0 -2
- package/src/qingflow_mcp/tools/export_tools.py +1565 -0
- package/src/qingflow_mcp/tools/import_tools.py +42 -2
- package/src/qingflow_mcp/tools/record_tools.py +12793 -8612
- package/src/qingflow_mcp/tools/resource_read_tools.py +40 -1
- package/src/qingflow_mcp/tools/task_context_tools.py +26 -8
- package/skills/qingflow-record-analysis/references/dsl-templates.md +0 -93
|
@@ -1,145 +1,91 @@
|
|
|
1
1
|
# Analysis Gotchas
|
|
2
2
|
|
|
3
|
-
## Do
|
|
3
|
+
## Do Not Skip Schema
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Correct path:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
1. `app_get`
|
|
8
|
+
2. `record_browse_schema_get`
|
|
9
|
+
3. `record_access`
|
|
10
|
+
4. Python
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
2. inspect the schema and choose fields
|
|
11
|
-
3. build one or more small DSLs
|
|
12
|
-
4. run `record_analyze`
|
|
12
|
+
`record_browse_schema_get` returns readable fields for the selected view. Missing fields are permission or view-scope boundaries, not invitations to guess hidden ids.
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
## Do Not Use Export For Analysis
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Export tools are for user-requested files. Analysis uses `record_access` because it returns structured completeness and compact field metadata.
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
## Do Not Treat `record_list` As Full Data
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
- `上个月` -> convert to a concrete month range
|
|
22
|
-
- `最近30天` -> convert to exact start/end dates
|
|
20
|
+
`record_list` is sample/browse only. It can be capped and should not justify:
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
- average
|
|
23
|
+
- share
|
|
24
|
+
- ranking
|
|
25
|
+
- trend
|
|
26
|
+
- regional distribution
|
|
27
|
+
- "all data" insights
|
|
25
28
|
|
|
26
|
-
## Do
|
|
29
|
+
## Do Not Control Paging
|
|
27
30
|
|
|
28
|
-
`
|
|
31
|
+
`record_access` owns paging internally.
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
- `row_cap_hit=true`
|
|
32
|
-
- `sample_only=true`
|
|
33
|
+
Do not invent:
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
- `page`
|
|
36
|
+
- `page_size`
|
|
37
|
+
- `limit`
|
|
38
|
+
- `requested_pages`
|
|
39
|
+
- `scan_max_pages`
|
|
40
|
+
- `max_rows`
|
|
41
|
+
- `timeout`
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
## Do Not Print Raw CSV
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
- 占比
|
|
40
|
-
- 排名
|
|
41
|
-
- 趋势
|
|
42
|
-
- 地域分布
|
|
43
|
-
- “基于全部数据”的 business insight
|
|
45
|
+
Read CSV files with pandas. Summarize computed results, not raw rows.
|
|
44
46
|
|
|
45
|
-
## Do
|
|
47
|
+
## Do Not Rename Source Files
|
|
46
48
|
|
|
47
|
-
|
|
49
|
+
CSV columns are directly readable and field-id anchored: `record_id`, `<字段标题>__field_<id>`. Use those columns directly in pandas.
|
|
48
50
|
|
|
49
|
-
|
|
51
|
+
## Do Not Trust Sparse Dimensions
|
|
50
52
|
|
|
51
|
-
-
|
|
52
|
-
- `样本观察`
|
|
53
|
+
Before final grouping, run a field-quality profile. If the selected field is mostly blank, say so and downgrade the claim.
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
Rules of thumb:
|
|
55
56
|
|
|
56
|
-
|
|
57
|
+
- Overall blank rate above 40%: not a primary conclusion dimension.
|
|
58
|
+
- Any compared period blank rate above 80%: do not use that field for period comparison.
|
|
59
|
+
- A sparse field can support only `已填写样本观察`.
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
- do not say `所有分组`
|
|
60
|
-
- do not say `完整名单`
|
|
61
|
+
If the user asks for a semantic field such as `板块`, test nearby candidates like product, platform, module, stage, source, owner, or department before concluding.
|
|
61
62
|
|
|
62
|
-
|
|
63
|
+
## Do Not Hide Incomplete Access
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
- keep the wording inside the returned group scope
|
|
65
|
+
If `needs_scope`, no CSV exists. Ask for a time/business scope.
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
If `partial`, use only subset wording and avoid full-population claims.
|
|
68
68
|
|
|
69
|
-
If
|
|
69
|
+
If field meaning is ambiguous, ask the user to confirm from a short list.
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
- do not guess ids
|
|
73
|
-
- do not switch from one read tool to another by trial and error
|
|
74
|
-
- do not keep retrying different guessed field names in a loop
|
|
71
|
+
## Do Not Guess Metrics
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
Before fetching data, decide whether the request needs count, sum, average, distinct count, ratio, ranking, trend, or comparison.
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
2. if several plausible candidates remain, ask the user to confirm from a short list
|
|
80
|
-
3. build the DSL only after the field is clear
|
|
75
|
+
## Do Not Call A Ratio Without Denominator
|
|
81
76
|
|
|
82
|
-
|
|
77
|
+
For penetration, conversion, or share:
|
|
83
78
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
## Do not try to control paging manually
|
|
90
|
-
|
|
91
|
-
`record_analyze` hides paging and scan budget on purpose.
|
|
92
|
-
|
|
93
|
-
- Do not invent `page_size`
|
|
94
|
-
- Do not invent `requested_pages`
|
|
95
|
-
- Do not invent `scan_max_pages`
|
|
96
|
-
- Do not invent `auto_expand_pages`
|
|
97
|
-
|
|
98
|
-
When the result is incomplete:
|
|
99
|
-
|
|
100
|
-
1. narrow the scope with views or filters
|
|
101
|
-
2. reduce the analysis problem into smaller DSLs
|
|
102
|
-
3. keep the answer at `初步观察` or `部分结果` if completeness is still not enough
|
|
103
|
-
|
|
104
|
-
## Do not guess metric semantics from loose business wording
|
|
105
|
-
|
|
106
|
-
Before building the DSL, first decide whether the question needs:
|
|
107
|
-
|
|
108
|
-
- `count`
|
|
109
|
-
- `sum`
|
|
110
|
-
- `avg`
|
|
111
|
-
- `distinct_count`
|
|
112
|
-
- a ratio with numerator + denominator
|
|
113
|
-
- a sorted ranking result
|
|
114
|
-
|
|
115
|
-
Do not jump straight from words like `数量`, `人数`, `单量`, or `金额` to one assumed metric.
|
|
116
|
-
|
|
117
|
-
## Do not hide partial completion
|
|
118
|
-
|
|
119
|
-
If the user asked for several outputs and only part of them is stable:
|
|
120
|
-
|
|
121
|
-
- say which parts are complete
|
|
122
|
-
- say which parts are still unresolved
|
|
123
|
-
- do not present the answer as fully finished
|
|
124
|
-
|
|
125
|
-
## Do not send unsupported formula or div-style metrics into `record_analyze`.
|
|
126
|
-
|
|
127
|
-
Examples to avoid:
|
|
128
|
-
|
|
129
|
-
- `{"op":"div", ...}`
|
|
130
|
-
- metric items with `formula`, `expr`, `numerator`, or `denominator`
|
|
131
|
-
|
|
132
|
-
Correct recovery:
|
|
133
|
-
|
|
134
|
-
1. query the source metrics with separate DSLs
|
|
135
|
-
2. confirm both sides are complete and compatible
|
|
136
|
-
3. compute the derived ratio outside MCP in the reasoning layer
|
|
79
|
+
1. define numerator
|
|
80
|
+
2. define denominator
|
|
81
|
+
3. query compatible source data
|
|
82
|
+
4. compute in Python
|
|
83
|
+
5. report numerator and denominator
|
|
137
84
|
|
|
138
|
-
##
|
|
85
|
+
## Normalize Relative Dates
|
|
139
86
|
|
|
140
|
-
|
|
87
|
+
Convert relative phrases into exact ranges before `record_access`.
|
|
141
88
|
|
|
142
|
-
1
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
4. only then compute and report the ratio
|
|
89
|
+
- `今年5月` -> exact May 1 to May 31 in the current year
|
|
90
|
+
- `去年同期` -> same date range in previous year
|
|
91
|
+
- `最近30天` -> exact rolling start/end dates
|
|
@@ -1,125 +1,112 @@
|
|
|
1
1
|
# Analysis Patterns
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
1.
|
|
27
|
-
2.
|
|
28
|
-
3.
|
|
29
|
-
4.
|
|
30
|
-
5.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
##
|
|
53
|
-
|
|
54
|
-
1.
|
|
55
|
-
2.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
- grouping dimension, if any
|
|
59
|
-
3. Build separate DSLs when numerator and denominator are not the same filtered population
|
|
60
|
-
4. Query the numerator first
|
|
61
|
-
5. Query the denominator second
|
|
62
|
-
6. Only compute the ratio outside MCP after both source results are complete and use compatible scopes
|
|
63
|
-
7. If the denominator is missing, do not call the output `渗透率`, `转化率`, `占比`, or `%`
|
|
64
|
-
|
|
65
|
-
## Average / ranking pattern
|
|
66
|
-
|
|
67
|
-
1. Run `record_browse_schema_get`
|
|
68
|
-
2. Choose one dimension field and one numeric metric field
|
|
69
|
-
3. Build a DSL with:
|
|
70
|
-
- `dimensions=[...]`
|
|
71
|
-
- `metrics=[count,sum]` or `metrics=[count,avg,min,max]`
|
|
72
|
-
4. Run `record_analyze`
|
|
73
|
-
5. If the answer uses ranking language, make the ranking come from structured sorted results
|
|
74
|
-
6. Prefer the structured `ranking` block when it exists instead of inferring order from loose text
|
|
75
|
-
7. Use list mode only to inspect examples after the aggregate result is understood
|
|
76
|
-
|
|
77
|
-
## Trend pattern
|
|
78
|
-
|
|
79
|
-
1. Run `record_browse_schema_get`
|
|
80
|
-
2. Choose a date/time field from `suggested_time_fields`
|
|
81
|
-
3. Build a DSL with `bucket=day|week|month|quarter|year`
|
|
82
|
-
4. Run `record_analyze`
|
|
83
|
-
5. Treat the result as final only if `safe_for_final_conclusion=true`
|
|
84
|
-
6. If the user asked for a relative time phrase such as `最近一个完整自然月`, translate it into an explicit legal date range before building the DSL
|
|
85
|
-
|
|
86
|
-
## Sample inspection pattern
|
|
87
|
-
|
|
88
|
-
Only use `record_list` after schema/analyze when you need:
|
|
89
|
-
|
|
90
|
-
- example rows
|
|
91
|
-
- spot checks
|
|
92
|
-
- representative samples
|
|
93
|
-
- manual inspection of records behind an aggregate bucket
|
|
94
|
-
|
|
95
|
-
Never use list mode alone to justify final averages, shares, rankings, or regional distribution claims.
|
|
96
|
-
|
|
97
|
-
## Statement-to-query discipline
|
|
98
|
-
|
|
99
|
-
- If you want to say `单量低` or `volume low`, query `count`
|
|
100
|
-
- If you want to say `金额高`, query `sum`
|
|
101
|
-
- If you want to say `客单价高`, query `avg` or trusted `sum + count`
|
|
102
|
-
- If you want to say `增长` or `下降`, query a time bucket
|
|
103
|
-
- If you want to say `渗透率` or `占比`, query both numerator and denominator
|
|
104
|
-
- If you want to say `各部门` / `全部渠道` / `完整名单`, make sure `completeness.statement_scope=full_population` and `completeness.rows_truncated=false`
|
|
105
|
-
- If you want to say `Top N` or `排名`, make sure the result is explicitly sorted and the conclusion follows that returned order
|
|
106
|
-
- If the task is complex, default to `先结构、后解读`
|
|
107
|
-
|
|
108
|
-
## Ambiguous field recovery
|
|
109
|
-
|
|
110
|
-
If the user asks for something like “来源分布” or “类型占比” and the exact field is unclear:
|
|
111
|
-
|
|
112
|
-
1. run `record_browse_schema_get`
|
|
113
|
-
2. inspect titles, aliases, and suggested fields
|
|
114
|
-
3. if one candidate is clearly dominant, proceed
|
|
115
|
-
4. if multiple candidates are still plausible, ask the user to confirm which field they want
|
|
3
|
+
## Canonical Sequence
|
|
4
|
+
|
|
5
|
+
1. `app_get`
|
|
6
|
+
2. `record_browse_schema_get`
|
|
7
|
+
3. decide metric intent
|
|
8
|
+
4. choose `record_access.columns / where / order_by`
|
|
9
|
+
5. `record_access`
|
|
10
|
+
6. Python over every returned CSV shard
|
|
11
|
+
7. optional `record_list` or `record_get` only for sample/detail verification
|
|
12
|
+
|
|
13
|
+
Metric intent must be one of:
|
|
14
|
+
|
|
15
|
+
- `count`
|
|
16
|
+
- `sum`
|
|
17
|
+
- `avg`
|
|
18
|
+
- `distinct_count`
|
|
19
|
+
- ratio with numerator and denominator
|
|
20
|
+
- sorted ranking
|
|
21
|
+
- time trend
|
|
22
|
+
- period comparison
|
|
23
|
+
|
|
24
|
+
## Distribution
|
|
25
|
+
|
|
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.
|
|
31
|
+
|
|
32
|
+
If the grouping field is ambiguous, ask the user to choose from a short candidate list.
|
|
33
|
+
|
|
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`.
|
|
116
58
|
|
|
117
|
-
|
|
59
|
+
If denominator is missing or scope differs, do not call the result a rate.
|
|
118
60
|
|
|
119
|
-
##
|
|
61
|
+
## Average / Sum
|
|
120
62
|
|
|
121
|
-
|
|
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.
|
|
67
|
+
|
|
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
|
|
122
111
|
|
|
123
|
-
|
|
124
|
-
2. state which parts are still unresolved
|
|
125
|
-
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,92 +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
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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
|
-
|
|
31
|
-
## Downgrade rule
|
|
32
|
-
|
|
33
|
-
If `record_browse_schema_get` was not used for an analysis task, downgrade the overall framing to `初步观察` instead of `洞察` or `结论`.
|
|
34
|
-
|
|
35
|
-
## Anti-mixing rule
|
|
36
|
-
|
|
37
|
-
Do not combine:
|
|
38
|
-
|
|
39
|
-
- full totals from `record_analyze`
|
|
40
|
-
- sample-only details from `record_list`
|
|
41
|
-
|
|
42
|
-
into one sentence like “基于全部数据分析...”.
|
|
43
|
-
|
|
44
|
-
Instead:
|
|
45
|
-
|
|
46
|
-
- full totals and distributions go into `全量可信结论`
|
|
47
|
-
- illustrative rows go into `样本观察`
|
|
48
|
-
|
|
49
|
-
## Semantic gate
|
|
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
|
|
50
17
|
|
|
51
|
-
|
|
18
|
+
## Initial Observation Gate
|
|
52
19
|
|
|
53
|
-
|
|
54
|
-
- the denominator was not queried
|
|
55
|
-
- the conclusion mentions trend but no time bucket was queried
|
|
56
|
-
- the conclusion mentions单量/volume but no `count` metric was queried
|
|
57
|
-
- the conclusion depends on a derived metric the DSL cannot natively express
|
|
58
|
-
- `completeness.statement_scope=returned_groups_only`
|
|
59
|
-
- `completeness.rows_truncated=true`
|
|
20
|
+
Use `初步观察` when:
|
|
60
21
|
|
|
61
|
-
|
|
22
|
+
- `record_access.status=needs_scope`
|
|
23
|
+
- `record_access.status=partial`
|
|
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
|
|
62
29
|
|
|
63
|
-
|
|
30
|
+
## Anti-Mixing Rule
|
|
64
31
|
|
|
65
|
-
|
|
66
|
-
- use `已返回分组中`, `主要分组`, or `前 N 个分组`
|
|
67
|
-
- 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.
|
|
68
33
|
|
|
69
|
-
|
|
34
|
+
Correct split:
|
|
70
35
|
|
|
71
|
-
|
|
36
|
+
- full totals/distributions: `全量可信结论`
|
|
37
|
+
- illustrative examples: `样本观察`
|
|
72
38
|
|
|
73
|
-
|
|
74
|
-
- explicitly disclose which parts are not yet complete
|
|
75
|
-
- do not collapse the answer into one all-clear conclusion
|
|
39
|
+
## Semantic Gate
|
|
76
40
|
|
|
77
|
-
|
|
41
|
+
Even with `safe_for_final_conclusion=true`, downgrade if:
|
|
78
42
|
|
|
79
|
-
|
|
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
|
|
80
50
|
|
|
81
|
-
|
|
82
|
-
- `safe_for_final_conclusion=true`
|
|
83
|
-
- 这里写最终业务结论
|
|
51
|
+
## Partial Disclosure
|
|
84
52
|
|
|
85
|
-
|
|
53
|
+
If only part of the user request is complete:
|
|
86
54
|
|
|
87
|
-
-
|
|
88
|
-
-
|
|
55
|
+
- say which parts are complete
|
|
56
|
+
- say which parts are unresolved
|
|
57
|
+
- do not collapse into one all-clear conclusion
|
|
89
58
|
|
|
90
|
-
|
|
59
|
+
## Compact Disclosure Template
|
|
91
60
|
|
|
92
|
-
|
|
61
|
+
```text
|
|
62
|
+
可信度:全量可信 / 初步观察
|
|
63
|
+
数据完整性:complete=..., truncated=..., safe_for_final_conclusion=...
|
|
64
|
+
字段质量:primary dimension blank_rate=..., period coverage=...
|
|
65
|
+
取数字段:...
|
|
66
|
+
时间范围:...
|
|
67
|
+
业务口径:...
|
|
68
|
+
限制:...
|
|
69
|
+
```
|