openyida 2026.10.16 → 2026.10.18-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 (70) hide show
  1. package/README.md +12 -5
  2. package/bin/yida.js +6 -1
  3. package/lib/agent/runtime-catalog.json +12 -12
  4. package/lib/app/check-prd-completeness.js +63 -1
  5. package/lib/app/form-navigation.js +7 -3
  6. package/lib/app/update-app.js +3 -0
  7. package/lib/core/command-manifest.js +27 -6
  8. package/lib/core/locales/en.js +68 -4
  9. package/lib/core/locales/zh.js +68 -4
  10. package/lib/core/process-approver-query.js +152 -0
  11. package/lib/core/query-data.js +19 -1
  12. package/lib/core/redact.js +4 -3
  13. package/lib/design-plan/entry-navigation.js +29 -2
  14. package/lib/design-plan/materialize.js +30 -4
  15. package/lib/integration/integration-api.js +30 -0
  16. package/lib/integration/integration-batch-data.js +177 -0
  17. package/lib/integration/integration-create.js +14 -12
  18. package/lib/integration/integration-data-retrieve.js +237 -0
  19. package/lib/integration/integration-detail-log.js +105 -0
  20. package/lib/integration/integration-message-roles.js +49 -0
  21. package/lib/integration/integration-readback.js +7 -0
  22. package/lib/integration/integration-spec-builder.js +48 -220
  23. package/lib/permission/get-permission.js +14 -6
  24. package/lib/permission/matrix-availability.js +46 -0
  25. package/lib/permission/package-type.js +29 -0
  26. package/lib/permission/permission-scope.js +119 -0
  27. package/lib/permission/permit-package-service.js +37 -4
  28. package/lib/permission/save-permission.js +112 -19
  29. package/lib/process/configure-process.js +12 -0
  30. package/lib/process/process-fields.js +22 -0
  31. package/lib/process/services/process-actor-config.js +37 -0
  32. package/lib/process/services/process-compiler.js +14 -9
  33. package/lib/process/services/process-field-permissions.js +101 -0
  34. package/lib/process/services/process-form-fields.js +94 -0
  35. package/lib/process/services/process-view-verifier.js +4 -0
  36. package/package.json +5 -5
  37. package/yida-skills/SKILL.md +14 -4
  38. package/yida-skills/skills/yida-app/SKILL.md +4 -0
  39. package/yida-skills/skills/yida-app/references/entry-navigation.md +14 -1
  40. package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +2 -0
  41. package/yida-skills/skills/yida-app/workflow/step-4-forms-processes.md +1 -1
  42. package/yida-skills/skills/yida-app/workflow/step-7-page-code.md +1 -1
  43. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +4 -2
  44. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +7 -1
  45. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +2 -0
  46. package/yida-skills/skills/yida-create-process/SKILL.md +3 -1
  47. package/yida-skills/skills/yida-data-management/SKILL.md +24 -2
  48. package/yida-skills/skills/yida-design/SKILL.md +1 -1
  49. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +6 -0
  50. package/yida-skills/skills/yida-flow-node-config/SKILL.md +48 -0
  51. package/yida-skills/skills/{yida-process-rule/references/approval-actions.md → yida-flow-node-config/references/actions.md} +14 -3
  52. package/yida-skills/skills/yida-flow-node-config/references/actors.md +115 -0
  53. package/yida-skills/skills/yida-flow-node-config/references/conditions-variables.md +116 -0
  54. package/yida-skills/skills/yida-flow-node-config/references/control.md +99 -0
  55. package/yida-skills/skills/yida-flow-node-config/references/data.md +56 -0
  56. package/yida-skills/skills/yida-flow-node-config/references/extensions.md +50 -0
  57. package/yida-skills/skills/yida-flow-node-config/references/fields.md +67 -0
  58. package/yida-skills/skills/yida-flow-node-config/references/human.md +79 -0
  59. package/yida-skills/skills/yida-flow-node-config/references/notifications.md +63 -0
  60. package/yida-skills/skills/yida-flow-node-config/references/start.md +49 -0
  61. package/yida-skills/skills/yida-form-permission/SKILL.md +68 -21
  62. package/yida-skills/skills/yida-form-permission/references/row-field-access.md +62 -0
  63. package/yida-skills/skills/yida-integration/SKILL.md +102 -439
  64. package/yida-skills/skills/yida-integration/references/batch-data.md +76 -0
  65. package/yida-skills/skills/yida-integration/references/cli-options.md +152 -0
  66. package/yida-skills/skills/yida-integration/references/integration-node-schemas.md +4 -1
  67. package/yida-skills/skills/yida-integration/references/spec-authoring.md +195 -0
  68. package/yida-skills/skills/yida-process-rule/SKILL.md +82 -416
  69. package/yida-skills/skills/yida-process-rule/references/official-component-nodes.md +64 -39
  70. package/yida-skills/skills-index.json +34 -5
package/README.md CHANGED
@@ -245,11 +245,14 @@ openyida configure-process APP_XXX FORM_XXX .cache/openyida/process/process.json
245
245
  openyida process preview APP_XXX PROC_INST_XXX --output .cache/openyida/process/process.html
246
246
  openyida data query form APP_XXX FORM_XXX --page 1 --size 20
247
247
  openyida data query form APP_XXX FORM_XXX --dynamic-order '{"dateField_xxx":"-"}'
248
+ openyida data query process APP_XXX FORM_XXX --current-approver USER_ID --count
248
249
  openyida data create form APP_XXX FORM_XXX --expect-form-name 客户 --expect-form-type receipt --data-file .cache/openyida/data-import/record.json
249
250
  openyida get-permission APP_XXX FORM_XXX
250
251
  ```
251
252
 
252
- Append and forward permissions are configured in the process definition through `nodes[].actions.normalActions/appendActions`. Both `create-process` and `configure-process` compile these settings into matching designer and runtime properties. See [approval action configuration](yida-skills/skills/yida-process-rule/references/approval-actions.md) for the JSON example, defaults, and verification limits.
253
+ `--current-approver` takes an exact userId, not a display name. It scans running instances and their current TODO records, counts each matching instance once, and respects the current login's server-authorized data scope. Omit `--count` to include matching instance data. An incomplete scan or permission failure is reported as an error; the result does not claim application-wide visibility.
254
+
255
+ Append and forward permissions are configured in the process definition through `nodes[].actions.normalActions/appendActions`. Both `create-process` and `configure-process` compile these settings into matching designer and runtime properties. See [approval action configuration](yida-skills/skills/yida-flow-node-config/references/actions.md) for the JSON example, defaults, and verification limits.
253
256
 
254
257
  `configure-process` 的流程 JSON 中,审批人可配置为发起人、指定成员、指定角色、部门主管或直属主管,例如:
255
258
 
@@ -387,6 +390,8 @@ A zero-dependency local dashboard (`npm run eval:dashboard`, then open `http://1
387
390
 
388
391
  ### Connectors, Integrations, and Reports
389
392
 
393
+ Automation spec `sendMessage` nodes accept `toRoles: [{"roleCode":"REAL_ROLE_ID","roleName":"Finance"}]` for NORMAL messages, alongside users and member fields. Process approval, operator, and CC nodes can also select roles. Role selection differs from conditional actor selection, which does not yet have a complete CLI shorthand. See the `yida-flow-node-config` skill for shared node guidance.
394
+
390
395
  ```bash
391
396
  openyida connector smart-create --curl "curl https://api.example.com/users"
392
397
  openyida connector list
@@ -476,7 +481,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
476
481
  | `openyida list-forms <appType> [--keyword <text>]` | List forms/pages in an app |
477
482
  | `openyida aggregate-table <list\|create-empty\|inspect\|preview\|save\|publish\|status> <appType> ...` | Manage aggregate tables (virtualView) |
478
483
  | `openyida get-schema <appType> <formUuid\|--all> [--summary-json\|--field-map-json\|--analysis-json]` | Get one form Schema or all form Schemas |
479
- | `openyida check-prd-completeness <prd.md> --app-type <appType> [--build-manifest <file>] [--json]` | Check PRD page/resource count risk |
484
+ | `openyida check-prd-completeness <prd.md> --app-type <appType> [--build-manifest <file>] [--json]` | Check resources, frontend menu hiding and application theme delivery |
480
485
  | `openyida check-design <design.md> [--prd <prd.md>] [--base-dir <dir>] [--json]` | Validate design documents, theme tokens and PRD handoff |
481
486
  | `openyida er <appType> [--format mermaid\|json] [--output file] [--include-system] [--include-pages]` | Export app entity relationship diagram |
482
487
  | `openyida create-page <appType> "<name>" [--mode dashboard] [--hide-nav] [--locale zh_CN\|en_US\|ja_JP] [--open\|--no-open]` | Create a custom display page |
@@ -496,8 +501,8 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
496
501
  | `openyida basic-info <overview\|commodity\|grant\|capacity\|quota\|abs-path\|dataflow\|i18n\|domain>` | Query organization basic info, capacity, quotas, and domain settings |
497
502
  | `openyida read-dingtalk-doc <docUrl> [--output <file>] [--json]` | Fetch Markdown content from a DingTalk document |
498
503
  | `openyida read-dingtalk-tingji <taskUuid> [--json]` | Fetch DingTalk Tingji details by task UUID |
499
- | `openyida get-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--json]` | Query form permission config |
500
- | `openyida save-permission <appType> <formUuid> --package-uuid <packageUuid> [--data-permission <json>\|--action-permission <json>\|--field-permission <json>]` | Save form permission config |
504
+ | `openyida get-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--package-type <FORM_PACKAGE_VIEW\|FORM_PACKAGE_START>] [--check-matrix] [--json]` | Query form permission config |
505
+ | `openyida save-permission <appType> <formUuid> [--package-type <FORM_PACKAGE_VIEW\|FORM_PACKAGE_START>] [--package-uuid <packageUuid>\|--create --name <name>] [--data-permission <json>] [--action-permission <json>] [--field-permission <json>] [--members <userIds>\|--roles <roleIds>\|--all-members\|--matrix <json>] [--confirm-member-replace] [--owner-field <fieldId>] [--field-access <fieldId:view\|edit\|hidden\|encrypt>] [--field-default <access>] [--dry-run]` | Save form permission config |
501
506
  | `openyida corp-manager <search-user\|list\|add\|remove\|address-book> ...` | Manage platform admins and address book permissions |
502
507
  | `openyida agent-center <list\|create\|update\|cancel\|range\|search-user> ...` | Manage process and departure delegation |
503
508
 
@@ -509,6 +514,7 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
509
514
  | `openyida create-process <appType> <formTitle> <fieldsJsonFile> <processDefinitionFile> [--replace] \| create-process <appType> --formUuid <formUuid> <processDefinitionFile> [--replace]` | Create process form (all-in-one); Supports append/forward via JSON nodes[].actions.normalActions/appendActions |
510
515
  | `openyida ai-form-setting <get\|fields\|models\|enable\|disable\|save> <appType> ...` | Manage process form AI approval prompts |
511
516
  | `openyida process preview <appType> ...` | Preview process instance (visual flowchart) |
517
+ | `openyida process fields <appType> <formUuid> [--json]` | Check process designer field loading and subtable field paths |
512
518
 
513
519
  ### Page Config & Sharing
514
520
 
@@ -550,12 +556,13 @@ Run `openyida --help` or `openyida <command> --help` for detailed usage.
550
556
 
551
557
  | Command | Description |
552
558
  |---------|-------------|
553
- | `openyida integration create <appType> ... [--spec file.json] [--connector-system-token-app <appType>]` | Create integration automation flow |
559
+ | `openyida integration create <appType> <formUuid> <flowName> [--spec file.json] [--publish] [--connector-system-token-app <appType>]` | Create integration automation flow |
554
560
  | `openyida integration update <appType> <formUuid> <processCode> --spec <desired-spec.json> [--publish]` | Probe integration update capability (currently blocked without full readback) |
555
561
  | `openyida integration list <appType> [--flow-types 1,2,3,5,6] [--form-uuid <uuid>] [--status y\|n] [--json]` | List integration automation flows |
556
562
  | `openyida integration enable <appType> <formUuid> <processCode>` | Enable integration automation flow |
557
563
  | `openyida integration disable <appType> <formUuid> <processCode>` | Disable integration automation flow |
558
564
  | `openyida integration check <appType...>` | Check abnormal integration automation run logs |
565
+ | `openyida integration detail-log <appType> <procInstId> [--json] [--include-params]` | View integration automation run log details |
559
566
  | `openyida integration diagnose (--text <text>\|--file <path>\|--rules) [--json]` | Diagnose integration automation tickets and common pitfalls |
560
567
  | `openyida dws <command> [args]` | DingTalk CLI (contacts/calendar/todo/approval etc.) |
561
568
  | `openyida dws contact user search --keyword <text>` | DingTalk CLI (contacts/calendar/todo/approval etc.) |
package/bin/yida.js CHANGED
@@ -1082,7 +1082,9 @@ async function main() {
1082
1082
  const subCommand = args[0];
1083
1083
  const subArgs = args.slice(1);
1084
1084
 
1085
- if (subCommand === 'preview') {
1085
+ if (subCommand === 'fields') {
1086
+ await require('../lib/process/process-fields').run(subArgs);
1087
+ } else if (subCommand === 'preview') {
1086
1088
  if (subArgs.length < 2) {
1087
1089
  throwCliUsage(t('cli.process_preview_usage'), t('cli.process_preview_example'));
1088
1090
  }
@@ -1247,6 +1249,9 @@ async function main() {
1247
1249
  } else if (subCommand === 'check') {
1248
1250
  const { run: runIntegrationCheck } = require('../lib/integration/integration-check');
1249
1251
  await runIntegrationCheck(subArgs);
1252
+ } else if (subCommand === 'detail-log') {
1253
+ const { run: runIntegrationDetailLog } = require('../lib/integration/integration-detail-log');
1254
+ await runIntegrationDetailLog(subArgs);
1250
1255
  } else if (subCommand === 'diagnose' || subCommand === 'doctor') {
1251
1256
  const { run: runIntegrationDiagnose } = require('../lib/integration/integration-diagnose');
1252
1257
  await runIntegrationDiagnose(subArgs);
@@ -13,33 +13,33 @@
13
13
  "platform": "darwin",
14
14
  "arch": "arm64",
15
15
  "packageName": "@openyida/local-agent-runtime-darwin-arm64",
16
- "packageVersion": "0.1.3",
17
- "runtimeVersion": "0.1.3",
18
- "manifestSha256": "1a9f5e148491c350457a41f095de9598775a2a349d872c43877c9fad63c09e28"
16
+ "packageVersion": "0.1.4",
17
+ "runtimeVersion": "0.1.4",
18
+ "manifestSha256": "48dc2a4473422c663e3330840c4f96e6646b2ff70ed61452fef8f1e68bf4a258"
19
19
  },
20
20
  {
21
21
  "platform": "darwin",
22
22
  "arch": "x64",
23
23
  "packageName": "@openyida/local-agent-runtime-darwin-x64",
24
- "packageVersion": "0.1.3",
25
- "runtimeVersion": "0.1.3",
26
- "manifestSha256": "46918d51efd40b73a645487525f2f7bdca94124ffb3ad6cdae6e9641f28b3963"
24
+ "packageVersion": "0.1.4",
25
+ "runtimeVersion": "0.1.4",
26
+ "manifestSha256": "1c93114b7fc9f2af7de1088d801ccbd3eaf32aabd967b5bd56917e8c1ec0661b"
27
27
  },
28
28
  {
29
29
  "platform": "win32",
30
30
  "arch": "x64",
31
31
  "packageName": "@openyida/local-agent-runtime-win32-x64",
32
- "packageVersion": "0.1.3",
33
- "runtimeVersion": "0.1.3",
34
- "manifestSha256": "64d471a37c54650e25c214e08d7ca7fa8dde068decfcbe71bd8abcbb2b7e74c6"
32
+ "packageVersion": "0.1.4",
33
+ "runtimeVersion": "0.1.4",
34
+ "manifestSha256": "13a7fc58b87a7f3f2592ba5239992c415463ab8b3fbf32312944db8c611fb813"
35
35
  },
36
36
  {
37
37
  "platform": "win32",
38
38
  "arch": "arm64",
39
39
  "packageName": "@openyida/local-agent-runtime-win32-arm64",
40
- "packageVersion": "0.1.3",
41
- "runtimeVersion": "0.1.3",
42
- "manifestSha256": "7b1ff527dc54285084eac0773d273fdfb892ce5ca352a810767c64eefc8e59c0"
40
+ "packageVersion": "0.1.4",
41
+ "runtimeVersion": "0.1.4",
42
+ "manifestSha256": "49e63f81730e1ee495863a48b9e90f687e9529e700788665196c169a630ed094"
43
43
  }
44
44
  ]
45
45
  }
@@ -268,8 +268,19 @@ function extractResources(markdown) {
268
268
  }
269
269
 
270
270
  function parsePrdMarkdown(markdown) {
271
+ const navigationVisibility = [];
272
+ let applicationTheme;
273
+ for (const match of String(markdown || '').matchAll(/```json\s*\n([\s\S]*?)\n```/g)) {
274
+ try {
275
+ const handoff = JSON.parse(match[1]);
276
+ if (Array.isArray(handoff.navigationVisibility)) {navigationVisibility.push(...handoff.navigationVisibility);}
277
+ if (Object.prototype.hasOwnProperty.call(handoff, 'applicationTheme')) {applicationTheme = handoff.applicationTheme;}
278
+ } catch { /* Other fenced examples are not the structured execution handoff. */ }
279
+ }
271
280
  return {
272
281
  resources: extractResources(markdown),
282
+ navigationVisibility,
283
+ ...(applicationTheme !== undefined ? { applicationTheme } : {}),
273
284
  };
274
285
  }
275
286
 
@@ -451,6 +462,7 @@ async function evaluatePrdCompleteness(markdown, options = {}, deps = {}) {
451
462
  const parsedManifest = parseBuildManifest(options.buildManifest);
452
463
  const items = [];
453
464
  const assetExecution = auditAssetExecution(options.buildManifest?.assetExecution, options.buildManifest?.assetTasks);
465
+ let themeVerification;
454
466
 
455
467
  function addItem(id, source, status, severity, message, details = {}) {
456
468
  items.push(makeRiskItem(id, source, status, severity, message, details));
@@ -465,6 +477,7 @@ async function evaluatePrdCompleteness(markdown, options = {}, deps = {}) {
465
477
  verdict,
466
478
  mode: 'delivery_risk_radar',
467
479
  assetExecution,
480
+ ...(themeVerification ? { themeVerification } : {}),
468
481
  appType,
469
482
  prdPath: options.prdPath || '',
470
483
  buildManifestPath: options.buildManifestPath || '',
@@ -510,7 +523,7 @@ async function evaluatePrdCompleteness(markdown, options = {}, deps = {}) {
510
523
  const fetchForms = deps.fetchForms || fetchFormPageList;
511
524
  let forms = [];
512
525
  try {
513
- forms = await fetchForms(appType, authRef);
526
+ forms = await fetchForms(appType, authRef, { includeNavigation: true });
514
527
  } catch (error) {
515
528
  addItem('app_resource_list_read_failed', 'remote.resource_list', 'fail', 'blocker', '目标应用资源列表读取失败,无法执行数量完整性检查', {
516
529
  expected: { appType, readable: true },
@@ -522,6 +535,55 @@ async function evaluatePrdCompleteness(markdown, options = {}, deps = {}) {
522
535
  const actualResources = forms.map(makeActualResource);
523
536
  const manifestResources = parsedManifest.resources.filter(resource => resource.required);
524
537
 
538
+ if (parsedPrd.applicationTheme !== undefined) {
539
+ const expected = parsedPrd.applicationTheme;
540
+ const { normalizeCssColorToHex } = require('./custom-theme');
541
+ const expectedColor = normalizeCssColorToHex(expected?.themeColor);
542
+ themeVerification = { configurationReadback: false, verified: false, runtimeVerified: false };
543
+ try {
544
+ if (!expectedColor || !['light', 'dark'].includes(expected?.navTheme)) {throw new Error('INVALID_THEME_EXPECTATION');}
545
+ const { fetchCurrentApp, getThemeSettings, getNavigationSettings } = require('./update-app');
546
+ const app = await (deps.fetchApp || fetchCurrentApp)(appType, authRef);
547
+ if (!app || typeof app !== 'object' || Array.isArray(app) || !Object.keys(app).length) {throw new Error('APP_SETTINGS_UNAVAILABLE');}
548
+ const settings = getThemeSettings(app);
549
+ const rawNav = getNavigationSettings(app, ['navTheme']).navTheme;
550
+ const actual = {
551
+ colour: settings.colour,
552
+ themeColor: normalizeCssColorToHex(settings.themeColor),
553
+ navTheme: ['white', 'gray'].includes(rawNav) ? 'light' : rawNav,
554
+ customThemeEnabled: settings.customThemeStyle?.enabled,
555
+ hasCssUrl: typeof settings.customThemeStyle?.cssUrl === 'string' && !!settings.customThemeStyle.cssUrl.trim(),
556
+ };
557
+ const matched = actual.colour === 'custom' && actual.themeColor === expectedColor
558
+ && actual.navTheme === expected.navTheme && actual.customThemeEnabled === true && actual.hasCssUrl;
559
+ themeVerification = { ...themeVerification, configurationReadback: true, verified: matched, expected, actual };
560
+ if (!matched) {
561
+ addItem('application_theme_mismatch', 'remote.application_theme', 'fail', 'blocker',
562
+ t('check_prd_completeness.application_theme_mismatch'), { expected, actual });
563
+ }
564
+ } catch {
565
+ addItem('application_theme_not_checked', 'remote.application_theme', 'not_checked', 'warning',
566
+ t('check_prd_completeness.application_theme_not_checked'), { expected });
567
+ }
568
+ }
569
+
570
+ // Reuse the resource-list readback. Page renderNav and menu visibility are
571
+ // independent; a successful publication cannot prove the latter.
572
+ for (const expected of parsedPrd.navigationVisibility) {
573
+ const matches = parsedManifest.resources.filter(resource => resource.name === expected?.name && resource.kind === 'display-page');
574
+ const ids = [...new Set(matches.map(resource => resource.formUuid).filter(Boolean))];
575
+ const actual = ids.length === 1 ? forms.find(form => form.formUuid === ids[0]) : undefined;
576
+ const known = value => typeof value === 'boolean';
577
+ const valid = expected?.hidden === true && expected?.mobileHidden === true;
578
+ if (valid && actual && (actual.hidden === false || actual.mobileHidden === false)) {
579
+ addItem('frontend_navigation_visible', 'remote.navigation', 'fail', 'blocker',
580
+ t('check_prd_completeness.frontend_navigation_visible', expected.name), { expected, actual });
581
+ } else if (!valid || !actual || !known(actual.hidden) || !known(actual.mobileHidden)) {
582
+ addItem('frontend_navigation_not_checked', 'prd.navigationVisibility', 'not_checked', 'warning',
583
+ t('check_prd_completeness.frontend_navigation_not_checked', expected?.name || ''), { expected, actual: actual || null });
584
+ }
585
+ }
586
+
525
587
  if (!options.buildManifest) {
526
588
  addItem('build_manifest_missing', 'build_manifest', 'not_checked', 'info', '未提供 build-manifest.json,只能基于 PRD 资源 hints 做风险提示', {
527
589
  expected: '--build-manifest <file>',
@@ -8,7 +8,7 @@ function resolveLocalizedText(value, fallback = '') {
8
8
  return parseYidaI18n(value, fallback, { parseJson: false });
9
9
  }
10
10
 
11
- function normalizeFormNavigationNode(node) {
11
+ function normalizeFormNavigationNode(node, options = {}) {
12
12
  if (!node || node.navType === 'SYSTEM' || !node.formUuid) {
13
13
  return null;
14
14
  }
@@ -21,10 +21,14 @@ function normalizeFormNavigationNode(node) {
21
21
  ),
22
22
  formType: node.formType || '',
23
23
  pathName: node.pathName || '',
24
+ ...(options.includeNavigation ? {
25
+ hidden: ['y', true].includes(node.hidden) ? true : ['n', false].includes(node.hidden) ? false : null,
26
+ mobileHidden: ['y', true].includes(node.mobileHidden) ? true : ['n', false].includes(node.mobileHidden) ? false : null,
27
+ } : {}),
24
28
  };
25
29
  }
26
30
 
27
- async function fetchFormPageList(appType, authRef) {
31
+ async function fetchFormPageList(appType, authRef, options = {}) {
28
32
  const result = await createYidaClient({ authRef }).get(
29
33
  `/dingtalk/web/${appType}/query/formnav/getFormNavigationListByOrder.json`,
30
34
  { _api: 'Nav.queryList', _mock: false }
@@ -39,7 +43,7 @@ async function fetchFormPageList(appType, authRef) {
39
43
 
40
44
  const items = Array.isArray(result.content) ? result.content : [];
41
45
  return items
42
- .map(normalizeFormNavigationNode)
46
+ .map(node => normalizeFormNavigationNode(node, options))
43
47
  .filter(Boolean);
44
48
  }
45
49
 
@@ -819,6 +819,9 @@ async function run(args) {
819
819
  }
820
820
 
821
821
  module.exports = {
822
+ fetchCurrentApp,
823
+ getThemeSettings,
824
+ getNavigationSettings,
822
825
  run,
823
826
  parseArgs,
824
827
  hasShellUpdate,
@@ -424,9 +424,11 @@ const COMMAND_SIDE_EFFECTS = new Map([
424
424
  'get-permission',
425
425
  'get-schema',
426
426
  'integration.check',
427
+ 'integration.detail-log',
427
428
  'integration.list',
428
429
  'list-forms',
429
430
  'process.preview',
431
+ 'process.fields',
430
432
  'read-dingtalk-tingji',
431
433
  'report.inspect',
432
434
  'verify-short-url',
@@ -672,10 +674,12 @@ const COMMAND_PERMISSIONS = new Map([
672
674
  'get-permission',
673
675
  'get-schema',
674
676
  'integration.check',
677
+ 'integration.detail-log',
675
678
  'integration.diagnose',
676
679
  'integration.list',
677
680
  'list-forms',
678
681
  'process.preview',
682
+ 'process.fields',
679
683
  'read-dingtalk-tingji',
680
684
  'report.inspect',
681
685
  'verify-short-url',
@@ -1493,7 +1497,7 @@ const COMMAND_GROUPS = [
1493
1497
  }),
1494
1498
  command('check-prd-completeness', ['check-prd-completeness'], 'check-prd-completeness <prd.md> --app-type <appType> [--build-manifest <file>] [--json]', 'help.cmd_check_prd_completeness', { managedRun: { scope: 'app', appParser: 'prd-completeness' },
1495
1499
  output: 'json',
1496
- notes: ['Checks resource counts and optional build-manifest.assetExecution recorded intervals. Include materialize.assetTasks and taskState records plus businessWork startedAt/endedAt; missing dispatch proof, missing overlap or assets before business in synchronous fallback produces needs_review. This is record consistency, not independent verification of host events.'],
1500
+ notes: ['Checks resource counts and optional build-manifest.assetExecution recorded intervals. Include materialize.assetTasks and taskState records plus businessWork startedAt/endedAt; missing dispatch proof, missing overlap or assets before business in synchronous fallback produces needs_review. This is record consistency, not independent verification of host events.', 'When the PRD execution handoff contains navigationVisibility, resolves frontend display pages through build-manifest resource IDs and checks PC/mobile menu hiding using the same remote resource-list read. A visible menu fails; unknown visibility or missing ID binding needs review. Checks PRD applicationTheme against live application settings: selected brand color, custom CSS enabled with a resource URL, and navigation tone. Mismatch fails; unreadable settings or invalid expectations need review. Reuses update-app readback field handling. Does not verify page renderNav, actual CSS content/loading, default routes or browser appearance.'],
1497
1501
  }),
1498
1502
  command('check-design', ['check-design'], 'check-design <design.md> [--prd <prd.md>] [--base-dir <dir>] [--json]', 'help.cmd_check_design', { managedRun: { scope: 'local' },
1499
1503
  requiresLogin: false,
@@ -1625,13 +1629,14 @@ const COMMAND_GROUPS = [
1625
1629
  } },
1626
1630
  } },
1627
1631
  output: 'json',
1628
- noteKeys: ['help.data_notes'],
1632
+ noteKeys: ['help.data_notes', 'query_data.approver_query_help'],
1629
1633
  notes: [
1630
1634
  'Each condition uses key (field ID), componentName, type, operator and value. Query types: TextField/TextareaField/TableField TEXT; NumberField/RateField/DateField/CascadeDateField DOUBLE; RadioField/SelectField/CheckboxField/MultiSelectField/DepartmentSelectField ARRAY; EmployeeField/CascadeSelectField/CitySelectField STRING; ImageField/AttachmentField TEXT.',
1631
1635
  'Ordinary form searchFormDatas accepts AND condition arrays via --search-json/--search-file. DateField: type DOUBLE, is/is_not, value ""; zero is filled. Query range endpoints as DateField with .start/.end: both empty means unfilled, both filled means complete.',
1632
1636
  'Use synchronized NumberField counts (eq 0/gt 0) for any filled endpoint, multi-choice options or subform rows; maintain every write entry and backfill history. --resolve-aliases supports rangeAlias.start/.end and parentId aliases. Use server pagination and dynamicOrder. Guide: yida-skills/references/query-condition-guide.md; sample: yida-data-management empty-query.',
1633
1637
  ],
1634
1638
  examples: [
1639
+ 'openyida data query process APP_XXX FORM_XXX --current-approver USER_ID --count',
1635
1640
  'openyida data query form APP_XXX FORM_XXX --page 1 --size 20 --search-json \'[{"key":"dateField_due","componentName":"DateField","type":"DOUBLE","operator":"is","value":""}]\'',
1636
1641
  'openyida data create form APP_XXX FORM_XXX --expect-form-name 客户 --expect-form-type receipt --data-json \'{"textField_name":"客户 A","dateField_followUp":1787932800000}\'',
1637
1642
  'openyida data delete form APP_XXX FORM_XXX --inst-id FINST_XXX --expect-form-name 客户 --expect-form-type receipt --confirm --json',
@@ -1647,8 +1652,9 @@ const COMMAND_GROUPS = [
1647
1652
  command('read-dingtalk-tingji', ['read-dingtalk-tingji'], 'read-dingtalk-tingji <taskUuid> [--json]', 'help.cmd_read_dingtalk_tingji', { managedRun: { scope: 'selected_input', inputType: 'tingji', inputField: 'taskUuid' },
1648
1653
  output: 'json',
1649
1654
  }),
1650
- command('get-permission', ['get-permission'], 'get-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--json]', 'help.cmd_get_permission', { managedRun: { scope: 'app', appPosition: 0 } }),
1651
- command('save-permission', ['save-permission'], 'save-permission <appType> <formUuid> --package-uuid <packageUuid> [--data-permission <json>|--action-permission <json>|--field-permission <json>]', 'help.cmd_save_permission', { managedRun: { scope: 'app', appPosition: 0, mutation: { operation: 'update_form_permission', formUuidPosition: 1 } },
1655
+ command('get-permission', ['get-permission'], 'get-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--package-type <FORM_PACKAGE_VIEW|FORM_PACKAGE_START>] [--check-matrix] [--json]', 'help.cmd_get_permission', { managedRun: { scope: 'app', appPosition: 0 }, noteKeys: ['permission_scope.matrix_notice'] }),
1656
+ command('save-permission', ['save-permission'], 'save-permission <appType> <formUuid> [--package-type <FORM_PACKAGE_VIEW|FORM_PACKAGE_START>] [--package-uuid <packageUuid>|--create --name <name>] [--data-permission <json>] [--action-permission <json>] [--field-permission <json>] [--members <userIds>|--roles <roleIds>|--all-members|--matrix <json>] [--confirm-member-replace] [--owner-field <fieldId>] [--field-access <fieldId:view|edit|hidden|encrypt>] [--field-default <access>] [--dry-run]', 'help.cmd_save_permission', { managedRun: { scope: 'app', appPosition: 0, mutation: { operation: 'update_form_permission', formUuidPosition: 1, forbiddenFlags: ['--dry-run'] } },
1657
+ noteKeys: ['permission_scope.options_help', 'permission_scope.overlap_notice'],
1652
1658
  examples: [
1653
1659
  'openyida get-permission APP_XXX FORM_XXX --json',
1654
1660
  'openyida save-permission APP_XXX FORM_XXX --package-uuid PACKAGE_XXX --data-permission \'{"dataRange":"ORIGINATOR"}\'',
@@ -1689,6 +1695,11 @@ const COMMAND_GROUPS = [
1689
1695
  aliases: ['ai-approve', 'aiFormSetting'],
1690
1696
  }),
1691
1697
  command('process.preview', ['process', 'preview'], 'process preview <appType> ...', 'help.cmd_process_preview', { managedRun: { scope: 'app', appPosition: 1 } }),
1698
+ command('process.fields', ['process', 'fields'], 'process fields <appType> <formUuid> [--json]', 'help.cmd_process_fields', {
1699
+ managedRun: { scope: 'app', appPosition: 1 },
1700
+ permission: permission('allow', 'read', { reason: 'Read-only process designer field diagnostics.' }),
1701
+ output: 'json',
1702
+ }),
1692
1703
  ],
1693
1704
  },
1694
1705
  {
@@ -1736,7 +1747,12 @@ const COMMAND_GROUPS = [
1736
1747
  id: 'integration',
1737
1748
  titleKey: 'help.group_integration',
1738
1749
  commands: [
1739
- command('integration.create', ['integration', 'create'], 'integration create <appType> ... [--spec file.json] [--connector-system-token-app <appType>]', 'help.cmd_integration', { managedRun: { scope: 'app', appPosition: 1, mutation: { operation: 'create_process' } } }),
1750
+ command('integration.create', ['integration', 'create'], 'integration create <appType> <formUuid> <flowName> [--spec file.json] [--publish] [--connector-system-token-app <appType>]', 'help.cmd_integration', { managedRun: { scope: 'app', appPosition: 1, mutation: { operation: 'create_process' } },
1751
+ examples: [
1752
+ 'openyida integration create APP_XXX FORM_XXX "批量复制明细" --spec .cache/openyida/task/integration/batch-data.json',
1753
+ 'openyida integration create APP_XXX FORM_XXX "库存不足通知" --receivers USER_ID --trigger-condition "numberField_stock:当前库存:LessThan:numberField_minStock:NumberField:processVar"',
1754
+ ],
1755
+ }),
1740
1756
  command('integration.update', ['integration', 'update'], 'integration update <appType> <formUuid> <processCode> --spec <desired-spec.json> [--publish]', 'help.cmd_integration_update', { managedRun: { scope: 'app', appPosition: 1 },
1741
1757
  requiresLogin: false,
1742
1758
  output: 'json',
@@ -1751,6 +1767,9 @@ const COMMAND_GROUPS = [
1751
1767
  output: 'json',
1752
1768
  }),
1753
1769
  command('integration.check', ['integration', 'check'], 'integration check <appType...>', 'help.cmd_integration_check', { managedRun: { scope: 'app', appPosition: 1 } }),
1770
+ command('integration.detail-log', ['integration', 'detail-log'], 'integration detail-log <appType> <procInstId> [--json] [--include-params]', 'help.cmd_integration_detail_log', { managedRun: { scope: 'app', appPosition: 1 },
1771
+ output: 'text|json',
1772
+ }),
1754
1773
  command('integration.diagnose', ['integration', 'diagnose'], 'integration diagnose (--text <text>|--file <path>|--rules) [--json]', 'help.cmd_integration_diagnose', { managedRun: { scope: 'local' },
1755
1774
  requiresLogin: false,
1756
1775
  output: 'text|json',
@@ -2084,7 +2103,9 @@ function summarizeLocalizedCommands(commands) {
2084
2103
  derived_summary: 'execution.entryModeSummary is generated for PRD and preview from the selected mode; do not author it in build-plan.json.',
2085
2104
  roles: ['service', 'management', 'workspace'],
2086
2105
  entry_required_fields: ['key', 'name', 'role', 'menu', 'defaultMenuKey'],
2087
- service_page_binding: 'sceneKey of the frontend page; standalone by default, preserve explicit platform-shell',
2106
+ service_page_binding: 'sceneKey of the frontend page; standalone by default, preserve explicit platform-shell. Missing page navigation for a multi-task service entry derives a custom top menu; single-task entries and explicit none retain their choice.',
2107
+ application_theme_handoff: 'Derived applicationTheme in the PRD execution handoff records final design themeColor/navTheme/designFile for full builds. Fast records the same contract. check-prd-completeness reads current application settings; publish does not install application themes. Resource-only changes add no theme task. Configuration matching is separate from browser acceptance and custom-page token consumption.',
2108
+ menu_visibility_handoff: 'Derived navigationVisibility in the PRD execution handoff, not a build-plan input: service-management hides frontend-only standalone display pages in PC/mobile platform menus. Shared forms and explicitly management-linked pages are preserved. Resolve names to build-manifest resource IDs; nav-group hide and readback are separate from page renderNav=false. Resource-only changes schedule no menu hiding.',
2088
2109
  page_navigation_policy: getPageNavigationContract(),
2089
2110
  local_menu_binding: 'Every entry containing local menus, including management/workspace, requires sceneKey matching exactly one page; each local menu requires resource equal to that page name and a nonempty viewKey.',
2090
2111
  menu_target_types: ['local', 'submission', 'page', 'custom'],
@@ -141,7 +141,7 @@ module.exports = {
141
141
  cmd_list_forms: 'List forms/pages in an app',
142
142
  cmd_aggregate_table: 'Manage aggregate tables (virtualView)',
143
143
  cmd_get_schema: 'Get one form Schema or all form Schemas',
144
- cmd_check_prd_completeness: 'Check PRD page/resource count risk',
144
+ cmd_check_prd_completeness: 'Check resources, frontend menu hiding and application theme delivery',
145
145
  cmd_er: 'Export app entity relationship diagram',
146
146
  cmd_create_page: 'Create a custom display page',
147
147
  cmd_build_page: 'Build Yida-compatible page source',
@@ -199,6 +199,7 @@ module.exports = {
199
199
  cmd_integration_enable: 'Enable integration automation flow',
200
200
  cmd_integration_disable: 'Disable integration automation flow',
201
201
  cmd_integration_check: 'Check abnormal integration automation run logs',
202
+ cmd_integration_detail_log: 'View integration automation run log details',
202
203
  cmd_integration_diagnose: 'Diagnose integration automation tickets and common pitfalls',
203
204
  cmd_dws: 'DingTalk CLI (contacts/calendar/todo/approval etc.)',
204
205
  cmd_dingtalk_link: 'Generate DingTalk AppLink / legacy dingtalk:// page links',
@@ -385,7 +386,7 @@ Examples:
385
386
  forbidden_alias_get_schema_form_uuid_option: '`{0}` takes formUuid as the second positional argument, not `{1}`.',
386
387
  nearest_command_suggestion: 'Unknown OpenYida command root "{0}". Did you mean "{1}"?',
387
388
  run_help: 'Run openyida --help for usage',
388
- integration_help: 'Usage: openyida integration <create|update|list|enable|disable|check|diagnose> ...',
389
+ integration_help: 'Usage: openyida integration <create|update|list|enable|disable|check|detail-log|diagnose> ...',
389
390
  integration_unknown: 'Unknown integration subcommand: {0}',
390
391
  integration_help_hint: 'Run openyida integration --help for available subcommands',
391
392
  integration_list_usage: 'Usage: openyida integration list <appType> [--form-uuid <uuid>] [--status y|n] [--key <kw>] [--size <n>] [--json]',
@@ -429,9 +430,9 @@ Examples:
429
430
  process_usage: 'Usage: openyida process <subcommand>\n\nSubcommands:\n preview <appType> <processInstanceId> [--output <path>] Preview process instance (generate visual flowchart)',
430
431
  process_preview_usage: 'Usage: openyida process preview <appType> <processInstanceId> [--output <path>]',
431
432
  process_preview_example: 'Example: openyida process preview APP_XXX proc-inst-id-xxx',
432
- get_permission_usage: 'Usage: openyida get-permission <appType> <formUuid> [--package-uuid <packageUuid>]',
433
+ get_permission_usage: 'Usage: openyida get-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--package-type <FORM_PACKAGE_VIEW|FORM_PACKAGE_START>]',
433
434
  get_permission_example: 'Example: openyida get-permission APP_XXX FORM-XXX',
434
- save_permission_usage: 'Usage: openyida save-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--data-permission <json>] [--action-permission <json>]',
435
+ save_permission_usage: 'Usage: openyida save-permission <appType> <formUuid> [--package-uuid <packageUuid>] [--data-permission <json>] [--action-permission <json>] [--package-type <FORM_PACKAGE_VIEW|FORM_PACKAGE_START>]',
435
436
  save_permission_example: "Example: openyida save-permission APP_XXX FORM-XXX --data-permission '{\"role\":\"DEFAULT\",\"dataRange\":\"SELF\"}'",
436
437
  exec_failed: '\n❌ Execution failed: {0}',
437
438
  login_usage: 'Usage: openyida login [entryUrl|--public|--alibaba|--intl] [--no-browser] [--check-only] [--json] [--client-id <clientId>]',
@@ -500,6 +501,18 @@ Examples:
500
501
  excel_exported: 'Excel exported: {0}',
501
502
  },
502
503
 
504
+ integration_detail_log: {
505
+ usage: 'Usage: openyida integration detail-log <appType> <procInstId> [--json] [--include-params] (known secrets are always masked; max 100 pages / 10,000 nodes; business parameters may still be sensitive)',
506
+ missing_args: 'Run log details require appType and procInstId',
507
+ unknown_option: 'Unsupported run log detail option: {0}',
508
+ params_require_json: '--include-params requires --json; known secrets are always masked, but business parameters may still be sensitive',
509
+ api_failed: 'Failed to query run log details: {0}',
510
+ invalid_response: 'Run log detail response has no valid node list or total count',
511
+ pagination_failed: 'Run log detail pages are inconsistent; incomplete data was not printed',
512
+ pagination_limit: 'Run log details exceed the pagination limit ({0} pages / {1} nodes); incomplete data was not printed',
513
+ summary: 'Run log details: {0} nodes (parameter keys only by default)',
514
+ },
515
+
503
516
  // ── lib/integration/integration-create.js ─────────
504
517
  integration: {
505
518
  create_usage: 'Usage: openyida integration create <appType> <formUuid> <flowName> [options]',
@@ -517,6 +530,7 @@ Examples:
517
530
  create_opt_spec: ' --spec <file.json> Use a structured flow spec for complex automation nodes (dataUpdate/route, etc.)',
518
531
  create_opt_data_form_uuid: ' --data-form-uuid <uuid> Target form UUID for a get-single-data node',
519
532
  create_opt_data_condition: ' --data-condition <rule> Get-data condition: targetField:label:triggerField[:component[:opCode[:valueType]]]',
533
+ create_opt_trigger_condition: ' --trigger-condition <rule> Trigger: field:label:opCode:value[:component[:valueType]]; RHS field: processVar, constant: literal',
520
534
  create_opt_get_self: ' --get-self Insert a get-self node (process runtime uses pid, designer uses proc_inst_id; ordinary forms use form_inst_id on both sides)',
521
535
  create_opt_get_self_field: ' --get-self-field <field> Override the trigger-side system field, default __masterdata_form_inst_id',
522
536
  create_opt_get_self_query_field: ' --get-self-query-field <f> Override the query-side system field (process: pid runtime / proc_inst_id designer; ordinary: form_inst_id)',
@@ -1555,6 +1569,10 @@ Examples:
1555
1569
  },
1556
1570
 
1557
1571
  check_prd_completeness: {
1572
+ application_theme_mismatch: 'The application theme does not match the selected project theme.',
1573
+ application_theme_not_checked: 'Application theme settings could not be verified; theme delivery remains unverified.',
1574
+ frontend_navigation_not_checked: 'Frontend menu hiding has not been verified: {0}',
1575
+ frontend_navigation_visible: 'Frontend page remains visible in the desktop or mobile management menu: {0}',
1558
1576
  usage: 'Usage: openyida check-prd-completeness <prd.md> --app-type <appType> [--build-manifest <file>] [--json]',
1559
1577
  example: 'Example: openyida check-prd-completeness prd/order-management/prd.md --app-type APP_XXX --build-manifest prd/order-management/build-manifest.json --json',
1560
1578
  prd_not_found: 'PRD file not found: {0}',
@@ -2043,6 +2061,11 @@ Options:
2043
2061
  };
2044
2062
 
2045
2063
  Object.assign(module.exports.query_data || (module.exports.query_data = {}), {
2064
+ approver_query_help: 'Current process approver: --current-approver <userId> [--count] scans all visible pages and counts distinct instances. Incomplete scans or permission failures are errors.',
2065
+ approver_option_invalid: 'Invalid current-approver query option: {0}. Use an exact userId and scan RUNNING instances from page 1.',
2066
+ approver_incomplete: 'The current-approver scan could not complete. No complete count was returned; check error details, permissions and pagination.',
2067
+ approver_response_invalid: 'The process API response could not be verified; a current-approver count cannot be determined.',
2068
+ approver_scope_note: 'Counts only instances visible to the current login under server authorization; this does not imply access to all application data.',
2046
2069
  association_derived_field_read_only: 'Derived association-form query field {0} is read-only and cannot be saved or updated. Write the source association field without the _id suffix.',
2047
2070
  association_value_invalid: 'The write value for association-form field {0} is invalid. Use an array of objects where every item includes appType, formUuid, formType, instanceId, and title.',
2048
2071
  command_unsupported: 'Unsupported data command: {0} {1}. Run openyida commands --json to inspect the actual capability.',
@@ -2063,6 +2086,19 @@ Object.assign(module.exports.query_data || (module.exports.query_data = {}), {
2063
2086
  target_identity_unverified: 'Could not read the name and type of target resource {0}. The operation stopped before mutation.',
2064
2087
  });
2065
2088
 
2089
+ module.exports.permission_scope = {
2090
+ roles_summary: 'Roles: {0}',
2091
+ options_help: '--owner-field restricts records to those whose top-level member field contains the current user; --roles selects ordinary Yida roles; --field-access is repeatable. Initial custom field access requires --field-default and shorthand updates require --package-uuid. --dry-run previews without writes.',
2092
+ invalid: 'Invalid permission options: {0}. Shorthand updates require --package-uuid; do not mix member scopes or field defaults.',
2093
+ owner_invalid: '--owner-field must identify a real top-level EmployeeField in the target form, not a creator alias, text or subtable field.',
2094
+ field_default_required: 'Initial --field-access requires --field-default view|edit|hidden|encrypt for all other fields; form-dependent behavior cannot be inferred.',
2095
+ overlap_notice: 'Other permission groups or overlapping roles may grant broader access. Saving this group does not verify effective row isolation or field access for all users.',
2096
+ matrix_notice: 'Native matrices use the OA enhancement entitlement package. Available does not prove purchase; unavailable requires an administrator to check or enable entitlement. Business APIs remain authoritative.',
2097
+ matrix_unavailable: 'Matrix usage is unavailable for this app. Ask an administrator to check or enable the OA enhancement entitlement package before retrying. No writes performed.',
2098
+ matrix_unknown: 'Matrix availability could not be established. Resolve the returned account-access or API error first. No writes performed.',
2099
+ };
2100
+
2101
+
2066
2102
  Object.assign(module.exports.common || (module.exports.common = {}), {
2067
2103
  non_idempotent_result_unknown: 'Authentication changed during the create request; the result is unknown. Verify the target state before retrying.',
2068
2104
  });
@@ -2268,3 +2304,31 @@ module.exports.help.cmd_data_manage_style_list = 'List optional data-management
2268
2304
  module.exports.help.cmd_data_manage_style_generate = 'Generate data-management CSS from an optional recipe (local only)';
2269
2305
 
2270
2306
  module.exports.help.cmd_data_manage_style_guide = 'Inspect data-management UI directions, tokens and scoped CSS guidance';
2307
+
2308
+ // Process fields and submission permission packages.
2309
+ Object.assign(module.exports.permission_common || (module.exports.permission_common = {}), {
2310
+ 'package_type_invalid': 'Use FORM_PACKAGE_VIEW or FORM_PACKAGE_START for --package-type.',
2311
+ 'start_scope_invalid': 'START supports submission members, fields and OPERATE_CREATE only; configure record data ranges and matrices separately.'
2312
+ });
2313
+ Object.assign(module.exports.process_errors || (module.exports.process_errors = {}), {
2314
+ 'field_permissions_invalid': 'Field permissions contain invalid or duplicate field IDs or behaviors.',
2315
+ 'field_source_failed': 'Could not read the form fields. Check the process binding and schema response.',
2316
+ 'fields_empty': 'The bound form has no readable fields. Check its saved schema.',
2317
+ 'designer_fields_missing': 'The process designer cannot load all bound form fields. Check its schema and process binding before publishing.',
2318
+ 'field_not_found': 'A process permission references a field missing from the bound form.',
2319
+ 'fields_verified': 'Field IDs were checked; browser behavior and runtime permissions remain unverified.'
2320
+ });
2321
+ Object.assign(module.exports.help || (module.exports.help = {}), {
2322
+ 'cmd_process_fields': 'Check process designer field loading and subtable field paths'
2323
+ });
2324
+ module.exports.cli.process_usage += '\n fields <appType> <formUuid> [--json] Inspect process designer field loading';
2325
+
2326
+ // Batch data nodes.
2327
+ Object.assign(module.exports.integration, {
2328
+ batch_invalid: 'Invalid batch configuration. Check source, quantity and fields using details.reason.',
2329
+ message_roles_invalid: 'Message roles require a non-empty role ID and NORMAL message type.',
2330
+ message_roles_readback_mismatch: 'Persisted message roles differ from the submitted recipients.',
2331
+ batch_retrieve_name: 'Get multiple records',
2332
+ batch_readback_mismatch: 'Persisted batch node type, source or quantity differs from the submitted configuration.',
2333
+ create_opt_spec: ' --spec <file.json> Configure batch retrieve/create, updates and branches with a structured spec',
2334
+ });