@salesforce/afv-skills 1.46.0 → 1.48.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 (317) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-observe/SKILL.md +32 -4
  3. package/skills/agentforce-observe/references/ahm-alerts.md +719 -0
  4. package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
  5. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
  6. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
  7. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
  8. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
  9. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
  10. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
  11. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
  12. package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
  13. package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
  14. package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
  15. package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
  16. package/skills/dx-devops-project-manage/SKILL.md +197 -0
  17. package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
  18. package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
  19. package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
  20. package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
  21. package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
  22. package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
  23. package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
  24. package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
  25. package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
  26. package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
  27. package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
  28. package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
  29. package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
  30. package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
  31. package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
  32. package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
  33. package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
  34. package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
  35. package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
  36. package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
  37. package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
  38. package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
  39. package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
  40. package/skills/education-cloud-domain-configure/SKILL.md +234 -0
  41. package/skills/education-cloud-domain-configure/references/dependent-features.md +198 -0
  42. package/skills/education-cloud-domain-configure/references/domain-features/academic-operations.md +386 -0
  43. package/skills/education-cloud-domain-configure/references/domain-features/alumni-relations.md +155 -0
  44. package/skills/education-cloud-domain-configure/references/domain-features/cross-domain-dependencies.md +18 -0
  45. package/skills/education-cloud-domain-configure/references/domain-features/industriessettings-toggle-reference.md +43 -0
  46. package/skills/education-cloud-domain-configure/references/domain-features/mentoring.md +198 -0
  47. package/skills/education-cloud-domain-configure/references/domain-features/recruitment-admissions.md +315 -0
  48. package/skills/education-cloud-domain-configure/references/domain-features/student-management.md +155 -0
  49. package/skills/education-cloud-domain-configure/references/domain-features/student-success.md +249 -0
  50. package/skills/education-cloud-domain-configure/references/domain-features.md +27 -0
  51. package/skills/education-cloud-domain-configure/references/gotchas-extended.md +23 -0
  52. package/skills/education-cloud-domain-configure/references/toggle-write-path.md +67 -0
  53. package/skills/education-cloud-domain-configure/scripts/check_license_provisioned.py +62 -0
  54. package/skills/education-cloud-domain-configure/scripts/check_org_edition.py +44 -0
  55. package/skills/education-cloud-domain-configure/scripts/check_permission_assigned.py +39 -0
  56. package/skills/education-cloud-multi-campus-configure/SKILL.md +7 -0
  57. package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +1 -2
  58. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
  59. package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
  60. package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
  61. package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
  62. package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
  63. package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
  64. package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
  65. package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
  66. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
  67. package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
  68. package/skills/experience-cms-brand-apply/SKILL.md +5 -5
  69. package/skills/experience-cms-brand-create/SKILL.md +2 -2
  70. package/skills/experience-cms-content-generate/SKILL.md +1 -0
  71. package/skills/experience-cms-content-render/SKILL.md +173 -0
  72. package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
  73. package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
  74. package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
  75. package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
  76. package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
  77. package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
  78. package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
  79. package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
  80. package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
  81. package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
  82. package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
  83. package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
  84. package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
  85. package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
  86. package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
  87. package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
  88. package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
  89. package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
  90. package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
  91. package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
  92. package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
  93. package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
  94. package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
  95. package/skills/experience-cms-content-render/references/package-api.md +106 -0
  96. package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
  97. package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
  98. package/skills/experience-cms-content-render/references/verify.md +49 -0
  99. package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
  100. package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
  101. package/skills/experience-search-coordinate/SKILL.md +198 -0
  102. package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
  103. package/skills/experience-search-coordinate/references/content-route.md +313 -0
  104. package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
  105. package/skills/experience-search-coordinate/references/media-route.md +172 -0
  106. package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
  107. package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
  108. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
  109. package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
  110. package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
  111. package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
  112. package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
  113. package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
  114. package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
  115. package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
  116. package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
  117. package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
  118. package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
  119. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
  120. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
  121. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
  122. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
  123. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
  124. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
  125. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
  126. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
  127. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
  128. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
  129. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
  130. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
  131. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
  132. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
  133. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
  134. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
  135. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
  136. package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
  137. package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
  138. package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
  139. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
  140. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
  141. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
  142. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
  143. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
  144. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
  145. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
  146. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
  147. package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
  148. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
  149. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
  150. package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
  151. package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
  152. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
  153. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
  154. package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
  155. package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
  156. package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
  157. package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
  158. package/skills/life-sciences-territory-configure/SKILL.md +217 -0
  159. package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
  160. package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
  161. package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
  162. package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
  163. package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
  164. package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
  165. package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
  166. package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
  167. package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
  168. package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
  169. package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
  170. package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
  171. package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
  172. package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
  173. package/skills/service-agentforce-channel-configure/SKILL.md +33 -28
  174. package/skills/service-agentforce-human-escalation-configure/SKILL.md +205 -0
  175. package/skills/service-agentforce-human-escalation-configure/assets/escalation-thresholds.instructions.md +37 -0
  176. package/skills/service-agentforce-human-escalation-configure/assets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xml +173 -0
  177. package/skills/service-agentforce-human-escalation-configure/assets/package.xml +8 -0
  178. package/skills/service-agentforce-human-escalation-configure/assets/sfdx-project.json +5 -0
  179. package/skills/service-agentforce-human-escalation-configure/references/classifier-contracts.md +103 -0
  180. package/skills/service-agentforce-human-escalation-configure/references/escalation-mechanism.md +63 -0
  181. package/skills/service-agentforce-human-escalation-configure/references/failure-policy.md +44 -0
  182. package/skills/service-agentforce-human-escalation-configure/references/nga-escalation.md +57 -0
  183. package/skills/service-agentforce-human-escalation-configure/references/runtime-verification.md +72 -0
  184. package/skills/service-agentforce-human-escalation-configure/scripts/classify-agent-active.mjs +49 -0
  185. package/skills/service-agentforce-human-escalation-configure/scripts/classify-nga-escalation.mjs +166 -0
  186. package/skills/service-agentforce-human-escalation-configure/scripts/extract-outbound-route.mjs +67 -0
  187. package/skills/service-agentforce-human-escalation-configure/scripts/patch-escalation-surfaces.mjs +131 -0
  188. package/skills/service-agentforce-human-escalation-configure/scripts/tests/__init__.py +0 -0
  189. package/skills/service-agentforce-human-escalation-configure/scripts/tests/_bootstrap.py +249 -0
  190. package/skills/service-agentforce-human-escalation-configure/scripts/tests/test_escalation_contracts.py +899 -0
  191. package/skills/service-agentforce-human-escalation-configure/scripts/verify-and-configure.sh +705 -0
  192. package/skills/service-agentforce-human-escalation-configure/scripts/verify-escalation-config.mjs +89 -0
  193. package/skills/service-de-channel-routing-configure/SKILL.md +13 -5
  194. package/skills/service-de-channel-routing-configure/scripts/tests/test_skill_contract.py +25 -0
  195. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +23 -10
  196. package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +63 -48
  197. package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +6 -2
  198. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
  199. package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
  200. package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
  201. package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
  202. package/skills/service-omni-agent-users-create/SKILL.md +96 -0
  203. package/skills/service-omni-agent-users-create/assets/create-users.apex.template +80 -0
  204. package/skills/service-omni-agent-users-create/references/apex-patterns.md +135 -0
  205. package/skills/service-omni-agent-users-create/references/apex-template-notes.md +40 -0
  206. package/skills/service-omni-agent-users-create/scripts/detect-and-create.sh +206 -0
  207. package/skills/service-omni-agent-users-create/scripts/detect-existing.sh +122 -0
  208. package/skills/service-omni-agent-users-create/scripts/run-create.sh +298 -0
  209. package/skills/service-omni-agent-users-create/scripts/tests/test_user_create_security.py +171 -0
  210. package/skills/service-omni-agent-work-sharing-configure/SKILL.md +78 -0
  211. package/skills/service-omni-agent-work-sharing-configure/references/api-notes.md +31 -0
  212. package/skills/service-omni-agent-work-sharing-configure/scripts/configure-and-report.sh +186 -0
  213. package/skills/service-omni-agent-work-sharing-configure/scripts/tests/_bootstrap.py +120 -0
  214. package/skills/service-omni-agent-work-sharing-configure/scripts/tests/test_agent_work_sharing_contracts.py +93 -0
  215. package/skills/service-omni-base-settings-configure/SKILL.md +77 -0
  216. package/skills/service-omni-base-settings-configure/assets/force-app/main/default/settings/OmniChannel.settings-meta.xml +8 -0
  217. package/skills/service-omni-base-settings-configure/assets/package.xml +8 -0
  218. package/skills/service-omni-base-settings-configure/assets/sfdx-project.json +12 -0
  219. package/skills/service-omni-base-settings-configure/references/api-notes.md +121 -0
  220. package/skills/service-omni-base-settings-configure/scripts/configure-and-report.sh +164 -0
  221. package/skills/service-omni-base-settings-configure/scripts/detect-existing.sh +69 -0
  222. package/skills/service-omni-channel-setup-coordinate/SKILL.md +168 -0
  223. package/skills/service-omni-channel-setup-coordinate/examples/output-templates.md +161 -0
  224. package/skills/service-omni-channel-setup-coordinate/references/gap-catalog.md +99 -0
  225. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +1542 -0
  226. package/skills/service-omni-channel-setup-coordinate/scripts/tests/__init__.py +0 -0
  227. package/skills/service-omni-channel-setup-coordinate/scripts/tests/_bootstrap.py +223 -0
  228. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +804 -0
  229. package/skills/service-omni-command-center-analyze/SKILL.md +84 -0
  230. package/skills/service-omni-command-center-analyze/references/api-notes.md +54 -0
  231. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +198 -0
  232. package/skills/service-omni-command-center-analyze/scripts/tests/_bootstrap.py +115 -0
  233. package/skills/service-omni-command-center-analyze/scripts/tests/test_command_center_analyze_contracts.py +165 -0
  234. package/skills/service-omni-permission-set-assign/SKILL.md +88 -0
  235. package/skills/service-omni-permission-set-assign/assets/package.xml +8 -0
  236. package/skills/service-omni-permission-set-assign/references/api-notes.md +143 -0
  237. package/skills/service-omni-permission-set-assign/scripts/verify-and-assign.sh +397 -0
  238. package/skills/service-omni-presence-status-deploy/SKILL.md +87 -0
  239. package/skills/service-omni-presence-status-deploy/assets/package.xml +12 -0
  240. package/skills/service-omni-presence-status-deploy/references/api-notes.md +115 -0
  241. package/skills/service-omni-presence-status-deploy/scripts/deploy-and-report.sh +422 -0
  242. package/skills/service-omni-presence-user-config-deploy/SKILL.md +80 -0
  243. package/skills/service-omni-presence-user-config-deploy/references/api-notes.md +60 -0
  244. package/skills/service-omni-presence-user-config-deploy/scripts/deploy-and-report.sh +261 -0
  245. package/skills/service-omni-presence-user-config-deploy/scripts/tests/_bootstrap.py +106 -0
  246. package/skills/service-omni-presence-user-config-deploy/scripts/tests/test_presence_user_config_contracts.py +142 -0
  247. package/skills/service-omni-queue-deploy/SKILL.md +91 -0
  248. package/skills/service-omni-queue-deploy/references/api-notes.md +140 -0
  249. package/skills/service-omni-queue-deploy/scripts/verify-and-align.sh +470 -0
  250. package/skills/service-omni-queue-members-assign/SKILL.md +93 -0
  251. package/skills/service-omni-queue-members-assign/references/api-notes.md +144 -0
  252. package/skills/service-omni-queue-members-assign/scripts/tests/_bootstrap.py +67 -0
  253. package/skills/service-omni-queue-members-assign/scripts/tests/test_queue_members_contracts.py +73 -0
  254. package/skills/service-omni-queue-members-assign/scripts/verify-and-bind.sh +362 -0
  255. package/skills/service-omni-queue-routing-config-deploy/SKILL.md +101 -0
  256. package/skills/service-omni-queue-routing-config-deploy/references/api-notes.md +127 -0
  257. package/skills/service-omni-queue-routing-config-deploy/scripts/tests/_bootstrap.py +90 -0
  258. package/skills/service-omni-queue-routing-config-deploy/scripts/tests/test_queue_routing_config_contracts.py +70 -0
  259. package/skills/service-omni-queue-routing-config-deploy/scripts/upsert-and-report.sh +538 -0
  260. package/skills/service-omni-routing-flow-deploy/SKILL.md +111 -0
  261. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.SkillsBased.flow-meta.xml +94 -0
  262. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.flow-meta.xml +88 -0
  263. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Cases.flow-meta.xml +144 -0
  264. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.SkillsBased.flow-meta.xml +94 -0
  265. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.flow-meta.xml +88 -0
  266. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCalls.flow-meta.xml +144 -0
  267. package/skills/service-omni-routing-flow-deploy/assets/package.xml +11 -0
  268. package/skills/service-omni-routing-flow-deploy/assets/sfdx-project.json +11 -0
  269. package/skills/service-omni-routing-flow-deploy/references/api-notes.md +265 -0
  270. package/skills/service-omni-routing-flow-deploy/scripts/deploy-and-report.sh +684 -0
  271. package/skills/service-omni-service-channel-configure/SKILL.md +83 -0
  272. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Cases.serviceChannel-meta.xml +9 -0
  273. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Incidents.serviceChannel-meta.xml +9 -0
  274. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/MessagingSessions.serviceChannel-meta.xml +9 -0
  275. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/VoiceCalls.serviceChannel-meta.xml +9 -0
  276. package/skills/service-omni-service-channel-configure/assets/package.xml +11 -0
  277. package/skills/service-omni-service-channel-configure/assets/sfdx-project.json +12 -0
  278. package/skills/service-omni-service-channel-configure/references/api-notes.md +84 -0
  279. package/skills/service-omni-service-channel-configure/scripts/deploy-and-report.sh +383 -0
  280. package/skills/service-omni-sidebar-configure/SKILL.md +77 -0
  281. package/skills/service-omni-sidebar-configure/references/api-notes.md +51 -0
  282. package/skills/service-omni-sidebar-configure/scripts/enable-and-report.sh +315 -0
  283. package/skills/service-omni-sidebar-configure/scripts/tests/_bootstrap.py +142 -0
  284. package/skills/service-omni-sidebar-configure/scripts/tests/test_sidebar_contracts.py +139 -0
  285. package/skills/service-omni-skills-based-routing-configure/SKILL.md +81 -0
  286. package/skills/service-omni-skills-based-routing-configure/references/api-notes.md +50 -0
  287. package/skills/service-omni-skills-based-routing-configure/scripts/configure-and-report.sh +270 -0
  288. package/skills/service-omni-skills-based-routing-configure/scripts/tests/_bootstrap.py +120 -0
  289. package/skills/service-omni-skills-based-routing-configure/scripts/tests/test_sbr_contracts.py +129 -0
  290. package/skills/service-omni-supervisor-config-deploy/SKILL.md +97 -0
  291. package/skills/service-omni-supervisor-config-deploy/assets/force-app/main/default/omniSupervisorConfigs/Omni_Supervisor.omniSupervisorConfig-meta.xml +9 -0
  292. package/skills/service-omni-supervisor-config-deploy/assets/package.xml +8 -0
  293. package/skills/service-omni-supervisor-config-deploy/assets/sfdx-project.json +12 -0
  294. package/skills/service-omni-supervisor-config-deploy/references/api-notes.md +205 -0
  295. package/skills/service-omni-supervisor-config-deploy/scripts/deploy-and-report.sh +586 -0
  296. package/skills/service-omni-supervisor-config-deploy/scripts/tests/_bootstrap.py +153 -0
  297. package/skills/service-omni-supervisor-config-deploy/scripts/tests/test_supervisor_config_contracts.py +116 -0
  298. package/skills/service-omni-supervisor-permset-assign/SKILL.md +88 -0
  299. package/skills/service-omni-supervisor-permset-assign/references/api-notes.md +48 -0
  300. package/skills/service-omni-supervisor-permset-assign/scripts/verify-and-assign.sh +316 -0
  301. package/skills/service-omni-supervisor-surface-deploy/SKILL.md +85 -0
  302. package/skills/service-omni-supervisor-surface-deploy/references/api-notes.md +47 -0
  303. package/skills/service-omni-supervisor-surface-deploy/scripts/deploy-and-report.sh +216 -0
  304. package/skills/service-omni-supervisor-surface-deploy/scripts/tests/_bootstrap.py +95 -0
  305. package/skills/service-omni-supervisor-surface-deploy/scripts/tests/test_supervisor_surface_contracts.py +154 -0
  306. package/skills/service-omni-supervisor-users-create/SKILL.md +92 -0
  307. package/skills/service-omni-supervisor-users-create/assets/create-supervisors.apex.template +72 -0
  308. package/skills/service-omni-supervisor-users-create/references/apex-patterns.md +73 -0
  309. package/skills/service-omni-supervisor-users-create/references/apex-template-notes.md +41 -0
  310. package/skills/service-omni-supervisor-users-create/scripts/detect-and-create.sh +197 -0
  311. package/skills/service-omni-supervisor-users-create/scripts/detect-existing.sh +112 -0
  312. package/skills/service-omni-supervisor-users-create/scripts/run-create.sh +296 -0
  313. package/skills/service-omni-work-skill-routing-configure/SKILL.md +80 -0
  314. package/skills/service-omni-work-skill-routing-configure/references/api-notes.md +67 -0
  315. package/skills/service-omni-work-skill-routing-configure/scripts/configure-and-report.sh +262 -0
  316. package/skills/service-omni-work-skill-routing-configure/scripts/tests/_bootstrap.py +121 -0
  317. package/skills/service-omni-work-skill-routing-configure/scripts/tests/test_work_skill_routing_contracts.py +161 -0
@@ -0,0 +1,101 @@
1
+ ---
2
+ name: service-omni-queue-routing-config-deploy
3
+ description: "Use to create or update a QueueRoutingConfig record on a Salesforce org via the Data API (idempotent SOQL detect + REST upsert). Naming is target-derived: Case→Case_Routing_Config, VoiceCall→Voice_Routing_Config, Incident→Incident_Routing_Config, MessagingSession→Messaging_Routing_Config (via QRC_ROUTING_TARGET), or pass an explicit developer-name/label/capacity/priority. RoutingModel MostAvailable (default) or LeastActive. Triggers: create a Case or Voice routing config, deploy a QueueRoutingConfig, set up queue routing for Omni Cases/Voice, configure CapacityWeight per queue. Do not use for attribute-based routing (IsAttributeBased=true is out of scope) or routing models other than MostAvailable/LeastActive."
4
+ allowed-tools: Bash Read Write Edit Glob Grep
5
+ metadata:
6
+ version: "1.0"
7
+ domains: ["Service"]
8
+ minApiVersion: "66.0"
9
+ relatedSkills:
10
+ - "service-omni-base-settings-configure"
11
+ - "service-omni-channel-setup-coordinate"
12
+ - "service-omni-queue-deploy"
13
+ - "service-omni-service-channel-configure"
14
+ accessCheck:
15
+ - type: license
16
+ value: ServiceCloud
17
+ cliTools:
18
+ - tool: ["jq"]
19
+ semver: ">=1.6"
20
+ - tool: ["python3"]
21
+ semver: ">=3.9"
22
+ - tool: ["sf"]
23
+ semver: ">=2.139.6"
24
+ ---
25
+
26
+ # service-omni-queue-routing-config-deploy
27
+
28
+ Create or update a `QueueRoutingConfig` via the Data API. This record tells Omni-Channel how to distribute work to agents on a queue: the routing model (`MostAvailable` for round-robin-style, `LeastActive` for load-balancing), how much capacity each work item consumes (`CapacityWeight` or `CapacityPercentage`), the push timeout, and the routing priority. It is a prerequisite for an Omni-routed `Queue` — `service-omni-queue-deploy` binds the queue to the config Id this skill returns. Detection is by `DeveloperName`, so the skill POSTs a new record or PATCHes an existing one to align, and is safe to re-run.
29
+
30
+ ## Inputs
31
+
32
+ ```bash
33
+ bash scripts/upsert-and-report.sh <org-alias> [routing-model] [developer-name] [master-label] [capacity-weight] [routing-priority] [overflow-assignee] [push-timeout]
34
+ # Case_Routing_Config, preserve model / create MostAvailable:
35
+ bash scripts/upsert-and-report.sh myorg
36
+ # align the Case QRC to LeastActive:
37
+ bash scripts/upsert-and-report.sh myorg LeastActive
38
+ # Voice_Routing_Config (coordinator path):
39
+ QRC_ROUTING_TARGET=VoiceCall bash scripts/upsert-and-report.sh myorg
40
+ # set a fallback/overflow assignee (route overflow work to a supervisor):
41
+ QRC_OVERFLOW_ASSIGNEE=supervisor@example.com bash scripts/upsert-and-report.sh myorg
42
+ # Voice uses 100% capacity and a 30-second push timeout:
43
+ QRC_ROUTING_TARGET=VoiceCall QRC_CAPACITY_PERCENTAGE=100 QRC_PUSH_TIMEOUT=30 bash scripts/upsert-and-report.sh myorg MostAvailable
44
+ ```
45
+
46
+ - `org-alias` (required).
47
+ - `routing-model` (optional, or `ROUTING_MODEL_INPUT`) — `MostAvailable` | `LeastActive`. Omitted: an existing record's model is preserved; a new record is created `MostAvailable`. Provided: written on create, aligned on an existing record.
48
+ - `developer-name` / `master-label` / `capacity-weight` (1..100) / `routing-priority` (≥1) — positional after routing-model, or via `QRC_DEVELOPER_NAME` / `QRC_MASTER_LABEL` / `QRC_CAPACITY_WEIGHT` / `QRC_ROUTING_PRIORITY`. Label, weight `5`, and priority `1` are defaults only when creating a new record; omitted values preserve an existing record.
49
+ - `QRC_CAPACITY_PERCENTAGE` (optional, 0..100) — use percentage capacity instead of weight. It is mutually exclusive with an explicitly supplied capacity weight; switching modes clears the old sibling field.
50
+ - `overflow-assignee` (optional 7th positional, or `QRC_OVERFLOW_ASSIGNEE`) — the fallback User (Username or `005` Id) that receives work when every queue member is unavailable (`OverflowAssigneeId`). Resolved to an **active** User Id before the write; omitted leaves an existing record's overflow untouched and a new record with none.
51
+ - `push-timeout` (optional 8th positional, or `QRC_PUSH_TIMEOUT`, 0..3600 seconds) — how long Omni waits for an agent to accept pushed work. Omitted preserves an existing value.
52
+ - `QRC_ROUTING_TARGET` (env) — `Case | VoiceCall | Incident | MessagingSession`; selects the canonical naming defaults. `service-omni-channel-setup-coordinate` sets this per target.
53
+
54
+ ## Preconditions and safety
55
+
56
+ - Target org authenticated via `sf` CLI (My Domain URL), Service Cloud license, `sf` CLI ≥ 2.139.6.
57
+ - Omni-Channel base settings enabled (`service-omni-base-settings-configure`) — otherwise `QueueRoutingConfig` is not writable (`INVALID_TYPE`).
58
+ - The three-way `safe_to_write` production guard applies.
59
+
60
+ ## Run
61
+
62
+ `upsert-and-report.sh` performs detect → upsert → verify:
63
+
64
+ 1. Query `QueueRoutingConfig WHERE DeveloperName = '<target-derived-or-explicit>'`, capturing the existing Id and field values.
65
+ 2. Compare against the requested/canonical values.
66
+ 3. POST a new record when none exists; no-op (`reused`) when all fields already match; PATCH when a field differs.
67
+ 4. Re-query to confirm the final state; block if the re-query shows a mismatch.
68
+
69
+ ## Behavior
70
+
71
+ **Target-derived naming.** With no explicit name, the DeveloperName follows the routing target (`Case_Routing_Config`, `Voice_Routing_Config`, etc.), so re-runs and the coordinator converge on the same record rather than creating parallel duplicates.
72
+
73
+ **Preserve over churn.** On an existing record, omitted routing model, label, routing priority, capacity mode/value, overflow assignee, push timeout, and attribute-based flag are preserved. Defaults (`MostAvailable`, target-derived label, weight `5`, priority `1`, non-attribute-based) apply only to a brand-new record. Capacity uses exactly one mode; explicitly changing from weight to percentage, or back, clears the old sibling field so the record cannot contain conflicting capacity settings.
74
+
75
+ **Fallback / overflow routing.** In the `QueueBased` model, "fallback" is the queue's overflow assignee — the User who receives work when no queue member is available (rather than the item sitting queued indefinitely). Agent availability is an async Omni decision, not observable in a routing flow, so this belongs on the `QueueRoutingConfig`, not the flow. When `overflow-assignee` is provided the skill resolves it to an active User (blocking on an unknown or inactive user, since overflow to an inactive user would silently strand work), writes `OverflowAssigneeId`, and verifies it round-trips.
76
+
77
+ **Read-back reporting.** All reported field values are re-queried from the org after the write (`values_source: "requeried"`), not echoed from inputs — a 201/204 only means the write was accepted. The skill never deletes a `QueueRoutingConfig` (queues, agents, and work skills may reference the Id) — it always PATCHes to align.
78
+
79
+ ## Output contract
80
+
81
+ A single JSON object with `status` ∈ `created` | `reused` | `updated` | `blocked`, plus `routing_target`, `developer_name`, `id`, `master_label`, `routing_model`, `routing_priority`, `capacity_mode`, `capacity_weight`, `capacity_percentage`, `is_attribute_based`, `push_timeout`, `overflow_assignee_id`, `overflow_assignee_requested`, `values_source`, a `before` snapshot, `manual_actions`, and `blocking_issue`.
82
+
83
+ - `created` — no record existed; POST succeeded.
84
+ - `reused` — a record existed with all fields matching; no-op.
85
+ - `updated` — a record existed but a field differed; PATCH succeeded.
86
+ - `blocked` — precondition failed (Omni not enabled, production org, a post-write mismatch, or an `overflow-assignee` that did not resolve to exactly one active User).
87
+
88
+ `before.existed` records whether a matching record was present at start (with its prior `capacity_weight`/`routing_model` when so); `id` is populated for every non-blocked status; `blocking_issue` is non-null only for `blocked`.
89
+
90
+ ## Limitations
91
+
92
+ - Attribute-based routing (`IsAttributeBased=true`) is out of scope — it requires an additional attribute schema.
93
+ - Only `MostAvailable` and `LeastActive` are supported on v66.
94
+ - Per-channel capacity weighting is deprecated on v66 (see `service-omni-service-channel-configure`); per-agent capacity totals are configured elsewhere.
95
+
96
+ ## References
97
+
98
+ | File | When to read |
99
+ |---|---|
100
+ | `references/api-notes.md` | On unexpected errors or when customizing fields — QueueRoutingConfig schema, RoutingModel semantics, and how CapacityWeight interacts with agent capacity |
101
+ | `scripts/tests/test_queue_routing_config_contracts.py` | When validating changes — run `python3 scripts/tests/test_queue_routing_config_contracts.py` from this skill directory |
@@ -0,0 +1,127 @@
1
+ # QueueRoutingConfig — API notes
2
+
3
+ Load this reference **only when the skill hits an unexpected error or when customizing fields**. The happy path is straightforward and doesn't need this doc.
4
+
5
+ **sObject type:** `QueueRoutingConfig` (first-class, SOQL-queryable via the Data API). **API version:** v66.
6
+
7
+ ---
8
+
9
+ ## Schema (fields we use)
10
+
11
+ | Field | Type | v1 default | Semantics |
12
+ |---|---|---|---|
13
+ | `Id` | Id | (auto-generated) | Primary key |
14
+ | `DeveloperName` | string(80) | `Case_Routing_Config` | Unique per-org identifier; used for idempotent detection |
15
+ | `MasterLabel` | string(80) | `Case Routing Config` | UI display name |
16
+ | `RoutingModel` | picklist | `MostAvailable` | See RoutingModel Semantics below |
17
+ | `RoutingPriority` | integer | `1` | **REQUIRED, non-nillable** (confirmed via `sf sobject describe`). Omitting it makes every POST fail with `REQUIRED_FIELD_MISSING`. `1` = highest priority |
18
+ | `IsAttributeBased` | boolean | `false` | Whether to use attribute-based routing (v1 does not — requires attribute definitions) |
19
+ | `CapacityWeight` | integer(1..10) | `5` | How much of an agent's capacity ONE work item from this queue consumes. See CapacityWeight interaction below |
20
+ | `PushTimeout` | integer (sec) | `null` | Seconds to wait before pushing work back to queue if agent doesn't accept. `null` = use Omni default of 30 sec |
21
+ | `OverflowAssigneeId` | User Id | `null` | Fallback User that work is assigned to when all queue members are unavailable. `null` = no overflow (work stays queued indefinitely). Settable via the skill's `overflow-assignee` input (`QRC_OVERFLOW_ASSIGNEE`) — a Username or `005` Id resolved to an **active** User before the write; omitting it preserves the existing value rather than clearing it |
22
+
23
+ ## RoutingModel semantics
24
+
25
+ | Value | Behavior |
26
+ |---|---|
27
+ | `MostAvailable` | Route to the agent with the most remaining capacity (i.e., handling the fewest current work items) |
28
+ | `LeastActive` | Route to the agent whose last work-item interaction was longest ago (load-balancing over time) |
29
+
30
+ **Not supported on v66:** `Priority` (removed), `SkillsBased` (moved to WorkSkillRouting on v66).
31
+
32
+ For most Omni Case setups, `MostAvailable` is the right default — it maximizes queue throughput. `LeastActive` is useful when you want to keep all agents equally busy over time (e.g., to prevent burnout of high-performers).
33
+
34
+ ## CapacityWeight interaction with agent capacity
35
+
36
+ Capacity in Omni-Channel v66 is a three-way math:
37
+
38
+ - **Agent total capacity:** `PresenceUserConfig.Capacity` (default 10) — how much total work an agent can hold at once
39
+ - **Per-queue weight:** `QueueRoutingConfig.CapacityWeight` (this skill's default 5) — how much a single work item from this queue consumes
40
+ - **Per-channel weight:** removed on v66 — used to be `ServiceChannel.CapacityWeight`; no longer configurable
41
+
42
+ **Concrete example:**
43
+ - Agent with `PresenceUserConfig.Capacity=10`
44
+ - Case routes through `Case_Routing_Config` with `CapacityWeight=5`
45
+ - Agent can hold `10 / 5 = 2` cases simultaneously
46
+ - If a third case comes in, it stays queued until the agent completes one
47
+
48
+ **Rules of thumb:**
49
+ - Weight = 1 → agent holds 10 cases at once (high-throughput but hard to focus)
50
+ - Weight = 5 → agent holds 2 cases at once (this skill's default — balanced)
51
+ - Weight = 10 → agent holds 1 case at a time (deep focus, low throughput)
52
+
53
+ ---
54
+
55
+ ## Data API endpoints used
56
+
57
+ **GET (query):**
58
+
59
+ ```text
60
+ GET /services/data/v66.0/query?q=SELECT+Id,+DeveloperName,+MasterLabel,+RoutingModel,+IsAttributeBased,+CapacityWeight,+PushTimeout,+OverflowAssigneeId+FROM+QueueRoutingConfig+WHERE+DeveloperName='Case_Routing_Config'
61
+ ```
62
+
63
+ Or equivalently via `sf data query --query "SELECT ... FROM QueueRoutingConfig WHERE ..."` (which is what the skill's script uses).
64
+
65
+ **POST (create):**
66
+
67
+ ```text
68
+ POST /services/data/v66.0/sobjects/QueueRoutingConfig
69
+ Content-Type: application/json
70
+
71
+ {
72
+ "DeveloperName": "Case_Routing_Config",
73
+ "MasterLabel": "Case Routing Config",
74
+ "RoutingModel": "MostAvailable",
75
+ "RoutingPriority": 1,
76
+ "CapacityWeight": 5,
77
+ "IsAttributeBased": false
78
+ }
79
+ ```
80
+
81
+ Response: `{"id":"0K9RZ...", "success":true, "errors":[]}` (HTTP 201).
82
+ `RoutingPriority` is REQUIRED — a POST without it fails with `REQUIRED_FIELD_MISSING`.
83
+
84
+ **PATCH (update):**
85
+
86
+ ```text
87
+ PATCH /services/data/v66.0/sobjects/QueueRoutingConfig/<id>
88
+ Content-Type: application/json
89
+
90
+ {
91
+ "MasterLabel": "Case Routing Config",
92
+ "RoutingModel": "MostAvailable",
93
+ "RoutingPriority": 1,
94
+ "CapacityWeight": 5,
95
+ "IsAttributeBased": false
96
+ }
97
+ ```
98
+
99
+ Response: empty body (HTTP 204). Note that PATCH does NOT include `DeveloperName` — Salesforce doesn't allow renaming via PATCH on QueueRoutingConfig.
100
+
101
+ Both invoked via `sf api request rest --target-org <alias> <path> --method POST|PATCH --body <json>`.
102
+
103
+ ---
104
+
105
+ ## Failure modes
106
+
107
+ | Symptom | Root cause | Skill behavior |
108
+ |---|---|---|
109
+ | Query returns `INVALID_TYPE` for QueueRoutingConfig | OmniChannelSettings not enabled | Skill translates to: `"OmniChannelSettings is not enabled on this org. Run service-omni-base-settings-configure first."` |
110
+ | POST returns `DUPLICATE_VALUE` on DeveloperName | Race with concurrent skill run | Retry once — the pre-check will now find the record and PATCH instead |
111
+ | POST/PATCH returns `INVALID_FIELD_VALUE` on RoutingModel | Value is not `MostAvailable` or `LeastActive` | Fail with a clear message naming the valid values |
112
+ | POST/PATCH returns `INVALID_FIELD_VALUE` on CapacityWeight | Value < 1 or > 10 | Fail with a clear message naming the valid range |
113
+ | PATCH silently changes nothing | Field values already match | Not a failure — just means Salesforce detected no diff. Skill correctly reports `status: reused` from its own pre-check |
114
+ | POST returns `INSUFFICIENT_ACCESS_OR_READONLY` | Executing user lacks `Manage Public List Views` OR the org has other Omni restrictions | Fail with escalation guidance |
115
+
116
+ ---
117
+
118
+ ## Why Data API instead of Metadata API
119
+
120
+ QueueRoutingConfig is a first-class sObject on Salesforce (unlike ServiceChannel, whose tuning fields are Metadata-only). The Data API has these advantages here:
121
+
122
+ - **Speed:** ~1 sec per call vs ~10 sec for Metadata deploy
123
+ - **Idempotency:** SOQL query returns clean field values for pre-check comparison; Metadata retrieve is slower and returns XML that needs parsing
124
+ - **Reversibility:** PATCH just updates fields; Metadata deploy replaces the whole record
125
+ - **No DX project overhead:** no `assets/`, no `sfdx-project.json`, no `package.xml`
126
+
127
+ Metadata API is still supported (`sf project deploy start --metadata "QueueRoutingConfig:Case_Routing_Config"` works), but adds latency with no functional benefit for this entity.
@@ -0,0 +1,90 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import os
5
+ import subprocess
6
+ import tempfile
7
+ from pathlib import Path
8
+
9
+ SKILLS_ROOT = Path(__file__).resolve().parents[3]
10
+ SCRIPT = "service-omni-queue-routing-config-deploy/scripts/upsert-and-report.sh"
11
+
12
+ _FAKE_SF = r'''#!/usr/bin/env bash
13
+ sub="${1:-} ${2:-}"; args="$*"
14
+ SANDBOX="${FAKE_SANDBOX:-true}"; TRIAL="${FAKE_TRIAL:-null}"; ORG_TYPE="${FAKE_ORG_TYPE:-Developer Edition}"
15
+ B_RM="${FAKE_BEFORE_RM:-MostAvailable}"; B_CW="${FAKE_BEFORE_CW:-5}"; B_CP="${FAKE_BEFORE_CP:-null}"
16
+ B_PT="${FAKE_BEFORE_PT:-null}"; B_RP="${FAKE_BEFORE_RP:-1}"; B_ML="${FAKE_BEFORE_ML:-Case Routing Config}"
17
+ F_RM="${FAKE_FINAL_RM:-MostAvailable}"; F_CW="${FAKE_FINAL_CW:-5}"; F_CP="${FAKE_FINAL_CP:-null}"
18
+ F_PT="${FAKE_FINAL_PT:-null}"; F_RP="${FAKE_FINAL_RP:-1}"; F_ML="${FAKE_FINAL_ML:-Case Routing Config}"
19
+ case "$sub" in
20
+ "org display") echo '{"status":0,"result":{"id":"00Dxx0000000000EAA"}}';;
21
+ "data query")
22
+ if printf '%s' "$args" | grep -q "FROM Organization"; then
23
+ printf '{"status":0,"result":{"records":[{"IsSandbox":%s,"TrialExpirationDate":%s,"OrganizationType":"%s"}]}}' "$SANDBOX" "$TRIAL" "$ORG_TYPE"
24
+ elif printf '%s' "$args" | grep -q "FROM User"; then
25
+ echo '{"status":0,"result":{"records":[{"Id":"005000000000001AAA","IsActive":true}],"totalSize":1}}'
26
+ elif printf '%s' "$args" | grep -q "FROM QueueRoutingConfig"; then
27
+ if printf '%s' "$args" | grep -q "WHERE Id="; then
28
+ printf '{"status":0,"result":{"totalSize":1,"records":[{"Id":"0Jrxx0000000001","DeveloperName":"Case_Routing_Config","MasterLabel":"%s","RoutingModel":"%s","RoutingPriority":%s,"IsAttributeBased":false,"CapacityWeight":%s,"CapacityPercentage":%s,"PushTimeout":%s,"OverflowAssigneeId":null}]}}' "$F_ML" "$F_RM" "$F_RP" "$F_CW" "$F_CP" "$F_PT"
29
+ elif [ "${FAKE_EXISTING:-0}" = "1" ]; then
30
+ printf '{"status":0,"result":{"totalSize":1,"records":[{"Id":"0Jrxx0000000001","DeveloperName":"Case_Routing_Config","MasterLabel":"%s","RoutingModel":"%s","RoutingPriority":%s,"IsAttributeBased":false,"CapacityWeight":%s,"CapacityPercentage":%s,"PushTimeout":%s,"OverflowAssigneeId":null}]}}' "$B_ML" "$B_RM" "$B_RP" "$B_CW" "$B_CP" "$B_PT"
31
+ else
32
+ echo '{"status":0,"result":{"records":[],"totalSize":0}}'
33
+ fi
34
+ else echo '{"status":0,"result":{"records":[],"totalSize":0}}'; fi;;
35
+ "api request")
36
+ if printf '%s' "$args" | grep -q "method POST"; then
37
+ echo '{"id":"0Jrxx0000000001","success":true,"errors":[]}'
38
+ else echo ''; fi;;
39
+ *) echo '{"status":0,"result":{}}';;
40
+ esac
41
+ '''
42
+
43
+
44
+ def run(args, path_prefix=None, scrub_sf=False, extra_env=None):
45
+ env = dict(os.environ)
46
+ if scrub_sf:
47
+ env["PATH"] = os.pathsep.join(d for d in env.get("PATH", "").split(os.pathsep)
48
+ if d and not os.path.exists(os.path.join(d, "sf")))
49
+ if path_prefix:
50
+ env["PATH"] = path_prefix + os.pathsep + env.get("PATH", "")
51
+ if extra_env:
52
+ env.update({key: str(value) for key, value in extra_env.items()})
53
+ proc = subprocess.run(["bash", str(SKILLS_ROOT / SCRIPT), *args], capture_output=True,
54
+ text=True, env=env, cwd=str(SKILLS_ROOT))
55
+ return proc.returncode, (proc.stdout or "") + (proc.stderr or "")
56
+
57
+
58
+ def last_json(out: str) -> dict:
59
+ decoder = json.JSONDecoder()
60
+ result, index = None, 0
61
+ while index < len(out):
62
+ if out[index] not in "{[":
63
+ index += 1
64
+ continue
65
+ try:
66
+ candidate, end = decoder.raw_decode(out, index)
67
+ if isinstance(candidate, dict):
68
+ result = candidate
69
+ index = end
70
+ except json.JSONDecodeError:
71
+ index += 1
72
+ assert result is not None, out
73
+ return result
74
+
75
+
76
+ class FakeSf:
77
+ def __init__(self, body=_FAKE_SF):
78
+ self.body = body
79
+ self.tmp = None
80
+
81
+ def __enter__(self):
82
+ self.tmp = tempfile.mkdtemp(prefix="qrc-fake-sf-")
83
+ executable = Path(self.tmp) / "sf"
84
+ executable.write_text(self.body)
85
+ executable.chmod(0o755)
86
+ return self.tmp
87
+
88
+ def __exit__(self, *_):
89
+ import shutil
90
+ shutil.rmtree(self.tmp, ignore_errors=True)
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python3
2
+ import sys
3
+ import unittest
4
+ from pathlib import Path
5
+
6
+ sys.path.insert(0, str(Path(__file__).resolve().parent))
7
+ from _bootstrap import FakeSf, last_json, run # noqa: E402
8
+
9
+
10
+ class InputTests(unittest.TestCase):
11
+ def test_weight_and_percentage_are_mutually_exclusive(self):
12
+ with FakeSf() as fake:
13
+ rc, out = run(["org", "LeastActive", "Case_Routing_Config", "Case Routing Config", "7"],
14
+ path_prefix=fake, extra_env={"QRC_CAPACITY_PERCENTAGE": "100"})
15
+ self.assertEqual(rc, 1, out)
16
+ self.assertIn("mutually exclusive", out)
17
+
18
+ def test_invalid_timeout_is_rejected(self):
19
+ with FakeSf() as fake:
20
+ rc, out = run(["org"], path_prefix=fake, extra_env={"QRC_PUSH_TIMEOUT": "99999"})
21
+ self.assertEqual(rc, 1, out)
22
+ self.assertIn("Invalid push-timeout", out)
23
+
24
+
25
+ class BehaviorTests(unittest.TestCase):
26
+ def test_create_percentage_capacity_and_timeout(self):
27
+ with FakeSf() as fake:
28
+ rc, out = run(["org", "LeastActive"], path_prefix=fake,
29
+ extra_env={"QRC_CAPACITY_PERCENTAGE": "100", "QRC_PUSH_TIMEOUT": "30",
30
+ "FAKE_FINAL_RM": "LeastActive", "FAKE_FINAL_CP": "100.0",
31
+ "FAKE_FINAL_PT": "30", "FAKE_FINAL_CW": "null"})
32
+ self.assertEqual(rc, 0, out)
33
+ result = last_json(out)
34
+ self.assertEqual(result["capacity_mode"], "percentage", out)
35
+ self.assertEqual(result["capacity_percentage"], 100.0, out)
36
+ self.assertEqual(result["push_timeout"], 30, out)
37
+
38
+ def test_matching_existing_record_is_reused(self):
39
+ with FakeSf() as fake:
40
+ rc, out = run(["org"], path_prefix=fake, extra_env={"FAKE_EXISTING": "1"})
41
+ self.assertEqual(rc, 0, out)
42
+ self.assertEqual(last_json(out)["status"], "reused", out)
43
+
44
+ def test_existing_custom_values_are_preserved_when_not_requested(self):
45
+ custom = {
46
+ "FAKE_EXISTING": "1",
47
+ "FAKE_BEFORE_RM": "LeastActive",
48
+ "FAKE_BEFORE_CW": "17",
49
+ "FAKE_BEFORE_PT": "45",
50
+ "FAKE_BEFORE_RP": "7",
51
+ "FAKE_BEFORE_ML": "Existing Queue Policy",
52
+ "FAKE_FINAL_RM": "LeastActive",
53
+ "FAKE_FINAL_CW": "17",
54
+ "FAKE_FINAL_PT": "45",
55
+ "FAKE_FINAL_RP": "7",
56
+ "FAKE_FINAL_ML": "Existing Queue Policy",
57
+ }
58
+ with FakeSf() as fake:
59
+ rc, out = run(["org"], path_prefix=fake, extra_env=custom)
60
+ self.assertEqual(rc, 0, out)
61
+ result = last_json(out)
62
+ self.assertEqual(result["status"], "reused", out)
63
+ self.assertEqual(result["master_label"], "Existing Queue Policy", out)
64
+ self.assertEqual(result["capacity_weight"], 17, out)
65
+ self.assertEqual(result["routing_priority"], 7, out)
66
+ self.assertEqual(result["push_timeout"], 45, out)
67
+
68
+
69
+ if __name__ == "__main__":
70
+ unittest.main(verbosity=2)