@josephyan/qingflow-app-builder-mcp 0.2.0-beta.2 → 0.2.0-beta.21

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 (33) hide show
  1. package/README.md +11 -2
  2. package/npm/lib/runtime.mjs +37 -0
  3. package/npm/scripts/postinstall.mjs +5 -1
  4. package/package.json +3 -2
  5. package/pyproject.toml +1 -1
  6. package/skills/qingflow-app-builder/SKILL.md +225 -0
  7. package/skills/qingflow-app-builder/agents/openai.yaml +4 -0
  8. package/skills/qingflow-app-builder/references/create-app.md +148 -0
  9. package/skills/qingflow-app-builder/references/environments.md +63 -0
  10. package/skills/qingflow-app-builder/references/flow-actors-and-permissions.md +124 -0
  11. package/skills/qingflow-app-builder/references/gotchas.md +64 -0
  12. package/skills/qingflow-app-builder/references/solution-playbooks.md +58 -0
  13. package/skills/qingflow-app-builder/references/tool-selection.md +96 -0
  14. package/skills/qingflow-app-builder/references/update-flow.md +233 -0
  15. package/skills/qingflow-app-builder/references/update-layout.md +91 -0
  16. package/skills/qingflow-app-builder/references/update-schema.md +90 -0
  17. package/skills/qingflow-app-builder/references/update-views.md +184 -0
  18. package/src/qingflow_mcp/__init__.py +1 -1
  19. package/src/qingflow_mcp/builder_facade/models.py +294 -1
  20. package/src/qingflow_mcp/builder_facade/service.py +2727 -235
  21. package/src/qingflow_mcp/server.py +7 -5
  22. package/src/qingflow_mcp/server_app_builder.py +80 -4
  23. package/src/qingflow_mcp/server_app_user.py +8 -182
  24. package/src/qingflow_mcp/solution/compiler/form_compiler.py +1 -1
  25. package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +21 -2
  26. package/src/qingflow_mcp/solution/executor.py +34 -7
  27. package/src/qingflow_mcp/tools/ai_builder_tools.py +1038 -30
  28. package/src/qingflow_mcp/tools/app_tools.py +1 -2
  29. package/src/qingflow_mcp/tools/approval_tools.py +357 -75
  30. package/src/qingflow_mcp/tools/directory_tools.py +158 -28
  31. package/src/qingflow_mcp/tools/record_tools.py +1954 -973
  32. package/src/qingflow_mcp/tools/task_tools.py +376 -225
  33. package/src/qingflow_mcp/tools/workflow_tools.py +78 -4
@@ -0,0 +1,124 @@
1
+ # Flow Actors And Permissions
2
+
3
+ Use this when the workflow needs real assignees or node-level editable field permissions.
4
+
5
+ ## Canonical policy
6
+
7
+ - Approval, fill, and copy nodes must declare at least one assignee.
8
+ - Prefer roles over explicit members.
9
+ - Resolve directory actors before calling `app_flow_plan` or `app_flow_apply`.
10
+ - Use canonical keys only:
11
+ - `assignees.role_names`
12
+ - `assignees.role_ids`
13
+ - `assignees.member_names`
14
+ - `assignees.member_emails`
15
+ - `assignees.member_uids`
16
+ - `permissions.editable_fields`
17
+
18
+ ## Recommended order
19
+
20
+ 1. `app_read_fields`
21
+ 2. `app_read_flow_summary`
22
+ 3. `role_search`
23
+ 4. `member_search` when the user explicitly names people
24
+ 5. `role_create` when no reusable role exists and the user wants role-based routing
25
+ 6. `app_flow_plan`
26
+ 7. `app_flow_apply`
27
+
28
+ ## Examples
29
+
30
+ ### Route an approval node to a reusable role
31
+
32
+ ```json
33
+ {
34
+ "tool_name": "app_flow_plan",
35
+ "arguments": {
36
+ "profile": "default",
37
+ "app_key": "APP_123",
38
+ "preset": "basic_approval",
39
+ "nodes": [
40
+ {
41
+ "id": "approve_1",
42
+ "type": "approve",
43
+ "name": "部门审批",
44
+ "assignees": {
45
+ "role_names": ["项目经理"]
46
+ }
47
+ }
48
+ ]
49
+ }
50
+ }
51
+ ```
52
+
53
+ ### Route to explicit members when the user names people
54
+
55
+ ```json
56
+ {
57
+ "tool_name": "app_flow_plan",
58
+ "arguments": {
59
+ "profile": "default",
60
+ "app_key": "APP_123",
61
+ "preset": "basic_approval",
62
+ "nodes": [
63
+ {
64
+ "id": "approve_1",
65
+ "type": "approve",
66
+ "name": "部门审批",
67
+ "assignees": {
68
+ "member_names": ["严琪东", "张三"]
69
+ }
70
+ }
71
+ ]
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Let one node edit selected fields only
77
+
78
+ ```json
79
+ {
80
+ "tool_name": "app_flow_apply",
81
+ "arguments": {
82
+ "profile": "default",
83
+ "app_key": "APP_123",
84
+ "mode": "replace",
85
+ "publish": true,
86
+ "nodes": [
87
+ {"id": "start", "type": "start", "name": "发起"},
88
+ {
89
+ "id": "approve_1",
90
+ "type": "approve",
91
+ "name": "部门审批",
92
+ "assignees": {
93
+ "role_names": ["项目经理"]
94
+ },
95
+ "permissions": {
96
+ "editable_fields": ["状态", "审批意见", "项目负责人"]
97
+ }
98
+ },
99
+ {"id": "end", "type": "end", "name": "结束"}
100
+ ],
101
+ "transitions": [
102
+ {"from": "start", "to": "approve_1"},
103
+ {"from": "approve_1", "to": "end"}
104
+ ]
105
+ }
106
+ }
107
+ ```
108
+
109
+ ## Common recovery
110
+
111
+ ### `ROLE_NOT_FOUND` / `AMBIGUOUS_ROLE`
112
+
113
+ - retry with `role_search`
114
+ - if the business wants a reusable route and no exact role exists, create one with `role_create`
115
+
116
+ ### `MEMBER_NOT_FOUND` / `AMBIGUOUS_MEMBER`
117
+
118
+ - retry with `member_search`
119
+ - do not guess user ids
120
+
121
+ ### `UNKNOWN_FLOW_FIELD`
122
+
123
+ - reread fields with `app_read_fields`
124
+ - only pass real current field names to `permissions.editable_fields`
@@ -0,0 +1,64 @@
1
+ # Builder Gotchas
2
+
3
+ ## Auth and workspace
4
+
5
+ - `auth_*` success does not mean a workspace is selected
6
+ - Re-run `workspace_select` after auth changes or route changes
7
+
8
+ ## Package ownership
9
+
10
+ - App creation and publish do not guarantee package attachment
11
+ - Treat `package_attach_app` as the source of truth for package ownership
12
+ - Check `tag_ids_after` after schema writes
13
+
14
+ ## Package vs app vs field
15
+
16
+ - A package/system is not an app
17
+ - Another app is not a field
18
+ - If the user names multiple forms/modules that relate to each other, create multiple apps and connect them with relation fields
19
+ - Do not use child app names like “项目/需求/任务/缺陷/团队” as plain text fields inside one app
20
+
21
+ ## Auto publish
22
+
23
+ - `app_schema_apply`, `app_layout_apply`, `app_flow_apply`, and `app_views_apply` publish by default
24
+ - Pass `publish=false` only when the user explicitly wants to leave changes in draft
25
+ - `app_publish_verify` is for explicit final verification, not the default next step after every write
26
+
27
+ ## Readback scope
28
+
29
+ - Prefer summary reads over large raw payloads
30
+ - Use `app_read_fields` before schema or view work
31
+ - Use `app_read_layout_summary` before layout work
32
+ - Use `app_read_flow_summary` before workflow work
33
+ - Use `app_read_views_summary` before view work
34
+
35
+ ## Workflow dependencies
36
+
37
+ - Approval-style flows usually require an explicit status field
38
+ - Approval, fill, and copy nodes also require at least one assignee
39
+ - Prefer roles over explicit members unless the user explicitly names people
40
+ - Resolve assignees with `role_search` / `member_search` before flow apply
41
+ - Use `permissions.editable_fields` for node-level editable field permissions; do not guess field ids
42
+ - Preset node ids matter. When patching `basic_approval` or `basic_fill_then_approve`, reuse `approve_1` and `fill_1` unless you are explicitly replacing the skeleton.
43
+ - If `app_flow_plan` reports `FLOW_DEPENDENCY_MISSING`, fix schema first
44
+ - Do not switch to hidden `solution_*` tools from public builder flows
45
+
46
+ ## Retry discipline
47
+
48
+ - If a write returns `partial_success`, read back before retrying
49
+ - Do not repeat create steps after `app_key` already exists
50
+ - For backend rejects, keep the retry narrow: retry only the failed tool, not the whole chain
51
+ - For `VALIDATION_ERROR`, do not keep guessing. Reuse `suggested_next_call`, `canonical_arguments`, `allowed_keys`, and `allowed_values` first.
52
+ - For layout `VALIDATION_ERROR`, also inspect `section_allowed_keys`, `section_aliases`, and `minimal_section_example`. If the same layout-shape error repeats twice, stop free-form retries and re-read `builder_tool_contract(app_layout_plan)`.
53
+ - For flow work, do not replay internal keys from old logs or plan outputs. Public builder calls should stay on:
54
+ - `assignees.role_ids` / `assignees.member_uids` / `assignees.member_emails`
55
+ - `permissions.editable_fields`
56
+ - For view work, treat `columns` as the only canonical public key. `app_read_views_summary` and `app_views_plan/apply` should all be read and written in that shape.
57
+ - For layout work, treat `title + rows` as the only canonical public section shape. `fields`, `field_ids`, and `columns` may appear in legacy/internal shapes, but they are not the preferred public write shape.
58
+ - A created view is not enough to claim a filter succeeded. When `app_views_apply` returns `partial_success`, `views_verified=false`, or `details.filter_mismatches`, treat the view as present but the filter as unverified.
59
+ - If duplicate view names exist, do not retry by name. Read the exact `view_key` and target that one.
60
+ - If a view or flow write fails, report the smallest next action:
61
+ - wrong key -> switch to canonical key
62
+ - unsupported preset -> switch to allowed canonical preset
63
+ - backend reject -> re-read summary and retry only the failed patch
64
+ - Do not translate abstract user phrases like “灵活流程” or “默认视图” directly into MCP arguments. First convert them to a preset or explicit patch plan.
@@ -0,0 +1,58 @@
1
+ # Builder Playbooks
2
+
3
+ Use these when you need a quick reminder of the standard v2 builder sequences.
4
+
5
+ ## Create a new app in an existing package
6
+
7
+ 1. `package_resolve`
8
+ 2. `app_resolve`
9
+ 3. `app_schema_plan`
10
+ 4. `app_schema_apply`
11
+ 5. `package_attach_app`
12
+ 6. `app_publish_verify` only if the user asks for explicit live verification
13
+
14
+ ## Update fields on an existing app
15
+
16
+ 1. `app_resolve`
17
+ 2. `app_read_fields`
18
+ 3. `app_schema_plan`
19
+ 4. `app_schema_apply`
20
+
21
+ ## Rework layout
22
+
23
+ 1. `app_read_layout_summary`
24
+ 2. `app_layout_plan`
25
+ 3. `app_layout_apply`
26
+
27
+ Prefer `mode=merge`. Use `mode=replace` only when every field placement is intentional.
28
+
29
+ ## Add or update workflow
30
+
31
+ 1. `app_read_fields`
32
+ 2. `app_read_flow_summary`
33
+ 3. `role_search` or `member_search`
34
+ 4. `role_create` if the business wants a reusable role and no good exact role exists
35
+ 5. `app_flow_plan`
36
+ 6. `app_flow_apply`
37
+
38
+ If `app_flow_plan` reports `FLOW_DEPENDENCY_MISSING`, fix schema first.
39
+ If it reports `FLOW_ASSIGNEE_REQUIRED`, resolve roles or members first and retry with canonical `assignees.*`.
40
+
41
+ ## Add or update views
42
+
43
+ 1. `app_read_fields`
44
+ 2. `app_read_views_summary`
45
+ 3. `app_views_plan`
46
+ 4. `app_views_apply`
47
+
48
+ For both workflow and view work, prefer `suggested_next_call` over re-guessing arguments after a validation failure.
49
+
50
+ ## Final readback
51
+
52
+ Prefer these fields after writes:
53
+
54
+ - `app_read_summary.tag_ids`
55
+ - `app_read_summary.publish_status`
56
+ - `app_read_layout_summary.unplaced_fields`
57
+ - `app_read_views_summary.views`
58
+ - `app_read_flow_summary.nodes`
@@ -0,0 +1,96 @@
1
+ # Tool Selection
2
+
3
+ Use the smallest v2 builder tool chain that can finish the task.
4
+
5
+ ## Default path
6
+
7
+ `resolve -> summary read -> plan -> apply -> attach -> publish_verify`
8
+
9
+ Use `plan` before `apply` unless the patch is trivial and already normalized.
10
+
11
+ ## Hierarchy first
12
+
13
+ Before picking tools, decide which layer the request targets:
14
+
15
+ - `package`: a solution/app bundle like “研发项目管理” or “费控管理系统”
16
+ - `app`: one form/app inside that package
17
+ - `field`: one field inside one app
18
+ - `relation`: a field that links two apps
19
+
20
+ If the user asks for multiple forms/modules that relate to each other, this is a package-level multi-app task, not a single-app create.
21
+
22
+ ## Resolve
23
+
24
+ - `package_create`: create a new package only after the user confirms package creation; exact-name duplicates return `noop=true`
25
+ - `package_resolve`: exact package lookup by name
26
+ - `package_list`: read-only fallback when package resolution is ambiguous
27
+ - `member_search`: resolve named people from the directory
28
+ - `role_search`: resolve reusable roles from the directory
29
+ - `role_create`: create a reusable role when the business owner wants role-based routing
30
+ - `app_resolve`: locate an existing app by `app_key` or `app_name`
31
+
32
+ ## Summary reads
33
+
34
+ - `app_read_summary`: overall app health, publish state, counts
35
+ - `app_read_fields`: field names, types, required flags, section ids
36
+ - `app_read_layout_summary`: sections, rows, unplaced fields
37
+ - `app_read_views_summary`: current view names, types, columns, group-by
38
+ - `app_read_flow_summary`: workflow enabled state, nodes, transitions
39
+
40
+ ## Plan tools
41
+
42
+ Use these when the patch is non-trivial or the model is likely to drift.
43
+
44
+ - `app_schema_plan`: normalize field patches before add/update/remove
45
+ - `app_layout_plan`: preview merge/replace layout changes or layout presets
46
+ - `app_flow_plan`: validate workflow nodes, transitions, and dependencies
47
+ - `app_views_plan`: normalize view aliases and validate referenced fields
48
+
49
+ Use `builder_tool_contract` before guessing keys, aliases, presets, or enum values.
50
+
51
+ ## Apply tools
52
+
53
+ These execute normalized patches and publish by default unless `publish=false`.
54
+
55
+ - `app_schema_apply`: create app shell or change fields
56
+ - `app_layout_apply`: merge or replace layout
57
+ - `app_flow_apply`: replace workflow
58
+ - `app_views_apply`: upsert or remove views
59
+
60
+ ## Explicit post-apply tools
61
+
62
+ - `package_attach_app`: attach an app to a package; do not assume create or publish attaches it
63
+ - `app_publish_verify`: explicit final publish verification when the user asks for live confirmation
64
+
65
+ ## Decision shortcuts
66
+
67
+ - Create one app inside an existing package:
68
+ `package_resolve -> app_resolve -> app_schema_plan -> app_schema_apply -> package_attach_app`
69
+ - Create a brand new package, then create one app in it:
70
+ `package_create -> package_resolve -> app_schema_plan -> app_schema_apply -> package_attach_app`
71
+ - Create a brand new multi-app system/package:
72
+ `package_create/resolve -> per-app app_schema_plan/apply -> package_attach_app per app -> relation field patches`
73
+ - Update fields on an existing app:
74
+ `app_resolve -> app_read_fields -> app_schema_plan -> app_schema_apply`
75
+ - Tidy layout:
76
+ `app_read_fields -> app_read_layout_summary -> builder_tool_contract (if shape is unclear) -> app_layout_plan -> app_layout_apply`
77
+ - Add workflow:
78
+ `builder_tool_contract -> app_read_fields -> app_read_flow_summary -> role_search/member_search -> app_flow_plan -> app_flow_apply -> app_read_flow_summary`
79
+ - Add views:
80
+ `builder_tool_contract -> app_read_fields -> app_read_views_summary -> app_views_plan -> app_views_apply -> app_read_views_summary`
81
+
82
+ ## Avoid
83
+
84
+ - Do not handcraft raw Qingflow schema payloads
85
+ - Do not rely on internal `solution_*` tools in public builder flows
86
+ - Do not create a new package without first asking the user to confirm package creation
87
+ - Do not treat a package/system name as `app_name` when the user clearly wants multiple apps inside it
88
+ - Do not compress multiple business objects into one app with several text fields
89
+ - Do not skip summary reads before flow or view work
90
+ - Do not emit `column_names`; always use `columns`
91
+ - Do not model layout shape with `fields`, `field_ids`, or top-level `columns`; custom layout sections should be `title + rows`
92
+ - Do not reuse internal flow keys such as `role_entries` or `editable_que_ids` in public builder calls
93
+ - Do not pass natural-language preset guesses such as `default_approval`; map them to canonical preset values first
94
+ - Do not omit assignees on approval/fill/copy nodes
95
+ - Do not patch preset flows with brand new approval/fill node ids unless you are intentionally replacing the skeleton; reuse preset ids like `approve_1` and `fill_1`
96
+ - Do not guess role ids, member ids, or editable field ids; resolve names first
@@ -0,0 +1,233 @@
1
+ # Update Flow
2
+
3
+ Use this when the app already exists and the task is only about workflow.
4
+
5
+ ## Minimal sequence
6
+
7
+ 1. `builder_tool_contract(tool_name="app_flow_plan")`
8
+ 2. `app_read_fields`
9
+ 3. `app_read_flow_summary`
10
+ 4. `role_search` or `member_search`
11
+ 5. `role_create` if the user wants a reusable directory role and no good role exists
12
+ 6. start from a canonical preset when possible
13
+ 7. patch the skeleton instead of freehanding a full graph
14
+ 8. reuse preset node ids when patching:
15
+ - `basic_approval` -> patch `approve_1`
16
+ - `basic_fill_then_approve` -> patch `fill_1` and `approve_1`
17
+ Do not add a second approval/fill node with a new id unless you are intentionally replacing the skeleton.
18
+ The MCP now auto-aligns the simplest single-node preset overrides, but still prefer explicit preset ids so the merged graph stays predictable.
19
+ 9. `app_flow_plan`
20
+ 10. `app_flow_apply`
21
+ 11. `app_read_flow_summary` when apply returns `partial_success` or the user asked for verification
22
+
23
+ If you are unsure about presets or node shapes, call `builder_tool_contract(tool_name="app_flow_apply")` before guessing.
24
+
25
+ ## Example
26
+
27
+ Canonical preset mapping:
28
+
29
+ - “默认审批/基础审批/普通审批” -> `basic_approval`
30
+ - “先填报再审批/提交后审批” -> `basic_fill_then_approve`
31
+
32
+ Plan a simple approval flow with a role assignee and node-level editable fields:
33
+
34
+ ```json
35
+ {
36
+ "tool_name": "app_flow_plan",
37
+ "arguments": {
38
+ "profile": "default",
39
+ "app_key": "APP_123",
40
+ "preset": "basic_approval",
41
+ "nodes": [
42
+ {
43
+ "id": "approve_1",
44
+ "type": "approve",
45
+ "name": "部门审批",
46
+ "assignees": {
47
+ "role_names": ["项目经理"]
48
+ },
49
+ "permissions": {
50
+ "editable_fields": ["状态", "审批意见"]
51
+ }
52
+ }
53
+ ]
54
+ }
55
+ }
56
+ ```
57
+
58
+ For flexible business requirements, do not jump straight to a full custom graph. Use this safer pattern:
59
+
60
+ 1. build a base skeleton from a preset
61
+ 2. identify the business-specific changes
62
+ 3. patch nodes/transitions explicitly
63
+
64
+ For branch flows, keep the public shape canonical:
65
+
66
+ 1. add a `branch` node
67
+ 2. add one or more `condition` nodes as branch lanes
68
+ 3. put filter rules on the `condition` nodes with `conditions` or `condition_groups`
69
+ 4. use an empty `condition` node as the default branch when needed
70
+
71
+ Canonical branch example:
72
+
73
+ ```json
74
+ {
75
+ "tool_name": "app_flow_plan",
76
+ "arguments": {
77
+ "profile": "default",
78
+ "app_key": "APP_123",
79
+ "mode": "replace",
80
+ "nodes": [
81
+ {"id": "start", "type": "start", "name": "发起"},
82
+ {"id": "route", "type": "branch", "name": "金额分支"},
83
+ {
84
+ "id": "high_amount",
85
+ "type": "condition",
86
+ "name": "金额大于等于一万",
87
+ "conditions": [
88
+ {"field_name": "预计金额", "operator": "gte", "value": 10000}
89
+ ]
90
+ },
91
+ {
92
+ "id": "approve_finance",
93
+ "type": "approve",
94
+ "name": "财务审批",
95
+ "assignees": {"role_names": ["财务负责人"]}
96
+ },
97
+ {"id": "default_lane", "type": "condition", "name": "其他情况"},
98
+ {
99
+ "id": "approve_manager",
100
+ "type": "approve",
101
+ "name": "部门审批",
102
+ "assignees": {"role_names": ["项目经理"]}
103
+ },
104
+ {"id": "end", "type": "end", "name": "结束"}
105
+ ],
106
+ "transitions": [
107
+ {"from": "start", "to": "route"},
108
+ {"from": "route", "to": "high_amount"},
109
+ {"from": "high_amount", "to": "approve_finance"},
110
+ {"from": "route", "to": "default_lane"},
111
+ {"from": "default_lane", "to": "approve_manager"},
112
+ {"from": "approve_finance", "to": "end"},
113
+ {"from": "approve_manager", "to": "end"}
114
+ ]
115
+ }
116
+ }
117
+ ```
118
+
119
+ Only after that should you use explicit nodes:
120
+
121
+ ```json
122
+ {
123
+ "tool_name": "app_flow_apply",
124
+ "arguments": {
125
+ "profile": "default",
126
+ "app_key": "APP_123",
127
+ "mode": "replace",
128
+ "publish": true,
129
+ "nodes": [
130
+ {"id": "start", "type": "start", "name": "发起"},
131
+ {
132
+ "id": "approve_1",
133
+ "type": "approve",
134
+ "name": "部门审批",
135
+ "assignees": {
136
+ "role_names": ["项目经理"]
137
+ },
138
+ "permissions": {
139
+ "editable_fields": ["状态", "审批意见"]
140
+ }
141
+ },
142
+ {"id": "end", "type": "end", "name": "结束"}
143
+ ],
144
+ "transitions": [
145
+ {"from": "start", "to": "approve_1"},
146
+ {"from": "approve_1", "to": "end"}
147
+ ]
148
+ }
149
+ }
150
+ ```
151
+
152
+ After `app_flow_plan` succeeds, prefer reusing its `suggested_next_call.arguments` directly. Do not rewrite the result into internal fields such as `role_entries` or `editable_que_ids`.
153
+ When you patch a preset, patch the preset node itself. Do not leave the preset approval node unassigned while adding a second custom approval node.
154
+
155
+ ## Common failures
156
+
157
+ ### `FLOW_ASSIGNEE_REQUIRED`
158
+
159
+ Approval, fill, and copy nodes must declare at least one assignee.
160
+
161
+ If this happens after using a preset, check for this specific mistake first:
162
+
163
+ - the preset created `approve_1` or `fill_1`
164
+ - your patch created a different node id instead of patching that preset node
165
+ - the original preset node remained in the graph without assignees
166
+
167
+ Preferred fix order:
168
+
169
+ 1. `role_search`
170
+ 2. `member_search` only if the user explicitly named members
171
+ 3. `role_create` if the business needs a reusable role
172
+ 4. patch the preset node id itself with canonical `assignees.*`
173
+ 5. retry `app_flow_plan` or `app_flow_apply`
174
+
175
+ ### `FLOW_DEPENDENCY_MISSING`
176
+
177
+ The workflow depends on fields that do not exist yet, usually `status`. Fix schema first.
178
+
179
+ Preferred recovery:
180
+
181
+ 1. use the returned `suggested_next_call`
182
+ 2. apply the minimal schema patch
183
+ 3. rerun `app_read_fields`
184
+ 4. rerun `app_flow_plan`
185
+
186
+ ### `INVALID_FLOW_EDGE`
187
+
188
+ One or more transitions reference unknown nodes or create an invalid graph.
189
+
190
+ ### `UNKNOWN_FLOW_FIELD`
191
+
192
+ The workflow referenced a field name that does not exist, often in:
193
+
194
+ - `permissions.editable_fields`
195
+ - branch `conditions`
196
+
197
+ Call `app_read_fields` and retry with the exact field names returned by the app.
198
+
199
+ ### `STATUS_FIELD_REQUIRED`
200
+
201
+ The app has no explicit status field recognized by the internal workflow compiler. Add one with `app_schema_apply`, then retry.
202
+
203
+ ### `FLOW_STAGE_CONTEXT_MISSING`
204
+
205
+ Internal flow stage context was missing or invalid. Re-run `app_flow_plan`, then retry `app_flow_apply`. Do not switch to hidden `solution_*` tools.
206
+
207
+ ### `VALIDATION_ERROR`
208
+
209
+ Do not keep guessing preset names or node shapes. First:
210
+
211
+ 1. inspect `suggested_next_call`
212
+ 2. reuse `canonical_arguments` if present
213
+ 3. check `allowed_values`
214
+ 4. retry with canonical preset or canonical node types
215
+ 5. for workflow actors and permissions, always convert to:
216
+ - `assignees.role_names`
217
+ - `assignees.member_names`
218
+ - `permissions.editable_fields`
219
+
220
+ Do not copy internal keys from old plan outputs or logs, including:
221
+
222
+ - `role_entries`
223
+ - `editable_que_ids`
224
+
225
+ ## Notes
226
+
227
+ - `mode=replace` is the only supported flow apply mode
228
+ - `app_flow_apply` publishes by default
229
+ - Prefer roles over explicit members unless the user explicitly asks for named members
230
+ - `basic_approval` and `basic_fill_then_approve` are skeletons, not complete business workflows
231
+ - Report results precisely:
232
+ - “基础流程骨架已创建” when only the preset landed
233
+ - “业务定制规则已补齐” only after the patch phase is complete
@@ -0,0 +1,91 @@
1
+ # Update Layout
2
+
3
+ Use this when fields already exist and the task is only about form grouping or ordering.
4
+
5
+ ## Minimal sequence
6
+
7
+ 1. `app_read_fields`
8
+ 2. `app_read_layout_summary`
9
+ 3. `builder_tool_contract` when the section shape is not already obvious
10
+ 4. `app_layout_plan`
11
+ 5. `app_layout_apply`
12
+
13
+ ## Example
14
+
15
+ Plan a custom layout with the canonical public section shape:
16
+
17
+ ```json
18
+ {
19
+ "tool_name": "app_layout_plan",
20
+ "arguments": {
21
+ "profile": "default",
22
+ "app_key": "APP_123",
23
+ "mode": "merge",
24
+ "sections": [
25
+ {
26
+ "title": "基础信息",
27
+ "rows": [
28
+ ["客户名称", "订单金额"],
29
+ ["状态", "跟进日期"]
30
+ ]
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ ```
36
+
37
+ Apply the layout. This publishes by default:
38
+
39
+ ```json
40
+ {
41
+ "tool_name": "app_layout_apply",
42
+ "arguments": {
43
+ "profile": "default",
44
+ "app_key": "APP_123",
45
+ "mode": "merge",
46
+ "publish": true,
47
+ "sections": [
48
+ {
49
+ "title": "基础信息",
50
+ "rows": [
51
+ ["客户名称", "订单金额"],
52
+ ["状态", "跟进日期"]
53
+ ]
54
+ }
55
+ ]
56
+ }
57
+ }
58
+ ```
59
+
60
+ ## Common failures
61
+
62
+ ### `UNKNOWN_LAYOUT_FIELD`
63
+
64
+ At least one field name does not exist. Re-read with `app_read_fields`.
65
+
66
+ ### `DUPLICATE_LAYOUT_FIELD`
67
+
68
+ The same field appears more than once in the requested layout.
69
+
70
+ ### `INCOMPLETE_LAYOUT`
71
+
72
+ Only happens in `mode=replace`. Switch to `mode=merge` unless you intend to place every field exactly once.
73
+
74
+ ### `LAYOUT_APPLY_FAILED`
75
+
76
+ Re-read with `app_read_layout_summary`. Check `current_field_names`, `request_id`, and `suggested_next_call`.
77
+
78
+ ### `VALIDATION_ERROR`
79
+
80
+ Do not keep guessing section keys. Reuse `suggested_next_call`, `canonical_arguments`, `section_allowed_keys`, and `minimal_section_example`.
81
+
82
+ If the same shape error repeats twice, stop free-form retries and re-read `builder_tool_contract(app_layout_plan)`.
83
+
84
+ ## Notes
85
+
86
+ - `section_id` is optional; it is generated from the section title
87
+ - `merge` is safer than `replace`
88
+ - Unmentioned fields stay in place or get auto-added to `未分组字段`
89
+ - Public builder layout sections use `title + rows`
90
+ - Do not treat “一行四个字段 / 四列布局 / 每行放四个” as a top-level `columns` parameter; translate it into a `rows` matrix
91
+ - Do not prefer `fields` or `field_ids` once `rows` is known, even though MCP may normalize those shorthands for recovery