@qingflow-tech/qingflow-cli 1.1.2 → 1.1.34

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 (103) hide show
  1. package/README.md +2 -2
  2. package/docs/local-agent-install.md +10 -0
  3. package/package.json +1 -1
  4. package/pyproject.toml +1 -1
  5. package/skills/qingflow-cli/SKILL.md +61 -47
  6. package/skills/qingflow-cli/manifest.yaml +1 -1
  7. package/skills/qingflow-cli/reference/00-INDEX.md +35 -0
  8. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_APP_DELIVERY_WORKFLOW.md +21 -477
  9. package/skills/qingflow-cli/reference/QINGFLOW_CLI_BUILDER_VIEWS_WORKFLOW.md +44 -290
  10. package/skills/qingflow-cli/reference/QINGFLOW_CLI_SCHEMA_APPLY_FIELD_TYPES_AND_SCENARIOS.md +11 -102
  11. package/skills/qingflow-cli/reference/builder/10-build-single-app.md +57 -0
  12. package/skills/qingflow-cli/reference/builder/20-build-complete-system.md +84 -0
  13. package/skills/qingflow-cli/reference/builder/30-schema-fields.md +317 -0
  14. package/skills/qingflow-cli/reference/builder/40-layout.md +70 -0
  15. package/skills/qingflow-cli/reference/builder/50-views.md +540 -0
  16. package/skills/qingflow-cli/reference/builder/60-charts.md +328 -0
  17. package/skills/qingflow-cli/reference/builder/70-portal.md +372 -0
  18. package/skills/qingflow-cli/reference/builder/80-buttons-associated-resources.md +148 -0
  19. package/skills/qingflow-cli/reference/builder/90-workflow.md +35 -0
  20. package/skills/qingflow-cli/reference/builder/99-publish-verify.md +64 -0
  21. package/skills/qingflow-cli/reference/builder/README.md +62 -0
  22. package/skills/qingflow-cli/reference/builder/code-integrations/README.md +130 -0
  23. package/skills/qingflow-cli/reference/builder/code-integrations/code-block.md +66 -0
  24. package/skills/qingflow-cli/reference/builder/code-integrations/q-linker.md +77 -0
  25. package/skills/qingflow-cli/reference/builder/reference/app-delivery-sop.md +508 -0
  26. package/skills/qingflow-cli/reference/builder/reference/match-rules.md +229 -0
  27. package/skills/qingflow-cli/reference/builder/reference/workspace-icons.md +89 -0
  28. package/skills/qingflow-cli/reference/builder/workflow/01-overview.md +48 -0
  29. package/skills/qingflow-cli/reference/builder/workflow/02-update-mode.md +63 -0
  30. package/skills/qingflow-cli/reference/builder/workflow/03-flow-patterns.md +59 -0
  31. package/skills/qingflow-cli/reference/builder/workflow/04-stage1-business-modeling.md +131 -0
  32. package/skills/qingflow-cli/reference/builder/workflow/05-stage2-members-roles.md +29 -0
  33. package/skills/qingflow-cli/reference/builder/workflow/06-stage3-build-spec.md +211 -0
  34. package/skills/qingflow-cli/reference/builder/workflow/07-stage4-validate-spec.md +36 -0
  35. package/skills/qingflow-cli/reference/builder/workflow/08-stage5-apply-verify.md +66 -0
  36. package/skills/qingflow-cli/reference/builder/workflow/09-stage6-summary.md +88 -0
  37. package/skills/qingflow-cli/reference/builder/workflow/10-node-config-reference.md +93 -0
  38. package/skills/qingflow-cli/reference/builder/workflow/11-troubleshooting.md +18 -0
  39. package/skills/qingflow-cli/reference/builder/workflow/README.md +88 -0
  40. package/skills/qingflow-cli/reference/builder/workflow/workflow-schema.json +1754 -0
  41. package/skills/qingflow-cli/reference/charts_upsert_dashboard_starter.example.json +81 -0
  42. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ADMIN_CHEATSHEET.md +94 -0
  43. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_DATA_RETRIEVAL_WORKFLOW.md +139 -0
  44. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_EXPLORATION_REPORT.md +84 -0
  45. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_FIELD_DATA_TYPES.md +129 -0
  46. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_MEMBER_CHEATSHEET.md +195 -0
  47. package/skills/qingflow-cli/reference/core/QINGFLOW_CLI_ONE_SHOT_CHEATSHEET.md +159 -0
  48. package/skills/qingflow-cli/reference/examples/README.md +17 -0
  49. package/skills/qingflow-cli/reference/examples/associated/associated_resources_semantic_full.example.json +50 -0
  50. package/skills/qingflow-cli/reference/examples/buttons/custom_buttons_advanced.example.json +56 -0
  51. package/skills/qingflow-cli/reference/examples/charts/charts_remove.example.json +1 -0
  52. package/skills/qingflow-cli/reference/examples/charts/charts_reorder.example.json +1 -0
  53. package/skills/qingflow-cli/reference/examples/charts/charts_upsert_bar.example.json +8 -0
  54. package/skills/qingflow-cli/reference/examples/charts/charts_upsert_dashboard_starter.example.json +118 -0
  55. package/skills/qingflow-cli/reference/examples/charts/charts_upsert_minimal.example.json +13 -0
  56. package/skills/qingflow-cli/reference/examples/layout/layout_sections_full.example.json +22 -0
  57. package/skills/qingflow-cli/reference/examples/portal/portal_sections_all_types.example.json +145 -0
  58. package/skills/qingflow-cli/reference/examples/portal/portal_sections_five_types.example.json +126 -0
  59. package/skills/qingflow-cli/reference/examples/portal/portal_sections_standard_workbench.example.json +178 -0
  60. package/skills/qingflow-cli/reference/examples/record/record_insert_all_field_types.example.json +35 -0
  61. package/skills/qingflow-cli/reference/examples/schema/_batch_schema_complex.json +18 -0
  62. package/skills/qingflow-cli/reference/examples/schema/_batch_schema_scalar.json +17 -0
  63. package/skills/qingflow-cli/reference/examples/schema/schema_add_fields_minimal.example.json +7 -0
  64. package/skills/qingflow-cli/reference/examples/schema/schema_apply_add_fields_all_types.json +78 -0
  65. package/skills/qingflow-cli/reference/examples/schema/schema_multi_app_form_relation_layout.example.json +166 -0
  66. package/skills/qingflow-cli/reference/examples/schema/schema_single_app_form_standard.example.json +95 -0
  67. package/skills/qingflow-cli/reference/examples/views/views_batch_full.example.json +159 -0
  68. package/skills/qingflow-cli/reference/examples/views/views_upsert_table_minimal.example.json +42 -0
  69. package/skills/qingflow-cli/reference/portal_sections_all_types.example.json +18 -4
  70. package/skills/qingflow-cli/reference/portal_sections_five_types.example.json +3 -3
  71. package/skills/qingflow-cli/reference/portal_sections_standard_workbench.example.json +57 -7
  72. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_CREATE_WORKFLOW.md +22 -0
  73. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_DELETE_WORKFLOW.md +31 -0
  74. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_IMPORT_WORKFLOW.md +176 -0
  75. package/skills/qingflow-cli/reference/record/QINGFLOW_CLI_RECORD_UPDATE_WORKFLOW.md +167 -0
  76. package/skills/qingflow-cli/reference/record/analysis/README.md +130 -0
  77. package/skills/qingflow-cli/reference/record/analysis/analysis-gotchas.md +91 -0
  78. package/skills/qingflow-cli/reference/record/analysis/analysis-patterns.md +112 -0
  79. package/skills/qingflow-cli/reference/record/analysis/business-context.md +74 -0
  80. package/skills/qingflow-cli/reference/record/analysis/confidence-reporting.md +69 -0
  81. package/skills/qingflow-cli/reference/record/analysis/data-access-playbook.md +106 -0
  82. package/skills/qingflow-cli/reference/record/analysis/pandas-recipes.md +172 -0
  83. package/skills/qingflow-cli/reference/record/analysis/report-format.md +76 -0
  84. package/skills/qingflow-cli/reference/record/insert/README.md +125 -0
  85. package/skills/qingflow-cli/reference/schema_apply_add_fields_all_types.json +1 -1
  86. package/skills/qingflow-cli/reference/task/QINGFLOW_CLI_TASK_CONTEXT_WORKFLOW.md +153 -0
  87. package/skills/qingflow-cli/reference/task/ops/README.md +134 -0
  88. package/skills/qingflow-cli/reference/task/ops/environments.md +43 -0
  89. package/skills/qingflow-cli/reference/task/ops/workflow-usage.md +29 -0
  90. package/skills/qingflow-cli/reference/views_upsert_table_minimal.example.json +42 -7
  91. package/skills/qingflow-cli/scripts/validate_system_build_summary.py +124 -0
  92. package/skills/qingflow-cli/scripts/workflow/diff_flow_spec.py +275 -0
  93. package/skills/qingflow-cli/scripts/workflow/validate_flow_spec.py +627 -0
  94. package/src/qingflow_mcp/builder_facade/models.py +413 -119
  95. package/src/qingflow_mcp/builder_facade/service.py +4238 -666
  96. package/src/qingflow_mcp/cli/commands/builder.py +232 -75
  97. package/src/qingflow_mcp/cli/main.py +34 -0
  98. package/src/qingflow_mcp/public_surface.py +10 -0
  99. package/src/qingflow_mcp/server_app_builder.py +62 -34
  100. package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
  101. package/src/qingflow_mcp/solution/executor.py +2 -0
  102. package/src/qingflow_mcp/tools/ai_builder_tools.py +2649 -457
  103. package/src/qingflow_mcp/tools/record_tools.py +23 -11
@@ -0,0 +1,317 @@
1
+ # Builder Schema And Fields
2
+
3
+ Read this when the task is about app creation fields, schema updates, field types, data title, data cover, relation fields, or system fields.
4
+
5
+ ## Scope
6
+
7
+ Responsible for: `builder schema apply`, app creation through `form`, field type aliases, data title/cover, relation field shape, and existing-app schema maintenance.
8
+
9
+ Not responsible for: standalone form layout operations. For normal app creation, put fields directly under `form` so fields and placement are written together.
10
+
11
+ ## Main chain
12
+
13
+ ```text
14
+ app/package resolve -> schema apply with form -> app get fields/layout readback -> publish/readback verify
15
+ ```
16
+
17
+ For complete systems, use `builder schema apply --apps-file` with `{package_id, apps}` and put each app's fields and form layout under `apps[].form`. For one app, use `--form-file` in create mode. Use `add_fields/update_fields/remove_fields` only for later schema maintenance.
18
+
19
+ ## Demo files
20
+
21
+ | Scenario | Example |
22
+ |----------|---------|
23
+ | New single app `--form-file` | [schema_single_app_form_standard.example.json](../examples/schema/schema_single_app_form_standard.example.json) |
24
+ | New complete system `--apps-file` | [schema_multi_app_form_relation_layout.example.json](../examples/schema/schema_multi_app_form_relation_layout.example.json) |
25
+ | Existing-app field capability probe | [schema_apply_add_fields_all_types.json](../examples/schema/schema_apply_add_fields_all_types.json) |
26
+
27
+ ## Create app with `form`
28
+
29
+ `form` is the only recommended creation shape. Each section contains rows; each row contains field objects. For new apps, `form` is both the field schema and the form layout. Do not create a separate `layout` object and do not call `builder layout apply` after app creation just to place those fields.
30
+
31
+ ```json
32
+ [
33
+ {
34
+ "section": "基础信息",
35
+ "rows": [
36
+ [
37
+ {"name": "工单编号", "type": "text", "data_title": true},
38
+ {"name": "产品", "type": "text"},
39
+ {"name": "状态", "type": "select", "options": ["待排产", "生产中", "已完工"]}
40
+ ],
41
+ [
42
+ {"name": "计划数量", "type": "number"},
43
+ {"name": "计划完成日期", "type": "date"}
44
+ ]
45
+ ]
46
+ }
47
+ ]
48
+ ```
49
+
50
+ Single-app CLI:
51
+
52
+ ```bash
53
+ qingflow --json builder schema apply \
54
+ --package-id <PACKAGE_ID> \
55
+ --app-name "生产工单" \
56
+ --icon table \
57
+ --color blue \
58
+ --form-file /abs/path/form.json \
59
+ > tmp/schema_apply_production_order.json
60
+ ```
61
+
62
+ Complete-system `apps-file` item:
63
+
64
+ ```json
65
+ {
66
+ "client_key": "production_order",
67
+ "app_name": "生产工单",
68
+ "icon": "table",
69
+ "color": "blue",
70
+ "form": [
71
+ {
72
+ "section": "基础信息",
73
+ "rows": [[{"name": "工单编号", "type": "text", "data_title": true}]]
74
+ }
75
+ ]
76
+ }
77
+ ```
78
+
79
+ Complete-system CLI:
80
+
81
+ ```bash
82
+ qingflow --json builder schema apply \
83
+ --apps-file /abs/path/apps.json \
84
+ > tmp/schema_apply_system.json
85
+ ```
86
+
87
+ For the complete-system apps-file, use the object shape below. The same file carries app identity, fields, relation fields, and layout:
88
+
89
+ ```json
90
+ {
91
+ "package_id": 123456,
92
+ "apps": [
93
+ {
94
+ "client_key": "product",
95
+ "app_name": "产品台账",
96
+ "icon": "database",
97
+ "color": "blue",
98
+ "form": [
99
+ {
100
+ "section": "产品基础信息",
101
+ "rows": [
102
+ [
103
+ {"name": "产品编码", "type": "text", "data_title": true, "required": true},
104
+ {"name": "产品名称", "type": "text", "required": true},
105
+ {"name": "产品状态", "type": "select", "options": ["研发中", "量产", "停用"]}
106
+ ]
107
+ ]
108
+ }
109
+ ]
110
+ },
111
+ {
112
+ "client_key": "production_order",
113
+ "app_name": "生产工单",
114
+ "icon": "table",
115
+ "color": "emerald",
116
+ "form": [
117
+ {
118
+ "section": "工单基础信息",
119
+ "rows": [
120
+ [
121
+ {"name": "工单编号", "type": "text", "data_title": true, "required": true},
122
+ {
123
+ "name": "关联产品",
124
+ "type": "relation",
125
+ "target_app_ref": "product",
126
+ "relation_mode": "single",
127
+ "display_field": {"name": "产品编码"},
128
+ "visible_fields": [{"name": "产品名称"}, {"name": "产品状态"}]
129
+ },
130
+ {"name": "工单状态", "type": "select", "options": ["待排产", "生产中", "已完工"]}
131
+ ],
132
+ [
133
+ {"name": "计划数量", "type": "number"},
134
+ {"name": "计划完成日期", "type": "date"}
135
+ ]
136
+ ]
137
+ }
138
+ ]
139
+ }
140
+ ]
141
+ }
142
+ ```
143
+
144
+ ## Existing-app schema maintenance only
145
+
146
+ - Re-read fields before updating; selectors may use `name`, `field_id`, or `que_id`.
147
+ - Switch from `add_fields` to `update_fields` when a field already exists.
148
+ - Use `remove_fields` only when deletion is explicitly intended.
149
+ - If apply returns uncertain write state, re-read fields before retrying.
150
+ - Do not use this section for new complete-system creation. New apps should stay on the `apps[].form` path above.
151
+
152
+ Example patch:
153
+
154
+ ```json
155
+ {
156
+ "app_key": "APP_KEY",
157
+ "publish": true,
158
+ "add_fields": [{"name": "跟进日期", "type": "date"}],
159
+ "update_fields": [
160
+ {
161
+ "selector": {"name": "金额"},
162
+ "set": {"name": "订单金额", "required": true}
163
+ }
164
+ ],
165
+ "remove_fields": [{"name": "旧字段"}]
166
+ }
167
+ ```
168
+
169
+ ## Field type reference
170
+
171
+ > **口径**:`field.type` 枚举以 **`qingflow --json builder contract --tool-name app_schema_apply`**(及包内 `PublicFieldType`)为准;**形状校验**以 `qingflow_mcp` 的 **`FieldPatch`**(`builder_facade/models.py`)与 **`app_schema_apply` 编排**(`builder_facade/service.py`)为准。
172
+ > **CLI**:`qingflow [--profile NAME] builder schema apply [--app-key APP_KEY | 创建模式… | --apps-file 多应用对象] [--publish|--no-publish] [--form-file …] [--update-fields-file …] [--remove-fields-file …]`;**`qingflow` 未在 PATH 时**可用 `npx @qingflow-tech/qingflow-cli` 前缀,并把 `--profile` 放在 `builder` 之前。
173
+ > **新建应用主规则**:`form` 里必须有且仅有一个顶层字段标记 `data_title: true`;数据封面可选,只能在顶层 `attachment` 字段标记 `data_cover: true`。
174
+ > **权限**:包内新建应用按后端 `CreateAppBean` 链路只预检目标包 **AddAppAuth**;已有应用的字段/基础信息变更才走应用自身 **EditAppAuth**。
175
+
176
+ ## 0. 字段建模一眼决策表
177
+
178
+ 先按业务语义选字段类型。主路径可以写智能体友好的别名,CLI 会归一化;读回出现 canonical 类型不是失败。
179
+
180
+ | 业务语义 | 推荐写法 | 注意 |
181
+ | --- | --- | --- |
182
+ | 名称、标题、编号、短文本 | `text` | 新建应用必须且只能有一个顶层可读字段标记 `data_title: true` |
183
+ | 说明、备注、描述、长文本 | `multiline` | 写入归一化为 `long_text`;不要因为读回 `long_text` 而重建字段 |
184
+ | 状态、类型、等级、阶段、是否枚举 | `select` | 写入归一化为 `single_select`;必须同时定义 `options` |
185
+ | 标签、多选项、多个类别 | `multi_select` | `checkbox` 是兼容别名;必须定义 `options` |
186
+ | 数量、比例、分数、工时、百分比、时长 | `number` | 需要小数或计算时优先 `number` |
187
+ | 金额、费用、单价、预算 | `amount` | 只用于货币/金额语义,不要拿它存比例或普通数量 |
188
+ | 日期、计划日、截止日 | `date` | 同时需要时分秒才用 `datetime` |
189
+ | 负责人、审批人、参与人 | `member` | 不要创建“申请人/提交人”等平台系统字段 |
190
+ | 部门、组织 | `department` | 可按需要补 `department_scope` |
191
+ | 图片、文件、附件 | `attachment` | 只有顶层 `attachment` 可标记 `data_cover: true` |
192
+ | 跨应用业务对象关系 | `relation` | 同批应用只用 `target_app_ref`;已存在应用维护才用 `target_app_key`;`display_field` / `visible_fields` 必须写对象选择器 |
193
+
194
+ 禁止创建平台系统字段:`数据ID`、`编号`、`申请人`、`申请时间`、`创建人`、`创建时间`、`提交人`、`提交时间`、`更新时间`、`更新人`、`当前流程状态`、`当前处理人`、`当前处理节点`、`流程标题`。需要引用系统字段时,只在工具明确支持的位置引用,例如按钮 `source_field: "数据ID"`。
195
+
196
+ ---
197
+
198
+ ## 1. 全部 `field.type`(19 种)
199
+
200
+ 与契约一致时,搭建侧 **`add_fields[]` / `update_fields[]`** 可用类型为:
201
+
202
+ | `type` | 说明(搭建语义) |
203
+ |--------|------------------|
204
+ | `text` | 单行文本 |
205
+ | `long_text` | 多行文本 |
206
+ | `number` | 数字 |
207
+ | `amount` | 金额 |
208
+ | `date` | 日期 |
209
+ | `datetime` | 日期时间 |
210
+ | `member` | 成员 |
211
+ | `department` | 部门(可带 `department_scope`) |
212
+ | `single_select` | 单选 |
213
+ | `multi_select` | 多选 |
214
+ | `phone` | 电话 |
215
+ | `email` | 邮箱 |
216
+ | `address` | 地址 |
217
+ | `attachment` | 附件 |
218
+ | `boolean` | 是否 |
219
+ | `q_linker` | 远程查询 / 数据获取(**`q_linker_binding`**) |
220
+ | `code_block` | 代码块(**`code_block_binding`** + 编译后的 `code_block_config`) |
221
+ | `relation` | 关联记录(**`relation_mode`**:`single` \| `multiple`) |
222
+ | `subtable` | 子表(**`subfields[]`**) |
223
+
224
+ **`relation_mode`**:仅 **`relation`** 使用,取值为 **`single`** 或 **`multiple`**。一个应用可以有多个 `relation` 字段;不要因为 relation 数量超过 1 就改成文本字段。
225
+
226
+ ### 1.1 智能体友好字段类型别名
227
+
228
+ 主路径可以写更符合直觉的字段类型;工具写入前自动归一化,读回和排障时仍使用 canonical 类型:
229
+
230
+ | 智能体写法 | canonical 类型 |
231
+ |------------|----------------|
232
+ | `multiline` / `multiline_text` / `textarea` | `long_text` |
233
+ | `select` / `single_choice` / `dropdown` | `single_select` |
234
+ | `multi_select` / `multi_choice` / `multiple_choice` / `checkbox` | `multi_select` |
235
+
236
+ 完整映射以 `builder contract --tool-name app_schema_apply` 的 `$.contract.allowed_values["field.type_aliases"]` 为准。
237
+
238
+ ---
239
+
240
+ ## 2. 按类型的必填 / 常用可选(写意图)
241
+
242
+ | `type` | 通常必填 | 常见可选 / 约束 |
243
+ |--------|----------|-----------------|
244
+ | 标量与选择器 | `name` + `type`(+ 业务 `required` 等) | `description`、`required`;新建应用时其中一个顶层可读字段须 `data_title: true`;**`single_select` / `multi_select` 的 `options` 可用字符串数组或对象数组**,如 `["A", "B"]` 或 `[{"label":"A","value":"a"}]`,工具会归一化为选项文案 |
245
+ | `department` | 同左 | **`department_scope`**:`mode: all \| custom`;`custom` 时 **`departments[]`**(含 `dept_id` 等) |
246
+ | `relation` | 同批新建:**`target_app_ref`**;已有目标应用维护:**`target_app_key`**;另需 **`display_field`**、**`visible_fields[]`** | **`relation_mode`**;目标应用元数据不可读时可多写 **`name`** 降级 |
247
+ | `subtable` | **`subfields[]` 非空** | 子列递归同父级规则;更新已存在子列优先契约 **`subfield_updates`** |
248
+ | `q_linker` | **`q_linker_binding`**:`inputs`、`request`、**`outputs[]` 每项须含 `target_field`**(能解析到本表单字段) | `request.url` 等须符合**租户/后端远程查询策略**;读回 JSON 可能**缺** `outputs[].target_field`,会导致本地再编译失败(见 §5) |
249
+ | `code_block` | **`code_block_binding`**:`inputs`、`code`、**`outputs[]` + `target_field`**;代码体须能被规范识别 **`qf_output` 赋值** | **`auto_trigger`**、按钮文案;勿与 **`code_block_config.code_content`** 与 **`binding.code`** 冲突 |
250
+
251
+ 别名:契约会把 `title`/`label` 映射到 **`name`** 等;字段类型自然别名见 §1.1。
252
+
253
+ ### 2.1 `relation` 选择器形态
254
+
255
+ `relation` 的目标应用可以用字符串键,但展示字段选择器必须写对象,不要写裸字符串:
256
+
257
+ ```json
258
+ {
259
+ "name": "关联产品",
260
+ "type": "relation",
261
+ "target_app_ref": "product",
262
+ "relation_mode": "single",
263
+ "display_field": {"name": "产品编码"},
264
+ "visible_fields": [{"name": "产品名称"}, {"name": "产品线"}]
265
+ }
266
+ ```
267
+
268
+ 允许的目标应用写法:同批多应用只写 `target_app_ref`,已存在且已读回确认的目标应用才写 `target_app_key`。如果返回 `display_field` / `visible_fields` 的 Pydantic 错误,通常是把选择器写成了字符串;只修这一段字段 payload,不要重建应用或改 app_key。
269
+
270
+ ### 2.2 工作流状态字段
271
+
272
+ 要启用工作流的应用,字段阶段就创建一个明确的业务状态单选字段,例如 `状态`、`处理状态`、`审批状态`、`工单状态`、`计划状态`、`报工状态`、`单据状态`。领域结果字段不等价于流程状态;例如质量场景的 `检验结论` 只能表达结果,仍建议另建 `处理状态` 用于流程节点、视图和报表。
273
+
274
+ ---
275
+
276
+ ## 3. `builder schema apply` 场景矩阵
277
+
278
+ | 场景 | 必备 CLI 参数 | 说明 |
279
+ |------|----------------|------|
280
+ | 编辑已有应用 | `--app-key`;可选 `--no-publish` | **不要**与 `--package-id` 同用 |
281
+ | 包内新建应用 | `--package-id`、`--app-name`(或 title 映射)、`--form-file` | `form` 内必须有且仅有一个顶层可读字段标记 `data_title: true` |
282
+ | 多应用一次性新建 | `--apps-file`,文件顶层写 `package_id` + `apps`,每个应用写 `apps[].form` | 应用包/系统里有 2 个以上应用,或同批应用之间有 `relation` 时使用;多应用按 `app_name` 直接提交创建,不自动查重或按名称复用;重名/冲突按后端结果和写后读回处理;`apps[].client_key` 被同批 relation 的 `target_app_ref` 引用;不要在主链路使用 raw apps array、singleton wrapper array、单独 layout 或逐个创建后回填 `target_app_key` |
283
+ | 仅增字段 | `--add-fields-file`(JSON 数组) | 与 **`update_fields`/`remove_fields`** 可同次组合(以契约为准) |
284
+ | 改字段 | `--update-fields-file` | 每项 **`selector`**(`name`/`que_id`/`field_id`)+ **`set`** |
285
+ | 删字段 | `--remove-fields-file` | 每项至少 **`name`/`que_id`/`field_id`** 之一 |
286
+ | 可见性(新建/部分元数据) | `--visibility-file` | `mode` / `external_mode` / `selectors` 见交付文 §3.2 |
287
+ | 发布 | 默认或 `--publish`;探针常用 **`--no-publish`** | 与 **`app_publish_verify`** 配合 |
288
+
289
+ ---
290
+
291
+ ## 4. 仓库示例文件(维护参考)
292
+
293
+ | 内容 | 位置 |
294
+ |------|------|
295
+ | **完整系统新建主示例:多应用 + 同批 relation + form 布局** | [schema_multi_app_form_relation_layout.example.json](../examples/schema/schema_multi_app_form_relation_layout.example.json) |
296
+ | **19 种 `type` + `code_block` + `q_linker` + 1 个 `relation`(字段能力探针,不是新建主模板)** | [schema_apply_add_fields_all_types.json](../examples/schema/schema_apply_add_fields_all_types.json)(用于字段类型覆盖测试;正式新建应用优先用上文 `form`) |
297
+ | **`q_linker_example` / `code_block_example`**(契约内置形状) | `ai_builder_tools.py` 中 `app_schema_apply` 合约 |
298
+ | 最小新建字段(1 个 text 标题字段) | [schema_add_fields_minimal.example.json](../examples/schema/schema_add_fields_minimal.example.json) |
299
+ | 历史 scalar / complex 批测(可选) | [_batch_schema_scalar.json](../examples/schema/_batch_schema_scalar.json)、[_batch_schema_complex.json](../examples/schema/_batch_schema_complex.json) |
300
+
301
+ ---
302
+
303
+ ## 5. 实跑结论
304
+
305
+ **一次性新建应用**:`--package-id` + `--app-name` + `--form-file` 是当前推荐写法;`form` 同时表达字段和表单分组布局。字段类型覆盖测试文件只用于能力探针,不作为正式业务应用模板。
306
+
307
+ **一次性新建多个应用**:用 `builder schema apply --apps-file tmp/apps.json`,其中 `tmp/apps.json` 唯一主写法为 `{ "package_id": 123, "apps": [...] }`,每个 `apps[]` 写顶层 `client_key + app_name + icon + color + form`;多应用模式按 `app_name` 直接提交创建,不在工具内查重或按名称复用。若后端返回重名/冲突,或写入结果不确定,先读回应用包和字段,再决定复用、补齐缺失资源或询问用户。`apps[].client_key` 可被同批 relation 字段的 `target_app_ref` 引用,工具会编译成真实 `target_app_key`。CLI 内部会并发创建 app 壳,再并发写入每个 app 的完整 schema;智能体仍只写同一个 `apps-file`。这是应用包/系统搭建的默认路径,尤其适合“商机 + 订单 + 回款”“花名册 + 工时”等互相关联场景;不要为了拿 `app_key` 先逐个创建再二次补关联字段。
308
+
309
+ **限制(平台硬性)**:`--app-key` 向已有应用追加字段时须 **字段名不重复**;`relation` 字段数量不做“每应用只能一个”的智能体侧限制,按后端实际校验和写后读回为准。**`example.com`** 作 `q_linker` URL 易触发 **`46031`**,本清单改用 httpbin。**读回缺 `outputs[].target_field` 的 `q_linker`** 会拖死后续 `schema apply`,须修复或删除该题。
310
+
311
+ **排障**:`--json`;**`DUPLICATE_FIELD`**;真实写入失败看 `SCHEMA_APPLY_FAILED` 的 `backend_code`、`details.relation_field_count` 和读回矩阵。
312
+
313
+ ## 6. 交叉引用
314
+
315
+ - 交付主流程(读场 / 改场 / 发布):[reference/app-delivery-sop.md](./reference/app-delivery-sop.md)(类型速查与 `relation`/`q_linker`/`code_block` 要点)。
316
+ - 记录读写 `kind`(与搭建 `type` 不同系):[QINGFLOW_CLI_FIELD_DATA_TYPES.md](../core/QINGFLOW_CLI_FIELD_DATA_TYPES.md)。
317
+ - 主技能:[../SKILL.md](../../SKILL.md)。
@@ -0,0 +1,70 @@
1
+ # Builder Layout
2
+
3
+ Read this only when the task is about repairing or changing the form layout of an existing app.
4
+
5
+ ## Scope
6
+
7
+ Responsible for: `builder layout apply`, section titles, `rows` matrix, merge/replace mode, and existing-app layout repair.
8
+
9
+ Not responsible for: creating new apps, adding fields, or complete-system app creation. New apps must put layout directly in `form` through [30-schema-fields.md](./30-schema-fields.md).
10
+
11
+ Do not read this as part of the normal complete-system creation path. If the app is new, write field objects inside `form[].rows[]` and submit them with `builder schema apply`.
12
+
13
+ ## Main chain
14
+
15
+ ```text
16
+ existing app get fields -> existing app get layout -> prepare sections -> builder layout apply -> readback when needed
17
+ ```
18
+
19
+ ## Demo file
20
+
21
+ Use [layout_sections_full.example.json](../examples/layout/layout_sections_full.example.json) as the existing-app layout maintenance base. Replace `app_key` and field names after reading the app fields.
22
+
23
+ ## Public shape
24
+
25
+ For existing-app layout maintenance, use section `title + rows`. This is form layout: each `rows[]` item is a row of field names. Do not invent top-level `columns`, and do not use portal `x/y/cols/rows` here.
26
+
27
+ ```json
28
+ {
29
+ "app_key": "APP_KEY",
30
+ "mode": "merge",
31
+ "publish": true,
32
+ "sections": [
33
+ {
34
+ "title": "基础信息",
35
+ "rows": [
36
+ ["客户名称", "订单金额"],
37
+ ["状态", "负责人"]
38
+ ]
39
+ }
40
+ ]
41
+ }
42
+ ```
43
+
44
+ ## One-eye form layout rules
45
+
46
+ | Intent | Correct shape | Avoid |
47
+ | --- | --- | --- |
48
+ | Group fields on a form | `sections[].title + sections[].rows` | Portal `position.pc` / `x` / `y` / `cols` |
49
+ | Put fields on one horizontal form row | `["客户名称", "订单金额"]` inside `rows` | Top-level `columns` |
50
+ | Keep existing layout and add/update groups | `mode: "merge"` | `replace` unless intentionally rewriting everything |
51
+ | Repair missing/unknown field errors | Re-read `app get fields` and remove/correct names | Guessing field ids from old payload |
52
+
53
+ Short rule: **form layout rows arrange fields; portal rows arrange components. Do not mix the two.**
54
+
55
+ ## Update existing layout
56
+
57
+ - Prefer `mode: "merge"` unless intentionally replacing the entire layout.
58
+ - Re-read `app get fields` before writing; every field in `rows` must exist.
59
+ - Re-read `app get layout` when apply returns `partial_success` or layout validation details.
60
+ - Batch layout writes are for existing-app maintenance only; each `apps[]` item carries its own `app_key` and layout payload.
61
+ - If you are creating apps, stop and use `builder schema apply --apps-file` with `apps[].form` instead.
62
+
63
+ ## Common failures
64
+
65
+ | Failure | Action |
66
+ |---------|--------|
67
+ | `UNKNOWN_LAYOUT_FIELD` | Re-read fields and remove or correct the missing field name. |
68
+ | `DUPLICATE_LAYOUT_FIELD` | Keep each field in only one row. |
69
+ | `INCOMPLETE_LAYOUT` | Switch to `merge` unless replacing the whole layout intentionally. |
70
+ | repeated shape errors | Read `builder contract --tool-name app_layout_apply`; reuse the canonical section example. |