@salesforce/afv-skills 1.55.0 → 1.56.0

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 (220) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-generate/SKILL.md +8 -0
  3. package/skills/agentforce-generate/references/actions-reference.md +2 -2
  4. package/skills/agentforce-generate/references/voice-modality-reference.md +51 -15
  5. package/skills/agentforce-generate/references/voice-telephony-cli.md +193 -0
  6. package/skills/agentforce-observe/SKILL.md +13 -9
  7. package/skills/agentforce-observe/references/ahm-alerts.md +193 -14
  8. package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +24 -15
  9. package/skills/automation-sandbox-post-copy-config-generate/assets/config_template.json +11 -0
  10. package/skills/automation-sandbox-post-copy-config-generate/assets/json_schema.json +33 -1
  11. package/skills/automation-sandbox-post-copy-config-generate/references/configuration_catalog.md +32 -1
  12. package/skills/automation-sandbox-post-copy-configure/SKILL.md +75 -71
  13. package/skills/automation-sandbox-post-copy-configure/assets/scheduled_apex_template.apex +13 -0
  14. package/skills/automation-sandbox-post-copy-configure/examples/sample_scheduled_apex_config.json +13 -0
  15. package/skills/automation-sandbox-post-copy-configure/references/scheduled_apex_path.md +155 -0
  16. package/skills/automation-sandbox-post-copy-configure/scripts/build-scheduled-apex.mjs +62 -0
  17. package/skills/automation-sandbox-post-copy-configure/scripts/soql-escape-job-name.mjs +28 -0
  18. package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +383 -0
  19. package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +324 -0
  20. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +63 -0
  21. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +100 -0
  22. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -0
  23. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +46 -0
  24. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/04-deploy-engine.js +198 -0
  25. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/05-deploy-tpm-accruals.js +231 -0
  26. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +82 -0
  27. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +517 -0
  28. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +416 -0
  29. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -0
  30. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +514 -0
  31. package/skills/consumer-goods-sync-management-configure/SKILL.md +137 -0
  32. package/skills/consumer-goods-sync-management-configure/examples/scenarios.md +294 -0
  33. package/skills/consumer-goods-sync-management-configure/references/act1-setup-sync.md +333 -0
  34. package/skills/consumer-goods-sync-management-configure/references/act2-assign-users.md +324 -0
  35. package/skills/consumer-goods-sync-management-configure/references/act3-plan-verify.md +113 -0
  36. package/skills/consumer-goods-sync-management-configure/references/readiness-and-enablement.md +164 -0
  37. package/skills/consumer-goods-sync-management-configure/references/sync-management-app-install-backbone.md +159 -0
  38. package/skills/consumer-goods-sync-management-configure/references/transports-and-namespace.md +220 -0
  39. package/skills/consumer-goods-sync-management-configure/references/verify-and-smoke.md +175 -0
  40. package/skills/dx-org-analyze/SKILL.md +0 -1
  41. package/skills/dx-org-analyze/scripts/collect_org_data.py +2 -2
  42. package/skills/dx-org-analyze/scripts/compute_diff.py +2 -4
  43. package/skills/dx-org-analyze/scripts/introspect_org.py +4 -40
  44. package/skills/dx-org-manage/SKILL.md +6 -50
  45. package/skills/dx-org-manage/examples/README.md +10 -16
  46. package/skills/dx-org-manage/references/scratch-org-create.md +1 -1
  47. package/skills/dx-org-manage/references/scratch-org-operations.md +1 -1
  48. package/skills/dx-org-shape-manage/SKILL.md +4 -3
  49. package/skills/education-cloud-domain-configure/references/gotchas-extended.md +1 -0
  50. package/skills/experience-accessibility-validate/SKILL.md +8 -5
  51. package/skills/experience-accessibility-validate/references/reviewers/sc-1-1-1-non-text-content.md +1 -4
  52. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-i-lists.md +0 -4
  53. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-ii-tables.md +20 -85
  54. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-iii-form-labels.md +4 -4
  55. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-iv-regions.md +0 -4
  56. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-1-v-groups.md +2 -4
  57. package/skills/experience-accessibility-validate/references/reviewers/sc-1-3-5-identify-input.md +0 -4
  58. package/skills/experience-accessibility-validate/references/reviewers/sc-1-4-3-contrast.md +4 -14
  59. package/skills/experience-accessibility-validate/references/reviewers/sc-2-1-1-keyboard.md +9 -5
  60. package/skills/experience-accessibility-validate/references/reviewers/sc-2-4-4-link-purpose.md +1 -4
  61. package/skills/experience-accessibility-validate/references/reviewers/sc-2-4-6-headings-labels.md +0 -4
  62. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-1-pointer-gestures.md +0 -4
  63. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-2-pointer-cancellation.md +0 -4
  64. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-3-label-in-name.md +0 -4
  65. package/skills/experience-accessibility-validate/references/reviewers/sc-2-5-7-dragging-movement.md +0 -4
  66. package/skills/experience-accessibility-validate/references/reviewers/sc-3-2-1-on-focus.md +0 -4
  67. package/skills/experience-accessibility-validate/references/reviewers/sc-3-2-2-on-input.md +1 -4
  68. package/skills/experience-accessibility-validate/references/reviewers/sc-3-3-1-error-identification.md +1 -4
  69. package/skills/experience-accessibility-validate/references/reviewers/sc-3-3-2-labels-instructions.md +1 -4
  70. package/skills/experience-accessibility-validate/references/reviewers/sc-3-3-3-error-suggestion.md +1 -4
  71. package/skills/experience-accessibility-validate/references/reviewers/sc-4-1-2-i-name.md +4 -5
  72. package/skills/experience-accessibility-validate/references/reviewers/sc-4-1-2-ii-role.md +1 -4
  73. package/skills/experience-accessibility-validate/references/reviewers/sc-4-1-2-iii-value.md +0 -4
  74. package/skills/experience-lwc-accessibility-jest-run/SKILL.md +104 -25
  75. package/skills/experience-lwc-accessibility-jest-run/assets/jest.config.js +4 -0
  76. package/skills/experience-lwc-accessibility-jest-run/assets/sa11y-jest-setup.js +5 -0
  77. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +5 -5
  78. package/skills/experience-ui-bundle-features-generate/SKILL.md +65 -36
  79. package/skills/experience-ui-bundle-features-generate/references/angular/features.md +74 -0
  80. package/skills/experience-ui-bundle-features-generate/references/react/features.md +59 -0
  81. package/skills/experience-ui-bundle-features-generate/scripts/detect-framework.sh +73 -0
  82. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +2 -2
  83. package/skills/experience-ui-bundle-metadata-generate/SKILL.md +26 -14
  84. package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +37 -0
  85. package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +32 -0
  86. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +73 -0
  87. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +30 -8
  88. package/skills/field-service-data-capture-migrate/SKILL.md +391 -0
  89. package/skills/field-service-data-capture-migrate/assets/sample-legacy-flow.flow-meta.xml +163 -0
  90. package/skills/field-service-data-capture-migrate/references/architecture-notes.md +40 -0
  91. package/skills/field-service-data-capture-migrate/references/component-mapping.md +278 -0
  92. package/skills/field-service-data-capture-migrate/references/converter-builder-contract.md +183 -0
  93. package/skills/field-service-data-capture-migrate/references/dc-platform-rules.md +130 -0
  94. package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +215 -0
  95. package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +36 -0
  96. package/skills/field-service-data-capture-migrate/references/migration-checklist.md +121 -0
  97. package/skills/field-service-data-capture-migrate/references/transformer-rules.md +132 -0
  98. package/skills/field-service-data-capture-migrate/scripts/analyze_flow.py +277 -0
  99. package/skills/field-service-data-capture-migrate/scripts/convert_to_dc_spec.py +1311 -0
  100. package/skills/field-service-data-capture-migrate/scripts/cud_analysis.py +402 -0
  101. package/skills/field-service-data-capture-migrate/scripts/deploy_flow.sh +230 -0
  102. package/skills/field-service-data-capture-migrate/scripts/discover_subflow_tree.py +230 -0
  103. package/skills/field-service-data-capture-migrate/scripts/flow_input.py +186 -0
  104. package/skills/field-service-data-capture-migrate/scripts/flow_xml_utils.py +39 -0
  105. package/skills/field-service-data-capture-migrate/scripts/fsm_dc_catalog.py +413 -0
  106. package/skills/field-service-data-capture-migrate/scripts/generate_summary.py +199 -0
  107. package/skills/field-service-data-capture-migrate/scripts/json_to_flow_xml.py +146 -0
  108. package/skills/field-service-data-capture-migrate/scripts/manual_review_flags.py +42 -0
  109. package/skills/field-service-data-capture-migrate/scripts/retrieve_flow_rest.sh +155 -0
  110. package/skills/field-service-data-capture-migrate/scripts/subflow_names.py +49 -0
  111. package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +1661 -0
  112. package/skills/field-service-data-capture-migrate/scripts/validate_flow.sh +147 -0
  113. package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +1258 -0
  114. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +1 -1
  115. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +1 -1
  116. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +14 -1
  117. package/skills/mobile-apps-create/SKILL.md +1 -1
  118. package/skills/{platform-agentsetup-categories-fetch → platform-agenticsetup-categories-get}/SKILL.md +7 -7
  119. package/skills/platform-sandbox-configure/SKILL.md +108 -133
  120. package/skills/platform-sandbox-configure/references/api-response-shapes.md +39 -0
  121. package/skills/platform-sandbox-configure/references/definition-file-approach.md +73 -0
  122. package/skills/platform-widget-generate/SKILL.md +26 -18
  123. package/skills/platform-widget-generate/examples/formulas.json +191 -0
  124. package/skills/platform-widget-generate/references/widget-formulas.md +123 -0
  125. package/skills/platform-widget-generate/references/widget-meta-directives.md +4 -4
  126. package/skills/sales-call-scoring-configure/SKILL.md +318 -0
  127. package/skills/sales-call-scoring-configure/assets/best-practice-competencies.json +67 -0
  128. package/skills/sales-call-scoring-configure/assets/ootb-competencies.json +58 -0
  129. package/skills/sales-call-scoring-configure/references/admin-communication.md +79 -0
  130. package/skills/sales-call-scoring-configure/references/competency-crud.md +130 -0
  131. package/skills/sales-call-scoring-configure/scripts/create-competency.sh +166 -0
  132. package/skills/sales-call-scoring-configure/scripts/create-custom-competency.sh +166 -0
  133. package/skills/sales-call-scoring-configure/scripts/edit-competency.sh +185 -0
  134. package/skills/sales-call-scoring-configure/scripts/edit-custom-competency.sh +190 -0
  135. package/skills/sales-call-scoring-configure/scripts/enable-call-scoring.sh +436 -0
  136. package/skills/sales-call-scoring-configure/scripts/get-competency.sh +72 -0
  137. package/skills/sales-call-scoring-configure/scripts/get-custom-competency.sh +78 -0
  138. package/skills/sales-call-scoring-configure/scripts/install-best-practice-competencies.sh +223 -0
  139. package/skills/sales-call-scoring-configure/scripts/install-ootb-competencies.sh +237 -0
  140. package/skills/sales-call-scoring-configure/scripts/list-competencies.sh +99 -0
  141. package/skills/sales-call-scoring-configure/scripts/shared/auth.sh +116 -0
  142. package/skills/sales-call-scoring-configure/scripts/shared/cap.sh +86 -0
  143. package/skills/sales-call-scoring-configure/scripts/shared/soap.sh +267 -0
  144. package/skills/sales-call-scoring-configure/scripts/shared/soql.sh +25 -0
  145. package/skills/sales-call-scoring-configure/scripts/toggle-competency.sh +112 -0
  146. package/skills/sales-call-scoring-configure/scripts/toggle-custom-competency.sh +125 -0
  147. package/skills/sales-call-scoring-configure/scripts/verify-ootb-competencies.sh +116 -0
  148. package/skills/service-concierge-portal-generate/references/portal-deploy-runbook.md +1 -0
  149. package/skills/service-de-channel-activate/SKILL.md +6 -5
  150. package/skills/service-de-channel-create/SKILL.md +3 -3
  151. package/skills/service-de-channel-routing-configure/SKILL.md +3 -3
  152. package/skills/service-de-channel-settings-configure/SKILL.md +195 -0
  153. package/skills/service-de-channel-settings-configure/references/channel-settings-facets.md +152 -0
  154. package/skills/{service-de-channel-consent-configure → service-de-channel-settings-configure}/references/gotchas.md +3 -3
  155. package/skills/{service-de-channel-consent-configure → service-de-channel-settings-configure}/references/language-keywords.md +4 -4
  156. package/skills/{service-de-channel-consent-configure → service-de-channel-settings-configure}/references/worked-examples.md +14 -14
  157. package/skills/service-de-headless-channel-configure/SKILL.md +6 -6
  158. package/skills/service-de-headless-channel-configure/references/worked-examples.md +1 -1
  159. package/skills/service-helpagent-coordinate/SKILL.md +3 -2
  160. package/skills/service-helpagent-coordinate/references/channel-voice.md +15 -4
  161. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +49 -31
  162. package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +71 -6
  163. package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +26 -4
  164. package/skills/service-itsm-agentic-setup-cmdb-access-assign/SKILL.md +35 -10
  165. package/skills/service-itsm-agentic-setup-cmdb-access-assign/references/mcp-invocation.md +25 -5
  166. package/skills/service-itsm-agentic-setup-cmdb-bundle-deploy/SKILL.md +1 -1
  167. package/skills/service-itsm-agentic-setup-cmdb-configure/SKILL.md +5 -5
  168. package/skills/service-itsm-agentic-setup-cmdb-configure/references/mcp-invocation.md +1 -1
  169. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +2 -2
  170. package/skills/service-itsm-agentic-setup-cmdb-coordinate/examples/output-templates.md +1 -1
  171. package/skills/service-itsm-agentic-setup-cmdb-discovery-configure/SKILL.md +25 -15
  172. package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +8 -5
  173. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/report-format.md +4 -2
  174. package/skills/service-itsm-agentic-setup-employee-agent-configure/references/workflow-detail.md +1 -1
  175. package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/render-report.mjs +29 -16
  176. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +8 -5
  177. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/report-format.md +4 -2
  178. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/workflow-detail.md +1 -1
  179. package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/render-report.mjs +29 -16
  180. package/skills/service-itsm-agentic-setup-incident-management/SKILL.md +138 -68
  181. package/skills/service-itsm-agentic-setup-incident-management/examples/output-templates.md +31 -15
  182. package/skills/service-itsm-agentic-setup-incident-management/references/incident-persona-psg.md +156 -0
  183. package/skills/service-itsm-agentic-setup-incident-management/references/incident-preferences.md +148 -0
  184. package/skills/service-itsm-agentic-setup-incident-management/references/major-incident-management.md +162 -0
  185. package/skills/service-itsm-agentic-setup-incident-management/references/service-mgmt-privilege.md +149 -0
  186. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +103 -89
  187. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone.json +2 -2
  188. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +21 -39
  189. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +3 -3
  190. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +18 -1
  191. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +63 -37
  192. package/skills/service-omni-attribute-routing-configure/SKILL.md +53 -0
  193. package/skills/service-omni-attribute-routing-configure/references/api-notes.md +7 -0
  194. package/skills/service-omni-attribute-routing-configure/scripts/configure-and-report.sh +224 -0
  195. package/skills/service-omni-attribute-routing-configure/scripts/tests/test_attribute_routing_contracts.py +137 -0
  196. package/skills/service-omni-channel-inventory-analyze/SKILL.md +96 -0
  197. package/skills/service-omni-channel-inventory-analyze/references/api-notes.md +52 -0
  198. package/skills/service-omni-channel-inventory-analyze/scripts/analyze.sh +185 -0
  199. package/skills/service-omni-channel-inventory-analyze/scripts/tests/_bootstrap.py +84 -0
  200. package/skills/service-omni-channel-inventory-analyze/scripts/tests/test_inventory_analyze_contracts.py +141 -0
  201. package/skills/service-omni-channel-limits-analyze/SKILL.md +70 -0
  202. package/skills/service-omni-channel-limits-analyze/references/api-notes.md +22 -0
  203. package/skills/service-omni-channel-limits-analyze/scripts/analyze.sh +159 -0
  204. package/skills/service-omni-channel-limits-analyze/scripts/tests/_bootstrap.py +87 -0
  205. package/skills/service-omni-channel-limits-analyze/scripts/tests/test_limits_analyze_contracts.py +99 -0
  206. package/skills/service-omni-channel-setup-coordinate/SKILL.md +12 -20
  207. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +55 -5
  208. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +38 -0
  209. package/skills/service-omni-command-center-analyze/SKILL.md +2 -2
  210. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
  211. package/skills/dx-org-manage/examples/snapshots/error_output.json +0 -9
  212. package/skills/dx-org-manage/examples/snapshots/success_output.json +0 -15
  213. package/skills/dx-org-manage/references/cli_flags.md +0 -67
  214. package/skills/dx-org-manage/references/creating-snapshot.md +0 -103
  215. package/skills/dx-org-manage/references/snapshot_usage.md +0 -74
  216. package/skills/experience-accessibility-validate/scripts/contrast-ratio.py +0 -153
  217. package/skills/experience-lwc-accessibility-jest-run/references/running-sa11y-jest-tests.md +0 -205
  218. package/skills/experience-ui-bundle-features-generate/scripts/verify-react-bundle.sh +0 -14
  219. /package/skills/experience-ui-bundle-features-generate/references/{conflict-resolution-schema.json → common/conflict-resolution-schema.json} +0 -0
  220. /package/skills/{platform-agentsetup-categories-fetch → platform-agenticsetup-categories-get}/references/api-response-schema.md +0 -0
@@ -1,25 +1,40 @@
1
1
  #!/bin/bash
2
2
  # Verifies that a UI bundle was created under force-app/main/default/uiBundles/
3
3
  # (and not at the repo root, which would be non-deployable), AND that the
4
- # scaffold itself is complete (package.json, src/, index.html present) — not
5
- # just a hand-authored metadata-only directory.
4
+ # scaffold itself is complete (package.json, src/, entry index.html present) —
5
+ # not just a hand-authored metadata-only directory.
6
+ #
7
+ # The entry index.html lives at the bundle root for React (reactbasic) and at
8
+ # src/index.html for Angular (angularbasic), so both locations are accepted.
6
9
  #
7
10
  # If a custom output directory was used (--output-dir on the scaffold command),
8
11
  # pass it as the second argument. The script then verifies the bundle exists
9
- # there instead of assuming the default location.
12
+ # there instead of assuming the default location. Pass the framework
13
+ # (react|angular) as the third argument so the remediation hint uses the right
14
+ # --template flag; pass "" for the second argument to supply only a framework.
10
15
 
11
16
  set -e
12
17
 
13
- if [[ $# -lt 1 || $# -gt 2 ]]; then
18
+ if [[ $# -lt 1 || $# -gt 3 ]]; then
14
19
  echo "ERROR: Bundle name required"
15
- echo "Usage: bash verify-bundle-location.sh <BundleName> [<CustomOutputDir>]"
20
+ echo "Usage: bash verify-bundle-location.sh <BundleName> [<CustomOutputDir>] [<framework>]"
16
21
  exit 1
17
22
  fi
18
23
 
19
24
  BUNDLE_NAME="$1"
20
25
  CUSTOM_OUTPUT_DIR="${2:-}"
26
+ FRAMEWORK="${3:-}"
27
+
28
+ # Pick the remediation template and the expected entry-HTML location from the
29
+ # framework. When the framework is not supplied we stay lenient: default the
30
+ # hint to reactbasic and accept the entry index.html at either location.
31
+ case "$FRAMEWORK" in
32
+ angular) TEMPLATE="angularbasic"; ENTRY="src/index.html" ;;
33
+ react) TEMPLATE="reactbasic"; ENTRY="index.html" ;;
34
+ *) TEMPLATE="reactbasic"; ENTRY="" ;;
35
+ esac
21
36
 
22
- # Checks that the scaffold actually produced a full React project, not just
37
+ # Checks that the scaffold actually produced a full project, not just
23
38
  # hand-written metadata files. Returns 1 (and prints guidance) if incomplete.
24
39
  # Pass a second argument with the --output-dir value when checking a bundle
25
40
  # in a custom location, so the remediation command matches where the bundle
@@ -30,10 +45,17 @@ check_scaffold_complete() {
30
45
  local missing=()
31
46
  [[ -f "$bundle_path/package.json" ]] || missing+=("package.json")
32
47
  [[ -d "$bundle_path/src" ]] || missing+=("src/")
33
- [[ -f "$bundle_path/index.html" ]] || missing+=("index.html")
48
+ # Entry HTML lives at the bundle root for React and at src/index.html for
49
+ # Angular. When the framework is known, require the correct location; when it
50
+ # is unknown, accept either.
51
+ if [[ -n "$ENTRY" ]]; then
52
+ [[ -f "$bundle_path/$ENTRY" ]] || missing+=("$ENTRY")
53
+ else
54
+ [[ -f "$bundle_path/index.html" || -f "$bundle_path/src/index.html" ]] || missing+=("index.html")
55
+ fi
34
56
 
35
57
  if [[ ${#missing[@]} -gt 0 ]]; then
36
- local scaffold_cmd="sf template generate ui-bundle -n $BUNDLE_NAME --template reactbasic"
58
+ local scaffold_cmd="sf template generate ui-bundle -n $BUNDLE_NAME --template $TEMPLATE"
37
59
  if [[ -n "$output_dir" ]]; then
38
60
  scaffold_cmd="$scaffold_cmd --output-dir \"$output_dir\""
39
61
  fi
@@ -0,0 +1,391 @@
1
+ ---
2
+ name: field-service-data-capture-migrate
3
+ description: "Fully automated migration of Field Service Mobile flows (processType='FieldServiceMobile') to DataCaptureFlow. Retrieves flow XML from the org, runs a transformer script to restructure the execution graph and convert all field types, deploys the migrated flow as Draft only (activation is always a separate manual admin step after validation), and reports functional-equivalence differences. Handles most flows end-to-end without manual intervention. Always use this skill even for changes that look trivial, like removing one component or reordering one element — Data Capture's runtime behaves differently from Flow Builder previews, in ways only the transformer script accounts for. Use when a user wants to migrate, modernize, convert, audit, or replace legacy Field Service Mobile flow `.flow` / `.flow-meta.xml` files with Data Capture, or assess migration readiness. Do not use to edit an existing Data Capture flow or author a new one from scratch — covers only the one-time legacy migration."
4
+ metadata:
5
+ version: "1.1"
6
+ domains: ["Field Service"]
7
+ minApiVersion: "67.0"
8
+ cliTools:
9
+ - tool: ["curl"]
10
+ semver: ">=7.0.0"
11
+ - tool: ["jq"]
12
+ semver: ">=1.6.0"
13
+ - tool: ["python3"]
14
+ semver: ">=3.9.0"
15
+ - tool: ["sf"]
16
+ semver: ">=2.0.0"
17
+ mcpTools:
18
+ slack:
19
+ tools: ["slack_create_canvas", "slack_send_message"]
20
+ semver: ">=1.0.0"
21
+ accessCheck:
22
+ - type: "license"
23
+ value: "Field Service"
24
+ ---
25
+
26
+ # Migrate Field Service Mobile Flows to Data Capture
27
+
28
+ This skill migrates legacy Field Service mobile flows (`processType='FieldServiceMobile'`) to `DataCaptureFlow` using a fully automated XML transformer. The transformer handles all known migration patterns including field type conversion, execution graph restructuring, variable deduplication, and platform-event removal.
29
+
30
+ **Goal:** Get Field Service customers off Mobile Screen Flows and onto Data Capture — the strategic direction for Field Service digital forms.
31
+
32
+ ```bash
33
+ SKILL_ROOT="${SKILL_ROOT:-${PLUGIN_ROOT:-$HOME/.vibe/skills}/field-service-data-capture-migrate}"
34
+ SCR="$SKILL_ROOT/scripts"
35
+ OUT="${FSM_OUT:-$PWD}" # *_DC files land in cwd; override via FSM_OUT.
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Why migrate
41
+
42
+ | Capability | Mobile Screen Flow | Data Capture Flow |
43
+ |---|---|---|
44
+ | Conditional Visibility | No — workaround via separate screens | Yes — built-in, within a single screen |
45
+ | Cross-Field Validation | No — validates on "Next" only | Yes — real-time, immediate feedback |
46
+ | Offline | Yes — good (Briefcase priming) | Yes — better, offline-first, autosave/pause |
47
+ | Repeatable Sections | Yes — medium UX (Loop + screens) | Yes — better UX (native Repeater) |
48
+ | Mobile UX | Yes — good | Yes — better, fewer clicks, in-screen logic |
49
+ | Dependent Picklists | Yes — mobile only | Partial — conditional filtering only (roadmap) |
50
+ | Backoffice Completion | Yes — supported | No — roadmap |
51
+ | Form Edit after Submit | No — limited | No — roadmap |
52
+ | Future Proofing | No — legacy path | Yes — AI, Voice to Form, ongoing investment |
53
+
54
+ ---
55
+
56
+ ## Automated migration workflow
57
+
58
+ ### Step 0 — Clarify migration scope FIRST
59
+
60
+ **Before querying the org, determine the user's intent.** If the request is ambiguous (e.g. "migrate flows", "migrate my org's flows"), ask explicitly whether they mean one specific flow, several named flows, or ALL Field Service Mobile flows in the org. **Only proceed to Step 1 after the scope is clear.** Never query all flows unless the user explicitly wants that.
61
+
62
+ ### Step 1 — Discover flows
63
+
64
+ **REST API endpoint:** `GET /services/data/v67.0/tooling/query`, auth via `Authorization: Bearer <token>`. Use `curl --config` — `-H` leaks via `ps`/`/proc`.
65
+
66
+ ```bash
67
+ # All Field Service Mobile flows:
68
+ # SOQL: SELECT Id, MasterLabel, ProcessType, Status, VersionNumber FROM Flow
69
+ # WHERE ProcessType = 'FieldServiceMobile' AND Status IN ('Active','Draft')
70
+ # ORDER BY MasterLabel, VersionNumber DESC
71
+ curl -X GET "https://<instance>.my.salesforce.com/services/data/v67.0/tooling/query?q=SELECT+Id%2C+MasterLabel%2C+ProcessType%2C+Status%2C+VersionNumber+FROM+Flow+WHERE+ProcessType+%3D+%27FieldServiceMobile%27+AND+Status+IN+%28%27Active%27%2C%27Draft%27%29+ORDER+BY+MasterLabel%2C+VersionNumber+DESC" \
72
+ --config <(printf 'header = "Authorization: Bearer %s"\n' "$TOKEN")
73
+
74
+ # One or more named flows — add: AND MasterLabel IN ('Work Order Wizard', 'Asset Inspection')
75
+ ```
76
+
77
+ **Response format:**
78
+ ```json
79
+ {
80
+ "size": 2, "totalSize": 2, "done": true,
81
+ "records": [
82
+ {"Id": "301xx000000001", "MasterLabel": "Asset Inspection", "ProcessType": "FieldServiceMobile", "Status": "Active", "VersionNumber": 5}
83
+ ]
84
+ }
85
+ ```
86
+
87
+ URL-encoding: space → `+`/`%20`, `'`→`%27`, `,`→`%2C`, `(`/`)`→`%28`/`%29`, `=`→`%3D`.
88
+
89
+ **Surface the query results to the user** (table or list). If the user named specific flows and any are missing, report that immediately.
90
+
91
+ ### Step 2 — Retrieve flow XML
92
+
93
+ **Handed the flow file(s) directly, no org?** Skip Steps 1–2 — run Step 4 on each in place (subflows first, `--is-subflow`), writing `<Name>_DC.flow-meta.xml` to the current dir, then skip Steps 5–6 (org-only). Otherwise retrieve from the org:
94
+
95
+ ```bash
96
+ mkdir -p /tmp/fsm-migration/project && cd /tmp/fsm-migration/project
97
+ echo '{"packageDirectories":[{"path":"force-app","default":true}],"namespace":"","sourceApiVersion":"67.0"}' > sfdx-project.json
98
+
99
+ # Single flow:
100
+ sf project retrieve start --metadata "Flow:<FlowApiName>" --target-org <alias>
101
+ # Multiple (comma-separated, no spaces after commas):
102
+ sf project retrieve start --metadata "Flow:<Flow1>,Flow:<Flow2>" --target-org <alias>
103
+ # All flows (ONLY if the user explicitly confirmed "all" in Step 0):
104
+ sf project retrieve start --metadata "Flow" --target-org <alias>
105
+ ```
106
+
107
+ **Critical:** `--metadata` must match the user's Step 0 selection — never retrieve all flows unless explicitly confirmed. (No REST equivalent exists yet for this step — see `references/architecture-notes.md`.)
108
+
109
+ ### Step 3 — Validate migration candidates
110
+
111
+ Only flows with BOTH `FieldServiceMobile` processType AND at least one `<screens>` element are valid candidates:
112
+
113
+ ```bash
114
+ migratable=()
115
+ for f in force-app/main/default/flows/*.flow-meta.xml; do
116
+ base=$(basename "$f" .flow-meta.xml)
117
+ if grep -q "FieldServiceMobile" "$f"; then
118
+ if grep -q "<screens>" "$f"; then
119
+ echo "[MIGRATABLE] $base"; migratable+=("$f")
120
+ else
121
+ echo "[NO SCREENS] $base — cannot migrate (pure automation flow)"
122
+ fi
123
+ else
124
+ processType=$(grep -oP '(?<=<processType>)[^<]+' "$f" || echo "unknown")
125
+ echo "[NOT FSM] $base — processType is '$processType'"
126
+ fi
127
+ done | sort
128
+ echo "Migratable flows: ${#migratable[@]}"
129
+ ```
130
+
131
+ If the user specified particular flows and any fail validation, **STOP and report the issue** — don't proceed with partial migration unless the user confirms skipping the invalid ones. If the user confirmed "migrate all", this filters to the migratable subset — report counts before proceeding. Pure automation flows (no `<screens>`) should stay as-is or become AutoLaunched flows; flag but don't migrate them.
132
+
133
+ ### Step 3b — Resolve the subflow dependency tree (composed flows)
134
+
135
+ Flows that call subflows must migrate **leaves-first** — a caller can't validate until every `_DC` subflow it references exists in the deploy set:
136
+
137
+ ```bash
138
+ python3 "$SCR/discover_subflow_tree.py" \
139
+ force-app/main/default/flows \
140
+ force-app/main/default/flows/<CallerFlowApiName>.flow-meta.xml \
141
+ --json /tmp/fsm-migration/subflow-tree.json
142
+ ```
143
+
144
+ | Exit | Meaning | Action |
145
+ |---|---|---|
146
+ | `0` | Every node is migratable | Transform in the printed order (Step 4), then bundle-validate (Step 5) |
147
+ | `1` | ≥1 dependency blocked (not FSM, no screens, cycle) or missing | **STOP — do not deploy the caller.** Report the blocking node(s). |
148
+ | `2` | Usage error | Pass a flows dir and at least one caller path (or `--all`) |
149
+
150
+ Use the JSON `order` array as the transform order for Step 4 and the file list for Step 5.
151
+
152
+ ### Step 4 — Transform each flow
153
+
154
+ ```bash
155
+ OUT="${FSM_OUT:-$PWD}"; mkdir -p "$OUT"
156
+ # Input: the retrieved project path below, or just <FlowApiName>.flow-meta.xml if handed the file.
157
+ python3 "$SCR/transform_flow.py" \
158
+ force-app/main/default/flows/<FlowApiName>.flow-meta.xml \
159
+ "$OUT/<FlowApiName>_DC.flow-meta.xml"
160
+ ```
161
+
162
+ **Pass `--is-subflow` for every node the Step 3b tree reports at `depth > 0`.** A DataCaptureFlow subflow cannot contain Create/Update/Delete — `--is-subflow` excises CUD unconditionally (not just reordering it) and routes CUD fault-path violations through the fault-severing pre-pass; the plain treatment is correct only for the top-level caller (`depth == 0`). Skipping it on a real subflow reproduces the "You can't use Create, Update, or Delete elements in a Data Capture flow subflow" deploy failure Step 3b prevents.
163
+
164
+ Use `python3 "$SCR/subflow_names.py" <FlowApiName>` to derive the correct output filename — for overridden names a plain `_DC` suffix won't match the caller's rewritten reference and the bundle dry-run will fail.
165
+
166
+ The transformer reports fields converted, CUD fixes, and warnings. Unsupported elements (Apex/action calls, subflows, fault paths, custom components, unknown field types) produce an `_incompleteMigration` list and an `<!-- INCOMPLETE MIGRATION ... -->` XML comment; unsupported field slots become read-only `DisplayText` placeholders, never silent `ShortText` inputs.
167
+
168
+ **Batch transform in parallel** — each flow's transform is independent, so use a bounded `xargs -P4` instead of a sequential loop. When Step 3b produced `subflow-tree.json`, look up each flow's `depth` there to decide whether to add `--is-subflow`; a flow absent from the tree (no composed dependencies) is always the top-level caller:
169
+
170
+ ```bash
171
+ OUT="${FSM_OUT:-$PWD}"; mkdir -p "$OUT"
172
+ TREE=/tmp/fsm-migration/subflow-tree.json
173
+ find force-app/main/default/flows -maxdepth 1 -name '*.flow-meta.xml' -print0 \
174
+ | while IFS= read -r -d '' f; do
175
+ grep -q "FieldServiceMobile" "$f" && grep -q "<screens>" "$f" && printf '%s\0' "$f"
176
+ done \
177
+ | xargs -0 -I{} -P4 bash -c '
178
+ f="{}"; base=$(basename "$f" .flow-meta.xml)
179
+ dcname=$(python3 "'"$SCR"'/subflow_names.py" "$base")
180
+ subflowFlag=""
181
+ if [ -f "'"$TREE"'" ]; then
182
+ depth=$(jq -r --arg n "$base" "(.order[] | select(.apiName == \$n) | .depth) // 0" "'"$TREE"'")
183
+ [ "$depth" -gt 0 ] 2>/dev/null && subflowFlag="--is-subflow"
184
+ fi
185
+ python3 "'"$SCR"'/transform_flow.py" "$f" "'"$OUT"'/${dcname}.flow-meta.xml" $subflowFlag 2>&1 \
186
+ | grep -E "(Transformed|SKIPPED|CUD|Warning)"
187
+ '
188
+ ```
189
+
190
+ Safe even for a composed tree — each transform reads no leaf output (one flow in, one flow out), so nothing needs sequencing here; the leaves-first order from Step 3b only matters for the Step 5 bundle dry-run.
191
+
192
+ **Output name collisions:** two source flows must never resolve to the same `dcname` via `subflow_names.py` — under `-P4` that's a concurrent write to the same file. If the batch has any name overrides, spot-check afterward: `find "${FSM_OUT:-$PWD}" -maxdepth 1 -name '*_DC.flow-meta.xml' | sort | uniq -d`.
193
+
194
+ ### Step 4b — Generate migration summary
195
+
196
+ ```bash
197
+ SUM=/tmp/fsm-migration/summaries; mkdir -p $SUM /tmp/fsm-migration/spec
198
+ find force-app/main/default/flows -maxdepth 1 -name '*.flow-meta.xml' -print0 \
199
+ | while IFS= read -r -d '' f; do
200
+ grep -q "FieldServiceMobile" "$f" && grep -q "<screens>" "$f" && printf '%s\0' "$f"
201
+ done \
202
+ | xargs -0 -I{} -P4 bash -c '
203
+ f="{}"; base=$(basename "$f" .flow-meta.xml)
204
+ python3 "'"$SCR"'/convert_to_dc_spec.py" "$f" "/tmp/fsm-migration/spec/${base}.json"
205
+ python3 "'"$SCR"'/generate_summary.py" \
206
+ "/tmp/fsm-migration/spec/${base}.json" \
207
+ "'"$SUM"'/${base}-migration-summary.md"
208
+ '
209
+ ```
210
+
211
+ The summary lists the component mapping (`[OK]`/`[WARNING]`/`[ERROR]` prefixes), conditional-logic decisions, unsupported components, behavioral notes, an offline-priming warning, a manual Review Checklist, and a clearly-labeled Advisory placeholder (the only place AI-generated prose belongs). `generate_summary.py` is deterministic and always writes this `.md` — it's both the input to the canvas in Step 4c and the offline fallback artifact.
212
+
213
+ ### Step 4c — Ask how to deliver the review, then publish
214
+
215
+ **Ask explicitly, if interactive — never silently default:** "Post the migration summary to Slack, or download it as an `.md` file?" The per-flow `.md` from Step 4b exists either way; this only decides whether a Slack canvas also gets created.
216
+
217
+ - **Slack:** ask for the destination channel and wait for it — never create a canvas without one (offer a remembered channel, but confirm). Canvas creation is the `slack_create_canvas` MCP tool (Python can't reach it). Per flow: read `${base}-migration-summary.md`, strip the leading `# Migration Summary: <formTitle>` H1 (the canvas takes the title separately), create a canvas titled `Migration Summary: <formTitle>` with the rest as content, `slack_send_message` posts its link into the channel, record the URL for Step 7. Remember the channel.
218
+ - **File download:** point to the `.md` path(s) already written in Step 4b — nothing further to do.
219
+
220
+ **Fallback:** no interactive user, or Slack unavailable / canvas errors — skip to the `.md` path(s); the run succeeds either way.
221
+
222
+ ### Step 5 — Validate (dry-run)
223
+
224
+ Optional, non-destructive pre-deploy gate — only when an org alias is available. **Ask before running** (costs wall-clock, not required for output; offline runs skip it and still succeed): _"Run dry-run validation against `<alias>` before deploying? (yes/no)"_ If the SE declines, treat as exit `3` below: deploy **as Draft only** (the only status this skill ever deploys).
225
+
226
+ **Default to one bundle dry-run, not one per flow** — this lets intra-tree `_DC` subflow references resolve within the deploy set (an isolated per-flow dry-run fails on a caller whose subflows aren't deployed yet). Fall back to per-flow only if the bundle fails on >1 flow and you need to attribute it:
227
+
228
+ ```bash
229
+ OUT="${FSM_OUT:-$PWD}"
230
+ set --
231
+ while IFS= read -r -d '' f; do set -- "$@" "$f"; done \
232
+ < <(find "$OUT" -maxdepth 1 -name '*_DC.flow-meta.xml' -print0)
233
+ if [ "$#" -gt 0 ]; then
234
+ "$SCR/validate_flow.sh" --bundle "<alias>" "$@"
235
+ code=$?
236
+ if [ "$code" -eq 1 ] && [ "$#" -gt 1 ]; then
237
+ echo "Bundle dry-run failed — re-running per-flow to attribute the failure(s):"
238
+ "$SCR/validate_flow.sh" "<alias>" "$@"
239
+ code=$?
240
+ fi
241
+ else
242
+ echo "No migrated flows to validate."; code=0
243
+ fi
244
+ ```
245
+
246
+ In per-flow fallback, a caller referencing `_DC` subflows fails even when it's fine (its subflow isn't in that isolated deploy set) — treat a `flow doesn't exist` failure on a known caller as this isolation artifact, not a real defect.
247
+
248
+ | Exit | Meaning | Action |
249
+ |---|---|---|
250
+ | `0` | All flows validated clean | Proceed to Step 6 and deploy (Draft) |
251
+ | `1` | ≥1 flow failed dry-run or file not found | Deploy as Draft if you want the output in-org for manual repair; otherwise fix the transformer gap and re-validate. |
252
+ | `2` | Usage error (zero arguments) | Should be prevented by the existence guard above |
253
+ | `3` | No target org — validation skipped | Expected offline; output is valid, validation deferred |
254
+
255
+ `deploy_flow.sh` always deploys Draft regardless of dry-run outcome — a failed dry-run just means the deploy isn't worth doing yet.
256
+
257
+ **Optional live smoke test (manual — not in CI).** The bundle dry-run proves the script's contract; running it once against a real org proves the output actually deploys:
258
+
259
+ ```bash
260
+ "$SCR/validate_flow.sh" <org-alias> "${FSM_OUT:-$PWD}/<FlowApiName>_DC.flow-meta.xml"
261
+ # Expected: exit 0, "PASS <FlowApiName>_DC.flow-meta.xml"
262
+ ```
263
+
264
+ ### Step 6 — Deploy (kickoff + rollback snapshot)
265
+
266
+ ```bash
267
+ OUT="${FSM_OUT:-$PWD}"
268
+ set --
269
+ while IFS= read -r -d '' f; do set -- "$@" "$f"; done \
270
+ < <(find "$OUT" -maxdepth 1 -name '*_DC.flow-meta.xml' -print0)
271
+
272
+ "$SCR/deploy_flow.sh" <alias> "$@"
273
+ ```
274
+
275
+ `deploy_flow.sh` captures a **pre-deploy rollback snapshot** of every target flow's prior org state before writing anything, then deploys only after **explicit SE confirmation** (`Proceed? [y/N]`; pass `--yes` to skip for an unattended demo). Every deploy is **Draft only** — the deploy copy's `<status>` is force-rewritten to `Draft` regardless of source content, so nothing here can deploy Active. Activation is the manual Step 8 action.
276
+
277
+ | Exit | Meaning | Action |
278
+ |---|---|---|
279
+ | `0` | Deploy succeeded | Proceed to Step 7. Snapshot path is printed for rollback. |
280
+ | `1` | Deploy failed, snapshot query failed, or a flow file was missing | **STOP.** Read the component errors under `Status:`. |
281
+ | `2` | Usage error (no flow files) | `find` matched nothing — check the output dir |
282
+ | `3` | No target org — deploy skipped | Expected offline; nothing was written |
283
+ | `4` | SE declined the confirmation prompt | Nothing was written; the snapshot is retained for reference |
284
+
285
+ **Rollback snapshot:** written to `/tmp/fsm-migration/rollback/<timestamp>/snapshot.json`, recording per-flow whether it `existedBeforeDeploy` and (if so) its prior label/active-version/latest-version IDs. To restore, re-deploy the version identified in the snapshot — but confirm no one edited the deployed `_DC` flow after this deploy, or that edit is lost.
286
+
287
+ **Deploy order:** subflows (leaves) before their callers — use the `discover_subflow_tree.py` `order` sequence from Step 3b.
288
+
289
+ ### Step 7 — Verify and report
290
+
291
+ ```bash
292
+ # REST API: GET /services/data/v67.0/tooling/query
293
+ # SOQL: SELECT MasterLabel, Status FROM Flow
294
+ # WHERE ProcessType = 'DataCaptureFlow' AND Status IN ('Draft','Active') ORDER BY MasterLabel
295
+ curl -X GET "https://<instance>.my.salesforce.com/services/data/v67.0/tooling/query?q=SELECT+MasterLabel%2C+Status+FROM+Flow+WHERE+ProcessType+%3D+%27DataCaptureFlow%27+AND+Status+IN+%28%27Draft%27%2C%27Active%27%29+ORDER+BY+MasterLabel" \
296
+ --config <(printf 'header = "Authorization: Bearer %s"\n' "$TOKEN")
297
+ ```
298
+
299
+ **Response format:**
300
+ ```json
301
+ {
302
+ "size": 3, "totalSize": 3, "done": true,
303
+ "records": [
304
+ {"MasterLabel": "Asset Inspection_DC", "Status": "Active"}
305
+ ]
306
+ }
307
+ ```
308
+
309
+ ```bash
310
+ # Functional equivalence check (runs on the SOURCE FieldServiceMobile flow, not the _DC output):
311
+ python3 "$SCR/analyze_flow.py" \
312
+ force-app/main/default/flows/<FlowApiName>.flow-meta.xml \
313
+ /tmp/fsm-migration/analysis/<FlowApiName>.json
314
+ ```
315
+
316
+ Surface any warnings to the user before they manually activate (Step 8).
317
+
318
+ **Publish the aggregate run-report** after the batch, matching the delivery picked in Step 4c. Include: flows migrated (count + names), dry-run/deploy outcomes per flow (by exit code), aggregate GREEN/YELLOW/RED/SKIP risk counts, total `[WARNING]`/`[ERROR]` component counts, and per-flow report links/paths.
319
+
320
+ - **Slack:** one aggregate canvas linking each per-flow canvas from Step 4c, posted into the same destination.
321
+ - **File download:** list the per-flow `.md` paths from Step 4b as the aggregate report — no separate file needed.
322
+
323
+ ### Step 8 — Activate and deactivate legacy
324
+
325
+ The **only** way a migrated flow goes live — nothing here activates a flow automatically. Once validated in Flow Builder and tested on device: open the DC flow and click **Activate**, then deactivate the old Field Service Mobile Flow (leave it inactive; don't delete until fully validated).
326
+
327
+ ---
328
+
329
+ ## How the transformer works
330
+
331
+ `transform_flow.py` is a direct XML-to-XML transformer covering field-type conversion, required-element injection, label placement, and CUD-at-end graph restructuring (4 patterns, up to 50 convergence iterations) — see `references/transformer-rules.md` for the complete field-type mapping table and the full list of automatic fixes plus what changes behaviorally after migration (lookup execution order, platform events, confirmation-screen placement, constants).
332
+
333
+ ## Patterns that cannot be automated (require Flow Builder redesign)
334
+
335
+ | Pattern | Why it can't be automated | Recommended redesign |
336
+ |---|---|---|
337
+ | **No screens (pure automation)** | DataCaptureFlow requires at least one screen | Keep as Field Service Mobile Flow, or convert to AutoLaunchedFlow |
338
+ | **Screen inside a loop** | DC doesn't support screens inside loops (detected + warned) | Replace loop+screen with a DC native **Repeater** field |
339
+ | **Lookup depends on just-created record** | `Create → Get (by new ID) → Create again` cycle; DC requires all CUD at end | Do all lookups before screens, accumulate in variables, batch-create at the end |
340
+ | **Confirmation screen shown after CUD** | DC requires screens before CUD | Move to a pre-CUD summary screen, or use DisplayText to preview what will be saved |
341
+ | **Backoffice/desktop completion needed** | DC forms complete only on FSL Mobile (roadmap) | Keep on Field Service Mobile Flow until roadmap ships |
342
+ | **Full dependent picklists** | DC only supports conditional filtering today (roadmap) | Use conditional visibility as workaround |
343
+
344
+ ## Migration risk classification
345
+
346
+ | Risk | Criteria | Automated? |
347
+ |---|---|---|
348
+ | **GREEN** | No screens in loop, no create→lookup cycles, no platform events | Yes — fully automated |
349
+ | **YELLOW** | Platform events, hoisted post-screen lookups, constants, `isRequired` on hidden fields, or complex DisplayText formulas | Yes — automated with warnings, review before activating |
350
+ | **RED — restructurable** | CUD violations the graph restructurer fixes automatically | Yes — automated, transformer resolves these |
351
+ | **RED — requires redesign** | Screen inside loop, create→lookup cycle, `Range` slider fields | No — manual Flow Builder redesign required |
352
+ | **SKIP** | No screens — pure automation flow | No — not a DataCaptureFlow candidate |
353
+
354
+ For the authoritative DataCaptureFlow platform rules (required headers, structure rules, accessor suffixes, DisplayText limitations, Repeater specifics, global variable allowlist) — consult `references/dc-platform-rules.md` when debugging deploy errors or validating a migrated flow manually. For a table of real deploy errors and their fixes, see `references/known-deploy-errors.md`. For which steps above still require the `sf` CLI vs. REST, and why, see `references/architecture-notes.md`.
355
+
356
+ ## What to check before activating
357
+
358
+ After deploying, open each DC flow in Flow Builder and verify:
359
+
360
+ 1. **Review transformer warnings** — any hoisted lookup that filtered on a screen field needs manual attention
361
+ 2. **Platform events removed** — if the original fired real-time dispatcher events, plan a replacement trigger (Apex or AutoLaunched flow)
362
+ 3. **`isRequired` on hidden fields** — clear `isRequired` and add a `validationRule` instead, for anything the transformer flagged
363
+ 4. **DisplayText formulas** — pre-calculate `IF`/`CASE`/date-math results in an Assignment and reference a simple variable instead
364
+ 5. **Calculation timing** — confirm the calculation element sits on a screen BEFORE the display screen, not on the same screen
365
+ 6. **Screen order and labels** — confirm the reordered screens still make sense
366
+ 7. **Lookup display** — confirm Lookup fields show the right label; adjust Primary Compact Layout if needed
367
+ 8. **`Range` slider fields** — replace manually with `dcNumeric` or `dcCounter`
368
+ 9. **Test on FSL Mobile** — complete the form end-to-end on a device
369
+ 10. **Test offline** — airplane mode + complete form → reconnect → verify sync
370
+
371
+ ---
372
+
373
+ ## Files in this skill
374
+
375
+ - **`scripts/transform_flow.py`** — primary migration tool; direct XML-to-XML transformer. Run on each source flow (Step 4).
376
+ - **`scripts/subflow_names.py`** — single source of truth for the migrated-subflow naming rule; imported by `transform_flow.py` and `discover_subflow_tree.py`.
377
+ - **`scripts/discover_subflow_tree.py`** — transitive subflow dependency discovery; builds the leaves-first order and classifies each node migratable/blocked/missing (Step 3b).
378
+ - **`scripts/analyze_flow.py`** — risk-assessment tool; runs on the source flow, produces JSON without modifying it (Step 7).
379
+ - **`scripts/convert_to_dc_spec.py`** — spec converter used for the migration summary (Step 4b); its JSON output must match `scripts/vendor/build_flow.py`'s input contract (see `references/converter-builder-contract.md`).
380
+ - **`scripts/generate_summary.py`** — renders the human-readable `migration-summary.md` from the spec JSON (Step 4b); deterministic and offline.
381
+ - **`scripts/validate_flow.sh`** — dry-run validator wrapping `sf project deploy start --dry-run`; exit `0`=all passed, `1`=≥1 failed, `2`=usage, `3`=skipped (no org) (Step 5).
382
+ - **`scripts/deploy_flow.sh`** — deploy kickoff + rollback snapshot; exit `0`=deployed, `1`=failed, `2`=usage, `3`=skipped, `4`=SE declined (Step 6).
383
+ - **`scripts/fsm_dc_catalog.py`** — authoritative FSM↔DC capability-parity catalog; `FIELD_TYPE_MAP` here must stay in sync with the mapping table in `references/transformer-rules.md`.
384
+ - `scripts/cud_analysis.py`, `scripts/flow_input.py`, `scripts/flow_xml_utils.py`, `scripts/json_to_flow_xml.py`, `scripts/manual_review_flags.py` — shared internals imported by the scripts above.
385
+ - `scripts/retrieve_flow_rest.sh` — experimental REST-based flow retrieval; not yet wired into Step 2 (see `references/architecture-notes.md`).
386
+ - `scripts/vendor/build_flow.py` — vendored Data Capture builder script consumed by `convert_to_dc_spec.py`'s contract.
387
+ - `references/fsm-dc-capability-catalog.md` — human-readable twin of `fsm_dc_catalog.py`; source of truth for supported/unsupported decisions.
388
+ - `references/component-mapping.md` — component equivalence table (companion to the catalog above).
389
+ - `references/converter-builder-contract.md` — authoritative JSON contract between `convert_to_dc_spec.py` and `build_flow.py`.
390
+ - `references/migration-checklist.md` — manual validation checklist for post-deploy testing.
391
+ - `assets/sample-legacy-flow.flow-meta.xml` — representative legacy `FieldServiceMobile` flow for trying the transformer end-to-end.
@@ -0,0 +1,163 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <Flow xmlns="http://soap.sforce.com/2006/04/metadata">
3
+ <apiVersion>58.0</apiVersion>
4
+ <label>Work Order Completion Form</label>
5
+ <processType>FieldServiceMobile</processType>
6
+ <status>Active</status>
7
+
8
+ <!-- Input variables -->
9
+ <variables>
10
+ <name>recordId</name>
11
+ <dataType>String</dataType>
12
+ <isInput>true</isInput>
13
+ <isOutput>false</isOutput>
14
+ </variables>
15
+
16
+ <!-- Screen 1: Basic Info -->
17
+ <screens>
18
+ <name>Screen_BasicInfo</name>
19
+ <label>Work Completion Details</label>
20
+ <allowBack>true</allowBack>
21
+ <allowFinish>true</allowFinish>
22
+ <allowPause>false</allowPause>
23
+ <showFooter>true</showFooter>
24
+ <fields>
25
+ <name>TechnicianName</name>
26
+ <extensionName>lightning:input</extensionName>
27
+ <fieldType>ComponentInstance</fieldType>
28
+ <inputParameters>
29
+ <name>type</name>
30
+ <value><stringValue>text</stringValue></value>
31
+ </inputParameters>
32
+ <inputParameters>
33
+ <name>label</name>
34
+ <value><stringValue>Technician Name</stringValue></value>
35
+ </inputParameters>
36
+ <inputParameters>
37
+ <name>required</name>
38
+ <value><booleanValue>true</booleanValue></value>
39
+ </inputParameters>
40
+ <isRequired>true</isRequired>
41
+ </fields>
42
+ <fields>
43
+ <name>CompletionDate</name>
44
+ <extensionName>lightning:input</extensionName>
45
+ <fieldType>ComponentInstance</fieldType>
46
+ <inputParameters>
47
+ <name>type</name>
48
+ <value><stringValue>date</stringValue></value>
49
+ </inputParameters>
50
+ <inputParameters>
51
+ <name>label</name>
52
+ <value><stringValue>Completion Date</stringValue></value>
53
+ </inputParameters>
54
+ <isRequired>true</isRequired>
55
+ </fields>
56
+ <fields>
57
+ <name>WorkPerformed</name>
58
+ <extensionName>lightning:textarea</extensionName>
59
+ <fieldType>ComponentInstance</fieldType>
60
+ <inputParameters>
61
+ <name>label</name>
62
+ <value><stringValue>Work Performed</stringValue></value>
63
+ </inputParameters>
64
+ <isRequired>true</isRequired>
65
+ </fields>
66
+ <connector>
67
+ <targetReference>Screen_Status</targetReference>
68
+ </connector>
69
+ </screens>
70
+
71
+ <!-- Screen 2: Status -->
72
+ <screens>
73
+ <name>Screen_Status</name>
74
+ <label>Work Status</label>
75
+ <allowBack>true</allowBack>
76
+ <allowFinish>true</allowFinish>
77
+ <allowPause>false</allowPause>
78
+ <showFooter>true</showFooter>
79
+ <fields>
80
+ <name>WorkStatus</name>
81
+ <extensionName>lightning:combobox</extensionName>
82
+ <fieldType>ComponentInstance</fieldType>
83
+ <inputParameters>
84
+ <name>label</name>
85
+ <value><stringValue>Work Status</stringValue></value>
86
+ </inputParameters>
87
+ <choiceReferences>choice_Completed</choiceReferences>
88
+ <choiceReferences>choice_PartiallyCompleted</choiceReferences>
89
+ <choiceReferences>choice_CannotComplete</choiceReferences>
90
+ <isRequired>true</isRequired>
91
+ </fields>
92
+ <fields>
93
+ <name>FollowUpRequired</name>
94
+ <extensionName>lightning:toggleButton</extensionName>
95
+ <fieldType>ComponentInstance</fieldType>
96
+ <inputParameters>
97
+ <name>label</name>
98
+ <value><stringValue>Follow-up Required?</stringValue></value>
99
+ </inputParameters>
100
+ <isRequired>false</isRequired>
101
+ </fields>
102
+ <connector>
103
+ <targetReference>Create_WorkOrderHistory</targetReference>
104
+ </connector>
105
+ </screens>
106
+
107
+ <!-- Choices -->
108
+ <choices>
109
+ <name>choice_Completed</name>
110
+ <choiceText>Completed</choiceText>
111
+ <dataType>String</dataType>
112
+ <value><stringValue>Completed</stringValue></value>
113
+ </choices>
114
+ <choices>
115
+ <name>choice_PartiallyCompleted</name>
116
+ <choiceText>Partially Completed</choiceText>
117
+ <dataType>String</dataType>
118
+ <value><stringValue>Partially Completed</stringValue></value>
119
+ </choices>
120
+ <choices>
121
+ <name>choice_CannotComplete</name>
122
+ <choiceText>Cannot Complete</choiceText>
123
+ <dataType>String</dataType>
124
+ <value><stringValue>Cannot Complete</stringValue></value>
125
+ </choices>
126
+
127
+ <!-- Record Create -->
128
+ <recordCreates>
129
+ <name>Create_WorkOrderHistory</name>
130
+ <label>Create Work Order History</label>
131
+ <locationX>176</locationX>
132
+ <locationY>500</locationY>
133
+ <inputAssignments>
134
+ <field>WorkOrderId</field>
135
+ <value><elementReference>recordId</elementReference></value>
136
+ </inputAssignments>
137
+ <inputAssignments>
138
+ <field>Field1</field>
139
+ <value><elementReference>TechnicianName</elementReference></value>
140
+ </inputAssignments>
141
+ <inputAssignments>
142
+ <field>Field2</field>
143
+ <value><elementReference>CompletionDate</elementReference></value>
144
+ </inputAssignments>
145
+ <inputAssignments>
146
+ <field>Field3</field>
147
+ <value><elementReference>WorkPerformed</elementReference></value>
148
+ </inputAssignments>
149
+ <inputAssignments>
150
+ <field>Status</field>
151
+ <value><elementReference>WorkStatus</elementReference></value>
152
+ </inputAssignments>
153
+ <object>WorkOrderHistory</object>
154
+ </recordCreates>
155
+
156
+ <start>
157
+ <locationX>50</locationX>
158
+ <locationY>0</locationY>
159
+ <connector>
160
+ <targetReference>Screen_BasicInfo</targetReference>
161
+ </connector>
162
+ </start>
163
+ </Flow>