@salesforce/afv-skills 1.58.0 → 1.60.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 (242) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-architecture-analyze/SKILL.md +66 -17
  3. package/skills/agentforce-architecture-analyze/assets/cli/show_access_token.yaml +4 -7
  4. package/skills/agentforce-architecture-analyze/references/contract.json +1 -1
  5. package/skills/agentforce-architecture-analyze/scripts/emit_env.py +2 -2
  6. package/skills/agentforce-architecture-analyze/scripts/main.py +40 -44
  7. package/skills/agentforce-architecture-analyze/scripts/rest_client.py +11 -3
  8. package/skills/agentforce-architecture-analyze/scripts/sf_cli.py +77 -10
  9. package/skills/agentforce-architecture-analyze/scripts/tests/test_end_to_end_fixture.py +1 -0
  10. package/skills/agentforce-architecture-analyze/scripts/tests/test_flow_children_inflation.py +1 -0
  11. package/skills/agentforce-architecture-analyze/scripts/tests/test_main_pipeline.py +53 -2
  12. package/skills/agentforce-architecture-analyze/scripts/tests/test_resolve_creds.py +184 -36
  13. package/skills/agentforce-architecture-analyze/scripts/tests/test_rest_client.py +17 -0
  14. package/skills/agentforce-architecture-analyze/scripts/tests/test_sf_cli.py +165 -11
  15. package/skills/agentforce-architecture-analyze/scripts/tests/test_skill_md_pipeline_block.py +319 -0
  16. package/skills/agentforce-bot-upgrade/SKILL.md +3 -1
  17. package/skills/agentforce-d360-analyze/SKILL.md +28 -10
  18. package/skills/agentforce-d360-analyze/scripts/dc.py +200 -50
  19. package/skills/agentforce-d360-analyze/scripts/discover_sessions.py +10 -6
  20. package/skills/agentforce-d360-analyze/scripts/fetch_dc.py +22 -6
  21. package/skills/agentforce-d360-analyze/scripts/resolve_session.py +21 -13
  22. package/skills/agentforce-d360-analyze/scripts/tests/test_dc_and_resolve_session.py +298 -76
  23. package/skills/agentforce-d360-analyze/scripts/tests/test_default_target_org.py +432 -0
  24. package/skills/agentforce-d360-analyze/scripts/tests/test_discover_sessions.py +1 -1
  25. package/skills/agentforce-d360-analyze/scripts/tests/test_resolve_session_main.py +9 -3
  26. package/skills/agentforce-d360-analyze/scripts/tests/test_skill_md_prefix_block.py +176 -0
  27. package/skills/agentforce-generate/SKILL.md +21 -1
  28. package/skills/agentforce-generate/references/known-issues.md +51 -1
  29. package/skills/agentforce-generate/references/legacy-nga-regression-eval.md +547 -0
  30. package/skills/agentforce-generate/references/upgrade-legacy-agent-to-agentscript.md +577 -0
  31. package/skills/agentforce-generate/scripts/upgrade-legacy-nga-analyze.py +404 -0
  32. package/skills/agentforce-generate/scripts/upgrade-legacy-nga-run-trials.sh +58 -0
  33. package/skills/agentforce-persona-generate/SKILL.md +505 -0
  34. package/skills/agentforce-persona-generate/assets/checklist-template.md +100 -0
  35. package/skills/agentforce-persona-generate/assets/persona-encoding-template.md +252 -0
  36. package/skills/agentforce-persona-generate/assets/persona-template.md +229 -0
  37. package/skills/agentforce-persona-generate/assets/sample-dialog-template.md +50 -0
  38. package/skills/agentforce-persona-generate/assets/workshop-outline-template.md +97 -0
  39. package/skills/agentforce-persona-generate/examples/concierge-persona.md +189 -0
  40. package/skills/agentforce-persona-generate/examples/concierge-sample-dialog.md +70 -0
  41. package/skills/agentforce-persona-generate/examples/drover-persona.md +194 -0
  42. package/skills/agentforce-persona-generate/examples/drover-sample-dialog.md +62 -0
  43. package/skills/agentforce-persona-generate/examples/steady-hand-persona.md +188 -0
  44. package/skills/agentforce-persona-generate/examples/steady-hand-sample-dialog.md +68 -0
  45. package/skills/agentforce-persona-generate/examples/yt-persona.md +195 -0
  46. package/skills/agentforce-persona-generate/examples/yt-sample-dialog.md +66 -0
  47. package/skills/agentforce-persona-generate/references/attributions.md +36 -0
  48. package/skills/agentforce-persona-generate/references/interaction-design-notes.md +30 -0
  49. package/skills/agentforce-persona-generate/references/persona-encoding-guide.md +566 -0
  50. package/skills/agentforce-persona-generate/references/persona-framework.md +796 -0
  51. package/skills/agentforce-persona-generate/references/refinement-mappings.md +31 -0
  52. package/skills/agentforce-persona-generate/references/scoring-rubric.md +58 -0
  53. package/skills/agentforce-persona-generate/references/voice-catalog.json +2327 -0
  54. package/skills/agentforce-persona-generate/references/workshop-question-policy.md +90 -0
  55. package/skills/agentforce-persona-generate/references/workshop-scenario-seeds.md +119 -0
  56. package/skills/agentforce-persona-generate/scripts/parse_agent_yaml.py +223 -0
  57. package/skills/consumer-goods-accruals-datakit-deploy/SKILL.md +17 -27
  58. package/skills/consumer-goods-accruals-datakit-deploy/scripts/setup.js +7 -17
  59. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/00-check-prerequisites.js +47 -63
  60. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/01-download-static-resource.js +10 -13
  61. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/02-replace-org-id.js +46 -46
  62. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/03-deploy-metadata.js +4 -21
  63. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/06-create-dataspace.js +58 -82
  64. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/07-deploy-accruals-reports.js +16 -315
  65. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/08-deploy-ui.js +9 -24
  66. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/09-completion.js +44 -44
  67. package/skills/consumer-goods-accruals-datakit-deploy/scripts/steps/utils.js +11 -63
  68. package/skills/consumer-goods-rtr-datacloud-export-configure/SKILL.md +2 -1
  69. package/skills/consumer-goods-tpe-dashboard-configure/SKILL.md +2 -1
  70. package/skills/consumer-goods-tpe-dashboard-custom-kpi-configure/SKILL.md +2 -1
  71. package/skills/consumer-goods-tpe-datakit-deploy/SKILL.md +2 -1
  72. package/skills/data360-schema-get/SKILL.md +3 -3
  73. package/skills/design-systems-slds-validate/references/report-format.md +1 -1
  74. package/skills/dx-app-analytics-query/SKILL.md +8 -8
  75. package/skills/dx-org-manage/SKILL.md +1 -0
  76. package/skills/dx-org-shape-manage/SKILL.md +1 -0
  77. package/skills/dx-org-snapshot-manage/SKILL.md +172 -0
  78. package/skills/dx-org-snapshot-manage/examples/create_error_output.json +16 -0
  79. package/skills/dx-org-snapshot-manage/examples/create_success_output.json +19 -0
  80. package/skills/dx-org-snapshot-manage/examples/delete_output.json +9 -0
  81. package/skills/dx-org-snapshot-manage/examples/get_output.json +19 -0
  82. package/skills/dx-org-snapshot-manage/examples/list_output.json +36 -0
  83. package/skills/dx-org-snapshot-manage/references/cli_flags.md +179 -0
  84. package/skills/dx-org-snapshot-manage/references/snapshot_usage.md +55 -0
  85. package/skills/dx-org-trial-expiration-check/SKILL.md +1 -1
  86. package/skills/dx-org-trial-expiration-check/scripts/check_expiration.sh +2 -2
  87. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +7 -5
  88. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +11 -11
  89. package/skills/experience-content-media-image-generate/SKILL.md +83 -0
  90. package/skills/experience-content-media-image-generate/scripts/download-image.sh +84 -0
  91. package/skills/experience-ui-bundle-app-coordinate/SKILL.md +12 -12
  92. package/skills/experience-ui-bundle-app-coordinate/references/phase-completion-validation.md +3 -3
  93. package/skills/experience-ui-bundle-app-coordinate/references/phase-execution-pattern.md +9 -7
  94. package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.mjs +132 -0
  95. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.mjs +62 -0
  96. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.mjs +71 -0
  97. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.mjs +95 -0
  98. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.mjs +78 -0
  99. package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.mjs +21 -0
  100. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.mjs +28 -0
  101. package/skills/experience-ui-bundle-custom-app-generate/SKILL.md +3 -1
  102. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.mjs +40 -0
  103. package/skills/experience-ui-bundle-frontend-generate/SKILL.md +7 -5
  104. package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.mjs +70 -0
  105. package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.mjs +76 -0
  106. package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.mjs +115 -0
  107. package/skills/experience-ui-bundle-metadata-generate/SKILL.md +7 -3
  108. package/skills/experience-ui-bundle-metadata-generate/references/angular-metadata-generate.md +1 -1
  109. package/skills/experience-ui-bundle-metadata-generate/references/react-metadata-generate.md +1 -1
  110. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.mjs +43 -0
  111. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.mjs +131 -0
  112. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.mjs +152 -0
  113. package/skills/experience-ui-bundle-mfa-configure/references/branding.md +10 -6
  114. package/skills/external-diagram-mermaid-generate/SKILL.md +12 -12
  115. package/skills/field-service-data-capture-migrate/references/component-mapping.md +1 -1
  116. package/skills/field-service-data-capture-migrate/references/fsm-dc-capability-catalog.md +1 -2
  117. package/skills/field-service-data-capture-migrate/references/known-deploy-errors.md +1 -0
  118. package/skills/field-service-data-capture-migrate/references/transformer-rules.md +1 -1
  119. package/skills/field-service-data-capture-migrate/scripts/transform_flow.py +12 -1
  120. package/skills/field-service-data-capture-migrate/scripts/vendor/build_flow.py +4 -1
  121. package/skills/field-service-setup-orchestrator-get/SKILL.md +0 -1
  122. package/skills/insurance-brokerage-agency-billing-configure/SKILL.md +233 -0
  123. package/skills/insurance-brokerage-agency-billing-configure/references/accounting-setup.md +117 -0
  124. package/skills/insurance-brokerage-agency-billing-configure/references/billing-rules-config.md +237 -0
  125. package/skills/insurance-brokerage-agency-billing-configure/references/billing-settings.md +271 -0
  126. package/skills/insurance-brokerage-agency-billing-configure/references/demo-policy-config.md +138 -0
  127. package/skills/insurance-brokerage-agency-billing-configure/references/org-defaults.md +64 -0
  128. package/skills/insurance-brokerage-agency-billing-configure/references/permissions-config.md +226 -0
  129. package/skills/insurance-brokerage-agency-billing-configure/references/prerequisites.md +142 -0
  130. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +3 -2
  131. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +3 -3
  132. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +68 -45
  133. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +17 -18
  134. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +16 -3
  135. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +16 -13
  136. package/skills/marketing-message-test/SKILL.md +194 -0
  137. package/skills/marketing-message-test/references/api-contract.md +333 -0
  138. package/skills/omnistudio-callable-apex-generate/SKILL.md +3 -3
  139. package/skills/omnistudio-datamapper-generate/SKILL.md +6 -6
  140. package/skills/omnistudio-datapacks-deploy/SKILL.md +11 -11
  141. package/skills/omnistudio-dependencies-analyze/SKILL.md +5 -5
  142. package/skills/omnistudio-epc-catalog-generate/SKILL.md +6 -6
  143. package/skills/omnistudio-flexcard-generate/SKILL.md +6 -6
  144. package/skills/omnistudio-integration-procedure-generate/SKILL.md +6 -6
  145. package/skills/omnistudio-omniscript-generate/SKILL.md +6 -5
  146. package/skills/platform-apex-logs-debug/SKILL.md +1 -0
  147. package/skills/platform-metadata-deploy/SKILL.md +1 -0
  148. package/skills/platform-models-api-configure/SKILL.md +5 -5
  149. package/skills/platform-soql-query/SKILL.md +1 -0
  150. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +17 -6
  151. package/skills/service-itsm-agentic-setup-incident-sla-configure/SKILL.md +107 -192
  152. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/attach-milestone-action.json +6 -6
  153. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/milestone-patterns.md +49 -20
  154. package/skills/service-itsm-agentic-setup-incident-sla-configure/examples/output-templates.md +4 -4
  155. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/mcp-invocation.md +224 -290
  156. package/skills/service-itsm-agentic-setup-incident-sla-configure/references/workflow.md +295 -0
  157. package/skills/service-itsm-incident-priority-configure/SKILL.md +1 -1
  158. package/skills/service-itsm-slack-itservice-configure/SKILL.md +2 -1
  159. package/skills/service-itsm-slack-itservice-configure/references/manage-slack-connection.md +2 -2
  160. package/skills/service-omni-channel-setup-coordinate/SKILL.md +20 -13
  161. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +5 -55
  162. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +0 -38
  163. package/skills/service-omni-command-center-analyze/SKILL.md +2 -3
  164. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +3 -3
  165. package/skills/tableau-next-asset-create/README.md +65 -0
  166. package/skills/tableau-next-asset-create/SKILL.md +409 -0
  167. package/skills/tableau-next-asset-create/references/admin-users.md +149 -0
  168. package/skills/tableau-next-asset-create/references/ai-readiness.md +355 -0
  169. package/skills/tableau-next-asset-create/references/alerts.md +111 -0
  170. package/skills/tableau-next-asset-create/references/build-workflow.md +819 -0
  171. package/skills/tableau-next-asset-create/references/dashboard-authoring.md +302 -0
  172. package/skills/tableau-next-asset-create/references/dashboard-design-principles.md +352 -0
  173. package/skills/tableau-next-asset-create/references/data-transform-gotchas.md +210 -0
  174. package/skills/tableau-next-asset-create/references/data-understanding.md +387 -0
  175. package/skills/tableau-next-asset-create/references/deep-reference-index.md +74 -0
  176. package/skills/tableau-next-asset-create/references/destructive-operations.md +62 -0
  177. package/skills/tableau-next-asset-create/references/edit-dashboard.md +273 -0
  178. package/skills/tableau-next-asset-create/references/edit-visualization.md +529 -0
  179. package/skills/tableau-next-asset-create/references/empty-source-handling.md +104 -0
  180. package/skills/tableau-next-asset-create/references/ingest-and-metric-gotchas.md +638 -0
  181. package/skills/tableau-next-asset-create/references/insight-bundle.md +69 -0
  182. package/skills/tableau-next-asset-create/references/large-flat-file-handling.md +331 -0
  183. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_envelope.json +54 -0
  184. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/_shared-widget-fields.json +122 -0
  185. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/add_page.json +29 -0
  186. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/delete_page.json +27 -0
  187. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/discard_dashboard.json +11 -0
  188. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget.json +30 -0
  189. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/move_widget_to_page.json +30 -0
  190. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/place_widget_on_page.json +30 -0
  191. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_dashboard.json +16 -0
  192. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/remove_widget_from_page.json +26 -0
  193. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/rename_page.json +28 -0
  194. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/save_dashboard.json +18 -0
  195. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/undo.json +11 -0
  196. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_button_widget.json +69 -0
  197. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_container_widget.json +88 -0
  198. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_filter_widget.json +146 -0
  199. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_metric_widget.json +78 -0
  200. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_navigation_widget.json +80 -0
  201. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_parameter_widget.json +160 -0
  202. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_text_widget.json +103 -0
  203. package/skills/tableau-next-asset-create/references/schemas/edit-dashboard/upsert_visualization_widget.json +68 -0
  204. package/skills/tableau-next-asset-create/references/sdm-tool-reference.md +721 -0
  205. package/skills/tableau-next-asset-create/references/semantic-query-and-enrichment.md +355 -0
  206. package/skills/tableau-next-asset-create/references/shared-gates.md +322 -0
  207. package/skills/tableau-next-asset-create/references/sharing-and-promotion.md +306 -0
  208. package/skills/tableau-next-asset-create/references/tasks/ai-readiness-audit.md +51 -0
  209. package/skills/tableau-next-asset-create/references/tasks/analyze-data.md +48 -0
  210. package/skills/tableau-next-asset-create/references/tasks/build-dashboard.md +66 -0
  211. package/skills/tableau-next-asset-create/references/tasks/build-end-to-end.md +73 -0
  212. package/skills/tableau-next-asset-create/references/tasks/create-data-transform.md +51 -0
  213. package/skills/tableau-next-asset-create/references/tasks/create-viz.md +58 -0
  214. package/skills/tableau-next-asset-create/references/tasks/edit-dashboard.md +80 -0
  215. package/skills/tableau-next-asset-create/references/tasks/edit-sdm.md +106 -0
  216. package/skills/tableau-next-asset-create/references/tasks/edit-viz.md +40 -0
  217. package/skills/tableau-next-asset-create/references/tasks/enrich-model.md +68 -0
  218. package/skills/tableau-next-asset-create/references/tasks/ingest-flat-file.md +68 -0
  219. package/skills/tableau-next-asset-create/references/tasks/manage-alert.md +35 -0
  220. package/skills/tableau-next-asset-create/references/tasks/profile-dataset.md +47 -0
  221. package/skills/tableau-next-asset-create/references/tasks/promote-or-reuse.md +46 -0
  222. package/skills/tableau-next-asset-create/references/tasks/provision-user.md +39 -0
  223. package/skills/tableau-next-asset-create/references/tasks/query-model.md +92 -0
  224. package/skills/tableau-next-asset-create/references/tasks/review-verified-questions.md +42 -0
  225. package/skills/tableau-next-asset-create/references/tasks/share-asset.md +37 -0
  226. package/skills/tableau-next-asset-create/references/verified-questions.md +125 -0
  227. package/skills/tableau-next-asset-create/references/viz-authoring.md +992 -0
  228. package/skills/experience-ui-bundle-app-coordinate/scripts/check-dangling-refs.sh +0 -42
  229. package/skills/experience-ui-bundle-app-coordinate/scripts/check-hosting-target.sh +0 -26
  230. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-1-complete.sh +0 -35
  231. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-4-complete.sh +0 -47
  232. package/skills/experience-ui-bundle-app-coordinate/scripts/check-phase-6-ready.sh +0 -33
  233. package/skills/experience-ui-bundle-app-coordinate/scripts/check-prerequisites.sh +0 -20
  234. package/skills/experience-ui-bundle-app-coordinate/scripts/check-sfdx-project.sh +0 -15
  235. package/skills/experience-ui-bundle-custom-app-generate/scripts/resolve-uibundle-path.sh +0 -30
  236. package/skills/experience-ui-bundle-frontend-generate/scripts/check-preconditions.sh +0 -37
  237. package/skills/experience-ui-bundle-frontend-generate/scripts/resolve-ui-bundle.sh +0 -66
  238. package/skills/experience-ui-bundle-frontend-generate/scripts/verify-rules.sh +0 -58
  239. package/skills/experience-ui-bundle-metadata-generate/scripts/check-api-version.sh +0 -30
  240. package/skills/experience-ui-bundle-metadata-generate/scripts/detect-framework.sh +0 -73
  241. package/skills/experience-ui-bundle-metadata-generate/scripts/verify-bundle-location.sh +0 -118
  242. package/skills/service-itsm-agentic-setup-incident-sla-configure/assets/predefined-incident-policy.json +0 -102
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env node
2
+ // Verifies that a UI bundle was created under force-app/main/default/uiBundles/
3
+ // (and not at the repo root, which would be non-deployable), AND that the
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.
9
+ //
10
+ // If a custom output directory was used (--output-dir on the scaffold command),
11
+ // pass it as the second argument. The script then verifies the bundle exists
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.
15
+ //
16
+ // Usage: node verify-bundle-location.mjs <BundleName> [<CustomOutputDir>] [<framework>]
17
+ //
18
+ // Always invoke via `node` (never as a bare executable) so this works on
19
+ // Windows cmd/PowerShell as well as macOS/Linux/Git Bash.
20
+
21
+ import fs from "node:fs";
22
+ import path from "node:path";
23
+
24
+ const args = process.argv.slice(2);
25
+
26
+ if (args.length < 1 || args.length > 3) {
27
+ console.log("ERROR: Bundle name required");
28
+ console.log("Usage: node verify-bundle-location.mjs <BundleName> [<CustomOutputDir>] [<framework>]");
29
+ process.exit(1);
30
+ }
31
+
32
+ const BUNDLE_NAME = args[0];
33
+ const CUSTOM_OUTPUT_DIR = args[1] ?? "";
34
+ const FRAMEWORK = args[2] ?? "";
35
+
36
+ // Pick the remediation template and the expected entry-HTML location from the
37
+ // framework. When the framework is not supplied we stay lenient: default the
38
+ // hint to reactbasic and accept the entry index.html at either location.
39
+ let TEMPLATE;
40
+ let ENTRY;
41
+ switch (FRAMEWORK) {
42
+ case "angular":
43
+ TEMPLATE = "angularbasic";
44
+ ENTRY = "src/index.html";
45
+ break;
46
+ case "react":
47
+ TEMPLATE = "reactbasic";
48
+ ENTRY = "index.html";
49
+ break;
50
+ default:
51
+ TEMPLATE = "reactbasic";
52
+ ENTRY = "";
53
+ break;
54
+ }
55
+
56
+ function isFile(p) {
57
+ try {
58
+ return fs.statSync(p).isFile();
59
+ } catch {
60
+ return false;
61
+ }
62
+ }
63
+
64
+ function isDir(p) {
65
+ try {
66
+ return fs.statSync(p).isDirectory();
67
+ } catch {
68
+ return false;
69
+ }
70
+ }
71
+
72
+ // Checks that the scaffold actually produced a full project, not just
73
+ // hand-written metadata files. Returns false (and prints guidance) if
74
+ // incomplete.
75
+ function checkScaffoldComplete(bundlePath, outputDir = "") {
76
+ const missing = [];
77
+ if (!isFile(path.join(bundlePath, "package.json"))) missing.push("package.json");
78
+ if (!isDir(path.join(bundlePath, "src"))) missing.push("src/");
79
+ // Entry HTML lives at the bundle root for React and at src/index.html for
80
+ // Angular. When the framework is known, require the correct location; when
81
+ // it is unknown, accept either.
82
+ if (ENTRY) {
83
+ if (!isFile(path.join(bundlePath, ENTRY))) missing.push(ENTRY);
84
+ } else if (!isFile(path.join(bundlePath, "index.html")) && !isFile(path.join(bundlePath, "src", "index.html"))) {
85
+ missing.push("index.html");
86
+ }
87
+
88
+ if (missing.length > 0) {
89
+ let scaffoldCmd = `sf template generate ui-bundle -n ${BUNDLE_NAME} --template ${TEMPLATE}`;
90
+ if (outputDir) {
91
+ scaffoldCmd = `${scaffoldCmd} --output-dir "${outputDir}"`;
92
+ }
93
+ console.error(`ERROR: Bundle found at ${bundlePath}, but the scaffold is incomplete. Missing:`);
94
+ for (const item of missing) {
95
+ console.error(` - ${item}`);
96
+ }
97
+ console.error("");
98
+ console.error("This usually means 'sf template generate ui-bundle' was never run — metadata");
99
+ console.error("files alone were hand-authored instead. Run the scaffold command now:");
100
+ console.error(` ${scaffoldCmd}`);
101
+ console.error("Metadata files are configuration ON TOP of the scaffold, not a substitute for it.");
102
+ return false;
103
+ }
104
+ return true;
105
+ }
106
+
107
+ if (CUSTOM_OUTPUT_DIR) {
108
+ const customPath = path.join(CUSTOM_OUTPUT_DIR, BUNDLE_NAME);
109
+ if (isDir(customPath)) {
110
+ if (checkScaffoldComplete(customPath, CUSTOM_OUTPUT_DIR)) {
111
+ console.log(`OK: Bundle found at ${customPath} (custom output-dir location, scaffold complete)`);
112
+ process.exit(0);
113
+ }
114
+ process.exit(1);
115
+ }
116
+ console.log(`ERROR: Bundle not found at custom output-dir location: ${customPath}`);
117
+ console.log("Check that --output-dir matched what was passed to the scaffold command.");
118
+ process.exit(1);
119
+ }
120
+
121
+ const EXPECTED_PATH = path.join("force-app", "main", "default", "uiBundles", BUNDLE_NAME);
122
+ const WRONG_PATH = path.join("uiBundles", BUNDLE_NAME);
123
+
124
+ if (isDir(EXPECTED_PATH)) {
125
+ if (checkScaffoldComplete(EXPECTED_PATH)) {
126
+ console.log(`OK: Bundle found at ${EXPECTED_PATH} (deployable location, scaffold complete)`);
127
+ process.exit(0);
128
+ }
129
+ process.exit(1);
130
+ }
131
+
132
+ if (isDir(WRONG_PATH)) {
133
+ console.log(`ERROR: Bundle found at repo root: ${WRONG_PATH}`);
134
+ console.log("This location is NOT deployable. The SFDX deploy command will not find it.");
135
+ console.log("");
136
+ console.log("To fix: Move the bundle to force-app/main/default/uiBundles/");
137
+ console.log(` Create the directory force-app/main/default/uiBundles/ (if it doesn't exist),`);
138
+ console.log(` then move ${WRONG_PATH} to ${EXPECTED_PATH}.`);
139
+ console.log("");
140
+ checkScaffoldComplete(WRONG_PATH);
141
+ process.exit(1);
142
+ }
143
+
144
+ console.log("ERROR: Bundle not found at either location:");
145
+ console.log(` - Expected: ${EXPECTED_PATH}`);
146
+ console.log(` - Also checked: ${WRONG_PATH}`);
147
+ console.log("");
148
+ console.log("If a custom --output-dir was used, re-run this script with that directory");
149
+ console.log(`as the second argument: node verify-bundle-location.mjs ${BUNDLE_NAME} <CustomOutputDir>`);
150
+ console.log("");
151
+ console.log("Otherwise, the scaffold command may have failed. Check for errors above.");
152
+ process.exit(1);
@@ -15,9 +15,11 @@ The MFA challenge page and login page are platform-rendered. Their branding is c
15
15
 
16
16
  ## Retrieve existing branding
17
17
 
18
- ```bash
19
- # Create a package.xml manifest
20
- cat > /tmp/branding-pkg.xml <<'EOF'
18
+ Create a package.xml manifest at `manifest/branding-pkg.xml` in the project (a
19
+ plain file write — avoid a shell heredoc, since `<<EOF` and `/tmp` are not
20
+ portable to Windows cmd/PowerShell) with this content:
21
+
22
+ ```xml
21
23
  <?xml version="1.0" encoding="UTF-8"?>
22
24
  <Package xmlns="http://soap.sforce.com/2006/04/metadata">
23
25
  <types>
@@ -26,11 +28,13 @@ cat > /tmp/branding-pkg.xml <<'EOF'
26
28
  </types>
27
29
  <version>62.0</version>
28
30
  </Package>
29
- EOF
31
+ ```
30
32
 
31
- # Retrieve from org
33
+ Then retrieve from the org:
34
+
35
+ ```bash
32
36
  sf project retrieve start --target-org <org-alias> \
33
- --manifest /tmp/branding-pkg.xml \
37
+ --manifest manifest/branding-pkg.xml \
34
38
  --target-metadata-dir ./branding-retrieve --unzip
35
39
  ```
36
40
 
@@ -2,6 +2,18 @@
2
2
  name: external-diagram-mermaid-generate
3
3
  description: "Salesforce architecture diagrams using Mermaid with ASCII fallback. Use this skill when generating text-based diagrams for Salesforce architecture, OAuth flows, ERDs, integration sequences, or Agentforce structure. TRIGGER when: user says \"diagram\", \"visualize\", \"ERD\", or asks for sequence diagrams, flowcharts, class diagrams, or architecture visualizations in Mermaid. DO NOT TRIGGER when: user asks about non-Salesforce systems."
4
4
  metadata:
5
+ version: "1.0"
6
+ domains: ["External"]
7
+ relatedSkills:
8
+ - "agentforce-generate"
9
+ - "automation-flow-generate"
10
+ - "integration-connectivity-connected-app-configure"
11
+ - "integration-connectivity-generate"
12
+ - "platform-apex-generate"
13
+ - "platform-custom-field-generate"
14
+ - "platform-custom-object-generate"
15
+ - "platform-data-manage"
16
+ - "platform-metadata-deploy"
5
17
  cliTools:
6
18
  - tool: ["curl"]
7
19
  semver: ">=7.0.0"
@@ -13,18 +25,6 @@ metadata:
13
25
  semver: ">=3.10.0"
14
26
  - tool: ["sf"]
15
27
  semver: ">=2.0.0"
16
- relatedSkills:
17
- - "agentforce-generate"
18
- - "automation-flow-generate"
19
- - "integration-connectivity-connected-app-configure"
20
- - "integration-connectivity-generate"
21
- - "platform-apex-generate"
22
- - "platform-custom-field-generate"
23
- - "platform-custom-object-generate"
24
- - "platform-data-manage"
25
- - "platform-metadata-deploy"
26
- version: "1.0"
27
- domains: ["External"]
28
28
  ---
29
29
 
30
30
  # external-diagram-mermaid-generate: Salesforce Diagram Generation
@@ -174,7 +174,7 @@ preserves these but flags for offline-priming verification.
174
174
  | Legacy parameter | DC parameter | Notes |
175
175
  |---|---|---|
176
176
  | `label` | `label` | Direct map for ComponentInstance fields |
177
- | `required` | Field-level `<isRequired>` | Moved from parameter to field attribute |
177
+ | `required` | Field-level `<isRequired>` **and** a `required` inputParameter | `ComponentInstance` fields read required-ness from the inputParameter at DC runtime, not `<isRequired>` alone — transformer emits both. Exception: `dcCheckbox`/`dcToggle` don't expose a `required` input attribute; only `<isRequired>` is set for those. |
178
178
  | `placeholder` | *(not supported)* | Bake into label text |
179
179
  | `disabled` / `readOnly` | `isDisabled` / `isReadonly` | Available on some DC components |
180
180
  | `helpText` | *(not supported)* | Bake into label or use DisplayText |
@@ -24,8 +24,7 @@ A `lightning:*` / `forceContent:*` / `c:*` name only ever appears as the
24
24
  Two inputs were reconciled:
25
25
 
26
26
  1. The **assessment spreadsheet** — *FSM Flow vs Data Capture Flow component
27
- assessment*
28
- ([sheet](https://docs.google.com/spreadsheets/d/1KeZPHw4AN8XxqxoTh4X9ciLavp9JNcOeYDbSzmCATGg/edit)).
27
+ assessment*.
29
28
  2. **Salesforce core code** (core-2206, 264 release line), which is
30
29
  authoritative where the two disagree.
31
30
 
@@ -34,3 +34,4 @@ These were encountered in real migration runs. All are handled automatically by
34
34
  | `Error while resolving default value reference` *(runtime — not deploy)* | Complex formula in `DisplayText` (`IF`, `CASE`, date math) | Transformer warns; pre-calculate in Assignment → reference simple variable in DisplayText |
35
35
  | `isRequired=true` blocks hidden field *(runtime — not deploy)* | Required check fires even when field is hidden behind `visibilityRule` | Transformer warns; manually clear `isRequired` and add `validationRule` |
36
36
  | `outputAssignments` in `dynamicChoiceSets` populates blank *(runtime — not deploy)* | `outputAssignments` inside choice sets deploys but does NOT populate variables at mobile runtime | Replace with post-selection `recordLookups` using `outputAssignments` |
37
+ | `We can't find this input attribute: "required"` on `dcCheckbox` / `dcToggle` | These boolean-backed components don't expose a `required` input attribute — unlike other `ComponentInstance` types, they don't need one to enforce required-ness | Transformer skips the `required` inputParameter injection for `dcCheckbox`/`dcToggle` extensions; `<isRequired>` is still set |
@@ -91,7 +91,7 @@ the `transform_flow.py` restructurer, which rewrites the flow XML connectors in
91
91
  - Strips fault connectors from all elements (not supported in DataCaptureFlow)
92
92
  - Removes platform event `<recordCreates>` nodes (DC can't create non-UI entities like `AsgnResourceLocUpdateEvent`) — **side effect: those events will no longer fire**
93
93
  - Removes `<outputAssignments>` from screen fields → replaced with `storeOutputAutomatically=true` + an injected `<assignments>` node to preserve variable bindings
94
- - Strips invalid `<inputParameters>`: `required`, `disabled`, `multiple`, `accept`, `helpText`, `placeholder` (none supported in DC; bake content into label text instead)
94
+ - Strips invalid incoming `<inputParameters>`: `required`, `disabled`, `multiple`, `accept`, `helpText`, `placeholder` (not carried over as-is from the legacy field). `disabled`/`helpText`/`placeholder`/`multiple`/`accept` stay stripped (bake content into label text instead). `required` is different: it's re-added as a computed inputParameter (from `<isRequired>`) on most `ComponentInstance` fields, since the DC runtime reads required-ness from the inputParameter, not `<isRequired>`, for those — except `dcCheckbox`/`dcToggle`, which don't expose a `required` input attribute at all and get only `<isRequired>`
95
95
  - Replaces `minimumDate`/`maximumDate` with `minDate`/`maxDate` on date fields
96
96
  - Replaces `multiSelection` with `isMultiSelection` on Lookup fields
97
97
  - Replaces `disabled`/`readOnly` with `isDisabled`/`isReadonly` (note lowercase `o`) on Lookup fields
@@ -267,6 +267,17 @@ CHOICE_REQUIRED = {
267
267
  # Invalid inputParameter names on dc* components
268
268
  INVALID_PARAMS = frozenset(('required', 'disabled', 'multiple', 'accept', 'helpText', 'placeholder'))
269
269
 
270
+ # dc* ComponentInstance extensions that do NOT expose a `required` input
271
+ # attribute — injecting one deploys as "We can't find this input attribute:
272
+ # 'required'". Confirmed for dcCheckbox (W-24086520); dcToggle is the other
273
+ # boolean-backed component and excluded on the same rationale: an unchecked/
274
+ # off boolean is itself a valid answer, so these components have no notion of
275
+ # "required" distinct from <isRequired> already being set on the field.
276
+ NO_REQUIRED_INPUT_PARAM_EXTENSIONS = frozenset((
277
+ 'runtime_service_fieldservice:dcCheckbox',
278
+ 'runtime_service_fieldservice:dcToggle',
279
+ ))
280
+
270
281
  # ──────────────────────────────────────────────
271
282
  # Phase 1: Screen field transformation
272
283
  # ──────────────────────────────────────────────
@@ -389,7 +400,7 @@ def _apply_component_type(field: ET.Element, new_ft: str, new_ext: str, label_st
389
400
  # don't need this — they read <isRequired> directly.)
390
401
  is_required = (findtext(field, 'isRequired') or 'false').lower() == 'true'
391
402
  has_required_param = any(findtext(p, 'name') == 'required' for p in findall(field, 'inputParameters'))
392
- if not has_required_param:
403
+ if not has_required_param and new_ext not in NO_REQUIRED_INPUT_PARAM_EXTENSIONS:
393
404
  ip = make('inputParameters')
394
405
  ip.append(make('name', 'required'))
395
406
  v = sub(ip, 'value')
@@ -719,7 +719,10 @@ def render_field(field: Field, spec: FormSpec, indent: str = " ") -> str:
719
719
  parts.append(f"{indent} <extensionName>{x(extension_name)}</extensionName>\n")
720
720
  parts.append(f"{indent} <fieldType>ComponentInstance</fieldType>\n")
721
721
  parts.append(render_input_param("label", label, indent=inner))
722
- if field.is_required:
722
+ # dcCheckbox/dcToggle don't expose a `required` input attribute — an
723
+ # unchecked/off boolean is itself a valid answer, so deploying `required`
724
+ # on these fails with "We can't find this input attribute: 'required'".
725
+ if field.is_required and field.field_type not in ("Checkbox", "Toggle"):
723
726
  parts.append(render_input_param("required", boolean_value=True, indent=inner))
724
727
  if field.field_type == "Counter":
725
728
  if field.counter_min is not None:
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: field-service-setup-orchestrator-get
3
3
  description: "Use this skill to set up Salesforce Field Service — Work Types, Skills, Service Territories, Operating Hours, Scheduling Policy, Work Rules, Service Objectives, Data Capture Forms, FSL mobile forms, Pre-Work Brief, Mobile Branding, or any FSL setup, enablement, or configuration request. Entry point that identifies what the user wants to configure and routes to the right sub-workflow: Foundation Setup, Scheduling Policy, Data Capture Forms, Pre-Work Brief, or Mobile Branding."
4
- user-invocable: false
5
4
  owning_team: sfs-setup-experience
6
5
  metadata:
7
6
  version: "1.0"
@@ -0,0 +1,233 @@
1
+ ---
2
+ name: insurance-brokerage-agency-billing-configure
3
+ description: "Configure end-to-end Agency Billing on a Salesforce FSC Insurance Brokerage org via dispatch MCP calls. Use this skill when users want to set up brokerage billing, configure agency billing, enable insurance billing features, create billing rules, set up accounting periods, assign billing permission sets, or create a demo policy for the Issue-to-Invoice flow. TRIGGER when: user mentions agency billing setup, brokerage billing configuration, insurance billing enablement, billing treatments, billing rules creation, accounting period setup, insurance policy billing information, or Issue-to-Invoice testing. Also use when users say things like set up my brokerage org for billing, configure billing on my insurance org, enable billing features, create billing treatments, set up GL accounts, or assign billing permissions. DO NOT TRIGGER when: user needs general Revenue Cloud Billing without insurance context, needs CPQ/quoting configuration, or needs claims processing setup."
4
+ metadata:
5
+ version: "2.0"
6
+ minApiVersion: "66.0"
7
+ accessCheck:
8
+ - type: "license"
9
+ value: "InsuranceBrokerageFoundationPsl"
10
+ ---
11
+
12
+ # Insurance Brokerage Agency Billing Configuration
13
+
14
+ Automates the full Agency Billing setup on a Salesforce FSC Insurance Brokerage org. Runs 7 sequential phases using `dispatch` MCP calls to verify licenses, enable features, **assign permissions early**, configure billing settings, create billing rules, set org defaults, set up accounting, and create a demo policy for Issue-to-Invoice testing. **Phase order is critical**: permissions must be assigned before billing settings configuration.
15
+
16
+ ## Scope
17
+
18
+ - **In scope**: License verification, feature enablement (Context Service, Brokerage, Billing, Salesforce Pricing), billing settings configuration, billing rules creation (Legal Entity, Billing Treatments, Tax Engine, Payment Terms, Product Selling Models, Proration Policy), accounting setup (periods, GL accounts, GLAAR rules), permission set assignment, FLS creation via metadata endpoint, and demo policy creation.
19
+ - **Out of scope**: Revenue Cloud CPQ/quoting, claims processing, policy administration workflows, custom Apex development, LWC UI components. Data Pipelines (Sonic) requires an org-level `SonicLicensedOrg` feature not present on standard brokerage orgs — enable it manually if needed.
20
+ - **All phases fully automated** via `dispatch` (headless routes + Metadata CRUD + Tooling API). No manual steps, no SF CLI, no gaps.
21
+
22
+ ---
23
+
24
+ ## CRITICAL — Standard Field Names (no __c anywhere)
25
+
26
+ Every field in this workflow is STANDARD. Never append `__c` to any field name. Here are the correct API names:
27
+
28
+ | Object | Field (correct) | WRONG (never use) |
29
+ |--------|----------------|-------------------|
30
+ | BillingTreatment | Status | ~~Status__c~~ |
31
+ | TaxEngine | TaxEngineName | ~~TaxEngineName__c~~ |
32
+ | PaymentTerm | DaysDue | ~~DaysDue__c~~ |
33
+ | PaymentTerm / PaymentTermItem | PeriodUnit | ~~PeriodUnit__c~~ |
34
+ | PaymentTerm | Active | ~~Active__c~~ |
35
+ | LegalEntity | Active | ~~Active__c~~ |
36
+ | BillingTreatmentItem | ChargeType | ~~ChargeType__c~~ |
37
+ | BillingTreatmentItem | BillingType | ~~BillingType__c~~ |
38
+ | BillingTreatmentItem | Active | ~~Active__c~~ |
39
+ | ProductSellingModel | Active | ~~Active__c~~ |
40
+
41
+ ---
42
+
43
+ ## Required Inputs
44
+
45
+ Do not ask the user for any information — proceed autonomously using defaults and the pre-configured environment.
46
+
47
+ - **Authenticated org**: The default target org is pre-configured in the MCP environment. Verify connectivity by calling `dispatch GET /chatter/users/me`.
48
+ - **Target user ID**: Capture the `id` field from the `/chatter/users/me` response and use it as AssigneeId for all license and permission assignments throughout all phases.
49
+
50
+ Defaults (always apply unless the user explicitly overrides in their initial prompt):
51
+ - All 7 phases execute in sequence
52
+ - Demo policy uses configuration from `references/demo-policy-config.md`
53
+ - Billing rules use configuration from `references/billing-rules-config.md`
54
+ - Permission sets from `references/permissions-config.md`
55
+
56
+ ---
57
+
58
+ ## Workflow
59
+
60
+ All phases are sequential. Do not skip or reorder. **Critical cross-dependencies:**
61
+ - Phase 2 (Permissions) MUST run before Phase 3 (Billing Settings) — many billing settings require billing admin permissions
62
+ - Phase 2 (Permissions) MUST run before Phase 4 (Billing Rules) — BillingTreatment object access requires permissions
63
+ - Phase 2 (Permissions) MUST run before Phase 7 (Demo Policy) — InsPolicyBillingInfo fields require permissions + propagation time
64
+
65
+ Follow the execution order below exactly.
66
+
67
+ ### Phase 1 — Prerequisites
68
+
69
+ 1. **Verify org connectivity and capture target user ID** — call `dispatch GET /chatter/users/me` and confirm a 200 response. **Capture the `id` field from the response and store it as `TARGET_USER_ID` — this SAME ID must be used throughout ALL phases for license assignments, permission set assignments, and any user-specific operations.** If Chatter is disabled, fall back to querying the User object: `dispatch GET /query?q=SELECT+Id,Username,Name+FROM+User+WHERE+IsActive=true+AND+Profile.Name+LIKE+'%25System+Administrator%25'+LIMIT+1` and capture the `Id` field from the first record.
70
+
71
+ **CRITICAL:** Do not re-query for the user ID in later phases. Use the same `TARGET_USER_ID` captured here for all subsequent operations. Re-querying can return a different user if multiple admins exist.
72
+
73
+ 2. **Verify 19 required licenses** — read `references/prerequisites.md` for the full license list. Use `dispatch GET /query?q=<SOQL>` to query `PermissionSetLicense` records. If any are missing from the org, stop and inform the user.
74
+
75
+ 3. **Assign missing licenses to target user** — query `PermissionSetLicenseAssign` for the `TARGET_USER_ID` captured in step 1. Assign any missing licenses via `dispatch POST /sobjects/PermissionSetLicenseAssign` using the same `TARGET_USER_ID`.
76
+
77
+ 4. **Enable features** — read `references/prerequisites.md` for the feature enablement sequence and exact routes. Each feature is a read → write → verify cycle. Enable in order: Context Service, Brokerage, Billing, Salesforce Pricing.
78
+
79
+ > Features MUST be enabled in dependency order. Context Service before Brokerage, Brokerage before Billing.
80
+
81
+ ### Phase 2 — Permissions Assignment (moved from Phase 6)
82
+
83
+ 5. **Assign permission sets EARLY** — read `references/permissions-config.md` for the 15 required sets. Query current assignments, assign only missing ones via `dispatch POST /sobjects/PermissionSetAssignment`. **This must run before Phase 3 (Billing Settings) because several billing settings require these permissions to modify.**
84
+
85
+ 6. **Create custom permission set with FLS for InsPolicyBillingInfo billing lookup fields** — **MANDATORY STEP, CANNOT BE SKIPPED UNDER ANY CIRCUMSTANCES.** The 6 billing lookup fields on InsPolicyBillingInfo require Field-Level Security to be visible: BillingTreatmentId, TaxTreatmentId, ProrationPolicyId, PaymentTermId, ProductSellingModelId, LegalEntityId. Without this FLS, Phase 7 will fail with INVALID_FIELD errors when creating InsPolicyBillingInfo records.
86
+
87
+ **CRITICAL: ALWAYS attempt to create the permission set — DO NOT skip this step based on FLS query results.** Even if FieldPermissions query shows FLS is already granted via another permission set, you MUST attempt to create the `Insurance_Billing_Field_Access` permission set. If it already exists, the API will return DUPLICATE_VALUE — treat this as success and continue.
88
+
89
+ **Step 1 — Verify FLS (for diagnostic purposes only, NOT a gate for creation):**
90
+ ```text
91
+ dispatch GET /query?q=SELECT+Field+FROM+FieldPermissions+WHERE+SobjectType='InsPolicyBillingInfo'+AND+Field+IN+('InsPolicyBillingInfo.BillingTreatmentId','InsPolicyBillingInfo.TaxTreatmentId','InsPolicyBillingInfo.ProrationPolicyId','InsPolicyBillingInfo.PaymentTermId','InsPolicyBillingInfo.ProductSellingModelId','InsPolicyBillingInfo.LegalEntityId')+AND+PermissionsRead=true+AND+PermissionsEdit=true
92
+ ```
93
+
94
+ **Step 2 — UNCONDITIONALLY create the permission set (DO NOT skip regardless of Step 1 results):**
95
+ ```text
96
+ dispatch POST /services/data/v66.0/headless/metadata
97
+ {
98
+ "type": "PermissionSet",
99
+ "fullName": "Insurance_Billing_Field_Access",
100
+ "xmlRep": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><PermissionSet xmlns=\"http://soap.sforce.com/2006/04/metadata\"><fieldPermissions><field>InsPolicyBillingInfo.BillingTreatmentId</field><readable>true</readable><editable>true</editable></fieldPermissions><fieldPermissions><field>InsPolicyBillingInfo.TaxTreatmentId</field><readable>true</readable><editable>true</editable></fieldPermissions><fieldPermissions><field>InsPolicyBillingInfo.ProrationPolicyId</field><readable>true</readable><editable>true</editable></fieldPermissions><fieldPermissions><field>InsPolicyBillingInfo.PaymentTermId</field><readable>true</readable><editable>true</editable></fieldPermissions><fieldPermissions><field>InsPolicyBillingInfo.ProductSellingModelId</field><readable>true</readable><editable>true</editable></fieldPermissions><fieldPermissions><field>InsPolicyBillingInfo.LegalEntityId</field><readable>true</readable><editable>true</editable></fieldPermissions><hasActivationRequired>false</hasActivationRequired><label>Insurance Billing Field Access</label><description>Grants FLS for InsPolicyBillingInfo billing lookup fields</description></PermissionSet>"
101
+ }
102
+ ```
103
+
104
+ **Expected outcomes:**
105
+ - Success (new creation): `{ results: [{ success: true, id: "0PS...", fullName: "Insurance_Billing_Field_Access" }] }` — capture the `id` field.
106
+ - DUPLICATE_VALUE (already exists): `{ results: [{ success: false, errors: [{ statusCode: "DUPLICATE_VALUE" }] }] }` — the permission set exists; proceed to reconciliation step below.
107
+
108
+ 7. **Reconcile FieldPermissions — MANDATORY, DO NOT SKIP.** A pre-existing `Insurance_Billing_Field_Access` permission set may be missing some of the 6 required entries. Resolve the permission set ID, query its FieldPermissions, and for each of the 6 required fields (`InsPolicyBillingInfo.BillingTreatmentId`, `.TaxTreatmentId`, `.ProrationPolicyId`, `.PaymentTermId`, `.ProductSellingModelId`, `.LegalEntityId`) that is missing or has read/edit false: create or PATCH the FieldPermissions record. See `references/permissions-config.md` § "Reconcile Field Permissions" for the exact API calls. Only after all 6 fields are confirmed read+edit proceed to assignment.
109
+
110
+ 8. **Assign the permission set to target user** — **MANDATORY STEP, DO NOT SKIP.** Query for the permission set ID (whether you just created it or it already existed), then verify assignment status and create the assignment if missing.
111
+
112
+ **First, resolve the permission set ID:**
113
+ ```text
114
+ dispatch GET /query?q=SELECT+Id+FROM+PermissionSet+WHERE+Name='Insurance_Billing_Field_Access'+AND+IsOwnedByProfile=false
115
+ ```
116
+
117
+ **Then check if already assigned:**
118
+ ```text
119
+ dispatch GET /query?q=SELECT+Id+FROM+PermissionSetAssignment+WHERE+AssigneeId='<TARGET_USER_ID>'+AND+PermissionSetId='<PS_ID>'
120
+ ```
121
+
122
+ **If the assignment query returns 0 records, create the assignment:**
123
+ ```text
124
+ dispatch POST /sobjects/PermissionSetAssignment
125
+ {"AssigneeId": "<TARGET_USER_ID>", "PermissionSetId": "<PS_ID>"}
126
+ ```
127
+
128
+ If the assignment POST returns DUPLICATE_VALUE, the user already has it assigned between your query and now (treat as success). Any other error is a failure and must be reported.
129
+
130
+ ### Phase 3 — Billing Settings (requires Phase 2 permissions)
131
+
132
+ 7. **Read current billing settings** — read `references/billing-settings.md` for the full settings map and routes. Call `dispatch GET /headless/invoke/platform/billing-settings/get-billing-general-setting-states` to read current state.
133
+
134
+ 8. **Write only changed settings** — compare each field against desired state and write only what differs. Enable Design Document Templates via `dispatch PATCH /headless/invoke/platform/accounting-guided-setup/setup-billing-doc-gen-and-fetch-invoice-template-data` (must run after billing is on). InsuranceBrokerage IPT/IPTD settings are now automated via `PATCH /setup/org/values/I_P_T_D_ENABLED_FOR_BROKERAGE` and `PATCH /setup/org/values/I_P_T_ENABLED_FOR_BROKERAGE`.
135
+
136
+ > **If any setting returns "Access denied":** Phase 2 permissions did not propagate yet. Wait 30 seconds and retry.
137
+
138
+ ### Phase 4 — Billing Rules (requires Phase 2 permissions for BillingTreatment object access)
139
+
140
+ 9. **Query existing billing rules** — for each record type (Legal Entity, Billing Treatments, Tax Engine, Tax Treatment, Payment Term, Product Selling Models, Proration Policy), use `dispatch GET /query?q=<SOQL>` before creating. Read `references/billing-rules-config.md` for exact field values and search patterns.
141
+
142
+ 10. **Create only missing records** — use `dispatch POST /sobjects/<Object>` for creates and `dispatch PATCH /sobjects/<Object>/<id>` for updates. For Billing Treatments, follow the Draft→Items→Activate sequence. Track all record IDs.
143
+
144
+ > Billing Treatments must be created in Draft, child Items created in Active, then parent activated. This is enforced by the platform.
145
+
146
+ ### Phase 5 — Org Defaults
147
+
148
+ 11. **Set billing defaults** — read `references/org-defaults.md`. Set the five default fields (Legal Entity, Billing Treatment, Tax Treatment, two DPE definitions) via dedicated headless routes. Use record IDs from Phase 4.
149
+
150
+ ### Phase 6 — Accounting
151
+
152
+ 12. **Create accounting periods** — read `references/accounting-setup.md`. Compute dates at runtime for the current fiscal year. Query existing periods via `dispatch GET /query?q=<SOQL>`, create only missing months via `dispatch POST /sobjects/AccountingPeriod`. Link periods to Legal Entity via `LegalEntyAccountingPeriod`.
153
+
154
+ 13. **Create GL accounts** — query by `AccountingCode`, create only missing accounts (11 total) via `dispatch POST /sobjects/GeneralLedgerAccount`. Link each to the Legal Entity.
155
+
156
+ 14. **Create GLAAR rules** — query existing rules, create parent `GeneralLedgerAcctAsgntRule` + child `GeneralLedgerJrnlEntryRule` if missing.
157
+
158
+ ### Phase 7 — Demo Policy
159
+
160
+ 15. **Demo policy** — proceed with creating a demo policy for Issue-to-Invoice testing. Skip only if the user explicitly requested to skip this phase in their initial prompt.
161
+
162
+ 16. **Create demo policy chain** — read `references/demo-policy-config.md`. Check for duplicate Account via `dispatch GET /query?q=<SOQL>`. If none exists, create: Account → Contact → Insurance Policy → Coverages → Surcharges → Insurance Policy Billing Information. Use record IDs from Phase 4 for billing info lookups. All creates via `dispatch POST /sobjects/<Object>`.
163
+
164
+ 17. **Verify FLS** — use `dispatch GET /query?q=<SOQL>` to query `FieldPermissions` for policy objects. Report any fields needing manual FLS configuration.
165
+
166
+ ---
167
+
168
+ ## Rules / Constraints
169
+
170
+ | Constraint | Rationale |
171
+ |-----------|-----------|
172
+ | Query before create — always | Prevents duplicates; existing records may have been created manually or by a colleague |
173
+ | Never ask the user questions or offer to run later | Proceed autonomously — execute all commands immediately. Never say "if you want me to run" or "say Run now". Just do it. Report results at the end. |
174
+ | Capture target user ID once in Phase 1, use everywhere | Phase 1 step 1 captures `TARGET_USER_ID` — this SAME ID is used for all license assignments, permission set assignments, and user-specific operations. Do NOT re-query for user ID in later phases. |
175
+ | Track all record IDs across phases | Later phases reference IDs from earlier phases for lookups |
176
+ | Enable features individually and sequentially | Cross-dependencies require ordered enablement |
177
+ | Use `dispatch` for all org operations | No sf CLI dependency — all reads/writes go through the project-codey MCP dispatch tool |
178
+ | Compute dates at runtime | Fiscal year, accounting periods, and policy dates must reflect the current calendar year |
179
+ | Read config from references/ files | Centralizes field values; prevents drift between instructions and actual creates |
180
+ | NEVER use `__c` suffix on ANY object or field | Every object and every field in this workflow is STANDARD. There are ZERO custom objects or custom fields. Never write `__c` anywhere — not on object names, not on field names. `Status` not `Status__c`. `Active` not `Active__c`. `BillingType` not `BillingType__c`. Using `__c` causes immediate DML failures. |
181
+ | Report skipped steps | When a commented-out section is skipped, tell the user which settings were not configured and why |
182
+
183
+ ---
184
+
185
+ ## Gotchas
186
+
187
+ | Issue | Resolution |
188
+ |-------|------------|
189
+ | Chatter may be disabled on the target org | If `GET /chatter/users/me` returns 403 FUNCTIONALITY_NOT_ENABLED, fall back to `SELECT Id,Username,Name FROM User WHERE IsActive=true AND Profile.Name LIKE '%System Administrator%' LIMIT 1` to identify the target user |
190
+ | Target user ID must be captured once in Phase 1 and used consistently across ALL phases | Capture the user ID from `/chatter/users/me` (or the User query fallback) in Phase 1 step 1 and store it as `TARGET_USER_ID`. Use this SAME ID for all license assignments (Phase 1), permission set assignments (Phase 2), and any user-specific operations. Do NOT re-query for the user ID in later phases — if multiple System Administrator users exist, re-querying can return a different user, causing "invalid user id" errors. If Phase 2 or Phase 7 returns INVALID_CROSS_REFERENCE_KEY with "invalid user id", you used the wrong ID — go back to Phase 1 and use the correct `TARGET_USER_ID` captured there. |
191
+ | `TaxEngine` name field is `TaxEngineName`, not `Name` | Use `TaxEngineName` in queries and creates |
192
+ | `PeriodUnit` (on PaymentTerm and PaymentTermItem) is singular, not `PeriodUnits` | Field was renamed; use singular form |
193
+ | `ProrationPolicy` has NO `Status` field | Do not include Status in queries or creates for this object |
194
+ | `BillingTreatment` activation validates children exist | Must create Items before activating parent |
195
+ | `InsPolicyBillingInfo` is abbreviated, not `InsurancePolicyBillingInformation` | Use the short API name |
196
+ | `InsPolicyTransactionDetail` is abbreviated, not `InsurancePolicyTransactionDetail` | Use the short API name |
197
+ | `GeneralLedgerAccount.Name` is auto-generated | Do not include Name in create; use `AccountingCode` + `AccountingName` |
198
+ | `LegalEntyAccountingPeriod.Name` is auto-generated | Do not include Name in create |
199
+ | `InsurancePolicyCoverage` uses `CoverageName` not `Name` | `Name` is auto-generated on this object |
200
+ | Surcharges must be on terminal nodes (coverages), not directly on the policy | Platform enforces this for tax proration to work correctly |
201
+ | Headless invoke routes use kebab-case path segments | The route `PATCH /headless/invoke/platform/billing-settings/set-billing-setup-enabled` is the canonical form; camelCase variants 404 |
202
+ | `INSURANCE_BILLING` requires `INSURANCE_TRANSACTION_DETAIL` on first | Enable `I_P_T_D_ENABLED_FOR_BROKERAGE` before `I_P_T_ENABLED_FOR_BROKERAGE`. The `handle-pref-enable` route is wrong for both — use `PATCH /setup/org/values/<name>` with `{"orgValue": true}` (same as `SetupApiFamilyController.updateOrgValue` in the UI). |
203
+ | `InsuranceBrokerageSettings` context mapping via `/setup/org/values/*` | Use the same pattern as IPTD/IPT: `GET/PATCH /setup/org/values/INS_BRK_BILLING_CTX_DEF` (and `_SCHED_GRP_MAP`, `_TNX_MAPPING`) with `{"orgValue": "<value>"}`. Tooling API `SELECT Metadata FROM InsuranceBrokerageSettings` returns `INVALID_TYPE` on standard orgs. |
204
+ | `BillingSettings` Tooling SOQL returns INVALID_TYPE | `SELECT Id,Metadata FROM BillingSettings` via Tooling API fails on many org types. `BillingSettings` is a standard platform Metadata type (Metadata API deploy/retrieve works), but the Tooling SOQL surface doesn't expose it universally. For Phase 4 org defaults, use the dedicated headless routes in `references/org-defaults.md` — they write the same underlying OrgValues without any Tooling API dependency. |
205
+ | `BillingTreatmentItem.Percentage` is required even for Advance/Arrears | Platform requires Percentage on all BTI types, not just Milestone. Use 100 for non-milestone items |
206
+ | `BillingTreatmentItem` has no `CurrencyIsoCode` field | Do not include CurrencyIsoCode — the field does not exist on this object |
207
+ | `InsurancePolicyCoverage` has no `CurrencyIsoCode` field | Do not include CurrencyIsoCode — the field does not exist on this object |
208
+ | `ProductSellingModel` OneTime cannot have `PricingTerm` or `PricingTermUnit` | Omit both fields when SellingModelType=OneTime; platform returns INVALID_INPUT if either is set |
209
+ | `PaymentTerm` must be created without Status, then activated after child item | Creating PaymentTerm with Status=Active fails if no PaymentTermItem exists. Create without Status, add PaymentTermItem, then PATCH Status=Active+IsDefault=true |
210
+ | `GeneralLedgerAcctAsgntRule` create fails with Status=Active if no child journal entry rule exists | Create with Status=Inactive, add GeneralLedgerJrnlEntryRule child, then PATCH Status=Active. Valid values: Active, Inactive (no Draft) |
211
+ | `LegalEntity` has no `CurrencyIsoCode` field on orgfarm orgs | Omit from SOQL query and create body |
212
+ | `BillingTreatment.ExcludeFromBilling` is a restricted picklist | Valid values are `"Yes"`/`"No"` only. Sending a boolean-like `"true"`/`"false"` string fails with `400 INVALID_OR_NULL_FOR_RESTRICTED_PICKLIST` |
213
+ | `InsPolicyBillingInfo` billing lookup fields require FLS grants from Phase 2 custom permission set | `BillingTreatmentId`, `TaxTreatmentId`, `ProrationPolicyId`, `PaymentTermId`, `ProductSellingModelId`, `LegalEntityId` are hidden from describe and SOQL until Field-Level Security is granted. Phase 2 creates a custom permission set "Insurance Billing Field Access" with FieldPermissions for these 6 fields and assigns it to the target user. If the POST returns INVALID_FIELD on any of these after Phase 2 completed, the FLS grants may not have been created correctly — verify the custom permission set exists and has the 6 FieldPermissions records. Phase 7 MUST run after Phase 2 completes. |
214
+
215
+ ---
216
+
217
+ ## Output Expectations
218
+
219
+ This skill produces no file artifacts. It configures an org via `dispatch` calls and produces a status report at the end of each phase and a comprehensive summary after all phases complete. Commented-out steps are reported as skipped with investigation notes.
220
+
221
+ ---
222
+
223
+ ## Reference File Index
224
+
225
+ | File | When to read |
226
+ |------|-------------|
227
+ | `references/prerequisites.md` | Phase 1 — license list, feature enablement routes |
228
+ | `references/permissions-config.md` | Phase 2 — 15 permission sets API names (moved early to unblock Phase 3) |
229
+ | `references/billing-settings.md` | Phase 3 — settings field map, headless routes, and desired values |
230
+ | `references/billing-rules-config.md` | Phase 4 — billing rules field values, search patterns, creation sequence |
231
+ | `references/org-defaults.md` | Phase 5 — investigation status and deferred default fields |
232
+ | `references/accounting-setup.md` | Phase 6 — GL account chart, GLAAR rule structure, period naming |
233
+ | `references/demo-policy-config.md` | Phase 7 — demo policy record fields, lookup resolution, and FLS verification |