@josephyan/qingflow-app-user-mcp 1.0.9 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +6 -2
  2. package/npm/bin/qingflow-app-user-mcp.mjs +31 -2
  3. package/npm/lib/runtime.mjs +43 -2
  4. package/package.json +1 -1
  5. package/pyproject.toml +2 -1
  6. package/skills/qingflow-app-builder/SKILL.md +276 -0
  7. package/skills/qingflow-app-builder/agents/openai.yaml +4 -0
  8. package/skills/qingflow-app-builder/references/build-complete-system.md +428 -0
  9. package/skills/qingflow-app-builder/references/build-single-app.md +530 -0
  10. package/skills/qingflow-app-builder/references/create-app.md +149 -0
  11. package/skills/qingflow-app-builder/references/environments.md +63 -0
  12. package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +123 -0
  13. package/skills/qingflow-app-builder/references/gotchas.md +108 -0
  14. package/skills/qingflow-app-builder/references/match-rules.md +114 -0
  15. package/skills/qingflow-app-builder/references/public-surface-sync.md +75 -0
  16. package/skills/qingflow-app-builder/references/solution-playbooks.md +52 -0
  17. package/skills/qingflow-app-builder/references/tool-selection.md +107 -0
  18. package/skills/qingflow-app-builder/references/update-flow.md +186 -0
  19. package/skills/qingflow-app-builder/references/update-layout.md +68 -0
  20. package/skills/qingflow-app-builder/references/update-schema.md +72 -0
  21. package/skills/qingflow-app-builder/references/update-views.md +291 -0
  22. package/skills/qingflow-app-builder-code-integrations/SKILL.md +137 -0
  23. package/skills/qingflow-app-builder-code-integrations/agents/openai.yaml +4 -0
  24. package/skills/qingflow-app-builder-code-integrations/references/code-block.md +66 -0
  25. package/skills/qingflow-app-builder-code-integrations/references/q-linker.md +77 -0
  26. package/skills/qingflow-app-user/SKILL.md +2 -1
  27. package/skills/qingflow-app-user/references/data-gotchas.md +5 -3
  28. package/skills/qingflow-app-user/references/public-surface-sync.md +6 -3
  29. package/skills/qingflow-app-user/references/record-patterns.md +14 -4
  30. package/skills/qingflow-mcp-setup/SKILL.md +111 -0
  31. package/skills/qingflow-mcp-setup/agents/openai.yaml +4 -0
  32. package/skills/qingflow-mcp-setup/references/claude-desktop.md +34 -0
  33. package/skills/qingflow-mcp-setup/references/environments.md +61 -0
  34. package/skills/qingflow-mcp-setup/references/generic-stdio.md +31 -0
  35. package/skills/qingflow-mcp-setup/scripts/check_local_server.sh +38 -0
  36. package/skills/qingflow-record-analysis/SKILL.md +94 -186
  37. package/skills/qingflow-record-analysis/agents/openai.yaml +2 -2
  38. package/skills/qingflow-record-analysis/references/analysis-gotchas.md +54 -113
  39. package/skills/qingflow-record-analysis/references/analysis-patterns.md +95 -134
  40. package/skills/qingflow-record-analysis/references/business-context.md +74 -0
  41. package/skills/qingflow-record-analysis/references/confidence-reporting.md +47 -74
  42. package/skills/qingflow-record-analysis/references/data-access-playbook.md +106 -0
  43. package/skills/qingflow-record-analysis/references/pandas-recipes.md +172 -0
  44. package/skills/qingflow-record-analysis/references/report-format.md +76 -0
  45. package/skills/qingflow-record-insert/SKILL.md +28 -7
  46. package/skills/qingflow-record-update/SKILL.md +3 -1
  47. package/skills/qingflow-workflow-builder/SKILL.md +96 -0
  48. package/skills/qingflow-workflow-builder/manifest.yaml +8 -0
  49. package/skills/qingflow-workflow-builder/references/01-overview.md +45 -0
  50. package/skills/qingflow-workflow-builder/references/02-update-mode.md +53 -0
  51. package/skills/qingflow-workflow-builder/references/03-flow-patterns.md +57 -0
  52. package/skills/qingflow-workflow-builder/references/04-stage1-business-modeling.md +131 -0
  53. package/skills/qingflow-workflow-builder/references/05-stage2-members-roles.md +29 -0
  54. package/skills/qingflow-workflow-builder/references/06-stage3-build-spec.md +165 -0
  55. package/skills/qingflow-workflow-builder/references/07-stage4-validate-spec.md +33 -0
  56. package/skills/qingflow-workflow-builder/references/08-stage5-apply-verify.md +51 -0
  57. package/skills/qingflow-workflow-builder/references/09-stage6-summary.md +88 -0
  58. package/skills/qingflow-workflow-builder/references/10-node-config-reference.md +93 -0
  59. package/skills/qingflow-workflow-builder/references/11-troubleshooting.md +15 -0
  60. package/skills/qingflow-workflow-builder/scripts/diff_flow_spec.py +275 -0
  61. package/skills/qingflow-workflow-builder/scripts/validate_flow_spec.py +605 -0
  62. package/src/qingflow_mcp/__init__.py +1 -1
  63. package/src/qingflow_mcp/backend_client.py +55 -1
  64. package/src/qingflow_mcp/builder_facade/models.py +532 -48
  65. package/src/qingflow_mcp/builder_facade/service.py +9194 -2384
  66. package/src/qingflow_mcp/builder_facade/workflow_spec.py +111 -0
  67. package/src/qingflow_mcp/cli/commands/app.py +3 -16
  68. package/src/qingflow_mcp/cli/commands/builder.py +354 -56
  69. package/src/qingflow_mcp/cli/commands/record.py +112 -6
  70. package/src/qingflow_mcp/cli/formatters.py +102 -2
  71. package/src/qingflow_mcp/cli/main.py +204 -3
  72. package/src/qingflow_mcp/public_surface.py +12 -9
  73. package/src/qingflow_mcp/response_trim.py +287 -22
  74. package/src/qingflow_mcp/server.py +29 -20
  75. package/src/qingflow_mcp/server_app_builder.py +108 -30
  76. package/src/qingflow_mcp/server_app_user.py +28 -23
  77. package/src/qingflow_mcp/solution/compiler/__init__.py +1 -3
  78. package/src/qingflow_mcp/solution/compiler/icon_utils.py +294 -0
  79. package/src/qingflow_mcp/solution/executor.py +3 -133
  80. package/src/qingflow_mcp/tools/ai_builder_tools.py +2617 -440
  81. package/src/qingflow_mcp/tools/app_tools.py +53 -8
  82. package/src/qingflow_mcp/tools/package_tools.py +16 -2
  83. package/src/qingflow_mcp/tools/record_tools.py +14283 -9162
  84. package/src/qingflow_mcp/tools/resource_read_tools.py +3 -0
  85. package/src/qingflow_mcp/tools/solution_tools.py +30 -2
  86. package/src/qingflow_mcp/tools/workflow_tools.py +3 -31
  87. package/skills/qingflow-record-analysis/references/dsl-templates.md +0 -93
  88. package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +0 -173
@@ -1,151 +1,112 @@
1
1
  # Analysis Patterns
2
2
 
3
- ## When to use this skill
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 whether the question needs `count`, `sum`, `avg`, `distinct_count`, `ratio`, or `ranking`
21
- 4. choose field_id-based `columns`, `where`, and `order_by`
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 inspection
11
+ 7. optional `record_list` or `record_get` only for sample/detail verification
25
12
 
26
- Result reading order:
13
+ Metric intent must be one of:
27
14
 
28
- 1. `record_access.status`
29
- 2. `record_access.complete`
30
- 3. `record_access.safe_for_final_conclusion`
31
- 4. `record_access.files[].local_path`
32
- 5. `record_access.metadata_files.schema`
33
- 6. Python outputs
34
- 7. `record_access.fields`
35
- 8. `record_access.warnings`
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
- If `record_access.status=needs_scope`, no CSV was written; ask for a time/business range or retry with a user-provided period from `scope.suggested_time_fields`. If `status=partial`, use the CSV files only as a limited subset and do not make a full-population conclusion.
24
+ ## Distribution
39
25
 
40
- Treat `record_browse_schema_get` as the browse-schema source of truth. It matches the selected Qingflow table view header and is the same schema source used by `record_access.fields` and `schema.json`. Missing fields are permission boundaries, not invitations to guess hidden ids.
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
- ## Lightweight `record_analyze` helper sequence
32
+ If the grouping field is ambiguous, ask the user to choose from a short candidate list.
43
33
 
44
- 1. `app_get`
45
- 2. `record_browse_schema_get`
46
- 3. decide whether the question needs `count`, `sum`, `avg`, `distinct_count`, `ratio`, or `ranking`
47
- 4. build one or more field_id-based DSLs
48
- 5. `record_analyze`
49
- 6. `record_list` only for sample inspection
50
-
51
- Result reading order:
52
-
53
- 1. `result.rows`
54
- 2. `result.totals.metric_totals`
55
- 3. `ranking`
56
- 4. `ratios`
57
- 5. `completeness`
58
- 6. `presentation`
59
-
60
- Use this only when a compact grouped result is enough; it is not the default path.
61
-
62
- ## Distribution / ratio pattern
63
-
64
- 1. Run `record_browse_schema_get`
65
- 2. Inspect candidate fields and aliases
66
- 3. If several plausible candidates remain, stop and ask the user to confirm the field from a short list
67
- 4. Build a DSL with:
68
- - one dimension
69
- - `count`
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
- Do not keep retrying different guessed field names in a loop.
61
+ ## Average / Sum
144
62
 
145
- ## Partial completion discipline
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
- If the user asked for several conclusions and only some of them are fully supported:
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
- 1. state which parts are complete
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
- ## Required output structure
3
+ ## Full Conclusion Gate
4
4
 
5
- When analysis is intended as a final answer, use this order:
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
- - the analysis path used `record_access` and Python, or an explicitly chosen lightweight `record_analyze` helper
17
- - every key analysis result has `safe_for_final_conclusion=true`
18
- - `safe_for_final_conclusion=true is necessary but not sufficient`
19
- - no key result depends on an invalid time phrase, an undefined denominator, or an unsupported derived metric
20
- - the result is not just a capped list sample
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
- ## Sample observation gate
18
+ ## Initial Observation Gate
23
19
 
24
- Put evidence into `样本观察` when:
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` or `record_access.truncated=true`
33
-
34
- ## Downgrade rule
35
-
36
- If `record_browse_schema_get` was not used for an analysis task, downgrade the overall framing to `初步观察` instead of `洞察` or `结论`.
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
- If grouped rows were truncated:
30
+ ## Anti-Mixing Rule
68
31
 
69
- - do not call the grouped output `各部门`, `全部渠道`, `完整名单`, or `所有分组`
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
- ## Partial completion disclosure
34
+ Correct split:
74
35
 
75
- If the user asked for multiple conclusions but only some are complete:
36
+ - full totals/distributions: `全量可信结论`
37
+ - illustrative examples: `样本观察`
76
38
 
77
- - explicitly disclose which parts are complete
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
- ## Example skeleton
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
- - `result.totals.metric_totals=...`
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.